Warp traps and tidying up the house

This commit is contained in:
2025-12-04 10:53:21 +00:00
parent e0c93be280
commit 00a433132b
38 changed files with 4036 additions and 192 deletions

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 30b3db05cf5720444aeb29bf0fd2822e
AudioImporter:
externalObjects: {}
serializedVersion: 8
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: c435e24017975524c8b66a69bbf99db5
AudioImporter:
externalObjects: {}
serializedVersion: 8
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: b3fc281979327fd4ea48ab0add748e35
AudioImporter:
externalObjects: {}
serializedVersion: 8
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: d3e2c5f35d74ee747b5552d0fc607ffc
AudioImporter:
externalObjects: {}
serializedVersion: 8
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 1a2fa0d484805034b8010c35e5e296b4
AudioImporter:
externalObjects: {}
serializedVersion: 8
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor; // Required for the buttons to appear
#endif
public class DebugControlPanel : MonoBehaviour
{
[Header("Target Scripts")]
public FrontDoorEvent frontDoorScript;
public StairWarp stairWarpScript;
// We don't need to drag in GameManager since it's a Singleton (GameManager.Instance)
[Header("Status")]
public string lastAction = "None";
// --- HELPER FUNCTIONS FOR THE BUTTONS ---
public void TestDoorbell()
{
if (frontDoorScript != null)
{
frontDoorScript.TriggerEvent();
lastAction = "Triggered Doorbell Sequence";
}
else Debug.LogError("Front Door Script not assigned!");
}
public void TestNightmare()
{
if (GameManager.Instance != null)
{
GameManager.Instance.TriggerNightmareMode();
lastAction = "Triggered Nightmare Mode";
}
else Debug.LogError("GameManager not found!");
}
public void ForceWarp()
{
// Note: You must change 'WarpPlayer' to PUBLIC in StairWarp.cs for this to work
if (stairWarpScript != null)
{
// We pass the player object to the warp script manually for testing
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player != null)
{
// Assuming you changed WarpPlayer to public, otherwise this line errors
stairWarpScript.WarpPlayer(player);
lastAction = "Forced Stair Warp";
}
}
}
public void ToggleAllLights()
{
if (GameManager.Instance != null)
{
foreach (LightSwitch sw in GameManager.Instance.allSwitches)
{
sw.Interact(); // Manually click every switch
}
lastAction = "Toggled All Lights";
}
}
}
// --- THE EDITOR MAGIC ---
// This part tells Unity how to draw the inspector for this specific script
#if UNITY_EDITOR
[CustomEditor(typeof(DebugControlPanel))]
public class DebugControlPanelEditor : Editor
{
public override void OnInspectorGUI()
{
// Draw the default variables (the slots to drag scripts into)
DrawDefaultInspector();
// Get reference to the script
DebugControlPanel myScript = (DebugControlPanel)target;
GUILayout.Space(20); // Add some spacing
GUILayout.Label("Event Triggers", EditorStyles.boldLabel);
// Draw Buttons
if (GUILayout.Button("Trigger Doorbell Event"))
{
myScript.TestDoorbell();
}
if (GUILayout.Button("Trigger Nightmare Mode"))
{
myScript.TestNightmare();
}
if (GUILayout.Button("Toggle All Lights"))
{
myScript.ToggleAllLights();
}
GUILayout.Space(10);
if (GUILayout.Button("Force Warp Player"))
{
myScript.ForceWarp();
}
}
}
#endif

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5e7c43ef1e9c4ea4285a66d4b9b1b630

View File

@@ -0,0 +1,165 @@
using UnityEngine;
using System.Collections;
public class FrontDoorEvent : MonoBehaviour, IInteractable
{
[Header("Door Settings")]
public float openAngle = 90f;
public float smoothSpeed = 2f;
[Header("Audio Clips")]
public AudioSource doorSource;
public AudioClip doorbellClip;
public AudioClip voiceClip; // <--- NEW: The voice line
[Tooltip("IMPORTANT: This must be a SINGLE knock sound, not a loop!")]
public AudioClip singleKnockClip;
public AudioClip doorOpenSound;
// windSound is removed
[Header("Timeline Settings")]
public float timeBeforeVoice = 3f; // Ring for 3 seconds
public float timeAfterVoice = 3f; // Ring for 3 seconds AFTER voice, then knock
[Header("Knocking Settings")]
[Range(0.1f, 1f)] public float heavyPitch = 0.8f;
public float totalKnockingDuration = 8f;
public float startDelay = 1.0f;
public float endDelay = 0.1f;
// State
private bool isOpen = false;
private bool eventActive = false;
private Quaternion initialRotation;
private Quaternion targetRotation;
void Start()
{
initialRotation = transform.localRotation;
targetRotation = initialRotation;
if(GameManager.Instance != null) GameManager.Instance.frontDoor = this;
}
void Update()
{
transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation, Time.deltaTime * smoothSpeed);
}
public void TriggerEvent()
{
if(eventActive || isOpen) return;
eventActive = true;
StartCoroutine(TheHauntingSequence());
}
IEnumerator TheHauntingSequence()
{
// --- PHASE 1: INITIAL RINGING ---
doorSource.pitch = 1f;
doorSource.volume = 0.5f;
doorSource.clip = doorbellClip;
doorSource.loop = true;
doorSource.Play();
// Wait...
float timer = 0f;
while (timer < timeBeforeVoice && !isOpen)
{
timer += Time.deltaTime;
yield return null;
}
if (isOpen) yield break;
// --- PHASE 2: THE VOICE ---
if (voiceClip != null)
{
doorSource.Stop(); // Cut the bell
doorSource.loop = false;
// Play Voice
doorSource.PlayOneShot(voiceClip);
// Wait for the exact length of the voice clip
float voiceTimer = 0f;
while (voiceTimer < voiceClip.length && !isOpen)
{
voiceTimer += Time.deltaTime;
yield return null;
}
}
if (isOpen) yield break;
// --- PHASE 3: RESUME RINGING ---
doorSource.clip = doorbellClip;
doorSource.loop = true;
doorSource.Play();
timer = 0f;
while (timer < timeAfterVoice && !isOpen)
{
timer += Time.deltaTime;
yield return null;
}
if (isOpen) yield break;
// --- PHASE 4: AGGRESSIVE KNOCKING (The Drummer Method) ---
doorSource.Stop();
doorSource.loop = false;
doorSource.pitch = heavyPitch; // Drop pitch for bass
float knockTimer = 0f;
while (knockTimer < totalKnockingDuration && !isOpen)
{
float progress = knockTimer / totalKnockingDuration;
// Volume Up
float currentVol = Mathf.Lerp(0.4f, 1f, progress);
doorSource.PlayOneShot(singleKnockClip, currentVol);
// Speed Up (Reduce Delay)
float currentDelay = Mathf.Lerp(startDelay, endDelay, progress);
// Wait for delay
float subTimer = 0f;
while(subTimer < currentDelay)
{
subTimer += Time.deltaTime;
knockTimer += Time.deltaTime;
if(isOpen) yield break;
yield return null;
}
}
// --- PHASE 5: SILENCE ---
Debug.Log("Knocking finished. Dead silence.");
}
public void Interact()
{
if (isOpen) return;
// Player Opened the Door!
isOpen = true;
eventActive = false;
// Open Visuals
targetRotation = initialRotation * Quaternion.Euler(0, openAngle, 0);
// Audio Reset
doorSource.Stop();
doorSource.pitch = 1f;
doorSource.volume = 1f;
// Just play the open sound, NO wind following it
doorSource.PlayOneShot(doorOpenSound);
// Trigger Nightmare Mode
if(GameManager.Instance != null) GameManager.Instance.TriggerNightmareMode();
}
public string GetDescription()
{
if (eventActive) return "Press [E] to <color=red>Check Noise</color>";
return isOpen ? "" : "Press [E] to Open";
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 48ce9e6b570caba4cb19ff957d7791a4

View File

@@ -6,6 +6,11 @@ public class GameManager : MonoBehaviour
public static GameManager Instance; public static GameManager Instance;
public List<LightSwitch> allSwitches = new List<LightSwitch>(); public List<LightSwitch> allSwitches = new List<LightSwitch>();
[Header("Front Door Event")]
public FrontDoorEvent frontDoor; // Assigned automatically by the door script
public int lightsOffToTriggerDoor = 4; // Event happens after 4 lights turned off
private int lightsTurnedOffCounter = 0;
void Awake() void Awake()
{ {
if (Instance == null) Instance = this; if (Instance == null) Instance = this;
@@ -19,16 +24,18 @@ public class GameManager : MonoBehaviour
public void CheckLights() public void CheckLights()
{ {
bool anyLightsOn = false; int currentOffCount = 0;
foreach (LightSwitch sw in allSwitches) foreach (LightSwitch sw in allSwitches)
{ {
if (sw.isLightOn) anyLightsOn = true; if (!sw.isLightOn) currentOffCount++;
} }
if (!anyLightsOn) // Check if we hit the threshold for the doorbell
if (currentOffCount >= lightsOffToTriggerDoor && frontDoor != null)
{ {
Debug.Log("All lights are off. Player can go to bed."); frontDoor.TriggerEvent();
// You can enable the "Bed" interaction collider here // Set to null so it doesn't trigger twice
frontDoor = null;
} }
} }
@@ -57,4 +64,24 @@ public class GameManager : MonoBehaviour
} }
return false; return false;
} }
public void TriggerNightmareMode()
{
Debug.Log("NOBODY IS HOME. NIGHTMARE MODE ACTIVE.");
foreach(LightSwitch sw in allSwitches)
{
// 1. Turn all lights back ON
sw.ForceLightOn();
// 2. Increase Difficulty (59% increase)
// If chance was 0.1 (10%), it becomes roughly 0.16
sw.malfunctionChance += (sw.malfunctionChance * 0.59f);
// Cap it so it's not impossible (e.g., max 50% fail rate)
if (sw.malfunctionChance > 0.5f) sw.malfunctionChance = 0.5f;
// 3. Make random scares more frequent
sw.subsequentEventChance += 10f;
}
}
} }

View File

@@ -7,7 +7,7 @@ public class InfiniteStairs : MonoBehaviour
public int loopsRequired = 3; public int loopsRequired = 3;
[Tooltip("Drag an empty GameObject here. Position it lower down the stairs.")] [Tooltip("Drag an empty GameObject here. Position it lower down the stairs.")]
public Transform resetPoint; public Transform[] resetPoint;
private int currentLoops = 0; private int currentLoops = 0;
@@ -29,8 +29,10 @@ public class InfiniteStairs : MonoBehaviour
// You must disable CC briefly to teleport, or it sometimes fights back // You must disable CC briefly to teleport, or it sometimes fights back
if (cc != null) cc.enabled = false; if (cc != null) cc.enabled = false;
foreach (Transform resetPoint in resetPoint)
{
other.transform.position = resetPoint.position + offset; other.transform.position = resetPoint.position + offset;
}
if (cc != null) cc.enabled = true; if (cc != null) cc.enabled = true;

View File

@@ -57,6 +57,8 @@ public class PlayerController : MonoBehaviour
void HandleGravity() void HandleGravity()
{ {
// If the trap disabled our controller, do not apply gravity!
if (controller == null || !controller.enabled) return;
// Check if the controller thinks it's on the ground // Check if the controller thinks it's on the ground
isGrounded = controller.isGrounded; isGrounded = controller.isGrounded;
@@ -75,6 +77,7 @@ public class PlayerController : MonoBehaviour
void HandleMovement() void HandleMovement()
{ {
if (controller == null || !controller.enabled) return;
Vector3 move = transform.right * moveInput.x + transform.forward * moveInput.y; Vector3 move = transform.right * moveInput.x + transform.forward * moveInput.y;
controller.Move(move * moveSpeed * Time.deltaTime); controller.Move(move * moveSpeed * Time.deltaTime);
} }

View File

@@ -0,0 +1,66 @@
using UnityEngine;
public class StairWarp : MonoBehaviour
{
[Header("Standard Warps")]
public Transform[] randomRooms;
[Header("Special Traps")]
public TVRoomTrap tvTrapScript; // <--- ASSIGN THIS IN INSPECTOR
[Range(0, 100)] public float trapChance = 10f; // 10% chance for the TV Trap
[Header("General Settings")]
[Range(0, 100)] public float warpChance = 30f;
public AudioSource audioSource;
public AudioClip warpWhooshSound;
private bool hasTriggered = false;
public void WarpPlayer(GameObject player)
{
// 1. Check for SPECIAL TRAP first
// If we have the script assigned and roll the dice successfully...
if (tvTrapScript != null && Random.Range(0, 100) < trapChance)
{
Debug.Log("TRIGGERING TV TRAP!");
tvTrapScript.TriggerTrap(player);
return; // Exit function, do not do normal warp
}
// 2. Normal Room Warp (Your existing logic)
if (randomRooms.Length == 0) return;
Transform target = randomRooms[Random.Range(0, randomRooms.Length)];
CharacterController cc = player.GetComponent<CharacterController>();
if (cc != null) cc.enabled = false;
player.transform.position = target.position;
player.transform.rotation = target.rotation;
if (cc != null) cc.enabled = true;
if (audioSource != null && warpWhooshSound != null)
audioSource.PlayOneShot(warpWhooshSound);
Debug.Log("Player warped to: " + target.name);
}
// (Keep your OnTriggerEnter / OnTriggerExit logic the same,
// just make sure OnTriggerEnter calls WarpPlayer(other.gameObject))
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player") && !hasTriggered)
{
hasTriggered = true;
if (Random.Range(0, 100) < warpChance)
{
WarpPlayer(other.gameObject);
}
}
}
void OnTriggerExit(Collider other)
{
if (other.CompareTag("Player")) hasTriggered = false;
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1625fad95a27da744bea569f094bc36f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
using UnityEngine;
using System.Collections;
public class TVRoomTrap : MonoBehaviour
{
[Header("Warp Locations")]
public Transform tvRoomSpawn; // Where they get trapped (TV Room)
public Transform mainHallSpawn; // Where they escape to (Hallway)
[Header("Room Events")]
public HauntedTV tvScript; // Reference to the TV script
public HauntedPram pramScript; // Reference to the Pram script
[Tooltip("How long they are trapped in the room")]
public float trapDuration = 3.0f;
[Header("Audio")]
public AudioSource trapAudioSource;
public AudioClip warpInSound;
public AudioClip warpOutSound;
// Call this function to start the nightmare
public void TriggerTrap(GameObject player)
{
StartCoroutine(TrapSequence(player));
}
IEnumerator TrapSequence(GameObject player)
{
CharacterController cc = player.GetComponent<CharacterController>();
// 1. DISABLE CONTROLS & PHYSICS
// We disable the CC so it doesn't fight the teleportation
if (cc != null) cc.enabled = false;
// 2. WARP TO TV ROOM
player.transform.position = tvRoomSpawn.position;
player.transform.rotation = tvRoomSpawn.rotation;
// Play Entry Sound
if(trapAudioSource && warpInSound) trapAudioSource.PlayOneShot(warpInSound);
// 3. FORCE TV SCARE
if (tvScript != null && pramScript != null)
{
pramScript.StartAllSounds();
tvScript.StartEvent();
}
// 4. WAIT (The 2 seconds of panic)
yield return new WaitForSeconds(trapDuration);
// 5. WARP TO MAIN HALL
player.transform.position = mainHallSpawn.position;
player.transform.rotation = mainHallSpawn.rotation;
// 6. FORCE TV SCARE
if (tvScript != null && pramScript != null)
{
pramScript.StopAllSounds();
tvScript.StopEvent();
}
// Play Exit Sound
if(trapAudioSource && warpOutSound) trapAudioSource.PlayOneShot(warpOutSound);
// 7. RE-ENABLE CONTROLS
if (cc != null) cc.enabled = true;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 15388158d6be9ad4795d02366d9a5db9

View File

@@ -50,7 +50,7 @@ Material:
m_Scale: {x: 1, y: 1} m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
- _MainTex: - _MainTex:
m_Texture: {fileID: 0} m_Texture: {fileID: 2800000, guid: 74bf1351d85e78747b7b513adae3b9de, type: 3}
m_Scale: {x: 1, y: 1} m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
- _MetallicGlossMap: - _MetallicGlossMap:
@@ -83,6 +83,7 @@ Material:
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
m_Ints: [] m_Ints: []
m_Floats: m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0 - _AlphaClip: 0
- _AlphaToMask: 0 - _AlphaToMask: 0
- _Blend: 0 - _Blend: 0
@@ -114,6 +115,7 @@ Material:
- _Surface: 0 - _Surface: 0
- _UVSec: 0 - _UVSec: 0
- _WorkflowMode: 1 - _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1 - _ZWrite: 1
m_Colors: m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1} - _BaseColor: {r: 1, g: 1, b: 1, a: 1}