Code

Code Samples:

As a programmer I'm known to periodically dabble in code. The following samples, taken primarily from the projects showcased on this site, can serve as an insight to my knowledge.

Name: playerController.cs

Project: Matherpillar

Description: the playerController controls the primary bodypart, or "head" of the caterpillar in Matherpillar.

Code:

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class playerController : MonoBehaviour {

    // The speed of which the Matherpillar will move at.
    public float bodySpeed = 10f;
    // The direction in which the Matherpillar will move.
    public Vector2 moveDir = Vector2.up;
    // Integer to indicate which number the Matherpillars head currently equals.
    private int currentNumber = 0;
    // String describing which Symbol Type the Matherpillar is currently utilizing.
    public string whichType = "Higher Than";
    // Distance needed to be able to attempt to eat a number/symbol.
    public float eatDistance = 0.2f;
    // Distance needed to "collide" with our own bodyparts.
    public float collisionDistance = 0.1f;
    // Bodypart-prefab to spawn in when the Matherpillar eats something.
    public GameObject bodyPrefab;
    // List of all Bodyparts connected to the head.
    public List<GameObject> bodyParts;
    // Stored position when gobbling food.
    public Vector2 storedPosition;
    // Positions stored to be used by the "child" object.
    public List<Vector2> myPositions;
    // Our "child" object, spawned when the Matherpillars Head eats a number.
    public GameObject myChild;
    // Bool set true when the Head eats something. 
    public bool hasEaten;
    // Distance needed to spawn a child after hasEaten has been set true.
    public float spawnDistance = 0.36f;
    // Bool set when we have spawned a child.
    public bool childSpawned;
    // List of all bodyparts tied to the Object.
    public List<GameObject> allBodyParts;
    // Stored number to pass to the "child" object.
    public int storedNumber;
    // Speedincrease when "eating" a number.
    public float speedIncrease = 0.1f;
    // To avoid the "number" rotating when we rotate the Sprite,
    // we keep it seperate from the object, and update its position
    // as we move.
    public GameObject numberObject;
    // Moving transform-updates to Update() to keep all frames.
    // Thus we need to control whether or not the body should move.
    public bool canMove = true;
    // Sprites for the Squashed-pieces of the Matherpillars body.
    public Sprite squashedHead;
    public Sprite squashedBody;
    // Referances to Master Scripts.
    private uiController uicontrol;
    private objectController objectcontrol;
    private masterScript master;
    private soundController soundcontrol;
   

    // Use this for initialization
    void Start () {
        // Find the Master Scripts.
        uicontrol = FindObjectOfType<uiController>();
        objectcontrol = FindObjectOfType<objectController>();
        master = FindObjectOfType<masterScript>();
        soundcontrol = FindObjectOfType<soundController>();
    }
    
    void Update()
    {
        if(canMove)
        {
            // Identify the current Axis, and move the Object in said direction (unless it is currently moving in the opposite direction).
            if (Input.GetAxis("Horizontal") > 0 && moveDir != Vector2.left)
            {
                moveDir = Vector2.right;
                transform.eulerAngles = new Vector3(0, 0, -90);
            }

            if (Input.GetAxis("Horizontal") < 0 && moveDir != Vector2.right)
            {
                moveDir = Vector2.left;
                transform.eulerAngles = new Vector3(0, 0, 90);
            }

            if (Input.GetAxis("Vertical") > 0 && moveDir != Vector2.down)
            {
                moveDir = Vector2.up;
                transform.eulerAngles = new Vector3(0, 0, 0);
            }

            if (Input.GetAxis("Vertical") < 0 && moveDir != Vector2.up)
            {
                moveDir = Vector2.down;
                transform.eulerAngles = new Vector3(0, 0, 180);
            }

            transform.Translate(moveDir * bodySpeed * Time.deltaTime, Space.World);
            // Moving the Number-object accordingly.
            numberObject.transform.position = new Vector2(transform.position.x - 0.05f, transform.position.y + 0.1f);

            if (hasEaten)
            {
                // Start storing positions in our child-pos List for the new bodypart to follow.
                myPositions.Add(transform.position);
                // When the head has eaten AND covered a set distance (approx. the physical size of a bodypart),
                // we can spawn a new bodypart.
                if (!childSpawned)
                {
                    if (Vector2.Distance(transform.position, storedPosition) >= spawnDistance)
                    {
                        // Setting bool to true to avoid spawning new ones.
                        childSpawned = true;
                        spawnChild();
                    }
                }
            }

            // Find all current Number-objects in the scene, and check the distance to them. If the object
            // is close enough, the Matherpillar will attempt to "eat" it.
            for (int i = 0; i < objectcontrol.numbersInScene.Count; i++)
            {
                if (Vector2.Distance(objectcontrol.numbersInScene[i].transform.position, transform.position) < eatDistance)
                {
                    eatNumber(objectcontrol.numbersInScene[i], objectcontrol.numbersInScene[i].GetComponent<numberScript>().myNumber);
                }
            }

            // Find the current Symbol-objects in the scene, and check the distance to them. If the objects are
            // close enough, the Matherpillar will consume it and adapt to its Symbol-type.
            for (int i = 0; i < objectcontrol.symbolsInScene.Count; i++)
            {
                if (Vector2.Distance(transform.position, objectcontrol.symbolsInScene[i].transform.position) < eatDistance)
                {
                    eatSymbol(objectcontrol.symbolsInScene[i], objectcontrol.symbolsInScene[i].GetComponent<symbolScript>().mySymbol);
                }
            }

            // Checking the distance to all of our "child"-objects. If we're too close (i.e. "colliding"), we lose the game.
            for (int i = 0; i < allBodyParts.Count; i++)
            {
                if (Vector2.Distance(transform.position, allBodyParts[i].transform.position) < collisionDistance)
                {
                    // Call the Death-function.
                    deathEffect();
                }
            }

            // Travelling beyond the boarders of the game will cause you to lose.
            if (transform.position.x > objectcontrol.horizontalLimit || transform.position.x < -objectcontrol.horizontalLimit || transform.position.y > objectcontrol.verticalLimit || transform.position.y < -objectcontrol.verticalLimit)
            {
                // Call the Death-function.
                deathEffect();
         
            }
        }
    }

    // Function used when we "collide" with a number. 
    // First we must identify if the number matches our current symbol
    // (Higher than/lower than/equals), and then we run the appropriate
    // actions.
    public void eatNumber(GameObject obj, int number)
    {
        bool success = false;
        if(whichType == "Higher Than")
        {
            if(number > currentNumber)
            {
                success = true;
            }
        }

        if(whichType == "Less Than")
        {
            if(number < currentNumber)
            {
                success = true;
            }
        }

        if(whichType == "Equals")
        {
            if(number == currentNumber)
            {
                success = true;
            }
        }

        // The number "matches" our current Symbol-type.
        // Spawn a child, or if we already have one, let the
        // last body part in the list spawn it.
        if(success)
        {
            // Play the Eat-SFX
            soundcontrol.playSFX("eat");
            bodySpeed += speedIncrease;
            master.updateScore(bodySpeed);
            storedNumber = currentNumber;
            numberObject.GetComponent<TextMesh>().text = number.ToString();
            currentNumber = number;
            objectcontrol.numbersInScene.Remove(obj);
            if (allBodyParts.Count == 0)
            {
                storedPosition = transform.position;
                hasEaten = true;
            }
            else
            {
                allBodyParts[allBodyParts.Count - 1].GetComponent<bodyController>().ateNumber();
            }
            // Spawning in a new number and destroying the old one.
            objectcontrol.spawnObject(true);
            Destroy(obj);
        }
        // If not, the game is over.
        else
        {
            deathEffect();
        }

    }

    // Eating a symbol, i.e. "colliding" with it, will change
    // the current Symbol-type accordingly.
    public void eatSymbol(GameObject obj, string symbol)
    {
        string symbolText = "";

        if (symbol == "Higher Than")
            symbolText = "+";

        if (symbol == "Less Than")
            symbolText = "-";

        if (symbol == "Equals")
            symbolText = "=";

        // Play the Eat-SFX
        soundcontrol.playSFX("eat");
        whichType = symbol;
        // Updating the UIcontroller to reflect the change.
        uicontrol.changeType(symbolText);
        objectcontrol.symbolsInScene.Remove(obj);
        // Spawning in a new Symbol and destroying the old one.
        objectcontrol.spawnObject(false);
        Destroy(obj);
    }

    public void spawnChild()
    {
        // Spawning a "child" object, and moving it to our stored position.
        GameObject childObj = Instantiate(bodyPrefab);
        childObj.transform.position = storedPosition;
        // Setting this gameobject as the childs "parent"
        childObj.GetComponent<bodyController>().parentObject = gameObject;
    }

    public void passNumber()
    {
        // Passing our stored number (the one before the current one) to our child,
        // who, in turn, will pass its number on to its child and so on.
        allBodyParts[0].GetComponent<bodyController>().changeNumber(storedNumber);
    }

    // Called when the Matherpillar dies. Will play a "death"-SFX and change the
    // sprite of all connected parts. 
    public void deathEffect() {
        // Letting the Master-script know we have died.
        master.playerDied();
        // We will no longer move.
        canMove = false;
        // Play the Death-SFX
        soundcontrol.playSFX("death");
        // Change the sprite of the head.
        GetComponent<SpriteRenderer>().sprite = squashedHead;
        // Change each bodyparts sprite.
        foreach(GameObject obj in allBodyParts)
        {
            obj.GetComponent<SpriteRenderer>().sprite = squashedBody;
        }
    }
}

Name: bodyController.cs

Project: Matherpillar

Description: the bodyController controls the secondary bodyparts of the caterpillar in Matherpillar.

Code:

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class bodyController : MonoBehaviour {

    // Position stored when the Matherpillars head eats a number.
    public Vector2 storedPosition;
    // Referance to the Master-object (Head) of the Matherpillar.
    public GameObject masterObject;
    // Index of our current position.
    public int positionIndex;
    // List of Positions stored and retrieved by the "child" of the bodypart.
    public List<Vector2> myPositions;
    // BodyPart-prefab.
    public GameObject bodyPrefab;
    // Our "child" object, spawned when the Matherpillars Head eats a number.
    public GameObject myChild;
    // Bool set true when the Head eats something. 
    public bool hasEaten;
    // Bool set when we have spawned a child.
    public bool childSpawned;
    // Referance to our "Parent" Object.
    public GameObject parentObject;
    // Bool set if our Parent is the "Head" object.
    public bool headParent;
    // The Number of the current Object.
    public int myNumber;
    // Referance to the playerController-script.
    private playerController player;
    private objectController objectcontrol;
   
    // Use this for initialization
    void Start () {
        if (parentObject.GetComponent<playerController>())
            headParent = true;
        else
            headParent = false;

        player = FindObjectOfType<playerController>();
        player.allBodyParts.Add(gameObject);
        objectcontrol = FindObjectOfType<objectController>();
    }
    
    // Update is called once per frame
    void Update () {
        if (player.canMove)
        {
            int parentCount = 0;
            // Move the bodypart to the next stored position if it has one.
            if (headParent)
                parentCount = player.myPositions.Count;
            else
                parentCount = parentObject.GetComponent<bodyController>().myPositions.Count;

            if (positionIndex < parentCount)
            {
                if (headParent)
                    transform.position = player.myPositions[positionIndex];
                else
                    transform.position = parentObject.GetComponent<bodyController>().myPositions[positionIndex];

                // Increase the index by 1.
                positionIndex++;
            }

            if (hasEaten)
            {
                // Start storing positions in our child-pos List for the new bodypart to follow.
                myPositions.Add(transform.position);
                // When the head has eaten AND covered a set distance (approx. the physical size of a bodypart),
                // we can spawn a new bodypart.
                if (!childSpawned)
                {
                    if (Vector2.Distance(transform.position, storedPosition) >= player.spawnDistance)
                    {
                        // Setting bool to true to avoid spawning new ones.
                        childSpawned = true;
                        spawnChild();
                    }
                }
            }
        }
    }

    public void ateNumber()
    {
        // Setting eaten bool to true so that the body can spawn a new part after a set amount
        // of distance has been covered.
        hasEaten = true;
        // Storing position.
        storedPosition = transform.position;
    }

    public void spawnChild()
    {
        // Spawning a "child" object, and moving it to our stored position.
        GameObject childObj = Instantiate(objectcontrol.bodyPrefab);
        childObj.transform.position = storedPosition;
        // Setting this gameobject as the childs "parent"
        childObj.GetComponent<bodyController>().parentObject = gameObject;
        // Setting the newly spawned object as our "child"-object.
        myChild = childObj;
        player.passNumber();
    }

    // Called by the "parent" object. Will change the numbers down the chain of bodyparts
    // when the "Head" eats a new number.
    public void changeNumber(int number)
    {
        if(myChild)
        {
            myChild.GetComponent<bodyController>().changeNumber(myNumber);
        }

        myNumber = number;
        transform.GetChild(0).GetComponent<TextMesh>().text = number.ToString();
    }

}

Name: playerScript.cs

Project: The Genesis Effect

Description: Primary Player Controller in The Genesis Effect.

Code:

 

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;

// The PlayerScript, the most important(?) part of the game.
// Tor.A.Ulven 2015.

public class playerScript : MonoBehaviour {

    [Header("Attributes")]
    [Tooltip("The Players Movement Speed")]
    public float speed = 20f;
    [Tooltip("The Players caximum amount of Hit Points.")]
    public float maxHitPoints;
    [Tooltip("The Players current Hit Points.")]
    public float hitPoints;
    [Tooltip("The Players rotation speed.")]
    public float rotationSpeed = 5f;
    [Tooltip("The Players shooting rate. The lower the number, the faster he/she will fire bullets.")]
    public float shootRate = 0.2f;
    [Tooltip("This state is usually set when a realtime event plays, to avoid the player moving before scripted time.")]
    public bool isDeactivated = false;
    public float crateDamage;

    // Counter for shootrate.
    private float elapsedTime = 0f;
    public int spyCloneCounter = 0;
    public int spyCloneLimit = 150;

    [Header("Lists and Arrays")]
    [Tooltip("A List keeping track of our positions. Will reset when you spawn a new clone, moving the list to the newly spawned clone.")]
    public List<Vector3> thePos;
    [Tooltip("A List keeping track of our rotations. Will reset when you spawn a new clone, moving the list to the newly spawned clone.")]
    public List<Vector3> theRot;
    [Tooltip("A List keeping track of our currently active clones. This list will update automatically when the Player spawns a new clone.")]
    public List<GameObject> activeClones;
    [Tooltip("A List keeping track of our framecount. This is used to move integers over to our frameShot-index, so that the clone will fire bullets at the same frames as the Player did.")]
    public int countFrames;

    [Tooltip("A List containing an index of when the next clone will fire its bullets.")]
    public List<int> frameShot;

    public List<int> animationForward;
    public List<int> animationLeft;
    public List<int> animationRight;

    [Header("GameObjects")]
    [Tooltip("The Clone GameObject. Usually located in the Prefabs-folder.")]
    public GameObject clone;
    [Tooltip("The Bullet GameObject. Usually located in the Prefabs-folder.")]
    public GameObject bullet;
    [Tooltip("The Sound Effect GameObject. Usually located in the Prefabs-folder.")]
    public GameObject soundEffect;
    [Tooltip("Save point Effect")]
    public GameObject savePointEffect;
    private GameObject currentSavePoint;
    

    [Header("Audio Clips")]
    [Tooltip("The Sound of the Players gunfire.")]
    public AudioClip shotSound;
    public AudioClip rewindSound;

    [Header("Positions")]
    [Tooltip("The Muzzle of our Weapon. Needs to be configured here.")]
    public Transform muzzle, muzzle2;
    [Tooltip("Our Starting position. Usually updated by itself.")]
    public Vector3 startPos;

    [Header("Clone States")]
    [Tooltip("The index of our States. A function will translate the index to a certain state.")]
    public int cloneState;
    [Tooltip("The index of our current selected clone.")]
    public int currentCloneType;
    [Tooltip("Set Save Clone to true or false. When set true, the Clone will update the Players savepoint upon activated/destroyed.")]
    public bool saveCloneActive = false;
    [Tooltip("Set Swap Clone to true or false. If true, the Player will swap bodies with the selected clone for a limited amount of time.")]
    public bool bodySwapped = false;
    [Tooltip("Make a Spy Clone of yourself, invisible to enemies, but cannot fire and moves slower.")]
    public bool spyClone = false;
    [Tooltip("Make a Copy of yourself, mimicing your every move.")]
    public bool playerCopy = false;
    [Tooltip("The actual copy, if any.")]
    public GameObject myCopy;

    public bool cloning;

    private GameObject spyObject;

    [Header("User Inferface Objects")]
    public Text lifeText;
    public Image lifeImage;

    [Header("List of Events to Reset")]
    [Tooltip("When we reset the scene, we need to clean up every object that we've activated (to hold on to the illusion that we're turning back time.)")]
    public List<GameObject> objectsToReset;

    [Header("The Game Manager Script")]
    public gameManager manager;

    [Header("Game Progression Variables")]
    public bool cloneLegal = false;
    public bool spyCloneLegal = false;
    public bool weaponLegal = false;
    public bool explodeLegal = false;
    public bool swapLegal = false;
    public bool assimilateLegal = false;
    public bool needsRigidForce;

    [Tooltip("Is saving allowed?")]
    public bool saveAllowed;

    [Header("Cursor Variables")]
    public List<Texture2D> cursors;
    public int cursorIndex;
    public int cursorTimer, cursorLimit;

    float translationA, translationB;


//	void Awake() {
//		DontDestroyOnLoad(gameObject); <- Add this eventually, when we have more levelsystems going.
//	}


    void Start() {
        // Since we never actually restart the scene (unless you die), we'll set the startpos upon first play.
        startPos = transform.position;

        manager = FindObjectOfType<gameManager>();

            GetComponent<Animation>().CrossFade("Kneel");
    }

    void Update() {

        if(!needsRigidForce && GetComponent<Rigidbody>().velocity.magnitude > 0)
            GetComponent<Rigidbody>().velocity = Vector3.ClampMagnitude(GetComponent<Rigidbody>().velocity, 0);

        if(Input.GetKeyDown(KeyCode.Escape)) {
            // Opening the In Game Menu.
            gameManager manager = FindObjectOfType<gameManager>();
            if(manager.levelBeat) {
                return;
            }
            else if(!manager.bossLevelPanel) {
                manager.menuToggle();
                return;
            }

            else if(!manager.bossLevelPanel.activeSelf) {
                manager.menuToggle();
                return;
            }
        }

        if(Time.timeScale == 0 || UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject()) {
            Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
        }
    }

    // FixedUpdate for everything that can(should) be paused by timescale.
    // Move everything else into a standard Update function if necessary.
    void FixedUpdate () {

        translationA = Input.GetAxis("Vertical") * speed;
        translationB= Input.GetAxis("Horizontal") * speed;

        // Storing the frames (for weaponfire predictions), positions and rotations.
        countFrames++;
        thePos.Add(transform.position);
        theRot.Add(transform.eulerAngles);

        if(Input.GetKey(KeyCode.Q)) {
            if(spyClone) {
                Camera.main.GetComponent<cameraMove>().player = transform;
                spyClone = false;
                Destroy(spyObject);
            }
        }

        if(spyClone) {
            spyCloneCounter++;
            if(spyCloneCounter == spyCloneLimit) {
                spyCloneCounter = 0;
                    Camera.main.GetComponent<cameraMove>().player = transform;
                    spyClone = false;
                    Destroy(spyObject);
            }
        }

        // If we are controlling a clone, we can't control the main object.
        if(bodySwapped)
            return;

        updateStats();

        if(spyClone)
            return;

        // Same here.
        if(isDeactivated)
            return;

        // Block further actions if we're clicking on UI-elements.
//		if(UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
//			return;
        // Didn't work as intended, disabled for now.


        // Finding the mouseposition on screen, and rotating the object towards it.
        Vector3 v3T = Input.mousePosition;
        v3T.z = Mathf.Abs(Camera.main.transform.position.y - transform.position.y);
        v3T = Camera.main.ScreenToWorldPoint(v3T);
        v3T -= transform.position;
        v3T = v3T * 10000.0f + transform.position;

        //find the vector pointing from our position to the target
        Vector3 _direction = (v3T - transform.position).normalized;
        
        //create the rotation we need to be in to look at the target
        Quaternion _lookRotation = Quaternion.LookRotation(_direction);
        
        //rotate us over time according to speed until we are in the required rotation
        transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation,Time.deltaTime * rotationSpeed);

//		transform.LookAt(v3T);
        transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);


        // Move this.
        // Updating some UI.
//		if(activeClones.Count == 0)
//			currentCloneText.text = "No Clones To Select";

        // Updating some UI.
//		if(currentCloneType == 0 && activeClones.Count > 0) {
//			currentCloneText.text = "Clone Selected: 1";
//			if(activeClones[currentCloneType].GetComponent<cloneScript>().myPath.Count == 0)
//				activeClones[currentCloneType].GetComponent<cloneScript>().makePath();
//		}

        // Function to scroll through current active clones. Clones that have ran their course can
        // still be selected here, so that you can plan for the next clone-reset.
        if (Input.GetAxis("Mouse ScrollWheel") > 0) {
            if(currentCloneType < (activeClones.Count -1)) {
                currentCloneType++;
                int shownCloneText = currentCloneType +1;
                foreach(GameObject clone in activeClones) {
                    clone.GetComponent<cloneScript>().hidePath();
                    clone.transform.Find ("PathLight").GetComponent<Light>().color = Color.gray;
                }

                activeClones[currentCloneType].transform.Find ("PathLight").GetComponent<Light>().color = Color.green;
                activeClones[currentCloneType].GetComponent<cloneScript>().makePath();
            }

        }

        // Same as the function above, only scrolling down instead of up.
        if (Input.GetAxis("Mouse ScrollWheel") < 0) {
            if(currentCloneType > 0) {
                currentCloneType--;
                int shownCloneText = currentCloneType +1;
                foreach(GameObject clone in activeClones) {
                    clone.GetComponent<cloneScript>().hidePath();
                    clone.transform.Find ("PathLight").GetComponent<Light>().color = Color.gray;
                }

                activeClones[currentCloneType].transform.Find ("PathLight").GetComponent<Light>().color = Color.green;

                if(activeClones[currentCloneType].GetComponent<cloneScript>().myPath.Count == 0) 
                    activeClones[currentCloneType].GetComponent<cloneScript>().makePath();
                else
                    activeClones[currentCloneType].GetComponent<cloneScript>().showPath();
            }
        }

        // Basic movement functions. Replace with horizontal/vertical inputs eventually.
        // Not 100% sure about Space.World translations.
        // Might have to test several versions to find the best choice.

        if(translationA > 0.2f || translationA < 0) {
            GetComponent<Animation>().CrossFade("MoveForward");
            animationLeft.Add(countFrames);

        }

        if(translationB > 0.1f || translationB < 0) {
            GetComponent<Animation>().CrossFade("MoveForward");
            animationRight.Add(countFrames);
        }
        else {
            //GetComponent<Animation>().CrossFade("MoveForward");
            animationForward.Add(countFrames);
        }

        translationA *= Time.deltaTime;
        translationB *= Time.deltaTime;

        transform.Translate(0, 0, translationA, Space.Self);
        transform.Translate(translationB, 0, 0, Space.Self);

//		if(Input.GetKey(KeyCode.Alpha1))
//			setCloneState(1);

        if(Input.GetKey(KeyCode.Alpha1))
            setCloneState(2);

        if(Input.GetKey (KeyCode.Alpha2)) 
            setCloneState(3);
    
        if(Input.GetKey (KeyCode.Alpha3)) 
            setCloneState(4);

        if(Input.GetKey (KeyCode.Alpha4)) 
            setCloneState(5);

        if(Input.GetKey (KeyCode.Mouse2))
            activateCloneState();


        if(Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") == 0) {
            cursorUpdate(-1);
        }
        else {
            cursorUpdate(1);
        }
        
        if(Input.GetKeyDown(KeyCode.Space)) {
            if(!saveAllowed)
                return;

            //objectsToReset.Clear();

            foreach(GameObject obj in objectsToReset) {
                if(obj.GetComponent<bossLevelCrate>()) {
                    obj.GetComponent<bossLevelCrate>().updatePos();
                }

                if(obj.GetComponent<CrateDestroyer>()) {
                    obj.GetComponent<CrateDestroyer>().updatePos();
                }

                if(obj.GetComponent<destructableObject>()) {
                    obj.GetComponent<destructableObject>().updateUs();
                }
                
                if(obj.GetComponent<resetObject>()) {
                    obj.GetComponent<resetObject>().updateUs();
                }

                if(obj.GetComponent<bossLevel1>()) {
                    obj.GetComponent<bossLevel1>().setSave();
                }

                if(obj.GetComponent<L04_Door>()) {
                    obj.GetComponent<L04_Door>().updateUs();
                }

                if(obj.GetComponent<moveCrate>()) {
                    obj.GetComponent<moveCrate>().updatePos();
                }

                if(obj.GetComponent<turretScript>()) {
                    obj.GetComponent<turretScript>().updateUs();
                }
            }

            startPos = transform.position;
            manager.stateCompleted(transform.position, "Save Point Updated");
            startPos = transform.position;
            theRot.Clear();
            thePos.Clear();
            countFrames = 0;
            frameShot.Clear();
            foreach(GameObject obj in activeClones) {
                // Every clone is destroyed when we set a new save point.
                Destroy(obj);
            }
            activeClones.Clear();
            if(currentSavePoint)
                Destroy(currentSavePoint);

            GameObject saveEff = (GameObject)Instantiate(savePointEffect);
            currentSavePoint = saveEff;
            saveEff.transform.position = transform.position;
        }

        // Updating elapsedTime.
        elapsedTime += Time.deltaTime;
        if(Input.GetKey(KeyCode.Mouse0)) {
            if(!weaponLegal)
                return;


            // If it creeps above our shootRate, we can fire again.
            if(elapsedTime > shootRate) {
                    Animation anim = GetComponent<Animation>();
                    foreach(AnimationState state in anim) {
                        if(state.name == "Shoot")
                            state.speed = 5f;
                    }
                    GetComponent<Animation>().CrossFade("Shoot");

                shootBullet();
                elapsedTime = 0;
            }
        }

        if(Input.GetKey(KeyCode.R)) {

            if(cloning)
                return;

            if(!cloneLegal)
                return;

            if(manager.tutorialLevel && manager.tutorialPanel.activeSelf)
                manager.tutorialPanel.SetActive(false);

            cloning = true;
            Camera.main.GetComponent<AudioSource>().PlayOneShot(rewindSound);
            StartCoroutine(cloneUp());
            // Move all this an own cleanup-function.
            if(activeClones.Count > 5) {
                // Cleaning up array and destroying "oldest" object once we have more than 6 clones.
                Destroy(activeClones[0].gameObject);
                activeClones.RemoveAt(0);
            }
            if(!saveCloneActive) {
                // Instantiating a new clone, and filling it with our behaviour information.
                GameObject obj = (GameObject)Instantiate(clone);
                activeClones.Add(obj);
                obj.transform.position = startPos;
                obj.GetComponent<cloneScript>().myList = thePos.ToArray();
                obj.GetComponent<cloneScript>().myRot = theRot.ToArray();
                obj.GetComponent<cloneScript>().frameShot = frameShot.ToArray();
                obj.GetComponent<cloneScript>().animationForward = animationForward.ToArray();
                obj.GetComponent<cloneScript>().animationLeft = animationLeft.ToArray();
                obj.GetComponent<cloneScript>().animationRight = animationRight.ToArray();
                obj.GetComponent<cloneScript>().maxHitPoints = hitPoints;
                obj.GetComponent<cloneScript>().hitPoints = hitPoints;
            }


            // Moving us to startPos, and clearing our lists.
            transform.position = startPos;
            countFrames = 0;
            thePos.Clear();
            theRot.Clear();
            frameShot.Clear();
            animationForward.Clear();
            animationLeft.Clear();
            animationRight.Clear();

            // Finding all clones and resetting their indexes.
            // Change this one to activeClones instead? Since we've already stored them there anyways.
            cloneScript[] clonescript = FindObjectsOfType<cloneScript>();
            foreach(cloneScript ob in clonescript) {
                // Might want to move this stuff into a respawn-function in the cloneScript for convenience.
                ob.frameCount = 0;
                ob.myFrameInt = 0;
                ob.myint = 0;
                ob.myRotInt = 0;
                ob.transform.Find ("PathLight").GetComponent<Light>().color = Color.gray;
                ob.hitPoints = ob.maxHitPoints;
                ob.stateActive = false;
                //ob.makePath();
                //ob.destroyPath();
            }
            // Finding all AI's in the scene, and resetting their positions. 
            // Might have to find a better way to do this with larger levels, 
            // but it will work for now.

            turretScript[] turrets = FindObjectsOfType<turretScript>();
            foreach(turretScript turret in turrets) {
                turret.reSpawn();
            }

            if(activeClones.Count > 0)
                activeClones[currentCloneType].transform.Find ("PathLight").GetComponent<Light>().color = Color.green;

            // Resetting states.
            if(saveCloneActive)
                saveCloneActive = false;

            if(GameObject.FindGameObjectWithTag("Boss"))
                GameObject.FindGameObjectWithTag("Boss").GetComponent<bossLevel1>().resetUs();
            
            foreach(GameObject obj in objectsToReset) {
                // Might have to make this function a bit more dynamic.
                // Perhaps make an own "reset"-script where you can add
                // which scripts to reset in the inspector.
                if(obj.GetComponent<destructableObject>()) {
                    obj.GetComponent<destructableObject>().resetUs();
                }

                if(obj.GetComponent<resetObject>()) {
                    obj.GetComponent<resetObject>().resetUs();
                }

                if(obj.GetComponent<CrateDestroyer>()) {
                    obj.GetComponent<CrateDestroyer>().resetUs();
                }

                if(obj.GetComponent<bossLevelCrate>()) {
                    obj.GetComponent<bossLevelCrate>().resetUs();
                }

                if(obj.GetComponent<L04_Door>()) {
                    obj.GetComponent<L04_Door>().ResetUs();
                }

                if(obj.GetComponent<moveCrate>()) {
                    obj.GetComponent<moveCrate>().resetUs();
                }

                if(obj.GetComponent<turretScript>()) {
                    obj.GetComponent<turretScript>().reSpawn();
                }
            }
        }
    }

    // Function to handle damage, update lifetext etc.
    // Called by the bulletscript.
    public void takeDamage(float dam, GameObject shooter) {
        hitPoints -= dam;
        float HP = (hitPoints * 100) / (maxHitPoints * 100); // Calculating % of Life.
        lifeText.text = ""+HP+"/"+maxHitPoints+""; // Setting the Text to be the current enemies Name.
        lifeImage.fillAmount = HP; // Setting the life total in % to be shown.
    }

    // Function to shoot bullet. Also records the frames in which a bullet is fired,
    // so that our next clone will get the information.
    void shootBullet() {

        frameShot.Add(countFrames);

        GameObject bul = (GameObject)Instantiate(bullet);
//		GameObject bul2 = (GameObject)Instantiate(bullet);
        bul.transform.position = muzzle.position;
        bul.transform.rotation = muzzle.rotation;
        bul.GetComponent<bulletScript>().shooter = gameObject;
//		bul2.transform.position = muzzle2.position;
//		bul2.transform.rotation = muzzle2.rotation;
//		bul2.GetComponent<bulletScript>().shooter = gameObject;

        GameObject sfx = (GameObject)Instantiate(soundEffect);
        sfx.transform.position = transform.position;
        sfx.GetComponent<soundEffect>().setClip(shotSound, 2, true);

    }
    

    // This function will set the current selected clone's state to our chosen index.
    void setCloneState(int type) {
        // Every clone except the spyClone (current type 5) requires an active clone.
        // So lets check the type first.
        if(type < 5) {
            // Check if we actually have any active clones before we do anything.
            if(activeClones.Count <= 0) 
                return;

            // Find the clonescript, since we have a clone selected.
            cloneScript checkClone = activeClones[currentCloneType].GetComponent<cloneScript>();

            // Clone is out of reach, i.e. in "storage". We can't set a state then.
            // (Can't use checkClone here, since we want the transform, not the script).
            if(activeClones[currentCloneType].transform.position.y > 500)
                return;

            // Already got a state set.
            if(checkClone.stateActive)
                return;
        }

        /* 
			1 = Save - Not in use atm.
			1 = Explosion.
			2 = Swap Clone.
			3 = Assimilate Clone.
			4 = Spy Clone.

		 */

        if(type == 1) {
            // Annoying, but needs to add this here for now.
            cloneScript checkClone = activeClones[currentCloneType].GetComponent<cloneScript>();
            saveCloneActive = true; // Do we need this?? Not sure actually. 
            checkClone.saveClone = true;
            checkClone.stateActive = true;
        }
        else if(type == 2) {
            if(!explodeLegal)
                return;

            cloneScript checkClone = activeClones[currentCloneType].GetComponent<cloneScript>();
            checkClone.explodeClone = true;
            checkClone.stateActive = true;
        }
        else if(type == 3) {
            if(!swapLegal)
                return;

            cloneScript checkClone = activeClones[currentCloneType].GetComponent<cloneScript>();
            checkClone.stateActive = true;
            activeClones[currentCloneType].GetComponent<cloneScript>().playerControlled = true;
            bodySwapped = true;
            Camera.main.GetComponent<cameraMove>().player = activeClones[currentCloneType].gameObject.transform;
        }
        else if(type == 4) {
            if(!assimilateLegal)
                return;

            foreach(GameObject obj in activeClones) {
                if(obj.transform.position.y > 500)
                    return;

                obj.GetComponent<cloneScript>().stateActive = true;
                obj.GetComponent<cloneScript>().assimilateClone = true;
            }

            manager.stateCompleted(transform.position, "Clones Assimilated");
        }

        else if(type == 5) {
            if(!spyCloneLegal)
                return;

            manager.stateCompleted(transform.position, "Spy Clone Created");
            spyClone = true;
            GameObject spy = (GameObject)Instantiate(clone);
            spy.GetComponent<cloneScript>().hitPoints = 5;
            spy.GetComponent<cloneScript>().spyClone = true;
            spy.transform.position = transform.position;
            spy.transform.rotation = transform.rotation;
            spyObject = spy;
            Camera.main.GetComponent<cameraMove>().player = spy.transform;
        }
    }

    void activateCloneState() {
        // Any state will automatically activate upon the end of the clones path,
        // but the player can also activate it before that point if he/she wants.

        // Check if we actually have any clones in which to activate states in.
        if(activeClones.Count <= 0) 
            return;

        activeClones[currentCloneType].GetComponent<cloneScript>().activateState();
    }


    // Checking current clones state to update clone state text.
    string checkCurrentState() {
        // Setting a temporary empty string so we have something to return.
        string tempString = "";

        // No clone = no text.
        if(activeClones.Count == 0) {
            tempString =  "";
            // We have to return here to avoid index-problems.
            return "";
        }

        // Finding the clonescript since we have a clone selected.
        cloneScript checkClone = activeClones[currentCloneType].GetComponent<cloneScript>();

        // No active state.
        if(!checkClone.stateActive)
            tempString = "No Active State";

        // Save clone.
        if(checkClone.saveClone)
            tempString = "Save State Active";

        // Exploding clone.
        if(checkClone.explodeClone)
            tempString = "Exploding State Active";


        return tempString;
    }

    // When we're travelling between bodies via swap clones, we need to update
    // our state text once we're back in our body.
    // Also nice to have them in their own function, to avoid FixedUpdate-cluttering.
    public void updateStats() {
        // Avoiding bugs by checking life each frame.
        // We don't want negative numbers / numbers exceeding our max life.
        if(hitPoints > maxHitPoints) hitPoints = maxHitPoints;


        if(hitPoints <= 0) {
            // Sleng innj explosion-particles.
            if(GetComponent<playerDeath>()) {
                GetComponent<playerDeath>().imDead = true;
                isDeactivated = true;
            }
            Time.timeScale = 0.3f;
            StartCoroutine(gameOverScreen());

        }

        // Calculating % of Life.
        float HP = (hitPoints * 100) / (maxHitPoints * 100);
        // Setting the Text to be the current hp/maxhp.
        lifeText.text = ""+hitPoints+"/"+maxHitPoints+"";
        // Setting the life total in % to be shown.
        lifeImage.fillAmount = HP; 
        
//		// Updating active clone text. 
//		int countClones = activeClones.Count;
//		activeCloneText.text = "Clones Loaded: "+countClones+"";

        // Clone states.
        //cloneStateText.text = "";
        // Setting cloneStateText based on current clones states.
        //cloneStateText.text = checkCurrentState();

//		if(activeClones.Count > 0) {
//			int shownType = currentCloneType +1;
//			currentCloneText.text = "Clone Selected: "+shownType+"";
//		}
    }

    public void cursorUpdate(int index) {
        cursorTimer++;
        if(cursorTimer == cursorLimit) {
            cursorTimer = 0;
            cursorIndex += index;
            if(cursorIndex >= cursors.Count -1)
                cursorIndex = cursors.Count -1;

            if(cursorIndex < 0)
                cursorIndex = 0;



            Cursor.SetCursor(cursors[cursorIndex], Vector2.zero, CursorMode.Auto);

        }
    }

    void OnCollisionEnter(Collision col) {
        if(col.gameObject.GetComponent<bossLevelCrate>()) {
            hitPoints -= crateDamage;

        }
    }

    private IEnumerator cloneUp() {
        yield return new WaitForSeconds(0.5f);
        cloning = false;
    }

    private IEnumerator gameOverScreen() {
        yield return new WaitForSeconds(1f);
        manager.gameOver();
    }
}

Name: cloneScript.cs

Project: The Genesis Effect

Description: Script controlling the "clones" instantiated by the Player in The Genesis Effect.

Code:

 

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;

// The CloneScript, used to add behaviours to the players spawned clones.
// Tor.A.Ulven 2015.

public class cloneScript : MonoBehaviour {

    [Header("Attributes")]
    [Tooltip("Are the clones destructible? If so, lets add HP/MaxHP.")]
    public float maxHitPoints; 
    [Tooltip("Are the clones destructible? If so, lets add HP/MaxHP.")]
    public float hitPoints;
    [Tooltip("The clones speed. Used by Swap Clone when the player inherits the object.")]
    public float speed = 10f;

    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    [Header("Vector and Behaviour Data")]
    public List<Vector3> myPos;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int myint = 0;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int myRotInt = 0;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int myFrameInt = 0;
    public int animLeftInt = 0;
    public int animRightInt = 0;
    public int animForwardInt = 0;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int originalSize;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int originalFrame;
    public int originalLeft;
    public int originalRight;
    public int originalForward;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int listCount;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int originalRot;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public Vector3[] myList;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public Vector3[] myRot;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int[] frameShot;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public int[] animationForward;
    public int[] animationLeft;
    public int[] animationRight;
    public int frameCount;
    [Tooltip("All the items on this list are updated automagically, and doesn't need editing.")]
    public List<GameObject> myPath;

    [Header("GameObjects")]
    [Tooltip("The clone bullet GameObject. Usually found in the Prefabs-folder.")]
    public GameObject bullet;
    [Tooltip("The Sound Effect GameObject. Usually found in the Prefabs-folder.")]
    public GameObject soundEffect;
    [Tooltip("The Path GameObject. Usually found in the Prefabs-folder.")]
    public GameObject path;
    [Tooltip("This Explosion effect for the Explode Clone.")]
    public GameObject explodeEffect;

    [Header("Audio Clips")]
    [Tooltip("The sound of the Clone weapon fire.")]
    public AudioClip shotSound;

    [Header("Clone States")]
    [Tooltip("There can be only one state active at any given time. If this is set to true, no other states can be infused.")]
    public bool stateActive = false;
    [Tooltip("Is the clone playercontroller? Usually set by the PlayerScript.")]
    public bool playerControlled;
    [Tooltip("Is the clone a Save Clone? Usually set by the PlayerScript.")]
    public bool saveClone;
    [Tooltip("Is the clone an Exploding Clone? Usually set by the PlayerScript.")]
    public bool explodeClone;
    [Tooltip("The Clone is about to be assimilated into the Player.")]
    public bool assimilateClone;
    [Tooltip("This clone is controlled by the player, but cannot fire, and moves slower.")]
    public bool spyClone;

    [Header("User Inferface Objects")]
    [Tooltip("When the player inhabits the Clone, we need to show how many seconds are left of the swap.")]
    public Text swapText;
    [Tooltip("The following are Inherited by the Clone upon swapping bodies with the player.")]
    public Text lifeText;
    public Image lifeImage;

    
    [Header("Transforms")]
    [Tooltip("The muzzle of the Clones weapon. Must be set in the editor.")]
    public Transform muzzle;

    [Header("Game Manager")]
    [Tooltip("The Game Manager Script. Set automagically upon spawn.")]
    public gameManager manager;

    [Header("The Player")]
    [Tooltip("The Player Script. Set automagically upon spawn.")]
    public playerScript player;

    void Start() {
        originalFrame = frameShot.Length;
        originalLeft = animationLeft.Length;
        originalRight = animationRight.Length;
        originalForward = animationForward.Length;
        originalSize = myList.Length;
        originalRot = myRot.Length;
        listCount = myList.Length;

        // Setting the gameManager.
        manager = FindObjectOfType<gameManager>();

        // Setting the Player.
        player = FindObjectOfType<playerScript>();

        lifeText = player.lifeText;
        lifeImage = player.lifeImage;

            GetComponent<Animation>().CrossFade("Kneel");
    }
    // FixedUpdate for everything that can(should) be paused by timescale.
    // Move everything else into a standard Update function
    void FixedUpdate () {

        if(hitPoints > maxHitPoints) hitPoints = maxHitPoints;

//		if(hitPoints <= 0) {
//			player.activeClones.Remove(gameObject);
//			if(spyClone) {
//				Camera.main.GetComponent<cameraMove>().player = GameObject.FindGameObjectWithTag("Player").transform;
//				player.spyClone = false;
//			}
//			Destroy(gameObject);
//		}

        // When being assimilated we will stop completely.
        if(assimilateClone) {
            transform.LookAt(GameObject.FindGameObjectWithTag("Player").transform.position);
            transform.Translate(Vector3.forward * 30 * Time.deltaTime);

            Vector3 playerPos = GameObject.FindGameObjectWithTag("Player").transform.position;

            if(Vector3.Distance(transform.position, playerPos) < 2) {
                player.hitPoints += 1;
                player.activeClones.Remove(gameObject);
                // Instantiate a particle effect here maybe?
                // Instantiate a sound effect here maybe?
                Destroy(gameObject);
            }

            return;
        }

        if(!playerControlled && !spyClone) {
            frameCount++;

            if(frameShot.Length > 0) {
                if(originalFrame > myFrameInt) {
                    if(frameShot[myFrameInt] == frameCount) {
                        shootBullet();
                        myFrameInt++;
                    }
                }
            }

            if(animationLeft.Length > 0) {
                if(originalLeft > animLeftInt) {
                    if(animationLeft[animLeftInt] == frameCount) {
                        GetComponent<Animation>().CrossFade("MoveLeft");
                        animLeftInt++;
                    }
                }
            }

            if(animationRight.Length > 0) {
                if(originalRight > animRightInt) {
                    if(animationRight[animRightInt] == frameCount) {
                        GetComponent<Animation>().CrossFade("MoveRight");
                        animRightInt++;
                    }
                }
            }

            if(animationForward.Length > 0) {
                if(originalForward > animForwardInt) {
                    if(animationForward[animForwardInt] == frameCount) {
                        GetComponent<Animation>().CrossFade("MoveForward");
                        animForwardInt++;
                    }
                }
            }

            if(myRot.Length > 0) {
                if(originalRot > myRotInt) {
                    transform.eulerAngles = myRot[myRotInt];
                    myRotInt++;
                }
            }

            if(myList.Length > 0) {
                if(originalSize > myint) {
                    transform.position = myList[myint];
                    myint++;
                }
                else if(myint == originalSize) {
                    activateState();
                    transform.position = new Vector3(1000, 1000, 1000);
                    //destroyPath();
                }
            }

        }
        else {
            // The player has taken control of the clone, and can now move it about
            // and fire the weapons, but nothing more.
            if(playerControlled) {
                myint++;
                int currentSec = myint / 50;
                int maxSec = originalSize / 50;
                int secRemaining = maxSec - currentSec;
                swapText.text = "Seconds Left of Swap: "+secRemaining+"";
                updateStats();
                // When we run out of frames, we swap back to our original body.
                if(myint >= originalSize) {    
                    manager.stateCompleted(transform.position, "Returned To Body");
                    swapText.text = "";
                    player.bodySwapped = false;
                    Camera.main.GetComponent<cameraMove>().player = GameObject.FindGameObjectWithTag("Player").transform;
                    transform.position = new Vector3(1000, 1000, 1000);
                    playerControlled = false;
                }
            }
            // Finding the mouseposition on screen, and rotating the object towards it.
            Vector3 v3T = Input.mousePosition;
            v3T.z = Mathf.Abs(Camera.main.transform.position.y - transform.position.y);
            v3T = Camera.main.ScreenToWorldPoint(v3T);
            v3T -= transform.position;
            v3T = v3T * 10000.0f + transform.position;
            transform.LookAt(v3T);
            transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);

            if(Input.GetKeyDown(KeyCode.Escape)) {
                // Will insert menu/pausescreen here.
                //Application.LoadLevel(Application.loadedLevel);
            }

            // Not 100% sure about World.Space translations. If changed in playerScript, change here as well.
            if(Input.GetKey(KeyCode.W)) {
                transform.Translate(Vector3.forward * speed * Time.deltaTime, Space.World);
            }
            if(Input.GetKey(KeyCode.S)) {
                transform.Translate(Vector3.back * speed * Time.deltaTime, Space.World);
            }
            if(Input.GetKey(KeyCode.D)) {
                transform.Translate(Vector3.right * speed * Time.deltaTime, Space.World);
            }
            if(Input.GetKey(KeyCode.A)) {
                transform.Translate(Vector3.left * speed * Time.deltaTime, Space.World);
            }
            if(Input.GetKeyDown(KeyCode.Mouse0)) {
                if(!spyClone)
                    shootBullet();
            }
        }
    }

    void updateStats() {
        // Avoiding bugs by checking energy/life each frame.
        // (We don't want negative numbers / numbers exceeding our max energy/life.
        if(hitPoints > maxHitPoints) hitPoints = maxHitPoints;
        if(hitPoints <= 0) hitPoints = 0;

        
        
        // Calculating % of Life.
        float HP = (hitPoints * 100) / (maxHitPoints * 100);
        // Setting the Text to be the current hp/maxhp.
        lifeText.text = ""+hitPoints+"/"+maxHitPoints+"";
        // Setting the life total in % to be shown.
        lifeImage.fillAmount = HP; 

    }

    public void hidePath() {
        // Changes the Layer of each path in the myPath-list,
        // hiding them from the minimap-camera.
        foreach(GameObject paths in myPath) {
            paths.layer = 17;
        }
    }

    public void showPath() {
        // Changes the Layer of each path in the myPath-list,
        // so that the minimap-camera can show it.
        foreach(GameObject paths in myPath) {
            paths.layer = 16;
        }
    }

    public void destroyPath() {

        // Destroying our projected path.
        foreach(GameObject paths in myPath) {
            Destroy(paths);
        }

        // Clearing the list.
        myPath.Clear();

    }

    public void makePath() {
        // Shows the clones projected path. Will remain in play until it is destroyed.
        foreach(Vector3 paths in myList) {
            GameObject pathPoint = (GameObject)Instantiate(path);
            pathPoint.transform.position = paths;
            myPath.Add(pathPoint);
        }
    }


    // The activate state function. Depending on which (if any) states are active,
    // the clone will do different things. There can only be one state active at
    // any given point.
    public void activateState() {

        // We have no active states, thus we do nothing.
        if(!stateActive)
            return;

        // Find the playerScript for referance.
        playerScript player = FindObjectOfType<playerScript>();

        if(explodeClone) {
            // Need to add damage function here.


            // Telling the gameManager our position, and what state has happened.
            manager.stateCompleted(transform.position, "Clone Exploded");

            // Removing the clone from the activeClones-list
            player.activeClones.Remove(gameObject);

            // We have to reset the players cloneindex to avoid problems.
            player.currentCloneType = 0;

            // Finding exploding items to interact with (need damage function here as well).
            explodingClone[] items = FindObjectsOfType<explodingClone>();
            foreach(explodingClone item in items) {
                item.checkProximity(transform.position);
            }

            Instantiate(explodeEffect, transform.position, Quaternion.identity);
            // Destroy us upon completed state.
            Destroy(gameObject);
        }

        if(saveClone) {
            // Telling the gameManager our position, and what state has happened.
            manager.stateCompleted(transform.position, "Save Clone Activated");
            player.startPos = myList[myint-1];
            player.saveCloneActive = true;
            foreach(GameObject obj in player.activeClones) {
                // Every clone is destroyed when we set a new save point.
                Destroy(obj);
            }
            player.activeClones.Clear();
        }
    }


    private void shootBullet() {

            GetComponent<Animation>().CrossFade("Shoot");

        // Instantiate and fire a bullet, with a sound to go with it.
        GameObject bul = (GameObject)Instantiate(bullet);
        bul.transform.position = muzzle.position;
        bul.transform.rotation = muzzle.rotation;
        bul.GetComponent<bulletScript>().shooter = gameObject;
        GameObject sfx = (GameObject)Instantiate(soundEffect);
        sfx.transform.position = transform.position;
        sfx.GetComponent<soundEffect>().setClip(shotSound, 2, true);
    }

    void OnDestroy(){
        // Destroying our projected path upon our own destruction.
        destroyPath();
    }

    public void takeDamage(float damage, GameObject shooter) {
        hitPoints -= damage;
    }

}

Name: modulePlacer.cs

Project: A Moron's Quest

Description: Primary script for the random dungeon generation in A Moron's Quest.

Code:

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class modulePlacer : MonoBehaviour {

    public List<GameObject> modulePrefabs;
    public List<GameObject> placedModules;
    public List<GameObject> tilesInLevel;
    public List<GameObject> enemyPrefabs;
    public List<GameObject> bloodPrefabs;
    public List<GameObject> items;
    public List<GameObject> tier1Items;
    public List<GameObject> tier2Items;
    public List<GameObject> tier3Items;
    public List<GameObject> legendaryItems;
    public List<GameObject> roofTiles;
    public List<GameObject> wallTiles;
    public List<GameObject> lowerWallTiles;
    public List<GameObject> enemies;
    public List<GameObject> crystals;
    public List<GameObject> wallTraps;
    public List<Vector2> roofPositions;
    public List<Vector2> tilePositions;
    public GameObject crystalPrefab;
    public GameObject trashCanPrefab;
    public List<Sprite> trapSprites;
    public Sprite exitSpriteOpen, exitSpriteClosed;
    public int levelSize;
    public int roomSize;
    public GameObject moduleWithExit;
    // Chance that each tile will spawn an item.
    public float itemSpawnChance;
    // Chance that each tile will spawn a monster.
    public float enemySpawnChance;
    // Chance that each tile surrounding an item will spawn a guardian.
    public float guardianSpawnChance;
    // Chance that each tile will spawn a crystal.
    public float crystalSpawnChance;
    // Chance that each tile will spawn a trap.
    public float trapSpawnChance;
    // Chance that each tile (neighboring a northern wall) will spawn a walltrap.
    public float walltrapSpawnChance;
    // Chance that each tile will spawn a trashcan.
    public float trashcanChance;
    // Chance to spawn legendary items;
    public float legendaryChance;
    // Chance to spawn tier 3 items;
    public float tier3Chance;
    // Chance to spawn tier 2 items items;
    public float tier2Chance;
    // Chance for spawning a special level;
    public float specialLevelChance;
    // Chance for magical gear
    public float magicChance;
    // Cap for level sizes
    public int levelCap = 10;
    public GameObject levelPrefab;

    private dungeon_Script dungeonmaster;
    private objectMaster objectmaster;
    private UIController uicontrol;
    public GameObject hidePrefab;
    public GameObject crystalparticle;
    public GameObject teleportEffectPrefab;
    public GameObject teleportTempPrefab;
    public GameObject confusionPrefab;
    public GameObject arrowPrefab;
    public GameObject arrowEffectShoot;

    void Start() {
        dungeonmaster = FindObjectOfType<dungeon_Script>();
        objectmaster = FindObjectOfType<objectMaster> ();
        uicontrol = FindObjectOfType<UIController> ();
       // generateLevel();
    }

    public void generateLevel() {
        placedModules.Clear ();
        tilesInLevel.Clear ();
        tilePositions.Clear ();
        roofPositions.Clear ();
        enemies.Clear();
        wallTiles.Clear();
        wallTraps.Clear();
        lowerWallTiles.Clear ();
        items.Clear();
        crystals.Clear();
        if (levelSize > levelCap)
            levelSize = levelCap;

        for (int i = 0; i < levelSize; i++) {
            GameObject obj = (GameObject)Instantiate(modulePrefabs[Random.Range(0, modulePrefabs.Count)]);
            placeRoom(obj);
        }

        for(int i = 0; i<placedModules.Count; i++)
        {
            checkExits(placedModules[i]);
        }

        closeExits();
    }

    //private IEnumerator delayClose() {
    //    yield return new WaitForSeconds(1f);
    //    foreach (GameObject obj in placedModules)
    //    {
    //        checkExits(obj);
    //    }

    //    closeExits();
    //}

    public void placeRoom(GameObject room) {
        if (placedModules.Count > 0)
        {
            int whereToPlace = Random.Range(0, placedModules.Count);
            int randomPlacement = Random.Range(0, 4);
            if (randomPlacement == 0)
            {
                if (!placedModules[whereToPlace].GetComponent<roomScript>().hasRightExit)
                {
                    room.transform.position = new Vector2(placedModules[whereToPlace].transform.position.x + roomSize, placedModules[whereToPlace].transform.position.y);
                    placedModules[whereToPlace].GetComponent<roomScript>().hasRightExit = true;
                    room.GetComponent<roomScript>().hasLeftExit = true;
                    placedModules.Add(room);
                    checkExits(room);
                }
                else
                {
                    placeRoom(room);
                }
            }

            if (randomPlacement == 1)
            {
                if (!placedModules[whereToPlace].GetComponent<roomScript>().hasLeftExit)
                {
                    room.transform.position = new Vector2(placedModules[whereToPlace].transform.position.x - roomSize, placedModules[whereToPlace].transform.position.y);
                    placedModules[whereToPlace].GetComponent<roomScript>().hasLeftExit = true;
                    room.GetComponent<roomScript>().hasRightExit = true;
                    placedModules.Add(room);
                    checkExits(room);
                }
                else
                {
                    placeRoom(room);
                }
            }

            if (randomPlacement == 2)
            {
                if (!placedModules[whereToPlace].GetComponent<roomScript>().hasUpExit)
                {
                    room.transform.position = new Vector2(placedModules[whereToPlace].transform.position.x, placedModules[whereToPlace].transform.position.y + roomSize);
                    placedModules[whereToPlace].GetComponent<roomScript>().hasUpExit = true;
                    room.GetComponent<roomScript>().hasDownExit = true;
                    placedModules.Add(room);
                    checkExits(room);
                }
                else
                {
                    placeRoom(room);
                }
            }

            if (randomPlacement == 3)
            {
                if (!placedModules[whereToPlace].GetComponent<roomScript>().hasDownExit)
                {
                    room.transform.position = new Vector2(placedModules[whereToPlace].transform.position.x, placedModules[whereToPlace].transform.position.y - roomSize);
                    placedModules[whereToPlace].GetComponent<roomScript>().hasDownExit = true;
                    room.GetComponent<roomScript>().hasUpExit = true;
                    placedModules.Add(room);
                    checkExits(room);
                }
                else
                {
                    placeRoom(room);
                }
            }

        }
        else {
            room.transform.position = new Vector3(0, 0, 0);
            placedModules.Add(room);
        }
    }

    // We might place the module next to other modules without knowing,
    // so we have to make sure to open all exits if so.
    public void checkExits(GameObject obj) {
        for(int i = 0; i<placedModules.Count; i++) { 
            if (placedModules[i] != obj) {
                Vector2 objVec = obj.transform.position;
                Vector2 modVec = placedModules[i].transform.position;
                roomScript objroom = obj.GetComponent<roomScript>();
                roomScript modroom = placedModules[i].GetComponent<roomScript>();

                if (Vector2.Distance(objVec, modVec) < 22) {
                    if ((objVec.x > modVec.x) && (objVec.y == modVec.y) && (!modroom.hasRightExit || !objroom.hasLeftExit)) {
                        objroom.hasLeftExit = true;
                        modroom.hasRightExit = true;
                    }

                    if ((objVec.x < modVec.x) && (objVec.y == modVec.y) && (!modroom.hasLeftExit || !objroom.hasRightExit))
                    {
                        objroom.hasRightExit = true;
                        modroom.hasLeftExit = true;
                    }

                    if ((objVec.y > modVec.y) && (objVec.x == modVec.x) && (!modroom.hasUpExit || !objroom.hasDownExit))
                    {
                        objroom.hasDownExit = true;
                        modroom.hasUpExit = true;
                    }

                    if ((objVec.y < modVec.y) && (objVec.x == modVec.x) && (!modroom.hasDownExit || !objroom.hasUpExit))
                    {
                        objroom.hasUpExit = true;
                        modroom.hasDownExit = true;
                    }
                }
            }
        }
    }

    public void closeExits() {
        GameObject dungeon = (GameObject)Instantiate (levelPrefab); 
        for(int i = 0; i<placedModules.Count; i++) {
            for(int j = 0; j< placedModules[i].transform.childCount; j++)
            {
                if (placedModules[i].transform.GetChild(j).gameObject.GetComponent<tile_Script>()) {
                    if (tilePositions.Contains (placedModules[i].transform.GetChild (j).transform.position)) {
                        Destroy (placedModules[i].transform.GetChild (j).gameObject);
                    } else {
                        tilesInLevel.Add (placedModules[i].transform.GetChild (j).gameObject);
                        tilePositions.Add (placedModules[i].transform.GetChild (j).transform.position);
                    }
                }

                if (placedModules[i].transform.GetChild(j).gameObject.tag == "Roof") {
                    roofTiles.Add(placedModules[i].transform.GetChild(j).gameObject);
                    roofPositions.Add (placedModules[i].transform.GetChild(j).transform.position);
                }

                if (placedModules[i].transform.GetChild(j).gameObject.tag == "Wall") {
                    wallTiles.Add(placedModules[i].transform.GetChild(j).gameObject);
                    if (placedModules [i].transform.GetChild (j).gameObject.transform.Find ("Wall_Lower_Cracks"))
                        lowerWallTiles.Add (placedModules [i].transform.GetChild (j).gameObject);
                }
            }
        }
        for(int i = 0; i<placedModules.Count; i++) {
            roomScript room = placedModules[i].GetComponent<roomScript>();

            if (room.hasDownExit)
                room.downWall.SetActive(false);
            if (room.hasUpExit)
                room.upWall.SetActive(false);
            if (room.hasRightExit)
                room.rightWall.SetActive(false);
            if (room.hasLeftExit)
                room.leftWall.SetActive(false);

            for(int j = 0; j<room.downWall.transform.childCount; j++)
            {
                if(room.downWall.transform.GetChild(j).gameObject.tag == "Roof")
                {
                    if (!roofTiles.Contains(room.downWall.transform.GetChild(j).gameObject))
                    {
                        roofTiles.Add(room.downWall.transform.GetChild(j).gameObject);
                        roofPositions.Add(room.downWall.transform.GetChild(j).position);
                    }
                   
                }
            }

            for (int j = 0; j < room.upWall.transform.childCount; j++)
            {
                if (room.upWall.transform.GetChild(j).gameObject.tag == "Roof")
                {
                    if (!roofTiles.Contains(room.upWall.transform.GetChild(j).gameObject))
                    {
                        roofTiles.Add(room.upWall.transform.GetChild(j).gameObject);
                        roofPositions.Add(room.upWall.transform.GetChild(j).position);
                    }
                }
            }

            for (int j = 0; j < room.rightWall.transform.childCount; j++)
            {
                if (room.rightWall.transform.GetChild(j).gameObject.tag == "Roof")
                {
                    if (!roofTiles.Contains(room.rightWall.transform.GetChild(j).gameObject))
                    {
                        roofTiles.Add(room.rightWall.transform.GetChild(j).gameObject);
                        roofPositions.Add(room.rightWall.transform.GetChild(j).position);
                    }
                }
            }

            for (int j = 0; j < room.leftWall.transform.childCount; j++)
            {
                if (room.leftWall.transform.GetChild(j).gameObject.tag == "Roof")
                {
                    if (!roofTiles.Contains(room.leftWall.transform.GetChild(j).gameObject))
                    {
                        roofTiles.Add(room.leftWall.transform.GetChild(j).gameObject);
                        roofPositions.Add(room.leftWall.transform.GetChild(j).position);
                    }

                }
            }


            placedModules[i].transform.parent = dungeon.transform;
        }

        randomizeObject(dungeon);
    }

    // Place random objects around the level in appropriate places.
    public void randomizeObject(GameObject parent)
    {
        GameObject spawner = null;
        dungeonmaster = FindObjectOfType<dungeon_Script>();
        bool exitPlaced = false;
        bool spawnedEnemies = false;
        bool spawnedCrystal = false;
        bool spawnedItem = false;
        bool spawnedTrashcan = false;
        bool canSpawnTrashcan = false;
        bool spawnedQuestReward = false;
        bool hasQuestReward = false;
        GameObject questReward = null;
        GameObject exitTile = null;
        int mobsSpawned = 0;
        int mobCap = dungeonmaster.mobCap;

        if(Random.Range(0, 100) < trashcanChance) {
            canSpawnTrashcan = true;
        }

        foreach (GameObject questie in uicontrol.journalEntries) {
            if (questie.GetComponent<questScript> ().questLevel == dungeonmaster.dungeonIndex + 1) {
                questReward = questie.GetComponent<questScript> ().myReward;
                hasQuestReward = true;
            }
        }

        // Special level
        if (Random.Range (0, 100) <= specialLevelChance) {
            objectmaster.specialLevel = true;
            objectmaster.iceLevel = true;
        }

        for (int i = 0; i < tilesInLevel.Count; i++) {
                
            GameObject temp = tilesInLevel [i];
            int randomIndex = Random.Range (i, tilesInLevel.Count);
            tilesInLevel [i] = tilesInLevel [randomIndex];
            tilesInLevel [randomIndex] = temp;
            tilesInLevel[i].GetComponent<tile_Script>().setNeighbors(tilesInLevel);
        }

        for (int i = 0; i<tilesInLevel.Count; i++)
        {
            bool roofOverTile = false;
            tilesInLevel[i].GetComponent<tile_Script> ().hidePrefab = hidePrefab;
            if (tilesInLevel [i].GetComponent<tile_Script> () && !tilesInLevel [i].GetComponent<tile_Script> ().containsItem && !tilesInLevel [i].GetComponent<tile_Script> ().containsChest && !tilesInLevel [i].GetComponent<tile_Script> ().containsCrystal && !tilesInLevel [i].GetComponent<tile_Script> ().containsEnemy && !tilesInLevel [i].GetComponent<tile_Script> ().isTrap && !tilesInLevel [i].GetComponent<tile_Script> ().isExit) {
                for (int j = 0; j < roofPositions.Count; j++) {
                    if (Vector2.Distance (tilesInLevel [i].transform.position, roofPositions [j]) < 0.5f) {
                        roofOverTile = true;
                    }
                }
                if (!roofOverTile) {
                    if (!exitPlaced) {
                        tilesInLevel [i].GetComponent<tile_Script> ().isExit = true;
                        tilesInLevel [i].GetComponent<tile_Script> ().isOpen = false;
                        tilesInLevel [i].GetComponent<SpriteRenderer> ().sprite = exitSpriteClosed;
                        exitPlaced = true;
                        parent.GetComponent<levelScript> ().exitTile = tilesInLevel [i];
                        exitTile = tilesInLevel [i];
                    } else if (hasQuestReward && !spawnedQuestReward) {
                        tilesInLevel [i].GetComponent<tile_Script> ().containsQuestItem = true;
                        tilesInLevel [i].GetComponent<tile_Script> ().itemInTile = questReward;
                        spawnedQuestReward = true;
                        bool placedGuardian = false;
                        for (int j = 0; j < tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles.Count; j++) {
                            tile_Script neighTile = tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ();
                            if (!neighTile.containsEnemy && !neighTile.containsItem && !neighTile.containsChest && !neighTile.containsQuestItem && !neighTile.containsCrystal && !placedGuardian) {
                                placedGuardian = true;
                                spawner = Instantiate (enemyPrefabs [0]);
                                spawner.transform.position = tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles [j].transform.position;
                                spawner.transform.parent = tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles [j].transform;
                                neighTile.containsEnemy = true;
                                neighTile.enemyInTile = spawner;
                                spawner.name = "SecretKeeper";
                            }
                        }
                    } else if (canSpawnTrashcan && !spawnedTrashcan) {
                        tilesInLevel [i].GetComponent<tile_Script> ().containsTrashcan = true;
                        spawner = (GameObject)Instantiate (trashCanPrefab);
                        spawner.transform.position = tilesInLevel [i].transform.position;
                        spawner.transform.parent = tilesInLevel [i].transform;
                        tilesInLevel [i].GetComponent<tile_Script> ().trashcanInTile = spawner;
                        spawnedTrashcan = true;

                    } else if (!spawnedItem) {
                        int itemChance = Random.Range (0, 100);
                        if (itemChance < legendaryChance) {
                            spawner = (GameObject)Instantiate (legendaryItems [UnityEngine.Random.Range (0, legendaryItems.Count)]);
                        } else if (itemChance < tier3Chance) {
                            spawner = (GameObject)Instantiate (tier3Items [UnityEngine.Random.Range (0, tier3Items.Count)]);
                        } else if (itemChance < tier2Chance) {
                            spawner = (GameObject)Instantiate (tier2Items [UnityEngine.Random.Range (0, tier2Items.Count)]);
                        } else {
                            spawner = (GameObject)Instantiate (tier1Items [UnityEngine.Random.Range (0, tier1Items.Count)]);
                        }

                        spawner.name = "Item_First";
                        if (spawner.GetComponent<itemScript> ()) {
                            tilesInLevel [i].GetComponent<tile_Script> ().itemInTile = spawner;
                            tilesInLevel [i].GetComponent<tile_Script> ().containsItem = true;
                            if (Random.Range (0, 100) < (magicChance+uicontrol.numberOfMagicFindUpgrades)) {
                                if (!spawner.GetComponent<itemScript> ().isPotion) {
                                    spawner.GetComponent<itemScript> ().randArt = true;
                                }
                            }
                        } else if (spawner.GetComponent<chestScript> ()) {
                            tilesInLevel [i].GetComponent<tile_Script> ().chestInTile = spawner;
                            tilesInLevel [i].GetComponent<tile_Script> ().containsChest = true;
                        } 
                        spawner.transform.position = tilesInLevel [i].transform.position;
                        spawner.transform.parent = parent.transform;
                        items.Add (spawner);
                        spawnedItem = true;
                    } else if (itemSpawnChance > Random.Range (0, 100)) {

                        int itemChance = Random.Range (0, 100);
                        if (itemChance < legendaryChance) {
                            spawner = (GameObject)Instantiate (legendaryItems [UnityEngine.Random.Range (0, legendaryItems.Count)]);
                        } else if (itemChance < tier3Chance) {
                            spawner = (GameObject)Instantiate (tier3Items [UnityEngine.Random.Range (0, tier3Items.Count)]);
                        } else if (itemChance < tier2Chance) {
                            spawner = (GameObject)Instantiate (tier2Items [UnityEngine.Random.Range (0, tier2Items.Count)]);
                        } else {
                            spawner = (GameObject)Instantiate (tier1Items [UnityEngine.Random.Range (0, tier1Items.Count)]);
                        }

                        spawner.name = "Item";
                        items.Add (spawner);
                        if (spawner.GetComponent<itemScript> ()) {
                            tilesInLevel [i].GetComponent<tile_Script> ().itemInTile = spawner;
                            tilesInLevel [i].GetComponent<tile_Script> ().containsItem = true;
                            if (Random.Range (0, 100) < (magicChance+uicontrol.numberOfMagicFindUpgrades)) {
                                if (!spawner.GetComponent<itemScript> ().isPotion) {
                                    spawner.GetComponent<itemScript> ().randArt = true;
                                }
                            }
                        } else if (spawner.GetComponent<chestScript> ()) {
                            tilesInLevel [i].GetComponent<tile_Script> ().chestInTile = spawner;
                            tilesInLevel [i].GetComponent<tile_Script> ().containsChest = true;
                        }

                        spawner.transform.position = tilesInLevel [i].transform.position;
                        spawner.transform.parent = parent.transform;
                    } else if (trapSpawnChance > Random.Range (0, 100)) {
                        tilesInLevel [i].GetComponent<SpriteRenderer> ().sprite = trapSprites [Random.Range (0, trapSprites.Count)];
                        tilesInLevel [i].GetComponent<tile_Script> ().isTrap = true;
                        tilesInLevel [i].GetComponent<tile_Script> ().trapName = "Spike Trap";
                        tilesInLevel [i].GetComponent<tile_Script> ().trapDamage = Random.Range (3, 8);
                    } else if (walltrapSpawnChance > Random.Range (0, 100)) {
                        Vector2 vec = tilesInLevel [i].transform.position;
                        for (int j = 0; j < lowerWallTiles.Count; j++) {
                            Vector2 vec2 = lowerWallTiles [j].transform.position;
                            if (vec.x == vec2.x && (vec.y + 1) == vec2.y) {
                                tilesInLevel [i].GetComponent<tile_Script> ().isWallTrap = true;
                                tilesInLevel [i].GetComponent<tile_Script> ().wallTrapOrigin = tilesInLevel [i];
                                tilesInLevel [i].GetComponent<tile_Script> ().trapDamage = Random.Range (1, 5);
                                tilesInLevel [i].GetComponent<tile_Script> ().trapName = "an Arrow";
                                wallTraps.Add(lowerWallTiles[j].transform.Find("Wall_Lower_Cracks").gameObject);
                            }
                        }
                    }
                    else if (!spawnedCrystal) {
                        Vector2 exitPos = exitTile.transform.position;
                        if (Vector2.Distance (tilesInLevel [i].transform.position, exitPos) > 10) {
                            spawner = (GameObject)Instantiate (crystalPrefab);
                            spawner.name = "Crystal";
                            tilesInLevel [i].GetComponent<tile_Script> ().crystalInTile = spawner;
                            tilesInLevel [i].GetComponent<tile_Script> ().containsCrystal = true;
                            spawner.transform.position = tilesInLevel [i].transform.position;
                            spawner.transform.parent = parent.transform;
                            crystals.Add (spawner);
                            parent.GetComponent<levelScript> ().numberOfCrystals++;
                            spawnedCrystal = true;
                        }
                    } else if (crystalSpawnChance > Random.Range (0, 100)) {
                        Vector2 exitPos = exitTile.transform.position;
                        if (Vector2.Distance (tilesInLevel [i].transform.position, exitPos) > 10) {
                            spawner = (GameObject)Instantiate (crystalPrefab);
                            spawner.name = "Crystal";
                            tilesInLevel [i].GetComponent<tile_Script> ().crystalInTile = spawner;
                            tilesInLevel [i].GetComponent<tile_Script> ().containsCrystal = true;
                            spawner.transform.position = tilesInLevel [i].transform.position;
                            spawner.transform.parent = parent.transform;
                            crystals.Add (spawner);
                            parent.GetComponent<levelScript> ().numberOfCrystals++;
                        }
                    } else if (!spawnedEnemies) {
                        spawner = (GameObject)Instantiate (enemyPrefabs [0]);
                        for (int j = 0; j < exitTile.GetComponent<tile_Script> ().neighboringTiles.Count; j++) {
                            if (!spawnedEnemies && exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> () && !exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().containsItem && !exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().containsChest && !exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().containsCrystal && !exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().isTrap && !roofPositions.Contains (exitTile.GetComponent<tile_Script> ().neighboringTiles [j].transform.position)) {
                                Vector2 spawnPos = exitTile.GetComponent<tile_Script> ().neighboringTiles [j].transform.position;
                                exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().containsEnemy = true;
                                exitTile.GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().enemyInTile = spawner;
                                spawner.GetComponent<living_Script> ().HitPoints += Random.Range (0, dungeonmaster.dungeonIndex * 2);
                                spawner.GetComponent<living_Script> ().MaxHitPoints += Random.Range (0, dungeonmaster.dungeonIndex);
                                spawner.GetComponent<living_Script> ().Strength += Random.Range (0, dungeonmaster.dungeonIndex);
                                spawner.GetComponent<living_Script> ().Dexterity += Random.Range (0, dungeonmaster.dungeonIndex);
                                if (!enemies.Contains (spawner))
                                    enemies.Add (spawner);
                                spawner.transform.position = spawnPos;
                                spawner.transform.parent = parent.transform;
                                spawner.name = "Enemy";
                                spawnedEnemies = true;
                            }
                        }
                    } else if (enemySpawnChance > Random.Range (0, 100) && mobsSpawned < mobCap) {
                        mobsSpawned++;
                        int ranSpawn = 0;
                        if(!objectmaster.iceLevel)
                            ranSpawn = Random.Range (1, enemyPrefabs.Count);
                        else
                            ranSpawn = Random.Range(1, enemyPrefabs.Count - 1);

                        spawner = (GameObject)Instantiate (enemyPrefabs [ranSpawn]);
                        spawner.name = "Enemy";
                        spawner.GetComponent<living_Script> ().HitPoints += Random.Range (0, dungeonmaster.dungeonIndex * 2);
                        spawner.GetComponent<living_Script> ().MaxHitPoints += Random.Range (0, dungeonmaster.dungeonIndex);
                        spawner.GetComponent<living_Script> ().Strength += Random.Range (0, dungeonmaster.dungeonIndex);
                        spawner.GetComponent<living_Script> ().Dexterity += Random.Range (0, dungeonmaster.dungeonIndex);
                        if (!enemies.Contains (spawner))
                            enemies.Add (spawner);
                        tilesInLevel [i].GetComponent<tile_Script> ().enemyInTile = spawner;
                        tilesInLevel [i].GetComponent<tile_Script> ().containsEnemy = true;
                        spawner.transform.position = tilesInLevel [i].transform.position;
                        spawner.transform.parent = parent.transform;
                    } else if ((guardianSpawnChance > Random.Range (0, 100)) && mobsSpawned < mobCap) {
                        mobsSpawned++;
                        for (int j = 0; j < tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles.Count; j++) {
                            if (tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> () && tilesInLevel [i].GetComponent<tile_Script> ().neighboringTiles [j].GetComponent<tile_Script> ().containsItem) {

                                spawner = (GameObject)Instantiate (enemyPrefabs [0]);
                                spawner.name = "Enemy";
                                spawner.GetComponent<living_Script> ().HitPoints += Random.Range (0, dungeonmaster.dungeonIndex * 2);
                                spawner.GetComponent<living_Script> ().MaxHitPoints += Random.Range (0, dungeonmaster.dungeonIndex);
                                spawner.GetComponent<living_Script> ().Strength += Random.Range (0, dungeonmaster.dungeonIndex);
                                spawner.GetComponent<living_Script> ().Dexterity += Random.Range (0, dungeonmaster.dungeonIndex);
                                if (!enemies.Contains (spawner))
                                    enemies.Add (spawner);
                                tilesInLevel [i].GetComponent<tile_Script> ().enemyInTile = spawner;
                                tilesInLevel [i].GetComponent<tile_Script> ().containsEnemy = true;
                                spawner.transform.position = tilesInLevel [i].transform.position;
                                spawner.transform.parent = parent.transform;
                            }
                        }
                    }
                }
            }
        }

        if (spawner && !spawner.transform.parent) {
            print (spawner.name + " spawned without parent.");
        }

        float nearestModule = 10000f;
        
        for(int i = 0; i<placedModules.Count; i++) 
        {
            if (Vector2.Distance(exitTile.transform.position, placedModules[i].transform.position) < nearestModule) {
                moduleWithExit = placedModules[i];
                nearestModule = Vector2.Distance(exitTile.transform.position, placedModules[i].transform.position);
            }
        }
            
        parent.GetComponent<levelScript> ().setStartTile ();
        dungeonmaster.addLevel(parent);
    }
}

Name: pathFinding.cs

Project: A Moron's Quest

Description: The Adventurer characters main pathfinding script in A Moron's Quest.

Code:

 

/// <summary>
/// This is the Adventurer's pathfinding script.
/// It handles everything related to moving/pathfinding.
/// </summary>
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class pathFinding : MonoBehaviour {

    [Header("Pathfinding Variables")]
    [Tooltip("The current tile of the gameObject.")]
    public GameObject currentTile;
    [Tooltip("Next tile in line in a set path.")]
    public GameObject nextTile;
    [Tooltip("The chosen path. Contains a List of tiles indexed by near to far.")]
    public List<GameObject> chosenPath;
    [Tooltip("Lists containing possible paths to choose from.")]
    public List<GameObject> path1, path2, path3, path4, path5, path6, path7, path8;
    [Tooltip("Current index of said paths.")]
    public int listIndex;
    [Tooltip("Object used to choose between lists of equal interest points.")]
    public GameObject leastVisitedTile;
    [Tooltip("Index of the current path.")]
    public int pathIndex;
    [Tooltip("Are we on a path decided by the Wizard/Player?")]
    public bool onPlayerPath;
    [Tooltip("The Vector 2 Position of said path.")]
    public Vector2 endPosLocation;
    [Tooltip("Specific tile we want the Hero to move towards.")]
    public GameObject chosenTile;
    [Tooltip("Specific tile containing a crystal construct.")]
    public GameObject crystalTile;
    [Tooltip("A list containing the combined interest points of all four possible directions.")]
    public List<int> interestValues;
    [Tooltip("The current paths interest value")]
    public int currentInterestValue;

    [Header("States of the Character")]
    [Tooltip("Is the character currently moving?")]
    public bool wandering;
    [Tooltip("Set when the character is in a teleporttile")]
    public bool teleportTile;
    [Tooltip("Set when the character sees an item in a neighboring tile")]
    public bool itemAround;
    [Tooltip("Set when the character sees an enemy in a neighboring tile")]
    public bool enemyAround;
    [Tooltip("Set when there is an item in the same tile as the character")]
    public bool itemInTile;
    [Tooltip("Set when the characters sees a crystal in a neighboring tile")]
    public bool crystalAround;
    [Tooltip("Set when the characters sees a chest in a neighboring tile")]
    public bool chestAround;
    [Tooltip("Set when there is a chest in the same tile as the character")]
    public bool chestInTile;
    [Tooltip("Set when the character sees a trashcan in a neighboring tile")]
    public bool trashcanAround;
    [Tooltip("Set when there is a trashcan in the same tile as the character")]
    public bool trashcanInTile;
    [Tooltip("Set if the chosenPath was abrupted by some other action")]
    public bool pathAbrupted;
    [Tooltip("Have we checked the current tile for actions to take?")]
    public bool tileChecked;
    [Tooltip("Checking a new path, to see if it is more interesting or not.")]
    public bool moreInterestingCheck;
    [Tooltip("If set true, the character will find a path to the exit.")]
    public bool movingToExit;
    [Tooltip("Set true if the character just picked up a potion. Used to avoid him drinking it instantly.")]
    public bool justFoundPotion;
    [Tooltip("Set true when the character can access the potion-decicion UI in the UIcontroller.")]
    public bool canDrinkPotion;
    [Tooltip("Set true when the character chooses to quaff a potion.")]
    public bool calledDrink;
    [Tooltip("Set true when the character can access the chest UI in the UIcontroller.")]
    public bool canOpenChest;
    [Tooltip("Set true when the character can access the trashcan UI in the UIcontroller.")]
    public bool canUseTrashcan;

    [Header("Affected GameObjects")]
    [Tooltip("The closest Enemy Object")]
    public GameObject enemyObject;
    [Tooltip("The destroyed remains of a crystal")]
    public GameObject destroyedCrystal;
    [Tooltip("List of enemies currently chasing us")]
    public List<GameObject> enemiesInChasing;

    [Header("Affected Values")]
    [Tooltip("The range of which the character can scout.")]
    public int lineOfSight;
    [Tooltip("Counters related to calling the walking sounds of the character.")]
    public int walkCounter, walkLimit;
    [Tooltip("The speed at which the character moves.")]
    public float wanderSpeed;

    // Temporarty List.
    public List<GameObject> tempList;

    // Scripts in the Scene we need access to.
    private objectMaster objectmaster;
    private UIController uicontrol;
    private mageScript magescript;
    private soundController soundcontroller;
    private tutorialScript myTutorialScript;
    private dungeon_Script dungeonmaster;
    private exitFinder exitfinder;
    private modulePlacer modulemaster;
    private forceFieldMaster forcefield;

    // Use this for initialization
    void Start () {
        // Finding the objectmaster, who has lists containing all objects in the scene based on tags.
        objectmaster = FindObjectOfType<objectMaster>();
        // Finding the UIController.
        uicontrol = FindObjectOfType<UIController>();
        // Finding the mageScript.
        magescript = FindObjectOfType<mageScript>();
        // Finding the soundcontroller
        soundcontroller = FindObjectOfType<soundController>();
        // Finding the dungeonmaster
        dungeonmaster = FindObjectOfType<dungeon_Script>();
        // Finding the tutorial script
        myTutorialScript = FindObjectOfType<tutorialScript>();
        // Finding the exitFinder
        exitfinder = FindObjectOfType<exitFinder>();
        // Finding the modulemaster
        modulemaster = FindObjectOfType<modulePlacer>();

        forcefield = FindObjectOfType<forceFieldMaster> ();
        // Calling a delayed update (we need the objectmaster to find all objects before requesting them).
        callDelay();

        // If we're not wielding a weapon, issue this information to the heroscript.
        if (!uicontrol.wieldedWeapon)
            GetComponent<heroScript>().performAction(4);
    }

    // A slight delay to allow for the objects in the scene to be sorted.
    public void callDelay() {
        StartCoroutine(delayedUpdate(1.5f));
    }

    // The delayed update, calling to the findPath()-function deciding the characters next path.
    private IEnumerator delayedUpdate(float delay) {
        wandering = false;
        yield return new WaitForSeconds(delay);
        findPath();
    }

    // Slight delay when the Hero chooses a new path.
    private IEnumerator delayedWander(float delay, bool whatToShow) {
        // Check if we're wielding a weapon, and call to the proper animation through heroscript.
        if(uicontrol.wieldedWeapon)
            GetComponent<heroScript>().performAction(0);
        else
            GetComponent<heroScript>().performAction(6);

        // Every once in a while the Adventurer will look for a potion in his/her
        // inventory, and quaff it while contemplating where to go next.
        // Unless the Player/Wizard has the influence spell with atleast 1 upgrade, there is no way to
        // avoid this.
        bool drinkIt = false;
        bool hasPotion = false;
        for (int i = 0; i < uicontrol.myInventory.Count; i++) {
            if (uicontrol.myInventory [i].GetComponent<itemScript> ().isPotion) {
                hasPotion = true;
            }
        }

        if (!myTutorialScript.isTutorial && hasPotion && canDrinkPotion)
        {
            // 10 percent chance (right now).
            if (Random.Range(0, 100) <= 10)
                drinkIt = true;
        }
        // In the tutorial we will quaff the potion the first chance we get, just
        // to avoid nasty bugs.
        else if(myTutorialScript.isTutorial && hasPotion) {
            drinkIt = true;
        }
    
        if (!justFoundPotion && drinkIt) {
            if (!calledDrink) {
                calledDrink = true;
                bool drankPotion = false;
                GameObject potion = null;
                // Randomizing Item List.
                for (int i = 0; i < uicontrol.myInventory.Count; i++) {
                    GameObject temp = uicontrol.myInventory [i];
                    int randomIndex = Random.Range (i, uicontrol.myInventory.Count);
                    uicontrol.myInventory [i] = uicontrol.myInventory [randomIndex];
                    uicontrol.myInventory [randomIndex] = temp;
                }

                // Picking a potion to drink.
                for (int i = 0; i < uicontrol.myInventory.Count; i++) {
                    if (!drankPotion) {
                        if (uicontrol.myInventory [i].GetComponent<itemScript> () && uicontrol.myInventory [i].GetComponent<itemScript> ().isPotion) {
                            potion = uicontrol.myInventory [i];
                            drankPotion = true;
                        }
                    }
                }
                // Checking if we have enough influence upgrades to manipulate the Adventurer.
                if (uicontrol.numberOfInfluenceUpgrades > 0) {
                    uicontrol.actionPanelUp (4, potion);
                    yield return new WaitForSeconds (4);
                    if (canDrinkPotion) {
                        GetComponent<living_Script> ().drinkPotion (potion);
                        canDrinkPotion = true;
                        calledDrink = false;
                    } else {
                        canDrinkPotion = true;
                        calledDrink = false;
                    }

                } 
                // Else just drink it for the heck of it.
                else {
                    canDrinkPotion = true;
                    calledDrink = false;
                    GetComponent<living_Script> ().drinkPotion (potion);
                }
            }
        }
        else {
            justFoundPotion = false;
        }

        yield return new WaitForSeconds(1);
        // Setting up our interest "bubble" for the Player to see.
        setInterest();
        yield return new WaitForSeconds(delay);

        // Checking if we're wielding a weapon before calling animations.
        if (uicontrol.wieldedWeapon)
            GetComponent<heroScript>().performAction(1);
        else
            GetComponent<heroScript>().performAction(5);
        
        wandering = true;
    }

    public void setArrow() {
        // If we're moving to the exit we're not going to show the Arrow
        if (movingToExit) {
            uicontrol.placeBubble(uicontrol.exitSprite, Vector3.zero, 0, Color.white);
            return;
        }

        // The same if we have no nextTile to move to.
        if (!nextTile)
            return;

        // Setting Arrow-rotation in our "thought" bubble based on the position of the next tile.
        if (nextTile.transform.position.x > currentTile.transform.position.x && nextTile.transform.position.y == currentTile.transform.position.y)
        {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 180), 0, Color.white);
        }
        if (nextTile.transform.position.x < currentTile.transform.position.x && nextTile.transform.position.y == currentTile.transform.position.y) {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 0), 0, Color.white);
        }
        if (nextTile.transform.position.y > currentTile.transform.position.y && nextTile.transform.position.x == currentTile.transform.position.x) {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, -90), 0, Color.white);
        }
        if (nextTile.transform.position.y < currentTile.transform.position.y && nextTile.transform.position.x == currentTile.transform.position.x)
        {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 90), 0, Color.white);
        }
        if (nextTile.transform.position.y > currentTile.transform.position.y && nextTile.transform.position.x > currentTile.transform.position.x)
        {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 230), 0, Color.white);
        }

        if (nextTile.transform.position.y > currentTile.transform.position.y && nextTile.transform.position.x < currentTile.transform.position.x)
        {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 310), 0, Color.white);
        }

        if (nextTile.transform.position.y < currentTile.transform.position.y && nextTile.transform.position.x > currentTile.transform.position.x)
        {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 130), 0, Color.white);
        }

        if (nextTile.transform.position.y < currentTile.transform.position.y && nextTile.transform.position.x < currentTile.transform.position.x)
        {
            uicontrol.placeBubble(uicontrol.arrowSprite, new Vector3(0, 0, 50), 0, Color.white);
        }
    }

    // Function to set up the "thought" bubble with the appropriate sprites.
    public void setInterest() {
        bool hasInterest = false;

        // Checking our current path for interestpoints, and setting up the placeBubble-function
        // in the UIController-script with the appropriate sprites, rotations and colors.
        foreach (GameObject obj in chosenPath)
        {
            if (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen)
            {
                uicontrol.placeBubble(uicontrol.exitSprite, Vector3.zero, 0, Color.white);
                hasInterest = true;
            }
            if (obj.GetComponent<tile_Script>().containsItem && obj.GetComponent<tile_Script>().itemInTile)
            {
                hasInterest = true;
                uicontrol.placeBubble(obj.GetComponent<tile_Script>().itemInTile.GetComponent<SpriteRenderer>().sprite, Vector3.zero, 0, obj.GetComponent<tile_Script>().itemInTile.GetComponent<SpriteRenderer>().color);
                if (obj.GetComponent<tile_Script> ().itemInTile.GetComponent<itemScript> ().isPotion) {
                    if (obj.GetComponent<tile_Script>().itemInTile.transform.childCount > 0)
                    {
                        Sprite newsprite = obj.GetComponent<tile_Script>().itemInTile.transform.GetChild(0).GetComponent<SpriteRenderer>().sprite;
                        Color col = obj.GetComponent<tile_Script>().itemInTile.transform.GetChild(0).GetComponent<SpriteRenderer>().color;
                        uicontrol.placeBackgroundBubble(newsprite, col);
                    }
                }
            }

            if (obj.GetComponent<tile_Script> ().containsTrashcan) {
                hasInterest = true;
                uicontrol.placeBubble (obj.GetComponent<tile_Script>().trashcanInTile.GetComponent<SpriteRenderer> ().sprite, Vector3.zero, 0, Color.white);
            }
                
            if (obj.GetComponent<tile_Script>().containsCrystal && obj.GetComponent<tile_Script>().crystalInTile)
            {
                hasInterest = true;
                if (obj.GetComponent<tile_Script>().crystalInTile.GetComponent<SpriteRenderer>())
                {
                    uicontrol.placeBubble(obj.GetComponent<tile_Script>().crystalInTile.GetComponent<SpriteRenderer>().sprite, Vector3.zero, 0, Color.white);
                }
                else
                {
                    uicontrol.placeBubble(uicontrol.crystalAssembledSprite, Vector3.zero, 1, Color.white);
                }
            }
            if (obj.GetComponent<tile_Script>().containsEnemy && obj.GetComponent<tile_Script>().enemyInTile && obj.GetComponent<tile_Script>().enemyInTile.GetComponent<living_Script>())
            {
                hasInterest = true;
                if(!obj.GetComponent<tile_Script>().enemyInTile.GetComponent<living_Script>().hasSeveralRenderers)
                    uicontrol.placeBubble(obj.GetComponent<tile_Script>().enemyInTile.GetComponent<SpriteRenderer>().sprite, Vector3.zero, 0, Color.white);
                else
                    uicontrol.placeBubble(obj.GetComponent<tile_Script>().enemyInTile.GetComponent<living_Script>().myAssembledSprite, Vector3.zero, 0, Color.white);
            }
        }

        // Set arrow if we find no interest points in the current path.
        if (!hasInterest) {
            setArrow();
        }
    }

    public void findPath() {
        path1.Clear();
        path2.Clear();
        path3.Clear();
        path4.Clear();
        path5.Clear();
        path6.Clear();
        path7.Clear();
        path8.Clear();
        interestValues[0] = 0;
        interestValues[1] = 0;
        interestValues[2] = 0;
        interestValues[3] = 0;
        interestValues[4] = 0;
        interestValues[5] = 0;
        interestValues[6] = 0;
        interestValues[7] = 0;
        tempList.Clear();
        listIndex = 0;



        if (!moreInterestingCheck)
            chosenPath.Clear();



        if (!currentTile)
        {
            foreach (GameObject obj in objectmaster.tileObjects)
            {
                if (Vector2.Distance(transform.position, obj.transform.position) < 0.1f)
                    currentTile = obj;
            }
        }

        // Randomizing the List of the current tiles neighbors, to avoid the Hero always choosing the same (first) object
        // in the list (In cases where all directions have the same number of interesting outcomes). 
        //We then pass the tile objects through a function to determine which one has the most interesting
        // path (in the eyes of the Hero).
        for (int i = 0; i < currentTile.GetComponent<tile_Script>().neighboringTiles.Count; i++)
        {
            if (currentTile.GetComponent<tile_Script>().neighboringTiles[i] != currentTile)
            {
                GameObject temp = currentTile.GetComponent<tile_Script>().neighboringTiles[i];
                int randomIndex = Random.Range(i, currentTile.GetComponent<tile_Script>().neighboringTiles.Count);
                currentTile.GetComponent<tile_Script>().neighboringTiles[i] = currentTile.GetComponent<tile_Script>().neighboringTiles[randomIndex];
                currentTile.GetComponent<tile_Script>().neighboringTiles[randomIndex] = temp;
            }
        }

        for (int i = 0; i < currentTile.GetComponent<tile_Script>().neighboringTiles.Count; i++) {
            listIndex++;
            checkPath(currentTile.GetComponent<tile_Script>().neighboringTiles[i]);
        }
        if (path1.Count > lineOfSight) {
            for (int toRemove = path1.Count -1; toRemove > lineOfSight; toRemove--) {
                path1.RemoveAt (toRemove);
            }
        }

        if (path2.Count > lineOfSight) {
            for (int toRemove = path2.Count -1; toRemove > lineOfSight; toRemove--) {
                path2.RemoveAt (toRemove);
            }
        }

        if (path3.Count > lineOfSight) {
            for (int toRemove = path3.Count -1; toRemove > lineOfSight; toRemove--) {
                path3.RemoveAt (toRemove);
            }
        }

        if (path4.Count > lineOfSight) {
            for (int toRemove = path4.Count -1; toRemove > lineOfSight; toRemove--) {
                path4.RemoveAt (toRemove);
            }
        }

        if (path5.Count > lineOfSight)
        {
            for (int toRemove = path5.Count - 1; toRemove > lineOfSight; toRemove--)
            {
                path5.RemoveAt(toRemove);
            }
        }

        if (path6.Count > lineOfSight)
        {
            for (int toRemove = path6.Count - 1; toRemove > lineOfSight; toRemove--)
            {
                path6.RemoveAt(toRemove);
            }
        }

        if (path7.Count > lineOfSight)
        {
            for (int toRemove = path7.Count - 1; toRemove > lineOfSight; toRemove--)
            {
                path7.RemoveAt(toRemove);
            }
        }

        if (path8.Count > lineOfSight)
        {
            for (int toRemove = path8.Count - 1; toRemove > lineOfSight; toRemove--)
            {
                path8.RemoveAt(toRemove);
            }
        }

        foreach (GameObject obj in path1) {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
            {
                interestValues[0]++;
            }
        }

        foreach (GameObject obj in path2)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
                {
                    interestValues[1]++;
                }
        }

        foreach (GameObject obj in path3)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsTrashcan && obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
                {
                    interestValues[2]++;
                }
        }
        foreach (GameObject obj in path4)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
                {
                    interestValues[3]++;
                }
        }

        foreach (GameObject obj in path5)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
            {
                interestValues[4]++;
            }
        }

        foreach (GameObject obj in path6)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
            {
                interestValues[5]++;
            }
        }

        foreach (GameObject obj in path7)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
            {
                interestValues[6]++;
            }
        }

        foreach (GameObject obj in path8)
        {
            if (obj.GetComponent<tile_Script>().containsTrashcan || (obj.GetComponent<tile_Script>().containsItem && !obj.GetComponent<tile_Script>().obfuscateItem) || obj.GetComponent<tile_Script>().containsCrystal || (obj.GetComponent<tile_Script>().isExit && obj.GetComponent<tile_Script>().isOpen) || obj.GetComponent<tile_Script>().containsEnemy || (obj.GetComponent<tile_Script>().containsChest && !obj.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted) || obj.GetComponent<tile_Script>().isTutorialInterest)
            {
                interestValues[7]++;
            }
        }

        int interest = 0;

        foreach (int value in interestValues) {
            if (value >= interest) {
                interest = value;
            }
        }

        if (interest == interestValues[0] && path1.Count > 0)
        {
            tempList.Add(path1[0]);
        }
        if (interest == interestValues[1] && path2.Count > 0)
        {
            tempList.Add(path2[0]);
        }

        if (interest == interestValues[2] && path3.Count > 0)
        {
            tempList.Add(path3[0]);
        }

        if (interest == interestValues[3] && path4.Count > 0)
        {
            tempList.Add(path4[0]);
        }

        if (interest == interestValues[4] && path5.Count > 0)
        {
            tempList.Add(path5[0]);
        }

        if (interest == interestValues[5] && path6.Count > 0)
        {
            tempList.Add(path6[0]);
        }

        if (interest == interestValues[6] && path7.Count > 0)
        {
            tempList.Add(path7[0]);
        }

        if (interest == interestValues[7] && path8.Count > 0)
        {
            tempList.Add(path8[0]);
        }

        int tempVisited = 1000;
        foreach (GameObject obj in tempList) {
            if (obj.GetComponent<tile_Script>().numberOftimesVisited < tempVisited) {
                tempVisited = obj.GetComponent<tile_Script>().numberOftimesVisited;
                leastVisitedTile = obj;
            }
        }

        tempList.Clear();

        if (path1.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path1) {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path1) {
                    tempList.Add(obj);
                }
            }
        }

        if (path2.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path2)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path2)
                {
                    tempList.Add(obj);
                }
            }
        }

        if (path3.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path3)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path3)
                {
                    tempList.Add(obj);
                }
            }
        }

        if (path4.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path4)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path4)
                {
                    tempList.Add(obj);
                }
            }
        }


        if (path5.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path5)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path5)
                {
                    tempList.Add(obj);
                }
            }
        }

        if (path6.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path6)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path6)
                {
                    tempList.Add(obj);
                }
            }
        }

        if (path7.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path7)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path7)
                {
                    tempList.Add(obj);
                }
            }
        }

        if (path8.Contains(leastVisitedTile))
        {
            if (!moreInterestingCheck)
            {
                foreach (GameObject obj in path8)
                {
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
            }
            else
            {
                foreach (GameObject obj in path8)
                {
                    tempList.Add(obj);
                }
            }
        }

        if (moreInterestingCheck)
        {
            if (interest > currentInterestValue)
            {
                chosenPath.Clear();
                foreach (GameObject obj in tempList)
                {  
                    chosenPath.Add(obj);
                }
                nextTile = chosenPath[0];
                currentInterestValue = interest;
                pathIndex = 0;
                StartCoroutine(delayedWander(0.1f, true));

            }
            else {
                continuePath();
            }

            moreInterestingCheck = false;
        }
        else {
            pathIndex = 0;
            StartCoroutine(delayedWander(0.1f, false));
        }
    }

    public void checkPath(GameObject obj) {
        // 0 = Right, 1 = Left, 2 = Up, 3 = Down;
        int dir = 0;

        if (listIndex == 1)
            path1.Add(obj);

        if (listIndex == 2)
            path2.Add(obj);

        if (listIndex == 3)
            path3.Add(obj);

        if (listIndex == 4)
            path4.Add(obj);

        if (listIndex == 5)
            path5.Add(obj);

        if (listIndex == 6)
            path6.Add(obj);

        if (listIndex == 7)
            path7.Add(obj);

        if (listIndex == 8)
            path8.Add(obj);

        // Check the direction 
        if (obj.transform.position.x > currentTile.transform.position.x && obj.transform.position.y == currentTile.transform.position.y)
        {
            dir = 0;
            
        }
        if (obj.transform.position.x < currentTile.transform.position.x && obj.transform.position.y == currentTile.transform.position.y)
        {
            dir = 1;

        }
        if (obj.transform.position.y > currentTile.transform.position.y && obj.transform.position.x == currentTile.transform.position.x)
        {
            dir = 2;

        }
        if (obj.transform.position.y < currentTile.transform.position.y && obj.transform.position.x == currentTile.transform.position.x)
        {
            dir = 3;

        }

        if (obj.transform.position.y > currentTile.transform.position.y && obj.transform.position.x > currentTile.transform.position.x) {
            dir = 4;
        }

        if (obj.transform.position.y > currentTile.transform.position.y && obj.transform.position.x < currentTile.transform.position.x)
        {
            dir = 5;
        }

        if (obj.transform.position.y < currentTile.transform.position.y && obj.transform.position.x > currentTile.transform.position.x)
        {
            dir = 6;
        }

        if (obj.transform.position.y < currentTile.transform.position.y && obj.transform.position.x < currentTile.transform.position.x)
        {
            dir = 7;
        }

        for (int i = 0; i < obj.GetComponent<tile_Script>().neighboringTiles.Count; i++) {
            if (dir == 0)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x > obj.transform.position.x && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y == obj.transform.position.y)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 1)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x < obj.transform.position.x && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y == obj.transform.position.y)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 2)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y > obj.transform.position.y && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x == obj.transform.position.x)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 3)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y < obj.transform.position.y && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x == obj.transform.position.x)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 4)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y > obj.transform.position.y && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x > obj.transform.position.x)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 5)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y > obj.transform.position.y && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x < obj.transform.position.x)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 6)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y < obj.transform.position.y && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x > obj.transform.position.x)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }

            if (dir == 7)
            {
                if (obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.y < obj.transform.position.y && obj.GetComponent<tile_Script>().neighboringTiles[i].transform.position.x < obj.transform.position.x)
                {
                    checkPath(obj.GetComponent<tile_Script>().neighboringTiles[i]);
                }
            }
        }
    }

    // Called at the arrival on a new tile, this function will check if the new tile or any neighboring tiles contain 
    //anything that requires an instant action. This could be an enemy, a crystal construct, an item etc.
    public void checkAction() {
        wandering = false;
        GameObject exitTemp = null;
        float closestToNext = 1000f;
        // Fake number just set to find the tile closest to our end-point if we're on a Player-decided path.
        float disToTarget = 1000;

        // Removing interest point if its a tutorial-based one
        if (currentTile.GetComponent<tile_Script>().isTutorialInterest)
            currentTile.GetComponent<tile_Script>().isTutorialInterest = false;

        // Checking current tile for items that haven't been obfuscated/hidden.
        if (currentTile.GetComponent<tile_Script>().containsItem && !currentTile.GetComponent<tile_Script>().obfuscateItem)
        {
            itemInTile = true;
            wandering = false;
        }
        // Checking current tile for chests that haven't been looted.
        if (currentTile.GetComponent<tile_Script>().containsChest && !currentTile.GetComponent<tile_Script>().chestInTile.GetComponent<chestScript>().isLooted)
        {
            chestInTile = true;
            wandering = false;
        }

        // Checking current tile for trashcans that haven't been used.
        if (currentTile.GetComponent<tile_Script> ().containsTrashcan && !currentTile.GetComponent<tile_Script> ().trashcanUsed) {
            trashcanInTile = true;
            wandering = false;
        }

        // Checking current tile for teleports.
        if (currentTile.GetComponent<tile_Script>().isTeleportTile) {
            teleportTile = true;
        }

        // Checking neighboring tiles for objects.
        foreach (GameObject obj in currentTile.GetComponent<tile_Script>().neighboringTiles) {
            tile_Script tileObj = obj.GetComponent<tile_Script>();

            // If we're on a player-decided path, we will find the closest tile to the endpoint
            // among the neighboring tiles, and set that one as our next tile.
            if (onPlayerPath) {
                if (itemInTile)
                    itemInTile = false;
                if (enemyAround)
                    enemyAround = false;
                
                if (tileObj.disToTarget < disToTarget && tileObj != currentTile)
                {
                    disToTarget = tileObj.disToTarget;
                    nextTile = obj;
                }
            }

            if (tileObj.containsCrystal)
            {
                crystalAround = true;
                crystalTile = obj;
            }

            if (tileObj.containsTrashcan && !tileObj.trashcanUsed) {
                trashcanAround = true;
                chosenTile = obj;
            }

            if(tileObj.containsChest && !tileObj.chestInTile.GetComponent<chestScript>().isLooted) {
                chestAround = true;
                chosenTile = obj;
            }

            if (tileObj.containsItem && !tileObj.obfuscateItem)
            {
                itemAround = true;
                chosenTile = obj;
            }

            if (tileObj.containsEnemy && tileObj.GetComponent<tile_Script>().enemyInTile && Vector2.Distance(transform.position, tileObj.GetComponent<tile_Script>().enemyInTile.transform.position) <= 1.7f)
            {
                enemyAround = true;
                enemyObject = tileObj.GetComponent<tile_Script>().enemyInTile;
            }

            if (movingToExit) {
                if (obj.GetComponent<tile_Script> ().distanceToExit <= closestToNext) {
                    closestToNext = obj.GetComponent<tile_Script> ().distanceToExit;
                    exitTemp = obj;
                }
            }
        }

        // If we're currently on a teleport-tile, we will teleport to the tile tied to it and re-position the camera,
        // and check for a new action to perform.
        if(teleportTile)
        {
            transform.position = currentTile.GetComponent<tile_Script>().teleportDestination.transform.position;
            currentTile = currentTile.GetComponent<tile_Script>().teleportDestination;
            uicontrol.findAdventurer();
            uicontrol.cleanTeleportSpell();
            teleportTile = false;
            checkAction();
            return;
        }

        // If we're on a player-decided path, we carry on while placing an arrow-sprite indicating our next position.
        if (onPlayerPath && !GetComponent<living_Script>().isSleeping && !GetComponent<living_Script>().isConfused) {
            setArrow ();
            wandering = true;
            return;
        }

        // If an enemy is seen in one of the neighboring tiles, we should suspend all other actions, and attack him/her/it.
        if (enemyAround) {
            if (enemyObject && Vector2.Distance (enemyObject.transform.position, transform.position) <= 1.7f) {
                // Setting enemyobject so that we can attack it.
                GetComponent<living_Script> ().setEnemy (enemyObject);
                if(GetComponent<living_Script>().isSleeping)
                    GetComponent<living_Script>().wakeUp();

                if (enemyObject.GetComponent<living_Script> () && !enemyObject.GetComponent<living_Script>().isAttacking)
                    enemyObject.GetComponent<living_Script> ().setEnemy (gameObject);
                return;
            } else {
                enemyAround = false;
            }
        }

        // CheckAction is called by living_Script at this point, and thus we set sleeping
        // to false if we find that state true, and continue our last path, or start a new one.
        if(GetComponent<living_Script>().isSleeping)
        {
            // Check if we're wielding a weapon before calling animations.
            if (uicontrol.wieldedWeapon)
                GetComponent<heroScript>().performAction(1);
            else
                GetComponent<heroScript>().performAction(5);

            if (pathIndex + 1 == chosenPath.Count)
            {
                currentInterestValue = 0;
                StartCoroutine(delayedUpdate(0));
                return;
            }
            else if (currentTile.GetComponent<tile_Script>().neighboringTiles.Count > 2)
            {
                moreInterestingCheck = true;
                findPath();
            }
            else
            {
                pathIndex++;
                nextTile = chosenPath[pathIndex];
                wandering = true;
            }
            return;
        }

        // Found a crystal in a surrounding tile. Let's destroy it!
        if (crystalAround) {
            StartCoroutine(destroyCrystal());
            return;
        }
        // Found a chest or item in our current tile. Call to itemWait to check what the next action is.
        if (itemInTile || chestInTile) {
            StartCoroutine(itemWait());
            return;
        }

        // When we are confused, we move to a completely random neighboring tile.
        if(GetComponent<living_Script>().isConfused)
        {
            pathAbrupted = true;
            int ranTile = Random.Range(0, currentTile.GetComponent<tile_Script>().neighboringTiles.Count);
            moveToTile(currentTile.GetComponent<tile_Script>().neighboringTiles[ranTile]);
            return;
        }

        // Found an item or a chest in a surrounding tile. Let's move to it!
        if (itemAround || chestAround) {
            pathAbrupted = true;
            moveToTile(chosenTile);
            return;
        }

        // Found a trashcan in our currenttile. Call to itemWait to check what the next action is.
        if (trashcanInTile) {
            StartCoroutine (itemWait ());
            return;
        }

        // Found a trashcan in a surrounding tile. Let's move to it!
        if (trashcanAround) {
            pathAbrupted = true;
            moveToTile (chosenTile);
            return;
        }

        // Moving to exit.
        if (movingToExit) {
            setArrow ();
            moveToTile (exitTemp);
            //wandering = true;
            return;
        }

        // If path was abrupted by some action (usually by the Player forcing the Adventurer off his current path),
        // we choose a new path.
        if (pathAbrupted)
        {
            pathAbrupted = false;
            findPath();
            return;
        }


        // If the character has reached the last index in a list, or the tile has more than two exits, 
        // we will look for a new path.
        // If not, the Hero will just continue on his/her already chosen path.
        if (pathIndex +1 == chosenPath.Count)
        {
            currentInterestValue = 0;
            StartCoroutine(delayedUpdate(0));
            return;
        }
        else if(currentTile.GetComponent<tile_Script>().neighboringTiles.Count > 2) {
            moreInterestingCheck = true;
            findPath();
        }
        else
        {
            pathIndex++;
            nextTile = chosenPath[pathIndex];
            wandering = true;
        }
    }

    // Called after checking for more interesting paths mid-path. If the new path
    // isn't more interesting, the Hero will continue on the old path.
    public void continuePath() {
        pathIndex++;
        nextTile = chosenPath[pathIndex];
        wandering = true;
        if(uicontrol.wieldedWeapon)
            GetComponent<heroScript>().performAction(1);
        else
            GetComponent<heroScript>().performAction(5);
    }

    // This function is called whenever we want the character to move to a specific tile.
    // This is usually called when an item can be found at any neighboring tile. Once the item has
    // been inspected/picked up, the Hero will choose another path.
    public void moveToTile(GameObject obj) {
        pathAbrupted = true;
        nextTile = obj;
        wandering = true;
    }

    // Ienumerator called when the Hero is in range of a crystal construct.
    // He/She will pause to destroy it, then reassume the original path afterwards.
    // (Unless there are more interesting actions to perform in the vicinity).
    private IEnumerator destroyCrystal()
    {
        GameObject destroyedCrystal = null;
        // Performing the appropriate actions.
        GetComponent<heroScript>().bubbleUp("!");
        uicontrol.updateInfoText("The Adventurer found a strange crystal construct.");
        if(uicontrol.wieldedWeapon)
            GetComponent<heroScript>().performAction(2);
        else
            GetComponent<heroScript>().performAction(6);


        if (crystalTile.transform.position.x > transform.position.x)
            transform.eulerAngles = new Vector3(0, 0, 0);
        else
            transform.eulerAngles = new Vector3(0, 180, 0);

        // Takes a little while to destroy.
        yield return new WaitForSeconds(1f);
        if (Vector2.Distance(crystalTile.transform.position, transform.position) <= 2)
        {
            // Play appropriate sounds.
            soundcontroller.playSFX(6, transform.position);
            // Removing all traces of the crystal and destroying it.
            crystalTile.GetComponent<tile_Script>().containsCrystal = false;
            objectmaster.crystalObjects.Remove(crystalTile.GetComponent<tile_Script>().crystalInTile);

            if (crystalTile && crystalTile.GetComponent<tile_Script>().crystalInTile)
            {
                // Adding powercharges upon crystal destroyed.
                magescript.powerCharges += 1;

                // Checking if we're lucky enough to get a double return from destruction.
                if (Random.Range (0, 100) < uicontrol.numberOfCrystalReturnUpgrades)
                    magescript.powerCharges += 1;

                // Call to tutorial-script upon destroying a crystal for the first time.
                if (myTutorialScript.isTutorial && !myTutorialScript.secondDone)
                {
                    myTutorialScript.tutorialProgression += 1;
                }

                // Update Power Charge UI.
                uicontrol.updatePower(false);

                if (dungeonmaster.isFinalLevel) {
                    forcefield.destroyedCrystal (crystalTile.GetComponent<tile_Script> ().crystalInTile);
                }
                // Spawn in destroyed sprites and remove traces of crystal from the tile.
                crystalTile.GetComponent<tile_Script>().crystalInTile.transform.GetChild(0).transform.parent = crystalTile.transform;
                destroyedCrystal = (GameObject)Instantiate(crystalTile.GetComponent<tile_Script>().crystalInTile.GetComponent<itemScript>().destroyedPrefab);
                destroyedCrystal.transform.position = crystalTile.GetComponent<tile_Script>().crystalInTile.transform.position;
                destroyedCrystal.transform.parent = dungeonmaster.currentDungeon.transform;
                Destroy(crystalTile.GetComponent<tile_Script>().crystalInTile);
                crystalTile.GetComponent<tile_Script>().crystalInTile = null;

                // Call to levelscript to tell it we're one crystal down. (The Exit will only open once all crystals are gone).
                if (dungeonmaster.currentDungeon.GetComponent<levelScript>())
                {
                    dungeonmaster.currentDungeon.GetComponent<levelScript>().removeCrystal();
                }

            }
        }
            crystalAround = false;
            // Performing the appropriate actions.
            if (uicontrol.wieldedWeapon)
                GetComponent<heroScript>().performAction(3);
            else
                GetComponent<heroScript>().performAction(5);

            // Update info text.
            uicontrol.updateInfoText("The Adventurer destroyed the crystal construct.");

            // Remove one point of interest from current path.
            currentInterestValue--;
            // Once we are done, we will check if there's anything else to do in this or surrounding tiles.
            checkAction();
    }

    // Ienumerator called when the Hero arrives at a tile with an item in it. 
    // If it is shiny, it will be picked up. Else, the Hero will just ignore it
    // and continue on his/her way.
    private IEnumerator itemWait()
    {
        GameObject currentCheckTile = currentTile;
        if (!onPlayerPath || GetComponent<living_Script>().isAttacking) {
            // Finding our tilescript and itemscript for easy access.
            tile_Script curTile = currentCheckTile.GetComponent<tile_Script> ();
            if ((curTile.containsItem && curTile.itemInTile) || (curTile.containsChest && curTile.chestInTile && !curTile.chestInTile.GetComponent<chestScript> ().isLooted) || (curTile.containsTrashcan && !curTile.trashcanUsed)) {
                itemScript item = null;

                if (curTile.itemInTile)
                    item = curTile.itemInTile.GetComponent<itemScript> ();

                // Performing appropriate actions.
                if (uicontrol.wieldedWeapon)
                    GetComponent<heroScript> ().performAction (0);
                else
                    GetComponent<heroScript> ().performAction (6);

                GetComponent<heroScript> ().bubbleUp ("?");
                if (item) {
                    string findText = "";
                    if (item.isIdentified)
                        findText = item.itemName;
                    else
                        findText = item.itemShort;
                    
                    uicontrol.updateInfoText ("The Adventurer found " + findText + ".");
                }
                if (curTile.containsChest)
                    uicontrol.updateInfoText ("The Adventurer found a chest.");

                if (curTile.containsTrashcan)
                    uicontrol.updateInfoText ("The Adventurer found a trashcan.");

                // Stare at the item for a while before deciding what to do.
                yield return new WaitForSeconds (1);
                if (!onPlayerPath || !GetComponent<living_Script>().isAttacking && Vector2.Distance(currentCheckTile.transform.position, transform.position) < 0.5f)
                {
                    // Pick the item up if its shiny.
                    if (item && item.isShiny && curTile.itemInTile)
                    {
                        string pickUpText = "";
                        if (item.isIdentified)
                            pickUpText = item.itemName;
                        else
                            pickUpText = item.itemShort;
                        if (uicontrol.inventoryItems.Count >= GetComponent<living_Script>().inventoryCap)
                        {
                            uicontrol.updateInfoText("The Adventurer ignores " + pickUpText + " since he has a full inventory.");
                            itemInTile = false;
                        }
                        else
                        {
                            // Play an appropriate sound.
                            uicontrol.soundcontroller.playSFX(4, transform.position);
                            // Give an appropriate response.
                            GetComponent<heroScript>().bubbleUp("!");
                            uicontrol.updateInfoText("The Adventurer decides to pick up " + pickUpText + " since it seems rather important.");

                            // Pass the item on to our living_Script for further use.
                            GetComponent<living_Script>().pickUpItem(curTile.itemInTile);
                            // Remove any trace of the item from both scripts.
                            itemInTile = false;
                            curTile.containsItem = false;
                            curTile.itemInTile = null;

                            if (uicontrol.wieldedWeapon)
                            {
                                GetComponent<heroScript>().performAction(7);
                                GetComponent<heroScript>().performAction(0);
                            }

                        }
                    }
                    // Add to inventory if potion
                    else if (item && item.isPotion && curTile.itemInTile)
                    {
                        string pickUpText = "";
                        if (item.isIdentified)
                            pickUpText = item.itemName;
                        else
                            pickUpText = item.itemShort;

                        if (uicontrol.inventoryItems.Count >= GetComponent<living_Script>().inventoryCap)
                        {
                            uicontrol.updateInfoText("The Adventurer ignores " + pickUpText + " since he has a full inventory.");
                            itemInTile = false;
                        }
                        else
                        {
                            GameObject potion = curTile.itemInTile;
                            uicontrol.addInventory(potion);
                            itemInTile = false;
                            curTile.itemInTile.transform.position = new Vector2(1000, 1000);
                            curTile.containsItem = false;
                            curTile.itemInTile = null;

                            uicontrol.updateInfoText("The Adventurer decides to pick up " + pickUpText + " since it looks rather delicious.");
                            justFoundPotion = true;
                        }
                    }
                    else if (curTile.containsChest && !curTile.chestInTile.GetComponent<chestScript>().isLocked && !curTile.chestInTile.GetComponent<chestScript>().isLooted)
                    {
                        chestScript chestie = curTile.chestInTile.GetComponent<chestScript>();
                        if (uicontrol.numberOfInfluenceUpgrades < 2)
                        {
                            string lootText = "";
                            int ranLoot = Random.Range(1, chestie.itemsInChest.Count - 1);
                            if (ranLoot > chestie.itemsInChest.Count - 1)
                                ranLoot = chestie.itemsInChest.Count - 1;

                            if (ranLoot + uicontrol.inventoryItems.Count > GetComponent<living_Script>().inventoryCap)
                            {
                                ranLoot = GetComponent<living_Script>().inventoryCap - uicontrol.inventoryItems.Count;
                            }

                            for (int i = 0; i < chestie.itemsInChest.Count; i++)
                            {
                                GameObject temp = chestie.itemsInChest[i];
                                int randomIndex = Random.Range(i, chestie.itemsInChest.Count);
                                chestie.itemsInChest[i] = chestie.itemsInChest[randomIndex];
                                chestie.itemsInChest[randomIndex] = temp;
                            }

                            for (int i = 0; i < ranLoot; i++)
                            {
                                GameObject obj = (GameObject)Instantiate(chestie.itemsInChest[i]);
                                // Find a better way to do this.
                                if (!obj.GetComponent<itemScript>().isPotion && Random.Range(0, 100) < (modulemaster.magicChance+uicontrol.numberOfMagicFindUpgrades))
                                {
                                    obj.GetComponent<itemScript>().randArt = true;
                                }
                                obj.transform.position = new Vector2(1000, 1000);
                                uicontrol.addInventory(obj);
                                chestie.itemsInChest.Remove(chestie.itemsInChest[i]);
                                if (i == 0)
                                    lootText = obj.GetComponent<itemScript>().itemShort;
                                else if (i < ranLoot - 1)
                                    lootText += ", " + obj.GetComponent<itemScript>().itemShort + "";
                                else if (i == ranLoot - 1)
                                    lootText += " and " + obj.GetComponent<itemScript>().itemShort + "";
                            }
                            uicontrol.updateInfoText("The Adventurer looted " + lootText + " from the chest.");
                            chestie.openChest();
                            chestie.isLooted = true;
                            chestAround = false;
                            chestInTile = false;
                        }
                        else
                        {
                            uicontrol.actionPanelUp(3, curTile.chestInTile);
                            yield return new WaitForSeconds(3);
                            if (!canOpenChest)
                            {
                                string lootText = "";
                                int ranLoot = Random.Range(1, chestie.itemsInChest.Count);
                                if (ranLoot > chestie.itemsInChest.Count)
                                    ranLoot = chestie.itemsInChest.Count;

                                if (ranLoot + uicontrol.inventoryItems.Count > GetComponent<living_Script>().inventoryCap)
                                {
                                    ranLoot = GetComponent<living_Script>().inventoryCap - uicontrol.inventoryItems.Count;
                                }

                                for (int i = 0; i < chestie.itemsInChest.Count; i++)
                                {
                                    GameObject temp = chestie.itemsInChest[i];
                                    int randomIndex = Random.Range(i, chestie.itemsInChest.Count);
                                    chestie.itemsInChest[i] = chestie.itemsInChest[randomIndex];
                                    chestie.itemsInChest[randomIndex] = temp;
                                }

                                for (int i = 0; i < ranLoot; i++)
                                {
                                    GameObject obj = (GameObject)Instantiate(chestie.itemsInChest[i]);
                                    obj.transform.position = new Vector2(1000, 1000);
                                    uicontrol.addInventory(obj);
                                    chestie.itemsInChest.Remove(chestie.itemsInChest[i]);
                                    if (i == 0)
                                        lootText = obj.GetComponent<itemScript>().itemShort;
                                    else if (i < ranLoot - 1)
                                        lootText += ", " + obj.GetComponent<itemScript>().itemShort + "";
                                    else if (i == ranLoot - 1)
                                        lootText += " and " + obj.GetComponent<itemScript>().itemShort + "";
                                }
                                uicontrol.updateInfoText("The Adventurer looted " + lootText + " from the chest.");
                                chestie.openChest();
                                chestie.isLooted = true;
                                chestAround = false;
                                chestInTile = false;
                            }
                        }
                    }
                    else if (curTile.containsTrashcan && !curTile.trashcanUsed)
                    {
                        // Chance this to full inventory after a while. - Just unworn/unused inventory for now.
                        if (uicontrol.numberOfInfluenceUpgrades < 3)
                        {
                            string lootText = "";
                            int ranLoot = Random.Range(1, uicontrol.myInventory.Count - 1);
                            if (ranLoot > uicontrol.myInventory.Count - 1)
                                ranLoot = uicontrol.myInventory.Count - 1;

                            if (ranLoot > 0)
                            {
                                for (int i = 0; i < uicontrol.myInventory.Count; i++)
                                {
                                    GameObject temp = uicontrol.myInventory[i];
                                    int randomIndex = Random.Range(i, uicontrol.myInventory.Count);
                                    uicontrol.myInventory[i] = uicontrol.myInventory[randomIndex];
                                    uicontrol.myInventory[randomIndex] = temp;
                                }

                                for (int i = 0; i < ranLoot; i++)
                                {
                                    GameObject obj = uicontrol.myInventory[i];
                                    uicontrol.removeInventory(obj);
                                    if (i == 0)
                                        lootText = obj.GetComponent<itemScript>().itemShort;
                                    else if (i < ranLoot - 1)
                                        lootText += ", " + obj.GetComponent<itemScript>().itemShort + "";
                                    else if (i == ranLoot - 1)
                                        lootText += " and " + obj.GetComponent<itemScript>().itemShort + "";
                                }
                                uicontrol.updateInfoText("The Adventurer tosses " + lootText + " into the trashcan.");
                                curTile.trashcanUsed = true;
                                trashcanAround = false;
                                trashcanInTile = false;
                            }


                            else
                            {
                                uicontrol.updateInfoText("The Adventurer stares blankly at the trashcan.");
                                curTile.trashcanUsed = true;
                                trashcanAround = false;
                                trashcanInTile = false;
                            }
                        }
                        else
                        {
                            uicontrol.actionPanelUp(4, curTile.trashcanInTile);
                            yield return new WaitForSeconds(3);
                            if (!canUseTrashcan)
                            {
                                string lootText = "";
                                int ranLoot = Random.Range(1, uicontrol.myInventory.Count - 1);
                                if (ranLoot > uicontrol.myInventory.Count - 1)
                                    ranLoot = uicontrol.myInventory.Count - 1;


                                for (int i = 0; i < uicontrol.myInventory.Count; i++)
                                {
                                    GameObject temp = uicontrol.myInventory[i];
                                    int randomIndex = Random.Range(i, uicontrol.myInventory.Count);
                                    uicontrol.myInventory[i] = uicontrol.myInventory[randomIndex];
                                    uicontrol.myInventory[randomIndex] = temp;
                                }

                                for (int i = 0; i < ranLoot; i++)
                                {
                                    GameObject obj = uicontrol.myInventory[i];
                                    uicontrol.removeInventory(obj);
                                    if (i == 0)
                                        lootText = obj.GetComponent<itemScript>().itemShort;
                                    else if (i < ranLoot - 1)
                                        lootText += ", " + obj.GetComponent<itemScript>().itemShort + "";
                                    else if (i == ranLoot - 1)
                                        lootText += " and " + obj.GetComponent<itemScript>().itemShort + "";
                                }
                                uicontrol.updateInfoText("The Adventurer tosses " + lootText + " into the trashcan.");
                                curTile.trashcanUsed = true;
                                trashcanAround = false;
                                trashcanInTile = false;
                            }
                        }
                    }

                    // Ignore if its not.
                    else
                    {
                        if (currentCheckTile.GetComponent<tile_Script>().itemInTile)
                        {
                            if (!item)
                                item = currentCheckTile.GetComponent<tile_Script>().itemInTile.GetComponent<itemScript>();
                            uicontrol.updateInfoText("The Adventurer stares at " + item.itemShort + " for a while, but doesn't seem that interested in it.");
                            itemInTile = false;
                            // Obfuscating the item so that the Hero won't count it as interesting for a little while (i.e. keep returning to it).
                            curTile.obfuscateOn();
                        }
                        else if (currentCheckTile.GetComponent<tile_Script>().containsTrashcan && currentCheckTile.GetComponent<tile_Script>().trashcanUsed)
                        {
                            uicontrol.updateInfoText("The Adventurer stares at a trashcan for a while, but doesn't seem that interested in it.");
                            trashcanInTile = false;
                            trashcanAround = false;
                        }

                    }
                }
            }
        }

        // Find a new path.
        itemAround = false;
        pathAbrupted = false;
        canOpenChest = false;
        canUseTrashcan = false;
        trashcanAround = false;
        chestAround = false;
        findPath();
    }

    // A path set by the Wizard/Player using some form of spell.
    // The Hero will move towards this point regardless of other items/events
    // in current or surrounding tiles.
    public void setPath(GameObject dest)
    {
        if (itemInTile)
            itemInTile = false;
        if (enemyAround)
            enemyAround = false;
        if (trashcanAround)
            trashcanAround = false;
        if (chestAround)
            chestAround = false;

        onPlayerPath = true;
        pathAbrupted = true;
        Vector2 endPos = dest.transform.position;
        foreach (GameObject obj in objectmaster.tileObjects)
        {
            obj.GetComponent<tile_Script>().disToTarget = Vector2.Distance(obj.transform.position, endPos);
        }
        GetComponent<heroScript> ().performAction (1);
        endPosLocation = endPos;
        checkAction();
    }

    void FixedUpdate () {

        if (GetComponent<living_Script>().isAttacking && GetComponent<living_Script>().enemyObject) {
            if(!GetComponent<living_Script>().enemyObject.GetComponent<living_Script>())
            {
                GetComponent<living_Script>().isAttacking = false;
                enemyAround = false;
                enemyObject = null;
                // Performing the appropriate actions.
                if (uicontrol.wieldedWeapon)
                    GetComponent<heroScript>().performAction(3);
                else
                    GetComponent<heroScript>().performAction(5);

                checkAction();
            }
            if (Vector2.Distance (GetComponent<living_Script> ().enemyObject.transform.position, transform.position) > 1.7f) {
                GetComponent<living_Script> ().isAttacking = false;
                GetComponent<living_Script> ().enemyObject = null;
                enemyAround = false;
                enemyObject = null;
                // Performing the appropriate actions.
                if (uicontrol.wieldedWeapon)
                    GetComponent<heroScript>().performAction(3);
                else
                    GetComponent<heroScript>().performAction(5);

                checkAction();
            }

            wandering = false;
        }

        if (GetComponent<living_Script>().isSleeping)
        {       
            if(uicontrol.wieldedWeapon)
                GetComponent<heroScript>().performAction(0);
            else
                GetComponent<heroScript>().performAction(6);

            return;
        }

        if (wandering) {

            walkCounter++;
            if (walkCounter == walkLimit) {
                walkCounter = 0;
                soundcontroller.playSFX (3, transform.position);
            }
                
            if (enemyAround && !onPlayerPath) {
                wandering = false;
                return;
            }

            if (!nextTile)
                findPath ();

            if (nextTile.transform.position.x > transform.position.x)
                transform.eulerAngles = new Vector3(0, 0, 0);
            else
                transform.eulerAngles = new Vector3(0, 180, 0);

            // Setting a cap for the maximum amount of speed,
            float actualSpeed = 0f;
            actualSpeed = wanderSpeed;
            if (actualSpeed > 1.5f)
                actualSpeed = 1.5f;

            transform.position = Vector2.MoveTowards(transform.position, nextTile.transform.position, actualSpeed);
            if (Vector2.Distance(transform.position, nextTile.transform.position) < 0.1f) {

                // Arrived at the destination. Setting nexttile to currenttile.
                currentTile.GetComponent<tile_Script>().playerIsHere = false;
                currentTile.GetComponent<tile_Script>().roofAlphaBack();
                currentTile = nextTile;

                tile_Script curTile = currentTile.GetComponent<tile_Script>();
                curTile.numberOftimesVisited++;
                curTile.playerIsHere = true;
                if (objectmaster.roofVectors.Contains(currentTile.transform.position))
                {
                    curTile.roofAlphaChange (3);
                }
                GetComponent<living_Script>().currentTile = currentTile;
                if (curTile.isTrap) {
                    GetComponent<living_Script>().takeDamage(currentTile, curTile.trapDamage, 0);
                }

                if (curTile.isWallTrap) {
                    curTile.activateTrap ();
                }

                // We have moved onto a tile from our main path, which (should) contain an item.
                // Resetting the bool upon arrival.
                if (itemAround)
                    itemAround = false;

                // If the tile is an exit tile, and it is open, end the level.
                if (curTile.isExit && curTile.isOpen)
                {
                    transform.position = new Vector2(1000, 1000);
                    magescript.endLevel();
                    return;
                }

                // If we're on a path decided by the Wizard/Player, it will override
                // everything else.
                if (onPlayerPath) {
                    if (Vector2.Distance(transform.position, endPosLocation) < 0.1f) {
                        onPlayerPath = false;
                    }
                }
                // Check what to do next.
                checkAction();
            }
        }
    }
}

Name: musicCycler.cs

Project: A Moron's Quest

Description: Script designed to handle a cycle mechanism for the music tracks in A Moron's Quest.

Code:

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

// Music Cycling Script. Put this on an empty GameObject in the scene,
// and add an AudioSource-component to it. Turn off Play On Awake.
// Make sure to place it and parent it to whatever object has the 
// AudioListener Object (usually the Main Camera).

public class musicCycler : MonoBehaviour {

    // List of Music Clips to cycle through. Set up in the inspector.
    public List<AudioClip> audioClips;
    // Referance to the AudioSource on the Object.
    private AudioSource mySource;
    // Index of the current tune being played. (Defaults to 0 at start).
    private int songIndex;

    void Start () {
        
        // Finding the AudioSource.
        mySource = GetComponent<AudioSource>();
        // Running the function to play the next tune in line. (Index 0 at start).
        playClip();
    }
    
    // Update is called once per frame
    void Update () {

        // When the AudioSource ends the clip, isPlaying is automatically
        // set to false. When we detect this, we feed it the next clip in
        // line, and play that.
        if (!mySource.isPlaying) {

            // Increasing the index, so that we may pass the next clip 
            // in the audioClips-list.
            songIndex++;
            // Unless ofcourse it is the last clip in the list,
            // then we reset the index back to 0.
            if (songIndex == audioClips.Count)
                songIndex = 0;

            // Running the function once we've updated the index.
            playClip();
        }
    }

    // The function handling the placing and playing of the audioclips.
    private void playClip()
    {
        // Setting the next clip on the Audiosource to be our current clip-index in the audioClips-list.
        mySource.clip = audioClips[songIndex];
        // Playing the actual clip.
        mySource.Play();
    }
}

Name: Script_General_Save.cs

Project: You Are a Seed

Description: Script designed to serialize, save, and load to/from files. Written for You Are a Seed, prior to the decicion of making it a Facebook-game.

Code:

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System;

public class Script_General_Save : MonoBehaviour {

    public static Script_General_Save saveMaster;
    // Last saved Section.
    public string lastSection;
    // Position for last saved Section;
    public Vector3 lastSaveVector;
    // Which of the map-pieces have been loaded.
    public List<string> mapPiecesLoaded;
    // Which was our last Region.
    public string lastRegion;
    // Our GameMaster.
    private Script_General_Gamemaster master;
    // Are we currently loading a scene?
    public bool loading;

    void Awake () {
        if(saveMaster == null){
            DontDestroyOnLoad(gameObject);
            saveMaster = this;
        }
        else if(saveMaster != this) {
            Destroy(gameObject);
        }
    }

    public void Save(){
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/playerinfo.dat");

        playerData data = new playerData();
        data.lastSection = lastSection;
        data.lastSaveVector = lastSaveVector;
        data.mapPiecesLoaded = mapPiecesLoaded;
        data.lastRegion = lastRegion;
        bf.Serialize(file, data);
        file.Close();
    }

    public void Load() {
        if(File.Exists(Application.persistentDataPath +"/playerinfo.dat")) {
            BinaryFormatter bf = new BinaryFormatter();
            FileStream file = File.Open(Application.persistentDataPath + "/playerinfo.dat", FileMode.Open);
            playerData data = (playerData)bf.Deserialize(file);
            file.Close();

            lastRegion = data.lastRegion;
            lastSection = data.lastSection;
            lastSaveVector = data.lastSaveVector;
            mapPiecesLoaded = data.mapPiecesLoaded;

            loading = true;
        }
    }
}
[Serializable]
class playerData {
    public string lastSection;
    public Vector3 lastSaveVector;
    public List<string> mapPiecesLoaded;
    public string lastRegion;
}

Name: lab_mon.c

Project: Cabal (LPC Multi-User Dungeon Project)

Description: Code designed to create a semi-random monster, based on a "mutation level" within the code. Created for VikingMUD.org.

Code:

 

#include "../../defines.h"
#define SEVER_HIT 100
inherit CABAL_MON;

int mutation_level;
int limb_count;
string *random_race;
string *random_short;
string *random_bloated;
string *random_lump;
string *random_lump_ooze;
string *random_creature;
string *random_limbs;
string *random_glow;
string *limbs;

static void create() {
  ::create();
    
    add_id("unformed");
    
    random_race = ({"human","elf","dwarf","drow","gnoll","gnome","orc","goblin","troll"});
    random_short = ({"disgusting","unwholesome","repulsive","sickening","appalling","foul","obscene","repugnant","repellent","loathsome","nauseating","ugly","hideous","unsightly"});
    random_bloated = ({"bloated","swollen","turgid","bulging","distended","tumescent"});
    random_lump = ({"lump","chunk","clod","glob","clump","cluster", "gobbet"});
    random_lump_ooze = ({"oozing","seeping","noxious","deleterious","pernicious","pestilential","insalubrious"});
    random_creature = ({"creature","thing","being","horror","mutant","abomination","anathema"});
    random_limbs = ({"waxy grey","sickly green","pallid blue","pale red", "sallow yellow", "wan purple"});
    random_glow = ({"glowing","pulsating","emanating","radiating"});
    limbs = ({});
    
}

// Checking damage type of our current limb(s).
string dam_type_check(string check) {
    string dtype;
    if(check == random_limbs[0])
        dtype = "blunt";
    
    if(check == random_limbs[1])
        dtype = "acid";
    
    if(check == random_limbs[2])
        dtype = "cold";
    
    if(check == random_limbs[3])
        dtype = "fire";
    
    if(check == random_limbs[4])
        dtype = "electricity";
    
    if(check == random_limbs[5])
        dtype = "magic";
    
    return dtype;
}

void set_desc() {
    string desc, short0, short1, short2, short3, short4, short5, short6, short7, short8;
    int i;
    
    short1 = random_lump[random(sizeof(random_lump))];
    short2 = random_lump_ooze[random(sizeof(random_lump_ooze))];
    short3 = random_short[random(sizeof(random_short))];
    short4 = random_limbs[random(sizeof(random_limbs))];
    short5 = random_bloated[random(sizeof(random_bloated))];
    short6 = random_race[random(sizeof(random_race))];
    short7 = random_creature[random(sizeof(random_creature))];
    short8 = random_glow[random(sizeof(random_glow))];
    desc = "";
    
    if(short3 == "unwholesome" || short3 == "ugly" || short3 == "appalling" || short3 == "obscene" || short3 == "unsightly")
        short0 = "an";
    else
        short0 = "a";
    
    if(mutation_level == 1) {
        set_short("a "+short1+" of "+short2+" flesh");
        desc += "An utterly "+short3+" "+short1+" of "+short2+" flesh slithers around your feet here. It has a strange "+short4+" complexion. ";
        add_property("unarmed_damage_type", dam_type_check(short4));
        set_name(short3 + short2 +" of flesh");
        add_id(({"flesh",short2 +" flesh", short3 +" flesh", short1}));
    }
    
    if(mutation_level == 2) {
        set_short("a "+short5+" and " +short3+" "+short6+"");
        desc += "Covered in "+short3+" "+short2+" boils and tumours, dripping unnamable fluids, you see a "+short5+" "+short6+" stumbling towards "+
                "you. What manner of malicious disease could have had this impact on a poor soul? ";
        set_name(short5 +" "+short6+"");
        set_race(short6);
        add_id(short2 + " "+short6+"");
    }
    
    if(mutation_level == 3) {
        set_short(short0 + " "+short3+" "+short7+" of "+limbs[0]+" complexion");
        desc+="Bulging formlessly before you is "+short0+" "+short3+" "+short7+", its abominable figure "+
              "taken straight from some mad mans nightmares. The massive body of the thing covers almost the entirity "+
              "of your vision, a hellish visage fit only for the uttermost depths of insanity indeed. ";
        set_name(short3 +" "+short7+"");
        add_id(({short7, short4 +" "+short7+""}));
        set_race("mutant");
        add_property("unarmed_damage_type", dam_type_check(limbs[0]));
    }
    
    if(mutation_level == 4) {
            set_short(short0 + " "+short3+" "+short7+" "+short8+" in a sickly hue");
        desc+="The "+short3+" "+short7+" towering before you reeks of decay and death, its unfathomable formless figure a "+
              "parody of all things living and dead. The mere presence of the monstrosity sends tremors of turmoil down to "+
              "the very core of your soul. How did this thing come to be? ";
        set_name(short3 +" "+short7+"");
        add_id(({short7, short4 +" "+short7+""}));
        set_race("mutant");    
    }
    
    if(mutation_level >= 3)
        desc += "Flailing around its repulsive body you see ";
    if(mutation_level >= 4) {
        if(sizeof(limbs) > 1) {
            for(i = 0; i<sizeof(limbs); i++) {
                if(i != sizeof(limbs)-1)
                    desc += "a "+limbs[i]+" tentacle, ";
                else
                    desc += "and a "+limbs[i]+" tentacle.";
            }
        }
        else {
            desc += "a "+limbs[i]+" tentacle.";
        }
    }
    else {
        if(sizeof(limbs) > 1)
            desc += ""+limb_count+" "+limbs[0]+" tentacles.";
        else
            desc += ""+limb_count+" "+limbs[0]+" tentacle.";
    }
    set_long(desc);
}

string *query_limbcheck() {
    return limbs;
}

void add_limb(string type) {
    limbs = limbs + ({type});
}

void set_limbs(int i) {
    int x;
    int ran_limb;
    
    limb_count = i;
    ran_limb = random(sizeof(random_limbs));
    for(x = 0; x<i; x++) {
        if(mutation_level >= 4) 
            add_limb(random_limbs[random(sizeof(random_limbs))]);
        else
            add_limb(random_limbs[ran_limb]);
    }
}

int query_limbs() {
    return limb_count;
}

void remove_limb() {
    object *attackers;
    int removelimb;
    int i,x,dam;
    string *temp_limbs;
    string removed_limb;
    
    removelimb = random(sizeof(limbs));
    temp_limbs = limbs;
    
    if(limb_count > 1) {
        removed_limb = limbs[removelimb];
        limbs = ({});
        
        for(i = 0; i<sizeof(temp_limbs); i++) {
            if(i != removelimb) {
                add_limb(temp_limbs[i]);
            }
        }
        limb_count--;
        set_desc();
        tell_room(environment(this_object()), "A "+removed_limb+" flies off the torso of "+query_name()+", spraying yellowish liquid through the air.\n");
        attackers = query_attackers();
        if(attackers && this_object()) {
            for(x = 0; x<sizeof(attackers); x++) {
                dam = attackers[i]->hit_player(10+random(10) * mutation_level,"Acid", this_object());
                if(dam > 0) {
                    message("hityou","You are soaked in a splash of yellowish toxic liquid!\n", attackers[x]);
                    tell_room(environment(this_object()),attackers[x]->query_name() +" is soaked in a splash of yellowish toxic liquid.\n",({attackers[x]}));
                }
                else {
                    message("missyou","You avoid the spray of yellowish toxic liquid by mere inches.\n", attackers[x]);
                    tell_room(environment(this_object()),attackers[x]->query_name() +" avoids the spray of yellowish toxic liquid by mere inches.\n",({attackers[x]}));
                }
            }
        }
        
    }
}

void set_mlevel(int i) {
    mutation_level = i;
}

int query_mlevel() {
    return mutation_level;
}

void create_mon() {
    if(mutation_level >= 3) {
        set_limbs(mutation_level + random(7));
        add_hook("__fight_beat",store_fp("attack_func"));
        add_hook("__hit_player",store_fp("hit_func"));
    }
    set_hp(500 * mutation_level);
    add_property("unarmed_weapon_class", mutation_level * 10 + random(query_level()));
    call_out("delayed_desc", 1);
}

void delayed_desc() {
    set_desc();
    if(mutation_level >= 4)
        add_property("unarmed_damage_type", dam_type_check(limbs[0]));
}    

void attack_func() {
    int i;
    string dam_type;
    for(i = 1; i<limb_count; i++) {
        add_property("unarmed_damage_type", dam_type_check(limbs[i]));
        attack();
    }
    
    add_property("unarmed_damage_type", dam_type_check(limbs[0]));
}

int hit_func(int dam) {
    if(dam >= SEVER_HIT && limb_count > 1) {
        remove_limb();
    }
}