diff --git a/.gitignore b/.gitignore index 662c08252..00057fb13 100644 --- a/.gitignore +++ b/.gitignore @@ -77,4 +77,6 @@ crashlytics-build.properties # Temporary auto-generated Android Assets /[Aa]ssets/[Ss]treamingAssets/aa.meta -/[Aa]ssets/[Ss]treamingAssets/aa/* \ No newline at end of file +/[Aa]ssets/[Ss]treamingAssets/aa/* +# Standalone build output +/Latest/ diff --git a/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.cs b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.cs new file mode 100644 index 000000000..95cbba0d4 --- /dev/null +++ b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.cs @@ -0,0 +1,91 @@ +using UnityEngine; + +[ExecuteInEditMode] +[RequireComponent(typeof(Camera))] +[AddComponentMenu("UberUnity/Compatibility/Fallback Image Effect")] +public class UberUnityFallbackImageEffect : MonoBehaviour +{ + [Header("Bloom And Flares")] + public int tweakMode; + public int screenBlendMode; + public bool hdr; + public float sepBlurSpread = 2.5f; + public int quality; + public float bloomIntensity = 0.5f; + public float bloomThreshhold = 0.4f; + public Color bloomThreshholdColor = Color.white; + public int bloomBlurIterations = 2; + public int hollywoodFlareBlurIterations = 2; + public float flareRotation; + public int lensflareMode = 1; + public float hollyStretchWidth = 2.5f; + public float lensflareIntensity; + public float lensflareThreshhold = 0.3f; + public float lensFlareSaturation = 0.75f; + public Color flareColorA = new Color(0.4f, 0.4f, 0.8f, 0.75f); + public Color flareColorB = new Color(0.4f, 0.8f, 0.8f, 0.75f); + public Color flareColorC = new Color(0.8f, 0.4f, 0.8f, 0.75f); + public Color flareColorD = new Color(0.8f, 0.4f, 0f, 0.75f); + public float blurWidth = 1f; + public Texture2D lensFlareVignetteMask; + public Shader lensFlareShader; + public Shader screenBlendShader; + public Shader blurAndFlaresShader; + public Shader brightPassFilterShader; + + [Header("Color Correction")] + public AnimationCurve redChannel = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public AnimationCurve greenChannel = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public AnimationCurve blueChannel = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public bool useDepthCorrection; + public AnimationCurve zCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public AnimationCurve depthRedChannel = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public AnimationCurve depthGreenChannel = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public AnimationCurve depthBlueChannel = AnimationCurve.Linear(0f, 0f, 1f, 1f); + public float saturation = 1f; + public bool selectiveCc; + public Color selectiveFromColor = Color.gray; + public Color selectiveToColor = Color.gray; + public int mode; + public bool updateTextures = true; + public Shader colorCorrectionCurvesShader; + public Shader simpleColorCorrectionCurvesShader; + public Shader colorCorrectionSelectiveShader; + + [Header("Sun Shafts")] + public int resolution = 1; + public Transform sunTransform; + public int radialBlurIterations = 1; + public Color sunColor = Color.white; + public float sunShaftBlurRadius = 2.5f; + public float sunShaftIntensity = 1f; + public float useSkyBoxAlpha = 0.75f; + public float maxRadius = 0.75f; + public bool useDepthTexture = true; + public Shader sunShaftsShader; + public Shader simpleClearShader; + + [Header("Fog")] + public int fogMode; + public float startDistance = 10f; + public float globalDensity = 0.01f; + public float heightScale = 1f; + public float height; + public Color globalFogColor = Color.gray; + public Shader fogShader; + + [Header("Contrast")] + public float intensity = 0.5f; + public float threshhold; + public float blurSpread = 1f; + public Shader separableBlurShader; + public Shader contrastCompositeShader; + + // These scene components came from missing post-processing scripts. + // The fallback keeps scenes loadable and simply passes the image through. + // NOTE: destination can be null — that means "render to screen" (final effect). + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + Graphics.Blit(source, destination); + } +} diff --git a/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.cs.meta b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.cs.meta new file mode 100644 index 000000000..6bdfa80a2 --- /dev/null +++ b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c9d5f92c4e6549e4876a7a8f55ad4b11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.shader b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.shader new file mode 100644 index 000000000..103e80062 --- /dev/null +++ b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.shader @@ -0,0 +1,32 @@ +Shader "Hidden/UberUnity/FallbackImageEffect" +{ + Properties + { + _MainTex ("Base (RGB)", 2D) = "white" {} + } + + SubShader + { + Cull Off + ZWrite Off + ZTest Always + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _MainTex; + + fixed4 frag(v2f_img i) : SV_Target + { + return tex2D(_MainTex, i.uv); + } + ENDCG + } + } + + Fallback Off +} diff --git a/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.shader.meta b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.shader.meta new file mode 100644 index 000000000..dd812a1b4 --- /dev/null +++ b/Assets/Compatibility/ImageEffects/UberUnityFallbackImageEffect.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f6a1a33524f74984ac8b71f5968b272a +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/MapPopulator.cs b/Assets/Editor/MapPopulator.cs new file mode 100644 index 000000000..ca6b3e1b5 --- /dev/null +++ b/Assets/Editor/MapPopulator.cs @@ -0,0 +1,260 @@ +using UnityEngine; +using System.Collections.Generic; +#if UNITY_EDITOR +using UnityEditor; +#endif + +/// +/// Editor tool: Place spawn points, pickups, and death areas from extracted original data. +/// Add this to any GameObject in the scene, select the map, and click "Populate Map" in Inspector. +/// Data is embedded from the UnityPy extraction of the original UberStrike level files. +/// +public class MapPopulator : MonoBehaviour +{ + [Header("Map Selection")] + public string mapName = "AqualabResearchHub"; + + [Header("Prefab References (assign in Inspector)")] + public GameObject spawnPointPrefab; + public GameObject healthPickupPrefab; + public GameObject armorPickupPrefab; + public GameObject ammoPickupPrefab; + public GameObject deathAreaPrefab; + + [Header("Options")] + public bool placeSpawns = true; + public bool placePickups = true; + public bool placeDeathAreas = true; + public bool clearExistingFirst = false; + + /// + /// Call this from an Editor button or context menu to populate the current scene. + /// + [ContextMenu("Populate Map")] + public void PopulateMap() + { + // The actual data would be loaded from the JSON files at runtime/editor time. + // For now, this demonstrates the placement approach. + // In practice, use: JsonUtility or Newtonsoft to load {MapName}_v2.json + Debug.Log("[MapPopulator] To use: load " + mapName + "_v2.json from UberStrike_Extracted/"); + Debug.Log("[MapPopulator] Or use the MapPopulatorEditor window for automatic placement."); + } +} + +#if UNITY_EDITOR +/// +/// Editor window that reads the extracted JSON and places objects in the scene. +/// Window > UberStrike > Map Populator +/// +public class MapPopulatorEditor : EditorWindow +{ + private string jsonFolder = @"C:\Users\Shadow\Downloads\UberStrike_Extracted"; + private string selectedMap = "AqualabResearchHub"; + private bool placeSpawns = true; + private bool placePickups = true; + private bool placeDeathAreas = true; + private Vector2 scrollPos; + + private static readonly string[] MAP_NAMES = { + "ApexTwin", "AqualabResearchHub", "Catalyst", "CuberSpace", "CuberStrike", + "FortWinter", "GhostIsland", "GideonsTower", "MonkeyIsland", "LostParadise2", + "SkyGarden", "SuperPRISMReactor", "TempleOfTheRaven", "TheHangar", "TheWarehouse" + }; + + [MenuItem("Window/UberStrike/Map Populator")] + public static void ShowWindow() + { + GetWindow("Map Populator"); + } + + void OnGUI() + { + GUILayout.Label("UberStrike Map Populator", EditorStyles.boldLabel); + GUILayout.Space(5); + + jsonFolder = EditorGUILayout.TextField("JSON Folder", jsonFolder); + + GUILayout.Space(5); + GUILayout.Label("Select Map:"); + scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(200)); + foreach (var map in MAP_NAMES) + { + if (GUILayout.Toggle(selectedMap == map, map, "Button")) + selectedMap = map; + } + EditorGUILayout.EndScrollView(); + + GUILayout.Space(10); + placeSpawns = EditorGUILayout.Toggle("Place Spawn Points", placeSpawns); + placePickups = EditorGUILayout.Toggle("Place Pickups", placePickups); + placeDeathAreas = EditorGUILayout.Toggle("Place Death Areas", placeDeathAreas); + + GUILayout.Space(10); + if (GUILayout.Button("Populate Scene", GUILayout.Height(30))) + { + PopulateScene(); + } + + if (GUILayout.Button("Clear Populated Objects", GUILayout.Height(25))) + { + ClearPopulated(); + } + } + + void PopulateScene() + { + string path = System.IO.Path.Combine(jsonFolder, selectedMap + "_v2.json"); + if (!System.IO.File.Exists(path)) + { + EditorUtility.DisplayDialog("Error", "JSON file not found: " + path, "OK"); + return; + } + + string json = System.IO.File.ReadAllText(path); + var data = JsonUtility.FromJson(json); + + // Create parent containers + GameObject root = new GameObject("[Populated_" + selectedMap + "]"); + Undo.RegisterCreatedObjectUndo(root, "Populate Map"); + + int count = 0; + + if (placeSpawns) + { + GameObject spawnRoot = new GameObject("SpawnPoints"); + spawnRoot.transform.SetParent(root.transform); + + count += PlaceSpawnGroup(data.spawns.DM, "DM", spawnRoot.transform); + count += PlaceSpawnGroup(data.spawns.TDM_Red, "TDM_Red", spawnRoot.transform); + count += PlaceSpawnGroup(data.spawns.TDM_Blue, "TDM_Blue", spawnRoot.transform); + count += PlaceSpawnGroup(data.spawns.TE_Red, "TE_Red", spawnRoot.transform); + count += PlaceSpawnGroup(data.spawns.TE_Blue, "TE_Blue", spawnRoot.transform); + } + + if (placePickups) + { + GameObject pickupRoot = new GameObject("Pickups"); + pickupRoot.transform.SetParent(root.transform); + + foreach (var pickup in data.pickups) + { + GameObject go = new GameObject(pickup.type + "_" + pickup.name); + go.transform.SetParent(pickupRoot.transform); + go.transform.position = new Vector3(pickup.position.x, pickup.position.y, pickup.position.z); + go.tag = "Powerup"; + count++; + } + } + + if (placeDeathAreas) + { + GameObject deathRoot = new GameObject("DeathAreas"); + deathRoot.transform.SetParent(root.transform); + + foreach (var da in data.death_areas) + { + GameObject go = new GameObject("DeathArea_" + da.name); + go.transform.SetParent(deathRoot.transform); + go.transform.position = new Vector3(da.position.x, da.position.y, da.position.z); + // Add a large trigger collider + BoxCollider col = go.AddComponent(); + col.isTrigger = true; + col.size = new Vector3(100, 5, 100); + count++; + } + } + + Debug.Log("[MapPopulator] Placed " + count + " objects for " + selectedMap); + } + + int PlaceSpawnGroup(List spawns, string groupName, Transform parent) + { + if (spawns == null || spawns.Count == 0) return 0; + + GameObject group = new GameObject(groupName); + group.transform.SetParent(parent); + + foreach (var sp in spawns) + { + GameObject go = new GameObject(groupName + "_" + sp.name); + go.transform.SetParent(group.transform); + go.transform.position = new Vector3(sp.position.x, sp.position.y, sp.position.z); + go.transform.rotation = new Quaternion(sp.rotation.x, sp.rotation.y, sp.rotation.z, sp.rotation.w); + } + + return spawns.Count; + } + + void ClearPopulated() + { + var populated = GameObject.FindObjectsByType(FindObjectsSortMode.None); + int removed = 0; + foreach (var t in populated) + { + if (t != null && t.name.StartsWith("[Populated_")) + { + Undo.DestroyObjectImmediate(t.gameObject); + removed++; + } + } + Debug.Log("[MapPopulator] Cleared " + removed + " populated roots"); + } + + // JSON data classes + [System.Serializable] + public class MapData + { + public string map_name; + public int level_index; + public SpawnData spawns; + public List pickups; + public List death_areas; + public List teleporters; + } + + [System.Serializable] + public class SpawnData + { + public List DM; + public List TDM_Red; + public List TDM_Blue; + public List TE_Red; + public List TE_Blue; + } + + [System.Serializable] + public class SpawnEntry + { + public string name; + public Vec3 position; + public Vec4 rotation; + } + + [System.Serializable] + public class PickupEntry + { + public string name; + public string type; + public Vec3 position; + } + + [System.Serializable] + public class PositionEntry + { + public string name; + public Vec3 position; + } + + [System.Serializable] + public class Vec3 + { + public float x, y, z; + } + + [System.Serializable] + public class Vec4 + { + public float x, y, z, w; + } +} +#endif diff --git a/Assets/Editor/MapPopulator.cs.meta b/Assets/Editor/MapPopulator.cs.meta new file mode 100644 index 000000000..8b46431be --- /dev/null +++ b/Assets/Editor/MapPopulator.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2a4773a1bff633943879076ac658a8f4 \ No newline at end of file diff --git a/Assets/Editor/SetupBootstrapScene.cs b/Assets/Editor/SetupBootstrapScene.cs new file mode 100644 index 000000000..cfe014a8e --- /dev/null +++ b/Assets/Editor/SetupBootstrapScene.cs @@ -0,0 +1,85 @@ +using UnityEngine; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine.SceneManagement; +using System.Collections.Generic; + +public class SetupBootstrapScene +{ + [MenuItem("UberStrike/Create Bootstrap Scene")] + public static void CreateBootstrapScene() + { + // Create a new empty scene + var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); + + // 1. Main Camera + var cameraGO = new GameObject("Main Camera"); + cameraGO.tag = "MainCamera"; + var cam = cameraGO.AddComponent(); + cam.clearFlags = CameraClearFlags.SolidColor; + cam.backgroundColor = Color.black; + cameraGO.AddComponent(); + + // 2. GlobalSceneLoader — the bootstrap entry point + var loaderGO = new GameObject("GlobalSceneLoader"); + loaderGO.AddComponent(); + + // 3. Save the scene + string scenePath = "Assets/Scenes/GlobalScene.unity"; + // Ensure directory exists + if (!System.IO.Directory.Exists("Assets/Scenes")) + System.IO.Directory.CreateDirectory("Assets/Scenes"); + + EditorSceneManager.SaveScene(scene, scenePath); + Debug.Log("Bootstrap scene created at: " + scenePath); + + // 4. Update Build Settings — put GlobalScene first + UpdateBuildSettings(scenePath); + + Debug.Log("Build settings updated. GlobalScene is now Scene 0."); + Debug.Log("Press Play to test authentication with HaZard's server!"); + } + + static void UpdateBuildSettings(string bootstrapScenePath) + { + var scenes = new List(); + + // Scene 0: Bootstrap (GlobalScene) + scenes.Add(new EditorBuildSettingsScene(bootstrapScenePath, true)); + + // Scene 1: MainMenu + scenes.Add(new EditorBuildSettingsScene("Assets/Menus/MainMenu.unity", true)); + + // Scene 2: Intro (optional, can skip to MainMenu) + scenes.Add(new EditorBuildSettingsScene("Assets/Menus/Intro.unity", true)); + + // Add all map scenes + string[] mapScenes = new string[] + { + "Assets/Maps/Apex_Twin/Apex_Twin.unity", + "Assets/Maps/Catalyst/Catalyst.unity", + "Assets/Maps/Cuberspace/Cuberspace.unity", + "Assets/Maps/Danger_Zone/Danger_Zone.unity", + "Assets/Maps/Fort_Winter/Fort_Winter.unity", + "Assets/Maps/Gideons_Tower_II/Gideons_Tower_II.unity", + "Assets/Maps/Lost_Paradise_II/Lost_Paradise_2.unity", + "Assets/Maps/Monkey_Island/Monkey_Island.unity", + "Assets/Maps/Research_Hub/Research_Hub.unity", + "Assets/Maps/Sky_Garden/Sky_Garden.unity", + "Assets/Maps/Space_City/Space_City.unity", + "Assets/Maps/Spaceport_Alpha/Spaceport_Alpha.unity", + "Assets/Maps/SuperPRISM_Reactor/SuperPRISM_Reactor.unity", + "Assets/Maps/Temple_Of_The_Raven/Temple_Of_The_Raven.unity", + "Assets/Maps/The_Hangar/The_Hangar.unity", + "Assets/Maps/The_Warehouse/The_Warehouse.unity", + }; + + foreach (var mapScene in mapScenes) + { + if (System.IO.File.Exists(mapScene)) + scenes.Add(new EditorBuildSettingsScene(mapScene, true)); + } + + EditorBuildSettings.scenes = scenes.ToArray(); + } +} diff --git a/Assets/Editor/SetupBootstrapScene.cs.meta b/Assets/Editor/SetupBootstrapScene.cs.meta new file mode 100644 index 000000000..3d96d0bb4 --- /dev/null +++ b/Assets/Editor/SetupBootstrapScene.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0b936e1c4be1b2e4f8afbec01f53fb4a \ No newline at end of file diff --git a/Assets/Gameplay/Network Scripts/Client.cs b/Assets/Gameplay/Network Scripts/Client.cs index a0397b8a4..bc9e1dcef 100644 --- a/Assets/Gameplay/Network Scripts/Client.cs +++ b/Assets/Gameplay/Network Scripts/Client.cs @@ -53,9 +53,14 @@ void Start() if (PlayerPrefs.HasKey("username")) localName = PlayerPrefs.GetString("username"); statsCanvas = GameObject.Find("Lobby Stats UI"); - globalResources = GameObject.Find("/Global Resources").GetComponent(); - log = GameObject.Find("/MenuSystem/Game Log UI/1_log_container").GetComponent(); - spawnPoints = GameObject.Find("/Environment/spawns").GetComponentsInChildren(); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + if (globalResourcesObject != null) globalResources = globalResourcesObject.GetComponent(); + + GameObject logObject = GameObject.Find("/MenuSystem/Game Log UI/1_log_container"); + if (logObject != null) log = logObject.GetComponent(); + + GameObject spawnPointRoot = GameObject.Find("/Environment/spawns"); + if (spawnPointRoot != null) spawnPoints = spawnPointRoot.GetComponentsInChildren(); AssignLocalPlayer(null); ConnectNotBlocking(host, port); @@ -68,49 +73,64 @@ private void CheckTheLead() foreach (object o in playerDatas.Values) { - PlayerData p = (PlayerData)o; + PlayerDataOriginal p = (PlayerDataOriginal)o; if (maxValue < p.kills) maxValue = p.kills; } bool lead = kills>maxValue; - if (hasTheLead != lead && GameObject.Find("/Player")) + GameObject playerObject = GameObject.Find("/Player"); + if (hasTheLead != lead && playerObject != null) { - GameObject.Find("/Player").SendMessage("HasTheLead", lead); - hasTheLead = lead; + playerObject.SendMessage("HasTheLead", lead); } + + hasTheLead = lead; } // Hide / Show stats void ToggleStats(bool show) { - statsCanvas.transform.GetChild(0).gameObject.SetActive(show); + if (statsCanvas != null && statsCanvas.transform.childCount > 0) + statsCanvas.transform.GetChild(0).gameObject.SetActive(show); } // Hide / show chat void ToggleChat() { + if (log == null) return; + if (!log.chatActive) { log.ToggleChat(true); - if (GameObject.Find("/Player")) + GameObject playerObject = GameObject.Find("/Player"); + if (playerObject != null) { - GameObject p = GameObject.Find("/Player"); - p.GetComponent().enabled = false; // Stop inputs - p.GetComponent().Move(0f, 0f); // Stop player - p.GetComponent().MouseLook(0f, 0f); + PlayerInput playerInput = playerObject.GetComponent(); + if (playerInput != null) playerInput.enabled = false; + + PlayerMotor playerMotor = playerObject.GetComponent(); + if (playerMotor != null) + { + playerMotor.Move(0f, 0f); + playerMotor.MouseLook(0f, 0f); + } } } else { log.ToggleChat(false); - if (GameObject.Find("/Player")) { - if(!GameObject.Find("/Player").GetComponent().gamePaused) - GameObject.Find("/Player").GetComponent().enabled = true; - //Cursor.visible = false; - //Cursor.lockState = CursorLockMode.Locked; + GameObject playerObject = GameObject.Find("/Player"); + if (playerObject != null) + { + PlayerManager playerManager = playerObject.GetComponent(); + PlayerInput playerInput = playerObject.GetComponent(); + if (playerManager != null && playerInput != null && !playerManager.gamePaused) + { + playerInput.enabled = true; + } } } @@ -121,13 +141,16 @@ public void AssignLocalPlayer(Transform newLocalPlayer) { if (newLocalPlayer != null) player = newLocalPlayer; else player = fakeLocalPlayer; - - playerCamera = player.GetChild(0); + + if (player != null && player.childCount > 0) playerCamera = player.GetChild(0); + else playerCamera = null; } // Send chat message to everyone void SendChatMessage(string message) { + if (!IsConnected()) return; + ByteBuffer buffer = new ByteBuffer(); buffer.Put((byte)2); buffer.Put(4); // put int @@ -138,6 +161,8 @@ void SendChatMessage(string message) // Send information when local player dies internal void LocalPlayerDied(int killerID, int criticalCode) { + if (!IsConnected()) return; + ByteBuffer buffer = new ByteBuffer(); buffer.Put((byte)2); buffer.Put(3); // put int @@ -149,6 +174,8 @@ internal void LocalPlayerDied(int killerID, int criticalCode) // Send damage caused to other players internal void DamageDealedTo(int receiverID, float amount, int criticalCode, Vector3 sourcePos) { + if (!IsConnected()) return; + //send to network ByteBuffer buffer = new ByteBuffer(); buffer.Put((byte)2); @@ -165,6 +192,8 @@ internal void DamageDealedTo(int receiverID, float amount, int criticalCode, Vec // send weapon swap to network void LocalPlayerChangedToWeapon(int weaponId) { + if (!IsConnected()) return; + ByteBuffer buffer = new ByteBuffer(); buffer.Put((byte)2); buffer.Put(0); // put int @@ -181,6 +210,8 @@ void LocalPlayerCrouch(bool value) void DetonateFinalWord() { + if (globalResources == null) return; + //detonate id is weapons lenght + 1 int wid = globalResources.weapons.Count+1; LocalPlayerChangedToWeapon(wid); @@ -189,6 +220,8 @@ void DetonateFinalWord() // Send primary fire to network void LocalPlayerFiredWeapon() { + if (!IsConnected()) return; + ByteBuffer buffer = new ByteBuffer(); buffer.Put((byte)2); buffer.Put(1); // put int @@ -198,13 +231,19 @@ void LocalPlayerFiredWeapon() // Spawn client to the game public void LocalPlayerSpawn() { - ByteBuffer buffer = new ByteBuffer(); - buffer.Put((byte)2); - buffer.Put(2); // put int - Send(buffer.Trim().Get()); + // Send spawn packet to server if connected (optional — offline play still works) + if (IsConnected()) + { + ByteBuffer buffer = new ByteBuffer(); + buffer.Put((byte)2); + buffer.Put(2); // put int + Send(buffer.Trim().Get()); + } - // player obj - if (GameObject.Find("/Dead Player")) Destroy(GameObject.Find("/Dead Player")); + // Always create player locally (camera is on the player prefab) + GameObject deadPlayer = GameObject.Find("/Dead Player"); + if (deadPlayer != null) Destroy(deadPlayer); + if (spawnPoints == null || spawnPoints.Length <= 1) return; int randomSpawn = UnityEngine.Random.Range(1,spawnPoints.Length);//dont include [0] GameObject pClone = Instantiate(localPlayerClone,spawnPoints[randomSpawn].position,spawnPoints[randomSpawn].rotation); pClone.name = "Player"; @@ -216,6 +255,8 @@ public void LocalPlayerSpawn() // Send equipped appereances to network void SendAppereances() { + if (!IsConnected() || globalResources == null) return; + List a = globalResources.appereances; int holo = a.IndexOf(Resources.Load(PlayerPrefs.GetString("equipped_holo"), typeof(GameObject)) as GameObject); @@ -258,7 +299,7 @@ public override void ConnectionResolve(bool success) // Update is called once per frame void Update() { - if (!isHandshaking) + if (!isHandshaking && player != null && playerCamera != null && IsConnected()) { playerPos = player.position; playerRot = player.rotation.eulerAngles; @@ -293,8 +334,15 @@ void Update() ToggleStats(Input.GetKey(KeyCode.Tab)); // Toggle chat - if (Input.GetKeyDown("return")) { if (log.chatActive) log.ChatEditEnd(); ToggleChat(); } - if (Input.GetKeyDown(KeyCode.Escape)) { if (log.chatActive) ToggleChat();} + if (Input.GetKeyDown("return")) + { + if (log != null && log.chatActive) log.ChatEditEnd(); + ToggleChat(); + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + if (log != null && log.chatActive) ToggleChat(); + } } public override void Packet(byte[] data) @@ -328,7 +376,7 @@ public override void Packet(byte[] data) ByteBuffer z = sendBuffer.Trim(); - Send(z.Get()); + if (IsConnected()) Send(z.Get()); int playerCount = buffer.GetInt(); @@ -410,7 +458,7 @@ internal void UpdatePlayerPositions(ByteBuffer buffer) if (pid != id) { - PlayerData pData = (PlayerData)playerDatas[pid]; + PlayerDataOriginal pData = (PlayerDataOriginal)playerDatas[pid]; if (pData != null) { pData.position = new Vector3(buffer.GetFloat(), buffer.GetFloat(), buffer.GetFloat()); pData.rotation = new Vector3(buffer.GetFloat(), buffer.GetFloat(), buffer.GetFloat()); @@ -452,7 +500,7 @@ internal void UpdatePlayerPositions(ByteBuffer buffer) // Network player joined internal void PlayerJoined(int playerID, string playerName) { - playerDatas.Add(playerID, new PlayerData(playerName)); + playerDatas.Add(playerID, new PlayerDataOriginal(playerName)); RunOnMainThread.Enqueue(() =>{ NetworkPlayer clone = Instantiate(playerClone); @@ -465,7 +513,7 @@ internal void PlayerJoined(int playerID, string playerName) internal void PlayerLeft(int playerID) { //Debug.Log("leaved player: " + playerID); - ((PlayerData)playerDatas[playerID]).destroy = true; + ((PlayerDataOriginal)playerDatas[playerID]).destroy = true; playerDatas.Remove(playerID); } @@ -476,8 +524,8 @@ internal void PlayerChangeWeapon(int playerID, int weaponID) if (weaponID == globalResources.weapons.Count + 1 && playerID != id) PlayerDetonatedFinalWord(playerID); else { - ((PlayerData)playerDatas[playerID]).weapon = weaponID; - ((PlayerData)playerDatas[playerID]).weaponChanged = true; + ((PlayerDataOriginal)playerDatas[playerID]).weapon = weaponID; + ((PlayerDataOriginal)playerDatas[playerID]).weaponChanged = true; } // lead RunOnMainThread.Enqueue(() => { @@ -488,7 +536,7 @@ internal void PlayerChangeWeapon(int playerID, int weaponID) // Network player fires weapon internal void PlayerFireWeapon(int playerID) { - ((PlayerData)playerDatas[playerID]).pendingPrimaryFire = true; + ((PlayerDataOriginal)playerDatas[playerID]).pendingPrimaryFire = true; } // Receive chat messages @@ -509,20 +557,20 @@ void ReceiveChatMessage(int senderID, string message) void PlayerCrouch(int playerId, byte value) { if (playerId == id) return; // self - ((PlayerData)playerDatas[playerId]).crouch = Convert.ToBoolean(value); + ((PlayerDataOriginal)playerDatas[playerId]).crouch = Convert.ToBoolean(value); } void PlayerDetonatedFinalWord(int playerId) { if (playerId == id) return; // self - ((PlayerData)playerDatas[playerId]).pendingFinalWord = true; + ((PlayerDataOriginal)playerDatas[playerId]).pendingFinalWord = true; } // Network player dies internal void PlayerDied(int killedID, int killerID, int criticalCode) { // kill network players - if (killedID != id) ((PlayerData)playerDatas[killedID]).die = true; + if (killedID != id) ((PlayerDataOriginal)playerDatas[killedID]).die = true; RunOnMainThread.Enqueue(() => { // Get critical type @@ -539,27 +587,32 @@ internal void PlayerDied(int killedID, int killerID, int criticalCode) // stats if (killedID == id) { deaths++; kills--; } - else { ((PlayerData)playerDatas[killedID]).deaths++; ((PlayerData)playerDatas[killedID]).kills--; } + else { ((PlayerDataOriginal)playerDatas[killedID]).deaths++; ((PlayerDataOriginal)playerDatas[killedID]).kills--; } } else // kills { //data - if (killedID != id) ((PlayerData)playerDatas[killedID]).lastKiller=killerID; + if (killedID != id) ((PlayerDataOriginal)playerDatas[killedID]).lastKiller=killerID; // log log.LogMessage((killerID == id) ? localName : GetLatestDatas(killerID).name, " " + criticalType + " ",(killedID == id) ? localName : GetLatestDatas(killedID).name, false, false); // stats kills if (killerID == id) kills++; - else ((PlayerData)playerDatas[killerID]).kills++; + else ((PlayerDataOriginal)playerDatas[killerID]).kills++; //stats deaths if (killedID == id) deaths++; - else ((PlayerData)playerDatas[killedID]).deaths++; + else ((PlayerDataOriginal)playerDatas[killedID]).deaths++; } // Add my kills - if (killerID == id && isAlive) GameObject.Find("/Player").GetComponent().GotKill(killedID, criticalCode); + if (killerID == id && isAlive) + { + GameObject playerObject = GameObject.Find("/Player"); + PlayerManager playerManager = playerObject != null ? playerObject.GetComponent() : null; + if (playerManager != null) playerManager.GotKill(killedID, criticalCode); + } }); } @@ -571,7 +624,9 @@ internal void DamageReceived(int dealerID, float amount, int criticalCode, Vecto { //Debug.Log("client "+dealerID+" dealed you "+amount+" damage"); RunOnMainThread.Enqueue(() => { - GameObject.Find("/Player").GetComponent().TakeDamage(amount, sourcePos, criticalCode, dealerID); + GameObject playerObject = GameObject.Find("/Player"); + PlayerManager playerManager = playerObject != null ? playerObject.GetComponent() : null; + if (playerManager != null) playerManager.TakeDamage(amount, sourcePos, criticalCode, dealerID); }); } } @@ -584,7 +639,7 @@ internal void ReceiveAppereances(int playerID, int holo, int head, int face, int //print(playerID+", "+ holo + ", " + head + ", " + face + ", " + gloves + ", " + upperbody + ", " + lowerbody + ", " + boots); // save to playerdata - PlayerData pd = ((PlayerData) playerDatas[playerID]); + PlayerDataOriginal pd = ((PlayerDataOriginal) playerDatas[playerID]); pd.holo = holo; pd.head = head; pd.face = face; @@ -599,8 +654,8 @@ internal void ReceiveAppereances(int playerID, int holo, int head, int face, int // init player stats if join during the game void InitPlayerStats(int pID, int kills, int deaths) { - ((PlayerData)playerDatas[pID]).kills = kills; - ((PlayerData)playerDatas[pID]).deaths = deaths; + ((PlayerDataOriginal)playerDatas[pID]).kills = kills; + ((PlayerDataOriginal)playerDatas[pID]).deaths = deaths; } // Close connection and disable this client gameObject @@ -612,16 +667,16 @@ internal void Quit() } // This is called every frame by every NetworkPlayer - public PlayerData GetLatestDatas(int networkId) + public PlayerDataOriginal GetLatestDatas(int networkId) { foreach (object i in playerDatas.Keys) { if (((int)i) == networkId) { - return (PlayerData)playerDatas[i]; + return (PlayerDataOriginal)playerDatas[i]; } } return null; } -} \ No newline at end of file +} diff --git a/Assets/Gameplay/Network Scripts/LobbyLog.cs b/Assets/Gameplay/Network Scripts/LobbyLog.cs index dc5241782..71d468f03 100644 --- a/Assets/Gameplay/Network Scripts/LobbyLog.cs +++ b/Assets/Gameplay/Network Scripts/LobbyLog.cs @@ -86,7 +86,11 @@ IEnumerator HideChat() public void ChatEditEnd() { - if(field.text.Length>0&& field.text.Length < 101) GameObject.Find("/Network Client").SendMessage("SendChatMessage", field.text); + if (field.text.Length > 0 && field.text.Length < 101) + { + GameObject networkClient = GameObject.Find("/Network Client"); + if (networkClient != null) networkClient.SendMessage("SendChatMessage", field.text); + } field.text = ""; scroll.value = 0f; } diff --git a/Assets/Gameplay/Network Scripts/LobbyStats.cs b/Assets/Gameplay/Network Scripts/LobbyStats.cs index 54d9273a1..0eeb62c6e 100644 --- a/Assets/Gameplay/Network Scripts/LobbyStats.cs +++ b/Assets/Gameplay/Network Scripts/LobbyStats.cs @@ -25,13 +25,15 @@ public class LobbyStats : MonoBehaviour void Start() { client = transform.parent.parent.gameObject.GetComponent(); + if (client == null) return; localName = client.localName; // default servername if (client.host == "127.0.0.1") serverNameText.text = "[FI] Debug"; else serverNameText.text = client.host; - globalResources = GameObject.Find("/Global Resources").GetComponent(); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + if (globalResourcesObject != null) globalResources = globalResourcesObject.GetComponent(); } void OnEnable() @@ -44,6 +46,8 @@ void OnEnable() void Update() { + if (client == null) return; + //get new datas playerDatas = client.playerDatas; @@ -63,7 +67,7 @@ void Update() t.GetChild(4).gameObject.GetComponent().text = client.deaths + ""; //deaths t.GetChild(5).gameObject.GetComponent().text = KDR(client.kills / client.deaths); //kdr if(!client.isAlive) t.GetChild(6).gameObject.GetComponent().color = Color.white; - else + else if (globalResources != null && client.localWeaponId >= 0 && client.localWeaponId < globalResources.weapons.Count) { t.GetChild(1).gameObject.SetActive(true); t.GetChild(2).gameObject.SetActive(true); @@ -76,7 +80,7 @@ void Update() //others foreach (object o in playerDatas.Values) { - PlayerData p = (PlayerData)o; + PlayerDataOriginal p = (PlayerDataOriginal)o; GameObject statItemClone = Instantiate(statListItemPrefab); Transform t2 = statItemClone.transform; @@ -86,7 +90,7 @@ void Update() t2.GetChild(4).gameObject.GetComponent().text = p.deaths+""; //deaths t2.GetChild(5).gameObject.GetComponent().text = KDR(p.kills / p.deaths); //kdr if (!p.isAlive) t2.GetChild(6).gameObject.GetComponent().color = Color.white; - else + else if (globalResources != null && p.weapon >= 0 && p.weapon < globalResources.weapons.Count) { t2.GetChild(1).gameObject.SetActive(true); t2.GetChild(2).gameObject.SetActive(true); diff --git a/Assets/Gameplay/Network Scripts/NetworkAvatar.cs b/Assets/Gameplay/Network Scripts/NetworkAvatar.cs index a37d763a6..c5d5bfcc5 100644 --- a/Assets/Gameplay/Network Scripts/NetworkAvatar.cs +++ b/Assets/Gameplay/Network Scripts/NetworkAvatar.cs @@ -30,7 +30,10 @@ public class NetworkAvatar : MonoBehaviour void Start() { player = GetComponent(); - globalResources = GameObject.Find("/Global Resources").GetComponent(); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + if (globalResourcesObject != null) globalResources = globalResourcesObject.GetComponent(); + if (globalResources == null) return; + appereances = globalResources.appereancesPrefab; lutzDefaultHat = globalResources.lutzDefaultHatPrefab; } diff --git a/Assets/Gameplay/Network Scripts/NetworkPlayer.cs b/Assets/Gameplay/Network Scripts/NetworkPlayer.cs index 743043199..cc0df2bd7 100644 --- a/Assets/Gameplay/Network Scripts/NetworkPlayer.cs +++ b/Assets/Gameplay/Network Scripts/NetworkPlayer.cs @@ -15,7 +15,7 @@ public class NetworkPlayer : MonoBehaviour private GlobalResources globalResources; private GameObject enemyRagdoll; - private PlayerData latestPlayerData; + private PlayerDataOriginal latestPlayerData; public Transform groundRayOrigin; public Transform raycastPivot; @@ -38,19 +38,27 @@ void Start() nameTag.GetChild(0).gameObject.GetComponent().text = networkName; // get client - client = GameObject.Find("/Network Client").GetComponent(); + GameObject networkClientObject = GameObject.Find("/Network Client"); + if (networkClientObject != null) client = networkClientObject.GetComponent(); // get global resources - globalResources = GameObject.Find("/Global Resources").GetComponent(); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + if (globalResourcesObject != null) globalResources = globalResourcesObject.GetComponent(); // log message - client.log.LogMessage(networkName, " joined the game", "", false, false); + if (client != null && client.log != null) + { + client.log.LogMessage(networkName, " joined the game", "", false, false); + } // set obj link - ((PlayerData)client.playerDatas[networkId]).playerObject = gameObject; + if (client != null && client.playerDatas[networkId] != null) + { + ((PlayerDataOriginal)client.playerDatas[networkId]).playerObject = gameObject; + } //ragdoll - enemyRagdoll = globalResources.enemyRagdoll; + if (globalResources != null) enemyRagdoll = globalResources.enemyRagdoll; //audio playerAudio = GetComponent(); @@ -58,9 +66,11 @@ void Start() void Update() { + if (client == null) return; + // Disconnect player if (latestPlayerData!=null&&latestPlayerData.destroy){ - client.log.LogMessage(networkName, " left the game", "", false, false); + if (client.log != null) client.log.LogMessage(networkName, " left the game", "", false, false); Destroy(gameObject); return;} @@ -71,6 +81,7 @@ void Update() // Get latest data /////////////////////////////////// latestPlayerData = client.GetLatestDatas(networkId);// ////////////////////////////////////////////////////// + if (latestPlayerData == null) return; // appereances & weapons if (latestPlayerData.appereancesChanged) LoadAppereances(); @@ -81,8 +92,8 @@ void Update() if (latestPlayerData.pendingFinalWord) FinalWord(); // death - if (latestPlayerData.position.y!=-666) ((PlayerData)client.playerDatas[networkId]).isAlive = true; - else ((PlayerData)client.playerDatas[networkId]).isAlive = false; + if (latestPlayerData.position.y!=-666) ((PlayerDataOriginal)client.playerDatas[networkId]).isAlive = true; + else ((PlayerDataOriginal)client.playerDatas[networkId]).isAlive = false; // position transform.position = Vector3.Lerp(transform.position, latestPlayerData.position, 0.3f); @@ -97,7 +108,8 @@ void Update() raycastPivot.localRotation = Quaternion.Euler(latestPlayerData.subRotation); // nameTag - nameTag.LookAt(2 * nameTag.position - client.playerCamera.position); + if (client.playerCamera != null) + nameTag.LookAt(2 * nameTag.position - client.playerCamera.position); nameTag.gameObject.SetActive(client.isAlive); // ground @@ -115,10 +127,10 @@ public void TakeDamage(float amount, int criticalDmgCode, Vector3 position, stri void Die() { - ((PlayerData)client.playerDatas[networkId]).die = false; + ((PlayerDataOriginal)client.playerDatas[networkId]).die = false; // drop weapon - GameObject wPrefab = globalResources.weapons[((PlayerData)client.playerDatas[networkId]).weapon]; + GameObject wPrefab = globalResources.weapons[((PlayerDataOriginal)client.playerDatas[networkId]).weapon]; PickupWeapon w = Instantiate(drop, latestPlayerData.position+(Vector3.up*2), Quaternion.identity); w.weaponPrefab = wPrefab; Destroy(w.gameObject, 8f); @@ -137,10 +149,10 @@ void Die() Destroy(cc,8f); //force - if (((PlayerData)client.playerDatas[networkId]).lastKiller > 0) + if (((PlayerDataOriginal)client.playerDatas[networkId]).lastKiller > 0) { Vector3 pos; - if (client.GetLatestDatas(((PlayerData)client.playerDatas[networkId]).lastKiller) != null) pos = client.GetLatestDatas(((PlayerData)client.playerDatas[networkId]).lastKiller).position; + if (client.GetLatestDatas(((PlayerDataOriginal)client.playerDatas[networkId]).lastKiller) != null) pos = client.GetLatestDatas(((PlayerDataOriginal)client.playerDatas[networkId]).lastKiller).position; else if (GameObject.Find("/Player")) pos = GameObject.Find("/Player").transform.position; else pos = transform.position; @@ -152,7 +164,7 @@ void Die() void LoadAppereances() { - ((PlayerData)client.playerDatas[networkId]).appereancesChanged = false; + ((PlayerDataOriginal)client.playerDatas[networkId]).appereancesChanged = false; // get appereances GameObject holo = (latestPlayerData.holo<=0) ? null : globalResources.appereances[latestPlayerData.holo]; @@ -181,14 +193,14 @@ void LoadAppereances() void EquipWeapon() { - ((PlayerData)client.playerDatas[networkId]).weaponChanged = false; + ((PlayerDataOriginal)client.playerDatas[networkId]).weaponChanged = false; // clear all for (int i = 0; i < weaponHand.childCount; i++) Destroy(weaponHand.GetChild(i).gameObject); // add current - GameObject newWeapon = Instantiate(FixedAudio(globalResources.weapons[((PlayerData)client.playerDatas[networkId]).weapon]), weaponHand.position,weaponHand.rotation); + GameObject newWeapon = Instantiate(FixedAudio(globalResources.weapons[((PlayerDataOriginal)client.playerDatas[networkId]).weapon]), weaponHand.position,weaponHand.rotation); Destroy(newWeapon.GetComponent()); newWeapon.transform.parent = weaponHand; newWeapon.transform.localRotation = Quaternion.Euler(0f, 90f, 90f); @@ -201,7 +213,7 @@ void FireWeapon() //get hit point RaycastHit t = GetFireHitPoint(); - ((PlayerData)client.playerDatas[networkId]).pendingPrimaryFire = false; + ((PlayerDataOriginal)client.playerDatas[networkId]).pendingPrimaryFire = false; // sound if(weaponHand.childCount>0) @@ -270,7 +282,7 @@ float getDistanceToGround() //detonate final word/kiss grenades internal void FinalWord() { - ((PlayerData)client.playerDatas[networkId]).pendingFinalWord = false; + ((PlayerDataOriginal)client.playerDatas[networkId]).pendingFinalWord = false; if (weaponHand.childCount > 0) if (weaponHand.GetChild(0).gameObject.GetComponent()) if (weaponHand.GetChild(0).gameObject.name.ToLower().Contains("final")) diff --git a/Assets/Gameplay/Network Scripts/TcpEngine.cs b/Assets/Gameplay/Network Scripts/TcpEngine.cs index c936b7b02..654a9c101 100644 --- a/Assets/Gameplay/Network Scripts/TcpEngine.cs +++ b/Assets/Gameplay/Network Scripts/TcpEngine.cs @@ -12,6 +12,11 @@ public class TcpEngine : MonoBehaviour private string tcpHost; private int tcpPort; + protected bool IsConnected() + { + return client != null && client.Connected; + } + internal bool ConnectBlocking(string host, int port) { try @@ -39,17 +44,17 @@ internal void ConnectNotBlocking(string host, int port) } private void connect() { - /*try - {*/ - client = new TcpClient(); - client.Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(tcpHost), tcpPort)); - ConnectionResolve(true); - /* } - - catch //(Exception ex) + try + { + client = new TcpClient(); + client.Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(tcpHost), tcpPort)); + ConnectionResolve(true); + } + catch (Exception ex) { + Debug.LogWarning("TCP connect failed: " + ex.Message); ConnectionResolve(false); - }*/ + } } @@ -80,8 +85,16 @@ internal void Disconnect() { if (client != null) { - client.GetStream().Close(); - client.Close(); + try + { + if (client.Connected) + client.GetStream().Close(); + client.Close(); + } + catch (Exception ex) + { + Debug.LogWarning("TCP disconnect: " + ex.Message); + } print("Disconnected"); } } @@ -103,28 +116,22 @@ public virtual void ConnectionResolve(bool success) internal void Send(byte[] data) { - - if (client == null) + if (!IsConnected()) { return; } - else + try { - try - { - NetworkStream ns = client.GetStream(); - - if (ns.CanWrite) - { - ns.Write(data, 0, data.Length); - } - - } - catch (SocketException se) + NetworkStream ns = client.GetStream(); + if (ns.CanWrite) { - Debug.LogError("SE:" + se); + ns.Write(data, 0, data.Length); } } + catch (Exception ex) + { + Debug.LogWarning("TCP send failed: " + ex.Message); + } } -} \ No newline at end of file +} diff --git a/Assets/Gameplay/Player Scrips/BodyBuilder.cs b/Assets/Gameplay/Player Scrips/BodyBuilder.cs index 20226a24a..c0de36b3c 100644 --- a/Assets/Gameplay/Player Scrips/BodyBuilder.cs +++ b/Assets/Gameplay/Player Scrips/BodyBuilder.cs @@ -22,7 +22,10 @@ public class BodyBuilder : MonoBehaviour public void BuildAppereances(GameObject holo, GameObject head, GameObject face, GameObject upperBody, GameObject gloves, GameObject lowerBody, GameObject boots) { - globalResources = GameObject.Find("/Global Resources").GetComponent(); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + if (globalResourcesObject != null) globalResources = globalResourcesObject.GetComponent(); + if (globalResources == null) return; + appereances = globalResources.appereancesPrefab; lutzDefaultHat = globalResources.lutzDefaultHatPrefab; diff --git a/Assets/Gameplay/Player Scrips/DeadPlayer.cs b/Assets/Gameplay/Player Scrips/DeadPlayer.cs index f18e8c994..02be8f699 100644 --- a/Assets/Gameplay/Player Scrips/DeadPlayer.cs +++ b/Assets/Gameplay/Player Scrips/DeadPlayer.cs @@ -40,7 +40,11 @@ void SetAppereances() void SetWeapon(int weaponId) { - GameObject wPrefab = GameObject.Find("/Global Resources").GetComponent().weapons[weaponId]; + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + GlobalResources globalResources = globalResourcesObject != null ? globalResourcesObject.GetComponent() : null; + if (globalResources == null || weaponId < 0 || weaponId >= globalResources.weapons.Count) return; + + GameObject wPrefab = globalResources.weapons[weaponId]; GameObject w = Instantiate(wPrefab, weapon.position, weapon.rotation); Destroy(w.GetComponent()); Destroy(w.GetComponent()); diff --git a/Assets/Gameplay/Player Scrips/PlayerAudio.cs b/Assets/Gameplay/Player Scrips/PlayerAudio.cs index 5075c2f1d..af0de18c4 100644 --- a/Assets/Gameplay/Player Scrips/PlayerAudio.cs +++ b/Assets/Gameplay/Player Scrips/PlayerAudio.cs @@ -49,7 +49,10 @@ public class PlayerAudio : MonoBehaviour void Start() { audioSource = GetComponent(); - audioSource.PlayOneShot(narrator[0], volume); + if (narrator != null && narrator.Length > 0 && narrator[0] != null) + { + audioSource.PlayOneShot(narrator[0], volume); + } // build footStep map foreach(AudioClip a in footSteps) @@ -58,13 +61,18 @@ void Start() } // Custom narrator - if (GameObject.Find("/Custom Narrator")) Destroy(GameObject.Find("/Custom Narrator")); + GameObject customNarrator = GameObject.Find("/Custom Narrator"); + if (customNarrator != null) Destroy(customNarrator); if (PlayerPrefs.HasKey("equipped_head")) { + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + GlobalResources globalResources = globalResourcesObject != null ? globalResourcesObject.GetComponent() : null; + if (globalResources == null) return; + //laitela if (PlayerPrefs.GetString("equipped_head") == "Paperbag laitela") { - CustomNarrator c=Instantiate(GameObject.Find("/Global Resources").GetComponent().laitelaNarrator); + CustomNarrator c = Instantiate(globalResources.laitelaNarrator); c.gameObject.name = "Custom Narrator"; } @@ -72,7 +80,7 @@ void Start() //taalasmaa if (PlayerPrefs.GetString("equipped_head") == "Paperbag taalasmaa") { - CustomNarrator c = Instantiate(GameObject.Find("/Global Resources").GetComponent().taalasmaaNarrator); + CustomNarrator c = Instantiate(globalResources.taalasmaaNarrator); c.gameObject.name = "Custom Narrator"; } @@ -82,7 +90,7 @@ void Start() // Call this to play sounds elsewhere public void Play(AudioClip clip) { - if(audioSource.enabled) + if(audioSource != null && audioSource.enabled && clip != null) audioSource.PlayOneShot(clip, volume); } @@ -110,37 +118,45 @@ public void PlayWalk(string groundMaterial) string foundType = "rock"; // default is rock // find type - foreach (string s in gTypes) if (groundMaterial.Contains(s)) { foundType = s; break; } + if (!string.IsNullOrEmpty(groundMaterial)) + foreach (string s in gTypes) if (groundMaterial.Contains(s)) { foundType = s; break; } // get clip count int i = 1; while (steps.Contains(foundType + i)) i++; i--; - int randomIndex = Random.Range(1, i); - if (steps.Contains(foundType + randomIndex)) Play((AudioClip)steps[foundType + randomIndex]); + if (i <= 0) return; + + int randomIndex = Random.Range(1, i + 1); + AudioClip clip = steps[foundType + randomIndex] as AudioClip; + if (clip != null) Play(clip); else Debug.LogWarning("footstep sound index out of bounds"); } // footsteps landing public void PlayLanding(string groundMaterial) { - if (audioSource.isPlaying) return; + if (audioSource == null || audioSource.isPlaying) return; if (canWalk != null) StopCoroutine(canWalk); canWalk = StartCoroutine(CanWalk()); string foundType = "rock"; // default is rock // find type - foreach (string s in gTypes) if (groundMaterial.Contains(s)) { foundType = s; break; } + if (!string.IsNullOrEmpty(groundMaterial)) + foreach (string s in gTypes) if (groundMaterial.Contains(s)) { foundType = s; break; } // get clip count int i = 1; while(steps.Contains(foundType + i)) i++; i--; - int randomIndex = Random.Range(1,i); - if (steps.Contains(foundType+randomIndex)) Play((AudioClip)steps[foundType + randomIndex]); + if (i <= 0) return; + + int randomIndex = Random.Range(1, i + 1); + AudioClip clip = steps[foundType + randomIndex] as AudioClip; + if (clip != null) Play(clip); else Debug.LogWarning("footstep sound index out of bounds"); } diff --git a/Assets/Gameplay/Player Scrips/PlayerHand.cs b/Assets/Gameplay/Player Scrips/PlayerHand.cs index 1290450cd..0dce63971 100644 --- a/Assets/Gameplay/Player Scrips/PlayerHand.cs +++ b/Assets/Gameplay/Player Scrips/PlayerHand.cs @@ -26,11 +26,16 @@ public class PlayerHand : MonoBehaviour // Init void Start() { - try { - networkClient = GameObject.Find("/Network Client"); - globalResources = GameObject.Find("/Global Resources").GetComponent(); + networkClient = GameObject.Find("/Network Client"); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + if (globalResourcesObject != null) + { + globalResources = globalResourcesObject.GetComponent(); + } + if (networkClient == null || globalResources == null) + { + Debug.LogWarning("PlayerHand did not find one or more network objects."); } - catch{Debug.LogWarning("Playerhand did not find network objects");} // Get weapons diff --git a/Assets/Gameplay/Player Scrips/PlayerInput.cs b/Assets/Gameplay/Player Scrips/PlayerInput.cs index 91703cee3..ea44f9453 100644 --- a/Assets/Gameplay/Player Scrips/PlayerInput.cs +++ b/Assets/Gameplay/Player Scrips/PlayerInput.cs @@ -21,9 +21,9 @@ private void Start() // This method reads player input every frame private void Update() { - // Get WASD - float x = Input.GetAxis("Vertical"); - float z = Input.GetAxis("Horizontal"); + // Get WASD — use GetAxisRaw for instant response (no Unity smoothing) + float x = Input.GetAxisRaw("Vertical"); + float z = Input.GetAxisRaw("Horizontal"); playerMotor.Move(x, z); // Get mouse @@ -39,8 +39,11 @@ private void Update() if (Input.GetButtonDown("Fire1")) { playerMotor.Shoot(true); } if (Input.GetButtonUp("Fire1")) { playerMotor.Shoot(false); } - // Get spacebar - if (Input.GetButtonDown("Jump")) { playerMotor.Jump(); } + // Track jump key state continuously — original UberStrike checks held state + // every physics frame, not just button-down events. This enables bunny hopping: + // press space mid-air → lands → instant jump on next physics frame. + playerMotor.jumpHeld = Input.GetButton("Jump"); + if (Input.GetButtonUp("Jump")) { playerMotor.JumpReleased(); } // Get mouse scroll wheel float scroll = Input.GetAxis("Mouse ScrollWheel"); @@ -52,11 +55,12 @@ private void Update() // Get E key if (Input.GetKeyDown(KeyCode.E)) { playerMotor.UseItem(1); } - // Weapon switch shorcuts - if (Input.GetKeyDown(KeyCode.Alpha1)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(1); } - if (Input.GetKeyDown(KeyCode.Alpha2)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(4); } - if (Input.GetKeyDown(KeyCode.Alpha3)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(3); } - if (Input.GetKeyDown(KeyCode.Alpha4)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(2); } + // Weapon switch: 1=Melee, 2=Primary, 3=Secondary, 4=Tertiary + // Hand hierarchy: child 0=Primary, child 1=Melee, child 2=Secondary, child 3=Tertiary + if (Input.GetKeyDown(KeyCode.Alpha1)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(2); } // Melee = index 1 + if (Input.GetKeyDown(KeyCode.Alpha2)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(1); } // Primary = index 0 + if (Input.GetKeyDown(KeyCode.Alpha3)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(3); } // Secondary = index 2 + if (Input.GetKeyDown(KeyCode.Alpha4)) { playerMotor.Aim(true); playerMotor.Aim(false); playerMotor.SetWeapon(4); } // Tertiary = index 3 // Pause // This Input is hardcoded. We should make input axis for this later @@ -67,10 +71,9 @@ private void Update() if (Input.GetKeyDown(KeyCode.P)) { playerUI.ToggleHUD(); } - // Get ctrl key for crouch - // This Input is hardcoded. We should make input axis for this later - if (Input.GetKeyDown(KeyCode.LeftControl)) { playerMotor.Crouch(true); } - if (Input.GetKeyUp(KeyCode.LeftControl)) { playerMotor.Crouch(false); } + // Get shift key for crouch + if (Input.GetKeyDown(KeyCode.LeftShift)) { playerMotor.Crouch(true); } + if (Input.GetKeyUp(KeyCode.LeftShift)) { playerMotor.Crouch(false); } } diff --git a/Assets/Gameplay/Player Scrips/PlayerManager.cs b/Assets/Gameplay/Player Scrips/PlayerManager.cs index f7c668a22..76d928113 100644 --- a/Assets/Gameplay/Player Scrips/PlayerManager.cs +++ b/Assets/Gameplay/Player Scrips/PlayerManager.cs @@ -35,22 +35,39 @@ public class PlayerManager : MonoBehaviour void Start() { inTheMenus = SceneManager.GetActiveScene().name == "MainMenu"; - if(!inTheMenus)respawnUI = GameObject.Find("/MenuSystem/Respawn UI").transform.GetChild(0).gameObject; + if (!inTheMenus) + { + var respawnUiRoot = GameObject.Find("/MenuSystem/Respawn UI"); + if (respawnUiRoot != null && respawnUiRoot.transform.childCount > 0) + { + respawnUI = respawnUiRoot.transform.GetChild(0).gameObject; + } + } playerUI = GetComponent(); playerAudio = GetComponent(); - if ((Resources.Load(PlayerPrefs.GetString("equipped_primary_quickitem"), typeof(GameObject)) as GameObject) != null) + var primaryPrefab = Resources.Load(PlayerPrefs.GetString("equipped_primary_quickitem"), typeof(GameObject)) as GameObject; + if (primaryPrefab != null) { - float ff = (Resources.Load(PlayerPrefs.GetString("equipped_primary_quickitem"), typeof(GameObject)) as GameObject).GetComponent().stockCount; - playerUI.UpdateItemCount(0, ff, false); - primaryItems = ff; + var primaryQuickItem = primaryPrefab.GetComponent(); + if (primaryQuickItem != null) + { + float ff = primaryQuickItem.stockCount; + playerUI.UpdateItemCount(0, ff, false); + primaryItems = ff; + } } - - if ((Resources.Load(PlayerPrefs.GetString("equipped_secondary_quickitem"), typeof(GameObject)) as GameObject) != null) + + var secondaryPrefab = Resources.Load(PlayerPrefs.GetString("equipped_secondary_quickitem"), typeof(GameObject)) as GameObject; + if (secondaryPrefab != null) { - float f = (Resources.Load(PlayerPrefs.GetString("equipped_secondary_quickitem"), typeof(GameObject)) as GameObject).GetComponent().stockCount; - playerUI.UpdateItemCount(1, f, false); - secondaryItems = f; + var secondaryQuickItem = secondaryPrefab.GetComponent(); + if (secondaryQuickItem != null) + { + float f = secondaryQuickItem.stockCount; + playerUI.UpdateItemCount(1, f, false); + secondaryItems = f; + } } playerHand = playerUI.playerHand; @@ -58,12 +75,19 @@ void Start() SetDefaultValues(); // Skybox - if(GameObject.Find("/Environment").GetComponent().skybox!=null)RenderSettings.skybox = GameObject.Find("/Environment").GetComponent().skybox; + var envObj = GameObject.Find("/Environment"); + var environment = envObj != null ? envObj.GetComponent() : null; + if (environment != null && environment.skybox != null) + RenderSettings.skybox = environment.skybox; - if (GameObject.Find("/Network Client")) + var networkClientObject = GameObject.Find("/Network Client"); + if (networkClientObject != null) { - client = GameObject.Find("/Network Client").GetComponent(); - client.AssignLocalPlayer(transform); + client = networkClientObject.GetComponent(); + if (client != null) + { + client.AssignLocalPlayer(transform); + } } } @@ -80,7 +104,10 @@ void SetDefaultValues() public void GotKill(int killedID, int criticalCode) { - playerUI.ShowKillName("You killed "+ client.GetLatestDatas(killedID).name); + if (playerUI == null || playerAudio == null || client == null) return; + + PlayerDataOriginal killedPlayer = client.GetLatestDatas(killedID); + playerUI.ShowKillName("You killed " + ((killedPlayer != null) ? killedPlayer.name : "Unknown")); killCombo++; if (killCombo > 6) killCombo = 6; @@ -115,6 +142,12 @@ private IEnumerator ClearCombos() internal void Die(int dealerPlayerID, int criticalCode) { if (inTheMenus) { PauseGame(); return; } + if (client == null) + { + Debug.LogWarning("PlayerManager.Die skipped network death handling because no Client was found."); + PauseGame(); + return; + } if (!client.isAlive) return; client.isAlive = false; deaths++; @@ -128,11 +161,12 @@ internal void Die(int dealerPlayerID, int criticalCode) //cause messages client.LocalPlayerDied(dealerPlayerID, criticalCode); // to others string causeMsg = ""; // self + PlayerDataOriginal dealerData = dealerPlayerID >= 0 ? client.GetLatestDatas(dealerPlayerID) : null; if (dealerPlayerID < 0) causeMsg = "Congratulations, you killed yourself."; - else if (criticalCode == 0) causeMsg = "Killed by " + client.GetLatestDatas(dealerPlayerID).name; - else if (criticalCode == 1) causeMsg = "Headshot from " + client.GetLatestDatas(dealerPlayerID).name; - else if (criticalCode == 2) causeMsg = "Nutshot from " + client.GetLatestDatas(dealerPlayerID).name; - else if (criticalCode == 3) causeMsg = "Smackdown from " + client.GetLatestDatas(dealerPlayerID).name; + else if (criticalCode == 0) causeMsg = "Killed by " + ((dealerData != null) ? dealerData.name : "Unknown"); + else if (criticalCode == 1) causeMsg = "Headshot from " + ((dealerData != null) ? dealerData.name : "Unknown"); + else if (criticalCode == 2) causeMsg = "Nutshot from " + ((dealerData != null) ? dealerData.name : "Unknown"); + else if (criticalCode == 3) causeMsg = "Smackdown from " + ((dealerData != null) ? dealerData.name : "Unknown"); playerUI.ShowKillName(""); @@ -142,16 +176,35 @@ internal void Die(int dealerPlayerID, int criticalCode) CustomNarrator("Die"); // hide pause - GameObject.Find("/MenuSystem/Pause UI").transform.GetChild(0).gameObject.SetActive(false); + GameObject pauseUi = GameObject.Find("/MenuSystem/Pause UI"); + if (pauseUi != null && pauseUi.transform.childCount > 0) + { + pauseUi.transform.GetChild(0).gameObject.SetActive(false); + } client.AssignLocalPlayer(null); - respawnUI.SetActive(true); - respawnUI.SendMessage("SetDeathCause", causeMsg); + if (respawnUI != null) + { + respawnUI.SetActive(true); + respawnUI.SendMessage("SetDeathCause", causeMsg); + } GameObject death = Instantiate(deathViewPrefab, transform.position, transform.rotation); death.SendMessage("SetWeapon", client.localWeaponId); - if(dealerPlayerID>0) death.SendMessage("SetKiller", client.GetLatestDatas(dealerPlayerID).playerObject); - death.SendMessage("StartVelocity",GetComponent().linearVelocity); + if (dealerPlayerID > 0) + { + PlayerDataOriginal killerData = client.GetLatestDatas(dealerPlayerID); + if (killerData != null && killerData.playerObject != null) + { + death.SendMessage("SetKiller", killerData.playerObject); + } + } + + Rigidbody rb = GetComponent(); + if (rb != null) + { + death.SendMessage("StartVelocity", rb.linearVelocity); + } Destroy(gameObject); @@ -330,9 +383,15 @@ public float GetCollectedAmmoFor(string weaponType) internal void PauseGame() { - GetComponent().enabled = false; // Stop inputs - GetComponent().Move(0f, 0f); // Stop player - GetComponent().MouseLook(0f, 0f); + PlayerInput playerInput = GetComponent(); + if (playerInput != null) playerInput.enabled = false; // Stop inputs + + PlayerMotor playerMotor = GetComponent(); + if (playerMotor != null) + { + playerMotor.Move(0f, 0f); // Stop player + playerMotor.MouseLook(0f, 0f); + } Cursor.lockState = CursorLockMode.None; Cursor.visible = true; @@ -344,14 +403,22 @@ internal void PauseGame() foreach(GameObject g in rootObjs) { if (g.name == "Player Avatar" || g.name == "MenuSystem") g.SetActive(true); - if(g.name == "Environment") g.GetComponent().volume = 1f; + if (g.name == "Environment") + { + AudioSource environmentAudio = g.GetComponent(); + if (environmentAudio != null) environmentAudio.volume = 1f; + } } Destroy(gameObject); //shop tab - GameObject.Find("/MenuSystem/Top Bar UI").SendMessage("NavigationBar", 3); - GameObject.Find("/MenuSystem/Top Bar UI").SendMessage("NavigationBar", 2); + GameObject topBarUi = GameObject.Find("/MenuSystem/Top Bar UI"); + if (topBarUi != null) + { + topBarUi.SendMessage("NavigationBar", 3); + topBarUi.SendMessage("NavigationBar", 2); + } } // Other maps else @@ -359,13 +426,21 @@ internal void PauseGame() playerUI.TogglePauseScreen(true); gamePaused = true; - GameObject g = GameObject.Find("/MenuSystem").transform.GetChild(0).gameObject; - g.SetActive(true); + GameObject menuSystem = GameObject.Find("/MenuSystem"); + if (menuSystem != null && menuSystem.transform.childCount > 0) + { + GameObject g = menuSystem.transform.GetChild(0).gameObject; + g.SetActive(true); + } } - if (GameObject.Find("/Player")) - GameObject.Find("/Player").GetComponent().movement = Vector3.zero; + GameObject player = GameObject.Find("/Player"); + if (player != null) + { + PlayerMotor localPlayerMotor = player.GetComponent(); + if (localPlayerMotor != null) localPlayerMotor.movement = Vector3.zero; + } } // call after game is paused @@ -375,8 +450,11 @@ public void ContinueGame() Cursor.visible = false; playerUI.TogglePauseScreen(false); gamePaused = false; - GetComponent().enabled = true; - GetComponent().UpdateOptions(); + PlayerInput playerInput = GetComponent(); + if (playerInput != null) playerInput.enabled = true; + + PlayerMotor playerMotor = GetComponent(); + if (playerMotor != null) playerMotor.UpdateOptions(); } // Pass weapon pickup to hand diff --git a/Assets/Gameplay/Player Scrips/PlayerMotor.cs b/Assets/Gameplay/Player Scrips/PlayerMotor.cs index 4f515742e..81553b843 100644 --- a/Assets/Gameplay/Player Scrips/PlayerMotor.cs +++ b/Assets/Gameplay/Player Scrips/PlayerMotor.cs @@ -30,15 +30,32 @@ public class PlayerMotor : MonoBehaviour private bool climbing = false; private bool swim = false; + // Manual vertical velocity — decoupled from Rigidbody to match CharacterController behavior + private float verticalVelocity = 0f; + + // Accumulated mouse input between frames for smooth camera + private float accumulatedMouseX = 0f; + private float accumulatedMouseY = 0f; + public ParticleSystem distortion; private float moveSpeed = 0f; private bool sideways = false; - public float groundMoveSpeed = 6f; - internal float rotationSpeed = 75f; //45 + public float groundMoveSpeed = 7.6f; // Authentic: CharacterMoveController.PlayerWalkSpeed = 7.6 + internal float rotationSpeed = 75f; internal float originalRotationSpeed = 75f; - public float jumpForce = 33f; + [Header("Movement — authentic UberStrike 4.7.1 (CharacterMoveController) constants")] + public float jumpForce = 15f; // PlayerJumpSpeed = 15 + public float uberGravity = 50f; // EnviromentSettings.Gravity = 50 + public float groundAccel = 15f; // GroundAcceleration + public float airAccel = 3f; // AirAcceleration — low value enables strafe-jump / bunny-hop + public float groundFriction = 8f; // GroundFriction + public float stopSpeed = 8f; // StopSpeed + public float maxHorizontalSpeed = 22.8f; // ClampHorizontally (3x walk = StrafeJumpMultiplier) + private Vector3 horizVel = Vector3.zero; // persistent horizontal velocity (carries momentum) + [Header("Pad Settings")] + public float maxPadVerticalVel = 45f; // Cap to prevent ceiling clipping on enclosed maps private Rigidbody primaryQuickItem; private Rigidbody secondaryQuickItem; public Transform playerCamera; @@ -55,6 +72,7 @@ public class PlayerMotor : MonoBehaviour private Animator handAnimator; private float rbDrag; private bool canJump = true; + internal bool jumpHeld = false; // Set by PlayerInput every frame (continuous state) private bool crouching = false; private Animator cameraAnimator; @@ -64,6 +82,13 @@ public class PlayerMotor : MonoBehaviour // Runs before first frame void Start() { + // Enforce physics values on every spawn — prevents prefab serialized values + // from overriding tuned values on death/respawn. Remove once prefab is updated. + groundMoveSpeed = 7.6f; // authentic PlayerWalkSpeed + jumpForce = 15f; // authentic PlayerJumpSpeed + uberGravity = 50f; // authentic EnviromentSettings.Gravity + maxPadVerticalVel = 45f; + capsule = GetComponent(); // Init array @@ -74,16 +99,15 @@ void Start() groundRayChecks[4] = new Vector3(-groundCheckRadius / 2, 0f, groundCheckRadius / 2); groundRayChecks[5] = new Vector3(groundCheckRadius / 2, 0f, -groundCheckRadius / 2); groundRayChecks[6] = new Vector3(-groundCheckRadius / 2, 0f, -groundCheckRadius / 2); - groundRayChecks[7] = new Vector3(groundCheckRadius / 2, 0f, groundCheckRadius / 2); groundRayChecks[7] = new Vector3(0f, 0f, 0f); // Init playerAudio = GetComponent(); - cameraAnimator = playerCamera.gameObject.GetComponent(); playerManager = GetComponent(); playerUI = GetComponent(); rigidBody = GetComponent(); playerCamera = transform.Find("Player Camera"); + cameraAnimator = playerCamera.gameObject.GetComponent(); hand = playerCamera.GetChild(0).gameObject; handCamera = playerCamera.Find("Camera Mask").gameObject.GetComponent(); @@ -91,8 +115,18 @@ void Start() lastRotation = rot.x; handAnimator = handCamera.GetComponent(); + // Ensure Rigidbody interpolation is on for smooth visual movement + rigidBody.interpolation = RigidbodyInterpolation.Interpolate; + + // Disable Unity's built-in gravity — we apply it manually to match + // original UberStrike's CharacterController (gravity=50, not Unity's 9.81) + rigidBody.useGravity = false; + // Prevent fast-moving player from clipping through geometry + rigidBody.collisionDetectionMode = CollisionDetectionMode.Continuous; + // Water - mapHasWater = GameObject.Find("/Environment").GetComponent().mapHasWater; + var envObj = GameObject.Find("/Environment"); + mapHasWater = envObj != null && envObj.GetComponent() != null && envObj.GetComponent().mapHasWater; rbDrag = rigidBody.linearDamping; UpdateOptions(); @@ -173,7 +207,7 @@ void Update() if (mapHasWater) { swim = rigidBody.position.y < 0; - rigidBody.useGravity = !swim; + // useGravity is always false — manual gravity handles swim vs air if (swim) rigidBody.linearDamping = 1f; else rigidBody.linearDamping = rbDrag; @@ -210,42 +244,100 @@ bool GetTransformDirectionCollision() // Do all movement in FixedUpdate method void FixedUpdate() { + // Refresh ground distance at physics rate + getDistanceToGround(); + float dt = Time.fixedDeltaTime; + + bool isGrounded = distanceToGround >= 0 && distanceToGround < groundLimit; + + // --- Jump check every physics frame (matches original CheckJump) --- + // Original: checks if jump key is HELD + canJump + grounded → jumps instantly. + // This enables bunny hopping: press space mid-air, land, instant jump next frame. + if (isGrounded && jumpHeld && canJump && !crouching && !climbing && !swim) + { + canJump = false; + verticalVelocity = jumpForce; + pendingHandEffect = true; + } + + // --- Vertical velocity (manual, like CharacterController) --- + // Apply gravity: _currentVelocity[1] -= Gravity * dt (original CharacterMoveController) + if (!isGrounded && !climbing) + { + if (swim) + verticalVelocity -= uberGravity * 0.1f * dt; + else + verticalVelocity -= uberGravity * dt; + } + else if (isGrounded && verticalVelocity < 0) + { + verticalVelocity = 0f; // Stop falling when grounded + } + // Clamp vertical velocity — original: Mathf.Clamp(_currentVelocity[1], -150, 150) + verticalVelocity = Mathf.Clamp(verticalVelocity, -150f, 150f); + + // Swim up with spacebar + if (swim && Input.GetKey(KeyCode.Space)) + verticalVelocity += uberGravity * 0.3f * dt; + + // Ladder climbing — W=up, S=down. Use raw vertical input directly. + // Don't use walk velocity (it pushes INTO ladder, collision cancels movement). + if (climbing) + { + float climbInput = Input.GetAxisRaw("Vertical"); // W=1, S=-1 + if (Mathf.Abs(climbInput) > 0.1f) + verticalVelocity = climbInput * moveSpeed * 1.5f; + else + verticalVelocity = 0f; // Hang on ladder when not pressing W/S + // Gentle push toward ladder to maintain OnCollisionStay contact + padPush = transform.forward * 1.5f; + } + //physics material - if (distanceToGround < groundLimit && !GetTransformDirectionCollision()) capsule.material = null; - else - if(climbing) capsule.material = null; + if (isGrounded && !GetTransformDirectionCollision()) capsule.material = null; + else if (climbing) capsule.material = null; else capsule.material = pMaterial; // Player movement SetMoveSpeed(); - if (rigidBody.linearVelocity.magnitude>0.3f|| movement.magnitude > 0.3f) Crouch(false); - // If ladder collision - if (climbing && movement!=Vector3.zero) rigidBody.MovePosition(rigidBody.position + transform.TransformDirection(Vector3.up) * moveSpeed*1.5f * Time.deltaTime); + // --- Authentic 4.7.1 horizontal movement: Quake accel + friction (CharacterMoveController) --- + // horizVel carries momentum across frames. Ground friction decelerates you; the low + // air-acceleration (3) with NO air friction is exactly what builds speed when strafe-jumping. + Vector3 wishDir = transform.TransformDirection(movement); + wishDir.y = 0f; + if (wishDir.sqrMagnitude > 1f) wishDir.Normalize(); - // If swim - if (swim && GetComponent().isActiveAndEnabled&&distanceToGround>groundLimit&&!Input.GetKey(KeyCode.Space)) rigidBody.AddForce(-Vector3.up, ForceMode.Acceleration); - else if(Input.GetKey(KeyCode.Space)) rigidBody.AddForce(Vector3.up, ForceMode.Acceleration); + if (isGrounded && !climbing) ApplyFriction(dt); + ApplyAcceleration(wishDir, moveSpeed, isGrounded ? groundAccel : airAccel, dt); - Vector3 useTheForce = movement; - // Jump speed gain - if (sideways && distanceToGround > groundLimit - && !swim && !climbing && distanceToGround < groundLimit + 2 - && Mathf.Abs(rigidBody.linearVelocity.z) < 6.6f && Mathf.Abs(rigidBody.linearVelocity.x) < 6.6f) - - if(sideways) rigidBody.AddForce(transform.TransformDirection(useTheForce) * moveSpeed * 1.8f,ForceMode.Acceleration); - //else rigidBody.AddForce(transform.TransformDirection(useTheForce) * moveSpeed * 5f); + // Clamp horizontal speed (original ClampHorizontally = 22.8) + if (horizVel.sqrMagnitude > maxHorizontalSpeed * maxHorizontalSpeed) + horizVel = horizVel.normalized * maxHorizontalSpeed; + + // --- Apply: Quake horizontal + manual vertical + external push (pads / explosions / ladder) --- + // linearVelocity is set fresh each frame; the physics engine resolves wall/ceiling collisions. + rigidBody.linearVelocity = new Vector3(horizVel.x, verticalVelocity, horizVel.z) + padPush; - rigidBody.MovePosition(rigidBody.position + transform.TransformDirection(movement) * moveSpeed * Time.deltaTime); + // Decay external push only (pads/explosions/ladder). Walk deceleration is ApplyFriction above. + if (isGrounded) + padPush = Vector3.Lerp(padPush, Vector3.zero, 8f * dt); + else + padPush = Vector3.Lerp(padPush, Vector3.zero, 1.5f * dt); + + // Player body rotation (uses accumulated mouse input) + Quaternion deltaRotation = Quaternion.Euler(new Vector3(0f, accumulatedMouseX, 0f) * rotationSpeed); + rigidBody.MoveRotation(rigidBody.rotation * deltaRotation); + accumulatedMouseX = 0f; // Walk anim if (movement.magnitude > 0.3f) { if (!handAnimator.enabled) handAnimator.Play("defaultHand"); - + // Enable animator handAnimator.enabled = true; - handAnimator.SetBool("walk", true); + handAnimator.SetBool("walk", true); } else { @@ -253,10 +345,10 @@ void FixedUpdate() handAnimator.enabled = false; handAnimator.SetBool("walk", false); - float rectW = 1f; //1.2f + float rectW = 1f; handCamera.rect = new Rect(handCamera.rect.x + -1f * playerRotationY * 0.001f, 0f, rectW, rectW); handCamera.rect = new Rect(Mathf.SmoothDamp(handCamera.rect.x, 0f, ref handVelocityY, handTime * Time.deltaTime), 0f, rectW, rectW); - if (handCamera.rect.x > -0.001f && handCamera.rect.x < 0.001f) handCamera.rect = new Rect(0f,0f,1f,1f); + if (handCamera.rect.x > -0.001f && handCamera.rect.x < 0.001f) handCamera.rect = new Rect(0f,0f,1f,1f); } // Hand Y @@ -270,16 +362,41 @@ void FixedUpdate() hand.transform.localPosition = new Vector3(0.263f, hand.transform.localPosition.y + -1f * playerRotationX * 0.001f,0.573f); hand.transform.localPosition = Vector3.SmoothDamp(hand.transform.localPosition, new Vector3(0.263f, handPositionY, 0.573f), ref handVelocity, handTime * Time.deltaTime); + } - // Player rotation - Quaternion deltaRotation = Quaternion.Euler(new Vector3(0f, playerRotationY, 0f) * rotationSpeed * Time.deltaTime); - rigidBody.MoveRotation(rigidBody.rotation * deltaRotation); + // --- Authentic Quake-style helpers (ported from CharacterMoveController 4.7.1) --- + + // Ground friction: bleed off speed toward zero. No friction in air → momentum for bunny-hop. + private void ApplyFriction(float dt) + { + float speed = horizVel.magnitude; + if (speed < 0.0001f) { horizVel = Vector3.zero; return; } + float control = Mathf.Max(stopSpeed, speed); + float drop = control * groundFriction * dt; + float newSpeed = Mathf.Max(speed - drop, 0f) / speed; + horizVel *= newSpeed; + } - // Player camera rotation + // Accelerate toward wishDir up to wishSpeed along that axis (classic Quake ground/air accel). + private void ApplyAcceleration(Vector3 wishDir, float wishSpeed, float accel, float dt) + { + float current = Vector3.Dot(horizVel, wishDir); + float add = wishSpeed - current; + if (add <= 0f) return; + float accelSpeed = accel * wishSpeed * dt; + if (accelSpeed > add) accelSpeed = add; + horizVel += wishDir * accelSpeed; + } + + // Camera rotation in LateUpdate for smooth mouse look (runs every render frame, not fixed timestep) + void LateUpdate() + { + // Player camera vertical rotation float clampAngle = 89f; - lastRotation += playerRotationX * rotationSpeed * Time.deltaTime; + lastRotation += accumulatedMouseY * rotationSpeed; lastRotation = Mathf.Clamp(lastRotation, -clampAngle, clampAngle); playerCamera.localRotation = Quaternion.Euler(lastRotation, 0f, 0.0f); + accumulatedMouseY = 0f; } private void SetMoveSpeed() @@ -290,15 +407,16 @@ private void SetMoveSpeed() if (aiming) { - // Slow down when aim + // Slow down when aim — original UberStrike: PLAYER_ZOOM_SLOWDOWN = 1.8f if(hand.GetComponent().currentWeapon.GetComponent() != null || hand.GetComponent().currentWeapon.GetComponent() != null) { - moveSpeed = groundMoveSpeed / 2.5f; - } + moveSpeed = groundMoveSpeed - 1.8f; + } } - if(swim) moveSpeed = groundMoveSpeed / 4f; + if (crouching) moveSpeed = groundMoveSpeed * 0.23f; // Original UberStrike: PLAYER_DUCK_SCALE + if (swim) moveSpeed = groundMoveSpeed * 0.4f; // Original UberStrike: PLAYER_SWIM_SCALE } internal void MouseScroll(float scroll) @@ -311,23 +429,16 @@ internal void MouseScroll(float scroll) else if(scroll != 0) hand.SendMessage("SetWeaponIndex", scroll); } + // Jump is now handled in FixedUpdate via jumpHeld state (continuous check). + // This method kept for any direct callers but FixedUpdate is the primary path. internal void Jump() { Crouch(false); - if (!canJump) return; - else StartCoroutine(CanJumpAgain()); - - if (distanceToGround < groundLimit+0.06 && distanceToGround > 0) - { - pendingHandEffect = true; - rigidBody.AddForce(transform.up * jumpForce, ForceMode.Impulse); - } } - IEnumerator CanJumpAgain() + // Called from PlayerInput when jump key is released + internal void JumpReleased() { - canJump = false; - yield return new WaitForSeconds(0.3f); canJump = true; } @@ -378,14 +489,18 @@ internal void MouseLook(float x, float y) { playerRotationY = x; playerRotationX = y; + // Accumulate for physics (FixedUpdate) and camera (LateUpdate) + accumulatedMouseX += x * Time.deltaTime; + accumulatedMouseY += y * Time.deltaTime; } internal void Move(float x, float z) { if (distanceToGround < groundLimit) - movement = Vector3.ClampMagnitude(new Vector3(z, 0f, x), 0.8f); + movement = Vector3.ClampMagnitude(new Vector3(z, 0f, x), 1f); else - movement = Vector3.Lerp(movement, Vector3.ClampMagnitude(new Vector3(z, 0f, x), 0.7f), 1.9f*Time.deltaTime); + // Air control: allow direction changes in air but slightly damped + movement = Vector3.Lerp(movement, Vector3.ClampMagnitude(new Vector3(z, 0f, x), 1f), 6f * Time.deltaTime); } // Spring grenade @@ -416,11 +531,22 @@ internal void UseItem(int itemId) } - public void PowerUp(Vector3 forceDirection) + // Temporary horizontal push from jump pads (decays over time) + private Vector3 padPush = Vector3.zero; + + /// + /// Called by ForceField/JumpPad. Accepts FINAL velocity vector (already scaled). + /// ForceField applies * 0.035 before calling. JumpPad applies its own multiplier. + /// Replaces velocity entirely (original ForceType.Exclusive behavior). + /// + public void PowerUp(Vector3 finalVelocity) { if (canUsePowerUp) { - rigidBody.AddForce(forceDirection * jumpForce, ForceMode.Impulse); + // Cap vertical — maxPadVerticalVel prevents extreme ceiling launches + verticalVelocity = Mathf.Clamp(finalVelocity.y, -maxPadVerticalVel, maxPadVerticalVel); + // Horizontal: let physics engine handle collision (no artificial cap needed) + padPush = new Vector3(finalVelocity.x, 0f, finalVelocity.z); canUsePowerUp = false; } } @@ -430,6 +556,21 @@ public void SetCanUsePowerUp(bool state) canUsePowerUp = state; } + /// + /// Apply explosion/rocket force to player. Additive — adds to current velocity + /// instead of replacing it (unlike PowerUp which is Exclusive). + /// Use this for rocket jumps, splash damage knockback, spring grenades, etc. + /// Original: ForceType.Additive → _currentVelocity = Scale(vel, (1, 0.5, 1)) + force * 0.035 + /// + public void ApplyExplosionForce(Vector3 force) + { + // Original additive: halves existing vertical velocity, adds scaled force + verticalVelocity = verticalVelocity * 0.5f + force.y; + // Always apply horizontal — ground friction in padPush decay handles sliding. + // Rocket jumping at your feet while grounded needs the horizontal push to work. + padPush += new Vector3(force.x, 0f, force.z); + } + void getDistanceToGround() { // Get closest ground around player @@ -501,10 +642,15 @@ internal void SetWeapon(int position) internal void Crouch(bool crouch) { - if (climbing || swim || rigidBody.linearVelocity != Vector3.zero) crouch = false; - if(crouch==crouching) return; - cameraAnimator.SetBool("down",crouch); + // Original UberStrike: can crouch while moving (duck walk at 23% speed) + // Only prevent crouch when climbing, swimming, or in air + if (climbing || swim) crouch = false; + bool isGrounded = distanceToGround >= 0 && distanceToGround < groundLimit; + if (!isGrounded && crouch) crouch = false; // Can't start crouching mid-air + if (crouch == crouching) return; + cameraAnimator.SetBool("down", crouch); crouching = crouch; - if (GameObject.Find("/Network Client")) GameObject.Find("/Network Client").SendMessage("LocalPlayerCrouch", crouching); + GameObject networkClient = GameObject.Find("/Network Client"); + if (networkClient != null) networkClient.SendMessage("LocalPlayerCrouch", crouching); } } diff --git a/Assets/Gameplay/Player Scrips/PlayerUI.cs b/Assets/Gameplay/Player Scrips/PlayerUI.cs index b3a94adb0..95dbf8e53 100644 --- a/Assets/Gameplay/Player Scrips/PlayerUI.cs +++ b/Assets/Gameplay/Player Scrips/PlayerUI.cs @@ -143,7 +143,12 @@ public void ToggleSniperScope(bool show) internal void SetIcon(int itemId, GameObject item) { - ((itemId == 0) ? primaryIcon : secondaryIcon).GetComponent().sprite = item.GetComponent().icon; + if (item == null) return; + var quickItem = item.GetComponent(); + if (quickItem != null && quickItem.icon != null) + { + ((itemId == 0) ? primaryIcon : secondaryIcon).GetComponent().sprite = quickItem.icon; + } } public void Zoom(float input) diff --git a/Assets/LibraryAssets/_MK/MKGlassFree/Shader/Inc/Forward/MKGlassForward.cginc b/Assets/LibraryAssets/_MK/MKGlassFree/Shader/Inc/Forward/MKGlassForward.cginc index 973e9c6d7..88199eeeb 100644 --- a/Assets/LibraryAssets/_MK/MKGlassFree/Shader/Inc/Forward/MKGlassForward.cginc +++ b/Assets/LibraryAssets/_MK/MKGlassFree/Shader/Inc/Forward/MKGlassForward.cginc @@ -65,12 +65,11 @@ UNITY_TRANSFER_LIGHTING(o,v.texcoord0.xy); #endif - //vertex fog + //vertex fog (fogCoord only declared on Unity < 2018; Unity 6 struct uses UNITY_LIGHTING_COORDS, no fogCoord) + #if UNITY_VERSION < 201800 UNITY_TRANSFER_FOG(o,o.pos); #endif - - //vertex fog - UNITY_TRANSFER_FOG(o,o.pos); + #endif #if UNITY_UV_STARTS_AT_TOP float scale = -1.0; @@ -114,8 +113,10 @@ mkts.Color_Out.a = lerp(0.625, 0.95, _MainTint); - //if enabled add some fog - forward rendering only + //if enabled add some fog - forward rendering only (fogCoord only on Unity < 2018) + #if UNITY_VERSION < 201800 UNITY_APPLY_FOG(o.fogCoord, mkts.Color_Out); + #endif return mkts.Color_Out; } #endif \ No newline at end of file diff --git a/Assets/Menus/Scripts/CreateGamePopup.cs b/Assets/Menus/Scripts/CreateGamePopup.cs index d9e7a2032..ce47a8e50 100644 --- a/Assets/Menus/Scripts/CreateGamePopup.cs +++ b/Assets/Menus/Scripts/CreateGamePopup.cs @@ -56,11 +56,9 @@ void Awake() public void CreateGame() { - if (gameMode == 2) - { - container.SetActive(false); - StartCoroutine(LoadAsync(map+2)); - } + container.SetActive(false); + // Scene indices: 0=GlobalScene, 1=MainMenu, 2=Intro, 3+=Maps + StartCoroutine(LoadAsync(map+3)); } public void CancelGame() diff --git a/Assets/Menus/Scripts/MouseOrbitImproved.cs b/Assets/Menus/Scripts/MouseOrbitImproved.cs index 84e7da854..abb62a906 100644 --- a/Assets/Menus/Scripts/MouseOrbitImproved.cs +++ b/Assets/Menus/Scripts/MouseOrbitImproved.cs @@ -23,9 +23,15 @@ public class MouseOrbitImproved : MonoBehaviour void Start() { // Skybox - RenderSettings.skybox = GameObject.Find("/Environment").GetComponent().skybox; + GameObject environmentObject = GameObject.Find("/Environment"); + Environment environment = environmentObject != null ? environmentObject.GetComponent() : null; + if (environment != null) RenderSettings.skybox = environment.skybox; - target = GameObject.Find("/Player Avatar").transform.GetChild(2); + GameObject playerAvatar = GameObject.Find("/Player Avatar"); + if (playerAvatar != null && playerAvatar.transform.childCount > 2) + { + target = playerAvatar.transform.GetChild(2); + } Vector3 angles = transform.eulerAngles; x = angles.y; @@ -48,6 +54,8 @@ void LateUpdate() private void Run() { + if (target == null) return; + x += Input.GetAxis("Mouse X") * xSpeed * distance * 0.02f; y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f; @@ -78,4 +86,4 @@ public static float ClampAngle(float angle, float min, float max) return Mathf.Clamp(angle, min, max); } -} \ No newline at end of file +} diff --git a/Assets/Menus/Scripts/TopBarUI.cs b/Assets/Menus/Scripts/TopBarUI.cs index f134b6198..cf63547c4 100644 --- a/Assets/Menus/Scripts/TopBarUI.cs +++ b/Assets/Menus/Scripts/TopBarUI.cs @@ -54,8 +54,9 @@ public class TopBarUI : MonoBehaviour void Start() { // Skybox - if(GameObject.Find("/Environment")) - if(GameObject.Find("/Environment").GetComponent().skybox!=null)RenderSettings.skybox = GameObject.Find("/Environment").GetComponent().skybox; + GameObject environmentObject = GameObject.Find("/Environment"); + Environment environment = environmentObject != null ? environmentObject.GetComponent() : null; + if (environment != null && environment.skybox != null) RenderSettings.skybox = environment.skybox; //audio @@ -313,7 +314,8 @@ private void UpdateUsername() { string newName = PlayerPrefs.GetString("username"); topBarUsername.GetComponent().text = newName; - if (GameObject.Find("/Player Avatar")) GameObject.Find("/Player Avatar").SendMessage("UpdateNameTag"); + GameObject playerAvatar = GameObject.Find("/Player Avatar"); + if (playerAvatar != null) playerAvatar.SendMessage("UpdateNameTag"); } // clears all local data @@ -325,16 +327,28 @@ public void ClearLocalData() public void SpawnPlayerInGame() { - if (inTheMenus|| respawnCanvas.GetChild(0).gameObject.GetComponent().currentTime>0) return; + if (inTheMenus || respawnCanvas == null || respawnCanvas.childCount == 0) return; + + GameObject respawnPanel = respawnCanvas.GetChild(0).gameObject; + RespawnManager respawnManager = respawnPanel.GetComponent(); + if (respawnManager != null && respawnManager.currentTime > 0) return; spawnActions.SetActive(false); // hide player avatar if(GameObject.Find("/Player Avatar")) GameObject.Find("/Player Avatar").SetActive(false); - respawnCanvas.GetChild(0).gameObject.SetActive(false); + respawnPanel.SetActive(false); // create player - GameObject.Find("/Network Client").GetComponent().LocalPlayerSpawn(); + GameObject networkClientObject = GameObject.Find("/Network Client"); + Client networkClient = networkClientObject != null ? networkClientObject.GetComponent() : null; + if (networkClient == null) + { + Debug.LogWarning("SpawnPlayerInGame skipped because /Network Client was not found."); + return; + } + + networkClient.LocalPlayerSpawn(); HideMenuSystemForGame(); } @@ -353,13 +367,15 @@ public void EditLoadoutInGame() { gameObject.SetActive(true); NavigationBar(2); - respawnCanvas.GetChild(0).gameObject.SetActive(false); + if (respawnCanvas != null && respawnCanvas.childCount > 0) + respawnCanvas.GetChild(0).gameObject.SetActive(false); //if(GameObject.Find("/Dead Player")) GameObject.Find("/Dead Player").GetComponentInChildren().rect = new Rect(-0.33f, 0f, 1f, 1f); } public void ResumeGame() { - GameObject.Find("/Player").SendMessage("ContinueGame"); + GameObject player = GameObject.Find("/Player"); + if (player != null) player.SendMessage("ContinueGame"); HideMenuSystemForGame(); } @@ -377,12 +393,23 @@ void HideMenuSystemForGame() public void LeaveServer() { - GameObject.Find("/Network Client").GetComponent().Quit(); + GameObject networkClientObject = GameObject.Find("/Network Client"); + Client networkClient = networkClientObject != null ? networkClientObject.GetComponent() : null; + if (networkClient == null) + { + Debug.LogWarning("LeaveServer skipped Client.Quit because /Network Client was not found."); + } + else + { + networkClient.Quit(); + } + SceneManager.LoadScene("MainMenu"); } public void KillYourself() { - if (GameObject.Find("/Player")) GameObject.Find("/Player").SendMessage("KillYourself"); + GameObject player = GameObject.Find("/Player"); + if (player != null) player.SendMessage("KillYourself"); } } diff --git a/Assets/Menus/Shop/QuickItemShopItem.cs b/Assets/Menus/Shop/QuickItemShopItem.cs index ac1ca2ba4..6766244db 100644 --- a/Assets/Menus/Shop/QuickItemShopItem.cs +++ b/Assets/Menus/Shop/QuickItemShopItem.cs @@ -10,12 +10,12 @@ public class QuickItemShopItem : ShopItem, IShopItem internal override string GetName() { - return prefab.GetComponent().itemName; + return prefab.GetComponent().itemName; } internal override Sprite GetThumb() { - return prefab.GetComponent().thumbnail; + return prefab.GetComponent().thumbnail; } // quickitems are not created dynamically, diff --git a/Assets/Menus/Shop/ShopKeeper.cs b/Assets/Menus/Shop/ShopKeeper.cs index 49be37a2f..c80e62dc4 100644 --- a/Assets/Menus/Shop/ShopKeeper.cs +++ b/Assets/Menus/Shop/ShopKeeper.cs @@ -42,14 +42,19 @@ public class ShopKeeper : MonoBehaviour void Start() { // get global resources - GlobalResources r = GameObject.Find("/Global Resources").GetComponent(); - weaponPrefabs = r.weapons.ToArray(); - appereancePrefabs = r.appereances.ToArray(); + GameObject globalResourcesObject = GameObject.Find("/Global Resources"); + GlobalResources r = globalResourcesObject != null ? globalResourcesObject.GetComponent() : null; + if (r != null) + { + weaponPrefabs = r.weapons.ToArray(); + appereancePrefabs = r.appereances.ToArray(); + } InitItemSlots(); audioSource = transform.parent.gameObject.GetComponent(); - playerAvatar = GameObject.Find("/Player Avatar").GetComponent(); - UpdateAvatar(); + GameObject playerAvatarObject = GameObject.Find("/Player Avatar"); + if (playerAvatarObject != null) playerAvatar = playerAvatarObject.GetComponent(); + if (playerAvatar != null) UpdateAvatar(); } // show only appereances of one class @@ -144,7 +149,7 @@ public void Drag(GameObject prefab, Sprite sprite, bool slotToSlot) // show right tab for draggable item // for springs - if (prefab.GetComponent() != null) + if (prefab.GetComponent() != null) { transform.parent.gameObject.GetComponent().LoadoutTabs(2); } @@ -204,7 +209,7 @@ public void EndDrag() if (mouseOnSlot && availableSlots.Contains(mouseOnSlot)) { // Equip items - if (prefabInDrag.GetComponent() != null) + if (prefabInDrag.GetComponent() != null) { audioSource.PlayOneShot(equipSoundQuickitem); } @@ -271,9 +276,9 @@ public string GetNameFromPrefab(GameObject prefab) } // in case if spring - else if (prefab.GetComponent() != null) + else if (prefab.GetComponent() != null) { - return prefab.GetComponent().itemName; + return prefab.GetComponent().itemName; } // in case of cloth else if (prefab.GetComponent() != null) @@ -291,9 +296,9 @@ public string GetTypeFromPrefab(GameObject prefab) return prefab.GetComponent().GetType().ToString(); } // in case of spring - else if (prefab.GetComponent() != null) + else if (prefab.GetComponent() != null) { - return prefab.GetComponent().type; + return prefab.GetComponent().type; } // in case of cloth else if (prefab.GetComponent() != null) @@ -313,9 +318,9 @@ public Sprite GetSpriteFromPrefab(GameObject prefab) } // in case if spring - else if (prefab.GetComponent() != null) + else if (prefab.GetComponent() != null) { - return prefab.GetComponent().thumbnail; + return prefab.GetComponent().thumbnail; } // in case of cloth else if (prefab.GetComponent() != null) @@ -435,10 +440,13 @@ public void SpawnToShootingRange() { if (GameObject.Find("/MenuSystem")) { + if (playerAvatar == null) return; playerAvatar.gameObject.SetActive(false); GameObject clonePlayer = Instantiate(player); clonePlayer.name = "Player"; - GameObject.Find("/Environment").GetComponent().volume = 0f; + GameObject environmentObject = GameObject.Find("/Environment"); + AudioSource environmentAudio = environmentObject != null ? environmentObject.GetComponent() : null; + if (environmentAudio != null) environmentAudio.volume = 0f; GameObject.Find("/MenuSystem").SetActive(false); } diff --git a/Assets/Prefabs/Powerups/Scripts/JumpPad.cs b/Assets/Prefabs/Powerups/Scripts/JumpPad.cs index 1e025510e..5ded53269 100644 --- a/Assets/Prefabs/Powerups/Scripts/JumpPad.cs +++ b/Assets/Prefabs/Powerups/Scripts/JumpPad.cs @@ -11,6 +11,10 @@ public class JumpPad : MonoBehaviour public bool isAccel = false; public float accelMultiply = 5f; + [Tooltip("Multiplier applied to forceDirection before sending to PlayerMotor. " + + "Sends final velocity directly — no extra modifier applied by PlayerMotor.")] + public float forceMultiplier = 10f; + void Start() { audioSource = GetComponent(); @@ -20,9 +24,15 @@ void OnTriggerEnter(Collider other) { if (other.tag == "Player") { - if (isAccel) other.gameObject.SendMessage("PowerUp",(transform.forward*accelMultiply)+new Vector3(0f,forceDirection.y,0f)); - else other.gameObject.SendMessage("PowerUp", forceDirection); - audioSource.Play(0); + Vector3 finalVelocity; + if (isAccel) + finalVelocity = (transform.forward * accelMultiply + new Vector3(0f, forceDirection.y, 0f)) * forceMultiplier; + else + finalVelocity = forceDirection * forceMultiplier; + + // PowerUp receives final velocity — sets it directly + other.gameObject.SendMessage("PowerUp", finalVelocity); + if (audioSource != null) audioSource.Play(0); } } diff --git a/Assets/Prefabs/Powerups/Scripts/SpringGrenade.cs b/Assets/Prefabs/Powerups/Scripts/SpringGrenade.cs index 539c9d3c0..f90eb178f 100644 --- a/Assets/Prefabs/Powerups/Scripts/SpringGrenade.cs +++ b/Assets/Prefabs/Powerups/Scripts/SpringGrenade.cs @@ -24,11 +24,11 @@ void OnTriggerStay(Collider other) { if (other.tag == "Player" && isArmed) { - // Explode grenade - Vector3 forceVector = new Vector3(0f, jumpForce, 0f); - other.gameObject.SendMessage("PowerUp", forceVector); + // Spring grenade — launches player upward (additive) + // Original: ForceType.Additive with force=1250 → 1250*0.035 = 43.75 vel + Vector3 springForce = new Vector3(0f, jumpForce * 15f, 0f); + other.gameObject.SendMessage("ApplyExplosionForce", springForce, SendMessageOptions.DontRequireReceiver); Destroy(gameObject); - other.gameObject.SendMessage("SetCanUsePowerUp", true); // Sound PlayerAudio audio = other.gameObject.GetComponent(); diff --git a/Assets/Prefabs/Powerups/Scripts/StickyMine.cs b/Assets/Prefabs/Powerups/Scripts/StickyMine.cs index f575618c1..ca0557960 100644 --- a/Assets/Prefabs/Powerups/Scripts/StickyMine.cs +++ b/Assets/Prefabs/Powerups/Scripts/StickyMine.cs @@ -95,9 +95,15 @@ private void Explosion() transform.position, -1, -1); - // Jump - hitColliders[i].SendMessage("PowerUp", (hitColliders[i].transform.position - transform.position) / 2 * selfJumpPower); - hitColliders[i].SendMessage("SetCanUsePowerUp", true); + // Explosion jump — additive force + float dist = Vector3.Distance(hitColliders[i].transform.position, transform.position); + if (dist < smallDmgRadius) + { + Vector3 blastDir = (hitColliders[i].transform.position - transform.position).normalized; + float proximityScale = 1f - (dist / smallDmgRadius); + Vector3 rocketForce = blastDir * selfJumpPower * proximityScale * 12f; + hitColliders[i].SendMessage("ApplyExplosionForce", rocketForce, SendMessageOptions.DontRequireReceiver); + } } i++; diff --git a/Assets/Prefabs/Weapons/Cannons/Cannon/cannon_projectile/CannonBullet.cs b/Assets/Prefabs/Weapons/Cannons/Cannon/cannon_projectile/CannonBullet.cs index fcde5920f..aafe8e46f 100644 --- a/Assets/Prefabs/Weapons/Cannons/Cannon/cannon_projectile/CannonBullet.cs +++ b/Assets/Prefabs/Weapons/Cannons/Cannon/cannon_projectile/CannonBullet.cs @@ -112,12 +112,17 @@ private void Explosion() transform.position, -1, -1); - // Jump + // Rocket jump — use ApplyExplosionForce (additive, doesn't replace velocity) + // Direction: away from explosion, scaled by selfJumpPower float dist = Vector3.Distance(hitColliders[i].transform.position, transform.position); - - if(dist<2) hitColliders[i].SendMessage("PowerUp", Vector3.Normalize((hitColliders[i].transform.position - transform.position)) * selfJumpPower); - - hitColliders[i].SendMessage("SetCanUsePowerUp", true); + if (dist < smallDmgRadius) + { + Vector3 blastDir = (hitColliders[i].transform.position - transform.position).normalized; + // Scale force by proximity (closer = stronger) and selfJumpPower + float proximityScale = 1f - (dist / smallDmgRadius); + Vector3 rocketForce = blastDir * selfJumpPower * proximityScale * 12f; + hitColliders[i].SendMessage("ApplyExplosionForce", rocketForce, SendMessageOptions.DontRequireReceiver); + } } i++; diff --git a/Assets/Prefabs/Weapons/Launchers/Launcher/grenade/LauncherGrenade.cs b/Assets/Prefabs/Weapons/Launchers/Launcher/grenade/LauncherGrenade.cs index cc9a860f2..fd97912c7 100644 --- a/Assets/Prefabs/Weapons/Launchers/Launcher/grenade/LauncherGrenade.cs +++ b/Assets/Prefabs/Weapons/Launchers/Launcher/grenade/LauncherGrenade.cs @@ -109,13 +109,19 @@ private void Explosion() // Send damage if (GameObject.Find("/Player")) GameObject.Find("/Player").GetComponent().TakeDamage( - Mathf.Floor(GetDmg(Vector3.Distance(hitColliders[i].transform.position, transform.position)) / reduceDmgToSelfBy), - transform.position, + Mathf.Floor(GetDmg(Vector3.Distance(hitColliders[i].transform.position, transform.position)) / reduceDmgToSelfBy), + transform.position, -1,-1); - - // Jump - hitColliders[i].SendMessage("PowerUp", (hitColliders[i].transform.position - transform.position) / 2 * selfJumpPower); - hitColliders[i].SendMessage("SetCanUsePowerUp", true); + + // Rocket jump — use ApplyExplosionForce (additive, doesn't replace velocity) + float dist = Vector3.Distance(hitColliders[i].transform.position, transform.position); + if (dist < smallDmgRadius) + { + Vector3 blastDir = (hitColliders[i].transform.position - transform.position).normalized; + float proximityScale = 1f - (dist / smallDmgRadius); + Vector3 rocketForce = blastDir * selfJumpPower * proximityScale * 12f; + hitColliders[i].SendMessage("ApplyExplosionForce", rocketForce, SendMessageOptions.DontRequireReceiver); + } } diff --git a/Assets/Prefabs/Weapons/Shotgun.cs b/Assets/Prefabs/Weapons/Shotgun.cs index 6a22d42a4..aa7e38c4c 100644 --- a/Assets/Prefabs/Weapons/Shotgun.cs +++ b/Assets/Prefabs/Weapons/Shotgun.cs @@ -40,6 +40,7 @@ public override void FiringActions() if (shellIndex) SpitShell(shellIndex, shellSpeed, 2); FireMuzzle(); + if (bulletTrail == null) return; List hitData = GetRaycastHitObject(maxRange, spread, shotCount); @@ -116,6 +117,8 @@ public override void FireMuzzle() internal override void NetworkFire(RaycastHit target) { + if (bulletTrail == null) return; + List hitData = GetRaycastHitObject(muzzleIndex, target.point, spread, shotCount); if (hitData.Count > 0) diff --git a/Assets/Prefabs/Weapons/Weapon.cs b/Assets/Prefabs/Weapons/Weapon.cs index af98988c5..c09462e60 100644 --- a/Assets/Prefabs/Weapons/Weapon.cs +++ b/Assets/Prefabs/Weapons/Weapon.cs @@ -296,10 +296,12 @@ internal Vector3 GetSpread(Vector2 spread) // same with sound option public void BulletTrail(Transform pos, Vector3 targetPoint, bool hasSound) { + if (bulletTrail == null) return; Transform clonet = Instantiate(bulletTrail, pos.position, pos.rotation); clonet.LookAt(targetPoint); - clonet.gameObject.GetComponent().sound = hasSound; - Destroy(clonet.gameObject, 1f); + var trail = clonet.gameObject.GetComponent(); + if (trail != null) trail.sound = hasSound; + Destroy(clonet.gameObject, 1f); } //custom narrator diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index bb11a5530..e930e9ed5 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -6,11 +6,14 @@ EditorBuildSettings: serializedVersion: 2 m_Scenes: - enabled: 1 - path: Assets/Menus/Intro.unity - guid: f7b286020c378264982286603976c541 + path: Assets/Scenes/GlobalScene.unity + guid: 1f05f0a7b71d0f948aa23c64e11f1d87 - enabled: 1 path: Assets/Menus/MainMenu.unity guid: 850382a7f8c81ea47a2504469e81789a + - enabled: 1 + path: Assets/Menus/Intro.unity + guid: f7b286020c378264982286603976c541 - enabled: 1 path: Assets/Maps/Apex_Twin/Apex_Twin.unity guid: c3fdb28bd94380940b61db76ac6dac05 @@ -56,5 +59,14 @@ EditorBuildSettings: - enabled: 1 path: Assets/Maps/The_Hangar/The_Hangar.unity guid: 4d951c4843244e845983843c4a3122d9 + - enabled: 0 + path: Assets/Maps/CuberStrike/CuberStrike.unity + guid: 91b2e7bed92e18c4a8ad5564553783ac + - enabled: 0 + path: Assets/Maps/GhostIsland/GhostIsland.unity + guid: 1dcd903f1950d7f4da9fef161c9524c6 + - enabled: 0 + path: Assets/Maps/Volley/Volley.unity + guid: ca5011381629bf14da393b88ade88224 m_configObjects: {} m_UseUCBPForAssetBundles: 0