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

public class GameManager : MonoBehaviour
{
    #region Game-Manager - Instanz
    private static GameManager gmInstance;
    public static GameManager GmInstance
    {
        get
        {
            return gmInstance;
        }
    }
    #endregion

    #region Variablen- und Objekt-Deklaration
    public bool pauseGame;

    public int numberOfTries = 3, correctlyPlacedItems = 0;

    public float playerHealth;

    [SerializeField]
    private WinLosePanel winOrLose;

    [SerializeField]
    private GameObject mainMenu;

    [SerializeField]
    public NarratorScript narrator;

    [SerializeField]
    public GameObject scrollPanel, bookPanel;
    public bool pageOpened, scrollOpened;
    #endregion

    #region Awake
    private void Awake()
    {
        if (gmInstance != null && gmInstance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            gmInstance = this;
        }

        DontDestroyOnLoad(this.gameObject);

    }
    #endregion

    #region Start
    void Start()
    {
        pauseGame = false;
        pageOpened = false;
        scrollOpened = false;
    }
    #endregion

    #region Methoden
    public void TogglePause()
    {
        if (!pauseGame)
        {
            Cursor.visible = true;
            pauseGame = true;
            Time.timeScale = 0f;
        }
        else
        {
            Time.timeScale = 1f;
            Cursor.visible = false;
            pauseGame = false;
        }
    }

    public void ActivatePage(GameObject pageToOpen)
    {
        TogglePause();
        pageOpened = !pageOpened;
        pageToOpen.SetActive(pageOpened);
    }

    public void ActivatePage()
    {
        TogglePause();
        pageOpened = !pageOpened;
            if (scrollPanel.activeSelf)
                scrollPanel.SetActive(pageOpened);
            if (bookPanel.activeSelf)
                bookPanel.SetActive(pageOpened);

        
    }

    public void WinGame()
    {
        Debug.Log("Won!");
        winOrLose.winPanel.SetActive(true);
        TogglePause();
    }

    public void LoseGame()
    {
        Debug.Log("Lost!");
        winOrLose.losePanel.SetActive(true);
        TogglePause();
    }

    public void ResetCounters()
    {
        numberOfTries = 3;
        correctlyPlacedItems = 0;
    }
    #endregion

    #region Outdated Stuff
    /*

    /// 
    /// Methode zum "Entladen" aller Szenen, bis auf die Globale Szene, welche Controller, Kamera und UI enthält
    /// 
    public void UnloadLevel()
    {
        for (int i = SceneManager.sceneCount - 1; i > 1; i--)
        {
            SceneManager.UnloadSceneAsync(SceneManager.GetSceneAt(i));
            Debug.Log("Level " + i + " unloaded!");
        }
    }
    
    /// 
    /// Hier wird das jeweilige Level geladen. Zuvor werden andere Szenen entladen und der Ursprungszustand des Levels wiederhergestellt.
    /// 
    public void LevelLoader()
    {
        UnloadLevel();
        SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);
        SceneManager.SetActiveScene(SceneManager.GetSceneAt(1));
    }
    */

    //lol
    //public void ActivateScroll()
    //{
    //    TogglePause();
    //    scrollOpened = !scrollOpened;
    //    scrollPanel.SetActive(scrollOpened);
    //}

    ///*public void ActivateBook()
    //{
    //    TogglePause();
    //    pageOpened = !pageOpened;
    //    bookPanel.SetActive(pageOpened);
    //}*/
    #endregion Outdated Stuff
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LevelManager : MonoBehaviour
{
    #region Instanz des LevelManagers
    private static LevelManager lmInstance;
    public static LevelManager LmInstance
    {
        get
        {
            return lmInstance;
        }
    }
    #endregion


    #region Variablen- und Property-Deklaration

    /// 
    /// Enum für die Level-Namen. Die Int-Werte repräsentieren den Build-Index, zugehörig zur jeweiligen Szene.
    /// 
    /// 

    public enum SceneName { Village = 2, HubDungeon, Level1, Level2, Level3, TestDungeon = 8 }

    public enum MenuName { SceneChanger = 7, MainMenu, PauseMenu }

    [SerializeField]
    private SceneName startLevel = SceneName.HubDungeon;

    public bool sceneChangeRunning = false;
    #endregion

    #region Awake (incl. Singleton)
    private void Awake()
    {
        if (lmInstance != null && lmInstance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            lmInstance = this;
        }

        DontDestroyOnLoad(this.gameObject);

    }
    #endregion


    #region Start
    void Start()
    {
        StartCoroutine(UnloadLevel());
        StartCoroutine(LoadLevel(startLevel));
    }
    #endregion

    #region Methoden
    public void InitializeLevel(SceneName levelName)
    {
        StartCoroutine(UnloadLevel());
        StartCoroutine(LoadLevel(levelName));
        PlayerManager.PmInstance.ResetPlayerPosition();
    }
    #endregion

    public int ReturnActiveScene()
    {
        return SceneManager.GetActiveScene().buildIndex;
    }

    #region Coroutines
    public IEnumerator LoadLevel(SceneName level)
    {
        yield return null;
        AsyncOperation loadLevel = SceneManager.LoadSceneAsync((int)level, LoadSceneMode.Additive);
        loadLevel.allowSceneActivation = false;
        while (!loadLevel.isDone)
        {
            // Check if the load has finished
            if (loadLevel.progress >= 0.9f)
            {
                loadLevel.allowSceneActivation = true;
            }
            yield return null;
        }
        PlayerManager.PmInstance.ResetPlayerPosition();
        yield return new WaitUntil(() => !sceneChangeRunning);
        SceneManager.SetActiveScene(SceneManager.GetSceneByBuildIndex((int)level));
        //Debug.Log(SceneManager.GetActiveScene().name);
        if(!GameManager.GmInstance.pauseGame)
        {
            AudioManager.AmInstance.PlayMusic(ReturnActiveScene());
        }
    }

    IEnumerator UnloadLevel()
    {
        yield return null;
        if (SceneManager.sceneCount > 1)
        {
            AsyncOperation unloadLevel = SceneManager.UnloadSceneAsync(SceneManager.GetSceneAt(1));
            while (!unloadLevel.isDone)
            {
                yield return null;
            }
        }
    }

    public IEnumerator ReloadLevel()
    {
        yield return null;
        AsyncOperation unloadLevel = SceneManager.UnloadSceneAsync(SceneManager.GetSceneAt(1));
        while (!unloadLevel.isDone)
        {
            yield return null;
        }

        AsyncOperation loadLevel = SceneManager.LoadSceneAsync((int)SceneName.Level1, LoadSceneMode.Additive);
        while (!loadLevel.isDone)
        {
            yield return null;
        }

    }

    public IEnumerator SceneChanger()
    {
        sceneChangeRunning = true;
        AsyncOperation loadingScreen = SceneManager.LoadSceneAsync((int)MenuName.SceneChanger, LoadSceneMode.Additive);
        yield return new WaitForSeconds(3f);
        SceneManager.UnloadSceneAsync((int)MenuName.SceneChanger);
        sceneChangeRunning = false;
        yield return null;
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerManager : MonoBehaviour
{
    #region Instanz vom PlayerManager
    private static PlayerManager pmInstance;
    public static PlayerManager PmInstance
    {
        get
        {
            return pmInstance;
        }
    }
    #endregion

    #region Variablendeklaration
    private Vector2 origin = new Vector2(-10.4f, -29.87f);

    [SerializeField]
    private Player player;
    //private Player playerPrefab;

    private Inventory inventory;
    #endregion

    #region Awake
    private void Awake()
    {
        if (pmInstance != null && pmInstance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            pmInstance = this;
        }

        DontDestroyOnLoad(this.gameObject);

        player = FindObjectOfType();
    }
    #endregion


    private void OnEnable()
    {
        inventory = GetComponent();        
    }

    #region Start
    void Start()
    {
        InitializePlayer();
    }
    #endregion


    #region Methoden
    /// 
    /// Player wird neu initialisiert: Inventar leeren, Gesundheit voll, Player-Position zurückgesetzt
    /// 
    public void InitializePlayer()
    {
        Inventory.instance.ClearInventory();
        player.Health = 100f;
        ResetPlayerPosition();
    }

    /// 
    /// Player-Position wird auf einen voreingestellten Ursprungswert gesetzt. 
    /// Später eventuell mittels Array, für verschiedene Levels.
    /// 
    public void ResetPlayerPosition()
    {
        player.transform.position = origin;
    }

    public bool MovementBlocked()
    {
        if (GameManager.GmInstance.pauseGame || LevelManager.LmInstance.sceneChangeRunning)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;

public class AudioManager : MonoBehaviour
{
    #region Instanz des AudioManagers
    private static AudioManager amInstance;
    public static AudioManager AmInstance
    {
        get
        {
            return amInstance;
        }
    }
    #endregion

    [SerializeField]
    private Slider musicVol, sfxVol, masterVol;

    [SerializeField]
    private AudioMixer audioMixer;

    private AudioSource gameMusic;
    [SerializeField]
    private AudioSource gameSFX;
    [SerializeField]
    private AudioSource narratorsVoice;

    [SerializeField]
    private AudioClip[] gameMusicClip;

    [SerializeField]
    private AudioClip collectItemSound, bubblePopUp, bubblePopDown;
    

    #region Awake (incl. Singleton)
    private void Awake()
    {
        if (amInstance != null && amInstance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            amInstance = this;
        }

        DontDestroyOnLoad(this.gameObject);

        gameMusic = GetComponent();
    }
    #endregion


    public void SetMusicLevel()
    {
        audioMixer.SetFloat("musicVolume", musicVol.value);
    }

    public void SetSFXLevel()
    {
        audioMixer.SetFloat("sfxVolume", sfxVol.value);
    }

    public void SetMasterLevel()
    {
        audioMixer.SetFloat("masterVolume", masterVol.value);
    }

    public void PlayMusic(int clipNumber)
    {
        gameMusic.Stop();
        if (clipNumber < gameMusicClip.Length)
        {
            gameMusic.clip = gameMusicClip[clipNumber];
        }
        gameMusic.Play();
    }

    public void PlayBubblePopUp()
    {
        gameSFX.PlayOneShot(bubblePopUp, 0.15f);
    }
    public void PlayBubblePopDown()
    {
        gameSFX.PlayOneShot(bubblePopDown, 0.15f);
    }

    public void PlayCollectItemSound()
    {
        gameSFX.PlayOneShot(collectItemSound, 0.5f);
    }

    public void PlaySound(AudioSource _gameSFX, AudioClip soundToPlay, float clipVolume)
    {
        _gameSFX.PlayOneShot(soundToPlay, clipVolume);
    }

    public void PlaySound(AudioSource _gameSFX, AudioClip[] soundToPlay, float clipVolume)
    {
        _gameSFX.PlayOneShot(soundToPlay[Random.Range(0, soundToPlay.Length)], clipVolume);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnimateBeings : MonoBehaviour
{
    #region Variablen und Properties
    protected Rigidbody2D myRigidbody;
    protected Animator myAnimator;
    private AnimateBeingSounds abSound;


    [SerializeField]
    protected float movementSpeed = 5f;

    private const float maxHealth = 100f;   // Wert für maximale Gesundheit

    private float health;       // Member-Variable für Gesundheit
    public float Health         // zugehöriges Property
    {
        get
        {
            return health;      // gibt aktuellen Gesundheitswert zurück
        }

        set     // Setter sichert ab, dass Gesundheit nicht unter 0 bzw Maximalwert nicht überschreiten kann
        {
            if(value > maxHealth)
            {
                health = maxHealth;
            }
            else if (value <= 0)
            {
                health = 0;
            }
            else
            {
                health = value;
            }
        }
    }


    /// Zugriff auf den Sprite-Renderer, um Blinken zu realisieren
    /// Wird als Array deklariert, um auch Child-Objects erfassen zu können
    private SpriteRenderer[] renderSprites;
    #endregion

    #region Awake
    private void Awake()
    {
        myRigidbody = GetComponent();
        myAnimator = GetComponent();
        abSound = GetComponent();
        renderSprites = GetComponentsInChildren();      // Sprite-Renderer jedes Child-Objects werden ins Array geladen

        myAnimator.SetBool("isAlive", true);        
        health = maxHealth;     // Gesundheit wird zu Beginn auf Maximalwert gesetzt
    }
    #endregion


    #region Methoden-Implementierung
    /// 
    /// Update-Funktion für die Bewegung der Lebend-Objekte inklusive Setzen der Animations-Parameter
    /// Deklariert als Virtual, um von abgeleiteten Klassen überschrieben werden kann
    /// 
    public virtual void Movement(Vector2 movementDirection)
    {
        /// Wenn der Charakter lebt, darf er sich bewegen. Falls nicht, wird der Bewegungsvektor auf 0 gesetzt.
        if (BeingAlive())
        {
            myRigidbody.velocity = movementDirection.normalized * movementSpeed;   // Bewegung
        }
        else
        {
            myRigidbody.velocity = Vector2.zero;
        }

        /// Wenn sich der Charakter bewegt, wird er auch entsprechend animiert
        if (movementDirection.x != 0 || movementDirection.y != 0)
        {
            myAnimator.SetBool("isMoving", true);
            myAnimator.SetFloat("moveX", movementDirection.x);
            myAnimator.SetFloat("moveY", movementDirection.y);
        }
        else
        {
            myAnimator.SetBool("isMoving", false);
        }
    }


    public virtual void Attack()
    {
        myAnimator.SetTrigger("isAttacking");        
    }
    /// 
    /// Überprüft, ob das Wesen am Leben ist. Falls nicht, wird Sterbeanimation eingeleitet.
    /// 
    /// Gibt einen Bool zurück.
    public virtual bool BeingAlive()
    {
        if(Health <= 0)
        {
            StopAllCoroutines();
            myAnimator.SetBool("isAlive", false);
            return false;
        }
        else
        {
            return true;
        }
    }


    /// 
    /// Kreatur nimmt Schaden, ein bestimmter Wert wird abgezogen und die Hit-Animation wird aktiviert.
    /// Eine Coroutine lässt den Charakter blinken, wenn er getroffen wurde.
    /// 
    /// Der abzuziehende Schadenswert wird an die Funktion übergeben.
    public virtual void TakeDamage(float damage)
    {        
        Health -= damage;
        abSound.PlayHitSound();        
        myAnimator.SetTrigger("gotHit");
        if(health > 0)
        {
            StartCoroutine(BlinkOnHit());
        }
    }
    
   
    /// 
    /// Einzelnes Blinken.
    /// Die For-Schleife durchläuft sämtliche Children des jeweiligen GameObjects, damit nicht nur ein Element blinkt.
    /// Der blinkState-Parameter entscheidet mittels Modifikation des Alpha-Kanals über On/Off-Status.
    /// 
    /// float-Wert zwischen 0 und 1 (0 = volle Transparenz, 1 = volle Sichtbarkeit)
    private void Blink(float blinkState)
    {
        for(int i = 0; i < renderSprites.Length; i++)
        {
            this.renderSprites[i].material.color = new Color(1, 1, 1, blinkState);
        }
    }

    /// 
    /// Coroutine, welche das Blinken bei einem Treffer realisiert.
    /// 
    /// 
    private IEnumerator BlinkOnHit()
    {
        for(int i = 0; i < 3; i++)
        {
            Blink(0.5f);
            yield return new WaitForSeconds(0.2f);
            Blink(1f);
            yield return new WaitForSeconds(0.2f);
        }
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnimateBeingSounds : MonoBehaviour
{
    protected AudioSource abAudioSource;

    [SerializeField]
    protected AudioClip[] footStep;

    [SerializeField]
    protected AudioClip hitSound, attackSound;


    private void OnEnable()
    {
        abAudioSource = GetComponent();
        abAudioSource.loop = false;
        abAudioSource.playOnAwake = false;
    }

    public void PlayFootStep()
    {
        AudioManager.AmInstance.PlaySound(abAudioSource, footStep, 1f);
    }

    public virtual void PlayAttackSound()
    {
        AudioManager.AmInstance.PlaySound(abAudioSource, attackSound, 1f);
    }

    public virtual void PlayHitSound()
    {
        AudioManager.AmInstance.PlaySound(abAudioSource, hitSound, 2.5f);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConditionObjectsScript : InteractableObjects
{
    public bool conditionCheck;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemies : AnimateBeings
{
    public Player player;

    protected bool playerIsInSight;           //Bool ob der Player in Reichweite ist


    private void Start()
    {
        // FindObjectOfType verwendet, um den Player auch Szenenübergreifend zu finden
        player = FindObjectOfType();
        myAnimator.SetBool("isAlive", true);
        playerIsInSight = false;
    }

    /// 
    ///Methode zur Verfolgung des Players.
    /// 
    public override void Movement(Vector2 playerPosition)
    {
        if (BeingAlive())
        {
            myRigidbody.MovePosition(Vector2.MoveTowards(transform.position, playerPosition, movementSpeed * Time.deltaTime));
        }
    }

    /// 
    /// Spezialisierte BeinAlive Funktion für die Enemies
    /// 
    /// 
    public override bool BeingAlive()
    {
        if (Health <= 0)
        {
            myAnimator.SetBool("isAlive", false);

            myRigidbody.velocity = Vector2.zero;
            myRigidbody.isKinematic = true;
            this.gameObject.GetComponent().enabled = false;
            Invoke("KillEnemy", 2f);

            return false;
        }
        else
        {
            return true;
        }
    }

    /// 
    /// Wenn der Spieler den Trigger bereich betritt wird der Bool das er in der Nähe ist auf true gesetzt.
    /// Ist vorläufig bis ich einen Raycast implementiert habe.
    /// 
    protected void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            playerIsInSight = true;
        }
    }

    /// 
    /// Wenn der Trigger verlassen wird, wird der Bool auf false gesetzt
    /// 
    protected void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            playerIsInSight = false;
        }
    }

    /// 
    /// Gegner nach 2 Sekunden Despawnen
    /// 
    protected void KillEnemy()
    {
        Destroy(this.gameObject);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// 
/// Basisklasse für alle Interactables
/// 
public class InteractableObjects : MonoBehaviour
{
    #region Override-Methoden
    /// 
    ///  Überschreibbare Methode, die bei Interaktion mit dem jeweiligen Objekt
    ///  vom Interagierenden (in dem Fall vom Player) aufgerufen wird.
    /// 
    public virtual void OnInteraction()
    {
        Debug.Log("Interacted with" + gameObject.name);
    }

    /// 
    /// Überladung der Methode zur Interaktion, bei der das Item übergeben wird, 
    /// mit welchem die Interaktion stattfindet
    /// 
    /// Das Item wird von der aufrufenden "InteractWith"-Methode mitgegeben
    public virtual void OnInteraction(Item item)
    {
        Debug.Log(gameObject.name + "interacted with " + item.name);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Player : AnimateBeings
{
    #region Variablen- und Objektdeklaration
    [SerializeField]
    private Inventory inventory;
    private RaycastHit2D objectHit;


    // Variablen und Objektreferenzen für die Sprechblasen
    [SerializeField]
    private GameObject speechBubblePrefab;
    private GameObject speechBubbleSpawned;
    private Vector3 bubbleOffset = new Vector3(1.1f, 0.9f, 0);
    #endregion

    private void OnEnable()
    {
        inventory = GetComponent();
    }

    #region Methoden
    /// 
    /// Der CircleCast fragt Objekte in der Umgebung ab und bestimmt den Radius, in welchem interagiert werden kann.
    /// In der Variable objectHit wird das Objekt in Reichweite gespeichert.
    /// 
    /// Es wird ein bool zurückgegeben, der Auskunft darüber gibt, ob überhaupt ein Objekt getroffen wurde.
    public bool CircleCast()
    {
        objectHit = Physics2D.CircleCast(new Vector2(transform.position.x, transform.position.y), 0.8f, Vector2.zero, 0, (1 << 8 | 1 << 9));
        if (objectHit.collider != null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private void SpawnBubble(string bubbleText)
    {
        if (!speechBubbleSpawned)
        {
            speechBubbleSpawned = Instantiate(speechBubblePrefab, transform.position + bubbleOffset, Quaternion.identity);
            speechBubbleSpawned.transform.SetParent(transform);
            speechBubbleSpawned.GetComponentInChildren().thisText.SetText(bubbleText);
        }
    }

    #region Methoden - Interaktion

    /// 
    /// Methode zur einfachen Interaktion mit einem Objekt (per Interact-Button). 
    /// Per Circle-Cast wird abgefragt, ob ein Objekt in Reichweite ist.
    /// Wenn ja, wird das entsprechende Objekt in einer Variable zwischengespeichert 
    /// und anschließend dessen .OnInteraction()-Methode aufgerufen.
    /// 
    public void InteractWith()
    {
        if (CircleCast())
        {
            InteractableObjects interactable = objectHit.collider.gameObject.GetComponent();
            interactable.OnInteraction();
            if (interactable.GetType() == typeof(Altar))
            {
                SpawnBubble("I think, I'll have to put something here.");
            }
        }
    }

    /// 
    /// Temporär!
    /// Methode, um ein Item im Inventar zu benutzen
    /// 
    /// 
    public void UseItem(int? inventorySlotNumber)
    {
        int i = 0;  // tmp-Variable zur Auswahl des Inventarslots
        if (inventorySlotNumber != null && inventorySlotNumber >= 0 && inventorySlotNumber <= inventory.items.Count)
        {
            i = (int)inventorySlotNumber - 1;   // Konvertierung des Nullable-Ints in regulären Int-Value, -1 da Inventarslots 0-basiert sind
            if (inventory.items.Count > 0 && inventory.items[i] != null)
            {
                if (CircleCast() && (inventory.items[i].itemCategory == "Food" || inventory.items[i].itemCategory == "Gifts" || inventory.items[i].itemCategory == "Hats"))
                {
                    InteractableObjects interactable = objectHit.collider.gameObject.GetComponent();
                    interactable.OnInteraction(inventory.items[i]);
                    return;
                }
                if (inventory.items[i].itemCategory == "Scroll")
                {
                    inventory.items[i].Use();
                }
            }
        }
        else
        {
            SpawnBubble("There is nothing to use!");
        }
    }
    #endregion Methoden - Interaktion


    #region Methoden - Overrided Standards
    public override void Attack()
    {
        if (CircleCast())
        {
            Enemies attackTarget = objectHit.collider.gameObject.GetComponent();
            Vector2 myPosition = new Vector2(this.transform.localScale.x, this.transform.localScale.y);


            if (attackTarget.GetType() == typeof(Slime))
            {
                attackTarget.TakeDamage(100f);
            }
            else if (attackTarget.GetType() == typeof(Skeleton))
            {
                attackTarget.TakeDamage(50f);
            }
            else
            {
                Debug.Log("I don't want to attack that!");
                return;
            }
        }
        base.Attack();
    }


    public override bool BeingAlive()
    {
        // teilt dem Gamemanager den aktuellen Lebens-Status mit (für die Health-Bar)
        GameManager.GmInstance.playerHealth = Health;

        if (Health <= 0)
        {
            //StopAllCoroutines();
            myAnimator.SetBool("isAlive", false);
            GameManager.GmInstance.LoseGame();
            return false;
        }
        else
        {
            myAnimator.SetBool("isAlive", true);
            return true;
        }
    }


    public override void Movement(Vector2 movementDirection)
    {
        if (!PlayerManager.PmInstance.MovementBlocked())
        {
            base.Movement(movementDirection);
        }
        else
        {
            myRigidbody.Sleep();
            myAnimator.SetBool("isMoving", false);
        }
    }
    #endregion Methoden - Overrided Standards

    #endregion Methoden

    #region OnTrigger- & OnCollider-Functions
    /// 
    /// Kollisionsabfrage.
    /// Der Spieler nimmt festen Schadenswert, sobald er einen Gegner berührt.
    /// 
    /// Gameobject, welches berührt wurde.
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Enemy"))
        {
            TakeDamage(25f);
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("Projectile"))
        {
            TakeDamage(10f);
        }
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    private Vector2 movementDirection;
    private bool isAttacking = false;
    private bool isInteracting = false;
    private int? usedKey = null;
    Player player;
    #endregion

    #region Awake
    private void Awake()
    {
        player = GetComponent();
        movementDirection = new Vector2(0f, 0f);
    }
    #endregion

    #region Update
    private void Update()
    {
        // Spielereingaben werden im Pause-Modus und bei Szenenwechsel nicht abgefangen
        if (!PlayerManager.PmInstance.MovementBlocked())
        {
            GetInput();
            ApplyInput();
        }
    }
    #endregion

    #region FixedUpdate
    private void FixedUpdate()
    {
        ApplyPhysicsInput();
    }
    #endregion


    #region Methoden
    /// 
    /// Abfangen der Eingaben
    /// 
    private void GetInput()
    {
        movementDirection.x = Input.GetAxis("Horizontal");
        movementDirection.y = Input.GetAxis("Vertical");

        // Buttons für Angriff
        if (Input.GetButtonDown("Jump"))
        {
            isAttacking = true;
        }
        if (Input.GetButtonUp("Jump"))
        {
            isAttacking = false;
        }

        // Button für Interaktion
        if (Input.GetKeyDown(KeyCode.E))
        {
            isInteracting = true;
        }
        if (Input.GetKeyUp(KeyCode.E))
        {
            isInteracting = false;
        }


        /// Eingabedaten für Inventar
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            usedKey = 1;
        }
        if (Input.GetKeyUp(KeyCode.Alpha1))
        {
            usedKey = null;
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            usedKey = 2;
        }
        if (Input.GetKeyUp(KeyCode.Alpha2))
        {
            usedKey = null;
        }
        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            usedKey = 3;
        }
        if (Input.GetKeyUp(KeyCode.Alpha3))
        {
            usedKey = null;
        }
        if (Input.GetKeyDown(KeyCode.Alpha4))
        {
            usedKey = 4;
        }
        if (Input.GetKeyUp(KeyCode.Alpha4))
        {
            usedKey = null;
        }

    }

    /// 
    /// Umsetzung des Inputs für die Update-Methode
    /// 
    private void ApplyInput()
    {
        if (isAttacking)
        {
            player.Attack();
            isAttacking = false;
        }

        if (isInteracting)
        {
            player.InteractWith();
            isInteracting = false;
        }

        /// Benutzung eines Items im Inventar
        if (usedKey != null)
        {
            player.UseItem(usedKey);
            usedKey = null;
        }

    }

    /// 
    /// Physics-Input für die Fixed-Update
    /// 
    private void ApplyPhysicsInput()
    {
        player.Movement(movementDirection);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerSound : AnimateBeingSounds
{
    [SerializeField]
    public AudioClip collectItemSound;

    public void PlayCollectItemSound()
    {
        AudioManager.AmInstance.PlaySound(abAudioSource, collectItemSound, 1.5f);
    }

    public override void PlayAttackSound()
    {
        AudioManager.AmInstance.PlaySound(abAudioSource, attackSound, 0.1f);
    }

    public override void PlayHitSound()
    {
        AudioManager.AmInstance.PlaySound(abAudioSource, hitSound, 1f);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    public static Inventory instance;

    public List items = new List();
    public const int space = 4;

    public Transform itemsParent;

    // Delegates für eine Callback-Funktion, die das Inventory-UI über Änderungen informieren
    public delegate void OnItemChanged();
    public OnItemChanged onItemChangedCallback;

    #region Singleton
    private void Awake()
    {
        if (instance != null)
        {
            Debug.Log("Warning! More than one inventory found");
            Destroy(gameObject);
            return;
        }
        else
        {
            instance = this;
        }
        //DontDestroyOnLoad(this.gameObject);
    }
    #endregion
    private void OnEnable()
    {
        //playerSound = GetComponent();
    }

    public bool Add(Item item)
    {
        if (items.Count < space)
        {
            items.Add(item);
            // Sagt der UI, dass sich im Inventory gerade was geändert hat
            if (onItemChangedCallback != null)
            {
                onItemChangedCallback.Invoke();
            }
            return true;
        }
        else
        {
            Debug.Log("Inventory full! Item not added." + items.Count);
            return false;
        }
    }

    public void RemoveItem(Item item)
    {
        items.Remove(item);

        // Sagt der UI, dass sich im Inventory gerade was geändert hat
        if (onItemChangedCallback != null)
        {
            onItemChangedCallback.Invoke();
        }
    }

    public void ClearInventory()
    {
        items.Clear();
        if (onItemChangedCallback != null)
        {
            onItemChangedCallback.Invoke();
        }
    }
}
using UnityEngine;
using UnityEngine.UI;

public class InventorySlot : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    public Image icon;

    Item item;
    #endregion


    #region Methoden
    public void AddItem(Item newItem)
    {
        item = newItem;

        icon.sprite = newItem.icon;
        icon.enabled = true;
    }

    public void ClearSlot()
    {
        item = null;

        icon.sprite = null;
        icon.enabled = false;
    }   

    public void UseItem()
    {
        if(item != null)
        {
            Debug.Log(item.name + "used");
            item.Use();
        }
    }
    #endregion
}
using UnityEngine;


[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/Items")]
public class Item : ScriptableObject
{
    #region Objektinhalte
    private Altar altar;
    public string itemName = "New Item";
    public string itemCategory = "Standard Item";
    public int itemID;
    public Sprite icon = null;
    #endregion

    #region Methoden
    public virtual void Use()
    {        
        Debug.Log("Used " + itemName);
    }

    public void RemoveFromInventory()
    {
        Inventory.instance.RemoveItem(this);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemPickup : MonoBehaviour

{
    #region Variablen- und Objekt-Deklaration
    public Item item;

    #endregion

    #region Methoden
    private void PickUp()
    {
        Debug.Log("Picked up " + item.itemName);
        bool wasPickedUp = Inventory.instance.Add(item);

        if (wasPickedUp)
        {
            AudioManager.AmInstance.PlayCollectItemSound();
            Destroy(gameObject);
        }
    }
    #endregion

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

public class ProjectileScript : MonoBehaviour
{
    private Transform playerPosition;

    [SerializeField]
    private float speed;

    private Vector2 target;

    void Start()
    {
        playerPosition = GetComponentInParent().player.transform;

        target = new Vector2(playerPosition.transform.position.x, playerPosition.transform.position.y);
    }

    void Update()
    {
        transform.position = Vector2.MoveTowards(transform.position, target, speed * Time.deltaTime);

        if (Vector2.Distance(gameObject.transform.position, target) < 0.1f)
        { 
            DestroyMe();
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            DestroyMe();
        }
    }

    private void DestroyMe()
    {
        Destroy(this.gameObject);
    }



    ///
    ///Problem = Knochen Despawnen nicht so wie sie sollen + beide Scripts noch nicht optimal! in Umfang und dirtyness!.
    ///
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Skeleton : Enemies
{
    [SerializeField]
    private GameObject bone;
    [SerializeField]
    private Transform[] patrolPoints;
    [SerializeField]
    private float attackDistance, retreatDistance, seeDistance;
    [SerializeField]
    private float shootingRate;

    private Vector2 lastPosition;

    private float shootingVariable;
    private int counter;
    private float patrolPauseTime;
    
    private void Start()
    {
        player = FindObjectOfType();
        myAnimator.SetBool("isAlive", true);
        playerIsInSight = false;
        counter = 0;
        patrolPauseTime = 1f;
        lastPosition = new Vector2(transform.position.x, transform.position.y);
        shootingVariable = 0;
    }

    private void FixedUpdate()
    {
        if (BeingAlive())
        {
            if (Vector2.Distance(transform.position, player.transform.position) <= seeDistance)
            {
                if (GameManager.GmInstance.playerHealth > 0)
                {
                    AttackMode();
                    playerIsInSight = true;
                }
                else
                {
                    playerIsInSight = false;
                }
            }
            else
            {
                playerIsInSight = false;
            }

            if (!playerIsInSight)
            {
                PatrolMode();
            }
        }
        else
        {
            
        }
    }

    private void AttackMode()
    {
        Vector2 playerPosition = new Vector2(player.transform.position.x, player.transform.position.y + 0.5f);

        if (Vector2.Distance(transform.position, player.transform.position) > attackDistance)
        {
            Movement(playerPosition);
            myAnimator.SetBool("isMoving", true);
        }
        else if (Vector2.Distance(transform.position, player.transform.position) > retreatDistance)
        {
            myAnimator.SetBool("isMoving", false);

            if (shootingVariable <= 0)
            {
                Attack();                
            }
            else
            {
                shootingVariable -= Time.deltaTime;
            }
        }
        else if (Vector2.Distance(transform.position, player.transform.position) <= retreatDistance)
        {
            myRigidbody.MovePosition(Vector2.MoveTowards(transform.position, playerPosition, -movementSpeed * Time.deltaTime));
            myAnimator.SetBool("isMoving", true);
        }

        SetFloats();
    }

    public override void Attack()
    {
        myAnimator.SetTrigger("isAttacking");
        GameObject newBone = Instantiate(bone, transform.position, Quaternion.identity);
        newBone.transform.parent = gameObject.transform;
        shootingVariable = shootingRate;
    }

    private void PatrolMode()
    {
        Movement(patrolPoints[counter].position);
        myAnimator.SetBool("isMoving", true);

        SetFloats();

        if (Vector2.Distance(transform.position, patrolPoints[counter].position) < 0.2f)
        {
            myAnimator.SetBool("isMoving", false);
            if (patrolPauseTime <= 0)
            {
                counter += 1;
                if (counter >= 4)
                {
                    counter = 0;
                }
                patrolPauseTime = 1f;
            }
            else
            {
                patrolPauseTime -= Time.deltaTime;
            }
        }
    }

    private void SetFloats()
    {
        Vector2 velocity = (Vector2)transform.position - lastPosition;
        lastPosition = transform.position;

        if (velocity.x != 0 || velocity.y != 0)
        {
            myAnimator.SetFloat("moveX", velocity.x);
            myAnimator.SetFloat("moveY", velocity.y);
        }
    }

    public override void Movement(Vector2 targetPoint)
    {
        myRigidbody.MovePosition(Vector2.MoveTowards(transform.position, targetPoint, movementSpeed * Time.deltaTime));
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SkeletonSound : AnimateBeingSounds
{
    private void Start()
    {
        abAudioSource.volume = 0.2f;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Slime : Enemies
{
    #region FixedUpdate
    /// 
    /// Wenn der Player in sicht ist wird die Bewegungsmethode aufgerufen.
    /// 
    private void FixedUpdate()
    {
        if (playerIsInSight)
        {
            Vector2 playerPosition = new Vector2(player.transform.position.x, player.transform.position.y + 0.5f);
            Movement(playerPosition);
        }
    }
    #endregion

    #region Methoden - Overrides
    #endregion


    #region Methoden - Originär
    ///// 
    ///// Gegner nach 2 Sekunden Despawnen
    ///// 
    //private void KillEnemy()
    //{        
    //    Destroy(this.gameObject);
    //}
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SlimeSound : AnimateBeingSounds
{
    private void Start()
    {
        abAudioSource.volume = 0.2f;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;


/// 
/// Mit dem NPC kann interagiert werden, daher erbt er von den Interactables
/// 
public class NPC : InteractableObjects
{
    #region Variablen- und Objekt-Deklaration
    protected enum TextFields { textMsg1, textMsg2, textMsg3, textMsg4 }

    protected string[] message = new string[4];

    // Speech-Bubble-Variablen
    [SerializeField]
    private GameObject speechBubblePrefab;
    private GameObject speechBubbleSpawned;
    private Vector3 bubbleOffset = new Vector3(1.1f, 0.9f, 0f);

    private int counter = -1;
    #endregion


    private void Start()
    {
        message[(int)TextFields.textMsg1] = "This is Standard-Message No. 1.";
        message[(int)TextFields.textMsg2] = "I'm not sure, but I suppose, this dungeons demon is hungry and wants some food as sacrifice.";
        message[(int)TextFields.textMsg3] = "I have heard, that there is some old cryptic writing with a hint which may be useful.";
        message[(int)TextFields.textMsg4] = "Fill this up";
    }

    #region Methoden - Overrides
    public override void OnInteraction()
    {
        base.OnInteraction();
               
        if (speechBubbleSpawned == null)
        {
            counter += 1;
            if (counter >= 4)
            {
                counter = 0;
            }
        }
        Debug.Log($"counter: {counter}");
        SpawnBubble(message[counter]);

        //SpawnBubble(message[Random.Range(0, 4)]);      
    }

    public override void OnInteraction(Item item)
    {
        SpawnBubble($"Yepp, that's a {item.name}. Tasty, huh?");
    }
    #endregion


    #region Methoden - Originär
    protected void SpawnBubble(string bubbleText)
    {
        if (!speechBubbleSpawned)
        {
            speechBubbleSpawned = Instantiate(speechBubblePrefab, transform.position + bubbleOffset, Quaternion.identity);
            speechBubbleSpawned.GetComponentInChildren().thisText.SetText(bubbleText);
        }
    }
    #endregion


    #region Outdated Stuff
    /// 
    /// Npc steht ja vor einem Teppich ohne Collider, der genau drei Felder groß ist.
    /// Ich dachte mir das dort die Items liegen und der Npc nur sowas sagt wie: "Eines dieser Items wird dein Vorhaben einen Erfolg werden lassen,
    /// die Anderen aber werden dich und dein Dorf ins Verderben stürzen".
    /// Dann sammelt man die alle ein und zieht weiter.
    /// So hätter der Npc den Nutzen dem Spieler schonmal zu sagen, dass es recht gefährlich ist einfach auszuprobieren.
    /// Tutorial mäßig quasi. Er kann auch schon sagen, das die Items auf den Altar gelegt werden.
    /// 
    public void TellTobi()
    {
        //Read above.
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_Bouncer : NPC
{
    void Start()
    {
        message[(int)TextFields.textMsg1] = "I won't let you pass!";
        message[(int)TextFields.textMsg2] = "That room is not for your eyes.";
        message[(int)TextFields.textMsg3] = "Please buy the DLC: 'Mount Mound - The next level' to pass through!";
        message[(int)TextFields.textMsg4] = "Proudly presented by a collaboration of Haeger & Friends and Chaoskopf-Games! (TM)";
    }

    public override void OnInteraction(Item item)
    {
        SpawnBubble($"You really want to oil my palm with a {item.name}? U think, I'm that cheap?");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_Father : NPC
{
    void Start()
    {
        message[(int)TextFields.textMsg1] = "Hi my s.. I mean ... daughter. Have you already chopped some wood for training?";
        message[(int)TextFields.textMsg2] = "You look beautifully strong today! Did you already slay monsters?";
        message[(int)TextFields.textMsg3] = "All I know is that there are 3 items in our village you need to collect. ";
        message[(int)TextFields.textMsg4] = "Maybe the owner of the destroyed house knows more.";
    }

    public override void OnInteraction(Item item)
    {
        SpawnBubble($"Right, my darling! Eat some {item.name}, that you grow to a proper b.. uhm girl!");
    }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_Hermit : NPC
{
    private void Start()
    {
        message[(int)TextFields.textMsg1] = "Maybe there was some kind of hint close to the items that will tell you who needs them.";
        message[(int)TextFields.textMsg2] = "I think the recipient of the item has hearing problems...  (hint hint)";
        message[(int)TextFields.textMsg3] = "I am totally convinced, that you will find your way.";
        message[(int)TextFields.textMsg4] = "Only One of the items you collected needs to be sacrificed.";
    }

    public override void OnInteraction(Item item)
    {
        SpawnBubble($"Mhhh, would you give me that {item.name}? I haven't eaten anything since 2 months!");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_Mother : NPC
{
    void Start()
    {
        message[(int)TextFields.textMsg1] = "Hello my dear! You look a bit chubby today.";
        message[(int)TextFields.textMsg2] = "Oh honey! You should not eat that much!";
        message[(int)TextFields.textMsg3] = "As our hero it is your task to calm the gods of Mount Mound.";
        message[(int)TextFields.textMsg4] = "I am the proud mother of the chosen hero of the village.";
    }

    public override void OnInteraction(Item item)
    {
        SpawnBubble($"Yikes, don't eat that {item.name}. You will just get fat!");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_Sad : NPC
{
    void Start()
    {
        message[(int)TextFields.textMsg1] = "*sniff* I lost all my goods and chattels by the lava!";
        message[(int)TextFields.textMsg2] = "Please save us from the angry gods of Mount Mound.";
        message[(int)TextFields.textMsg3] = "Did you collect all items? I think you need to sacrifice them, or at least one of them. ";
        message[(int)TextFields.textMsg4] = "Thats all i know. Talk to the crazy hermit north of the village";
    }

    public override void OnInteraction(Item item)
    {
        SpawnBubble($"Wow! A {item.name}. Maybe you should sacrifice that!");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_SomeGrayGuy : NPC
{
    private void Start()
    {
        message[(int)TextFields.textMsg1] = "Maybe you explore the dungeon a little bit, to find out, what secrets it keeps.";
        message[(int)TextFields.textMsg2] = "I'm not sure, but I suppose, this dungeons demon is hungry and wants some food as sacrifice.";
        message[(int)TextFields.textMsg3] = "I have heard, that there is some old cryptic writing with a hint which may be useful.";
        message[(int)TextFields.textMsg4] = "Maybe you check the sigils within the dungeons, to get a feeling for which sacrifice belongs to whom.";
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Altar : InteractableObjects
{
    private Gods associatedGod;


    private void Start()
    {
        associatedGod = GetComponentInParent();
    }

    #region Methoden-Overrides
    /// 
    /// Klasse die dem GameManager mitteilt, ob gewonnen oder verloren wurde, anhand des jeweils gegebenen Items
    /// 
    public override void OnInteraction(Item item)
    {
        switch(associatedGod.name)
        {
            case "Baal":

                if (item.name == "Chicken")
                {
                    RightChoice("Yummy! You brought me chicken! I'm pleased and no longer angry.\nLet me dispose the other useless crap for you!");
                }
                else
                {
                    WrongChoice($"Baaaah! Is that {item.name}? Do you want to poison me? For that failure may the streams of lava flow forever!");
                }
                break;

            case "Lilith":

                if (item.name == "Rose")
                {
                    RightChoice("Oh cutie! That's all I ever wanted as a proof of true love. I will not harm the villagers.\nI'll put the rest to the trash.");
                }
                else
                {
                    WrongChoice("Capitalistic b***h! All you can think about is physical wealth! I will melt all your crappy metalstuff and the villagers with it.");
                }
                break;

            case "Vulcan":

                if (item.name == "TinyEars")
                {
                    RightChoice("Wooooow! New ears! Now I can listen to Haendels 'Music for the royal fireworks'! No more need for fireworks in the village.");
                }
                else
                {
                    WrongChoice("Nope! Don't like it. Your ugly village will drown in lava!");
                }
                break;

            default:
                break;
        }

    
    }

    private void WrongChoice(string bubbleText)
    {
        associatedGod.SpawnBubble(bubbleText);
        GameManager.GmInstance.numberOfTries--;
        if (GameManager.GmInstance.numberOfTries == 0)
        {
            GameManager.GmInstance.LoseGame();
        }
    }

    private void RightChoice(string bubbleText)
    {
        associatedGod.SpawnBubble(bubbleText);
        GameManager.GmInstance.correctlyPlacedItems++;
        Inventory.instance.ClearInventory();
        if (GameManager.GmInstance.correctlyPlacedItems == 3)
        {
            GameManager.GmInstance.WinGame();
        }
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gods : MonoBehaviour
{
    [SerializeField]
    private Animator myAnimator;


    [SerializeField]
    private GameObject speechBubblePrefab;
    private GameObject speechBubbleSpawned;
    private Vector3 bubbleOffset = new Vector3(1.5f, -0.5f, 0f);

    /// 
    /// Es wird per Switch Case ausgewählt welcher Gott reagieren muss da der Spieler in seine Nähe gekommen ist.
    /// 
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            myAnimator.SetBool("playerIsClose", true);
        }
    }

    /// 
    /// Wenn der Trigger verlassen wird, wird der Bool auf false gesetzt
    /// 
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            myAnimator.SetBool("playerIsClose", false);
        }
    }

    public void SpawnBubble(string bubbleText)
    {
        if (!speechBubbleSpawned)
        {
            speechBubbleSpawned = Instantiate(speechBubblePrefab, transform.position + bubbleOffset, Quaternion.identity);
            speechBubbleSpawned.GetComponentInChildren().thisText.SetText(bubbleText);
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BrazierInteractionScript : ConditionObjectsScript
{
    private Animator myAnimator;

    [SerializeField]
    private Light myLight;

    void Start()
    {
        myAnimator = GetComponent();
        myAnimator.SetBool("isLit", false);
        conditionCheck = false;
        myLight.enabled = false;
    }

    public override void OnInteraction()
    {
        myAnimator.SetBool("isLit", true);
        conditionCheck = true;
        myLight.enabled = true;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChestScript : ConditionObjectsScript
{
    #region Variablen- und Objekt-Deklaration
    [SerializeField]
    private Animator chestAnimator;

    [SerializeField]
    private GameObject scroll;

    public bool chestOpened = false;

    #endregion

    private void Start()
    {
        conditionCheck = false;
    }

    #region Update
    private void Update()
    {
        
    }
    #endregion


    #region Override-Methoden
    public override void OnInteraction()
    {
        if(!chestOpened)
        {
            AnimateChest();
            Instantiate(scroll, new Vector3 (transform.position.x, transform.position.y - 1, 0), Quaternion.identity );
            base.OnInteraction();
            chestOpened = true;
            conditionCheck = true;
        }
    }
    #endregion

    #region Methoden - Originär
    private void AnimateChest()
    {
        chestAnimator.SetTrigger("isOpened");
    }
    #endregion
}


// Old AnimateChest:
//if (GameManager.GmInstance.playerInteraction)
//{
//    chestAnimator.SetBool("isOpened", GameManager.GmInstance.playerInteraction);
//    GameManager.GmInstance.riddleScroll.GetComponent().Activate();
//}
//else if (GameManager.GmInstance.playerInteraction == false && GameManager.GmInstance.pauseGame == true)
//{
//    GameManager.GmInstance.riddleScroll.GetComponent().Deactivate();
//}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlickeringFire : MonoBehaviour
{
    #region Variablen- und Methoden-Deklaration
    [SerializeField]
    private float minIntensity = 4.5F, maxIntensity = 6.0F;

    [SerializeField]
    private float flickeringRate = 0.1f;


    private float targetIntensity = 1.0f;
    private float lastIntensity = 1.0f;

    private float timePassed = 0.0f;

    private Light lightSource;
    private const double tolerance = 0.0001;
    #endregion

    #region Start
    private void Start()
    {
        lightSource = GetComponent();
        lastIntensity = lightSource.intensity;
    }
    #endregion

    #region FixedUpdate
    private void FixedUpdate()
    {
        Flicker();
    }

    private void Flicker()
    {
        timePassed += Time.deltaTime;
        lightSource.intensity = Mathf.Lerp(lastIntensity, targetIntensity, timePassed / flickeringRate);

        if (Mathf.Abs(lightSource.intensity - targetIntensity) < tolerance)
        {
            lastIntensity = lightSource.intensity;
            targetIntensity = Random.Range(minIntensity, maxIntensity);
            timePassed = 0.0f;
        }
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GateScript : MonoBehaviour
{
    [SerializeField]
    private ConditionObjectsScript conditionObject;


    private void Update()
    {
        if (conditionObject.conditionCheck)
        {
            Destroy(this.gameObject);
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InfoBookScript : InteractableObjects
{
    private GameObject pageToOpen;

    private void Start()
    {
        pageToOpen = GameManager.GmInstance.bookPanel;
    }

    public override void OnInteraction()
    {
        GameManager.GmInstance.ActivatePage(pageToOpen);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MovingObstacleScript : MonoBehaviour
{
    public Enemies enemy;
    [SerializeField]
    private float speed;

    private void Update()
    {
        if (!enemy.BeingAlive())
        {
            Invoke("MoveObstacle", 0.5f);
        }
    }

    private void MoveObstacle()
    {
        transform.Translate(new Vector3(0f, 0.5f, 0f) * speed * Time.deltaTime);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[CreateAssetMenu(fileName = "New Scroll", menuName = "Inventory/Scrolls")]
public class Scroll : Item
{
    private GameObject pageToOpen;

       
    #region Methoden - Overrides
    public override void Use()
    {
        Debug.Log("Scroll opened");
        pageToOpen = GameManager.GmInstance.scrollPanel;
        //GameManager.GmInstance.TogglePause();
        GameManager.GmInstance.ActivatePage(pageToOpen);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class SpeechBubble : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    [SerializeField]
    float fadingSpeed = 0;

    private float t;
    bool coroutineRunning = false;

    private Vector3 alignmentCorrection = new Vector3(-1f, -0.5f, 0);


    public TMP_Text thisText;
    #endregion


    #region Start
    private void Start()
    {
        thisText = GetComponentInChildren();
        //testText.SetText($"This text was called by {FindObjectOfType()}");
        if (!coroutineRunning)
        {
            StartCoroutine("PopUpBubble");
        }
    }
    #endregion


    #region Coroutines
    public IEnumerator PopUpBubble()
    {
        coroutineRunning = true;

        AudioManager.AmInstance.PlayBubblePopUp();

        while (t <= 1)
        {
            transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, t);
            t += 0.1f * fadingSpeed * Time.deltaTime;
            yield return new WaitForEndOfFrame();
        }
        yield return new WaitForSeconds(3f);

        AudioManager.AmInstance.PlayBubblePopDown();
        while (t > 0)
        {
            transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, t);
            t -= 0.1f * fadingSpeed * Time.deltaTime;
            yield return new WaitForEndOfFrame();
        }

        transform.localScale = Vector3.zero;


        coroutineRunning = false;
        Destroy(this.gameObject);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class NarratorScript : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    private TextMeshProUGUI narratorText;
    private TextDatabase dataBase = new TextDatabase();

    public string keyword = "Default";
    #endregion

    #region Awake
    private void Awake()
    {
        narratorText = gameObject.GetComponent();
    }
    #endregion


    #region Methoden
    public bool StartText(string textKeyword)
    {
        if(keyword == "Default")
        {
            StopAllCoroutines();
            keyword = textKeyword;
            StartCoroutine(FadeIn());
            return true;
        }
        else
        {
            return false;
        }
    }
    
    private void ResetText()
    {
        narratorText.text = " ";
    }
    #endregion

    #region Coroutines
    private IEnumerator FadeIn()
    {
        narratorText.maxVisibleCharacters = 0;

        // Get text from the Database.
        narratorText.text = dataBase.textSource[keyword];

        // Get number of Visible Characters in the text object.
        int totalVisibleCharacters = narratorText.text.Length;
        int counter = 0;
        Debug.Log($"counter : {counter}, total: {totalVisibleCharacters}");

        while (counter != totalVisibleCharacters)
        {
            int visibleCount = counter;

            // how many characters should TextMeshPro display?
            narratorText.maxVisibleCharacters = visibleCount;

            counter += 1;
            yield return new WaitForSeconds(0.025f);
        }

        keyword = "Default";
        Invoke("ResetText", 1f);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class TextDatabase
{
    public Dictionary textSource = new Dictionary()
    {
        {
            "Default", " "
        },
        //VillageTexts
        {
            "IntroductionToGameVillage", "Hey Guhrl, let me introduce myself. I am the “Narrator”, your red ball of joy. Now lets get you introduced to the game, to start please press Escape. This should open the menu where you'll finde the controlls. "
        },
        {
            "GoToTheVillageFirstVillage", "Now that we are all set up it is time to start this little adventure of yours. I have a feeling that it is essential for us to go to the village first and talk to the townsfolk. You 'll find it down the road to south-east."
        },
        {
            "AdmireTheVillage", "This is where you live?   Pretty place. \nLets hope the people here have some valid information for us! "
        },
        {
            "BrutalHelmetVillage", "Wow, this helmet looks brutal, so metal. "
        },
        //HubDungeon Texts
        {
            "IntroTextHubDungeon", "Uhh, spooky place. \nI'm looking forward to meet those gods everyone keeps blabbering about. What did the villagers say again? \nI think we need search the altar of Vulcan first. "
        },
        {
            "EnteringBaalRoomHubDungeon", "You see those stairs?, that must be one of the dungeon entrances. \nWe should totally go in there! "
        },
        {
            "BaalLooksHotHubDungeon", "O - M - G \nDo you see that? This is way better than I expected. "
        },
        {
            "StandigInFrontOfVulcanHubDungeon", "This seems to be one of them altars, but how do we know if it is the right one? \nHow Emanzia...HOW? "
        },
        {
            "PillarOfEternityHubDungeon", "Isn't this a beautiful pillar?! \nmhm-hmm...   thumbs up. "
        },
        {
            "DungeonTwoEntranceHubDungeon", "It seems it is dungeontime! \nHopp down that ladder girl. "
        },
        {
            "LillithAltarHubDungeon", "Uhh, one of them fancy Altars. \nI wonder if those paintings on the wall mean anything... "
        },
        //Dungeon One Texts
        {
            "IntroTextDungeonOne", "Uhh, what a fancy little Dungeon.  7/10 would recommend! "
        },
        {
            "GateClosedDungeonOne", "The way seems to be blocked by this fence. Bad luck... this would make an amazing shortcut! "
        },
        {
            "LittleConversationDUngeonOne", "Hey Emanzia, i have something on my mind. Why isn’t 11 pronounced “onety-one”? "
        },
        {
            "AttackOnDungeonOne", "Engaaaagggeeeeeeeeeeeee!!!!!11!!! "
        },
        {
            "EndOfTheRoadDungeonOne", "Well, that is a waste of time, DeAd EnD. "
        },
        {
            "ChestInSightDungeonOne", "Chest! Chest! I have seen it first! It is all mine! Leave your dirty little fingers of it! "
        },
        {
            "NarratorDisappointmentDungeonOne", "Ughh, that was a huge disappointment! You can keep the stupid piece of paper. At least the shortcut is open now. "
        },
        //Dungeon Two Texts
        {
            "IntroductionTextDungeonTwo", "Here we go! So many possibilities. \nI hope the game designers did a good job, those lazy dudes. "
        },
        {
            "NecklaceRoomDungeonTwo", "This is one pretty necklace. \nYou think I could sell that? "
        },
        {
            "SlimoBookRoomDungeonTwo", "Ohhh look at that little slimo, the poor thing i captured. This makes me sad. \nAlso there is a book, maybe you should take a look at it. "
        },
        {
            "ThisRoomIsBoringDungeonTwo", "Boring. "
        },
        {
            "ItIsGettingBetterDungeonTwo", "Ok, it gets better. I hope the next room keeps its promise. "
        },
        {
            "IDunnoIfThatsGoodDungeonTwo", "Mehh, its ok i guess. Let us keep going. "
        },
        {
            "BrazierRiddleDungeonTwo", "I wonder why that torch is unlit. But on the other hand who keeps the other ones lit? I thought no one entered this dungeon in over 100 years... \nNow this is the real riddle. "
        },
        {
            "RoseRoomDungeonTwo", "Roses are red, violetes are blue \nFuck the system and overthrow the capitalist regime. "
        },
        {
            "DangerFightTakeDamageDungeonTwo", "Caution Emanzia, that fella looks angry. \nYou could say he is... bad to the bone. "
        },
        {
            "DidTheStatueJustMoveDungeonTwo", "di-did you see that??? The statue just moved out of the way... I can not believe it. \nI bet the next room is of much importance. "
        },
        {
            "OneRingDungeonTwo", "This ring is so shiny... \n We want it, the master must give it to us. \nIt is ours, it is our precioussss. "
        },
        //Dungeon Three Texts
        {
            "CheaterDungeonThree", "Oh you little cheater, this was not supposed to happen. \nShame on you, SHAME! \nNow you will be trapped here for eternity you cheesy Fachbereichsleiter."
        }
    };
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TextTriggerScript : MonoBehaviour
{
    [SerializeField]
    private string myNameIsTheKeyword;

    private void KeywordTransmitter()
    {
        this.gameObject.SetActive(!GameManager.GmInstance.narrator.StartText(myNameIsTheKeyword));
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
            KeywordTransmitter();
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ChangeScene : MonoBehaviour
{
    [SerializeField]
    private LevelManager.SceneName jumpDestination;

    private void LoadNewScene()
    {
        LevelManager.LmInstance.InitializeLevel(jumpDestination);
    }

    #region OnTrigger-Events
    private void OnTriggerEnter2D(Collider2D collision)
    {        
        LevelManager.LmInstance.StartCoroutine(LevelManager.LmInstance.SceneChanger());
        Invoke("LoadNewScene", 0.5f);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class HealthBar : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    private Image healthBar;
    #endregion

    #region Awake
    private void Awake()
    {
        healthBar = GetComponent();
    }
    #endregion

    #region Update
    void Update()
    {

        healthBar.fillAmount = GameManager.GmInstance.playerHealth / 100;
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InventoryUI : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    Inventory inventory;

    public Transform itemsParent;
    InventorySlot[] slots;
    #endregion

    #region Start
    void Start()
    {
        inventory = Inventory.instance;
        inventory.onItemChangedCallback += UpdateUI;

        slots = itemsParent.GetComponentsInChildren();
    }
    #endregion


    #region Methoden
    void UpdateUI()
    {
        for(int i = 0; i < slots.Length; i++)
        {
            if(i < inventory.items.Count)
            {
                slots[i].AddItem(inventory.items[i]);
            }
            else
            {
                slots[i].ClearSlot();
            }
        }
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LoadingBar : MonoBehaviour
{
    private Image loadingBar;


    private float loadingTime = 3f;
    private float runningTime = 0f;
    private float percent = 0f;

    private void Awake()
    {
        loadingBar = GetComponent();

    }

    private void Start()
    {
        loadingBar.fillAmount = 0f;
    }

    private void Update()
    {
        runningTime += Time.deltaTime;
        percent = runningTime / loadingTime;
        loadingBar.fillAmount = Mathf.Lerp(0, 1, percent);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MainMenu : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    [SerializeField]
    protected GameObject myMenu;
    #endregion

    #region Start
    private void Start()
    {
        OpenMainMenu();
    }
    #endregion

    #region Methoden
    public void OpenMainMenu()
    {
        GameManager.GmInstance.TogglePause();
        myMenu.SetActive(true);
        AudioManager.AmInstance.PlayMusic(0);
    }

    public void PlayTheGame()
    {
        GameManager.GmInstance.TogglePause();
        myMenu.SetActive(false);

        LevelManager.LmInstance.InitializeLevel(LevelManager.SceneName.Village);
    }

    public void ExitTheGame()
    {
        Application.Quit();
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PauseMenu : MainMenu
{
    #region Variablen- und Objekt-Deklaration
    [SerializeField]
    private GameObject pauseMenuCanvas;

    public Canvas stupidCanvasShit;
    #endregion

    #region Start
    public void Start()
    {
        pauseMenuCanvas.SetActive(false);
    }
    #endregion

    #region Update
    private void Update()
    {
        if (Input.GetKeyUp(KeyCode.Escape))
        {
            if (!myMenu.activeSelf)
            {
                if (GameManager.GmInstance.pageOpened)
                {
                    GameManager.GmInstance.ActivatePage();
                    pauseMenuCanvas.SetActive(false);
                }
                else if (pauseMenuCanvas.activeSelf)
                {
                    ContinueTheGame();
                }
                else
                {
                    PauseTheGame();
                }
            }
        }
    }
    #endregion


    #region Methoden
    public void PauseTheGame()
    {
        GameManager.GmInstance.TogglePause();
        pauseMenuCanvas.SetActive(true);
        stupidCanvasShit.enabled = true;
        Debug.Log("Work you stupid shit");
    }

    public void ContinueTheGame()
    {
        GameManager.GmInstance.TogglePause();
        pauseMenuCanvas.SetActive(false);
        stupidCanvasShit.enabled = false;

    }

    public void ExitToMainMenu()
    {
        GameManager.GmInstance.TogglePause();
        OpenMainMenu();
        pauseMenuCanvas.SetActive(false);
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WinLosePanel : MonoBehaviour
{
    #region Variablen- und Objekt-Deklaration
    [SerializeField]
    public GameObject winPanel;

    [SerializeField]
    public GameObject losePanel;
    #endregion

    #region Start
    private void Start()
    {
        losePanel.SetActive(false);
        winPanel.SetActive(false);
    }
    #endregion

    #region Methoden
    public void ExitTheGame()
    {
        Application.Quit();
    }

    /// 
    /// Reset diverser Parameter, um das Spiel neu zu starten
    /// 
    public void RestartTheGame()
    {
        StartCoroutine(LevelManager.LmInstance.SceneChanger());
        PlayerManager.PmInstance.InitializePlayer();
        GameManager.GmInstance.ResetCounters();
        LevelManager.LmInstance.InitializeLevel(LevelManager.SceneName.Village);
        losePanel.SetActive(false);
        winPanel.SetActive(false);
        GameManager.GmInstance.TogglePause();
    }
    #endregion
}