diff options
author | chai <215380520@qq.com> | 2023-10-27 11:05:14 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2023-10-27 11:05:14 +0800 |
commit | 766cdff5ffa72b65d7f106658d1603f47739b2ba (patch) | |
tree | 34d7799a94dfa9be182825577583c0fa6dc935f7 |
+ init
1395 files changed, 92452 insertions, 0 deletions
diff --git a/Doc/ROUNDS分析.xlsx b/Doc/ROUNDS分析.xlsx Binary files differnew file mode 100644 index 0000000..36f3d44 --- /dev/null +++ b/Doc/ROUNDS分析.xlsx diff --git a/GameCode/AbyssalCountdown.cs b/GameCode/AbyssalCountdown.cs new file mode 100644 index 0000000..062e920 --- /dev/null +++ b/GameCode/AbyssalCountdown.cs @@ -0,0 +1,189 @@ +using System; +using Sonigon; +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +public class AbyssalCountdown : MonoBehaviour +{ + public SoundEvent soundAbyssalChargeLoop; + + private bool soundChargeIsPlaying; + + private float soundCounterLast; + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + [Range(0f, 1f)] + public float counter; + + public float timeToFill = 10f; + + public float timeToEmpty = 3f; + + public float duration; + + public float hpMultiplier = 2f; + + public ProceduralImage outerRing; + + public ProceduralImage fill; + + public Transform rotator; + + public Transform still; + + private CharacterData data; + + public GameObject[] abyssalObjects; + + private float remainingDuration; + + private bool isAbyssalForm; + + private float startCounter; + + private void Start() + { + soundCounterLast = counter; + data = GetComponentInParent<CharacterData>(); + HealthHandler healthHandler = data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(ResetStuff)); + GetComponentInParent<ChildRPC>().childRPCs.Add("Abyssal", RPCA_Activate); + } + + private void OnDestroy() + { + HealthHandler healthHandler = data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(ResetStuff)); + GetComponentInParent<ChildRPC>().childRPCs.Remove("Abyssal"); + SoundStop(); + } + + private void OnDisable() + { + SoundStop(); + } + + private void SoundPlay() + { + if (!soundChargeIsPlaying) + { + soundChargeIsPlaying = true; + SoundManager.Instance.Play(soundAbyssalChargeLoop, base.transform, soundParameterIntensity); + } + } + + private void SoundStop() + { + if (soundChargeIsPlaying) + { + soundChargeIsPlaying = false; + SoundManager.Instance.Stop(soundAbyssalChargeLoop, base.transform); + } + } + + private void ResetStuff() + { + SoundStop(); + remainingDuration = 0f; + counter = 0f; + if (isAbyssalForm) + { + for (int i = 0; i < abyssalObjects.Length; i++) + { + abyssalObjects[i].gameObject.SetActive(value: false); + } + data.maxHealth /= hpMultiplier; + data.health /= hpMultiplier; + data.stats.ConfigureMassAndSize(); + isAbyssalForm = false; + rotator.gameObject.SetActive(value: false); + still.gameObject.SetActive(value: false); + } + SoundStop(); + } + + private void RPCA_Activate() + { + remainingDuration = duration; + } + + private void Update() + { + if (soundCounterLast < counter) + { + SoundPlay(); + } + else + { + SoundStop(); + } + soundCounterLast = counter; + soundParameterIntensity.intensity = counter; + outerRing.fillAmount = counter; + fill.fillAmount = counter; + rotator.transform.localEulerAngles = new Vector3(0f, 0f, 0f - Mathf.Lerp(0f, 360f, counter)); + if (!data.playerVel.simulated) + { + startCounter = 1f; + return; + } + startCounter -= TimeHandler.deltaTime; + if (startCounter > 0f) + { + return; + } + if (remainingDuration > 0f) + { + if (!isAbyssalForm) + { + for (int i = 0; i < abyssalObjects.Length; i++) + { + abyssalObjects[i].gameObject.SetActive(value: true); + } + data.maxHealth *= hpMultiplier; + data.health *= hpMultiplier; + data.stats.ConfigureMassAndSize(); + isAbyssalForm = true; + } + remainingDuration -= TimeHandler.deltaTime; + counter = remainingDuration / duration; + return; + } + if (isAbyssalForm) + { + for (int j = 0; j < abyssalObjects.Length; j++) + { + abyssalObjects[j].gameObject.SetActive(value: false); + } + data.maxHealth /= hpMultiplier; + data.health /= hpMultiplier; + data.stats.ConfigureMassAndSize(); + isAbyssalForm = false; + } + if (data.input.direction == Vector3.zero || data.input.direction == Vector3.down) + { + counter += TimeHandler.deltaTime / timeToFill; + } + else + { + counter -= TimeHandler.deltaTime / timeToEmpty; + } + counter = Mathf.Clamp(counter, -0.1f / timeToFill, 1f); + if (counter >= 1f && data.view.IsMine) + { + remainingDuration = duration; + GetComponentInParent<ChildRPC>().CallFunction("Abyssal"); + } + if (counter <= 0f) + { + rotator.gameObject.SetActive(value: false); + still.gameObject.SetActive(value: false); + } + else + { + rotator.gameObject.SetActive(value: true); + still.gameObject.SetActive(value: true); + } + } +} diff --git a/GameCode/Accelerate.cs b/GameCode/Accelerate.cs new file mode 100644 index 0000000..9bc086b --- /dev/null +++ b/GameCode/Accelerate.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class Accelerate : MonoBehaviour +{ + private MoveTransform move; + + public float startMultiplier = 0.5f; + + public float acceleratonPerSecond = 2f; + + public float pow = 1f; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + move.multiplier *= startMultiplier; + move.multiplier = Mathf.Clamp(move.multiplier, 0.01f, float.PositiveInfinity); + } + + private void Update() + { + move.multiplier = Mathf.Clamp(move.multiplier + TimeHandler.deltaTime * acceleratonPerSecond * Mathf.Pow(move.multiplier, pow), 0f, 25f); + } +} diff --git a/GameCode/ActivateSciptWhenCanSeeOtherPlayer.cs b/GameCode/ActivateSciptWhenCanSeeOtherPlayer.cs new file mode 100644 index 0000000..5a527fc --- /dev/null +++ b/GameCode/ActivateSciptWhenCanSeeOtherPlayer.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class ActivateSciptWhenCanSeeOtherPlayer : MonoBehaviour +{ + public enum Target + { + OtherPlayer, + Closest + } + + public Target target; + + private SpawnedAttack spawned; + + public MonoBehaviour script; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + } + + private void Update() + { + Player player = null; + player = ((target != 0) ? PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true) : PlayerManager.instance.GetOtherPlayer(spawned.spawner)); + if ((bool)player) + { + if (PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee) + { + script.enabled = true; + } + else + { + script.enabled = false; + } + } + else + { + script.enabled = false; + } + } +} diff --git a/GameCode/AddShake.cs b/GameCode/AddShake.cs new file mode 100644 index 0000000..227a243 --- /dev/null +++ b/GameCode/AddShake.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class AddShake : MonoBehaviour +{ + public Vector2 shake; + + public bool auto = true; + + public bool inheritScale; + + public float max = float.PositiveInfinity; + + private void Start() + { + if (auto) + { + DoShake(); + } + } + + public void DoShake() + { + GamefeelManager.GameFeel(shake * Mathf.Clamp(inheritScale ? base.transform.localScale.x : 1f, 0f, max)); + } +} diff --git a/GameCode/Aim.cs b/GameCode/Aim.cs new file mode 100644 index 0000000..45288a5 --- /dev/null +++ b/GameCode/Aim.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class Aim : MonoBehaviour +{ + private GeneralInput input; + + private HoldingObject holdingObject; + + private CharacterData data; + + private Vector3 aimDirection; + + private void Awake() + { + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + holdingObject = GetComponentInChildren<HoldingObject>(); + } + + private void Update() + { + if ((double)input.aimDirection.magnitude > 0.2) + { + aimDirection = input.aimDirection; + } + if (input.direction.magnitude > 0.2f && Optionshandler.leftStickAim && input.aimDirection == Vector3.zero) + { + aimDirection = input.direction; + } + if ((bool)holdingObject) + { + if (aimDirection != Vector3.zero) + { + holdingObject.transform.rotation = Quaternion.LookRotation(aimDirection); + } + data.aimDirection = aimDirection; + } + } +} diff --git a/GameCode/AimForPlayer.cs b/GameCode/AimForPlayer.cs new file mode 100644 index 0000000..5a9ab24 --- /dev/null +++ b/GameCode/AimForPlayer.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +public class AimForPlayer : MonoBehaviour +{ + public enum Target + { + OtherPlayer, + Closest + } + + public float upOffset; + + public Target target; + + private SpawnedAttack spawned; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + } + + private void Update() + { + Player player = null; + player = ((target != 0) ? PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true) : PlayerManager.instance.GetOtherPlayer(spawned.spawner)); + if ((bool)player && PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee) + { + base.transform.rotation = Quaternion.LookRotation(player.transform.position + Vector3.up * Vector3.Distance(player.transform.position, base.transform.position) * 0.1f * upOffset - base.transform.position, Vector3.forward); + } + } +} diff --git a/GameCode/AmplifyColorBase.cs b/GameCode/AmplifyColorBase.cs new file mode 100644 index 0000000..214d0a4 --- /dev/null +++ b/GameCode/AmplifyColorBase.cs @@ -0,0 +1,879 @@ +using System; +using System.Collections.Generic; +using AmplifyColor; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +[AddComponentMenu("")] +public class AmplifyColorBase : MonoBehaviour +{ + public const int LutSize = 32; + + public const int LutWidth = 1024; + + public const int LutHeight = 32; + + private const int DepthCurveLutRange = 1024; + + public Tonemapping Tonemapper; + + public float Exposure = 1f; + + public float LinearWhitePoint = 11.2f; + + [FormerlySerializedAs("UseDithering")] + public bool ApplyDithering; + + public Quality QualityLevel = Quality.Standard; + + public float BlendAmount; + + public Texture LutTexture; + + public Texture LutBlendTexture; + + public Texture MaskTexture; + + public bool UseDepthMask; + + public AnimationCurve DepthMaskCurve = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 1f)); + + public bool UseVolumes; + + public float ExitVolumeBlendTime = 1f; + + public Transform TriggerVolumeProxy; + + public LayerMask VolumeCollisionMask = -1; + + private Camera ownerCamera; + + private Shader shaderBase; + + private Shader shaderBlend; + + private Shader shaderBlendCache; + + private Shader shaderMask; + + private Shader shaderMaskBlend; + + private Shader shaderDepthMask; + + private Shader shaderDepthMaskBlend; + + private Shader shaderProcessOnly; + + private RenderTexture blendCacheLut; + + private Texture2D defaultLut; + + private Texture2D depthCurveLut; + + private Color32[] depthCurveColors; + + private ColorSpace colorSpace = ColorSpace.Uninitialized; + + private Quality qualityLevel = Quality.Standard; + + private Material materialBase; + + private Material materialBlend; + + private Material materialBlendCache; + + private Material materialMask; + + private Material materialMaskBlend; + + private Material materialDepthMask; + + private Material materialDepthMaskBlend; + + private Material materialProcessOnly; + + private bool blending; + + private float blendingTime; + + private float blendingTimeCountdown; + + private Action onFinishBlend; + + private AnimationCurve prevDepthMaskCurve = new AnimationCurve(); + + private bool volumesBlending; + + private float volumesBlendingTime; + + private float volumesBlendingTimeCountdown; + + private Texture volumesLutBlendTexture; + + private float volumesBlendAmount; + + private Texture worldLUT; + + private AmplifyColorVolumeBase currentVolumeLut; + + private RenderTexture midBlendLUT; + + private bool blendingFromMidBlend; + + private VolumeEffect worldVolumeEffects; + + private VolumeEffect currentVolumeEffects; + + private VolumeEffect blendVolumeEffects; + + private float worldExposure = 1f; + + private float currentExposure = 1f; + + private float blendExposure = 1f; + + private float effectVolumesBlendAdjust; + + private List<AmplifyColorVolumeBase> enteredVolumes = new List<AmplifyColorVolumeBase>(); + + private AmplifyColorTriggerProxyBase actualTriggerProxy; + + [HideInInspector] + public VolumeEffectFlags EffectFlags = new VolumeEffectFlags(); + + [SerializeField] + [HideInInspector] + private string sharedInstanceID = ""; + + private bool silentError; + + public Texture2D DefaultLut + { + get + { + if (!(defaultLut == null)) + { + return defaultLut; + } + return CreateDefaultLut(); + } + } + + public bool IsBlending => blending; + + private float effectVolumesBlendAdjusted => Mathf.Clamp01((effectVolumesBlendAdjust < 0.99f) ? ((volumesBlendAmount - effectVolumesBlendAdjust) / (1f - effectVolumesBlendAdjust)) : 1f); + + public string SharedInstanceID => sharedInstanceID; + + public bool WillItBlend + { + get + { + if (LutTexture != null && LutBlendTexture != null) + { + return !blending; + } + return false; + } + } + + public void NewSharedInstanceID() + { + sharedInstanceID = Guid.NewGuid().ToString(); + } + + private void ReportMissingShaders() + { + Debug.LogError("[AmplifyColor] Failed to initialize shaders. Please attempt to re-enable the Amplify Color Effect component. If that fails, please reinstall Amplify Color."); + base.enabled = false; + } + + private void ReportNotSupported() + { + Debug.LogError("[AmplifyColor] This image effect is not supported on this platform."); + base.enabled = false; + } + + private bool CheckShader(Shader s) + { + if (s == null) + { + ReportMissingShaders(); + return false; + } + if (!s.isSupported) + { + ReportNotSupported(); + return false; + } + return true; + } + + private bool CheckShaders() + { + if (CheckShader(shaderBase) && CheckShader(shaderBlend) && CheckShader(shaderBlendCache) && CheckShader(shaderMask) && CheckShader(shaderMaskBlend)) + { + return CheckShader(shaderProcessOnly); + } + return false; + } + + private bool CheckSupport() + { + if (!SystemInfo.supportsImageEffects) + { + ReportNotSupported(); + return false; + } + return true; + } + + private void OnEnable() + { + if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null) + { + Debug.LogWarning("[AmplifyColor] Null graphics device detected. Skipping effect silently."); + silentError = true; + } + else if (CheckSupport() && CreateMaterials()) + { + Texture2D texture2D = LutTexture as Texture2D; + Texture2D texture2D2 = LutBlendTexture as Texture2D; + if ((texture2D != null && texture2D.mipmapCount > 1) || (texture2D2 != null && texture2D2.mipmapCount > 1)) + { + Debug.LogError("[AmplifyColor] Please disable \"Generate Mip Maps\" import settings on all LUT textures to avoid visual glitches. Change Texture Type to \"Advanced\" to access Mip settings."); + } + } + } + + private void OnDisable() + { + if (actualTriggerProxy != null) + { + UnityEngine.Object.DestroyImmediate(actualTriggerProxy.gameObject); + actualTriggerProxy = null; + } + ReleaseMaterials(); + ReleaseTextures(); + } + + private void VolumesBlendTo(Texture blendTargetLUT, float blendTimeInSec) + { + volumesLutBlendTexture = blendTargetLUT; + volumesBlendAmount = 0f; + volumesBlendingTime = blendTimeInSec; + volumesBlendingTimeCountdown = blendTimeInSec; + volumesBlending = true; + } + + public void BlendTo(Texture blendTargetLUT, float blendTimeInSec, Action onFinishBlend) + { + LutBlendTexture = blendTargetLUT; + BlendAmount = 0f; + this.onFinishBlend = onFinishBlend; + blendingTime = blendTimeInSec; + blendingTimeCountdown = blendTimeInSec; + blending = true; + } + + private void CheckCamera() + { + if (ownerCamera == null) + { + ownerCamera = GetComponent<Camera>(); + } + if (UseDepthMask && (ownerCamera.depthTextureMode & DepthTextureMode.Depth) == 0) + { + ownerCamera.depthTextureMode |= DepthTextureMode.Depth; + } + } + + private void Start() + { + if (!silentError) + { + CheckCamera(); + worldLUT = LutTexture; + worldVolumeEffects = EffectFlags.GenerateEffectData(this); + blendVolumeEffects = (currentVolumeEffects = worldVolumeEffects); + worldExposure = Exposure; + blendExposure = (currentExposure = worldExposure); + } + } + + private void Update() + { + if (silentError) + { + return; + } + CheckCamera(); + bool flag = false; + if (volumesBlending) + { + volumesBlendAmount = (volumesBlendingTime - volumesBlendingTimeCountdown) / volumesBlendingTime; + volumesBlendingTimeCountdown -= Time.smoothDeltaTime; + if (volumesBlendAmount >= 1f) + { + volumesBlendAmount = 1f; + flag = true; + } + } + else + { + volumesBlendAmount = Mathf.Clamp01(volumesBlendAmount); + } + if (blending) + { + BlendAmount = (blendingTime - blendingTimeCountdown) / blendingTime; + blendingTimeCountdown -= Time.smoothDeltaTime; + if (BlendAmount >= 1f) + { + LutTexture = LutBlendTexture; + BlendAmount = 0f; + blending = false; + LutBlendTexture = null; + if (onFinishBlend != null) + { + onFinishBlend(); + } + } + } + else + { + BlendAmount = Mathf.Clamp01(BlendAmount); + } + if (UseVolumes) + { + if (actualTriggerProxy == null) + { + GameObject gameObject = new GameObject(base.name + "+ACVolumeProxy") + { + hideFlags = HideFlags.HideAndDontSave + }; + if (TriggerVolumeProxy != null && TriggerVolumeProxy.GetComponent<Collider2D>() != null) + { + actualTriggerProxy = gameObject.AddComponent<AmplifyColorTriggerProxy2D>(); + } + else + { + actualTriggerProxy = gameObject.AddComponent<AmplifyColorTriggerProxy>(); + } + actualTriggerProxy.OwnerEffect = this; + } + UpdateVolumes(); + } + else if (actualTriggerProxy != null) + { + UnityEngine.Object.DestroyImmediate(actualTriggerProxy.gameObject); + actualTriggerProxy = null; + } + if (flag) + { + LutTexture = volumesLutBlendTexture; + volumesBlendAmount = 0f; + volumesBlending = false; + volumesLutBlendTexture = null; + effectVolumesBlendAdjust = 0f; + currentVolumeEffects = blendVolumeEffects; + currentVolumeEffects.SetValues(this); + currentExposure = blendExposure; + if (blendingFromMidBlend && midBlendLUT != null) + { + midBlendLUT.DiscardContents(); + } + blendingFromMidBlend = false; + } + } + + public void EnterVolume(AmplifyColorVolumeBase volume) + { + if (!enteredVolumes.Contains(volume)) + { + enteredVolumes.Insert(0, volume); + } + } + + public void ExitVolume(AmplifyColorVolumeBase volume) + { + if (enteredVolumes.Contains(volume)) + { + enteredVolumes.Remove(volume); + } + } + + private void UpdateVolumes() + { + if (volumesBlending) + { + currentVolumeEffects.BlendValues(this, blendVolumeEffects, effectVolumesBlendAdjusted); + } + if (volumesBlending) + { + Exposure = Mathf.Lerp(currentExposure, blendExposure, effectVolumesBlendAdjusted); + } + Transform transform = ((TriggerVolumeProxy == null) ? base.transform : TriggerVolumeProxy); + if (actualTriggerProxy.transform.parent != transform) + { + actualTriggerProxy.Reference = transform; + actualTriggerProxy.gameObject.layer = transform.gameObject.layer; + } + AmplifyColorVolumeBase amplifyColorVolumeBase = null; + int num = int.MinValue; + for (int i = 0; i < enteredVolumes.Count; i++) + { + AmplifyColorVolumeBase amplifyColorVolumeBase2 = enteredVolumes[i]; + if (amplifyColorVolumeBase2.Priority > num) + { + amplifyColorVolumeBase = amplifyColorVolumeBase2; + num = amplifyColorVolumeBase2.Priority; + } + } + if (!(amplifyColorVolumeBase != currentVolumeLut)) + { + return; + } + currentVolumeLut = amplifyColorVolumeBase; + Texture texture = ((amplifyColorVolumeBase == null) ? worldLUT : amplifyColorVolumeBase.LutTexture); + float num2 = ((amplifyColorVolumeBase == null) ? ExitVolumeBlendTime : amplifyColorVolumeBase.EnterBlendTime); + if (volumesBlending && !blendingFromMidBlend && texture == LutTexture) + { + LutTexture = volumesLutBlendTexture; + volumesLutBlendTexture = texture; + volumesBlendingTimeCountdown = num2 * ((volumesBlendingTime - volumesBlendingTimeCountdown) / volumesBlendingTime); + volumesBlendingTime = num2; + currentVolumeEffects = VolumeEffect.BlendValuesToVolumeEffect(EffectFlags, currentVolumeEffects, blendVolumeEffects, effectVolumesBlendAdjusted); + currentExposure = Mathf.Lerp(currentExposure, blendExposure, effectVolumesBlendAdjusted); + effectVolumesBlendAdjust = 1f - volumesBlendAmount; + volumesBlendAmount = 1f - volumesBlendAmount; + } + else + { + if (volumesBlending) + { + materialBlendCache.SetFloat("_LerpAmount", volumesBlendAmount); + if (blendingFromMidBlend) + { + Graphics.Blit(midBlendLUT, blendCacheLut); + materialBlendCache.SetTexture("_RgbTex", blendCacheLut); + } + else + { + materialBlendCache.SetTexture("_RgbTex", LutTexture); + } + materialBlendCache.SetTexture("_LerpRgbTex", (volumesLutBlendTexture != null) ? volumesLutBlendTexture : defaultLut); + Graphics.Blit(midBlendLUT, midBlendLUT, materialBlendCache); + blendCacheLut.DiscardContents(); + currentVolumeEffects = VolumeEffect.BlendValuesToVolumeEffect(EffectFlags, currentVolumeEffects, blendVolumeEffects, effectVolumesBlendAdjusted); + currentExposure = Mathf.Lerp(currentExposure, blendExposure, effectVolumesBlendAdjusted); + effectVolumesBlendAdjust = 0f; + blendingFromMidBlend = true; + } + VolumesBlendTo(texture, num2); + } + blendVolumeEffects = ((amplifyColorVolumeBase == null) ? worldVolumeEffects : amplifyColorVolumeBase.EffectContainer.FindVolumeEffect(this)); + blendExposure = ((amplifyColorVolumeBase == null) ? worldExposure : amplifyColorVolumeBase.Exposure); + if (blendVolumeEffects == null) + { + blendVolumeEffects = worldVolumeEffects; + } + } + + private void SetupShader() + { + colorSpace = QualitySettings.activeColorSpace; + qualityLevel = QualityLevel; + shaderBase = Shader.Find("Hidden/Amplify Color/Base"); + shaderBlend = Shader.Find("Hidden/Amplify Color/Blend"); + shaderBlendCache = Shader.Find("Hidden/Amplify Color/BlendCache"); + shaderMask = Shader.Find("Hidden/Amplify Color/Mask"); + shaderMaskBlend = Shader.Find("Hidden/Amplify Color/MaskBlend"); + shaderDepthMask = Shader.Find("Hidden/Amplify Color/DepthMask"); + shaderDepthMaskBlend = Shader.Find("Hidden/Amplify Color/DepthMaskBlend"); + shaderProcessOnly = Shader.Find("Hidden/Amplify Color/ProcessOnly"); + } + + private void ReleaseMaterials() + { + SafeRelease(ref materialBase); + SafeRelease(ref materialBlend); + SafeRelease(ref materialBlendCache); + SafeRelease(ref materialMask); + SafeRelease(ref materialMaskBlend); + SafeRelease(ref materialDepthMask); + SafeRelease(ref materialDepthMaskBlend); + SafeRelease(ref materialProcessOnly); + } + + private Texture2D CreateDefaultLut() + { + defaultLut = new Texture2D(1024, 32, TextureFormat.RGB24, mipChain: false, linear: true) + { + hideFlags = HideFlags.HideAndDontSave + }; + defaultLut.name = "DefaultLut"; + defaultLut.hideFlags = HideFlags.DontSave; + defaultLut.anisoLevel = 1; + defaultLut.filterMode = FilterMode.Bilinear; + Color32[] array = new Color32[32768]; + for (int i = 0; i < 32; i++) + { + int num = i * 32; + for (int j = 0; j < 32; j++) + { + int num2 = num + j * 1024; + for (int k = 0; k < 32; k++) + { + float num3 = (float)k / 31f; + float num4 = (float)j / 31f; + float num5 = (float)i / 31f; + byte r = (byte)(num3 * 255f); + byte g = (byte)(num4 * 255f); + byte b = (byte)(num5 * 255f); + array[num2 + k] = new Color32(r, g, b, byte.MaxValue); + } + } + } + defaultLut.SetPixels32(array); + defaultLut.Apply(); + return defaultLut; + } + + private Texture2D CreateDepthCurveLut() + { + SafeRelease(ref depthCurveLut); + depthCurveLut = new Texture2D(1024, 1, TextureFormat.Alpha8, mipChain: false, linear: true) + { + hideFlags = HideFlags.HideAndDontSave + }; + depthCurveLut.name = "DepthCurveLut"; + depthCurveLut.hideFlags = HideFlags.DontSave; + depthCurveLut.anisoLevel = 1; + depthCurveLut.wrapMode = TextureWrapMode.Clamp; + depthCurveLut.filterMode = FilterMode.Bilinear; + depthCurveColors = new Color32[1024]; + return depthCurveLut; + } + + private void UpdateDepthCurveLut() + { + if (depthCurveLut == null) + { + CreateDepthCurveLut(); + } + float num = 0f; + int num2 = 0; + while (num2 < 1024) + { + depthCurveColors[num2].a = (byte)Mathf.FloorToInt(Mathf.Clamp01(DepthMaskCurve.Evaluate(num)) * 255f); + num2++; + num += 0.0009775171f; + } + depthCurveLut.SetPixels32(depthCurveColors); + depthCurveLut.Apply(); + } + + private void CheckUpdateDepthCurveLut() + { + bool flag = false; + if (DepthMaskCurve.length != prevDepthMaskCurve.length) + { + flag = true; + } + else + { + float num = 0f; + int num2 = 0; + while (num2 < DepthMaskCurve.length) + { + if (Mathf.Abs(DepthMaskCurve.Evaluate(num) - prevDepthMaskCurve.Evaluate(num)) > float.Epsilon) + { + flag = true; + break; + } + num2++; + num += 0.0009775171f; + } + } + if (depthCurveLut == null || flag) + { + UpdateDepthCurveLut(); + prevDepthMaskCurve = new AnimationCurve(DepthMaskCurve.keys); + } + } + + private void CreateHelperTextures() + { + ReleaseTextures(); + blendCacheLut = new RenderTexture(1024, 32, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) + { + hideFlags = HideFlags.HideAndDontSave + }; + blendCacheLut.name = "BlendCacheLut"; + blendCacheLut.wrapMode = TextureWrapMode.Clamp; + blendCacheLut.useMipMap = false; + blendCacheLut.anisoLevel = 0; + blendCacheLut.Create(); + midBlendLUT = new RenderTexture(1024, 32, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) + { + hideFlags = HideFlags.HideAndDontSave + }; + midBlendLUT.name = "MidBlendLut"; + midBlendLUT.wrapMode = TextureWrapMode.Clamp; + midBlendLUT.useMipMap = false; + midBlendLUT.anisoLevel = 0; + midBlendLUT.Create(); + CreateDefaultLut(); + if (UseDepthMask) + { + CreateDepthCurveLut(); + } + } + + private bool CheckMaterialAndShader(Material material, string name) + { + if (material == null || material.shader == null) + { + Debug.LogWarning("[AmplifyColor] Error creating " + name + " material. Effect disabled."); + base.enabled = false; + } + else if (!material.shader.isSupported) + { + Debug.LogWarning("[AmplifyColor] " + name + " shader not supported on this platform. Effect disabled."); + base.enabled = false; + } + else + { + material.hideFlags = HideFlags.HideAndDontSave; + } + return base.enabled; + } + + private bool CreateMaterials() + { + SetupShader(); + if (!CheckShaders()) + { + return false; + } + ReleaseMaterials(); + materialBase = new Material(shaderBase); + materialBlend = new Material(shaderBlend); + materialBlendCache = new Material(shaderBlendCache); + materialMask = new Material(shaderMask); + materialMaskBlend = new Material(shaderMaskBlend); + materialDepthMask = new Material(shaderDepthMask); + materialDepthMaskBlend = new Material(shaderDepthMaskBlend); + materialProcessOnly = new Material(shaderProcessOnly); + if (1 == 0 || !CheckMaterialAndShader(materialBase, "BaseMaterial") || !CheckMaterialAndShader(materialBlend, "BlendMaterial") || !CheckMaterialAndShader(materialBlendCache, "BlendCacheMaterial") || !CheckMaterialAndShader(materialMask, "MaskMaterial") || !CheckMaterialAndShader(materialMaskBlend, "MaskBlendMaterial") || !CheckMaterialAndShader(materialDepthMask, "DepthMaskMaterial") || !CheckMaterialAndShader(materialDepthMaskBlend, "DepthMaskBlendMaterial") || !CheckMaterialAndShader(materialProcessOnly, "ProcessOnlyMaterial")) + { + return false; + } + CreateHelperTextures(); + return true; + } + + private void SetMaterialKeyword(string keyword, bool state) + { + bool flag = materialBase.IsKeywordEnabled(keyword); + if (state && !flag) + { + materialBase.EnableKeyword(keyword); + materialBlend.EnableKeyword(keyword); + materialBlendCache.EnableKeyword(keyword); + materialMask.EnableKeyword(keyword); + materialMaskBlend.EnableKeyword(keyword); + materialDepthMask.EnableKeyword(keyword); + materialDepthMaskBlend.EnableKeyword(keyword); + materialProcessOnly.EnableKeyword(keyword); + } + else if (!state && materialBase.IsKeywordEnabled(keyword)) + { + materialBase.DisableKeyword(keyword); + materialBlend.DisableKeyword(keyword); + materialBlendCache.DisableKeyword(keyword); + materialMask.DisableKeyword(keyword); + materialMaskBlend.DisableKeyword(keyword); + materialDepthMask.DisableKeyword(keyword); + materialDepthMaskBlend.DisableKeyword(keyword); + materialProcessOnly.DisableKeyword(keyword); + } + } + + private void SafeRelease<T>(ref T obj) where T : UnityEngine.Object + { + if ((UnityEngine.Object)obj != (UnityEngine.Object)null) + { + if (obj.GetType() == typeof(RenderTexture)) + { + (obj as RenderTexture).Release(); + } + UnityEngine.Object.DestroyImmediate(obj); + obj = null; + } + } + + private void ReleaseTextures() + { + RenderTexture.active = null; + SafeRelease(ref blendCacheLut); + SafeRelease(ref midBlendLUT); + SafeRelease(ref defaultLut); + SafeRelease(ref depthCurveLut); + } + + public static bool ValidateLutDimensions(Texture lut) + { + bool result = true; + if (lut != null) + { + if (lut.width / lut.height != lut.height) + { + Debug.LogWarning("[AmplifyColor] Lut " + lut.name + " has invalid dimensions."); + result = false; + } + else if (lut.anisoLevel != 0) + { + lut.anisoLevel = 0; + } + } + return result; + } + + private void UpdatePostEffectParams() + { + if (UseDepthMask) + { + CheckUpdateDepthCurveLut(); + } + Exposure = Mathf.Max(Exposure, 0f); + } + + private int ComputeShaderPass() + { + bool flag = QualityLevel == Quality.Mobile; + bool flag2 = colorSpace == ColorSpace.Linear; + bool allowHDR = ownerCamera.allowHDR; + int num = (flag ? 18 : 0); + if (allowHDR) + { + num += 2; + num += (flag2 ? 8 : 0); + num += (ApplyDithering ? 4 : 0); + return (int)(num + Tonemapper); + } + return num + (flag2 ? 1 : 0); + } + + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + if (silentError) + { + Graphics.Blit(source, destination); + return; + } + BlendAmount = Mathf.Clamp01(BlendAmount); + if (colorSpace != QualitySettings.activeColorSpace || qualityLevel != QualityLevel) + { + CreateMaterials(); + } + UpdatePostEffectParams(); + bool num = ValidateLutDimensions(LutTexture); + bool flag = ValidateLutDimensions(LutBlendTexture); + bool flag2 = LutTexture == null && LutBlendTexture == null && volumesLutBlendTexture == null; + Texture texture = ((LutTexture == null) ? defaultLut : LutTexture); + Texture lutBlendTexture = LutBlendTexture; + int pass = ComputeShaderPass(); + bool flag3 = BlendAmount != 0f || blending; + bool flag4 = flag3 || (flag3 && lutBlendTexture != null); + bool flag5 = flag4; + bool num2 = !num || !flag || flag2; + Material material = (num2 ? materialProcessOnly : ((flag4 || volumesBlending) ? ((!UseDepthMask) ? ((MaskTexture != null) ? materialMaskBlend : materialBlend) : materialDepthMaskBlend) : ((!UseDepthMask) ? ((MaskTexture != null) ? materialMask : materialBase) : materialDepthMask))); + material.SetFloat("_Exposure", Exposure); + material.SetFloat("_ShoulderStrength", 0.22f); + material.SetFloat("_LinearStrength", 0.3f); + material.SetFloat("_LinearAngle", 0.1f); + material.SetFloat("_ToeStrength", 0.2f); + material.SetFloat("_ToeNumerator", 0.01f); + material.SetFloat("_ToeDenominator", 0.3f); + material.SetFloat("_LinearWhite", LinearWhitePoint); + material.SetFloat("_LerpAmount", BlendAmount); + if (MaskTexture != null) + { + material.SetTexture("_MaskTex", MaskTexture); + } + if (UseDepthMask) + { + material.SetTexture("_DepthCurveLut", depthCurveLut); + } + if (MaskTexture != null && source.dimension == TextureDimension.Tex2DArray) + { + material.SetVector("_StereoScale", new Vector4(0.5f, 1f, 0.5f, 0f)); + } + else + { + material.SetVector("_StereoScale", new Vector4(1f, 1f, 0f, 0f)); + } + if (!num2) + { + if (volumesBlending) + { + volumesBlendAmount = Mathf.Clamp01(volumesBlendAmount); + materialBlendCache.SetFloat("_LerpAmount", volumesBlendAmount); + if (blendingFromMidBlend) + { + materialBlendCache.SetTexture("_RgbTex", midBlendLUT); + } + else + { + materialBlendCache.SetTexture("_RgbTex", texture); + } + materialBlendCache.SetTexture("_LerpRgbTex", (volumesLutBlendTexture != null) ? volumesLutBlendTexture : defaultLut); + Graphics.Blit(texture, blendCacheLut, materialBlendCache); + } + if (flag5) + { + materialBlendCache.SetFloat("_LerpAmount", BlendAmount); + RenderTexture renderTexture = null; + if (volumesBlending) + { + renderTexture = RenderTexture.GetTemporary(blendCacheLut.width, blendCacheLut.height, blendCacheLut.depth, blendCacheLut.format, RenderTextureReadWrite.Linear); + Graphics.Blit(blendCacheLut, renderTexture); + materialBlendCache.SetTexture("_RgbTex", renderTexture); + } + else + { + materialBlendCache.SetTexture("_RgbTex", texture); + } + materialBlendCache.SetTexture("_LerpRgbTex", (lutBlendTexture != null) ? lutBlendTexture : defaultLut); + Graphics.Blit(texture, blendCacheLut, materialBlendCache); + if (renderTexture != null) + { + RenderTexture.ReleaseTemporary(renderTexture); + } + material.SetTexture("_RgbBlendCacheTex", blendCacheLut); + } + else if (volumesBlending) + { + material.SetTexture("_RgbBlendCacheTex", blendCacheLut); + } + else + { + if (texture != null) + { + material.SetTexture("_RgbTex", texture); + } + if (lutBlendTexture != null) + { + material.SetTexture("_LerpRgbTex", lutBlendTexture); + } + } + } + Graphics.Blit(source, destination, material, pass); + if (flag5 || volumesBlending) + { + blendCacheLut.DiscardContents(); + } + } +} diff --git a/GameCode/AmplifyColorEffect.cs b/GameCode/AmplifyColorEffect.cs new file mode 100644 index 0000000..ca37822 --- /dev/null +++ b/GameCode/AmplifyColorEffect.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +[ImageEffectAllowedInSceneView] +[ImageEffectTransformsToLDR] +[ExecuteInEditMode] +[AddComponentMenu("Image Effects/Amplify Color")] +public sealed class AmplifyColorEffect : AmplifyColorBase +{ +} diff --git a/GameCode/AmplifyColorRenderMask.cs b/GameCode/AmplifyColorRenderMask.cs new file mode 100644 index 0000000..8890a0e --- /dev/null +++ b/GameCode/AmplifyColorRenderMask.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +[ExecuteInEditMode] +[RequireComponent(typeof(Camera))] +[RequireComponent(typeof(AmplifyColorEffect))] +[AddComponentMenu("Image Effects/Amplify Color Render Mask")] +public class AmplifyColorRenderMask : AmplifyColorRenderMaskBase +{ +} diff --git a/GameCode/AmplifyColorRenderMaskBase.cs b/GameCode/AmplifyColorRenderMaskBase.cs new file mode 100644 index 0000000..589c64a --- /dev/null +++ b/GameCode/AmplifyColorRenderMaskBase.cs @@ -0,0 +1,174 @@ +using AmplifyColor; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.XR; + +[ExecuteInEditMode] +[RequireComponent(typeof(Camera))] +[AddComponentMenu("")] +public class AmplifyColorRenderMaskBase : MonoBehaviour +{ + [FormerlySerializedAs("clearColor")] + public Color ClearColor = Color.black; + + [FormerlySerializedAs("renderLayers")] + public RenderLayer[] RenderLayers = new RenderLayer[0]; + + [FormerlySerializedAs("debug")] + public bool DebugMask; + + private Camera referenceCamera; + + private Camera maskCamera; + + private AmplifyColorBase colorEffect; + + private int width; + + private int height; + + private RenderTexture maskTexture; + + private Shader colorMaskShader; + + private bool singlePassStereo; + + private void OnEnable() + { + if (maskCamera == null) + { + GameObject gameObject = new GameObject("Mask Camera", typeof(Camera)) + { + hideFlags = HideFlags.HideAndDontSave + }; + gameObject.transform.parent = base.gameObject.transform; + maskCamera = gameObject.GetComponent<Camera>(); + } + referenceCamera = GetComponent<Camera>(); + colorEffect = GetComponent<AmplifyColorBase>(); + colorMaskShader = Shader.Find("Hidden/RenderMask"); + } + + private void OnDisable() + { + DestroyCamera(); + DestroyRenderTextures(); + } + + private void DestroyCamera() + { + if (maskCamera != null) + { + Object.DestroyImmediate(maskCamera.gameObject); + maskCamera = null; + } + } + + private void DestroyRenderTextures() + { + if (maskTexture != null) + { + RenderTexture.active = null; + Object.DestroyImmediate(maskTexture); + maskTexture = null; + } + } + + private void UpdateRenderTextures(bool singlePassStereo) + { + int num = referenceCamera.pixelWidth; + int num2 = referenceCamera.pixelHeight; + if (maskTexture == null || width != num || height != num2 || !maskTexture.IsCreated() || this.singlePassStereo != singlePassStereo) + { + width = num; + height = num2; + DestroyRenderTextures(); + if (XRSettings.enabled) + { + num = XRSettings.eyeTextureWidth * ((!singlePassStereo) ? 1 : 2); + num2 = XRSettings.eyeTextureHeight; + } + if (maskTexture == null) + { + maskTexture = new RenderTexture(num, num2, 24, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB) + { + hideFlags = HideFlags.HideAndDontSave, + name = "MaskTexture" + }; + maskTexture.name = "AmplifyColorMaskTexture"; + bool allowMSAA = maskCamera.allowMSAA; + maskTexture.antiAliasing = ((!allowMSAA || QualitySettings.antiAliasing <= 0) ? 1 : QualitySettings.antiAliasing); + } + maskTexture.Create(); + this.singlePassStereo = singlePassStereo; + } + if (colorEffect != null) + { + colorEffect.MaskTexture = maskTexture; + } + } + + private void UpdateCameraProperties() + { + maskCamera.CopyFrom(referenceCamera); + maskCamera.targetTexture = maskTexture; + maskCamera.clearFlags = CameraClearFlags.Nothing; + maskCamera.renderingPath = RenderingPath.VertexLit; + maskCamera.pixelRect = new Rect(0f, 0f, width, height); + maskCamera.depthTextureMode = DepthTextureMode.None; + maskCamera.allowHDR = false; + maskCamera.enabled = false; + } + + private void OnPreRender() + { + if (!(maskCamera != null)) + { + return; + } + RenderBuffer activeColorBuffer = Graphics.activeColorBuffer; + RenderBuffer activeDepthBuffer = Graphics.activeDepthBuffer; + bool flag = false; + if (referenceCamera.stereoEnabled) + { + flag = XRSettings.eyeTextureDesc.vrUsage == VRTextureUsage.TwoEyes; + maskCamera.SetStereoViewMatrix(Camera.StereoscopicEye.Left, referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Left)); + maskCamera.SetStereoViewMatrix(Camera.StereoscopicEye.Right, referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Right)); + maskCamera.SetStereoProjectionMatrix(Camera.StereoscopicEye.Left, referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left)); + maskCamera.SetStereoProjectionMatrix(Camera.StereoscopicEye.Right, referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right)); + } + UpdateRenderTextures(flag); + UpdateCameraProperties(); + Graphics.SetRenderTarget(maskTexture); + GL.Clear(clearDepth: true, clearColor: true, ClearColor); + if (flag) + { + maskCamera.worldToCameraMatrix = referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Left); + maskCamera.projectionMatrix = referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left); + maskCamera.rect = new Rect(0f, 0f, 0.5f, 1f); + } + RenderLayer[] renderLayers = RenderLayers; + for (int i = 0; i < renderLayers.Length; i++) + { + RenderLayer renderLayer = renderLayers[i]; + Shader.SetGlobalColor("_COLORMASK_Color", renderLayer.color); + maskCamera.cullingMask = renderLayer.mask; + maskCamera.RenderWithShader(colorMaskShader, "RenderType"); + } + if (flag) + { + maskCamera.worldToCameraMatrix = referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Right); + maskCamera.projectionMatrix = referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right); + maskCamera.rect = new Rect(0.5f, 0f, 0.5f, 1f); + renderLayers = RenderLayers; + for (int i = 0; i < renderLayers.Length; i++) + { + RenderLayer renderLayer2 = renderLayers[i]; + Shader.SetGlobalColor("_COLORMASK_Color", renderLayer2.color); + maskCamera.cullingMask = renderLayer2.mask; + maskCamera.RenderWithShader(colorMaskShader, "RenderType"); + } + } + Graphics.SetRenderTarget(activeColorBuffer, activeDepthBuffer); + } +} diff --git a/GameCode/AmplifyColorTriggerProxy.cs b/GameCode/AmplifyColorTriggerProxy.cs new file mode 100644 index 0000000..916f8f1 --- /dev/null +++ b/GameCode/AmplifyColorTriggerProxy.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +[RequireComponent(typeof(Rigidbody))] +[RequireComponent(typeof(SphereCollider))] +[AddComponentMenu("")] +public class AmplifyColorTriggerProxy : AmplifyColorTriggerProxyBase +{ + private SphereCollider sphereCollider; + + private Rigidbody rigidBody; + + private void Start() + { + sphereCollider = GetComponent<SphereCollider>(); + sphereCollider.radius = 0.01f; + sphereCollider.isTrigger = true; + rigidBody = GetComponent<Rigidbody>(); + rigidBody.useGravity = false; + rigidBody.isKinematic = true; + } + + private void LateUpdate() + { + base.transform.position = Reference.position; + base.transform.rotation = Reference.rotation; + } +} diff --git a/GameCode/AmplifyColorTriggerProxy2D.cs b/GameCode/AmplifyColorTriggerProxy2D.cs new file mode 100644 index 0000000..c4bc606 --- /dev/null +++ b/GameCode/AmplifyColorTriggerProxy2D.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +[RequireComponent(typeof(Rigidbody2D))] +[RequireComponent(typeof(CircleCollider2D))] +[AddComponentMenu("")] +public class AmplifyColorTriggerProxy2D : AmplifyColorTriggerProxyBase +{ + private CircleCollider2D circleCollider; + + private Rigidbody2D rigidBody; + + private void Start() + { + circleCollider = GetComponent<CircleCollider2D>(); + circleCollider.radius = 0.01f; + circleCollider.isTrigger = true; + rigidBody = GetComponent<Rigidbody2D>(); + rigidBody.gravityScale = 0f; + rigidBody.isKinematic = true; + } + + private void LateUpdate() + { + base.transform.position = Reference.position; + base.transform.rotation = Reference.rotation; + } +} diff --git a/GameCode/AmplifyColorTriggerProxyBase.cs b/GameCode/AmplifyColorTriggerProxyBase.cs new file mode 100644 index 0000000..efb1cac --- /dev/null +++ b/GameCode/AmplifyColorTriggerProxyBase.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +[AddComponentMenu("")] +public class AmplifyColorTriggerProxyBase : MonoBehaviour +{ + public Transform Reference; + + public AmplifyColorBase OwnerEffect; +} diff --git a/GameCode/AmplifyColorVolume.cs b/GameCode/AmplifyColorVolume.cs new file mode 100644 index 0000000..e616e57 --- /dev/null +++ b/GameCode/AmplifyColorVolume.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +[RequireComponent(typeof(BoxCollider))] +[AddComponentMenu("Image Effects/Amplify Color Volume")] +public class AmplifyColorVolume : AmplifyColorVolumeBase +{ + private void OnTriggerEnter(Collider other) + { + AmplifyColorTriggerProxy component = other.GetComponent<AmplifyColorTriggerProxy>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.EnterVolume(this); + } + } + + private void OnTriggerExit(Collider other) + { + AmplifyColorTriggerProxy component = other.GetComponent<AmplifyColorTriggerProxy>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.ExitVolume(this); + } + } +} diff --git a/GameCode/AmplifyColorVolume2D.cs b/GameCode/AmplifyColorVolume2D.cs new file mode 100644 index 0000000..3dd0bbd --- /dev/null +++ b/GameCode/AmplifyColorVolume2D.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +[RequireComponent(typeof(BoxCollider2D))] +[AddComponentMenu("Image Effects/Amplify Color Volume 2D")] +public class AmplifyColorVolume2D : AmplifyColorVolumeBase +{ + private void OnTriggerEnter2D(Collider2D other) + { + AmplifyColorTriggerProxy2D component = other.GetComponent<AmplifyColorTriggerProxy2D>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.EnterVolume(this); + } + } + + private void OnTriggerExit2D(Collider2D other) + { + AmplifyColorTriggerProxy2D component = other.GetComponent<AmplifyColorTriggerProxy2D>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.ExitVolume(this); + } + } +} diff --git a/GameCode/AmplifyColorVolumeBase.cs b/GameCode/AmplifyColorVolumeBase.cs new file mode 100644 index 0000000..b241f7f --- /dev/null +++ b/GameCode/AmplifyColorVolumeBase.cs @@ -0,0 +1,74 @@ +using AmplifyColor; +using UnityEngine; + +[ExecuteInEditMode] +[AddComponentMenu("")] +public class AmplifyColorVolumeBase : MonoBehaviour +{ + public Texture2D LutTexture; + + public float Exposure = 1f; + + public float EnterBlendTime = 1f; + + public int Priority; + + public bool ShowInSceneView = true; + + [HideInInspector] + public VolumeEffectContainer EffectContainer = new VolumeEffectContainer(); + + private void OnDrawGizmos() + { + if (!ShowInSceneView) + { + return; + } + BoxCollider component = GetComponent<BoxCollider>(); + BoxCollider2D component2 = GetComponent<BoxCollider2D>(); + if (component != null || component2 != null) + { + Vector3 center; + Vector3 size; + if (component != null) + { + center = component.center; + size = component.size; + } + else + { + center = component2.offset; + size = component2.size; + } + Gizmos.color = Color.green; + Gizmos.matrix = base.transform.localToWorldMatrix; + Gizmos.DrawWireCube(center, size); + } + } + + private void OnDrawGizmosSelected() + { + BoxCollider component = GetComponent<BoxCollider>(); + BoxCollider2D component2 = GetComponent<BoxCollider2D>(); + if (component != null || component2 != null) + { + Color green = Color.green; + green.a = 0.2f; + Gizmos.color = green; + Gizmos.matrix = base.transform.localToWorldMatrix; + Vector3 center; + Vector3 size; + if (component != null) + { + center = component.center; + size = component.size; + } + else + { + center = component2.offset; + size = component2.size; + } + Gizmos.DrawCube(center, size); + } + } +} diff --git a/GameCode/ApplyCardStats.cs b/GameCode/ApplyCardStats.cs new file mode 100644 index 0000000..378db39 --- /dev/null +++ b/GameCode/ApplyCardStats.cs @@ -0,0 +1,305 @@ +using System.Collections.Generic; +using Photon.Pun; +using UnityEngine; + +public class ApplyCardStats : MonoBehaviour +{ + private Gun myGunStats; + + private CharacterStatModifiers myPlayerStats; + + private Block myBlock; + + private Player playerToUpgrade; + + private CardAudioModifier cardAudio; + + private bool done; + + private DamagableEvent damagable; + + public bool shootToPick; + + private void Start() + { + myGunStats = GetComponent<Gun>(); + myPlayerStats = GetComponent<CharacterStatModifiers>(); + myBlock = GetComponentInChildren<Block>(); + cardAudio = GetComponent<CardAudioModifier>(); + damagable = GetComponentInChildren<DamagableEvent>(); + } + + private void Update() + { + if (shootToPick && damagable.dead && (bool)damagable.lastPlayer) + { + Pick(damagable.lastPlayer.teamID); + Object.Destroy(base.gameObject); + } + } + + [PunRPC] + public void RPCA_Pick(int[] actorIDs) + { + for (int i = 0; i < actorIDs.Length; i++) + { + playerToUpgrade = PlayerManager.instance.GetPlayerWithActorID(actorIDs[i]); + ApplyStats(); + CardBarHandler.instance.AddCard(playerToUpgrade.playerID, GetComponent<CardInfo>().sourceCard); + } + } + + [PunRPC] + public void OFFLINE_Pick(Player[] players) + { + for (int i = 0; i < players.Length; i++) + { + playerToUpgrade = players[i]; + ApplyStats(); + CardBarHandler.instance.AddCard(playerToUpgrade.playerID, GetComponent<CardInfo>().sourceCard); + } + } + + public void Pick(int pickerID, bool forcePick = false, PickerType pickerType = PickerType.Team) + { + Start(); + if (done && !forcePick) + { + return; + } + done = true; + Player[] array = PlayerManager.instance.GetPlayersInTeam(pickerID); + if (pickerType == PickerType.Player) + { + array = new Player[1] { PlayerManager.instance.players[pickerID] }; + } + if (PhotonNetwork.OfflineMode) + { + OFFLINE_Pick(array); + return; + } + int[] array2 = new int[array.Length]; + for (int i = 0; i < array.Length; i++) + { + array2[i] = array[i].data.view.ControllerActorNr; + } + GetComponent<PhotonView>().RPC("RPCA_Pick", RpcTarget.All, array2); + } + + private void ApplyStats() + { + done = true; + PlayerAudioModifyers component = playerToUpgrade.GetComponent<PlayerAudioModifyers>(); + Gun component2 = playerToUpgrade.GetComponent<Holding>().holdable.GetComponent<Gun>(); + Player component3 = playerToUpgrade.GetComponent<Player>(); + CharacterData component4 = playerToUpgrade.GetComponent<CharacterData>(); + HealthHandler component5 = playerToUpgrade.GetComponent<HealthHandler>(); + playerToUpgrade.GetComponent<Movement>(); + Gravity component6 = playerToUpgrade.GetComponent<Gravity>(); + Block component7 = playerToUpgrade.GetComponent<Block>(); + CharacterStatModifiers component8 = component3.GetComponent<CharacterStatModifiers>(); + GunAmmo componentInChildren = component2.GetComponentInChildren<GunAmmo>(); + if ((bool)componentInChildren && (bool)myGunStats) + { + componentInChildren.ammoReg += myGunStats.ammoReg; + componentInChildren.maxAmmo += myGunStats.ammo; + componentInChildren.maxAmmo = Mathf.Clamp(componentInChildren.maxAmmo, 1, 90); + componentInChildren.reloadTimeMultiplier *= myGunStats.reloadTime; + componentInChildren.reloadTimeAdd += myGunStats.reloadTimeAdd; + } + component3.data.currentCards.Add(GetComponent<CardInfo>().sourceCard); + if ((bool)myGunStats) + { + if (myGunStats.lockGunToDefault) + { + component2.defaultCooldown = myGunStats.forceSpecificAttackSpeed; + component2.lockGunToDefault = myGunStats.lockGunToDefault; + } + if ((bool)myGunStats && myGunStats.projectiles.Length != 0) + { + component2.projectiles[0].objectToSpawn = myGunStats.projectiles[0].objectToSpawn; + } + if ((bool)myGunStats) + { + CopyGunStats(myGunStats, component2); + } + } + if ((bool)myPlayerStats) + { + component8.sizeMultiplier *= myPlayerStats.sizeMultiplier; + component4.maxHealth *= myPlayerStats.health; + component8.ConfigureMassAndSize(); + component8.movementSpeed *= myPlayerStats.movementSpeed; + component8.jump *= myPlayerStats.jump; + component4.jumps += myPlayerStats.numberOfJumps; + component6.gravityForce *= myPlayerStats.gravity; + component5.regeneration += myPlayerStats.regen; + if ((bool)myPlayerStats.AddObjectToPlayer) + { + component8.objectsAddedToPlayer.Add(Object.Instantiate(myPlayerStats.AddObjectToPlayer, component3.transform.position, component3.transform.rotation, component3.transform)); + } + component8.lifeSteal += myPlayerStats.lifeSteal; + component8.respawns += myPlayerStats.respawns; + component8.secondsToTakeDamageOver += myPlayerStats.secondsToTakeDamageOver; + if (myPlayerStats.refreshOnDamage) + { + component8.refreshOnDamage = true; + } + if (!myPlayerStats.automaticReload) + { + component8.automaticReload = false; + } + } + if ((bool)myBlock) + { + if (myBlock.objectsToSpawn != null) + { + for (int i = 0; i < myBlock.objectsToSpawn.Count; i++) + { + component7.objectsToSpawn.Add(myBlock.objectsToSpawn[i]); + } + } + component7.cdMultiplier *= myBlock.cdMultiplier; + component7.cdAdd += myBlock.cdAdd; + component7.forceToAdd += myBlock.forceToAdd; + component7.forceToAddUp += myBlock.forceToAddUp; + component7.additionalBlocks += myBlock.additionalBlocks; + component7.healing += myBlock.healing; + if (myBlock.autoBlock) + { + component7.autoBlock = myBlock.autoBlock; + } + } + if ((bool)component && (bool)cardAudio) + { + component.AddToStack(cardAudio); + } + component8.WasUpdated(); + component5.Revive(); + } + + public static void CopyGunStats(Gun copyFromGun, Gun copyToGun) + { + if (copyFromGun.unblockable) + { + copyToGun.unblockable = copyFromGun.unblockable; + } + if (copyFromGun.ignoreWalls) + { + copyToGun.ignoreWalls = copyFromGun.ignoreWalls; + } + float num = 1f; + if (copyFromGun.numberOfProjectiles != 0 && copyToGun.numberOfProjectiles != 1) + { + num = (float)copyFromGun.numberOfProjectiles / ((float)copyFromGun.numberOfProjectiles + (float)copyToGun.numberOfProjectiles); + } + copyToGun.damage *= 1f - num * (1f - copyFromGun.damage); + if (copyToGun.damage < 0.25f) + { + copyToGun.damage = 0.25f; + } + copyToGun.size += copyFromGun.size; + float num2 = 1f; + if (copyFromGun.chargeNumberOfProjectilesTo != 0f) + { + num2 = copyFromGun.chargeNumberOfProjectilesTo / (copyFromGun.chargeNumberOfProjectilesTo + copyToGun.chargeNumberOfProjectilesTo); + } + copyToGun.chargeDamageMultiplier *= 1f - num2 * (1f - copyFromGun.chargeDamageMultiplier); + copyToGun.knockback *= 1f - num * (1f - copyFromGun.knockback); + copyToGun.projectileSpeed *= copyFromGun.projectileSpeed; + copyToGun.projectielSimulatonSpeed *= copyFromGun.projectielSimulatonSpeed; + copyToGun.gravity *= copyFromGun.gravity; + copyToGun.multiplySpread *= copyFromGun.multiplySpread; + copyToGun.attackSpeed *= copyFromGun.attackSpeed; + copyToGun.bodyRecoil *= copyFromGun.recoilMuiltiplier; + copyToGun.speedMOnBounce *= copyFromGun.speedMOnBounce; + copyToGun.dmgMOnBounce *= copyFromGun.dmgMOnBounce; + copyToGun.bulletDamageMultiplier *= copyFromGun.bulletDamageMultiplier; + copyToGun.spread += copyFromGun.spread; + copyToGun.drag += copyFromGun.drag; + copyToGun.timeBetweenBullets += copyFromGun.timeBetweenBullets; + copyToGun.dragMinSpeed += copyFromGun.dragMinSpeed; + copyToGun.evenSpread += copyFromGun.evenSpread; + copyToGun.numberOfProjectiles += copyFromGun.numberOfProjectiles; + copyToGun.reflects += copyFromGun.reflects; + copyToGun.smartBounce += copyFromGun.smartBounce; + copyToGun.bulletPortal += copyFromGun.bulletPortal; + copyToGun.randomBounces += copyFromGun.randomBounces; + copyToGun.bursts += copyFromGun.bursts; + copyToGun.slow += copyFromGun.slow; + copyToGun.overheatMultiplier += copyFromGun.overheatMultiplier; + copyToGun.projectileSize += copyFromGun.projectileSize; + copyToGun.percentageDamage += copyFromGun.percentageDamage; + copyToGun.damageAfterDistanceMultiplier *= copyFromGun.damageAfterDistanceMultiplier; + copyToGun.timeToReachFullMovementMultiplier *= copyFromGun.timeToReachFullMovementMultiplier; + copyToGun.cos += copyFromGun.cos; + if (copyFromGun.dontAllowAutoFire) + { + copyToGun.dontAllowAutoFire = true; + } + if (copyFromGun.destroyBulletAfter != 0f) + { + copyToGun.destroyBulletAfter = copyFromGun.destroyBulletAfter; + } + copyToGun.chargeSpreadTo += copyFromGun.chargeSpreadTo; + copyToGun.chargeSpeedTo += copyFromGun.chargeSpeedTo; + copyToGun.chargeEvenSpreadTo += copyFromGun.chargeEvenSpreadTo; + copyToGun.chargeNumberOfProjectilesTo += copyFromGun.chargeNumberOfProjectilesTo; + copyToGun.chargeRecoilTo += copyFromGun.chargeRecoilTo; + if (copyFromGun.projectileColor != Color.black) + { + if (copyToGun.projectileColor == Color.black) + { + copyToGun.projectileColor = copyFromGun.projectileColor; + } + float r = Mathf.Pow((copyToGun.projectileColor.r * copyToGun.projectileColor.r + copyFromGun.projectileColor.r * copyFromGun.projectileColor.r) / 2f, 0.5f); + float g = Mathf.Pow((copyToGun.projectileColor.g * copyToGun.projectileColor.g + copyFromGun.projectileColor.g * copyFromGun.projectileColor.g) / 2f, 0.5f); + float b = Mathf.Pow((copyToGun.projectileColor.b * copyToGun.projectileColor.b + copyFromGun.projectileColor.b * copyFromGun.projectileColor.b) / 2f, 0.5f); + Color rgbColor = new Color(r, g, b, 1f); + float H = 0f; + float S = 0f; + float V = 0f; + Color.RGBToHSV(rgbColor, out H, out S, out V); + S = 1f; + V = 1f; + copyToGun.projectileColor = Color.HSVToRGB(H, S, V); + } + List<ObjectsToSpawn> list = new List<ObjectsToSpawn>(); + for (int i = 0; i < copyToGun.objectsToSpawn.Length; i++) + { + list.Add(copyToGun.objectsToSpawn[i]); + } + for (int j = 0; j < copyFromGun.objectsToSpawn.Length; j++) + { + bool flag = false; + for (int k = 0; k < list.Count; k++) + { + if ((bool)list[k].effect && (bool)copyFromGun.objectsToSpawn[j].effect) + { + if (list[k].effect.name == copyFromGun.objectsToSpawn[j].effect.name && list[k].scaleStacks) + { + list[k].stacks++; + flag = true; + } + } + else if ((bool)list[k].AddToProjectile && (bool)copyFromGun.objectsToSpawn[j].AddToProjectile && list[k].AddToProjectile.name == copyFromGun.objectsToSpawn[j].AddToProjectile.name && list[k].scaleStacks) + { + list[k].stacks++; + flag = true; + } + } + if (!flag) + { + list.Add(copyFromGun.objectsToSpawn[j]); + } + } + copyToGun.objectsToSpawn = list.ToArray(); + if (copyFromGun.useCharge) + { + copyToGun.useCharge = copyFromGun.useCharge; + } + copyToGun.soundGun.AddSoundShotModifier(copyFromGun.soundShotModifier); + copyToGun.soundGun.AddSoundImpactModifier(copyFromGun.soundImpactModifier); + copyToGun.soundGun.RefreshSoundModifiers(); + } +} diff --git a/GameCode/ApplyRootScale.cs b/GameCode/ApplyRootScale.cs new file mode 100644 index 0000000..36ef87a --- /dev/null +++ b/GameCode/ApplyRootScale.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class ApplyRootScale : MonoBehaviour +{ + public float amount = 0.5f; + + private void Start() + { + base.transform.localScale = Vector3.Lerp(base.transform.localScale, base.transform.root.localScale, amount); + } +} diff --git a/GameCode/ArmRotator.cs b/GameCode/ArmRotator.cs new file mode 100644 index 0000000..a8f02a9 --- /dev/null +++ b/GameCode/ArmRotator.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class ArmRotator : MonoBehaviour +{ + public Vector3 rotation; + + private void Start() + { + base.transform.localEulerAngles = rotation; + } +} diff --git a/GameCode/ArtHandler.cs b/GameCode/ArtHandler.cs new file mode 100644 index 0000000..1421de0 --- /dev/null +++ b/GameCode/ArtHandler.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class ArtHandler : MonoBehaviour +{ + public ArtInstance[] arts; + + public PostProcessVolume volume; + + public static ArtHandler instance; + + private ColorGrading colorGrading; + + private int currentArt = -1; + + private void Awake() + { + instance = this; + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.LeftShift)) + { + NextArt(); + } + } + + public void NextArt() + { + for (int i = 0; i < arts.Length; i++) + { + arts[i].TogglePart(on: false); + } + int num = Random.Range(0, arts.Length); + if (num >= arts.Length) + { + num = 0; + } + ApplyArt(arts[num]); + } + + private void ApplyArt(ArtInstance art) + { + art.TogglePart(on: true); + currentArt = GetArtID(art); + volume.profile = art.profile; + } + + public void SetSpecificArt(ArtInstance art) + { + ApplyArt(art); + } + + public void ApplyPost(PostProcessProfile profileToSet) + { + volume.profile = profileToSet; + } + + public void SetSpecificArt(string artName) + { + for (int i = 0; i < arts.Length; i++) + { + if (arts[i].profile.name == artName) + { + ApplyArt(arts[i]); + break; + } + } + } + + private int GetArtID(ArtInstance art) + { + int result = -1; + for (int i = 0; i < arts.Length; i++) + { + if (art == arts[i]) + { + result = i; + } + } + return result; + } +} diff --git a/GameCode/ArtInstance.cs b/GameCode/ArtInstance.cs new file mode 100644 index 0000000..49c24b3 --- /dev/null +++ b/GameCode/ArtInstance.cs @@ -0,0 +1,23 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +[Serializable] +public class ArtInstance +{ + [FoldoutGroup("$profile", 0)] + public PostProcessProfile profile; + + [FoldoutGroup("$profile", 0)] + public ParticleSystem[] parts; + + public void TogglePart(bool on) + { + for (int i = 0; i < parts.Length; i++) + { + parts[i].gameObject.SetActive(on); + parts[i].Play(); + } + } +} diff --git a/GameCode/AttackLevel.cs b/GameCode/AttackLevel.cs new file mode 100644 index 0000000..78c92dd --- /dev/null +++ b/GameCode/AttackLevel.cs @@ -0,0 +1,53 @@ +using System; +using UnityEngine; + +public class AttackLevel : MonoBehaviour +{ + public int attackLevel = 1; + + public float levelScaleM = 0.7f; + + public Action<int> LevelUpAction; + + private void Start() + { + SpawnedAttack componentInParent = GetComponentInParent<SpawnedAttack>(); + if ((bool)componentInParent) + { + attackLevel = componentInParent.attackLevel; + } + bool flag = false; + AttackLevel[] componentsInChildren = base.transform.root.GetComponentsInChildren<AttackLevel>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (!(componentsInChildren[i] == this) && componentsInChildren[i].gameObject.name == base.gameObject.name) + { + componentsInChildren[i].LevelUp(); + flag = true; + } + } + if (flag) + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + public float LevelScale() + { + return 1f + ((float)attackLevel - 1f) * levelScaleM; + } + + public int LevelsUp() + { + return attackLevel - 1; + } + + public void LevelUp() + { + attackLevel++; + if (LevelUpAction != null) + { + LevelUpAction(attackLevel); + } + } +} diff --git a/GameCode/AttackTrigger.cs b/GameCode/AttackTrigger.cs new file mode 100644 index 0000000..a452de0 --- /dev/null +++ b/GameCode/AttackTrigger.cs @@ -0,0 +1,43 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class AttackTrigger : MonoBehaviour +{ + public bool triggerOnEveryShot = true; + + public UnityEvent triggerEvent; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(gun.ShootPojectileAction, new Action<GameObject>(Shoot)); + data.weaponHandler.gun.AddAttackAction(Attack); + } + + private void OnDestroy() + { + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Remove(gun.ShootPojectileAction, new Action<GameObject>(Shoot)); + data.weaponHandler.gun.RemoveAttackAction(Attack); + } + + public void Attack() + { + if (!triggerOnEveryShot) + { + triggerEvent.Invoke(); + } + } + + public void Shoot(GameObject projectile) + { + if (triggerOnEveryShot) + { + triggerEvent.Invoke(); + } + } +} diff --git a/GameCode/AudioModifyer.cs b/GameCode/AudioModifyer.cs new file mode 100644 index 0000000..ddfaad9 --- /dev/null +++ b/GameCode/AudioModifyer.cs @@ -0,0 +1,9 @@ +using System; + +[Serializable] +public class AudioModifyer +{ + public CardAudioModifier modifier; + + public int stacks; +} diff --git a/GameCode/Background.cs b/GameCode/Background.cs new file mode 100644 index 0000000..0b694c7 --- /dev/null +++ b/GameCode/Background.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +public class Background : MonoBehaviour +{ + private ParticleSystem[] parts; + + private bool hasBeenInitiated; + + private void Init() + { + parts = GetComponentsInChildren<ParticleSystem>(); + hasBeenInitiated = true; + } + + public void ToggleBackground(bool on) + { + if (!hasBeenInitiated) + { + Init(); + } + for (int i = 0; i < parts.Length; i++) + { + if (on) + { + parts[i].Play(); + } + else + { + parts[i].Stop(); + } + } + } +} diff --git a/GameCode/BackgroundHandler.cs b/GameCode/BackgroundHandler.cs new file mode 100644 index 0000000..90823de --- /dev/null +++ b/GameCode/BackgroundHandler.cs @@ -0,0 +1,39 @@ +using System.Collections; +using UnityEngine; + +public class BackgroundHandler : MonoBehaviour +{ + private Background[] backgrounds; + + private float untilSwitch; + + private void Start() + { + backgrounds = GetComponentsInChildren<Background>(includeInactive: true); + } + + private void Update() + { + untilSwitch -= TimeHandler.deltaTime; + if (untilSwitch < 0f) + { + SwitchBackground(); + } + } + + private void SwitchBackground() + { + untilSwitch = Random.Range(30, 60); + for (int i = 0; i < backgrounds.Length; i++) + { + backgrounds[i].ToggleBackground(on: false); + } + StartCoroutine(StartBackGroundSoon()); + } + + private IEnumerator StartBackGroundSoon() + { + yield return new WaitForSeconds(5f); + backgrounds[Random.Range(0, backgrounds.Length)].ToggleBackground(on: true); + } +} diff --git a/GameCode/BeamAttack.cs b/GameCode/BeamAttack.cs new file mode 100644 index 0000000..a05ee28 --- /dev/null +++ b/GameCode/BeamAttack.cs @@ -0,0 +1,145 @@ +using System.Collections; +using UnityEngine; + +public class BeamAttack : MonoBehaviour +{ + public float selfHeal; + + public float damage = 8f; + + public float force = 2500f; + + public float scalingForce; + + public float overTimeForce; + + public float overTimeScalingForce; + + public float overTimeDrag; + + public float effectOverTimeTime = 0.1f; + + public float interval = 0.2f; + + public float slow; + + public float maxSlow = 1f; + + public Color dmgColor; + + private Player attacker; + + private Player thisPlayer; + + private LineEffect[] lineEffects; + + private ParticleSystem[] parts; + + private CharacterStatModifiers stats; + + private float scaleMultiplier = 1f; + + private SpawnedAttack spawnedAttack; + + private float counter; + + private void Start() + { + lineEffects = GetComponentsInChildren<LineEffect>(includeInactive: true); + parts = GetComponentsInChildren<ParticleSystem>(); + thisPlayer = GetComponentInParent<Player>(); + stats = thisPlayer.GetComponent<CharacterStatModifiers>(); + attacker = PlayerManager.instance.GetOtherPlayer(thisPlayer); + scaleMultiplier = base.transform.localScale.x; + spawnedAttack = GetComponentInParent<SpawnedAttack>(); + if (thisPlayer == spawnedAttack.spawner) + { + Object.Destroy(base.gameObject); + } + } + + private void Update() + { + if (!attacker || !thisPlayer) + { + return; + } + counter += TimeHandler.deltaTime; + if (!(counter > interval)) + { + return; + } + CanSeeInfo canSeeInfo = PlayerManager.instance.CanSeePlayer(attacker.transform.position, thisPlayer); + if (canSeeInfo.canSee) + { + Vector2 vector = thisPlayer.transform.position - attacker.transform.position; + Vector2 normalized = vector.normalized; + if (force != 0f) + { + thisPlayer.data.healthHandler.TakeForce(normalized * scaleMultiplier * force); + } + if (scalingForce != 0f) + { + thisPlayer.data.healthHandler.TakeForce(vector * scaleMultiplier * scalingForce); + } + if (damage != 0f) + { + thisPlayer.data.healthHandler.TakeDamage(damage * scaleMultiplier * normalized, base.transform.position, dmgColor, null, attacker); + } + if (selfHeal != 0f) + { + attacker.data.healthHandler.Heal(selfHeal * scaleMultiplier); + } + for (int i = 0; i < lineEffects.Length; i++) + { + lineEffects[i].Play(attacker.transform, thisPlayer.transform); + } + StartCoroutine(DoOverTimeEffects(attacker)); + if (slow > 0f && (bool)stats) + { + stats.AddSlowAddative(slow * scaleMultiplier, maxSlow); + } + } + else + { + for (int j = 0; j < lineEffects.Length; j++) + { + lineEffects[j].Play(attacker.transform, canSeeInfo.hitPoint); + } + for (int k = 0; k < parts.Length; k++) + { + parts[k].transform.position = canSeeInfo.hitPoint; + parts[k].transform.localScale = Vector3.one * scaleMultiplier; + parts[k].Play(); + } + } + counter = 0f; + } + + private IEnumerator DoOverTimeEffects(Player attacker) + { + float c = 0f; + while (c < effectOverTimeTime) + { + c += TimeHandler.deltaTime; + if ((bool)attacker && (bool)thisPlayer) + { + Vector2 vector = thisPlayer.transform.position - attacker.transform.position; + Vector2 normalized = vector.normalized; + if (overTimeForce != 0f) + { + thisPlayer.data.healthHandler.TakeForce(normalized * scaleMultiplier * TimeHandler.deltaTime * overTimeForce); + } + if (overTimeScalingForce != 0f) + { + thisPlayer.data.healthHandler.TakeForce(vector * scaleMultiplier * TimeHandler.deltaTime * overTimeScalingForce, ForceMode2D.Force); + } + if (overTimeDrag > 0f) + { + thisPlayer.data.playerVel.AddForce(-thisPlayer.data.playerVel.velocity * Mathf.Clamp(TimeHandler.deltaTime * scaleMultiplier * overTimeDrag, 0f, 0.95f), ForceMode2D.Force); + } + } + yield return null; + } + } +} diff --git a/GameCode/BezierCurve.cs b/GameCode/BezierCurve.cs new file mode 100644 index 0000000..5fb99b8 --- /dev/null +++ b/GameCode/BezierCurve.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public static class BezierCurve +{ + public static Vector3 CubicBezier(Vector3 Start, Vector3 _P1, Vector3 _P2, Vector3 end, float _t) + { + return (1f - _t) * QuadraticBezier(Start, _P1, _P2, _t) + _t * QuadraticBezier(_P1, _P2, end, _t); + } + + public static Vector3 QuadraticBezier(Vector3 start, Vector3 _P1, Vector3 end, float _t) + { + return (1f - _t) * LinearBezier(start, _P1, _t) + _t * LinearBezier(_P1, end, _t); + } + + public static Vector3 LinearBezier(Vector3 start, Vector3 end, float _t) + { + return (1f - _t) * start + _t * end; + } +} diff --git a/GameCode/BlinkStep.cs b/GameCode/BlinkStep.cs new file mode 100644 index 0000000..4a52737 --- /dev/null +++ b/GameCode/BlinkStep.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +public class BlinkStep : MonoBehaviour +{ + public float interval = 0.29f; + + private CharacterData data; + + private float counter; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + if (data.view.IsMine) + { + counter += TimeHandler.deltaTime; + if (counter > interval) + { + counter = 0f; + data.block.CallDoBlock(firstBlock: true, dontSetCD: true); + } + } + } +} diff --git a/GameCode/Block.cs b/GameCode/Block.cs new file mode 100644 index 0000000..b48d264 --- /dev/null +++ b/GameCode/Block.cs @@ -0,0 +1,353 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class Block : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundBlockStart; + + public SoundEvent soundBlockRecharged; + + public SoundEvent soundBlockBlocked; + + public SoundEvent soundBlockStatusEffect; + + [Header("Settings")] + public List<GameObject> objectsToSpawn = new List<GameObject>(); + + public float sinceBlock; + + private GeneralInput input; + + public ParticleSystem particle; + + public ParticleSystem reloadParticle; + + public ParticleSystem blockedPart; + + public float cooldown; + + public float counter = 1000f; + + public float cdMultiplier = 1f; + + public float cdAdd; + + public float forceToAdd; + + public float forceToAddUp; + + public bool autoBlock; + + public bool blockedThisFrame; + + public int additionalBlocks; + + public float healing; + + private float timeBetweenBlocks = 0.2f; + + private CharacterData data; + + private HealthHandler health; + + private bool active = true; + + public Action BlockRechargeAction; + + private bool blockedLastFrame; + + public Action<BlockTrigger.BlockTriggerType> BlockAction; + + public Action<BlockTrigger.BlockTriggerType> BlockActionEarly; + + public Action<BlockTrigger.BlockTriggerType> FirstBlockActionThatDelaysOthers; + + public Action<BlockTrigger.BlockTriggerType> SuperFirstBlockAction; + + public Vector3 blockedAtPos; + + public bool delayOtherActions; + + public ParticleSystem statusBlockPart; + + private float lastStatusBlock; + + public Action<GameObject, Vector3, Vector3> BlockProjectileAction; + + public float Cooldown() + { + return (cooldown + cdAdd) * cdMultiplier; + } + + private void Start() + { + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + health = GetComponent<HealthHandler>(); + sinceBlock = 100f; + } + + private void Update() + { + if ((bool)input && data.playerVel.simulated) + { + if (!blockedLastFrame) + { + blockedThisFrame = false; + } + blockedLastFrame = false; + sinceBlock += TimeHandler.deltaTime; + counter += TimeHandler.deltaTime; + if (counter > Cooldown() && !active) + { + active = true; + reloadParticle.Play(); + BlockRechargeAction(); + SoundManager.Instance.Play(soundBlockRecharged, base.transform); + } + if (input.shieldWasPressed) + { + TryBlock(); + } + } + } + + public void DoBlockAtPosition(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 blockPos = default(Vector3), bool onlyBlockEffects = false) + { + blockedAtPos = blockPos; + RPCA_DoBlock(firstBlock, dontSetCD, triggerType, blockPos, onlyBlockEffects); + } + + internal void ResetStats() + { + objectsToSpawn = new List<GameObject>(); + sinceBlock = 10f; + cooldown = 4f; + counter = 1000f; + cdMultiplier = 1f; + cdAdd = 0f; + forceToAdd = 0f; + forceToAddUp = 0f; + autoBlock = false; + blockedThisFrame = false; + additionalBlocks = 0; + healing = 0f; + delayOtherActions = false; + } + + public void CallDoBlock(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 useBlockPos = default(Vector3), bool onlyBlockEffects = false) + { + data.view.RPC("RPCA_DoBlock", RpcTarget.All, firstBlock, dontSetCD, (int)triggerType, useBlockPos, onlyBlockEffects); + } + + [PunRPC] + public void RPCA_DoBlock(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 useBlockPos = default(Vector3), bool onlyBlockEffects = false) + { + if (triggerType == BlockTrigger.BlockTriggerType.Default && firstBlock) + { + for (int i = 0; i < additionalBlocks; i++) + { + StartCoroutine(DelayBlock(((float)i + 1f) * timeBetweenBlocks)); + } + } + StartCoroutine(IDoBlock(firstBlock, dontSetCD, triggerType, useBlockPos, onlyBlockEffects)); + } + + private IEnumerator IDoBlock(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 useBlockPos = default(Vector3), bool onlyBlockEffects = false) + { + active = false; + Vector3 position = base.transform.position; + if (useBlockPos != Vector3.zero) + { + base.transform.position = useBlockPos; + } + if (SuperFirstBlockAction != null) + { + SuperFirstBlockAction(triggerType); + } + if (FirstBlockActionThatDelaysOthers != null) + { + FirstBlockActionThatDelaysOthers(triggerType); + } + if (useBlockPos != Vector3.zero) + { + base.transform.position = position; + } + if (!onlyBlockEffects) + { + sinceBlock = 0f; + } + if (delayOtherActions) + { + yield return new WaitForSeconds(0.2f); + } + position = base.transform.position; + if (useBlockPos != Vector3.zero) + { + base.transform.position = useBlockPos; + } + if (BlockActionEarly != null) + { + BlockActionEarly(triggerType); + } + if (BlockAction != null) + { + BlockAction(triggerType); + } + if (firstBlock) + { + if (forceToAdd != 0f) + { + health.TakeForce(data.hand.transform.forward * forceToAdd * data.playerVel.mass * 0.01f); + } + if (forceToAddUp != 0f) + { + health.TakeForce(Vector3.up * forceToAddUp * data.playerVel.mass * 0.01f); + } + } + blockedLastFrame = true; + bool flag = false; + for (int i = 0; i < data.currentCards.Count; i++) + { + if (data.currentCards[i].soundDisableBlockBasic) + { + flag = true; + break; + } + } + if (!flag && triggerType != BlockTrigger.BlockTriggerType.ShieldCharge) + { + SoundManager.Instance.Play(soundBlockStart, base.transform); + } + if (!onlyBlockEffects) + { + particle.Play(); + } + if (!dontSetCD) + { + counter = 0f; + } + GamefeelManager.GameFeel(UnityEngine.Random.insideUnitCircle.normalized * 1f); + if (!onlyBlockEffects) + { + sinceBlock = 0f; + } + Spawn(); + health.Heal(healing); + if (useBlockPos != Vector3.zero) + { + base.transform.position = position; + } + } + + public void ShowStatusEffectBlock() + { + if (!(Time.unscaledTime < lastStatusBlock + 0.25f) && data.view.IsMine) + { + lastStatusBlock = Time.unscaledTime; + data.view.RPC("RPCA_ShowStatusEffectBlock", RpcTarget.All); + } + } + + [PunRPC] + public void RPCA_ShowStatusEffectBlock() + { + SoundManager.Instance.Play(soundBlockStatusEffect, base.transform); + statusBlockPart.Play(); + } + + public void TryBlock() + { + if (!(counter < Cooldown())) + { + RPCA_DoBlock(firstBlock: true); + counter = 0f; + } + } + + private IEnumerator DelayBlock(float t) + { + yield return new WaitForSeconds(t); + yield return new WaitForEndOfFrame(); + RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.Echo); + } + + public void Spawn() + { + for (int i = 0; i < objectsToSpawn.Count; i++) + { + SpawnedAttack component = UnityEngine.Object.Instantiate(objectsToSpawn[i], base.transform.position, Quaternion.identity).GetComponent<SpawnedAttack>(); + if ((bool)component) + { + component.spawner = GetComponent<Player>(); + } + } + } + + public void blocked(GameObject projectile, Vector3 forward, Vector3 hitPos) + { + SoundManager.Instance.Play(soundBlockBlocked, base.transform); + projectile.GetComponent<ProjectileHit>().RemoveOwnPlayerFromPlayersHit(); + projectile.GetComponent<ProjectileHit>().AddPlayerToHeld(GetComponent<HealthHandler>()); + projectile.GetComponent<MoveTransform>().velocity *= -1f; + projectile.GetComponent<RayCastTrail>().WasBlocked(); + blockedPart.transform.position = hitPos + base.transform.forward * 5f; + blockedPart.transform.rotation = Quaternion.LookRotation(-forward * 1.5f); + GamefeelManager.GameFeel(forward); + blockedPart.Play(); + SpawnedAttack componentInParent = projectile.GetComponentInParent<SpawnedAttack>(); + if ((!componentInParent || !(componentInParent.spawner.gameObject == base.transform.root.gameObject)) && BlockProjectileAction != null) + { + BlockProjectileAction(projectile, forward, hitPos); + } + } + + public void ResetCD(bool soundPlay) + { + active = true; + reloadParticle.Play(); + counter = Cooldown() + 1f; + if (soundPlay) + { + SoundManager.Instance.Play(soundBlockRecharged, base.transform); + } + } + + public bool TryBlockMe(GameObject toBlock, Vector3 forward, Vector3 hitPos) + { + if (sinceBlock < 0.3f) + { + blocked(toBlock, forward, hitPos); + sinceBlock = 0f; + particle.Play(); + return true; + } + return false; + } + + public void DoBlock(GameObject toBlock, Vector3 forward, Vector3 hitPos) + { + sinceBlock = 0f; + blocked(toBlock, forward, hitPos); + particle.Play(); + } + + public bool IsBlocking() + { + if (sinceBlock < 0.3f) + { + ShowStatusEffectBlock(); + } + return sinceBlock < 0.3f; + } + + public bool IsOnCD() + { + return counter < Cooldown(); + } +} diff --git a/GameCode/BlockEffect.cs b/GameCode/BlockEffect.cs new file mode 100644 index 0000000..3cc771c --- /dev/null +++ b/GameCode/BlockEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class BlockEffect : MonoBehaviour +{ + public abstract void DoBlockedProjectile(GameObject projectile, Vector3 forward, Vector3 hitPos); +} diff --git a/GameCode/BlockEffectCounter.cs b/GameCode/BlockEffectCounter.cs new file mode 100644 index 0000000..56c7e39 --- /dev/null +++ b/GameCode/BlockEffectCounter.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class BlockEffectCounter : BlockEffect +{ + public int ownAttacksToSendBack; + + private SpawnObjectEffect spawn; + + private void Start() + { + spawn = GetComponentInParent<SpawnObjectEffect>(); + } + + public override void DoBlockedProjectile(GameObject projectile, Vector3 forward, Vector3 hitPos) + { + for (int i = 0; i < ownAttacksToSendBack; i++) + { + spawn.DoEffect(forward); + } + } +} diff --git a/GameCode/BlockRechargeUI.cs b/GameCode/BlockRechargeUI.cs new file mode 100644 index 0000000..d2ad92a --- /dev/null +++ b/GameCode/BlockRechargeUI.cs @@ -0,0 +1,20 @@ +using UnityEngine; +using UnityEngine.UI; + +public class BlockRechargeUI : MonoBehaviour +{ + private Block block; + + private Image img; + + private void Start() + { + img = GetComponentInChildren<Image>(); + block = GetComponentInParent<Block>(); + } + + private void Update() + { + img.fillAmount = block.counter / block.Cooldown(); + } +} diff --git a/GameCode/BlockTrigger.cs b/GameCode/BlockTrigger.cs new file mode 100644 index 0000000..604c466 --- /dev/null +++ b/GameCode/BlockTrigger.cs @@ -0,0 +1,140 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class BlockTrigger : MonoBehaviour +{ + public enum BlockTriggerType + { + Default, + None, + ShieldCharge, + Echo, + Empower + } + + public UnityEvent triggerEvent; + + public UnityEvent triggerEventEarly; + + public bool delayOtherActions; + + public UnityEvent triggerFirstBlockThatDelaysOthers; + + public UnityEvent triggerSuperFirstBlock; + + public UnityEvent successfulBlockEvent; + + public UnityEvent blockRechargeEvent; + + private BlockEffect[] effects; + + public float cooldown; + + private float lastTriggerTime = -5f; + + public BlockTriggerType blackListedType = BlockTriggerType.None; + + public float cooldownSuccess; + + private float lastTriggerTimeSuccessful = -5f; + + private void Start() + { + effects = GetComponents<BlockEffect>(); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.SuperFirstBlockAction, new Action<BlockTriggerType>(DoSuperFirstBlock)); + componentInParent.FirstBlockActionThatDelaysOthers = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.FirstBlockActionThatDelaysOthers, new Action<BlockTriggerType>(DoFirstBlockThatDelaysOthers)); + componentInParent.BlockAction = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.BlockAction, new Action<BlockTriggerType>(DoBlock)); + componentInParent.BlockActionEarly = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.BlockActionEarly, new Action<BlockTriggerType>(DoBlockEarly)); + componentInParent.BlockProjectileAction = (Action<GameObject, Vector3, Vector3>)Delegate.Combine(componentInParent.BlockProjectileAction, new Action<GameObject, Vector3, Vector3>(DoBlockedProjectile)); + componentInParent.BlockRechargeAction = (Action)Delegate.Combine(componentInParent.BlockRechargeAction, new Action(DoBlockRecharge)); + if (delayOtherActions) + { + GetComponentInParent<Block>().delayOtherActions = true; + } + } + + private void OnDestroy() + { + Block componentInParent = GetComponentInParent<Block>(); + if ((bool)componentInParent && componentInParent.SuperFirstBlockAction != null) + { + componentInParent.SuperFirstBlockAction = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.SuperFirstBlockAction, new Action<BlockTriggerType>(DoSuperFirstBlock)); + } + if ((bool)componentInParent && componentInParent.FirstBlockActionThatDelaysOthers != null) + { + componentInParent.FirstBlockActionThatDelaysOthers = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.FirstBlockActionThatDelaysOthers, new Action<BlockTriggerType>(DoFirstBlockThatDelaysOthers)); + } + if ((bool)componentInParent && componentInParent.BlockAction != null) + { + componentInParent.BlockAction = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.BlockAction, new Action<BlockTriggerType>(DoBlock)); + } + if ((bool)componentInParent && componentInParent.BlockActionEarly != null) + { + componentInParent.BlockActionEarly = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.BlockActionEarly, new Action<BlockTriggerType>(DoBlockEarly)); + } + if ((bool)componentInParent && componentInParent.BlockProjectileAction != null) + { + componentInParent.BlockProjectileAction = (Action<GameObject, Vector3, Vector3>)Delegate.Remove(componentInParent.BlockProjectileAction, new Action<GameObject, Vector3, Vector3>(DoBlockedProjectile)); + } + if ((bool)componentInParent && componentInParent.BlockRechargeAction != null) + { + componentInParent.BlockRechargeAction = (Action)Delegate.Remove(componentInParent.BlockRechargeAction, new Action(DoBlockRecharge)); + } + } + + public void DoSuperFirstBlock(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerSuperFirstBlock.Invoke(); + } + } + + public void DoFirstBlockThatDelaysOthers(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerFirstBlockThatDelaysOthers.Invoke(); + } + } + + public void DoBlockEarly(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerEventEarly.Invoke(); + } + } + + public void DoBlock(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerEvent.Invoke(); + } + } + + public void DoBlockedProjectile(GameObject projectile, Vector3 forward, Vector3 hitPos) + { + if (!(lastTriggerTimeSuccessful + cooldownSuccess > Time.time)) + { + lastTriggerTimeSuccessful = Time.time; + successfulBlockEvent.Invoke(); + for (int i = 0; i < effects.Length; i++) + { + effects[i].DoBlockedProjectile(projectile, forward, hitPos); + } + } + } + + public void DoBlockRecharge() + { + blockRechargeEvent.Invoke(); + } +} diff --git a/GameCode/BlurPost.cs b/GameCode/BlurPost.cs new file mode 100644 index 0000000..1e10746 --- /dev/null +++ b/GameCode/BlurPost.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +[ExecuteInEditMode] +public class BlurPost : MonoBehaviour +{ + [SerializeField] + private Material postprocessMaterial; + + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height); + Graphics.Blit(source, temporary, postprocessMaterial, 0); + Graphics.Blit(temporary, destination, postprocessMaterial, 1); + RenderTexture.ReleaseTemporary(temporary); + } +} diff --git a/GameCode/BounceEffect.cs b/GameCode/BounceEffect.cs new file mode 100644 index 0000000..ff98414 --- /dev/null +++ b/GameCode/BounceEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class BounceEffect : MonoBehaviour +{ + public abstract void DoBounce(HitInfo hit); +} diff --git a/GameCode/BounceEffectRetarget.cs b/GameCode/BounceEffectRetarget.cs new file mode 100644 index 0000000..8e1ef79 --- /dev/null +++ b/GameCode/BounceEffectRetarget.cs @@ -0,0 +1,103 @@ +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class BounceEffectRetarget : BounceEffect +{ + [Header("Sound")] + public SoundEvent soundTargetBounceTargetPlayer; + + private MoveTransform move; + + private PhotonView view; + + private void Start() + { + view = GetComponentInParent<PhotonView>(); + move = GetComponentInParent<MoveTransform>(); + GetComponentInParent<ChildRPC>().childRPCsVector2.Add("TargetBounce", SetNewVel); + GetComponentInParent<ChildRPC>().childRPCsInt.Add("TargetBounceLine", DrawLineTo); + } + + public override void DoBounce(HitInfo hit) + { + StartCoroutine(DelayMove(hit)); + } + + private void ActuallyDoBounce(int playerId) + { + Player playerWithID = PlayerManager.instance.GetPlayerWithID(playerId); + if ((bool)playerWithID) + { + GetComponentInParent<ChildRPC>().CallFunction("TargetBounce", (playerWithID.data.playerVel.position + Vector2.up * move.GetUpwardsCompensation(base.transform.position, playerWithID.data.playerVel.position) - (Vector2)base.transform.position).normalized * move.velocity.magnitude); + SoundManager.Instance.PlayAtPosition(soundTargetBounceTargetPlayer, SoundManager.Instance.GetTransform(), base.transform); + } + else + { + GetComponentInParent<ChildRPC>().CallFunction("TargetBounce", move.velocity); + } + } + + private void SetNewVel(Vector2 newVel) + { + move.enabled = true; + move.velocity = newVel; + } + + private Player FindTarget(HitInfo hit) + { + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position + (Vector3)hit.normal * 0.1f); + if (PlayerManager.instance.CanSeePlayer(base.transform.position, closestPlayer).canSee) + { + return closestPlayer; + } + return null; + } + + private IEnumerator DelayMove(HitInfo hit) + { + Player p = FindTarget(hit); + if ((bool)p && view.IsMine) + { + GetComponentInParent<ChildRPC>().CallFunction("TargetBounceLine", p.playerID); + } + move.enabled = false; + if ((bool)hit.rigidbody) + { + move.GetComponent<RayCastTrail>().IgnoreRigFor(hit.rigidbody, 0.5f); + } + yield return new WaitForSeconds(0.1f); + if (view.IsMine) + { + if ((bool)p) + { + ActuallyDoBounce(p.playerID); + } + else + { + ActuallyDoBounce(-1); + } + } + } + + private void DrawLineTo(int playerID) + { + Player playerWithID = PlayerManager.instance.GetPlayerWithID(playerID); + if ((bool)playerWithID) + { + StartCoroutine(DrawLine(playerWithID.transform)); + } + } + + private IEnumerator DrawLine(Transform target) + { + LineEffect line = GetComponentInChildren<LineEffect>(includeInactive: true); + line.StartDraw(); + while ((bool)line) + { + line.DrawLine(base.transform.position, target.position); + yield return null; + } + } +} diff --git a/GameCode/BounceTrigger.cs b/GameCode/BounceTrigger.cs new file mode 100644 index 0000000..8d7a1b5 --- /dev/null +++ b/GameCode/BounceTrigger.cs @@ -0,0 +1,22 @@ +using System; +using UnityEngine; + +public class BounceTrigger : MonoBehaviour +{ + private BounceEffect[] bounceEffects; + + private void Start() + { + bounceEffects = GetComponents<BounceEffect>(); + RayHitReflect componentInParent = GetComponentInParent<RayHitReflect>(); + componentInParent.reflectAction = (Action<HitInfo>)Delegate.Combine(componentInParent.reflectAction, new Action<HitInfo>(Reflect)); + } + + public void Reflect(HitInfo hit) + { + for (int i = 0; i < bounceEffects.Length; i++) + { + bounceEffects[i].DoBounce(hit); + } + } +} diff --git a/GameCode/BrodalAIController.cs b/GameCode/BrodalAIController.cs new file mode 100644 index 0000000..1d0d60f --- /dev/null +++ b/GameCode/BrodalAIController.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class BrodalAIController : MonoBehaviour +{ + private PlayerAPI m_playerAPI; + + private int m_sampleCount = 250; + + private float m_sampleSize; + + private LayerMask m_layerMask; + + private Dictionary<Guid, Platform> m_platforms = new Dictionary<Guid, Platform>(); + + private Platform m_currentPlatform; + + private Vector2 m_pointOnLine; + + private bool inited; + + private void Start() + { + m_playerAPI = GetComponentInParent<PlayerAPI>(); + HealthHandler healthHandler = m_playerAPI.player.data.healthHandler; + healthHandler.delayedReviveAction = (Action)Delegate.Combine(healthHandler.delayedReviveAction, new Action(Init)); + } + + public void Init() + { + m_platforms.Clear(); + m_currentPlatform = null; + PlotPlatforms(); + RaycastMap(); + PostProcessPlatforms(); + inited = true; + Debug.Log("Revived"); + } + + private void PostProcessPlatforms() + { + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + platform.Value.PostProcessPlatformPoints(); + } + } + + private void PlotPlatforms() + { + BoxCollider2D[] array = UnityEngine.Object.FindObjectsOfType<BoxCollider2D>(); + foreach (BoxCollider2D boxCollider2D in array) + { + if (boxCollider2D.gameObject.layer == LayerMask.GetMask("Player")) + { + continue; + } + bool flag = false; + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + foreach (BoxCollider2D boxCollider in platform.Value.BoxColliders) + { + bool flag2 = false; + if (boxCollider2D.bounds.Intersects(boxCollider.bounds)) + { + flag2 = true; + } + if (flag2) + { + m_platforms[platform.Key].AddCollider(boxCollider2D); + flag = true; + break; + } + } + if (flag) + { + break; + } + } + if (!flag) + { + Guid key = Guid.NewGuid(); + m_platforms.Add(key, new Platform()); + m_platforms[key].AddCollider(boxCollider2D); + } + } + } + + private void MergePlatforms() + { + } + + private void RaycastMap() + { + m_layerMask = LayerMask.GetMask("Default"); + Camera component = MainCam.instance.transform.GetComponent<Camera>(); + Vector3 vector = component.ViewportToWorldPoint(new Vector2(0f, 1f)); + Vector3 vector2 = component.ViewportToWorldPoint(new Vector2(1f, 1f)); + m_sampleSize = (vector2.x - vector.x) / (float)m_sampleCount; + for (float num = vector.x; num < vector2.x; num += m_sampleSize) + { + RaycastHit2D[] array = Physics2D.RaycastAll(new Vector3(num, vector.y, 0f), Vector2.down, 9999f, m_layerMask); + for (int i = 0; i < array.Length; i++) + { + RaycastHit2D raycastHit2D = array[i]; + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + if (platform.Value.ContainsCollider((BoxCollider2D)raycastHit2D.collider)) + { + m_platforms[platform.Key].AddPlatformPoint(raycastHit2D.point); + break; + } + } + } + } + } + + private void Update() + { + if (inited) + { + FindClosestPlatform(base.transform.position); + Vector2 vector = m_playerAPI.OtherPlayerPosition() - base.transform.position; + float magnitude = vector.magnitude; + vector.Normalize(); + Vector2 normalized = (vector + new Vector2(0f, 0.15f)).normalized; + m_playerAPI.SetAimDirection(normalized); + Vector2 position = new Vector2(base.transform.position.x, base.transform.position.y) + vector * 1.5f; + bool num = m_currentPlatform.IsPositionOutsidePlatform(position); + m_playerAPI.Move(m_playerAPI.TowardsOtherPlayer()); + if (num) + { + m_playerAPI.Jump(); + } + vector.y = 0f; + vector.Normalize(); + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position, vector, 0.85f, m_layerMask); + RaycastHit2D raycastHit2D2 = Physics2D.Raycast(base.transform.position, vector, magnitude, m_layerMask); + if ((bool)raycastHit2D.collider) + { + m_playerAPI.Jump(); + } + if (raycastHit2D2.collider == null) + { + m_playerAPI.Attack(); + } + m_playerAPI.Block(); + } + } + + private void FindClosestPlatform(Vector2 position) + { + float num = float.MaxValue; + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + float closestDistance = platform.Value.GetClosestDistance(position); + if (closestDistance < num) + { + m_currentPlatform = platform.Value; + num = closestDistance; + } + } + } +} diff --git a/GameCode/BuildOnly.cs b/GameCode/BuildOnly.cs new file mode 100644 index 0000000..48988a5 --- /dev/null +++ b/GameCode/BuildOnly.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BuildOnly : MonoBehaviour +{ + private void Start() + { + if (Application.isEditor) + { + base.gameObject.SetActive(value: false); + } + } +} diff --git a/GameCode/BulletBase.cs b/GameCode/BulletBase.cs new file mode 100644 index 0000000..446970a --- /dev/null +++ b/GameCode/BulletBase.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BulletBase : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/BulletDamageEvents.cs b/GameCode/BulletDamageEvents.cs new file mode 100644 index 0000000..09dae56 --- /dev/null +++ b/GameCode/BulletDamageEvents.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class BulletDamageEvents : MonoBehaviour +{ + public DmgEvent[] damageEvents; + + public void Start() + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + for (int i = 0; i < damageEvents.Length; i++) + { + if (componentInParent.damage > damageEvents[i].dmg) + { + damageEvents[i].eventToCall.Invoke(); + } + } + } +} diff --git a/GameCode/BulletPoint.cs b/GameCode/BulletPoint.cs new file mode 100644 index 0000000..d7a9157 --- /dev/null +++ b/GameCode/BulletPoint.cs @@ -0,0 +1,56 @@ +using System; +using UnityEngine; + +public class BulletPoint : MonoBehaviour +{ + public LayerMask mask; + + private Gun gun; + + private MoveTransform move; + + private ProjectileHit hit; + + private float counter = 5f; + + private void Start() + { + gun = GetComponent<Gun>(); + Gun obj = gun; + obj.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(obj.ShootPojectileAction, new Action<GameObject>(Fire)); + } + + private void Attack() + { + gun.Attack(1f, forceAttack: true); + } + + private void Fire(GameObject projectile) + { + move = projectile.GetComponent<MoveTransform>(); + } + + private void Update() + { + if ((bool)move) + { + counter = 0f; + Vector3 vector = base.transform.position - base.transform.root.position; + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.root.position, vector, vector.magnitude, mask, -10000f); + Vector3 vector2 = base.transform.position; + if (raycastHit2D.transform != null) + { + vector2 = raycastHit2D.point - (Vector2)vector.normalized * 0.1f; + } + move.velocity = Vector2.Lerp(move.velocity, (vector2 - move.transform.position) * 50f, TimeHandler.deltaTime * 50f); + } + else + { + counter += TimeHandler.deltaTime; + if (counter > 2f) + { + Attack(); + } + } + } +} diff --git a/GameCode/BulletSurf.cs b/GameCode/BulletSurf.cs new file mode 100644 index 0000000..23579ee --- /dev/null +++ b/GameCode/BulletSurf.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BulletSurf : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/BulletWrapper.cs b/GameCode/BulletWrapper.cs new file mode 100644 index 0000000..1229787 --- /dev/null +++ b/GameCode/BulletWrapper.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BulletWrapper +{ + public float damage; + + public Vector2 velocity; + + public ProjectileHit projectileHit; + + public MoveTransform projectileMovement; +} diff --git a/GameCode/CameraZoomHandler.cs b/GameCode/CameraZoomHandler.cs new file mode 100644 index 0000000..56c8b86 --- /dev/null +++ b/GameCode/CameraZoomHandler.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class CameraZoomHandler : MonoBehaviour +{ + private Camera[] cameras; + + private void Start() + { + cameras = GetComponentsInChildren<Camera>(); + } + + private void Update() + { + float b = 20f; + if (MapManager.instance.currentMap != null) + { + b = MapManager.instance.currentMap.Map.size; + } + for (int i = 0; i < cameras.Length; i++) + { + cameras[i].orthographicSize = Mathf.Lerp(cameras[i].orthographicSize, b, Time.unscaledDeltaTime * 5f); + } + } +} diff --git a/GameCode/CanSeeInfo.cs b/GameCode/CanSeeInfo.cs new file mode 100644 index 0000000..947131d --- /dev/null +++ b/GameCode/CanSeeInfo.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public class CanSeeInfo +{ + public bool canSee; + + public Vector2 hitPoint; + + public float distance; +} diff --git a/GameCode/CapScale.cs b/GameCode/CapScale.cs new file mode 100644 index 0000000..bcb62a0 --- /dev/null +++ b/GameCode/CapScale.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class CapScale : MonoBehaviour +{ + public float min = 2f; + + public float max = 10f; + + private void Start() + { + if (base.transform.localScale.x < min) + { + base.transform.localScale = Vector3.one * min; + } + if (base.transform.localScale.x > max) + { + base.transform.localScale = Vector3.one * max; + } + } +} diff --git a/GameCode/CappedDeltaTime.cs b/GameCode/CappedDeltaTime.cs new file mode 100644 index 0000000..8bb24c6 --- /dev/null +++ b/GameCode/CappedDeltaTime.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class CappedDeltaTime : MonoBehaviour +{ + public static float time; + + private void Update() + { + time = Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.02f); + } +} diff --git a/GameCode/CardAnimation.cs b/GameCode/CardAnimation.cs new file mode 100644 index 0000000..3578ec6 --- /dev/null +++ b/GameCode/CardAnimation.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class CardAnimation : MonoBehaviour +{ +} diff --git a/GameCode/CardAudioModifier.cs b/GameCode/CardAudioModifier.cs new file mode 100644 index 0000000..f6206c0 --- /dev/null +++ b/GameCode/CardAudioModifier.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class CardAudioModifier : MonoBehaviour +{ + public enum StackType + { + RTPCValue, + PostEvent + } + + public string stackName; + + public StackType stackType; +} diff --git a/GameCode/CardBar.cs b/GameCode/CardBar.cs new file mode 100644 index 0000000..e985288 --- /dev/null +++ b/GameCode/CardBar.cs @@ -0,0 +1,95 @@ +using Sonigon; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CardBar : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCardPick; + + [Header("Settings")] + public GameObject pointer; + + [Header("Settings")] + public GameObject cardPos; + + private GameObject source; + + private CardInfo ci; + + private GameObject currentCard; + + private void Start() + { + source = base.transform.GetChild(0).gameObject; + } + + public void ClearBar() + { + if ((bool)currentCard) + { + Object.Destroy(currentCard); + } + for (int num = base.transform.childCount - 1; num >= 0; num--) + { + if (base.transform.GetChild(num).gameObject.activeSelf) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + } + } + + public void AddCard(CardInfo card) + { + SoundManager.Instance.Play(soundCardPick, base.transform); + ci = card; + GameObject obj = Object.Instantiate(source, source.transform.position, source.transform.rotation, source.transform.parent); + obj.transform.localScale = Vector3.one; + string cardName = card.cardName; + cardName = cardName.Substring(0, 2); + string text = cardName[0].ToString().ToUpper(); + if (cardName.Length > 1) + { + string text2 = cardName[1].ToString().ToLower(); + cardName = text + text2; + } + else + { + cardName = text; + } + obj.GetComponentInChildren<TextMeshProUGUI>().text = cardName; + obj.GetComponent<CardBarButton>().card = card; + obj.gameObject.SetActive(value: true); + } + + public void OnHover(CardInfo card, Vector3 hoverPos) + { + if ((bool)currentCard) + { + Object.Destroy(currentCard); + } + currentCard = CardChoice.instance.AddCardVisual(card, cardPos.transform.position); + Collider2D[] componentsInChildren = currentCard.transform.root.GetComponentsInChildren<Collider2D>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].enabled = false; + } + currentCard.GetComponentInChildren<Canvas>().sortingLayerName = "MostFront"; + currentCard.GetComponentInChildren<GraphicRaycaster>().enabled = false; + currentCard.GetComponentInChildren<SetScaleToZero>().enabled = false; + currentCard.GetComponentInChildren<SetScaleToZero>().transform.localScale = Vector3.one * 1.15f; + } + + public void StopHover() + { + if ((bool)currentCard) + { + Object.Destroy(currentCard); + } + } + + private void Update() + { + } +} diff --git a/GameCode/CardBarButton.cs b/GameCode/CardBarButton.cs new file mode 100644 index 0000000..13d9c62 --- /dev/null +++ b/GameCode/CardBarButton.cs @@ -0,0 +1,19 @@ +using UnityEngine; +using UnityEngine.EventSystems; + +public class CardBarButton : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler +{ + internal CardInfo card; + + public void OnPointerEnter(PointerEventData eventData) + { + GetComponentInParent<CardBar>().OnHover(card, base.transform.position); + base.transform.localScale = Vector3.one * 1.1f; + } + + public void OnPointerExit(PointerEventData eventData) + { + GetComponentInParent<CardBar>().StopHover(); + base.transform.localScale = Vector3.one * 1f; + } +} diff --git a/GameCode/CardBarHandler.cs b/GameCode/CardBarHandler.cs new file mode 100644 index 0000000..f6ceea2 --- /dev/null +++ b/GameCode/CardBarHandler.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class CardBarHandler : MonoBehaviour +{ + private CardBar[] cardBars; + + public static CardBarHandler instance; + + private void Start() + { + instance = this; + cardBars = GetComponentsInChildren<CardBar>(); + } + + public void AddCard(int teamId, CardInfo card) + { + cardBars[teamId].AddCard(card); + } + + public void ResetCardBards() + { + for (int i = 0; i < cardBars.Length; i++) + { + cardBars[i].ClearBar(); + } + } +} diff --git a/GameCode/CardCategories.cs b/GameCode/CardCategories.cs new file mode 100644 index 0000000..055dc4c --- /dev/null +++ b/GameCode/CardCategories.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class CardCategories : MonoBehaviour +{ +} diff --git a/GameCode/CardCategory.cs b/GameCode/CardCategory.cs new file mode 100644 index 0000000..7961b24 --- /dev/null +++ b/GameCode/CardCategory.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "Card Category", menuName = "Square Brawl/Card Category", order = 1)] +public class CardCategory : ScriptableObject +{ +} diff --git a/GameCode/CardChoice.cs b/GameCode/CardChoice.cs new file mode 100644 index 0000000..ac3ebb8 --- /dev/null +++ b/GameCode/CardChoice.cs @@ -0,0 +1,460 @@ +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using SoundImplementation; +using UnityEngine; + +public class CardChoice : MonoBehaviour +{ + private enum StickDirection + { + Left, + Right, + None + } + + public int pickrID = -1; + + public ArtInstance cardPickArt; + + private Transform[] children; + + public CardInfo[] cards; + + public int picks = 6; + + public static CardChoice instance; + + public bool IsPicking; + + private List<GameObject> spawnedCards = new List<GameObject>(); + + public AnimationCurve curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + + private float speed = 4f; + + private bool isPlaying; + + private StickDirection lastStickDirection; + + private int currentlySelectedCard; + + private float counter = 1f; + + private PickerType pickerType; + + public CardThemeColor[] cardThemes; + + private void Awake() + { + instance = this; + } + + private void Start() + { + for (int i = 0; i < cards.Length; i++) + { + PhotonNetwork.PrefabPool.RegisterPrefab(cards[i].gameObject.name, cards[i].gameObject); + } + children = new Transform[base.transform.childCount]; + for (int j = 0; j < children.Length; j++) + { + children[j] = base.transform.GetChild(j); + } + } + + public CardInfo GetSourceCard(CardInfo info) + { + for (int i = 0; i < cards.Length; i++) + { + if (cards[i].cardName == info.cardName) + { + return cards[i]; + } + } + return null; + } + + public void Pick(GameObject pickedCard = null, bool clear = false) + { + if ((bool)pickedCard) + { + pickedCard.GetComponentInChildren<ApplyCardStats>().Pick(pickrID, forcePick: false, pickerType); + GetComponent<PhotonView>().RPC("RPCA_DoEndPick", RpcTarget.All, CardIDs(), pickedCard.GetComponent<PhotonView>().ViewID, pickedCard.GetComponent<PublicInt>().theInt, pickrID); + } + else if (PlayerManager.instance.GetPlayerWithID(pickrID).data.view.IsMine) + { + StartCoroutine(ReplaceCards(pickedCard, clear)); + } + } + + private int[] CardIDs() + { + int[] array = new int[spawnedCards.Count]; + for (int i = 0; i < spawnedCards.Count; i++) + { + array[i] = spawnedCards[i].GetComponent<PhotonView>().ViewID; + } + return array; + } + + private List<GameObject> CardFromIDs(int[] cardIDs) + { + List<GameObject> list = new List<GameObject>(); + for (int i = 0; i < cardIDs.Length; i++) + { + list.Add(PhotonNetwork.GetPhotonView(cardIDs[i]).gameObject); + } + return list; + } + + [PunRPC] + private void RPCA_DoEndPick(int[] cardIDs, int targetCardID, int theInt = 0, int pickId = -1) + { + GameObject pickedCard = PhotonNetwork.GetPhotonView(targetCardID).gameObject; + spawnedCards = CardFromIDs(cardIDs); + StartCoroutine(IDoEndPick(pickedCard, theInt, pickId)); + } + + public IEnumerator IDoEndPick(GameObject pickedCard = null, int theInt = 0, int pickId = -1) + { + Vector3 startPos = pickedCard.transform.position; + Vector3 endPos = CardChoiceVisuals.instance.transform.position; + float c2 = 0f; + while (c2 < 1f) + { + CardChoiceVisuals.instance.framesToSnap = 1; + Vector3 position = Vector3.LerpUnclamped(startPos, endPos, curve.Evaluate(c2)); + pickedCard.transform.position = position; + base.transform.GetChild(theInt).position = position; + c2 += Time.deltaTime * speed; + yield return null; + } + GamefeelManager.GameFeel((startPos - endPos).normalized * 2f); + for (int i = 0; i < spawnedCards.Count; i++) + { + if ((bool)spawnedCards[i]) + { + if (spawnedCards[i].gameObject != pickedCard) + { + spawnedCards[i].AddComponent<Rigidbody>().AddForce((spawnedCards[i].transform.position - endPos) * Random.Range(0f, 50f)); + spawnedCards[i].GetComponent<Rigidbody>().AddTorque(Random.onUnitSphere * Random.Range(0f, 200f)); + spawnedCards[i].AddComponent<RemoveAfterSeconds>().seconds = Random.Range(0.5f, 1f); + spawnedCards[i].GetComponent<RemoveAfterSeconds>().shrink = true; + } + else + { + spawnedCards[i].GetComponentInChildren<CardVisuals>().Leave(); + } + } + } + yield return new WaitForSeconds(0.25f); + AnimationCurve softCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + Vector3 startPos2 = base.transform.GetChild(theInt).transform.position; + Vector3 endPos2 = startPos; + c2 = 0f; + while (c2 < 1f) + { + Vector3 position2 = Vector3.LerpUnclamped(startPos2, endPos2, softCurve.Evaluate(c2)); + base.transform.GetChild(theInt).position = position2; + c2 += Time.deltaTime * speed * 1.5f; + yield return null; + } + SoundPlayerStatic.Instance.PlayPlayerBallDisappear(); + base.transform.GetChild(theInt).position = startPos; + spawnedCards.Clear(); + if (PlayerManager.instance.GetPlayerWithID(pickId).data.view.IsMine) + { + StartCoroutine(ReplaceCards(pickedCard)); + } + } + + private GameObject Spawn(GameObject objToSpawn, Vector3 pos, Quaternion rot) + { + return PhotonNetwork.Instantiate(GetCardPath(objToSpawn), pos, rot, 0); + } + + private string GetCardPath(GameObject targetObj) + { + return targetObj.name; + } + + public GameObject AddCard(CardInfo cardToSpawn) + { + GameObject gameObject = Spawn(cardToSpawn.gameObject, new Vector3(30f, -10f, 0f), Quaternion.identity); + spawnedCards.Add(gameObject); + return gameObject; + } + + public GameObject AddCardVisual(CardInfo cardToSpawn, Vector3 pos) + { + GameObject obj = Object.Instantiate(cardToSpawn.gameObject, pos, Quaternion.identity); + obj.GetComponentInChildren<CardVisuals>().firstValueToSet = true; + return obj; + } + + private IEnumerator ReplaceCards(GameObject pickedCard = null, bool clear = false) + { + if (picks > 0) + { + SoundPlayerStatic.Instance.PlayPlayerBallAppear(); + } + isPlaying = true; + if (clear && spawnedCards != null) + { + for (int j = 0; j < spawnedCards.Count; j++) + { + if (pickedCard != spawnedCards[j]) + { + spawnedCards[j].GetComponentInChildren<CardVisuals>().Leave(); + yield return new WaitForSecondsRealtime(0.1f); + } + } + yield return new WaitForSecondsRealtime(0.2f); + if ((bool)pickedCard) + { + pickedCard.GetComponentInChildren<CardVisuals>().Pick(); + } + spawnedCards.Clear(); + } + yield return new WaitForSecondsRealtime(0.2f); + if (picks > 0) + { + for (int j = 0; j < children.Length; j++) + { + spawnedCards.Add(SpawnUniqueCard(children[j].transform.position, children[j].transform.rotation)); + spawnedCards[j].AddComponent<PublicInt>().theInt = j; + yield return new WaitForSecondsRealtime(0.1f); + } + } + else + { + GetComponent<PhotonView>().RPC("RPCA_DonePicking", RpcTarget.All); + } + picks--; + isPlaying = false; + } + + [PunRPC] + private void RPCA_DonePicking() + { + IsPicking = false; + } + + private GameObject GetRanomCard() + { + GameObject result = null; + float num = 0f; + for (int i = 0; i < cards.Length; i++) + { + if (cards[i].rarity == CardInfo.Rarity.Common) + { + num += 10f; + } + if (cards[i].rarity == CardInfo.Rarity.Uncommon) + { + num += 4f; + } + if (cards[i].rarity == CardInfo.Rarity.Rare) + { + num += 1f; + } + } + float num2 = Random.Range(0f, num); + for (int j = 0; j < cards.Length; j++) + { + if (cards[j].rarity == CardInfo.Rarity.Common) + { + num2 -= 10f; + } + if (cards[j].rarity == CardInfo.Rarity.Uncommon) + { + num2 -= 4f; + } + if (cards[j].rarity == CardInfo.Rarity.Rare) + { + num2 -= 1f; + } + if (num2 <= 0f) + { + result = cards[j].gameObject; + break; + } + } + return result; + } + + private GameObject SpawnUniqueCard(Vector3 pos, Quaternion rot) + { + GameObject ranomCard = GetRanomCard(); + CardInfo component = ranomCard.GetComponent<CardInfo>(); + Player player = null; + player = ((pickerType != 0) ? PlayerManager.instance.players[pickrID] : PlayerManager.instance.GetPlayersInTeam(pickrID)[0]); + for (int i = 0; i < spawnedCards.Count; i++) + { + bool flag = spawnedCards[i].GetComponent<CardInfo>().cardName == ranomCard.GetComponent<CardInfo>().cardName; + if (pickrID != -1) + { + Holdable holdable = player.data.GetComponent<Holding>().holdable; + if ((bool)holdable) + { + Gun component2 = holdable.GetComponent<Gun>(); + Gun component3 = ranomCard.GetComponent<Gun>(); + if ((bool)component3 && (bool)component2 && component3.lockGunToDefault && component2.lockGunToDefault) + { + flag = true; + } + } + for (int j = 0; j < player.data.currentCards.Count; j++) + { + CardInfo component4 = player.data.currentCards[j].GetComponent<CardInfo>(); + for (int k = 0; k < component4.blacklistedCategories.Length; k++) + { + for (int l = 0; l < component.categories.Length; l++) + { + if (component.categories[l] == component4.blacklistedCategories[k]) + { + flag = true; + } + } + } + if (!component4.allowMultiple && component.cardName == component4.cardName) + { + flag = true; + } + } + } + if (flag) + { + return SpawnUniqueCard(pos, rot); + } + } + GameObject obj = Spawn(ranomCard.gameObject, pos, rot); + obj.GetComponent<CardInfo>().sourceCard = ranomCard.GetComponent<CardInfo>(); + obj.GetComponentInChildren<DamagableEvent>().GetComponent<Collider2D>().enabled = false; + return obj; + } + + private void Update() + { + counter += Time.deltaTime; + _ = isPlaying; + if (pickrID != -1 && IsPicking) + { + DoPlayerSelect(); + } + if (Application.isEditor && !DevConsole.isTyping && Input.GetKeyDown(KeyCode.N)) + { + picks++; + instance.Pick(null, clear: true); + } + } + + private void DoPlayerSelect() + { + SoundMusicManager.Instance.PlayIngame(isCard: true); + if (spawnedCards.Count == 0 || pickrID == -1) + { + return; + } + PlayerActions[] array = null; + array = ((pickerType != 0) ? PlayerManager.instance.GetActionsFromPlayer(pickrID) : PlayerManager.instance.GetActionsFromTeam(pickrID)); + if (array == null) + { + Pick(spawnedCards[0]); + return; + } + StickDirection stickDirection = StickDirection.None; + for (int i = 0; i < array.Length; i++) + { + if (array[i] == null) + { + continue; + } + if (array[i].Right.Value > 0.7f) + { + stickDirection = StickDirection.Right; + } + if (array[i].Left.Value > 0.7f) + { + stickDirection = StickDirection.Left; + } + currentlySelectedCard = Mathf.Clamp(currentlySelectedCard, 0, spawnedCards.Count - 1); + for (int j = 0; j < spawnedCards.Count; j++) + { + if ((bool)spawnedCards[j] && (spawnedCards[j].GetComponentInChildren<CardVisuals>().isSelected != (currentlySelectedCard == j) || counter > 0.2f)) + { + counter = 0f; + spawnedCards[j].GetComponent<PhotonView>().RPC("RPCA_ChangeSelected", RpcTarget.All, currentlySelectedCard == j); + } + } + if (array[i].Jump.WasPressed && !isPlaying && spawnedCards[currentlySelectedCard] != null) + { + Pick(spawnedCards[currentlySelectedCard]); + pickrID = -1; + break; + } + } + if (stickDirection != lastStickDirection) + { + if (stickDirection == StickDirection.Left) + { + currentlySelectedCard--; + } + if (stickDirection == StickDirection.Right) + { + currentlySelectedCard++; + } + lastStickDirection = stickDirection; + } + if (CardChoiceVisuals.instance.currentCardSelected != currentlySelectedCard) + { + CardChoiceVisuals.instance.SetCurrentSelected(currentlySelectedCard); + } + } + + public IEnumerator DoPick(int picksToSet, int picketIDToSet, PickerType pType = PickerType.Team) + { + pickerType = pType; + StartPick(picksToSet, picketIDToSet); + while (IsPicking) + { + yield return null; + } + UIHandler.instance.StopShowPicker(); + CardChoiceVisuals.instance.Hide(); + } + + public void StartPick(int picksToSet, int pickerIDToSet) + { + pickrID = pickerIDToSet; + IsPicking = true; + picks = picksToSet; + ArtHandler.instance.SetSpecificArt(cardPickArt); + Pick(); + } + + public Color GetCardColor(CardThemeColor.CardThemeColorType colorType) + { + for (int i = 0; i < cardThemes.Length; i++) + { + if (cardThemes[i].themeType == colorType) + { + return cardThemes[i].targetColor; + } + } + return Color.black; + } + + public Color GetCardColor2(CardThemeColor.CardThemeColorType colorType) + { + for (int i = 0; i < cardThemes.Length; i++) + { + if (cardThemes[i].themeType == colorType) + { + return cardThemes[i].bgColor; + } + } + return Color.black; + } +} diff --git a/GameCode/CardChoiceVisuals.cs b/GameCode/CardChoiceVisuals.cs new file mode 100644 index 0000000..bf09e08 --- /dev/null +++ b/GameCode/CardChoiceVisuals.cs @@ -0,0 +1,162 @@ +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class CardChoiceVisuals : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCardSwitch; + + public static CardChoiceVisuals instance; + + [Header("Settings")] + public int currentCardSelected; + + public GameObject cardParent; + + public Transform leftHandTarget; + + public Transform rightHandTarget; + + public Transform shieldGem; + + private Vector3 leftHandRestPos; + + private Vector3 rightHandRestPos; + + private Vector3 leftHandVel; + + private Vector3 rightHandVel; + + public float spring = 40f; + + public float drag = 10f; + + public float sway = 1f; + + public float swaySpeed = 1f; + + public int framesToSnap; + + private bool isShowinig; + + private GameObject currentSkin; + + private void Awake() + { + instance = this; + leftHandRestPos = leftHandTarget.position; + rightHandRestPos = rightHandTarget.position; + } + + private void Start() + { + } + + private void Update() + { + if (!isShowinig || Time.unscaledDeltaTime > 0.1f || currentCardSelected >= cardParent.transform.childCount || currentCardSelected < 0) + { + return; + } + if (rightHandTarget.position.x == float.NaN || rightHandTarget.position.y == float.NaN || rightHandTarget.position.z == float.NaN) + { + rightHandTarget.position = Vector3.zero; + rightHandVel = Vector3.zero; + } + if (leftHandTarget.position.x == float.NaN || leftHandTarget.position.y == float.NaN || leftHandTarget.position.z == float.NaN) + { + leftHandTarget.position = Vector3.zero; + leftHandVel = Vector3.zero; + } + GameObject obj = cardParent.transform.GetChild(currentCardSelected).gameObject; + Vector3 zero = Vector3.zero; + zero = obj.transform.GetChild(0).position; + if (currentCardSelected < 2) + { + leftHandVel += (zero - leftHandTarget.position) * spring * Time.unscaledDeltaTime; + leftHandVel -= leftHandVel * Time.unscaledDeltaTime * drag; + rightHandVel += (rightHandRestPos - rightHandTarget.position) * spring * Time.unscaledDeltaTime * 0.5f; + rightHandVel -= rightHandVel * Time.unscaledDeltaTime * drag * 0.5f; + rightHandVel += sway * new Vector3(-0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed, 0f), -0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed + 100f, 0f), 0f) * Time.unscaledDeltaTime; + shieldGem.transform.position = rightHandTarget.position; + if (framesToSnap > 0) + { + leftHandTarget.position = zero; + } + } + else + { + rightHandVel += (zero - rightHandTarget.position) * spring * Time.unscaledDeltaTime; + rightHandVel -= rightHandVel * Time.unscaledDeltaTime * drag; + leftHandVel += (leftHandRestPos - leftHandTarget.position) * spring * Time.unscaledDeltaTime * 0.5f; + leftHandVel -= leftHandVel * Time.unscaledDeltaTime * drag * 0.5f; + leftHandVel += sway * new Vector3(-0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed, Time.unscaledTime * swaySpeed), -0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed + 100f, Time.unscaledTime * swaySpeed + 100f), 0f) * Time.unscaledDeltaTime; + shieldGem.transform.position = leftHandTarget.position; + if (framesToSnap > 0) + { + rightHandTarget.position = zero; + } + } + framesToSnap--; + leftHandTarget.position += leftHandVel * Time.unscaledDeltaTime; + rightHandTarget.position += rightHandVel * Time.unscaledDeltaTime; + } + + public void Show(int pickerID = 0, bool animateIn = false) + { + isShowinig = true; + base.transform.GetChild(0).gameObject.SetActive(value: true); + if (animateIn) + { + GetComponent<CurveAnimation>().PlayIn(); + } + else + { + base.transform.localScale = Vector3.one * 33f; + } + if ((bool)currentSkin) + { + Object.Destroy(currentSkin); + } + if (PlayerManager.instance.players[pickerID].data.view.IsMine) + { + PlayerFace playerFace = null; + playerFace = ((!PhotonNetwork.OfflineMode) ? CharacterCreatorHandler.instance.selectedPlayerFaces[0] : CharacterCreatorHandler.instance.selectedPlayerFaces[pickerID]); + GetComponent<PhotonView>().RPC("RPCA_SetFace", RpcTarget.All, playerFace.eyeID, playerFace.eyeOffset, playerFace.mouthID, playerFace.mouthOffset, playerFace.detailID, playerFace.detailOffset, playerFace.detail2ID, playerFace.detail2Offset); + } + currentSkin = Object.Instantiate(PlayerSkinBank.GetPlayerSkinColors(pickerID).gameObject, base.transform.GetChild(0).transform.position, Quaternion.identity, base.transform.GetChild(0).transform); + currentSkin.GetComponentInChildren<ParticleSystem>().Play(); + leftHandTarget.position = base.transform.GetChild(0).position; + rightHandTarget.position = base.transform.GetChild(0).position; + leftHandVel *= 0f; + rightHandVel *= 0f; + StopAllCoroutines(); + } + + public void Hide() + { + GetComponent<CurveAnimation>().PlayOut(); + StartCoroutine(DelayHide()); + } + + private IEnumerator DelayHide() + { + yield return new WaitForSecondsRealtime(0.3f); + base.transform.GetChild(0).gameObject.SetActive(value: false); + isShowinig = false; + } + + internal void SetCurrentSelected(int toSet) + { + GetComponent<PhotonView>().RPC("RPCA_SetCurrentSelected", RpcTarget.All, toSet); + } + + [PunRPC] + internal void RPCA_SetCurrentSelected(int toSet) + { + SoundManager.Instance.Play(soundCardSwitch, base.transform); + currentCardSelected = toSet; + } +} diff --git a/GameCode/CardInfo.cs b/GameCode/CardInfo.cs new file mode 100644 index 0000000..e0b39fc --- /dev/null +++ b/GameCode/CardInfo.cs @@ -0,0 +1,68 @@ +using Photon.Pun; +using Sirenix.OdinInspector; +using UnityEngine; + +public class CardInfo : MonoBehaviour +{ + public enum Rarity + { + Common, + Uncommon, + Rare + } + + [Header("Sound Settings")] + public bool soundDisableBlockBasic; + + [Header("Settings")] + public string cardName = ""; + + [TextArea] + public string cardDestription = ""; + + public CardInfoStat[] cardStats; + + public Rarity rarity; + + public GameObject cardArt; + + public Sprite sprite; + + [HideInInspector] + public CardInfo sourceCard; + + public Color cardColor = new Color(0.14509805f, 0.14509805f, 0.14509805f); + + public CardCategory[] categories; + + [FoldoutGroup("Restrictions", 0)] + public bool allowMultiple = true; + + [FoldoutGroup("Restrictions", 0)] + public CardCategory[] blacklistedCategories; + + public GameObject cardBase; + + public CardThemeColor.CardThemeColorType colorTheme; + + private void Awake() + { + sourceCard = CardChoice.instance.GetSourceCard(this); + cardBase = Object.Instantiate(cardBase, base.transform.position, base.transform.rotation); + cardBase.transform.SetParent(base.transform, worldPositionStays: true); + bool charge = false; + Gun component = GetComponent<Gun>(); + if ((bool)component && component.useCharge) + { + charge = true; + } + cardBase.GetComponent<CardInfoDisplayer>().DrawCard(cardStats, cardName, cardDestription, sprite, charge); + cardBase.GetComponentInChildren<GeneralParticleSystem>().particleSettings.randomColor = cardColor; + } + + [PunRPC] + public void RPCA_ChangeSelected(bool setSelected) + { + GetComponentInChildren<CardVisuals>().ChangeSelected(setSelected); + } +} diff --git a/GameCode/CardInfoDisplayer.cs b/GameCode/CardInfoDisplayer.cs new file mode 100644 index 0000000..7c19bfe --- /dev/null +++ b/GameCode/CardInfoDisplayer.cs @@ -0,0 +1,61 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CardInfoDisplayer : MonoBehaviour +{ + public Color negativeColor; + + public Color positiveColor; + + public GameObject statObject; + + public GameObject grid; + + public GameObject chargeObj; + + public TextMeshProUGUI effectText; + + public TextMeshProUGUI nameText; + + public Image icon; + + public void DrawCard(CardInfoStat[] stats, string cardName, string description = "", Sprite image = null, bool charge = false) + { + if (charge) + { + chargeObj.SetActive(value: true); + chargeObj.transform.SetParent(grid.transform, worldPositionStays: true); + } + if (description != "") + { + effectText.text = description; + effectText.gameObject.SetActive(value: true); + effectText.transform.SetParent(grid.transform, worldPositionStays: true); + } + nameText.text = cardName.ToUpper(); + for (int i = 0; i < stats.Length; i++) + { + GameObject obj = Object.Instantiate(statObject, grid.transform.position, grid.transform.rotation, grid.transform); + obj.SetActive(value: true); + obj.transform.localScale = Vector3.one; + TextMeshProUGUI component = obj.transform.GetChild(0).GetComponent<TextMeshProUGUI>(); + TextMeshProUGUI component2 = obj.transform.GetChild(1).GetComponent<TextMeshProUGUI>(); + component.text = stats[i].stat; + if (stats[i].simepleAmount != 0 && !Optionshandler.showCardStatNumbers) + { + component2.text = stats[i].GetSimpleAmount(); + } + else + { + component2.text = stats[i].amount; + } + component2.color = (stats[i].positive ? positiveColor : negativeColor); + } + if ((bool)image) + { + icon.sprite = image; + } + effectText.transform.position += Vector3.up * 0.3f; + } +} diff --git a/GameCode/CardInfoStat.cs b/GameCode/CardInfoStat.cs new file mode 100644 index 0000000..943936c --- /dev/null +++ b/GameCode/CardInfoStat.cs @@ -0,0 +1,69 @@ +using System; + +[Serializable] +public class CardInfoStat +{ + public enum SimpleAmount + { + notAssigned, + aLittleBitOf, + Some, + aLotOf, + aHugeAmountOf, + slightlyLower, + lower, + aLotLower, + slightlySmaller, + smaller + } + + public bool positive; + + public string amount; + + public SimpleAmount simepleAmount; + + public string stat; + + public string GetSimpleAmount() + { + string result = ""; + if (simepleAmount == SimpleAmount.aLittleBitOf) + { + result = "Slightly more "; + } + if (simepleAmount == SimpleAmount.Some) + { + result = "More "; + } + if (simepleAmount == SimpleAmount.aLotOf) + { + result = "A bunch more "; + } + if (simepleAmount == SimpleAmount.aHugeAmountOf) + { + result = "A huge amount of"; + } + if (simepleAmount == SimpleAmount.slightlyLower) + { + result = "Slightly lower "; + } + if (simepleAmount == SimpleAmount.lower) + { + result = "Lower "; + } + if (simepleAmount == SimpleAmount.aLotLower) + { + result = "A lot lower"; + } + if (simepleAmount == SimpleAmount.smaller) + { + result = "Smaller"; + } + if (simepleAmount == SimpleAmount.slightlySmaller) + { + result = "Slightly smaller"; + } + return result; + } +} diff --git a/GameCode/CardRarityColor.cs b/GameCode/CardRarityColor.cs new file mode 100644 index 0000000..3008ae7 --- /dev/null +++ b/GameCode/CardRarityColor.cs @@ -0,0 +1,33 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +public class CardRarityColor : MonoBehaviour +{ + public Color uncommonColor; + + public Color rareColor; + + public Color uncommonColorOff; + + public Color rareColorOff; + + private void Awake() + { + CardVisuals componentInParent = GetComponentInParent<CardVisuals>(); + componentInParent.toggleSelectionAction = (Action<bool>)Delegate.Combine(componentInParent.toggleSelectionAction, new Action<bool>(Toggle)); + } + + public void Toggle(bool isOn) + { + CardInfo componentInParent = GetComponentInParent<CardInfo>(); + if (componentInParent.rarity == CardInfo.Rarity.Uncommon) + { + GetComponent<Image>().color = (isOn ? uncommonColor : uncommonColorOff); + } + if (componentInParent.rarity == CardInfo.Rarity.Rare) + { + GetComponent<Image>().color = (isOn ? rareColor : rareColorOff); + } + } +} diff --git a/GameCode/CardThemeColor.cs b/GameCode/CardThemeColor.cs new file mode 100644 index 0000000..780dcd5 --- /dev/null +++ b/GameCode/CardThemeColor.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; + +[Serializable] +public class CardThemeColor +{ + public enum CardThemeColorType + { + DestructiveRed, + FirepowerYellow, + DefensiveBlue, + TechWhite, + EvilPurple, + PoisonGreen, + NatureBrown, + ColdBlue, + MagicPink + } + + public CardThemeColorType themeType; + + public Color targetColor; + + public Color bgColor; +} diff --git a/GameCode/CardVisuals.cs b/GameCode/CardVisuals.cs new file mode 100644 index 0000000..483d5d7 --- /dev/null +++ b/GameCode/CardVisuals.cs @@ -0,0 +1,138 @@ +using System; +using Photon.Pun; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CardVisuals : MonoBehaviour +{ + private ScaleShake shake; + + public bool isSelected; + + private GeneralParticleSystem part; + + private Color selectedColor; + + private Color unSelectedColor = new Color(0.1f, 0.1f, 0.1f); + + public Color defaultColor; + + public Color chillColor; + + public Image[] images; + + public TextMeshProUGUI nameText; + + public GameObject statsObj; + + public GameObject[] objectsToToggle; + + private CardAnimation[] cardAnims; + + private CanvasGroup group; + + public bool firstValueToSet; + + public Action<bool> toggleSelectionAction; + + private void Start() + { + group = base.transform.Find("Canvas/Front/Grid").GetComponent<CanvasGroup>(); + selectedColor = GetComponentInParent<CardInfo>().cardColor; + part = GetComponentInChildren<GeneralParticleSystem>(); + shake = GetComponent<ScaleShake>(); + Transform transform = base.transform.Find("Canvas/Front/Background/Art"); + CardInfo componentInParent = GetComponentInParent<CardInfo>(); + defaultColor = CardChoice.instance.GetCardColor(componentInParent.colorTheme); + selectedColor = CardChoice.instance.GetCardColor2(componentInParent.colorTheme); + if ((bool)componentInParent.cardArt) + { + GameObject obj = UnityEngine.Object.Instantiate(componentInParent.cardArt, transform.transform.position, transform.transform.rotation, transform); + obj.transform.localPosition = Vector3.zero; + obj.transform.SetAsFirstSibling(); + obj.transform.localScale = Vector3.one; + } + cardAnims = GetComponentsInChildren<CardAnimation>(); + isSelected = !firstValueToSet; + ChangeSelected(firstValueToSet); + } + + public void Leave() + { + UnityEngine.Object.Destroy(base.transform.root.gameObject); + } + + public void Pick() + { + PhotonNetwork.Destroy(base.transform.root.gameObject); + } + + public void ChangeSelected(bool setSelected) + { + if (!part || isSelected == setSelected) + { + return; + } + isSelected = setSelected; + toggleSelectionAction?.Invoke(isSelected); + if (isSelected) + { + part.simulationSpeedMultiplier = 1.25f; + part.particleSettings.randomColor = selectedColor; + shake.targetScale = 1.15f; + group.alpha = 1f; + for (int i = 0; i < images.Length; i++) + { + images[i].color = defaultColor; + } + for (int j = 0; j < objectsToToggle.Length; j++) + { + objectsToToggle[j].SetActive(value: false); + } + for (int k = 0; k < cardAnims.Length; k++) + { + cardAnims[k].enabled = true; + } + nameText.color = defaultColor; + CurveAnimation[] componentsInChildren = GetComponentsInChildren<CurveAnimation>(); + for (int l = 0; l < componentsInChildren.Length; l++) + { + if (componentsInChildren[l].transform.parent != base.transform) + { + componentsInChildren[l].PlayIn(); + } + else if (componentsInChildren[l].currentState != 0) + { + componentsInChildren[l].PlayIn(); + } + } + return; + } + part.simulationSpeedMultiplier = 0.5f; + part.particleSettings.randomColor = unSelectedColor; + shake.targetScale = 0.9f; + group.alpha = 0.15f; + for (int m = 0; m < images.Length; m++) + { + images[m].color = chillColor; + } + for (int n = 0; n < objectsToToggle.Length; n++) + { + objectsToToggle[n].SetActive(value: true); + } + for (int num = 0; num < cardAnims.Length; num++) + { + cardAnims[num].enabled = false; + } + nameText.color = chillColor; + CurveAnimation[] componentsInChildren2 = GetComponentsInChildren<CurveAnimation>(); + for (int num2 = 0; num2 < componentsInChildren2.Length; num2++) + { + if (componentsInChildren2[num2].transform.parent != base.transform) + { + componentsInChildren2[num2].PlayOut(); + } + } + } +} diff --git a/GameCode/ChangeColor.cs b/GameCode/ChangeColor.cs new file mode 100644 index 0000000..a0d61bf --- /dev/null +++ b/GameCode/ChangeColor.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class ChangeColor : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/ChangeDamageMultiplierAfterDistanceTravelled.cs b/GameCode/ChangeDamageMultiplierAfterDistanceTravelled.cs new file mode 100644 index 0000000..7bd1bf8 --- /dev/null +++ b/GameCode/ChangeDamageMultiplierAfterDistanceTravelled.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class ChangeDamageMultiplierAfterDistanceTravelled : MonoBehaviour +{ + public float muiltiplier = 2f; + + public float distance = 10f; + + private ProjectileHit hit; + + private MoveTransform move; + + private TrailRenderer trail; + + private void Awake() + { + trail = GetComponentInChildren<TrailRenderer>(); + } + + private void Start() + { + hit = GetComponent<ProjectileHit>(); + move = GetComponent<MoveTransform>(); + } + + private void Update() + { + if (move.distanceTravelled > distance) + { + hit.damage *= muiltiplier; + hit.shake *= muiltiplier; + if ((bool)trail) + { + trail.widthMultiplier *= 2f; + } + Object.Destroy(this); + } + } +} diff --git a/GameCode/ChannelMessage.cs b/GameCode/ChannelMessage.cs new file mode 100644 index 0000000..2349349 --- /dev/null +++ b/GameCode/ChannelMessage.cs @@ -0,0 +1,3 @@ +using Irc; + +public delegate void ChannelMessage(ChannelMessageEventArgs channelMessageArgs); diff --git a/GameCode/CharacterCreator.cs b/GameCode/CharacterCreator.cs new file mode 100644 index 0000000..55d31ed --- /dev/null +++ b/GameCode/CharacterCreator.cs @@ -0,0 +1,101 @@ +using System; +using UnityEngine; + +public class CharacterCreator : MonoBehaviour +{ + public PlayerFace currentPlayerFace; + + public GameObject objectToEnable; + + public int playerID; + + public int portraitID; + + public bool ready; + + public PlayerActions playerActions; + + public GeneralInput.InputType inputType; + + public MenuControllerHandler.MenuControl currentControl = MenuControllerHandler.MenuControl.Unassigned; + + public MenuControllerHandler.MenuControl lastControl = MenuControllerHandler.MenuControl.Unassigned; + + public Action<MenuControllerHandler.MenuControl> SwitchAction; + + public CharacterCreatorNavigation nav; + + private void Start() + { + nav = GetComponentInChildren<CharacterCreatorNavigation>(); + } + + private void Update() + { + if (currentControl != lastControl) + { + SwitchAction?.Invoke(currentControl); + } + lastControl = currentControl; + } + + public void Close() + { + CharacterCreatorHandler.instance.ReleasePortrait(portraitID); + if (playerActions == null) + { + base.gameObject.SetActive(value: false); + MainMenuHandler.instance.Open(); + } + else + { + objectToEnable.SetActive(value: true); + base.gameObject.SetActive(value: false); + } + } + + public void Finish() + { + CharacterCreatorHandler.instance.ReleasePortrait(portraitID); + CharacterCreatorHandler.instance.SetFacePreset(portraitID, currentPlayerFace); + CharacterCreatorHandler.instance.SelectFace(0, currentPlayerFace, portraitID); + if (playerActions == null) + { + base.gameObject.SetActive(value: false); + MainMenuHandler.instance.Open(); + } + else + { + objectToEnable.SetActive(value: true); + base.gameObject.SetActive(value: false); + } + } + + internal void SetOffset(Vector2 offset, CharacterItemType itemType, int slotID) + { + if (itemType == CharacterItemType.Eyes) + { + currentPlayerFace.eyeOffset = offset; + } + if (itemType == CharacterItemType.Mouth) + { + currentPlayerFace.mouthOffset = offset; + } + if (itemType == CharacterItemType.Detail) + { + if (slotID == 0) + { + currentPlayerFace.detailOffset = offset; + } + if (slotID == 1) + { + currentPlayerFace.detail2Offset = offset; + } + } + } + + internal void SpawnFace(PlayerFace currentFace) + { + GetComponentInChildren<CharacterCreatorItemEquipper>().SpawnPlayerFace(currentFace); + } +} diff --git a/GameCode/CharacterCreatorButtonSpawner.cs b/GameCode/CharacterCreatorButtonSpawner.cs new file mode 100644 index 0000000..9e0fffb --- /dev/null +++ b/GameCode/CharacterCreatorButtonSpawner.cs @@ -0,0 +1,146 @@ +using UnityEngine; + +public class CharacterCreatorButtonSpawner : MonoBehaviour +{ + public GameObject sourceButton; + + private CharacterCreatorItemLoader loader; + + private CharacterCreator creator; + + private void Start() + { + creator = GetComponent<CharacterCreator>(); + loader = CharacterCreatorItemLoader.instance; + OpenMenu(CharacterItemType.Eyes, 0); + } + + public void OpenMenu(int id) + { + if (id == 0) + { + OpenMenu(CharacterItemType.Eyes, 0); + } + if (id == 1) + { + OpenMenu(CharacterItemType.Mouth, 0); + } + if (id == 2) + { + OpenMenu(CharacterItemType.Detail, 0); + } + if (id == 3) + { + OpenMenu(CharacterItemType.Detail, 1); + } + } + + public void OpenMenu(CharacterItemType target, int slotNr) + { + CharacterItem[] array = null; + if (target == CharacterItemType.Eyes) + { + array = loader.eyes; + } + if (target == CharacterItemType.Mouth) + { + array = loader.mouths; + } + if (target == CharacterItemType.Detail) + { + array = loader.accessories; + } + for (int i = 0; i < sourceButton.transform.parent.childCount; i++) + { + if (sourceButton.transform.parent.GetChild(i).gameObject.activeSelf) + { + Object.Destroy(sourceButton.transform.parent.GetChild(i).gameObject); + } + } + for (int j = 0; j < array.Length; j++) + { + GameObject gameObject = Object.Instantiate(sourceButton, sourceButton.transform.parent); + gameObject.SetActive(value: true); + Transform parent = gameObject.transform.Find("ItemParent"); + GameObject gameObject2 = Object.Instantiate(array[j].gameObject, parent); + gameObject.GetComponent<CharacterItemButton>().itemType = target; + gameObject.GetComponent<CharacterItemButton>().slotNr = slotNr; + gameObject.GetComponentInChildren<CharacterItem>().sprite = array[j].gameObject.GetComponent<SpriteRenderer>().sprite; + gameObject2.GetComponentInChildren<CharacterItem>().GetComponent<SpriteRenderer>().sortingOrder = array[j].gameObject.GetComponent<SpriteRenderer>().sortingOrder; + gameObject2.GetComponentInChildren<CharacterItem>().scale = array[j].scale; + gameObject2.GetComponentInChildren<CharacterItem>().itemType = target; + gameObject2.GetComponentInChildren<CharacterItem>().offset = array[j].offset; + gameObject2.GetComponentInChildren<CharacterItem>().slotNr = slotNr; + gameObject2.GetComponentInChildren<SpriteRenderer>().transform.localPosition = array[j].offset; + gameObject2.GetComponentInChildren<SpriteRenderer>().transform.localScale = array[j].scale * Vector2.one; + if (target == CharacterItemType.Eyes && j == creator.currentPlayerFace.eyeID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + if (target == CharacterItemType.Mouth && j == creator.currentPlayerFace.mouthID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + if (target == CharacterItemType.Detail && j == creator.currentPlayerFace.detailID && slotNr == 0) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + if (target == CharacterItemType.Detail && slotNr == 1 && j == creator.currentPlayerFace.detail2ID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + } + } + + public void SelectButton(CharacterItemType itemType, int slotNr) + { + for (int i = 0; i < sourceButton.transform.parent.childCount; i++) + { + GameObject gameObject = sourceButton.transform.parent.GetChild(i).gameObject; + if (itemType == CharacterItemType.Eyes) + { + if (i - 1 == creator.currentPlayerFace.eyeID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + if (itemType == CharacterItemType.Mouth) + { + if (i - 1 == creator.currentPlayerFace.mouthID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + if (itemType == CharacterItemType.Detail) + { + if (i - 1 == creator.currentPlayerFace.detailID && slotNr == 0) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + if (itemType == CharacterItemType.Detail && slotNr == 1) + { + if (i - 1 == creator.currentPlayerFace.detail2ID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + } + } +} diff --git a/GameCode/CharacterCreatorDragging.cs b/GameCode/CharacterCreatorDragging.cs new file mode 100644 index 0000000..21ec9f1 --- /dev/null +++ b/GameCode/CharacterCreatorDragging.cs @@ -0,0 +1,116 @@ +using InControl; +using UnityEngine; + +public class CharacterCreatorDragging : MonoBehaviour +{ + public Vector2 rightStick; + + private CharacterCreator creator; + + private Transform draggedObject; + + private Vector2 lastMouse = Vector3.zero; + + private void Start() + { + creator = GetComponentInParent<CharacterCreator>(); + } + + private void Update() + { + if (creator.inputType == GeneralInput.InputType.Keyboard || creator.inputType == GeneralInput.InputType.Either) + { + DoMouse(); + } + if (creator.inputType == GeneralInput.InputType.Controller || creator.inputType == GeneralInput.InputType.Either) + { + DoController(); + } + } + + private void DoController() + { + int num = -1; + int barPos = creator.nav.barPos; + for (int i = 0; i < base.transform.childCount; i++) + { + CharacterItem component = base.transform.GetChild(i).GetComponent<CharacterItem>(); + if (barPos == 0 && component.itemType == CharacterItemType.Eyes) + { + num = i; + } + if (barPos == 1 && component.itemType == CharacterItemType.Mouth) + { + num = i; + } + if (barPos == 2 && component.itemType == CharacterItemType.Detail && component.slotNr == 0) + { + num = i; + } + if (barPos == 3 && component.itemType == CharacterItemType.Detail && component.slotNr == 1) + { + num = i; + } + } + if (num >= base.transform.childCount) + { + return; + } + Vector2 vector = Vector2.zero; + if (creator.playerActions != null) + { + vector = creator.playerActions.Aim.Value; + } + else + { + for (int j = 0; j < InputManager.ActiveDevices.Count; j++) + { + vector = InputManager.ActiveDevices[j].RightStick.Value; + } + } + base.transform.GetChild(num).transform.position += (Vector3)vector * Time.deltaTime * 3f; + if (vector != Vector2.zero) + { + CharacterItem component2 = base.transform.GetChild(num).GetComponent<CharacterItem>(); + Vector2 offset = (Vector2)base.transform.GetChild(num).localPosition - component2.offset; + creator.SetOffset(offset, component2.itemType, component2.slotNr); + } + } + + private void DoMouse() + { + Vector2 vector = MainCam.instance.cam.ScreenToWorldPoint(Input.mousePosition); + if (Input.GetKeyDown(KeyCode.Mouse0)) + { + float num = 2f; + int num2 = -1; + for (int i = 0; i < base.transform.childCount; i++) + { + float num3 = Vector2.Distance(vector, base.transform.GetChild(i).transform.position); + Debug.DrawLine(vector, base.transform.GetChild(i).GetComponent<SpriteRenderer>().bounds.center, Color.red, 2f); + if (num3 < num) + { + num = num3; + num2 = i; + } + } + if (num2 != -1) + { + draggedObject = base.transform.GetChild(num2); + } + } + if (Input.GetKeyUp(KeyCode.Mouse0) && (bool)draggedObject) + { + CharacterItem component = draggedObject.GetComponent<CharacterItem>(); + Vector2 offset = (Vector2)draggedObject.transform.localPosition - component.offset; + creator.SetOffset(offset, component.itemType, component.slotNr); + draggedObject = null; + } + if ((bool)draggedObject) + { + draggedObject.transform.position += (Vector3)(vector - lastMouse); + draggedObject.transform.localPosition = Vector2.ClampMagnitude(draggedObject.transform.localPosition, 4.5f); + } + lastMouse = vector; + } +} diff --git a/GameCode/CharacterCreatorHandler.cs b/GameCode/CharacterCreatorHandler.cs new file mode 100644 index 0000000..1dd23c7 --- /dev/null +++ b/GameCode/CharacterCreatorHandler.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class CharacterCreatorHandler : MonoBehaviour +{ + public static CharacterCreatorHandler instance; + + public PlayerFace[] playerFaces = new PlayerFace[10]; + + public PlayerFace[] selectedPlayerFaces = new PlayerFace[4]; + + public int[] selectedFaceID = new int[4]; + + public List<int> lockedPortraits; + + public Action lockedPortraitAction; + + public Action<int> faceWasUpdatedAction; + + public void LockPortrait(int portrait) + { + lockedPortraits.Add(portrait); + lockedPortraitAction?.Invoke(); + } + + public void ReleasePortrait(int porttrait) + { + for (int i = 0; i < lockedPortraits.Count; i++) + { + if (porttrait == lockedPortraits[i]) + { + lockedPortraits.RemoveAt(i); + break; + } + } + lockedPortraitAction?.Invoke(); + } + + private void ReleaseAllPortraits() + { + lockedPortraits.Clear(); + lockedPortraitAction?.Invoke(); + } + + private void Awake() + { + instance = this; + for (int i = 0; i < playerFaces.Length; i++) + { + playerFaces[i].LoadFace(i.ToString()); + } + for (int j = 0; j < selectedFaceID.Length; j++) + { + selectedFaceID[j] = PlayerPrefs.GetInt("SelectedFace" + j); + SelectFace(j, playerFaces[selectedFaceID[j]], selectedFaceID[j]); + } + } + + internal void SelectFace(int faceID, PlayerFace selectedFace, int faceSlot) + { + selectedFaceID[faceID] = faceSlot; + PlayerPrefs.SetInt("SelectedFace" + faceID, selectedFaceID[faceID]); + selectedPlayerFaces[faceID] = selectedFace; + } + + public PlayerFace GetFacePreset(int faceID) + { + return playerFaces[faceID]; + } + + public bool SomeoneIsEditing() + { + for (int i = 0; i < base.transform.childCount; i++) + { + if (base.transform.GetChild(i).gameObject.activeSelf) + { + return true; + } + } + return false; + } + + internal void SetFacePreset(int faceID, PlayerFace currentPlayerFace) + { + playerFaces[faceID] = PlayerFace.CopyFace(currentPlayerFace); + playerFaces[faceID].SaveFace(faceID.ToString()); + faceWasUpdatedAction?.Invoke(faceID); + } + + public void EditCharacterLocalMultiplayer(int playerId, int portraitID, GameObject objectToEnable, PlayerFace currentFace) + { + LockPortrait(portraitID); + CharacterCreator component = base.transform.GetChild(playerId + 1).GetComponent<CharacterCreator>(); + component.playerActions = PlayerManager.instance.players[playerId].data.playerActions; + component.inputType = PlayerManager.instance.players[playerId].data.input.inputType; + component.gameObject.SetActive(value: true); + component.playerID = playerId; + component.objectToEnable = objectToEnable; + component.currentPlayerFace = currentFace; + component.portraitID = portraitID; + component.SpawnFace(currentFace); + } + + public void EditCharacterPortrait(int portraitID, PlayerFace currentFace) + { + LockPortrait(portraitID); + MainMenuHandler.instance.Close(); + CharacterCreator component = base.transform.GetChild(0).GetComponent<CharacterCreator>(); + component.inputType = GeneralInput.InputType.Either; + component.currentPlayerFace = currentFace; + component.gameObject.SetActive(value: true); + component.playerID = 0; + component.portraitID = portraitID; + component.SpawnFace(currentFace); + } + + public void CloseMenus() + { + for (int i = 0; i < base.transform.childCount; i++) + { + base.transform.GetChild(i).GetComponent<CharacterCreator>().Close(); + } + ReleaseAllPortraits(); + } + + public void EndCustomization(int playerId = -1) + { + if (playerId == -1) + { + GetComponentInChildren<CharacterCreator>(includeInactive: true).Finish(); + base.transform.GetChild(0).gameObject.SetActive(value: false); + } + } +} diff --git a/GameCode/CharacterCreatorItemEquipper.cs b/GameCode/CharacterCreatorItemEquipper.cs new file mode 100644 index 0000000..ba03491 --- /dev/null +++ b/GameCode/CharacterCreatorItemEquipper.cs @@ -0,0 +1,130 @@ +using Photon.Pun; +using UnityEngine; + +public class CharacterCreatorItemEquipper : MonoBehaviour +{ + public GameObject itemParent; + + public GameObject defaultEyes; + + public GameObject defaultMouth; + + private CharacterCreatorItemLoader itemLoader; + + private CharacterCreator creator; + + public float scaleM = 1f; + + private bool spawnedSpecific; + + private bool inited; + + private void Start() + { + Init(); + if ((bool)creator && !spawnedSpecific) + { + Equip(defaultEyes.GetComponent<CharacterItem>(), CharacterItemType.Eyes); + Equip(defaultMouth.GetComponent<CharacterItem>(), CharacterItemType.Mouth); + } + } + + public void SpawnPlayerFace(PlayerFace newFace) + { + spawnedSpecific = true; + EquipFace(newFace); + } + + private void Init() + { + if (!inited) + { + inited = true; + creator = GetComponent<CharacterCreator>(); + itemLoader = CharacterCreatorItemLoader.instance; + } + } + + [PunRPC] + public void RPCA_SetFace(int eyeID, Vector2 eyeOffset, int mouthID, Vector2 mouthOffset, int detailID, Vector2 detailOffset, int detail2ID, Vector2 detail2Offset) + { + PlayerFace face = PlayerFace.CreateFace(eyeID, eyeOffset, mouthID, mouthOffset, detailID, detailOffset, detail2ID, detail2Offset); + EquipFace(face); + } + + public void EquipFace(PlayerFace face) + { + Init(); + Equip(itemLoader.GetItem(face.eyeID, CharacterItemType.Eyes), CharacterItemType.Eyes, face.eyeOffset); + Equip(itemLoader.GetItem(face.mouthID, CharacterItemType.Mouth), CharacterItemType.Mouth, face.mouthOffset); + Equip(itemLoader.GetItem(face.detailID, CharacterItemType.Detail), CharacterItemType.Detail, face.detailOffset); + Equip(itemLoader.GetItem(face.detail2ID, CharacterItemType.Detail), CharacterItemType.Detail, face.detail2Offset, 1); + } + + public void Equip(CharacterItem newSprite, CharacterItemType itemType, Vector2 offset = default(Vector2), int slotNr = 0) + { + if (newSprite == null) + { + return; + } + Init(); + if ((bool)creator) + { + if (itemType == CharacterItemType.Eyes) + { + creator.currentPlayerFace.eyeID = itemLoader.GetItemID(newSprite, itemType); + } + if (itemType == CharacterItemType.Mouth) + { + creator.currentPlayerFace.mouthID = itemLoader.GetItemID(newSprite, itemType); + } + if (itemType == CharacterItemType.Detail) + { + if (slotNr == 0) + { + creator.currentPlayerFace.detailID = itemLoader.GetItemID(newSprite, itemType); + } + if (slotNr == 1) + { + creator.currentPlayerFace.detail2ID = itemLoader.GetItemID(newSprite, itemType); + } + } + } + Clear(itemType, slotNr); + SpawnItem(newSprite, itemType, offset, slotNr); + CopyChildren[] componentsInChildren = GetComponentsInChildren<CopyChildren>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].DoUpdate(); + } + } + + private void SpawnItem(CharacterItem newSprite, CharacterItemType itemType, Vector2 offset = default(Vector2), int slotNr = 0) + { + GameObject obj = Object.Instantiate(newSprite.gameObject); + obj.gameObject.SetActive(value: true); + obj.transform.SetParent(itemParent.transform); + obj.GetComponent<SpriteRenderer>().sprite = newSprite.GetComponent<CharacterItem>().sprite; + obj.GetComponent<SpriteRenderer>().sortingOrder = newSprite.GetComponent<CharacterItem>().GetComponent<SpriteRenderer>().sortingOrder; + obj.GetComponent<CharacterItem>().itemType = itemType; + obj.GetComponent<SpriteRenderer>().color = newSprite.GetComponent<SpriteRenderer>().color; + obj.GetComponentInChildren<CharacterItem>().offset = newSprite.GetComponent<CharacterItem>().offset; + obj.GetComponentInChildren<CharacterItem>().sprite = newSprite.GetComponent<CharacterItem>().sprite; + obj.GetComponentInChildren<CharacterItem>().slotNr = slotNr; + obj.transform.localScale = newSprite.GetComponent<CharacterItem>().scale * Vector3.one * scaleM; + obj.transform.localPosition = (newSprite.GetComponent<CharacterItem>().offset + offset) * scaleM; + creator?.SetOffset(offset, itemType, slotNr); + } + + private void Clear(CharacterItemType itemType, int slotNr = 0) + { + for (int i = 0; i < itemParent.transform.childCount; i++) + { + CharacterItem component = itemParent.transform.GetChild(i).GetComponent<CharacterItem>(); + if (component.itemType == itemType && component.slotNr == slotNr) + { + Object.DestroyImmediate(itemParent.transform.GetChild(i).gameObject); + } + } + } +} diff --git a/GameCode/CharacterCreatorItemLoader.cs b/GameCode/CharacterCreatorItemLoader.cs new file mode 100644 index 0000000..2a79940 --- /dev/null +++ b/GameCode/CharacterCreatorItemLoader.cs @@ -0,0 +1,77 @@ +using UnityEngine; + +public class CharacterCreatorItemLoader : MonoBehaviour +{ + public CharacterItem[] eyes; + + public CharacterItem[] mouths; + + public CharacterItem[] accessories; + + public static CharacterCreatorItemLoader instance; + + private void Awake() + { + instance = this; + } + + private void Update() + { + } + + internal CharacterItem GetItem(int itemID, CharacterItemType itemType) + { + try + { + return itemType switch + { + CharacterItemType.Eyes => eyes[itemID], + CharacterItemType.Mouth => mouths[itemID], + _ => accessories[itemID], + }; + } + catch + { + return null; + } + } + + internal int GetItemID(CharacterItem newSprite, CharacterItemType itemType) + { + CharacterItem[] array = null; + array = itemType switch + { + CharacterItemType.Eyes => eyes, + CharacterItemType.Mouth => mouths, + _ => accessories, + }; + for (int i = 0; i < array.Length; i++) + { + if (array[i].sprite == newSprite.sprite) + { + return i; + } + } + return -1; + } + + public void UpdateItems(CharacterItemType target, CharacterItem[] items) + { + for (int i = 0; i < items.Length; i++) + { + items[i].sprite = items[i].GetComponent<SpriteRenderer>().sprite; + } + if (target == CharacterItemType.Eyes) + { + eyes = items; + } + if (target == CharacterItemType.Mouth) + { + mouths = items; + } + if (target == CharacterItemType.Detail) + { + accessories = items; + } + } +} diff --git a/GameCode/CharacterCreatorNavigation.cs b/GameCode/CharacterCreatorNavigation.cs new file mode 100644 index 0000000..46292e4 --- /dev/null +++ b/GameCode/CharacterCreatorNavigation.cs @@ -0,0 +1,162 @@ +using InControl; +using UnityEngine; +using UnityEngine.UI; + +public class CharacterCreatorNavigation : MonoBehaviour +{ + private int itemsInRow = 7; + + private CharacterCreator creator; + + private Transform grid; + + private Transform bar; + + private GameObject currentObject; + + private GameObject currentBarObject; + + private CharacterCreatorDragging dragging; + + public int x; + + public int y; + + public int barPos; + + private float cd; + + private void Awake() + { + creator = GetComponent<CharacterCreator>(); + dragging = GetComponentInChildren<CharacterCreatorDragging>(); + grid = base.transform.GetChild(0).GetChild(0); + bar = base.transform.GetChild(0).GetChild(1); + } + + private void Update() + { + if (creator.playerActions != null) + { + PlayerActionUpdate(creator.playerActions.Device); + } + else if (creator.playerActions == null) + { + creator.currentControl = MenuControllerHandler.menuControl; + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + InputDevice device = InputManager.ActiveDevices[i]; + PlayerActionUpdate(device); + } + } + } + + private void PlayerActionUpdate(InputDevice device) + { + cd += Time.unscaledDeltaTime; + if (device != null) + { + if (device.CommandWasPressed) + { + creator.Finish(); + } + dragging.rightStick = device.RightStick.Value; + GridMovement(device); + BarMovement(device); + } + } + + private void BarMovement(InputDevice device) + { + if (!currentBarObject) + { + MoveNav(0); + } + if (device.LeftTrigger.WasPressed) + { + MoveNav(-1); + } + if (device.RightTrigger.WasPressed) + { + MoveNav(1); + } + } + + private void MoveNav(int delta) + { + cd = 0f; + if (delta > 0) + { + barPos++; + } + if (delta < 0) + { + barPos--; + } + VerifyBarPos(); + } + + private void VerifyBarPos() + { + if ((bool)currentBarObject) + { + currentBarObject.GetComponent<HoverEvent>().exitEvent.Invoke(); + } + barPos = Mathf.Clamp(barPos, 0, 3); + currentBarObject = bar.GetChild(barPos).gameObject; + currentBarObject.GetComponent<HoverEvent>().enterEvent.Invoke(); + currentBarObject.GetComponent<Button>().onClick.Invoke(); + } + + private void GridMovement(InputDevice device) + { + if (!currentObject) + { + MoveNav(Vector2.zero); + } + if (device.LeftStick.Value.magnitude > 0.75f && cd > 0.1f) + { + MoveNav(device.LeftStick); + } + if (device.Action1.WasPressed) + { + currentObject.GetComponent<Button>().onClick.Invoke(); + } + } + + private void MoveNav(Vector2 delta) + { + cd = 0f; + if (delta.x > 0.5f) + { + x++; + } + if (delta.x < -0.5f) + { + x--; + } + if (delta.y > 0.5f) + { + y--; + } + if (delta.y < -0.5f) + { + y++; + } + VerifyPos(); + } + + private void VerifyPos() + { + if ((bool)currentObject) + { + currentObject.GetComponent<HoverEvent>().exitEvent.Invoke(); + } + x = Mathf.Clamp(x, 1, itemsInRow); + y = Mathf.Clamp(y, 0, Mathf.CeilToInt((grid.childCount - 2) / itemsInRow)); + x = Mathf.Clamp(x, 1, grid.childCount - y * itemsInRow - 1); + int index = x + y * itemsInRow; + currentObject = grid.GetChild(index).gameObject; + currentObject.GetComponent<HoverEvent>().enterEvent.Invoke(); + } +} diff --git a/GameCode/CharacterCreatorPortrait.cs b/GameCode/CharacterCreatorPortrait.cs new file mode 100644 index 0000000..1c14cc2 --- /dev/null +++ b/GameCode/CharacterCreatorPortrait.cs @@ -0,0 +1,121 @@ +using System; +using InControl; +using UnityEngine; +using UnityEngine.UI; + +public class CharacterCreatorPortrait : MonoBehaviour +{ + public int playerId = -1; + + public PlayerFace myFace; + + public GameObject selectedObj; + + public MenuControllerHandler.MenuControl controlType = MenuControllerHandler.MenuControl.Unassigned; + + private Color defColor; + + private HoverEvent hoverEvent; + + public GameObject lockedObj; + + private bool isLocked; + + private void Start() + { + defColor = base.transform.Find("BG").GetComponent<Image>().color; + CharacterCreatorHandler instance = CharacterCreatorHandler.instance; + instance.faceWasUpdatedAction = (Action<int>)Delegate.Combine(instance.faceWasUpdatedAction, new Action<int>(FaceUpdated)); + myFace = CharacterCreatorHandler.instance.GetFacePreset(base.transform.GetSiblingIndex()); + hoverEvent = GetComponent<HoverEvent>(); + GetComponentInChildren<CharacterCreatorItemEquipper>().EquipFace(myFace); + if (CharacterCreatorHandler.instance.selectedFaceID[0] == base.transform.GetSiblingIndex()) + { + ClickButton(); + } + CharacterCreatorHandler instance2 = CharacterCreatorHandler.instance; + instance2.lockedPortraitAction = (Action)Delegate.Combine(instance2.lockedPortraitAction, new Action(CheckLocked)); + CheckLocked(); + } + + private void CheckLocked() + { + isLocked = false; + for (int i = 0; i < CharacterCreatorHandler.instance.lockedPortraits.Count; i++) + { + if (base.transform.GetSiblingIndex() == CharacterCreatorHandler.instance.lockedPortraits[i]) + { + isLocked = true; + } + } + if (isLocked) + { + lockedObj.SetActive(value: true); + } + else + { + lockedObj.SetActive(value: false); + } + } + + private void FaceUpdated(int faceID) + { + if (faceID == base.transform.GetSiblingIndex()) + { + myFace = CharacterCreatorHandler.instance.GetFacePreset(faceID); + GetComponent<CharacterCreatorItemEquipper>().EquipFace(myFace); + } + } + + public void ClickButton() + { + CharacterCreatorHandler.instance.SelectFace(Mathf.Clamp(playerId, 0, 10), myFace, base.transform.GetSiblingIndex()); + ShownFace(); + } + + private void ShownFace() + { + for (int i = 0; i < base.transform.parent.childCount; i++) + { + if (base.transform.parent.GetChild(i) == base.transform) + { + base.transform.parent.GetChild(i).Find("Frame").gameObject.SetActive(value: true); + } + else + { + base.transform.parent.GetChild(i).Find("Frame").gameObject.SetActive(value: false); + } + } + } + + public void EditCharacter() + { + if (!isLocked) + { + ClickButton(); + if (playerId == -1) + { + CharacterCreatorHandler.instance.EditCharacterPortrait(base.transform.GetSiblingIndex(), myFace); + return; + } + GameObject gameObject = base.transform.parent.parent.parent.gameObject; + gameObject.SetActive(value: false); + CharacterCreatorHandler.instance.EditCharacterLocalMultiplayer(playerId, base.transform.GetSiblingIndex(), gameObject, myFace); + } + } + + private void Update() + { + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].Action4.WasPressed && hoverEvent.isSelected) + { + EditCharacter(); + } + } + if (Input.GetKeyDown(KeyCode.Mouse1) && controlType != 0 && hoverEvent.isHovered) + { + EditCharacter(); + } + } +} diff --git a/GameCode/CharacterData.cs b/GameCode/CharacterData.cs new file mode 100644 index 0000000..2f41ef3 --- /dev/null +++ b/GameCode/CharacterData.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using Photon.Pun; +using UnityEngine; + +public class CharacterData : MonoBehaviour +{ + public Vector3 aimDirection; + + public List<CardInfo> currentCards; + + public float sinceGroundedMultiplierWhenWallGrab = 0.2f; + + public PlayerActions playerActions; + + public ParticleSystem[] landParts; + + public int jumps = 1; + + public int currentJumps = 1; + + public bool isPlaying; + + public bool dead; + + public bool isStunned; + + public bool isSilenced; + + public float stunTime; + + public float silenceTime; + + public float health = 100f; + + public float maxHealth = 100f; + + public AnimationCurve slamCurve; + + public Vector3 wallPos; + + public Vector2 wallNormal; + + public Vector3 groundPos; + + public Transform hand; + + public float sinceWallGrab = float.PositiveInfinity; + + public bool isWallGrab; + + public float wallDistance = 1f; + + private bool wasWallGrabLastFrame; + + public float sinceGrounded; + + public bool isGrounded = true; + + private bool wasGroundedLastFrame = true; + + public Player player; + + public float sinceJump = 1f; + + public PlayerVelocity playerVel; + + public HealthHandler healthHandler; + + public GeneralInput input; + + public PlayerMovement movement; + + public PlayerJump jump; + + public Block block; + + public CharacterStatModifiers stats; + + public WeaponHandler weaponHandler; + + public StunHandler stunHandler; + + public SilenceHandler silenceHandler; + + public Player lastSourceOfDamage; + + public Player master; + + public Player lastDamagedPlayer; + + public Collider2D mainCol; + + public PlayerSounds playerSounds; + + private Transform wobblePos; + + private LayerMask groundMask; + + public PhotonView view; + + private CrownPos crownPos; + + public Rigidbody2D standOnRig; + + public Action<float, Vector3, Vector3, Transform> TouchGroundAction; + + public Action<float, Vector3, Vector3> TouchWallAction; + + public float HealthPercentage + { + get + { + return health / maxHealth; + } + internal set + { + } + } + + private void Awake() + { + crownPos = GetComponentInChildren<CrownPos>(); + view = GetComponent<PhotonView>(); + mainCol = GetComponent<Collider2D>(); + wobblePos = GetComponentInChildren<PlayerWobblePosition>().transform; + stats = GetComponent<CharacterStatModifiers>(); + player = GetComponent<Player>(); + weaponHandler = GetComponent<WeaponHandler>(); + block = GetComponent<Block>(); + input = GetComponent<GeneralInput>(); + movement = GetComponent<PlayerMovement>(); + jump = GetComponent<PlayerJump>(); + stunHandler = GetComponent<StunHandler>(); + silenceHandler = GetComponent<SilenceHandler>(); + hand = GetComponentInChildren<HandPos>().transform; + playerVel = GetComponent<PlayerVelocity>(); + healthHandler = GetComponent<HealthHandler>(); + playerSounds = GetComponent<PlayerSounds>(); + } + + internal Vector3 GetCrownPos() + { + if ((bool)crownPos) + { + return crownPos.transform.position + Vector3.up * crownPos.GetOffset(); + } + Debug.LogError("NO CROWN POS!?"); + return Vector3.up * 1000f; + } + + private void Start() + { + groundMask = LayerMask.GetMask("Default"); + if (!view.IsMine) + { + PlayerManager.RegisterPlayer(player); + } + } + + private void Update() + { + if (!playerVel.simulated) + { + sinceGrounded = 0f; + } + sinceJump += TimeHandler.deltaTime; + Wall(); + } + + private void FixedUpdate() + { + Ground(); + } + + private void Ground() + { + if (!isPlaying) + { + return; + } + if (!isGrounded) + { + sinceGrounded += TimeHandler.fixedDeltaTime * ((isWallGrab && wallDistance < 0.7f) ? sinceGroundedMultiplierWhenWallGrab : 1f); + if (sinceGrounded < 0f) + { + sinceGrounded = Mathf.Lerp(sinceGrounded, 0f, TimeHandler.fixedDeltaTime * 15f); + } + } + if (!wasGroundedLastFrame) + { + isGrounded = false; + } + wasGroundedLastFrame = false; + } + + private void Wall() + { + if (!isWallGrab) + { + sinceWallGrab += TimeHandler.deltaTime; + } + if (!wasWallGrabLastFrame) + { + isWallGrab = false; + } + wasWallGrabLastFrame = false; + } + + public void TouchGround(Vector3 pos, Vector3 groundNormal, Rigidbody2D groundRig, Transform groundTransform = null) + { + if (sinceJump > 0.2f) + { + currentJumps = jumps; + } + if (TouchGroundAction != null) + { + TouchGroundAction(sinceGrounded, pos, groundNormal, groundTransform); + } + if (groundRig == null) + { + standOnRig = null; + } + else if (!groundRig.GetComponent<NetworkPhysicsObject>()) + { + standOnRig = groundRig; + } + if (playerVel.velocity.y < -20f && !isGrounded) + { + for (int i = 0; i < landParts.Length; i++) + { + landParts[i].transform.localScale = Vector3.one * Mathf.Clamp((0f - playerVel.velocity.y) / 40f, 0.5f, 1f) * 0.5f; + landParts[i].transform.position = new Vector3(base.transform.position.x + playerVel.velocity.x * 0.03f, pos.y, 5f); + landParts[i].transform.rotation = Quaternion.LookRotation(groundNormal); + landParts[i].Play(); + } + GamefeelManager.instance.AddGameFeel(Vector2.down * Mathf.Clamp((sinceGrounded - 0.5f) * 1f, 0f, 4f)); + } + groundPos = pos; + wasGroundedLastFrame = true; + isGrounded = true; + sinceGrounded = 0f; + } + + public void TouchWall(Vector2 normal, Vector3 pos) + { + if (isGrounded) + { + return; + } + wallNormal = normal; + wallPos = pos; + groundPos = pos; + wallDistance = Vector2.Distance(base.transform.position, pos); + if (!(sinceJump < 0.15f)) + { + currentJumps = jumps; + if (TouchWallAction != null) + { + TouchWallAction(sinceWallGrab, pos, normal); + } + _ = sinceWallGrab; + _ = 0.15f; + sinceWallGrab = 0f; + wasWallGrabLastFrame = true; + isWallGrab = true; + } + } + + public bool ThereIsGroundBelow(Vector3 pos, float range = 5f) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(pos, Vector2.down, range, groundMask); + if ((bool)raycastHit2D.transform && raycastHit2D.distance > 0.1f) + { + return true; + } + return false; + } + + public void SetAI(Player aiMaster = null) + { + master = aiMaster; + input.controlledElseWhere = true; + GetComponent<PlayerAPI>().enabled = true; + } + + public void SetWobbleObjectChild(Transform obj) + { + obj.transform.SetParent(wobblePos, worldPositionStays: true); + } +} diff --git a/GameCode/CharacterItem.cs b/GameCode/CharacterItem.cs new file mode 100644 index 0000000..4588084 --- /dev/null +++ b/GameCode/CharacterItem.cs @@ -0,0 +1,42 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +public class CharacterItem : MonoBehaviour +{ + public Sprite sprite; + + public float scale = 1f; + + public Vector2 offset = Vector2.zero; + + public CharacterItemType itemType; + + internal int slotNr; + + [ShowIf("itemType", CharacterItemType.Detail, true)] + public float moveHealthBarUp; + + [Button] + public void SaveTransform() + { + offset = base.transform.localPosition; + scale = base.transform.localScale.x; + } + + private void Start() + { + if (!base.transform.root.GetComponent<Player>()) + { + return; + } + base.gameObject.AddComponent<CharacterItemMirror>(); + if (moveHealthBarUp != 0f) + { + HealthBar componentInChildren = base.transform.root.GetComponentInChildren<HealthBar>(); + if ((bool)componentInChildren) + { + componentInChildren.transform.localPosition += Vector3.up * moveHealthBarUp; + } + } + } +} diff --git a/GameCode/CharacterItemButton.cs b/GameCode/CharacterItemButton.cs new file mode 100644 index 0000000..576dce0 --- /dev/null +++ b/GameCode/CharacterItemButton.cs @@ -0,0 +1,16 @@ +using SoundImplementation; +using UnityEngine; + +public class CharacterItemButton : MonoBehaviour +{ + public CharacterItemType itemType; + + public int slotNr; + + public void Click() + { + SoundPlayerStatic.Instance.PlayButtonClick(); + GetComponentInParent<CharacterCreatorItemEquipper>().Equip(base.gameObject.GetComponentInChildren<CharacterItem>(), itemType, Vector2.zero, slotNr); + GetComponentInParent<CharacterCreatorButtonSpawner>().SelectButton(itemType, slotNr); + } +} diff --git a/GameCode/CharacterItemMirror.cs b/GameCode/CharacterItemMirror.cs new file mode 100644 index 0000000..d3ff572 --- /dev/null +++ b/GameCode/CharacterItemMirror.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class CharacterItemMirror : MonoBehaviour +{ + private float speedThreshol = 3f; + + private LeftRight leftRight; + + private Player player; + + private void Start() + { + player = GetComponentInParent<Player>(); + if (base.transform.localPosition.x > 0f) + { + leftRight = LeftRight.Right; + } + else + { + leftRight = LeftRight.Left; + } + } + + private void Update() + { + LeftRight leftRight = this.leftRight; + if (player.data.playerVel.velocity.x > speedThreshol) + { + leftRight = LeftRight.Right; + } + if (player.data.playerVel.velocity.x < 0f - speedThreshol) + { + leftRight = LeftRight.Left; + } + if (leftRight != this.leftRight) + { + base.transform.localPosition = new Vector3(base.transform.localPosition.x * -1f, base.transform.localPosition.y, base.transform.localPosition.z); + base.transform.localScale = new Vector3(base.transform.localScale.x * -1f, base.transform.localScale.y, base.transform.localScale.z); + this.leftRight = leftRight; + } + } +} diff --git a/GameCode/CharacterItemType.cs b/GameCode/CharacterItemType.cs new file mode 100644 index 0000000..395a8ab --- /dev/null +++ b/GameCode/CharacterItemType.cs @@ -0,0 +1,6 @@ +public enum CharacterItemType +{ + Eyes, + Mouth, + Detail +} diff --git a/GameCode/CharacterSelectionInstance.cs b/GameCode/CharacterSelectionInstance.cs new file mode 100644 index 0000000..dd11ab4 --- /dev/null +++ b/GameCode/CharacterSelectionInstance.cs @@ -0,0 +1,157 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CharacterSelectionInstance : MonoBehaviour +{ + public int currentlySelectedFace; + + public Player currentPlayer; + + public GameObject getReadyObj; + + private HoverEvent currentButton; + + private CharacterSelectionInstance[] selectors; + + private HoverEvent[] buttons; + + public bool isReady; + + private float counter; + + private void Start() + { + selectors = base.transform.parent.GetComponentsInChildren<CharacterSelectionInstance>(); + } + + public void ResetMenu() + { + base.transform.GetChild(0).gameObject.SetActive(value: false); + currentPlayer = null; + getReadyObj.gameObject.SetActive(value: false); + PlayerManager.instance.RemovePlayers(); + } + + private void OnEnable() + { + if (!base.transform.GetChild(0).gameObject.activeSelf) + { + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).gameObject.SetActive(value: true); + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).Play(); + } + } + + public void StartPicking(Player pickingPlayer) + { + currentPlayer = pickingPlayer; + currentlySelectedFace = 0; + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).gameObject.SetActive(value: false); + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).Stop(); + base.transform.GetChild(0).gameObject.SetActive(value: true); + getReadyObj.gameObject.SetActive(value: true); + if (currentPlayer.data.input.inputType == GeneralInput.InputType.Keyboard) + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = "PRESS [SPACE] WHEN READY"; + } + else + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = "PRESS [START] WHEN READY"; + } + buttons = base.transform.GetComponentsInChildren<HoverEvent>(); + for (int i = 0; i < buttons.Length; i++) + { + if (pickingPlayer.data.input.inputType == GeneralInput.InputType.Controller) + { + buttons[i].enabled = false; + buttons[i].GetComponent<Button>().interactable = false; + buttons[i].GetComponent<CharacterCreatorPortrait>().controlType = MenuControllerHandler.MenuControl.Controller; + continue; + } + buttons[i].enabled = true; + buttons[i].GetComponent<Button>().interactable = true; + buttons[i].GetComponent<CharacterCreatorPortrait>().controlType = MenuControllerHandler.MenuControl.Mouse; + Navigation navigation = buttons[i].GetComponent<Button>().navigation; + navigation.mode = Navigation.Mode.None; + buttons[i].GetComponent<Button>().navigation = navigation; + } + } + + public void ReadyUp() + { + isReady = !isReady; + bool flag = true; + for (int i = 0; i < selectors.Length; i++) + { + if (!selectors[i].isReady) + { + flag = false; + } + } + if (flag) + { + MainMenuHandler.instance.Close(); + GM_ArmsRace.instance.StartGame(); + } + if (currentPlayer.data.input.inputType == GeneralInput.InputType.Keyboard) + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = (isReady ? "READY" : "PRESS [SPACE] WHEN READY"); + } + else + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = (isReady ? "READY" : "PRESS [START] WHEN READY"); + } + } + + private void Update() + { + if (!currentPlayer) + { + return; + } + if (currentPlayer.data.input.inputType != 0) + { + if (Input.GetKeyDown(KeyCode.Space)) + { + ReadyUp(); + } + return; + } + if (currentPlayer.data.playerActions.Device.CommandWasPressed) + { + ReadyUp(); + } + HoverEvent component = buttons[currentlySelectedFace].GetComponent<HoverEvent>(); + if (currentButton != component) + { + if ((bool)currentButton) + { + currentButton.GetComponent<SimulatedSelection>().Deselect(); + } + currentButton = component; + currentButton.GetComponent<SimulatedSelection>().Select(); + } + counter += Time.deltaTime; + if (Mathf.Abs(currentPlayer.data.playerActions.Move.X) > 0.5f && counter > 0.2f) + { + if (currentPlayer.data.playerActions.Move.X > 0.5f) + { + currentlySelectedFace++; + } + else + { + currentlySelectedFace--; + } + counter = 0f; + } + if (currentPlayer.data.playerActions.Jump.WasPressed) + { + currentButton.GetComponent<Button>().onClick.Invoke(); + } + if (currentPlayer.data.playerActions.Device.Action4.WasPressed) + { + currentButton.GetComponent<CharacterCreatorPortrait>().EditCharacter(); + } + currentlySelectedFace = Mathf.Clamp(currentlySelectedFace, 0, buttons.Length - 1); + } +} diff --git a/GameCode/CharacterSelectionMenu.cs b/GameCode/CharacterSelectionMenu.cs new file mode 100644 index 0000000..ed6c36a --- /dev/null +++ b/GameCode/CharacterSelectionMenu.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +public class CharacterSelectionMenu : MonoBehaviour +{ + private void Start() + { + PlayerManager instance = PlayerManager.instance; + instance.PlayerJoinedAction = (Action<Player>)Delegate.Combine(instance.PlayerJoinedAction, new Action<Player>(PlayerJoined)); + } + + private void PlayerJoined(Player joinedPlayer) + { + base.transform.GetChild(0).GetChild(PlayerManager.instance.players.Count - 1).GetComponent<CharacterSelectionInstance>() + .StartPicking(joinedPlayer); + } + + private void Update() + { + } +} diff --git a/GameCode/CharacterStatModifiers.cs b/GameCode/CharacterStatModifiers.cs new file mode 100644 index 0000000..9122d66 --- /dev/null +++ b/GameCode/CharacterStatModifiers.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class CharacterStatModifiers : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterSlowFreeze; + + private float soundSlowTime; + + private float soundSlowSpeedSec = 0.3f; + + [Header("Settings")] + public GameObject AddObjectToPlayer; + + [HideInInspector] + public List<GameObject> objectsAddedToPlayer; + + [Header("Multiply")] + public float sizeMultiplier = 1f; + + public float health = 1f; + + public float movementSpeed = 1f; + + public float jump = 1f; + + public float gravity = 1f; + + public float slow; + + public float slowSlow; + + public float fastSlow; + + [Header("Add")] + public float secondsToTakeDamageOver; + + public int numberOfJumps; + + public float regen; + + public float lifeSteal; + + public bool refreshOnDamage; + + public bool automaticReload = true; + + public int respawns; + + [HideInInspector] + public int remainingRespawns; + + [HideInInspector] + public float tasteOfBloodSpeed = 1f; + + [HideInInspector] + public float rageSpeed = 1f; + + public float attackSpeedMultiplier = 1f; + + private WasDealtDamageEffect[] wasDealtDamageEffects; + + private DealtDamageEffect[] dealtDamageEffects; + + private CharacterData data; + + public ParticleSystem slowPart; + + private float soundBigThreshold = 1.5f; + + public Action<Vector2, bool> DealtDamageAction; + + public Action<Vector2, bool> WasDealtDamageAction; + + public Action<int> OnReloadDoneAction; + + public Action<int> OutOfAmmpAction; + + internal float sinceDealtDamage; + + public bool SoundTransformScaleThresholdReached() + { + if (base.transform.localScale.x > soundBigThreshold) + { + return true; + } + return false; + } + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + public float GetSlow() + { + return Mathf.Clamp(slow, 0f, 0.9f); + } + + private void Update() + { + attackSpeedMultiplier = tasteOfBloodSpeed * rageSpeed; + sinceDealtDamage += TimeHandler.deltaTime; + if ((bool)data && !data.isPlaying) + { + sinceDealtDamage = 100f; + } + slow = slowSlow; + if (fastSlow > slowSlow) + { + slow = fastSlow; + } + if (slowSlow > 0f) + { + slowSlow = Mathf.Clamp(slowSlow - TimeHandler.deltaTime * 0.3f, 0f, 10f); + } + if (fastSlow > 0f) + { + fastSlow = Mathf.Clamp(fastSlow - TimeHandler.deltaTime * 2f, 0f, 1f); + } + } + + public void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null) + { + if (lifeSteal != 0f && !selfDamage) + { + GetComponent<HealthHandler>().Heal(damage.magnitude * lifeSteal); + } + if (refreshOnDamage) + { + GetComponent<Holding>().holdable.GetComponent<Weapon>().sinceAttack = float.PositiveInfinity; + } + if (DealtDamageAction != null) + { + DealtDamageAction(damage, selfDamage); + } + if ((bool)damagedPlayer) + { + data.lastDamagedPlayer = damagedPlayer; + } + if (!selfDamage) + { + sinceDealtDamage = 0f; + } + if (dealtDamageEffects != null) + { + for (int i = 0; i < dealtDamageEffects.Length; i++) + { + dealtDamageEffects[i].DealtDamage(damage, selfDamage, damagedPlayer); + } + } + } + + internal void ResetStats() + { + for (int i = 0; i < objectsAddedToPlayer.Count; i++) + { + UnityEngine.Object.Destroy(objectsAddedToPlayer[i]); + } + objectsAddedToPlayer.Clear(); + data.health = 100f; + data.maxHealth = 100f; + sizeMultiplier = 1f; + health = 1f; + movementSpeed = 1f; + jump = 1f; + gravity = 1f; + slow = 0f; + slowSlow = 0f; + fastSlow = 0f; + secondsToTakeDamageOver = 0f; + numberOfJumps = 0; + regen = 0f; + lifeSteal = 0f; + respawns = 0; + refreshOnDamage = false; + automaticReload = true; + tasteOfBloodSpeed = 1f; + rageSpeed = 1f; + attackSpeedMultiplier = 1f; + WasUpdated(); + ConfigureMassAndSize(); + } + + public void WasDealtDamage(Vector2 damage, bool selfDamage) + { + if (WasDealtDamageAction != null) + { + WasDealtDamageAction(damage, selfDamage); + } + if (wasDealtDamageEffects != null) + { + for (int i = 0; i < wasDealtDamageEffects.Length; i++) + { + wasDealtDamageEffects[i].WasDealtDamage(damage, selfDamage); + } + } + } + + public void WasUpdated() + { + GetComponent<ForceMultiplier>().multiplier = 1f / base.transform.root.localScale.x; + wasDealtDamageEffects = GetComponentsInChildren<WasDealtDamageEffect>(); + dealtDamageEffects = GetComponentsInChildren<DealtDamageEffect>(); + } + + public void AddSlowAddative(float slowToAdd, float maxValue = 1f, bool isFastSlow = false) + { + if (data.block.IsBlocking()) + { + return; + } + DoSlowDown(slowToAdd); + if (isFastSlow) + { + if (fastSlow < maxValue) + { + fastSlow += slowToAdd; + fastSlow = Mathf.Clamp(slow, 0f, maxValue); + } + } + else if (slowSlow < maxValue) + { + slowSlow += slowToAdd; + slowSlow = Mathf.Clamp(slowSlow, 0f, maxValue); + } + } + + [PunRPC] + public void RPCA_AddSlow(float slowToAdd, bool isFastSlow = false) + { + DoSlowDown(slowToAdd); + if (isFastSlow) + { + fastSlow = Mathf.Clamp(fastSlow, slowToAdd, 1f); + } + else + { + slowSlow = Mathf.Clamp(slowSlow, slowToAdd, 10f); + } + } + + private void DoSlowDown(float newSlow) + { + if (soundSlowTime + soundSlowSpeedSec < Time.time) + { + soundSlowTime = Time.time; + SoundManager.Instance.Play(soundCharacterSlowFreeze, base.transform); + } + float num = Mathf.Clamp(newSlow - slow, 0f, 1f); + slowPart.Emit((int)Mathf.Clamp((newSlow * 0.1f + num * 0.7f) * 50f, 1f, 50f)); + data.playerVel.velocity *= 1f - num * 1f; + data.sinceGrounded *= 1f - num * 1f; + } + + internal void ConfigureMassAndSize() + { + base.transform.localScale = Vector3.one * 1.2f * Mathf.Pow(data.maxHealth / 100f * 1.2f, 0.2f) * sizeMultiplier; + data.playerVel.mass = 100f * Mathf.Pow(data.maxHealth / 100f * 1.2f, 0.8f) * sizeMultiplier; + } + + internal void OnReload(int bulletsReloaded) + { + if (OnReloadDoneAction != null) + { + OnReloadDoneAction(bulletsReloaded); + } + } + + internal void OnOutOfAmmp(int maxAmmo) + { + if (OutOfAmmpAction != null) + { + OutOfAmmpAction(maxAmmo); + } + } +} diff --git a/GameCode/ChargeFeedback.cs b/GameCode/ChargeFeedback.cs new file mode 100644 index 0000000..322fe89 --- /dev/null +++ b/GameCode/ChargeFeedback.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +public class ChargeFeedback : MonoBehaviour +{ + private Gun gun; + + public float drag = 1f; + + public float spring = 1f; + + public float angle = 45f; + + public float chargeAngle = 15f; + + private float currentAngle; + + private float velocity; + + public float charge; + + private void Start() + { + gun = GetComponentInParent<Gun>(); + gun.AddAttackAction(Shoot); + } + + private void Update() + { + charge = 0f; + if (!gun.IsReady(0.15f)) + { + charge = 1f; + } + velocity += (charge * chargeAngle - currentAngle) * CappedDeltaTime.time * spring; + velocity -= velocity * CappedDeltaTime.time * drag; + currentAngle += CappedDeltaTime.time * velocity; + base.transform.localEulerAngles = new Vector3(currentAngle, 0f, 0f); + } + + public void Shoot() + { + velocity += (0f - angle) * 1000f * (gun.damage / 55f); + } +} diff --git a/GameCode/Chase.cs b/GameCode/Chase.cs new file mode 100644 index 0000000..1101987 --- /dev/null +++ b/GameCode/Chase.cs @@ -0,0 +1,62 @@ +using UnityEngine; +using UnityEngine.Events; + +public class Chase : MonoBehaviour +{ + public UnityEvent turnOnEvent; + + public UnityEvent turnOffEvent; + + public UnityEvent switchTargetEvent; + + private Player player; + + private LineEffect lineEffect; + + private bool isOn; + + private Player currentTarget; + + private void Start() + { + lineEffect = GetComponentInChildren<LineEffect>(includeInactive: true); + player = GetComponentInParent<Player>(); + } + + private void Update() + { + Player player = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(this.player.teamID), needVision: true); + if ((bool)player && (Vector2.Angle(player.transform.position - base.transform.position, this.player.data.input.direction) > 70f || this.player.data.input.direction == Vector3.zero)) + { + player = null; + } + if ((bool)player) + { + if (currentTarget != this.player) + { + currentTarget = this.player; + switchTargetEvent.Invoke(); + lineEffect.Play(base.transform, player.transform); + } + if (!isOn) + { + isOn = true; + turnOnEvent.Invoke(); + } + } + else + { + if (isOn) + { + isOn = false; + turnOffEvent.Invoke(); + } + if (lineEffect.isPlaying) + { + lineEffect.Stop(); + lineEffect.gameObject.SetActive(value: false); + } + currentTarget = null; + } + } +} diff --git a/GameCode/ChatFilter.cs b/GameCode/ChatFilter.cs new file mode 100644 index 0000000..91b8c96 --- /dev/null +++ b/GameCode/ChatFilter.cs @@ -0,0 +1,75 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +public class ChatFilter : MonoBehaviour +{ + [TextArea] + public string enterData; + + public string category; + + public static ChatFilter instance; + + public ChatFilterInstance[] filters; + + private void Awake() + { + instance = this; + } + + [Button] + private void EnterData() + { + string[] array = enterData.Replace('"', ' ').Trim().Split(','); + ChatFilterInstance chatFilterInstance = null; + for (int i = 0; i < filters.Length; i++) + { + if (filters[i].category == category) + { + chatFilterInstance = filters[i]; + break; + } + } + if (chatFilterInstance == null) + { + UnityEngine.Debug.LogError("No valid category target!"); + return; + } + for (int j = 0; j < array.Length; j++) + { + array[j] = array[j].Trim(); + array[j] = array[j].ToUpper(); + if (array[j] == "") + { + continue; + } + bool flag = false; + for (int k = 0; k < chatFilterInstance.words.Count; k++) + { + if (chatFilterInstance.words[k] == array[j]) + { + flag = true; + } + } + if (!flag) + { + chatFilterInstance.words.Add(array[j]); + } + } + } + + public string FilterMessage(string message) + { + for (int i = 0; i < filters.Length; i++) + { + for (int j = 0; j < filters[i].words.Count; j++) + { + if (message.ToUpper().Contains(filters[i].words[j])) + { + return filters[i].replacement; + } + } + } + return message; + } +} diff --git a/GameCode/ChatFilterInstance.cs b/GameCode/ChatFilterInstance.cs new file mode 100644 index 0000000..ef6d153 --- /dev/null +++ b/GameCode/ChatFilterInstance.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +[Serializable] +public class ChatFilterInstance +{ + public List<string> words = new List<string>(); + + public string category; + + [TextArea] + public string replacement; +} diff --git a/GameCode/ChildRPC.cs b/GameCode/ChildRPC.cs new file mode 100644 index 0000000..1305ce1 --- /dev/null +++ b/GameCode/ChildRPC.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using Photon.Pun; +using UnityEngine; + +public class ChildRPC : MonoBehaviour +{ + public Dictionary<string, Action<Vector2, Vector2, int>> childRPCsVector2Vector2Int = new Dictionary<string, Action<Vector2, Vector2, int>>(); + + public Dictionary<string, Action<Vector2, Vector2, int, int>> childRPCsVector2Vector2IntInt = new Dictionary<string, Action<Vector2, Vector2, int, int>>(); + + public Dictionary<string, Action<Vector2>> childRPCsVector2 = new Dictionary<string, Action<Vector2>>(); + + public Dictionary<string, Action<Vector3, Quaternion>> childRPCsVector3Quaternion = new Dictionary<string, Action<Vector3, Quaternion>>(); + + public Dictionary<string, Action<int>> childRPCsInt = new Dictionary<string, Action<int>>(); + + public Dictionary<string, Action> childRPCs = new Dictionary<string, Action>(); + + private PhotonView view; + + private void Start() + { + view = GetComponent<PhotonView>(); + } + + public void CallFunction(string key) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key) + { + if (childRPCs.ContainsKey(key)) + { + childRPCs[key](); + } + } + + public void CallFunction(string key, int intData) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, intData); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, int intData) + { + if (childRPCsInt.ContainsKey(key)) + { + childRPCsInt[key](intData); + } + } + + public void CallFunction(string key, Vector2 vectorData) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector2 vectorData) + { + if (childRPCsVector2.ContainsKey(key)) + { + childRPCsVector2[key](vectorData); + } + } + + public void CallFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData, vectorData2, intData); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData) + { + if (childRPCsVector2Vector2Int.ContainsKey(key)) + { + childRPCsVector2Vector2Int[key](vectorData, vectorData2, intData); + } + } + + public void CallFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData, int intData2) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData, vectorData2, intData, intData2); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData, int intData2) + { + if (childRPCsVector2Vector2IntInt.ContainsKey(key)) + { + childRPCsVector2Vector2IntInt[key](vectorData, vectorData2, intData, intData2); + } + } + + public void CallFunction(string key, Vector3 vectorData, Quaternion quaterion) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData, quaterion); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector3 vectorData, Quaternion quaterion) + { + if (childRPCsVector3Quaternion.ContainsKey(key)) + { + childRPCsVector3Quaternion[key](vectorData, quaterion); + } + } +} diff --git a/GameCode/ChillingTouch.cs b/GameCode/ChillingTouch.cs new file mode 100644 index 0000000..487ab51 --- /dev/null +++ b/GameCode/ChillingTouch.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class ChillingTouch : DamageEffect +{ + public float baseSlow = 0.2f; + + public float scalingSlow = 0.01f; + + private AttackLevel level; + + private void Start() + { + level = GetComponent<AttackLevel>(); + } + + public override void DoDamageEffect(Vector2 dmg, bool selfDmg, Player damagedPlayer = null) + { + damagedPlayer.data.stats.RPCA_AddSlow((baseSlow + dmg.magnitude * scalingSlow) * (1f + ((float)level.attackLevel - 1f) * 0.3f)); + } +} diff --git a/GameCode/ChomaticAberrationFeeler.cs b/GameCode/ChomaticAberrationFeeler.cs new file mode 100644 index 0000000..ebe7c16 --- /dev/null +++ b/GameCode/ChomaticAberrationFeeler.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class ChomaticAberrationFeeler : GameFeeler +{ + public float force = 10f; + + public float damper = 0.95f; + + public float damperSpring = 0.95f; + + public float threshold; + + private PostProcessVolume postProcessVolume; + + private ChromaticAberration chromaticAberration; + + private float intensity; + + private float velocity; + + private float targetIntensity; + + public override void OnAwake() + { + postProcessVolume = GetComponent<PostProcessVolume>(); + if (!postProcessVolume.profile.TryGetSettings<ChromaticAberration>(out chromaticAberration)) + { + Debug.LogError("No ChromaticAberration in post!"); + } + else + { + targetIntensity = chromaticAberration.intensity.value; + } + } + + public override void OnGameFeel(Vector2 feelDirection) + { + feelDirection = Vector2.ClampMagnitude(feelDirection, 50f); + if (feelDirection.magnitude < threshold) + { + feelDirection = feelDirection.normalized * threshold * 0.3f; + } + velocity += feelDirection.sqrMagnitude * 0.2f * force; + } + + private void Update() + { + velocity *= damper; + intensity *= damperSpring; + intensity += velocity * Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.02f); + chromaticAberration.intensity.value = intensity + targetIntensity; + } + + private void FixedUpdate() + { + intensity *= 0.9f; + } + + public override void OnUIGameFeel(Vector2 feelDirection) + { + } +} diff --git a/GameCode/Cluster.cs b/GameCode/Cluster.cs new file mode 100644 index 0000000..2e5c648 --- /dev/null +++ b/GameCode/Cluster.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +public class Cluster : MonoBehaviour +{ + public float distanceToTravel = 8f; + + public float spread; + + public float velocitySpread; + + public int clusters = 3; + + private MoveTransform move; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + } + + private void Update() + { + if (!(move.distanceTravelled > distanceToTravel)) + { + return; + } + for (int i = 0; i < clusters; i++) + { + GameObject obj = Object.Instantiate(base.transform.root.gameObject, base.transform.root.position, base.transform.root.rotation); + Cluster componentInChildren = obj.GetComponentInChildren<Cluster>(); + if ((bool)componentInChildren) + { + Object.Destroy(componentInChildren); + } + MoveTransform component = obj.GetComponent<MoveTransform>(); + if ((bool)component) + { + component.DontRunStart = true; + component.velocity = base.transform.root.GetComponent<MoveTransform>().velocity; + component.multiplier = base.transform.root.GetComponent<MoveTransform>().multiplier; + component.velocity += base.transform.right * Random.Range(0f - spread, spread); + component.velocity *= Random.Range(1f - velocitySpread * 0.01f, 1f + velocitySpread * 0.01f); + } + } + Object.Destroy(this); + } +} diff --git a/GameCode/CodeAnimation.cs b/GameCode/CodeAnimation.cs new file mode 100644 index 0000000..ae132b3 --- /dev/null +++ b/GameCode/CodeAnimation.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +public class CodeAnimation : MonoBehaviour +{ + [HideInInspector] + public bool isPlaying; + + public bool loonIn; + + public bool playInOnAwake; + + public bool playInOnEnable; + + public float enablePlayDelay; + + public bool interuptAnimations = true; + + public bool setFirstFrame; + + public bool useTimeScale = true; + + private Vector3 defaultScale; + + private Vector3 defaultLocalPosition; + + private Vector3 defaultRectPosition; + + private Vector3 defaultLocalRotation; + + public CodeAnimationInstance[] animations; + + private RectTransform rectTransform; + + [HideInInspector] + public CodeAnimationInstance.AnimationUse currentState; + + [HideInInspector] + public float animationValue; + + private Action AnimationChangeAction; + + public void Start() + { + currentState = CodeAnimationInstance.AnimationUse.None; + rectTransform = GetComponent<RectTransform>(); + for (int i = 0; i < animations.Length; i++) + { + animations[i].animationSpeed += UnityEngine.Random.Range((0f - animations[i].animationSpeed) * animations[i].randomSpeedAmount, animations[i].animationSpeed * animations[i].randomSpeedAmount); + if (animations[i].animationUse == CodeAnimationInstance.AnimationUse.In) + { + float num = animations[i].curve[animations[i].curve.length - 1].value - animations[i].curve[0].value; + if ((bool)rectTransform && animations[i].animationType == CodeAnimationInstance.AnimationType.rectPosition) + { + rectTransform.anchoredPosition += num * (Vector2)animations[i].direction * (0f - animations[i].multiplier); + } + } + } + SetDefaults(); + if (playInOnAwake) + { + PlayIn(); + } + if (setFirstFrame) + { + ApplyValues(animations[0], 0f); + } + } + + private void OnEnable() + { + if (playInOnEnable) + { + StartCoroutine(DelayEnablePlay()); + } + } + + private IEnumerator DelayEnablePlay() + { + yield return new WaitForSecondsRealtime(enablePlayDelay); + PlayIn(); + } + + private void SetDefaults() + { + defaultScale = base.transform.localScale; + defaultLocalPosition = base.transform.localPosition; + defaultLocalRotation = base.transform.localRotation.eulerAngles; + if ((bool)rectTransform) + { + defaultRectPosition = rectTransform.anchoredPosition; + } + } + + public void Animate(CodeAnimationInstance.AnimationUse use) + { + currentState = use; + if (interuptAnimations) + { + StopAllCoroutines(); + } + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].animationUse == use) + { + StartCoroutine(PlayAnimations(animations[i])); + } + } + } + + [Button] + public void PlayIn() + { + Animate(CodeAnimationInstance.AnimationUse.In); + } + + [Button] + public void PlayOut() + { + Animate(CodeAnimationInstance.AnimationUse.Out); + } + + [Button] + public void PlayBoop() + { + Animate(CodeAnimationInstance.AnimationUse.Boop); + } + + private IEnumerator PlayAnimations(CodeAnimationInstance animation) + { + isPlaying = true; + animation.startEvent.Invoke(); + StartCoroutine(DelayTimedEvent(animation.eventTiming / animation.animationSpeed, animation.timedEvent)); + float t = animation.curve.keys[animation.curve.keys.Length - 1].time; + float c = 0f; + while (c < t) + { + ApplyValues(animation, c); + c += (useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime) * animation.animationSpeed; + yield return null; + } + ApplyValues(animation, t); + isPlaying = false; + animation.endEvent.Invoke(); + if (loonIn) + { + PlayIn(); + } + } + + private void ApplyValues(CodeAnimationInstance animation, float time) + { + if (animation.animationType == CodeAnimationInstance.AnimationType.rectPosition && (bool)rectTransform) + { + rectTransform.anchoredPosition = defaultRectPosition + animation.direction * animation.curve.Evaluate(time) * animation.multiplier; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.position) + { + base.transform.localPosition = defaultLocalPosition + animation.direction * animation.curve.Evaluate(time) * animation.multiplier; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.scale) + { + Vector3 localScale = defaultScale * animation.curve.Evaluate(time) * animation.multiplier; + if (!animation.X) + { + localScale.x = base.transform.localScale.x; + } + if (!animation.Y) + { + localScale.y = base.transform.localScale.y; + } + if (!animation.Z) + { + localScale.z = base.transform.localScale.z; + } + base.transform.localScale = localScale; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.floatNumber) + { + animationValue = animation.curve.Evaluate(time) * animation.multiplier; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.rotation) + { + base.transform.localRotation = Quaternion.Euler(animation.curve.Evaluate(time) * animation.direction + defaultLocalRotation); + } + if (AnimationChangeAction != null) + { + AnimationChangeAction(); + } + } + + public void AddAnimationChangeAction(Action action) + { + AnimationChangeAction = (Action)Delegate.Combine(AnimationChangeAction, action); + } + + private IEnumerator DelayTimedEvent(float time, UnityEvent eventToCall) + { + yield return new WaitForSeconds(time); + eventToCall.Invoke(); + } +} diff --git a/GameCode/CodeAnimationInstance.cs b/GameCode/CodeAnimationInstance.cs new file mode 100644 index 0000000..be847e3 --- /dev/null +++ b/GameCode/CodeAnimationInstance.cs @@ -0,0 +1,62 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +[Serializable] +public class CodeAnimationInstance +{ + public enum AnimationType + { + position, + scale, + rectPosition, + floatNumber, + rotation + } + + public enum AnimationUse + { + In, + Out, + None, + Boop + } + + public float animationSpeed = 1f; + + [FoldoutGroup("Random", 0)] + public float randomSpeedAmount; + + [FoldoutGroup("USE", 0)] + public bool X = true; + + [FoldoutGroup("USE", 0)] + public bool Y = true; + + [FoldoutGroup("USE", 0)] + public bool Z = true; + + [Space(15f)] + public AnimationType animationType; + + public AnimationUse animationUse; + + public AnimationCurve curve; + + public float multiplier = 1f; + + public Vector3 direction; + + [FoldoutGroup("Events", 0)] + public UnityEvent startEvent; + + [FoldoutGroup("Events", 0)] + public UnityEvent timedEvent; + + [FoldoutGroup("Events", 0)] + public float eventTiming; + + [FoldoutGroup("Events", 0)] + public UnityEvent endEvent; +} diff --git a/GameCode/CollisionChecker.cs b/GameCode/CollisionChecker.cs new file mode 100644 index 0000000..a344911 --- /dev/null +++ b/GameCode/CollisionChecker.cs @@ -0,0 +1,41 @@ +using System; +using UnityEngine; + +public class CollisionChecker : MonoBehaviour +{ + private CharacterData data; + + public Action<Collision2D> collisionAction; + + private void Awake() + { + data = GetComponent<CharacterData>(); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + Collide(collision); + } + + private void OnCollisionStay2D(Collision2D collision) + { + Collide(collision); + } + + private void Collide(Collision2D collision) + { + if (collisionAction != null) + { + collisionAction(collision); + } + if (Vector3.Angle(Vector3.up, collision.contacts[0].normal) > 70f) + { + Vector3.Angle(Vector3.up, collision.contacts[0].normal); + _ = 110f; + } + else + { + data.TouchGround(collision.contacts[0].point, collision.contacts[0].normal, collision.otherRigidbody, collision.transform); + } + } +} diff --git a/GameCode/ColorBlink.cs b/GameCode/ColorBlink.cs new file mode 100644 index 0000000..35ebf03 --- /dev/null +++ b/GameCode/ColorBlink.cs @@ -0,0 +1,42 @@ +using System.Collections; +using UnityEngine; + +public class ColorBlink : MonoBehaviour +{ + public Color blinkColor; + + public float timeAmount; + + private Color defaultColor; + + private SpriteRenderer sprite; + + private bool inited; + + private void Start() + { + if (!inited) + { + inited = true; + sprite = GetComponent<SpriteRenderer>(); + defaultColor = sprite.color; + } + } + + public void DoBlink() + { + StopAllCoroutines(); + StartCoroutine(IDoBlink()); + } + + private IEnumerator IDoBlink() + { + if (!sprite) + { + Start(); + } + sprite.color = blinkColor; + yield return new WaitForSeconds(timeAmount); + sprite.color = defaultColor; + } +} diff --git a/GameCode/ColorHandler.cs b/GameCode/ColorHandler.cs new file mode 100644 index 0000000..b185b72 --- /dev/null +++ b/GameCode/ColorHandler.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Sirenix.OdinInspector; +using UnityEngine; + +public class ColorHandler : SerializedMonoBehaviour +{ + public enum ColorType + { + PhysicsObject + } + + public Dictionary<ColorType, Color> colors = new Dictionary<ColorType, Color>(); + + public static ColorHandler instance; + + private void Awake() + { + instance = this; + } + + public Color GetColor(ColorType colorType) + { + return colors[colorType]; + } +} diff --git a/GameCode/Comment.cs b/GameCode/Comment.cs new file mode 100644 index 0000000..020c8e3 --- /dev/null +++ b/GameCode/Comment.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +public class Comment : MonoBehaviour +{ + [TextArea(20, 100)] + public string comment; +} diff --git a/GameCode/Connected.cs b/GameCode/Connected.cs new file mode 100644 index 0000000..4ccc116 --- /dev/null +++ b/GameCode/Connected.cs @@ -0,0 +1 @@ +public delegate void Connected(); diff --git a/GameCode/ControllerImageToggler.cs b/GameCode/ControllerImageToggler.cs new file mode 100644 index 0000000..22463f4 --- /dev/null +++ b/GameCode/ControllerImageToggler.cs @@ -0,0 +1,71 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +public class ControllerImageToggler : MonoBehaviour +{ + public Sprite MKSprite; + + public Sprite controllerSprite; + + private Image img; + + private CharacterCreatorPortrait portrait; + + private CharacterSelectionInstance selector; + + private void Awake() + { + selector = GetComponentInParent<CharacterSelectionInstance>(); + portrait = GetComponentInParent<CharacterCreatorPortrait>(); + if ((bool)portrait && portrait.controlType != MenuControllerHandler.MenuControl.Unassigned) + { + Switch(portrait.controlType); + } + } + + private void Start() + { + img = GetComponent<Image>(); + MenuControllerHandler instance = MenuControllerHandler.instance; + instance.switchControlAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(instance.switchControlAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + if (!selector && portrait.controlType == MenuControllerHandler.MenuControl.Unassigned) + { + Switch(MenuControllerHandler.menuControl); + } + } + + private void Update() + { + if ((bool)selector && (bool)selector.currentPlayer) + { + if (selector.currentPlayer.data.input.inputType == GeneralInput.InputType.Controller) + { + img.sprite = controllerSprite; + } + else + { + img.sprite = MKSprite; + } + } + } + + private void Switch(MenuControllerHandler.MenuControl control) + { + if (!img) + { + img = GetComponent<Image>(); + } + if (!selector) + { + if (control == MenuControllerHandler.MenuControl.Controller) + { + img.sprite = controllerSprite; + } + else + { + img.sprite = MKSprite; + } + } + } +} diff --git a/GameCode/CooldownCondition.cs b/GameCode/CooldownCondition.cs new file mode 100644 index 0000000..51bbbf6 --- /dev/null +++ b/GameCode/CooldownCondition.cs @@ -0,0 +1,20 @@ +using UnityEngine; +using UnityEngine.Events; + +public class CooldownCondition : MonoBehaviour +{ + public UnityEvent triggerEvent; + + public float cooldown = 0.25f; + + private float lastTime = -100f; + + public void TryEvent() + { + if (!(Time.time < lastTime + cooldown)) + { + lastTime = Time.time; + triggerEvent.Invoke(); + } + } +} diff --git a/GameCode/CooldownWindUp.cs b/GameCode/CooldownWindUp.cs new file mode 100644 index 0000000..3d443a0 --- /dev/null +++ b/GameCode/CooldownWindUp.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class CooldownWindUp : MonoBehaviour +{ + public AnimationCurve multiplierCurve; + + private float currentMultiplier = 1f; + + private float startValue; + + private float currentValue; + + public float increasePerShot = 1f; + + private CooldownCondition cooldown; + + private void Start() + { + cooldown = GetComponent<CooldownCondition>(); + startValue = cooldown.cooldown; + } + + private void Update() + { + currentMultiplier = multiplierCurve.Evaluate(currentValue); + currentValue = Mathf.Clamp(currentValue, 0f, 100f); + cooldown.cooldown = startValue / currentMultiplier; + } + + public void Reset() + { + currentValue = 0f; + } + + public void Add() + { + currentValue += increasePerShot / currentMultiplier; + } +} diff --git a/GameCode/CopyChildren.cs b/GameCode/CopyChildren.cs new file mode 100644 index 0000000..6c1757d --- /dev/null +++ b/GameCode/CopyChildren.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class CopyChildren : MonoBehaviour +{ + public GameObject target; + + public void DoUpdate() + { + for (int num = base.transform.childCount - 1; num >= 0; num--) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + for (int i = 0; i < target.transform.childCount; i++) + { + Transform child = target.transform.GetChild(i); + Object.Instantiate(child.gameObject, base.transform.TransformPoint(child.localPosition), Quaternion.identity, base.transform).transform.localScale = child.localScale; + } + } + + private void Update() + { + DoUpdate(); + } +} diff --git a/GameCode/CopyObject.cs b/GameCode/CopyObject.cs new file mode 100644 index 0000000..c8ca2ed --- /dev/null +++ b/GameCode/CopyObject.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class CopyObject : MonoBehaviour +{ + public void CopySelf() + { + Object.Instantiate(base.gameObject, base.transform.position, base.transform.rotation, base.transform.parent); + } +} diff --git a/GameCode/CopyOwnerGunStats.cs b/GameCode/CopyOwnerGunStats.cs new file mode 100644 index 0000000..d9497a1 --- /dev/null +++ b/GameCode/CopyOwnerGunStats.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class CopyOwnerGunStats : MonoBehaviour +{ + private void Start() + { + ApplyCardStats.CopyGunStats(base.transform.root.GetComponent<SpawnedAttack>().spawner.GetComponent<WeaponHandler>().gun, GetComponent<Gun>()); + } +} diff --git a/GameCode/CopyPlayerAim.cs b/GameCode/CopyPlayerAim.cs new file mode 100644 index 0000000..46f2300 --- /dev/null +++ b/GameCode/CopyPlayerAim.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +public class CopyPlayerAim : MonoBehaviour +{ + public float spreadPerLevel; + + public float spread; + + private AttackLevel level; + + private void Start() + { + level = GetComponentInParent<AttackLevel>(); + } + + public void Go() + { + float num = Random.Range(0f - spread, spread); + float num2 = 0f; + if ((bool)level) + { + num2 = (float)level.attackLevel * spreadPerLevel; + } + num += Random.Range(0f - num2, num2); + Holding component = base.transform.root.GetComponent<Holding>(); + if ((bool)component) + { + base.transform.rotation = component.holdable.GetComponentInChildren<ShootPos>().transform.rotation; + } + base.transform.Rotate(Vector3.Cross(Vector3.forward, base.transform.forward) * num); + } +} diff --git a/GameCode/Cos.cs b/GameCode/Cos.cs new file mode 100644 index 0000000..d547ade --- /dev/null +++ b/GameCode/Cos.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class Cos : MonoBehaviour +{ + public float multiplier = 1f; + + private void Update() + { + base.transform.root.position += base.transform.right * Mathf.Cos(Time.time * 20f * multiplier) * 10f * multiplier * Time.smoothDeltaTime; + } +} diff --git a/GameCode/CounterUI.cs b/GameCode/CounterUI.cs new file mode 100644 index 0000000..a23dd69 --- /dev/null +++ b/GameCode/CounterUI.cs @@ -0,0 +1,59 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI.ProceduralImage; + +public class CounterUI : MonoBehaviour +{ + [Range(0f, 1f)] + public float counter; + + public float timeToFill = 10f; + + public ProceduralImage outerRing; + + public ProceduralImage fill; + + public Transform rotator; + + public Transform still; + + private float remainingDuration; + + private bool isAbyssalForm; + + private bool done; + + public UnityEvent doneEvent; + + private void ResetStuff() + { + counter = 0f; + } + + private void Update() + { + if (!done) + { + outerRing.fillAmount = counter; + fill.fillAmount = counter; + rotator.transform.localEulerAngles = new Vector3(0f, 0f, 0f - Mathf.Lerp(0f, 360f, counter)); + counter += TimeHandler.deltaTime / timeToFill; + counter = Mathf.Clamp(counter, -0.1f / timeToFill, 1f); + if (counter >= 1f) + { + done = true; + doneEvent.Invoke(); + } + if (counter <= 0f) + { + rotator.gameObject.SetActive(value: false); + still.gameObject.SetActive(value: false); + } + else + { + rotator.gameObject.SetActive(value: true); + still.gameObject.SetActive(value: true); + } + } + } +} diff --git a/GameCode/CrownPos.cs b/GameCode/CrownPos.cs new file mode 100644 index 0000000..f8cd30a --- /dev/null +++ b/GameCode/CrownPos.cs @@ -0,0 +1,16 @@ +using TMPro; +using UnityEngine; + +public class CrownPos : MonoBehaviour +{ + public TextMeshProUGUI text; + + public float GetOffset() + { + if (!(text.text == "")) + { + return 0.45f; + } + return 0f; + } +} diff --git a/GameCode/CurveAnimation.cs b/GameCode/CurveAnimation.cs new file mode 100644 index 0000000..cf4611f --- /dev/null +++ b/GameCode/CurveAnimation.cs @@ -0,0 +1,249 @@ +using System.Collections; +using Sirenix.OdinInspector; +using Sonigon; +using SoundImplementation; +using UnityEngine; +using UnityEngine.Events; + +public class CurveAnimation : MonoBehaviour +{ + [Header("Sound")] + public SoundAnimationPlay[] soundPlay = new SoundAnimationPlay[0]; + + [Header("Settings")] + public CurveAnimationInstance[] animations; + + [HideInInspector] + public Vector3 startScale; + + [HideInInspector] + public Vector3 startLocalPos; + + [HideInInspector] + public Vector3 startAnchoredPos; + + [HideInInspector] + public Vector3 startRotation; + + public CurveAnimationUse currentState = CurveAnimationUse.Out; + + private RectTransform rectTransform; + + [FoldoutGroup("Global settings", 0)] + public bool useTimeScale = true; + + [FoldoutGroup("Global settings", 0)] + public bool X = true; + + [FoldoutGroup("Global settings", 0)] + public bool Y = true; + + [FoldoutGroup("Global settings", 0)] + public bool Z = true; + + [FoldoutGroup("Global settings", 0)] + public bool stopAllAnimations; + + private bool inited; + + private void Init() + { + if (!inited) + { + startScale = base.transform.localScale; + startLocalPos = base.transform.localScale; + rectTransform = GetComponent<RectTransform>(); + if ((bool)rectTransform) + { + startAnchoredPos = rectTransform.anchoredPosition; + } + startRotation = base.transform.localEulerAngles; + } + } + + private void Awake() + { + Init(); + } + + private void OnDisable() + { + StopAllCoroutines(); + ResetAnimationState(); + for (int i = 0; i < animations.Length; i++) + { + animations[i].isPlaying = false; + } + } + + private void OnEnable() + { + ResetAnimationState(); + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].playOnAwake) + { + PlayAnimation(animations[i]); + } + } + } + + [Button] + public void PlayIn() + { + PlayAnimationWithUse(CurveAnimationUse.In); + } + + [Button] + public void PlayOut() + { + PlayAnimationWithUse(CurveAnimationUse.Out); + } + + [Button] + public void PlayBoop() + { + PlayAnimationWithUse(CurveAnimationUse.Boop); + } + + [Button] + public void Stop() + { + StopAllCoroutines(); + } + + private void ResetAnimationState() + { + ApplyAnimationFrame(GetAnimationWithUse(CurveAnimationUse.In), 0f); + } + + private CurveAnimationInstance GetAnimationWithUse(CurveAnimationUse use) + { + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].animationUse == use) + { + return animations[i]; + } + } + return animations[0]; + } + + public void PlayAnimation(CurveAnimationInstance animation) + { + for (int i = 0; i < soundPlay.Length; i++) + { + if (soundPlay[i] != null) + { + soundPlay[i].soundHasPlayed = false; + } + } + if (stopAllAnimations) + { + StopAllCoroutines(); + } + if (animation.isPlaying && animation.animation != null) + { + StopCoroutine(animation.animation); + } + animation.animation = StartCoroutine(DoAnimation(animation)); + } + + public void PlayAnimationWithUse(CurveAnimationUse animationUse) + { + for (int i = 0; i < soundPlay.Length; i++) + { + if (soundPlay[i] != null) + { + soundPlay[i].soundHasPlayed = false; + } + } + if (stopAllAnimations) + { + StopAllCoroutines(); + } + currentState = animationUse; + for (int j = 0; j < animations.Length; j++) + { + if (animations[j].animationUse == animationUse) + { + if (animations[j].isPlaying && animations[j].animation != null) + { + StopCoroutine(animations[j].animation); + } + animations[j].animation = StartCoroutine(DoAnimation(animations[j])); + } + } + } + + private IEnumerator DoAnimation(CurveAnimationInstance animation) + { + StartCoroutine(DelayEvent(animation.delay / animation.speed, animation.delayedEvent)); + animation.statEvent.Invoke(); + animation.isPlaying = true; + float c = 0f; + float t = animation.Curve().keys[animation.Curve().keys.Length - 1].time; + while (c < t) + { + c += (useTimeScale ? (TimeHandler.deltaTime * animation.speed) : (Time.unscaledDeltaTime * animation.speed)); + for (int i = 0; i < soundPlay.Length; i++) + { + if (soundPlay[i] != null && soundPlay[i].soundEvent != null && c >= soundPlay[i].soundDelay && animation.animationUse == soundPlay[i].curveAnimationUse && !soundPlay[i].soundHasPlayed && (bool)SoundManager.Instance) + { + soundPlay[i].soundHasPlayed = true; + SoundManager.Instance.Play(soundPlay[i].soundEvent, base.transform); + } + } + ApplyAnimationFrame(animation, c); + yield return null; + } + ApplyAnimationFrame(animation, t); + animation.isPlaying = false; + animation.endEvent.Invoke(); + if (animation.loop) + { + PlayAnimationWithUse(animation.animationUse); + } + } + + private IEnumerator DelayEvent(float seconds, UnityEvent eventToCall) + { + yield return new WaitForSeconds(seconds); + eventToCall.Invoke(); + } + + private void ApplyAnimationFrame(CurveAnimationInstance anim, float time) + { + if (anim.animationType == CurveAnimationType.Scale) + { + Vector3 vector = startScale * anim.Curve().Evaluate(time) * anim.multiplier; + Vector3 localScale = new Vector3(X ? vector.x : base.transform.localScale.x, Y ? vector.y : base.transform.localScale.y, Z ? vector.z : base.transform.localScale.z); + base.transform.localScale = localScale; + } + else if (anim.animationType == CurveAnimationType.Position) + { + base.transform.localPosition = startLocalPos + anim.animDirection * anim.Curve().Evaluate(time) * anim.multiplier; + } + else if (anim.animationType == CurveAnimationType.RectPosition) + { + rectTransform.anchoredPosition = startAnchoredPos + anim.animDirection * anim.Curve().Evaluate(time) * anim.multiplier; + } + else if (anim.animationType == CurveAnimationType.Rotation) + { + base.transform.localEulerAngles = startRotation + anim.animDirection * anim.Curve().Evaluate(time) * anim.multiplier; + } + } + + public bool IsPlaying() + { + bool result = false; + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].isPlaying) + { + result = true; + } + } + return result; + } +} diff --git a/GameCode/CurveAnimationInstance.cs b/GameCode/CurveAnimationInstance.cs new file mode 100644 index 0000000..6d5ed2f --- /dev/null +++ b/GameCode/CurveAnimationInstance.cs @@ -0,0 +1,73 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +[Serializable] +public class CurveAnimationInstance +{ + [FoldoutGroup("$animationUse", 0)] + public CurveAnimationType animationType; + + [FoldoutGroup("$animationUse", 0)] + public CurveAnimationUse animationUse; + + [ShowIf("animationUse", CurveAnimationUse.In, true)] + [FoldoutGroup("$animationUse", 0)] + public AnimationCurve inCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f); + + [ShowIf("animationUse", CurveAnimationUse.Out, true)] + [FoldoutGroup("$animationUse", 0)] + public AnimationCurve outCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f); + + [ShowIf("animationUse", CurveAnimationUse.Boop, true)] + [FoldoutGroup("$animationUse", 0)] + public AnimationCurve boopCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [HideIf("animationType", CurveAnimationType.Scale, true)] + [FoldoutGroup("$animationUse", 0)] + public Vector3 animDirection; + + [FoldoutGroup("$animationUse/Settings", 0)] + public bool loop; + + [FoldoutGroup("$animationUse/Settings", 0)] + public bool playOnAwake; + + [FoldoutGroup("$animationUse/Settings", 0)] + public float speed = 1f; + + [FoldoutGroup("$animationUse/Settings", 0)] + public float multiplier = 1f; + + [FoldoutGroup("$animationUse/Events", 0)] + public UnityEvent statEvent; + + [FoldoutGroup("$animationUse/Events", 0)] + public UnityEvent endEvent; + + [FoldoutGroup("$animationUse/Events", 0)] + public UnityEvent delayedEvent; + + [FoldoutGroup("$animationUse/Events", 0)] + public float delay; + + [FoldoutGroup("$animationUse/Debug", 0, Order = 0, Expanded = false)] + public bool isPlaying; + + [HideInInspector] + public Coroutine animation; + + public AnimationCurve Curve() + { + if (animationUse == CurveAnimationUse.Boop) + { + return boopCurve; + } + if (animationUse != 0) + { + return outCurve; + } + return inCurve; + } +} diff --git a/GameCode/CurveAnimationType.cs b/GameCode/CurveAnimationType.cs new file mode 100644 index 0000000..ad2e885 --- /dev/null +++ b/GameCode/CurveAnimationType.cs @@ -0,0 +1,7 @@ +public enum CurveAnimationType +{ + Scale, + Position, + RectPosition, + Rotation +} diff --git a/GameCode/CurveAnimationUse.cs b/GameCode/CurveAnimationUse.cs new file mode 100644 index 0000000..f56a698 --- /dev/null +++ b/GameCode/CurveAnimationUse.cs @@ -0,0 +1,6 @@ +public enum CurveAnimationUse +{ + In, + Out, + Boop +} diff --git a/GameCode/Damagable.cs b/GameCode/Damagable.cs new file mode 100644 index 0000000..69afa0a --- /dev/null +++ b/GameCode/Damagable.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public abstract class Damagable : MonoBehaviour +{ + public abstract void CallTakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true); + + public abstract void TakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false); + + public abstract void TakeDamage(Vector2 damage, Vector2 damagePosition, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false); +} diff --git a/GameCode/DamagableEvent.cs b/GameCode/DamagableEvent.cs new file mode 100644 index 0000000..3d70256 --- /dev/null +++ b/GameCode/DamagableEvent.cs @@ -0,0 +1,134 @@ +using System; +using Photon.Pun; +using UnityEngine; +using UnityEngine.Events; + +public class DamagableEvent : Damagable +{ + public bool networkedDamage; + + public bool disabled; + + [HideInInspector] + public bool dead; + + public float currentHP = 100f; + + public float regenDelay = 1f; + + public float regenPerSecond; + + [HideInInspector] + public float maxHP = 100f; + + public UnityEvent damageEvent; + + public UnityEvent deathEvent; + + private float sinceDamage = 1f; + + [HideInInspector] + public Player lastPlayer; + + [HideInInspector] + public GameObject lastWeapon; + + private PhotonView view; + + public Action<Vector2> DieAction; + + private void Start() + { + view = GetComponent<PhotonView>(); + maxHP = currentHP; + } + + public override void TakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (disabled || dead) + { + return; + } + if (networkedDamage) + { + if ((bool)damagingPlayer) + { + if (!damagingPlayer.data.view.IsMine) + { + return; + } + view.RPC("RPCA_TakeDamage", RpcTarget.Others, damage, damagePosition); + } + else + { + if (!view.IsMine) + { + return; + } + view.RPC("RPCA_TakeDamage", RpcTarget.Others, damage, damagePosition); + } + } + DoDamage(damage, damagePosition, damagingWeapon, damagingPlayer, lethal, ignoreBlock); + } + + [PunRPC] + public void RPCA_TakeDamage(Vector2 damage, Vector2 damagePosition) + { + DoDamage(damage, damagePosition); + } + + private void DoDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if ((bool)damagingPlayer) + { + lastPlayer = damagingPlayer; + } + if ((bool)damagingWeapon) + { + lastWeapon = damagingWeapon; + } + sinceDamage = 0f; + currentHP -= damage.magnitude; + if (currentHP <= 0f) + { + Die(damage); + } + else + { + damageEvent.Invoke(); + } + } + + private void Die(Vector2 damage = default(Vector2)) + { + if (!dead && !disabled) + { + DieAction?.Invoke(damage); + deathEvent.Invoke(); + dead = true; + } + } + + private void Update() + { + if (!dead && !disabled) + { + sinceDamage += TimeHandler.deltaTime; + if (sinceDamage > regenDelay && currentHP < maxHP) + { + currentHP += regenPerSecond * TimeHandler.deltaTime; + currentHP = Mathf.Clamp(currentHP, float.NegativeInfinity, maxHP); + } + } + } + + public override void TakeDamage(Vector2 damage, Vector2 damagePosition, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + TakeDamage(damage, damagePosition, damagingWeapon, damagingPlayer, lethal); + } + + public override void CallTakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + TakeDamage(damage, damagePosition, Color.red, damagingWeapon, damagingPlayer, lethal); + } +} diff --git a/GameCode/DamageBox.cs b/GameCode/DamageBox.cs new file mode 100644 index 0000000..e86d79f --- /dev/null +++ b/GameCode/DamageBox.cs @@ -0,0 +1,96 @@ +using Sonigon; +using UnityEngine; + +public class DamageBox : MonoBehaviour +{ + [Header("Sound")] + public bool soundPlaySawDamage; + + public SoundEvent soundSawDamage; + + [Header("Settings")] + public bool towardsCenterOfMap; + + public bool awayFromMe; + + public float damage = 25f; + + public float force; + + public float setFlyingFor; + + public float shake; + + public float cd = 0.3f; + + public bool ignoreBlock; + + public ParticleSystem dmgPart; + + private float time; + + private SpawnedAttack spawned; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + Collide(collision); + } + + private void OnCollisionStay2D(Collision2D collision) + { + Collide(collision); + } + + private void Collide(Collision2D collision) + { + if (Time.time < time + cd) + { + return; + } + Vector3 vector = base.transform.root.forward; + if (towardsCenterOfMap) + { + vector = -collision.contacts[0].point.normalized; + } + if (awayFromMe) + { + vector = (collision.transform.position - base.transform.position).normalized; + } + Damagable componentInParent = collision.transform.GetComponentInParent<Damagable>(); + if (!componentInParent) + { + return; + } + time = Time.time; + HealthHandler component = componentInParent.GetComponent<HealthHandler>(); + CharacterData component2 = component.GetComponent<CharacterData>(); + if (!component2 || component2.view.IsMine) + { + if ((bool)component) + { + component.CallTakeForce(vector * force, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock, setFlyingFor); + } + componentInParent.CallTakeDamage(damage * vector, base.transform.position, null, (spawned != null) ? spawned.spawner : null); + if (soundPlaySawDamage) + { + SoundManager.Instance.PlayAtPosition(soundSawDamage, SoundManager.Instance.GetTransform(), base.transform); + } + if ((bool)dmgPart) + { + Vector3 forward = vector; + vector.z = 0f; + dmgPart.transform.parent.rotation = Quaternion.LookRotation(forward); + dmgPart.Play(); + } + if (shake != 0f) + { + component2.player.Call_AllGameFeel(shake * (Vector2)vector); + } + } + } +} diff --git a/GameCode/DamageEffect.cs b/GameCode/DamageEffect.cs new file mode 100644 index 0000000..d8d4907 --- /dev/null +++ b/GameCode/DamageEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class DamageEffect : MonoBehaviour +{ + public abstract void DoDamageEffect(Vector2 dmg, bool selfDmg, Player damagedPlayer = null); +} diff --git a/GameCode/DamageOverTime.cs b/GameCode/DamageOverTime.cs new file mode 100644 index 0000000..c1c6a17 --- /dev/null +++ b/GameCode/DamageOverTime.cs @@ -0,0 +1,38 @@ +using System.Collections; +using Sonigon; +using UnityEngine; + +public class DamageOverTime : MonoBehaviour +{ + private HealthHandler health; + + private CharacterData data; + + private void Start() + { + health = GetComponent<HealthHandler>(); + data = GetComponent<CharacterData>(); + } + + public void TakeDamageOverTime(Vector2 damage, Vector2 position, float time, float interval, Color color, SoundEvent soundDamageOverTime, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + StartCoroutine(DoDamageOverTime(damage, position, time, interval, color, soundDamageOverTime, damagingWeapon, damagingPlayer, lethal)); + } + + private IEnumerator DoDamageOverTime(Vector2 damage, Vector2 position, float time, float interval, Color color, SoundEvent soundDamageOverTime, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + float damageDealt = 0f; + float damageToDeal = damage.magnitude; + float dpt = damageToDeal / time * interval; + while (damageDealt < damageToDeal) + { + if (soundDamageOverTime != null && data.isPlaying && !data.dead) + { + SoundManager.Instance.Play(soundDamageOverTime, base.transform); + } + damageDealt += dpt; + health.DoDamage(damage.normalized * dpt, position, color, damagingWeapon, damagingPlayer, healthRemoval: true, lethal); + yield return new WaitForSeconds(interval / TimeHandler.timeScale); + } + } +} diff --git a/GameCode/DealDamageToPlayer.cs b/GameCode/DealDamageToPlayer.cs new file mode 100644 index 0000000..bfad181 --- /dev/null +++ b/GameCode/DealDamageToPlayer.cs @@ -0,0 +1,47 @@ +using Sonigon; +using UnityEngine; + +public class DealDamageToPlayer : MonoBehaviour +{ + public enum TargetPlayer + { + Own, + Other + } + + [Header("Sounds")] + public SoundEvent soundDamage; + + [Header("Settings")] + public float damage = 25f; + + public bool lethal = true; + + public TargetPlayer targetPlayer; + + private CharacterData data; + + private Player target; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + public void Go() + { + if (!target) + { + target = data.player; + if (targetPlayer == TargetPlayer.Other) + { + target = PlayerManager.instance.GetOtherPlayer(target); + } + } + if (soundDamage != null && target != null && target.data != null && target.data.isPlaying && !target.data.dead && !target.data.block.IsBlocking()) + { + SoundManager.Instance.Play(soundDamage, target.transform); + } + target.data.healthHandler.TakeDamage(damage * Vector2.up, base.transform.position, null, data.player, lethal); + } +} diff --git a/GameCode/DealtDamageEffect.cs b/GameCode/DealtDamageEffect.cs new file mode 100644 index 0000000..ec5cddc --- /dev/null +++ b/GameCode/DealtDamageEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class DealtDamageEffect : MonoBehaviour +{ + public abstract void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null); +} diff --git a/GameCode/DealtDamageTrigger.cs b/GameCode/DealtDamageTrigger.cs new file mode 100644 index 0000000..d596b4d --- /dev/null +++ b/GameCode/DealtDamageTrigger.cs @@ -0,0 +1,19 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class DealtDamageTrigger : MonoBehaviour +{ + public UnityEvent triggerEvent; + + private void Start() + { + CharacterStatModifiers stats = GetComponentInParent<Player>().data.stats; + stats.DealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(stats.DealtDamageAction, new Action<Vector2, bool>(DealtDamage)); + } + + private void DealtDamage(Vector2 dmg, bool lethal) + { + triggerEvent.Invoke(); + } +} diff --git a/GameCode/DeathEffect.cs b/GameCode/DeathEffect.cs new file mode 100644 index 0000000..5819e64 --- /dev/null +++ b/GameCode/DeathEffect.cs @@ -0,0 +1,101 @@ +using System.Collections; +using Sonigon; +using UnityEngine; + +public class DeathEffect : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundPhoenixActivate; + + public SoundEvent soundPhoenixChargeLoop; + + public SoundEvent soundPhoenixRespawn; + + private SoundParameterIntensity soundParameterChargeLoopIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + [Header("Settings")] + public float forceMulti = 1f; + + public float minScale = 0.9f; + + public float maxScale = 1.1f; + + public float minDrag = 0.9f; + + public float maxDrag = 1.1f; + + public float minForce = 0.9f; + + public float maxForce = 1.1f; + + public float spread = 0.5f; + + private Rigidbody2D[] rigs; + + private Color baseColor; + + private ParticleSystem[] parts; + + public ParticleSystem partToColor; + + public ParticleSystem[] partsToColor; + + private float respawnTimeCurrent; + + private float respawnTime = 2.53f; + + private void Update() + { + } + + public void PlayDeath(Color color, PlayerVelocity playerRig, Vector2 vel, int playerIDToRevive = -1) + { + if (vel.magnitude < 30f) + { + vel = vel.normalized * 30f; + } + vel *= 1f; + parts = GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < parts.Length; i++) + { + _ = parts[i].main; + if (parts[i].name.Contains("ROT")) + { + parts[i].transform.rotation = Quaternion.LookRotation(vel); + } + } + ParticleSystem.MainModule main = partToColor.main; + main.startColor = PlayerSkinBank.GetPlayerSkinColors(playerRig.GetComponent<Player>().playerID).color; + for (int j = 0; j < partsToColor.Length; j++) + { + ParticleSystem.MainModule main2 = partsToColor[j].main; + main2.startColor = PlayerSkinBank.GetPlayerSkinColors(playerRig.GetComponent<Player>().playerID).color; + } + if (playerIDToRevive != -1) + { + SoundManager.Instance.Play(soundPhoenixActivate, base.transform); + SoundManager.Instance.Play(soundPhoenixChargeLoop, base.transform, soundParameterChargeLoopIntensity); + StartCoroutine(RespawnPlayer(playerIDToRevive)); + } + } + + private IEnumerator RespawnPlayer(int playerIDToRevive = -1) + { + while (respawnTimeCurrent < respawnTime) + { + soundParameterChargeLoopIntensity.intensity = respawnTimeCurrent / respawnTime; + respawnTimeCurrent += 0.1f; + yield return new WaitForSeconds(0.1f); + } + SoundManager.Instance.Play(soundPhoenixRespawn, base.transform); + SoundManager.Instance.Stop(soundPhoenixChargeLoop, base.transform); + PlayerManager.instance.players[playerIDToRevive].data.healthHandler.Revive(isFullRevive: false); + PlayerManager.instance.players[playerIDToRevive].data.block.RPCA_DoBlock(firstBlock: true); + } + + private IEnumerator DoEffect(Rigidbody2D rig) + { + yield return new WaitForSeconds(Random.Range(0.05f, 0.15f)); + rig.GetComponent<SpriteRenderer>().color = baseColor; + } +} diff --git a/GameCode/Debug.cs b/GameCode/Debug.cs new file mode 100644 index 0000000..b35bd1d --- /dev/null +++ b/GameCode/Debug.cs @@ -0,0 +1,53 @@ +using System; +using UnityEngine; + +public static class Debug +{ + public static void Log(object logMsg) + { + } + + public static void Log(string logMsg) + { + } + + public static void Log(Exception exeption) + { + } + + public static void LogError(string logMsg) + { + } + + public static void LogError(string logMsg, object ob) + { + } + + public static void LogError(string logMsg, GameObject go) + { + } + + public static void LogWarning(string logMsg) + { + } + + public static void LogWarning(string logMsg, object ob) + { + } + + public static void ClearDeveloperConsole() + { + } + + public static void Assert(Transform t, string m) + { + } + + public static void DrawLine(Vector3 v1, Vector3 v2, Color c, float t) + { + } + + public static void DrawLine(Vector3 v1, Vector3 v2, Color c) + { + } +} diff --git a/GameCode/DelayEvent.cs b/GameCode/DelayEvent.cs new file mode 100644 index 0000000..0ebea56 --- /dev/null +++ b/GameCode/DelayEvent.cs @@ -0,0 +1,61 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Events; + +public class DelayEvent : MonoBehaviour +{ + public UnityEvent delayedEvent; + + public float time = 1f; + + public bool auto; + + public bool repeating; + + public bool usedTimeScale = true; + + private void Start() + { + CodeAnimation componentInParent = GetComponentInParent<CodeAnimation>(); + if ((bool)componentInParent) + { + time /= componentInParent.animations[0].animationSpeed; + } + if (auto) + { + Go(); + } + } + + public void Go() + { + StartCoroutine(DelayEventCall()); + } + + private IEnumerator DelayEventCall() + { + yield return 1; + if (usedTimeScale) + { + yield return new WaitForSeconds(time); + } + else + { + yield return new WaitForSecondsRealtime(time); + } + if (base.enabled) + { + delayedEvent.Invoke(); + if (repeating) + { + Go(); + } + } + } + + public void DoEvent() + { + StopAllCoroutines(); + delayedEvent.Invoke(); + } +} diff --git a/GameCode/DelayedEvent.cs b/GameCode/DelayedEvent.cs new file mode 100644 index 0000000..cfde350 --- /dev/null +++ b/GameCode/DelayedEvent.cs @@ -0,0 +1,14 @@ +using System; +using UnityEngine.Events; + +[Serializable] +public class DelayedEvent +{ + public UnityEvent eventTrigger; + + public float delay; + + public int cycles = 1; + + public int cyclesPerLvl; +} diff --git a/GameCode/DestroyEvent.cs b/GameCode/DestroyEvent.cs new file mode 100644 index 0000000..2e4fe63 --- /dev/null +++ b/GameCode/DestroyEvent.cs @@ -0,0 +1,22 @@ +using UnityEngine; +using UnityEngine.Events; + +public class DestroyEvent : MonoBehaviour +{ + public UnityEvent deathEvent; + + private bool m_isQuitting; + + private void OnDestroy() + { + if (!m_isQuitting) + { + deathEvent.Invoke(); + } + } + + private void OnApplicationQuit() + { + m_isQuitting = true; + } +} diff --git a/GameCode/DestroyObjects.cs b/GameCode/DestroyObjects.cs new file mode 100644 index 0000000..8cb52e2 --- /dev/null +++ b/GameCode/DestroyObjects.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public class DestroyObjects : MonoBehaviour +{ + public GameObject[] objectsToDestroy; + + public void DestroySelf() + { + Object.Destroy(base.gameObject); + } + + public void DestroyAllObjects() + { + for (int i = 0; i < objectsToDestroy.Length; i++) + { + Object.Destroy(objectsToDestroy[i]); + } + } +} diff --git a/GameCode/DestroyOnAwake.cs b/GameCode/DestroyOnAwake.cs new file mode 100644 index 0000000..47d4227 --- /dev/null +++ b/GameCode/DestroyOnAwake.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class DestroyOnAwake : MonoBehaviour +{ + private void Awake() + { + Object.Destroy(base.gameObject); + } +} diff --git a/GameCode/Destructible.cs b/GameCode/Destructible.cs new file mode 100644 index 0000000..e2b71b0 --- /dev/null +++ b/GameCode/Destructible.cs @@ -0,0 +1,45 @@ +using System; +using UnityEngine; + +public class Destructible : Damagable +{ + public float threshold = 25f; + + public float force = 1f; + + public float rangeMulti = 1f; + + public override void CallTakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + throw new NotImplementedException(); + } + + public override void TakeDamage(Vector2 damage, Vector2 position, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (!(damage.magnitude < threshold)) + { + damage = damage.normalized * 100f; + Transform[] array = new Transform[base.transform.childCount]; + for (int i = 0; i < array.Length; i++) + { + array[i] = base.transform.GetChild(i); + } + foreach (Transform transform in array) + { + transform.gameObject.SetActive(value: true); + transform.SetParent(null, worldPositionStays: true); + float num = damage.magnitude * 0.02f * rangeMulti; + float num2 = Mathf.Clamp((num - Vector2.Distance(transform.position, position)) / num, 0f, 1f); + Rigidbody2D component = transform.GetComponent<Rigidbody2D>(); + component.AddForce(damage * num2 * force * 0.1f * component.mass, ForceMode2D.Impulse); + transform.gameObject.AddComponent<RemoveAfterSeconds>().seconds = UnityEngine.Random.Range(1f, 3f); + } + base.gameObject.SetActive(value: false); + } + } + + public override void TakeDamage(Vector2 damage, Vector2 damagePosition, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + TakeDamage(damage, damagePosition, dmgColor, damagingWeapon, damagingPlayer, lethal); + } +} diff --git a/GameCode/DestructibleBoxDestruction.cs b/GameCode/DestructibleBoxDestruction.cs new file mode 100644 index 0000000..d7f7fb8 --- /dev/null +++ b/GameCode/DestructibleBoxDestruction.cs @@ -0,0 +1,40 @@ +using System; +using Sonigon; +using UnityEngine; + +public class DestructibleBoxDestruction : MonoBehaviour +{ + public bool soundPlayDestruction; + + public SoundEvent soundBoxDestruction; + + private void Start() + { + DamagableEvent componentInParent = GetComponentInParent<DamagableEvent>(); + componentInParent.DieAction = (Action<Vector2>)Delegate.Combine(componentInParent.DieAction, new Action<Vector2>(Die)); + } + + private void Die(Vector2 dmg) + { + if (soundPlayDestruction) + { + SoundManager.Instance.PlayAtPosition(soundBoxDestruction, SoundManager.Instance.GetTransform(), base.transform); + } + Rigidbody2D[] componentsInChildren = GetComponentsInChildren<Rigidbody2D>(includeInactive: true); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (base.transform != componentsInChildren[i].transform) + { + componentsInChildren[i].transform.SetParent(base.transform.root); + componentsInChildren[i].transform.gameObject.SetActive(value: true); + componentsInChildren[i].AddForce(dmg * UnityEngine.Random.Range(0f, 1f) * 500f, ForceMode2D.Impulse); + componentsInChildren[i].AddTorque(UnityEngine.Random.Range(-1f, 1f) * 1000f, ForceMode2D.Impulse); + componentsInChildren[i].GetComponent<RemoveAfterSeconds>().seconds = UnityEngine.Random.Range(0f, 0.5f); + componentsInChildren[i].GetComponentInChildren<GetColor>().Start(); + componentsInChildren[i].GetComponentInChildren<ColorBlink>().timeAmount *= UnityEngine.Random.Range(0.5f, 2f); + componentsInChildren[i].GetComponentInChildren<ColorBlink>().DoBlink(); + componentsInChildren[i].gameObject.layer = 18; + } + } + } +} diff --git a/GameCode/DevConsole.cs b/GameCode/DevConsole.cs new file mode 100644 index 0000000..e972cba --- /dev/null +++ b/GameCode/DevConsole.cs @@ -0,0 +1,128 @@ +using Photon.Pun; +using TMPro; +using UnityEngine; + +public class DevConsole : MonoBehaviour +{ + public TMP_InputField inputField; + + public static bool isTyping; + + private void Start() + { + isTyping = false; + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.Return)) + { + inputField.gameObject.SetActive(!inputField.gameObject.activeSelf); + isTyping = inputField.gameObject.activeSelf; + GameManager.lockInput = isTyping; + if (inputField.gameObject.activeSelf) + { + inputField.ActivateInputField(); + } + else + { + Send(inputField.text); + } + } + } + + private void Send(string message) + { + if (Application.isEditor || ((bool)GM_Test.instance && GM_Test.instance.gameObject.activeSelf)) + { + SpawnCard(message); + } + if (Application.isEditor) + { + SpawnMap(message); + } + int viewID = PlayerManager.instance.GetPlayerWithActorID(PhotonNetwork.LocalPlayer.ActorNumber).data.view.ViewID; + GetComponent<PhotonView>().RPC("RPCA_SendChat", RpcTarget.All, message, viewID); + } + + private void SpawnMap(string message) + { + try + { + int iD = int.Parse(message); + MapManager.instance.LoadLevelFromID(iD, onlyMaster: false, callInImidetly: true); + } + catch + { + } + } + + [PunRPC] + private void RPCA_SendChat(string message, int playerViewID) + { + PhotonNetwork.GetPhotonView(playerViewID).GetComponentInChildren<PlayerChat>().Send(message); + } + + private void SpawnCard(string message) + { + CardInfo[] cards = CardChoice.instance.cards; + int num = -1; + float num2 = 0f; + for (int i = 0; i < cards.Length; i++) + { + string text = cards[i].GetComponent<CardInfo>().cardName.ToUpper(); + text = text.Replace(" ", ""); + string text2 = message.ToUpper(); + text2 = text2.Replace(" ", ""); + float num3 = 0f; + for (int j = 0; j < text2.Length; j++) + { + if (text.Length > j && text2[j] == text[j]) + { + num3 += 1f / (float)text2.Length; + } + } + num3 -= (float)Mathf.Abs(text2.Length - text.Length) * 0.001f; + if (num3 > 0.1f && num3 > num2) + { + num2 = num3; + num = i; + } + } + if (num != -1) + { + GameObject obj = CardChoice.instance.AddCard(cards[num]); + obj.GetComponentInChildren<CardVisuals>().firstValueToSet = true; + obj.transform.root.GetComponentInChildren<ApplyCardStats>().shootToPick = true; + } + } + + public static int GetClosestString(string inputText, string[] compareTo) + { + CardInfo[] cards = CardChoice.instance.cards; + int result = -1; + float num = 0f; + for (int i = 0; i < cards.Length; i++) + { + string text = compareTo[i]; + text = text.Replace(" ", ""); + string text2 = inputText.ToUpper(); + text2 = text2.Replace(" ", ""); + float num2 = 0f; + for (int j = 0; j < text2.Length; j++) + { + if (text.Length > j && text2[j] == text[j]) + { + num2 += 1f / (float)text2.Length; + } + } + num2 -= (float)Mathf.Abs(text2.Length - text.Length) * 0.001f; + if (num2 > 0.1f && num2 > num) + { + num = num2; + result = i; + } + } + return result; + } +} diff --git a/GameCode/DisableChildren.cs b/GameCode/DisableChildren.cs new file mode 100644 index 0000000..e51223c --- /dev/null +++ b/GameCode/DisableChildren.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class DisableChildren : MonoBehaviour +{ + private void Start() + { + ParticleSystem[] componentsInChildren = GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].gameObject.SetActive(value: false); + } + } +} diff --git a/GameCode/DisableEvent.cs b/GameCode/DisableEvent.cs new file mode 100644 index 0000000..698d2e2 --- /dev/null +++ b/GameCode/DisableEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class DisableEvent : MonoBehaviour +{ + public UnityEvent disableEvent; + + public void OnDisable() + { + disableEvent.Invoke(); + } +} diff --git a/GameCode/DisableIfSimple.cs b/GameCode/DisableIfSimple.cs new file mode 100644 index 0000000..514da3d --- /dev/null +++ b/GameCode/DisableIfSimple.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +public class DisableIfSimple : MonoBehaviour +{ + private void Start() + { + Unparent componentInParent = GetComponentInParent<Unparent>(); + if ((bool)componentInParent && (bool)componentInParent.parent) + { + base.gameObject.SetActive(!componentInParent.parent.root.GetComponentInChildren<PlayerSkinHandler>().simpleSkin); + } + else + { + base.gameObject.SetActive(!base.transform.root.GetComponentInChildren<PlayerSkinHandler>().simpleSkin); + } + } +} diff --git a/GameCode/DisableObjects.cs b/GameCode/DisableObjects.cs new file mode 100644 index 0000000..e6c7516 --- /dev/null +++ b/GameCode/DisableObjects.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class DisableObjects : MonoBehaviour +{ + public bool playOnAwake = true; + + public GameObject[] objects; + + private void Start() + { + if (playOnAwake) + { + DoIt(); + } + } + + private void DoIt() + { + for (int i = 0; i < objects.Length; i++) + { + objects[i].SetActive(value: false); + } + } +} diff --git a/GameCode/DisplayMatchPlayerNames.cs b/GameCode/DisplayMatchPlayerNames.cs new file mode 100644 index 0000000..10e3cf5 --- /dev/null +++ b/GameCode/DisplayMatchPlayerNames.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using Photon.Pun; +using Photon.Realtime; +using TMPro; +using UnityEngine; + +public class DisplayMatchPlayerNames : MonoBehaviour +{ + public TextMeshProUGUI local; + + public TextMeshProUGUI other; + + public void ShowNames() + { + List<Photon.Realtime.Player> list = PhotonNetwork.CurrentRoom.Players.Select((KeyValuePair<int, Photon.Realtime.Player> p) => p.Value).ToList(); + bool flag = false; + flag = PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey(NetworkConnectionHandler.TWITCH_ROOM_AUDIENCE_RATING_KEY); + for (int i = 0; i < list.Count; i++) + { + string text = (flag ? (" (" + list[i].CustomProperties[NetworkConnectionHandler.TWITCH_PLAYER_SCORE_KEY].ToString() + ")") : string.Empty); + if (i == 0) + { + local.text = list[i].NickName + text; + } + else + { + other.text = list[i].NickName + text; + } + } + } +} diff --git a/GameCode/DmgEvent.cs b/GameCode/DmgEvent.cs new file mode 100644 index 0000000..16d50b1 --- /dev/null +++ b/GameCode/DmgEvent.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine.Events; + +[Serializable] +public class DmgEvent +{ + public UnityEvent eventToCall; + + public float dmg; +} diff --git a/GameCode/DoPlayerReload.cs b/GameCode/DoPlayerReload.cs new file mode 100644 index 0000000..8faa4e6 --- /dev/null +++ b/GameCode/DoPlayerReload.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class DoPlayerReload : MonoBehaviour +{ + private WeaponHandler wh; + + private void Start() + { + wh = GetComponentInParent<WeaponHandler>(); + } + + public void DoReload() + { + wh.DoReload(); + } +} diff --git a/GameCode/DodgeGround.cs b/GameCode/DodgeGround.cs new file mode 100644 index 0000000..a7d3815 --- /dev/null +++ b/GameCode/DodgeGround.cs @@ -0,0 +1,141 @@ +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class DodgeGround : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundSneakyDodgeGroundLoop; + + private bool soundIsPlaying; + + private float soundTimeToStopPlaying = 0.5f; + + private float soundTimeCurrent; + + private Transform spawnedSpawnerTransform; + + [Header("Settings")] + public float rayLength = 3f; + + public float rayUp = 0.3f; + + public float force; + + public LayerMask mask; + + private MoveTransform move; + + private SpawnedAttack spawned; + + public ParticleSystem p1; + + public ParticleSystem p2; + + public ParticleSystem p3; + + public LineRenderer l1; + + public LineRenderer l2; + + private float c3; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + move = GetComponentInParent<MoveTransform>(); + GetComponentInParent<SyncProjectile>().active = true; + if (spawned != null && spawned.spawner != null) + { + spawnedSpawnerTransform = spawned.spawner.transform; + } + } + + private void SoundStart() + { + if (!soundIsPlaying && spawnedSpawnerTransform != null) + { + soundIsPlaying = true; + SoundManager.Instance.PlayAtPosition(soundSneakyDodgeGroundLoop, spawnedSpawnerTransform, base.transform); + } + } + + private void SoundStop() + { + if (soundIsPlaying && spawnedSpawnerTransform != null) + { + soundIsPlaying = false; + SoundManager.Instance.StopAtPosition(soundSneakyDodgeGroundLoop, base.transform); + } + } + + private void OnDestroy() + { + SoundStop(); + } + + private void Update() + { + float magnitude = move.velocity.magnitude; + c3 += TimeHandler.deltaTime; + l1.enabled = false; + l2.enabled = false; + bool flag = false; + float num = 1f; + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position, base.transform.forward + base.transform.right * rayUp, rayLength, mask); + if ((bool)raycastHit2D && (bool)raycastHit2D.transform && !raycastHit2D.collider.GetComponent<Damagable>() && raycastHit2D.transform.gameObject.layer != 10) + { + flag = true; + } + bool flag2 = false; + RaycastHit2D raycastHit2D2 = Physics2D.Raycast(base.transform.position, base.transform.forward + base.transform.right * (0f - rayUp), rayLength, mask); + if ((bool)raycastHit2D2 && (bool)raycastHit2D2.transform && !raycastHit2D2.collider.GetComponent<Damagable>() && raycastHit2D2.transform.gameObject.layer != 10) + { + flag2 = true; + } + if (flag && flag2 && raycastHit2D.transform == raycastHit2D2.transform) + { + if (raycastHit2D.distance < raycastHit2D2.distance) + { + flag2 = false; + } + else + { + flag = false; + } + } + if (flag) + { + move.velocity += (Vector3)raycastHit2D.normal * force * move.velocity.magnitude * num * TimeHandler.deltaTime; + l1.enabled = true; + l1.SetPosition(0, base.transform.position); + l1.SetPosition(1, raycastHit2D.point); + } + if (flag2) + { + move.velocity += (Vector3)raycastHit2D2.normal * force * move.velocity.magnitude * num * TimeHandler.deltaTime; + l2.enabled = true; + l2.SetPosition(0, base.transform.position); + l2.SetPosition(1, raycastHit2D2.point); + } + if (flag || flag2) + { + soundTimeCurrent = soundTimeToStopPlaying; + SoundStart(); + } + else if (soundIsPlaying) + { + soundTimeCurrent -= TimeHandler.deltaTime; + if (soundTimeCurrent < 0f) + { + SoundStop(); + } + } + move.velocity = move.velocity.normalized * magnitude; + if (flag && c3 > 0.05f) + { + c3 = 0f; + p3.Emit(1); + } + } +} diff --git a/GameCode/DontChangeMe.cs b/GameCode/DontChangeMe.cs new file mode 100644 index 0000000..cbef7b6 --- /dev/null +++ b/GameCode/DontChangeMe.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class DontChangeMe : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/DuringReloadTrigger.cs b/GameCode/DuringReloadTrigger.cs new file mode 100644 index 0000000..6f3609f --- /dev/null +++ b/GameCode/DuringReloadTrigger.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using UnityEngine.Events; + +public class DuringReloadTrigger : MonoBehaviour +{ + public UnityEvent triggerEvent; + + public UnityEvent triggerStartEvent; + + public UnityEvent triggerEndEvent; + + private Gun gunAmmo; + + private bool triggering; + + private void Start() + { + gunAmmo = GetComponentInParent<WeaponHandler>().gun; + } + + private void Update() + { + if (gunAmmo.isReloading) + { + if (!triggering) + { + triggerStartEvent.Invoke(); + triggering = true; + } + triggerEvent.Invoke(); + } + else if (triggering) + { + triggerEndEvent.Invoke(); + triggering = false; + } + } +} diff --git a/GameCode/DynamicParticleSet.cs b/GameCode/DynamicParticleSet.cs new file mode 100644 index 0000000..44931b9 --- /dev/null +++ b/GameCode/DynamicParticleSet.cs @@ -0,0 +1,9 @@ +using System; + +[Serializable] +public class DynamicParticleSet +{ + public ObjectsToSpawn objectsToSpawn; + + public float dmg; +} diff --git a/GameCode/DynamicParticles.cs b/GameCode/DynamicParticles.cs new file mode 100644 index 0000000..26a0cad --- /dev/null +++ b/GameCode/DynamicParticles.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +public class DynamicParticles : MonoBehaviour +{ + public static DynamicParticles instance; + + public DynamicParticleSet[] bulletHit; + + private int spawnsThisFrame; + + private void Start() + { + instance = this; + } + + private void Update() + { + spawnsThisFrame = 0; + } + + public void PlayBulletHit(float damage, Transform spawnerTransform, HitInfo hit, Color projectielColor) + { + if ((float)spawnsThisFrame > 5f) + { + return; + } + spawnsThisFrame++; + int num = 0; + for (int i = 1; i < bulletHit.Length && !(bulletHit[i].dmg > damage); i++) + { + num = i; + } + GameObject[] array = ObjectsToSpawn.SpawnObject(base.transform, hit, bulletHit[num].objectsToSpawn, null, null); + if (!(projectielColor != Color.black)) + { + return; + } + for (int j = 0; j < array.Length; j++) + { + for (int k = 0; k < array[j].transform.childCount; k++) + { + ChangeColor componentInChildren = array[j].transform.GetChild(k).GetComponentInChildren<ChangeColor>(); + if ((bool)componentInChildren) + { + componentInChildren.GetComponent<ParticleSystemRenderer>().material.color = projectielColor; + } + } + } + } +} diff --git a/GameCode/Emoji.cs b/GameCode/Emoji.cs new file mode 100644 index 0000000..14f1e06 --- /dev/null +++ b/GameCode/Emoji.cs @@ -0,0 +1,7 @@ +using System; + +[Serializable] +public class Emoji +{ + public CharacterItem[] emojiPieces; +} diff --git a/GameCode/EmojiButton.cs b/GameCode/EmojiButton.cs new file mode 100644 index 0000000..08e434a --- /dev/null +++ b/GameCode/EmojiButton.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class EmojiButton : MonoBehaviour +{ + private void Update() + { + } +} diff --git a/GameCode/EmojiCombiner.cs b/GameCode/EmojiCombiner.cs new file mode 100644 index 0000000..08039c4 --- /dev/null +++ b/GameCode/EmojiCombiner.cs @@ -0,0 +1,49 @@ +using UnityEngine; + +public class EmojiCombiner : MonoBehaviour +{ + public GameObject currentEmoji; + + public void AddEmoji(GameObject newEmoji) + { + CharacterItem characterItem = FindEmojiPiece(currentEmoji, "M"); + CharacterItem characterItem2 = FindEmojiPiece(newEmoji, "M"); + float delta = GetDelta(characterItem, characterItem2); + CharacterItem characterItem3 = FindEmojiPiece(currentEmoji, "E"); + CharacterItem characterItem4 = FindEmojiPiece(newEmoji, "E"); + float delta2 = GetDelta(characterItem3, characterItem4); + if (delta > delta2) + { + Object.Destroy(characterItem.gameObject); + GameObject obj = Object.Instantiate(characterItem2.gameObject); + obj.transform.SetParent(currentEmoji.transform); + obj.transform.localPosition = characterItem2.transform.localPosition; + } + else + { + Object.Destroy(characterItem3.gameObject); + GameObject obj2 = Object.Instantiate(characterItem4.gameObject); + obj2.transform.SetParent(currentEmoji.transform); + obj2.transform.localPosition = characterItem4.transform.localPosition; + } + } + + private float GetDelta(CharacterItem from, CharacterItem to) + { + return 1f; + } + + private CharacterItem FindEmojiPiece(GameObject emoji, string target) + { + target = target.ToUpper(); + CharacterItem[] componentsInChildren = emoji.GetComponentsInChildren<CharacterItem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].name.ToUpper()[0] == target.ToCharArray()[0]) + { + return componentsInChildren[i]; + } + } + return null; + } +} diff --git a/GameCode/Empower.cs b/GameCode/Empower.cs new file mode 100644 index 0000000..742e29a --- /dev/null +++ b/GameCode/Empower.cs @@ -0,0 +1,110 @@ +using System; +using Sonigon; +using UnityEngine; + +public class Empower : MonoBehaviour +{ + public SoundEvent soundEmpowerSpawn; + + public GameObject addObjectToBullet; + + public float dmgMultiplier = 2f; + + public float speedMultiplier = 2f; + + public Color empowerColor; + + private CharacterData data; + + private ParticleSystem[] parts; + + private Transform particleTransform; + + private bool empowered; + + private bool isOn; + + private void Start() + { + particleTransform = base.transform.GetChild(0); + data = GetComponentInParent<CharacterData>(); + parts = GetComponentsInChildren<ParticleSystem>(); + HealthHandler healthHandler = GetComponentInParent<Player>().data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(ResetEmpower)); + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(gun.ShootPojectileAction, new Action<GameObject>(Attack)); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void OnDestroy() + { + HealthHandler healthHandler = GetComponentInParent<Player>().data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Remove(healthHandler.reviveAction, new Action(ResetEmpower)); + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Remove(gun.ShootPojectileAction, new Action<GameObject>(Attack)); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void ResetEmpower() + { + empowered = false; + } + + public void Block(BlockTrigger.BlockTriggerType trigger) + { + if (trigger != BlockTrigger.BlockTriggerType.Echo && trigger != BlockTrigger.BlockTriggerType.Empower && trigger != BlockTrigger.BlockTriggerType.ShieldCharge) + { + empowered = true; + } + } + + public void Attack(GameObject projectile) + { + SpawnedAttack component = projectile.GetComponent<SpawnedAttack>(); + if (!component) + { + return; + } + if (empowered) + { + ProjectileHit component2 = projectile.GetComponent<ProjectileHit>(); + MoveTransform component3 = projectile.GetComponent<MoveTransform>(); + component.SetColor(empowerColor); + component2.damage *= dmgMultiplier; + component3.localForce *= speedMultiplier; + if ((bool)addObjectToBullet) + { + UnityEngine.Object.Instantiate(addObjectToBullet, projectile.transform.position, projectile.transform.rotation, projectile.transform); + } + } + empowered = false; + } + + private void Update() + { + if (empowered) + { + particleTransform.transform.position = data.weaponHandler.gun.transform.position; + particleTransform.transform.rotation = data.weaponHandler.gun.transform.rotation; + if (!isOn) + { + SoundManager.Instance.PlayAtPosition(soundEmpowerSpawn, SoundManager.Instance.GetTransform(), base.transform); + for (int i = 0; i < parts.Length; i++) + { + parts[i].Play(); + } + isOn = true; + } + } + else if (isOn) + { + for (int j = 0; j < parts.Length; j++) + { + parts[j].Stop(); + } + isOn = false; + } + } +} diff --git a/GameCode/EmpowerStopBlockObjectFollow.cs b/GameCode/EmpowerStopBlockObjectFollow.cs new file mode 100644 index 0000000..dd64869 --- /dev/null +++ b/GameCode/EmpowerStopBlockObjectFollow.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; + +public class EmpowerStopBlockObjectFollow : MonoBehaviour +{ + private void Start() + { + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void OnDestroy() + { + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void Block(BlockTrigger.BlockTriggerType triggerTyp) + { + if (triggerTyp == BlockTrigger.BlockTriggerType.Empower && (bool)GetComponent<SpawnObjects>()) + { + GetComponent<SpawnObjects>().mostRecentlySpawnedObject.GetComponent<FollowPlayer>().enabled = false; + } + } +} diff --git a/GameCode/EmptySprite.cs b/GameCode/EmptySprite.cs new file mode 100644 index 0000000..4442b89 --- /dev/null +++ b/GameCode/EmptySprite.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public static class EmptySprite +{ + private static Sprite instance; + + public static Sprite Get() + { + if (instance == null) + { + instance = Resources.Load<Sprite>("procedural_ui_image_default_sprite"); + } + return instance; + } + + public static bool IsEmptySprite(Sprite s) + { + if (Get() == s) + { + return true; + } + return false; + } +} diff --git a/GameCode/EnableEvent.cs b/GameCode/EnableEvent.cs new file mode 100644 index 0000000..2a2cfa0 --- /dev/null +++ b/GameCode/EnableEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class EnableEvent : MonoBehaviour +{ + public UnityEvent enableEvent; + + public void OnEnable() + { + enableEvent.Invoke(); + } +} diff --git a/GameCode/EnableObjectPerLevel.cs b/GameCode/EnableObjectPerLevel.cs new file mode 100644 index 0000000..ce1606c --- /dev/null +++ b/GameCode/EnableObjectPerLevel.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class EnableObjectPerLevel : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/EnsnareEffect.cs b/GameCode/EnsnareEffect.cs new file mode 100644 index 0000000..834d154 --- /dev/null +++ b/GameCode/EnsnareEffect.cs @@ -0,0 +1,98 @@ +using Sirenix.OdinInspector; +using Sonigon; +using UnityEngine; + +public class EnsnareEffect : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundEnsnare; + + public SoundEvent soundEnsnareBreak; + + public bool soundEnsnareJumpChange; + + public float range = 1f; + + private float seconds = 1f; + + public float force = 2000f; + + public float breakDistance = 2f; + + public float drag = 0.98f; + + private CharacterData target; + + private Vector2 startPos; + + public bool startPosIsMyPos; + + private float scale = 1f; + + private LineEffect line; + + [FoldoutGroup("SNAP", 0)] + public float snapCapLineTime = 0.5f; + + [FoldoutGroup("SNAP", 0)] + public float snapCapTimeTime = 0.5f; + + private bool done; + + private bool doneDone; + + private void Start() + { + scale *= base.transform.localScale.x; + range *= (1f + base.transform.localScale.x) * 0.5f; + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true); + if ((bool)closestPlayer && Vector3.Distance(base.transform.position, closestPlayer.transform.position) < range) + { + target = closestPlayer.data; + startPos = target.transform.position; + if (startPosIsMyPos) + { + startPos = base.transform.position; + } + float bezierOffset = 1f; + if (startPosIsMyPos) + { + bezierOffset = 0f; + } + line = GetComponentInChildren<LineEffect>(includeInactive: true); + line.Play(base.transform, closestPlayer.transform, bezierOffset); + if (soundEnsnare != null) + { + SoundManager.Instance.Play(soundEnsnare, target.transform); + } + if (soundEnsnareJumpChange) + { + target.playerSounds.AddEnsnareEffect(this); + } + } + } + + private void FixedUpdate() + { + if (!target || !(line.currentWidth > 0f)) + { + return; + } + target.sinceGrounded = 0f; + target.playerVel.velocity *= Mathf.Pow(drag, scale); + target.playerVel.AddForce(Vector2.ClampMagnitude(startPos - (Vector2)target.transform.position, 60f) * scale * force, ForceMode2D.Force); + if (!done && Vector2.Distance(startPos, target.transform.position) > breakDistance) + { + done = true; + line.counter = Mathf.Clamp(line.counter, snapCapLineTime, float.PositiveInfinity); + if (soundEnsnareJumpChange) + { + target.playerSounds.RemoveEnsnareEffect(this); + } + if (soundEnsnareBreak != null) + { + SoundManager.Instance.Play(soundEnsnareBreak, target.transform); + } + } + } +} diff --git a/GameCode/ErrorHandler.cs b/GameCode/ErrorHandler.cs new file mode 100644 index 0000000..e9ffc17 --- /dev/null +++ b/GameCode/ErrorHandler.cs @@ -0,0 +1,30 @@ +using TMPro; +using UnityEngine; + +public class ErrorHandler : MonoBehaviour +{ + public static ErrorHandler instance; + + public TextMeshProUGUI contextText; + + public TextMeshProUGUI reasonText; + + public GameObject UI; + + private void Awake() + { + instance = this; + } + + public void ShowError(string context, string reason) + { + contextText.text = context; + reasonText.text = reason; + UI.SetActive(value: true); + } + + public void HideError() + { + UI.SetActive(value: false); + } +} diff --git a/GameCode/EscapeMenuHandler.cs b/GameCode/EscapeMenuHandler.cs new file mode 100644 index 0000000..0204501 --- /dev/null +++ b/GameCode/EscapeMenuHandler.cs @@ -0,0 +1,62 @@ +using InControl; +using UnityEngine; + +public class EscapeMenuHandler : MonoBehaviour +{ + public static bool isEscMenu; + + public GameObject[] togglers; + + public GameObject canvs; + + private void Start() + { + isEscMenu = false; + } + + private void Update() + { + if (CharacterCreatorHandler.instance.SomeoneIsEditing() || canvs.activeInHierarchy) + { + return; + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + ToggleEsc(); + } + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].CommandWasPressed) + { + ToggleEsc(); + } + } + } + + public void ToggleEsc() + { + isEscMenu = !isEscMenu; + if (isEscMenu) + { + ListMenu.instance.SelectButton(GetComponentInChildren<ListMenuPage>().firstSelected); + } + else + { + ListMenu.instance.SelectButton(GetComponentsInChildren<ListMenuButton>()[1]); + } + for (int i = 0; i < togglers.Length; i++) + { + togglers[i].SetActive(isEscMenu); + } + if (isEscMenu) + { + ListMenu.instance.SelectButton(GetComponentInChildren<ListMenuPage>().firstSelected); + return; + } + ListMenuButton[] componentsInChildren = GetComponentsInChildren<ListMenuButton>(includeInactive: true); + if (componentsInChildren.Length > 2) + { + ListMenu.instance.SelectButton(componentsInChildren[1]); + } + } +} diff --git a/GameCode/EventSequence.cs b/GameCode/EventSequence.cs new file mode 100644 index 0000000..f875669 --- /dev/null +++ b/GameCode/EventSequence.cs @@ -0,0 +1,52 @@ +using System.Collections; +using UnityEngine; + +public class EventSequence : MonoBehaviour +{ + public bool playOnAwake = true; + + public bool useTimeScale = true; + + public DelayedEvent[] events; + + private int level; + + private void Start() + { + level = GetComponentInParent<AttackLevel>().attackLevel; + if (playOnAwake) + { + Go(); + } + } + + public void Go() + { + StartCoroutine(DoSequence()); + } + + private IEnumerator DoSequence() + { + for (int i = 0; i < events.Length; i++) + { + float num = 0f; + for (int i2 = 0; i2 < events[i].cycles + events[i].cyclesPerLvl * level; i2++) + { + num += events[i].delay; + if (num > TimeHandler.deltaTime) + { + if (useTimeScale) + { + yield return new WaitForSeconds(num); + } + else + { + yield return new WaitForSecondsRealtime(num); + } + num = 0f; + } + events[i].eventTrigger.Invoke(); + } + } + } +} diff --git a/GameCode/ExceptionThrown.cs b/GameCode/ExceptionThrown.cs new file mode 100644 index 0000000..1ba81e0 --- /dev/null +++ b/GameCode/ExceptionThrown.cs @@ -0,0 +1,3 @@ +using System; + +public delegate void ExceptionThrown(Exception exeption); diff --git a/GameCode/Explosion.cs b/GameCode/Explosion.cs new file mode 100644 index 0000000..02af031 --- /dev/null +++ b/GameCode/Explosion.cs @@ -0,0 +1,216 @@ +using System; +using Photon.Pun; +using Sirenix.OdinInspector; +using Sonigon; +using UnityEngine; + +public class Explosion : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundDamage; + + [Header("Settings")] + public float slow; + + public float silence; + + public bool fastSlow; + + public float stun; + + public float force = 2000f; + + public float objectForceMultiplier = 1f; + + public bool forceIgnoreMass; + + public float damage = 25f; + + public Color dmgColor = Color.black; + + public float range = 2f; + + public float flyingFor; + + public bool auto = true; + + public bool ignoreTeam; + + public bool ignoreWalls; + + public bool staticRangeMultiplier; + + [FoldoutGroup("Scaling", 0)] + public bool scaleSlow = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleSilence = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleDmg = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleRadius = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleStun = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleForce = true; + + [FoldoutGroup("Immunity", 0)] + public float immunity; + + private SpawnedAttack spawned; + + public bool locallySimulated; + + public Action<Damagable> DealDamageAction; + + public Action<Damagable> DealHealAction; + + public Action<Damagable, float> HitTargetAction; + + private PhotonView view; + + public Action<CharacterData, float> hitPlayerAction; + + private void Start() + { + spawned = GetComponent<SpawnedAttack>(); + view = GetComponent<PhotonView>(); + if (auto) + { + Explode(); + } + } + + private void DoExplosionEffects(Collider2D hitCol, float rangeMultiplier, float distance) + { + float num = (scaleDmg ? base.transform.localScale.x : 1f); + float num2 = (scaleForce ? base.transform.localScale.x : 1f); + float num3 = (scaleSlow ? base.transform.localScale.x : 1f); + float num4 = (scaleSilence ? base.transform.localScale.x : 1f); + float num5 = (scaleStun ? ((1f + base.transform.localScale.x) * 0.5f) : 1f); + Damagable componentInParent = hitCol.gameObject.GetComponentInParent<Damagable>(); + CharacterData characterData = null; + if ((bool)componentInParent) + { + characterData = hitCol.gameObject.GetComponentInParent<CharacterData>(); + if ((immunity > 0f && (bool)characterData && characterData.GetComponent<PlayerImmunity>().IsImune(immunity, num * damage * rangeMultiplier, base.gameObject.name)) || (!ignoreWalls && (bool)characterData && !PlayerManager.instance.CanSeePlayer(base.transform.position, characterData.player).canSee)) + { + return; + } + if (slow != 0f && (bool)componentInParent.GetComponent<CharacterStatModifiers>()) + { + if (locallySimulated) + { + if (spawned.IsMine() && !characterData.block.IsBlocking()) + { + characterData.stats.RPCA_AddSlow(slow * rangeMultiplier * num3, fastSlow); + } + } + else if (spawned.IsMine() && !characterData.block.IsBlocking()) + { + characterData.view.RPC("RPCA_AddSlow", RpcTarget.All, slow * rangeMultiplier * num3, fastSlow); + } + } + if (silence != 0f && (bool)componentInParent.GetComponent<SilenceHandler>() && spawned.IsMine() && !characterData.block.IsBlocking()) + { + characterData.view.RPC("RPCA_AddSilence", RpcTarget.All, silence * rangeMultiplier * num4); + } + if ((bool)spawned) + { + _ = spawned.spawner; + } + hitPlayerAction?.Invoke(characterData, rangeMultiplier); + if (damage < 0f) + { + if ((bool)characterData) + { + characterData.healthHandler.Heal(0f - damage); + } + if (DealHealAction != null) + { + DealHealAction(componentInParent); + } + } + else if (damage > 0f) + { + if (soundDamage != null && characterData != null) + { + SoundManager.Instance.Play(soundDamage, characterData.transform); + } + Vector2 vector = ((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized; + if (vector == Vector2.zero) + { + vector = Vector2.up; + } + if (spawned.IsMine()) + { + componentInParent.CallTakeDamage(num * damage * rangeMultiplier * vector, base.transform.position, null, spawned.spawner); + } + if (DealDamageAction != null) + { + DealDamageAction(componentInParent); + } + } + } + if ((bool)characterData) + { + if (HitTargetAction != null) + { + HitTargetAction(componentInParent, distance); + } + if (force != 0f) + { + if (locallySimulated) + { + characterData.healthHandler.TakeForce(((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized * rangeMultiplier * force * num2, ForceMode2D.Impulse, forceIgnoreMass); + } + else if (spawned.IsMine()) + { + characterData.healthHandler.CallTakeForce(((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized * rangeMultiplier * force * num2, ForceMode2D.Impulse, forceIgnoreMass, ignoreBlock: false, flyingFor * rangeMultiplier); + } + } + if (stun > 0f) + { + characterData.stunHandler.AddStun(stun * num5); + } + } + else if ((bool)hitCol.attachedRigidbody) + { + hitCol.attachedRigidbody.AddForce(((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized * rangeMultiplier * force * num2, ForceMode2D.Impulse); + } + } + + public void Explode() + { + float num = (scaleRadius ? base.transform.localScale.x : 1f); + Collider2D[] array = Physics2D.OverlapCircleAll(base.transform.position, range * num); + for (int i = 0; i < array.Length; i++) + { + if (array[i].gameObject.layer != 19) + { + Damagable componentInParent = array[i].gameObject.GetComponentInParent<Damagable>(); + float num2 = Vector2.Distance(base.transform.position, array[i].bounds.ClosestPoint(base.transform.position)); + float value = 1f - num2 / (range * num); + if (staticRangeMultiplier) + { + value = 1f; + } + value = Mathf.Clamp(value, 0f, 1f); + NetworkPhysicsObject component = array[i].GetComponent<NetworkPhysicsObject>(); + if ((bool)component && component.photonView.IsMine) + { + float num3 = (scaleForce ? base.transform.localScale.x : 1f); + component.BulletPush((Vector2)(component.transform.position - base.transform.position).normalized * objectForceMultiplier * 1f * value * force * num3, Vector2.zero, null); + } + if (((bool)componentInParent || (bool)array[i].attachedRigidbody) && (!ignoreTeam || !spawned || !(spawned.spawner.gameObject == array[i].transform.gameObject))) + { + DoExplosionEffects(array[i], value, num2); + } + } + } + } +} diff --git a/GameCode/Explosion_Overpower.cs b/GameCode/Explosion_Overpower.cs new file mode 100644 index 0000000..13a98ac --- /dev/null +++ b/GameCode/Explosion_Overpower.cs @@ -0,0 +1,23 @@ +using System; +using UnityEngine; + +public class Explosion_Overpower : MonoBehaviour +{ + public float dmgPer100Hp; + + private void Awake() + { + Explosion component = GetComponent<Explosion>(); + component.hitPlayerAction = (Action<CharacterData, float>)Delegate.Combine(component.hitPlayerAction, new Action<CharacterData, float>(HitPlayer)); + } + + private void HitPlayer(CharacterData data, float rangeMultiplier) + { + SpawnedAttack component = GetComponent<SpawnedAttack>(); + if (component.IsMine()) + { + float num = component.spawner.data.maxHealth * dmgPer100Hp * 0.01f * base.transform.localScale.x; + data.healthHandler.CallTakeDamage(num * (data.transform.position - component.spawner.transform.position).normalized, base.transform.position, null, GetComponent<SpawnedAttack>().spawner); + } + } +} diff --git a/GameCode/Extensions.cs b/GameCode/Extensions.cs new file mode 100644 index 0000000..41040bc --- /dev/null +++ b/GameCode/Extensions.cs @@ -0,0 +1,19 @@ +using System; + +public static class Extensions +{ + public static double NextGaussianDouble(this Random r) + { + double num; + double num3; + do + { + num = 2.0 * r.NextDouble() - 1.0; + double num2 = 2.0 * r.NextDouble() - 1.0; + num3 = num * num + num2 * num2; + } + while (num3 >= 1.0); + double num4 = Math.Sqrt(-2.0 * Math.Log(num3) / num3); + return num * num4; + } +} diff --git a/GameCode/ExtraBlock.cs b/GameCode/ExtraBlock.cs new file mode 100644 index 0000000..a14cdab --- /dev/null +++ b/GameCode/ExtraBlock.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class ExtraBlock : MonoBehaviour +{ + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + public void Go() + { + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true); + } +} diff --git a/GameCode/FRILerp.cs b/GameCode/FRILerp.cs new file mode 100644 index 0000000..f27815b --- /dev/null +++ b/GameCode/FRILerp.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +public class FRILerp : MonoBehaviour +{ + private void Start() + { + } + + public static Vector3 Lerp(Vector3 from, Vector3 target, float speed) + { + return Vector3.Lerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Vector3 LerpUnclamped(Vector3 from, Vector3 target, float speed) + { + return Vector3.LerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static float Lerp(float from, float target, float speed) + { + return Mathf.Lerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static float LerpUnclamped(float from, float target, float speed) + { + return Mathf.LerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Vector3 Slerp(Vector3 from, Vector3 target, float speed) + { + return Vector3.Slerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Vector3 SlerpUnclamped(Vector3 from, Vector3 target, float speed) + { + return Vector3.SlerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Quaternion Lerp(Quaternion from, Quaternion target, float speed) + { + return Quaternion.Lerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Quaternion LerpUnclamped(Quaternion from, Quaternion target, float speed) + { + return Quaternion.LerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } +} diff --git a/GameCode/FakeParticleDB.cs b/GameCode/FakeParticleDB.cs new file mode 100644 index 0000000..0e82935 --- /dev/null +++ b/GameCode/FakeParticleDB.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "FakeParticleDB", menuName = "FakeParticleDB", order = 999999999)] +public class FakeParticleDB : ScriptableObject +{ + public Material m_DefaultMaterial; + + public Material m_ParticleMaterial; + + private static FakeParticleDB _inst; + + private static FakeParticleDB instance + { + get + { + if (_inst == null) + { + _inst = Resources.Load("FakeParticleDB") as FakeParticleDB; + } + return _inst; + } + } + + public static Material GetParticleMaterial() + { + return instance.m_ParticleMaterial; + } + + public static Material GetDefaultMaterial() + { + return instance.m_DefaultMaterial; + } +} diff --git a/GameCode/FlickerEvent.cs b/GameCode/FlickerEvent.cs new file mode 100644 index 0000000..dd4096e --- /dev/null +++ b/GameCode/FlickerEvent.cs @@ -0,0 +1,48 @@ +using UnityEngine; +using UnityEngine.Events; + +public class FlickerEvent : MonoBehaviour +{ + public UnityEvent onEvent; + + public UnityEvent offEvent; + + public float interval; + + private float c; + + public bool isOn; + + private bool flickedOn; + + private void Start() + { + } + + private void Update() + { + c += TimeHandler.deltaTime; + if (isOn) + { + if (c > interval) + { + flickedOn = !flickedOn; + if (flickedOn) + { + onEvent.Invoke(); + } + else + { + offEvent.Invoke(); + } + c = 0f; + } + } + else if (flickedOn && c > interval) + { + c = 0f; + offEvent.Invoke(); + flickedOn = false; + } + } +} diff --git a/GameCode/FollowInactiveHand.cs b/GameCode/FollowInactiveHand.cs new file mode 100644 index 0000000..a52b5e7 --- /dev/null +++ b/GameCode/FollowInactiveHand.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class FollowInactiveHand : MonoBehaviour +{ + private CharacterData data; + + public Vector3 offSet; + + public GameObject leftHand; + + public GameObject rightHand; + + private void Start() + { + data = base.transform.root.GetComponent<CharacterData>(); + } + + private void Update() + { + if (data.aimDirection.x < 0f) + { + base.transform.position = rightHand.transform.TransformPoint(offSet); + } + else + { + base.transform.position = leftHand.transform.TransformPoint(offSet); + } + } +} diff --git a/GameCode/FollowLocalPos.cs b/GameCode/FollowLocalPos.cs new file mode 100644 index 0000000..194f947 --- /dev/null +++ b/GameCode/FollowLocalPos.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +public class FollowLocalPos : MonoBehaviour +{ + private Vector3 relative; + + private Vector3 relativeForward; + + private Vector3 relativeUp; + + public Transform target; + + public Player targetPlayer; + + private void Start() + { + if ((bool)target && relative == Vector3.zero) + { + Follow(target); + } + } + + private void LateUpdate() + { + if ((bool)target && target.gameObject.activeInHierarchy) + { + base.transform.position = target.TransformPoint(relative); + base.transform.rotation = Quaternion.LookRotation(target.TransformDirection(relativeForward), target.TransformDirection(relativeUp)); + } + else + { + Object.Destroy(base.gameObject); + } + } + + public void Follow(Transform targetTransform) + { + if ((bool)targetTransform) + { + target = targetTransform; + Player component = target.transform.root.GetComponent<Player>(); + Vector3 position = base.transform.position; + if ((bool)component) + { + targetPlayer = component; + base.transform.position -= base.transform.forward * 2f; + Vector3 position2 = target.position; + Vector3 vector = (base.transform.position - target.position).normalized * 1.1f; + position = position2 + vector; + base.transform.position = new Vector3(base.transform.position.x, base.transform.position.y, component.transform.position.z); + } + relative = targetTransform.InverseTransformPoint(position); + relativeForward = targetTransform.InverseTransformDirection(base.transform.forward); + relativeUp = targetTransform.InverseTransformDirection(base.transform.up); + } + } +} diff --git a/GameCode/FollowPlayer.cs b/GameCode/FollowPlayer.cs new file mode 100644 index 0000000..cd3c826 --- /dev/null +++ b/GameCode/FollowPlayer.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +public class FollowPlayer : MonoBehaviour +{ + public enum Target + { + Self, + Other + } + + public Target target; + + public bool inheritScale = true; + + private Vector3 startScale; + + private Player ownPlayer; + + private void Start() + { + startScale = base.transform.localScale; + ownPlayer = GetComponentInParent<Player>(); + if (!ownPlayer) + { + ownPlayer = GetComponentInParent<SpawnedAttack>().spawner; + } + } + + private void LateUpdate() + { + Player player = null; + player = ((target != Target.Other) ? ownPlayer : PlayerManager.instance.GetOtherPlayer(ownPlayer)); + if (inheritScale) + { + base.transform.localScale = new Vector3(player.transform.localScale.x * startScale.x, player.transform.localScale.y * startScale.y, player.transform.localScale.z * startScale.z); + } + base.transform.position = player.transform.position; + base.transform.rotation = player.transform.rotation; + } +} diff --git a/GameCode/FollowRandomPlayer.cs b/GameCode/FollowRandomPlayer.cs new file mode 100644 index 0000000..c8d8516 --- /dev/null +++ b/GameCode/FollowRandomPlayer.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +public class FollowRandomPlayer : MonoBehaviour +{ + public bool X = true; + + public bool Y = true; + + private Transform targetPlayer; + + public bool snap; + + private void Start() + { + } + + private void Update() + { + if (!targetPlayer) + { + GetNewPlayer(); + } + else if (snap) + { + base.transform.position = new Vector3(X ? targetPlayer.position.x : base.transform.position.x, Y ? targetPlayer.position.y : base.transform.position.y, 0f); + } + else + { + base.transform.position = Vector3.Lerp(base.transform.position, new Vector3(X ? targetPlayer.position.x : base.transform.position.x, Y ? targetPlayer.position.y : base.transform.position.y, 0f), TimeHandler.deltaTime * 5f); + } + } + + private void GetNewPlayer() + { + if (PlayerManager.instance.players.Count > 0) + { + targetPlayer = PlayerManager.instance.players[Random.Range(0, PlayerManager.instance.players.Count)].transform; + } + } +} diff --git a/GameCode/FollowScale.cs b/GameCode/FollowScale.cs new file mode 100644 index 0000000..6666c05 --- /dev/null +++ b/GameCode/FollowScale.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class FollowScale : MonoBehaviour +{ + public Transform target; + + private void Update() + { + if ((bool)target) + { + base.transform.localScale = target.transform.localScale; + } + } +} diff --git a/GameCode/FollowTransform.cs b/GameCode/FollowTransform.cs new file mode 100644 index 0000000..32c0671 --- /dev/null +++ b/GameCode/FollowTransform.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class FollowTransform : MonoBehaviour +{ + public Transform target; + + private Vector3 spawnOffset; + + public Vector3 offset; + + private void Start() + { + spawnOffset = base.transform.position - target.position; + } + + private void LateUpdate() + { + if ((bool)target) + { + base.transform.position = target.position + spawnOffset + offset; + } + } +} diff --git a/GameCode/ForceMultiplier.cs b/GameCode/ForceMultiplier.cs new file mode 100644 index 0000000..064bbfc --- /dev/null +++ b/GameCode/ForceMultiplier.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class ForceMultiplier : MonoBehaviour +{ + public float multiplier = 1f; +} diff --git a/GameCode/FreeModifier.cs b/GameCode/FreeModifier.cs new file mode 100644 index 0000000..4f8badf --- /dev/null +++ b/GameCode/FreeModifier.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Free")] +public class FreeModifier : ProceduralImageModifier +{ + [SerializeField] + private Vector4 radius; + + public Vector4 Radius + { + get + { + return radius; + } + set + { + radius = value; + base._Graphic.SetVerticesDirty(); + } + } + + public override Vector4 CalculateRadius(Rect imageRect) + { + return radius; + } + + protected void OnValidate() + { + radius.x = Mathf.Max(0f, radius.x); + radius.y = Mathf.Max(0f, radius.y); + radius.z = Mathf.Max(0f, radius.z); + radius.w = Mathf.Max(0f, radius.w); + } +} diff --git a/GameCode/GM_ArmsRace.cs b/GameCode/GM_ArmsRace.cs new file mode 100644 index 0000000..3d309ae --- /dev/null +++ b/GameCode/GM_ArmsRace.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class GM_ArmsRace : MonoBehaviour +{ + private int playersNeededToStart = 2; + + private int pointsToWinRound = 2; + + public int roundsToWinGame = 5; + + public int p1Points; + + public int p2Points; + + public int p1Rounds; + + public int p2Rounds; + + private PhotonView view; + + public static GM_ArmsRace instance; + + private bool isWaiting; + + public Action StartGameAction; + + public bool pickPhase = true; + + [HideInInspector] + public bool isPicking; + + private bool waitingForOtherPlayer = true; + + private int currentWinningTeamID = -1; + + public Action pointOverAction; + + private bool isTransitioning; + + private void Awake() + { + instance = this; + } + + private void Start() + { + view = GetComponent<PhotonView>(); + PlayerManager.instance.SetPlayersSimulated(simulated: false); + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + PlayerAssigner.instance.SetPlayersCanJoin(canJoin: true); + PlayerManager.instance.AddPlayerDiedAction(PlayerDied); + PlayerManager playerManager = PlayerManager.instance; + playerManager.PlayerJoinedAction = (Action<Player>)Delegate.Combine(playerManager.PlayerJoinedAction, new Action<Player>(PlayerJoined)); + ArtHandler.instance.NextArt(); + playersNeededToStart = 2; + UIHandler.instance.SetNumberOfRounds(roundsToWinGame); + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + if (!PhotonNetwork.OfflineMode) + { + UIHandler.instance.ShowJoinGameText("PRESS JUMP\n TO JOIN", PlayerSkinBank.GetPlayerSkinColors(0).winText); + } + } + + private void Update() + { + if (Input.GetKey(KeyCode.Alpha4)) + { + playersNeededToStart = 4; + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + } + if (Input.GetKey(KeyCode.Alpha2)) + { + playersNeededToStart = 2; + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + } + } + + public void PlayerJoined(Player player) + { + if (PhotonNetwork.OfflineMode) + { + return; + } + if (!PhotonNetwork.OfflineMode) + { + if (player.data.view.IsMine) + { + UIHandler.instance.ShowJoinGameText("WAITING", PlayerSkinBank.GetPlayerSkinColors(1).winText); + } + else + { + UIHandler.instance.ShowJoinGameText("PRESS JUMP\n TO JOIN", PlayerSkinBank.GetPlayerSkinColors(1).winText); + } + } + player.data.isPlaying = false; + int count = PlayerManager.instance.players.Count; + if (count >= playersNeededToStart) + { + StartGame(); + } + else if (PhotonNetwork.OfflineMode) + { + if (playersNeededToStart - count == 3) + { + UIHandler.instance.ShowJoinGameText("ADD THREE MORE PLAYER TO START", PlayerSkinBank.GetPlayerSkinColors(count).winText); + } + if (playersNeededToStart - count == 2) + { + UIHandler.instance.ShowJoinGameText("ADD TWO MORE PLAYER TO START", PlayerSkinBank.GetPlayerSkinColors(count).winText); + } + if (playersNeededToStart - count == 1) + { + UIHandler.instance.ShowJoinGameText("ADD ONE MORE PLAYER TO START", PlayerSkinBank.GetPlayerSkinColors(count).winText); + } + } + } + + [PunRPC] + private void RPCO_RequestSyncUp() + { + view.RPC("RPCM_ReturnSyncUp", RpcTarget.Others); + } + + [PunRPC] + private void RPCM_ReturnSyncUp() + { + isWaiting = false; + } + + private IEnumerator WaitForSyncUp() + { + if (!PhotonNetwork.OfflineMode) + { + isWaiting = true; + view.RPC("RPCO_RequestSyncUp", RpcTarget.Others); + while (isWaiting) + { + yield return null; + } + } + } + + public void StartGame() + { + if (!GameManager.instance.isPlaying) + { + StartGameAction?.Invoke(); + GameManager.instance.isPlaying = true; + StartCoroutine(DoStartGame()); + } + } + + private IEnumerator DoStartGame() + { + GameManager.instance.battleOngoing = false; + UIHandler.instance.ShowJoinGameText("LETS GOO!", PlayerSkinBank.GetPlayerSkinColors(1).winText); + yield return new WaitForSeconds(0.25f); + UIHandler.instance.HideJoinGameText(); + PlayerManager.instance.SetPlayersSimulated(simulated: false); + PlayerManager.instance.SetPlayersVisible(visible: false); + MapManager.instance.LoadNextLevel(); + TimeHandler.instance.DoSpeedUp(); + yield return new WaitForSecondsRealtime(1f); + if (pickPhase) + { + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + yield return StartCoroutine(WaitForSyncUp()); + CardChoiceVisuals.instance.Show(i, animateIn: true); + yield return CardChoice.instance.DoPick(1, PlayerManager.instance.players[i].playerID, PickerType.Player); + yield return new WaitForSecondsRealtime(0.1f); + } + yield return StartCoroutine(WaitForSyncUp()); + CardChoiceVisuals.instance.Hide(); + } + MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); + TimeHandler.instance.DoSpeedUp(); + TimeHandler.instance.StartGame(); + GameManager.instance.battleOngoing = true; + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + PlayerManager.instance.SetPlayersVisible(visible: true); + } + + private IEnumerator PointTransition(int winningTeamID, string winTextBefore, string winText) + { + StartCoroutine(PointVisualizer.instance.DoSequence(p1Points, p2Points, winningTeamID == 0)); + yield return new WaitForSecondsRealtime(1f); + MapManager.instance.LoadNextLevel(); + yield return new WaitForSecondsRealtime(0.5f); + yield return StartCoroutine(WaitForSyncUp()); + MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); + PlayerManager.instance.RevivePlayers(); + yield return new WaitForSecondsRealtime(0.3f); + TimeHandler.instance.DoSpeedUp(); + GameManager.instance.battleOngoing = true; + isTransitioning = false; + } + + private void PointOver(int winningTeamID) + { + int num = p1Points; + int num2 = p2Points; + if (winningTeamID == 0) + { + num--; + } + else + { + num2--; + } + string winTextBefore = num + " - " + num2; + string winText = p1Points + " - " + p2Points; + StartCoroutine(PointTransition(winningTeamID, winTextBefore, winText)); + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + } + + private IEnumerator RoundTransition(int winningTeamID, int killedTeamID) + { + StartCoroutine(PointVisualizer.instance.DoWinSequence(p1Points, p2Points, p1Rounds, p2Rounds, winningTeamID == 0)); + yield return new WaitForSecondsRealtime(1f); + MapManager.instance.LoadNextLevel(); + yield return new WaitForSecondsRealtime(0.3f); + yield return new WaitForSecondsRealtime(1f); + TimeHandler.instance.DoSpeedUp(); + if (pickPhase) + { + Debug.Log("PICK PHASE"); + PlayerManager.instance.SetPlayersVisible(visible: false); + Player[] players = PlayerManager.instance.GetPlayersInTeam(killedTeamID); + for (int i = 0; i < players.Length; i++) + { + yield return StartCoroutine(WaitForSyncUp()); + yield return CardChoice.instance.DoPick(1, players[i].playerID, PickerType.Player); + yield return new WaitForSecondsRealtime(0.1f); + } + PlayerManager.instance.SetPlayersVisible(visible: true); + } + yield return StartCoroutine(WaitForSyncUp()); + TimeHandler.instance.DoSlowDown(); + MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); + PlayerManager.instance.RevivePlayers(); + yield return new WaitForSecondsRealtime(0.3f); + TimeHandler.instance.DoSpeedUp(); + isTransitioning = false; + GameManager.instance.battleOngoing = true; + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + } + + private void RoundOver(int winningTeamID, int losingTeamID) + { + currentWinningTeamID = winningTeamID; + StartCoroutine(RoundTransition(winningTeamID, losingTeamID)); + p1Points = 0; + p2Points = 0; + } + + private IEnumerator GameOverTransition(int winningTeamID) + { + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + UIHandler.instance.DisplayScreenText(PlayerManager.instance.GetColorFromTeam(winningTeamID).winText, "VICTORY!", 1f); + yield return new WaitForSecondsRealtime(2f); + GameOverRematch(winningTeamID); + } + + private void GameOverRematch(int winningTeamID) + { + UIHandler.instance.DisplayScreenTextLoop(PlayerManager.instance.GetColorFromTeam(winningTeamID).winText, "REMATCH?"); + UIHandler.instance.DisplayYesNoLoop(PlayerManager.instance.GetFirstPlayerInTeam(winningTeamID), GetRematchYesNo); + MapManager.instance.LoadNextLevel(); + } + + private void GetRematchYesNo(PopUpHandler.YesNo yesNo) + { + if (yesNo == PopUpHandler.YesNo.Yes) + { + StartCoroutine(IDoRematch()); + } + else + { + DoRestart(); + } + } + + [PunRPC] + public void RPCA_PlayAgain() + { + waitingForOtherPlayer = false; + } + + private IEnumerator IDoRematch() + { + if (!PhotonNetwork.OfflineMode) + { + GetComponent<PhotonView>().RPC("RPCA_PlayAgain", RpcTarget.Others); + UIHandler.instance.DisplayScreenTextLoop("WAITING"); + float c = 0f; + while (waitingForOtherPlayer) + { + c += Time.unscaledDeltaTime; + if (c > 10f) + { + DoRestart(); + yield break; + } + yield return null; + } + } + yield return null; + UIHandler.instance.StopScreenTextLoop(); + PlayerManager.instance.ResetCharacters(); + ResetMatch(); + StartCoroutine(DoStartGame()); + waitingForOtherPlayer = true; + } + + private void ResetMatch() + { + p1Points = 0; + p1Rounds = 0; + p2Points = 0; + p2Rounds = 0; + isTransitioning = false; + waitingForOtherPlayer = false; + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + CardBarHandler.instance.ResetCardBards(); + PointVisualizer.instance.ResetPoints(); + } + + private void GameOverContinue(int winningTeamID) + { + UIHandler.instance.DisplayScreenTextLoop(PlayerManager.instance.GetColorFromTeam(winningTeamID).winText, "CONTINUE?"); + UIHandler.instance.DisplayYesNoLoop(PlayerManager.instance.GetFirstPlayerInTeam(winningTeamID), GetContinueYesNo); + MapManager.instance.LoadNextLevel(); + } + + private void GetContinueYesNo(PopUpHandler.YesNo yesNo) + { + if (yesNo == PopUpHandler.YesNo.Yes) + { + DoContinue(); + } + else + { + DoRestart(); + } + } + + private void DoContinue() + { + UIHandler.instance.StopScreenTextLoop(); + roundsToWinGame += 2; + UIHandler.instance.SetNumberOfRounds(roundsToWinGame); + RoundOver(currentWinningTeamID, PlayerManager.instance.GetOtherTeam(currentWinningTeamID)); + } + + private void DoRestart() + { + GameManager.instance.battleOngoing = false; + if (PhotonNetwork.OfflineMode) + { + Application.LoadLevel(Application.loadedLevel); + } + else + { + NetworkConnectionHandler.instance.NetworkRestart(); + } + } + + private void GameOver(int winningTeamID) + { + currentWinningTeamID = winningTeamID; + StartCoroutine(GameOverTransition(winningTeamID)); + } + + public void PlayerDied(Player killedPlayer, int playersAlive) + { + if (!PhotonNetwork.OfflineMode) + { + Debug.Log("PlayerDied: " + killedPlayer.data.view.Owner.NickName); + } + if (PlayerManager.instance.TeamsAlive() < 2) + { + TimeHandler.instance.DoSlowDown(); + if (PhotonNetwork.IsMasterClient) + { + view.RPC("RPCA_NextRound", RpcTarget.All, PlayerManager.instance.GetOtherTeam(PlayerManager.instance.GetLastTeamAlive()), PlayerManager.instance.GetLastTeamAlive(), p1Points, p2Points, p1Rounds, p2Rounds); + } + } + } + + [PunRPC] + public void RPCA_NextRound(int losingTeamID, int winningTeamID, int p1PointsSet, int p2PointsSet, int p1RoundsSet, int p2RoundsSet) + { + if (isTransitioning) + { + return; + } + GameManager.instance.battleOngoing = false; + p1Points = p1PointsSet; + p2Points = p2PointsSet; + p1Rounds = p1RoundsSet; + p2Rounds = p2RoundsSet; + Debug.Log("Winning team: " + winningTeamID); + Debug.Log("Losing team: " + losingTeamID); + isTransitioning = true; + GameManager.instance.GameOver(winningTeamID, losingTeamID); + PlayerManager.instance.SetPlayersSimulated(simulated: false); + switch (winningTeamID) + { + case 0: + p1Points++; + if (p1Points >= pointsToWinRound) + { + p1Rounds++; + if (p1Rounds >= roundsToWinGame) + { + Debug.Log("Game over, winning team: " + winningTeamID); + GameOver(winningTeamID); + pointOverAction(); + } + else + { + Debug.Log("Round over, winning team: " + winningTeamID); + RoundOver(winningTeamID, losingTeamID); + pointOverAction(); + } + } + else + { + Debug.Log("Point over, winning team: " + winningTeamID); + PointOver(winningTeamID); + pointOverAction(); + } + break; + case 1: + p2Points++; + if (p2Points >= pointsToWinRound) + { + p2Rounds++; + if (p2Rounds >= roundsToWinGame) + { + Debug.Log("Game over, winning team: " + winningTeamID); + GameOver(winningTeamID); + pointOverAction(); + } + else + { + Debug.Log("Round over, winning team: " + winningTeamID); + RoundOver(winningTeamID, losingTeamID); + pointOverAction(); + } + } + else + { + Debug.Log("Point over, winning team: " + winningTeamID); + PointOver(winningTeamID); + pointOverAction(); + } + break; + } + } +} diff --git a/GameCode/GM_Test.cs b/GameCode/GM_Test.cs new file mode 100644 index 0000000..b5d7ef6 --- /dev/null +++ b/GameCode/GM_Test.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections; +using UnityEngine; + +public class GM_Test : MonoBehaviour +{ + public bool testMap; + + public static GM_Test instance; + + private void Awake() + { + instance = this; + if (base.gameObject.activeSelf && !Application.isEditor) + { + testMap = false; + } + } + + private void Start() + { + if (testMap) + { + base.transform.root.GetComponent<SetOfflineMode>().SetOffline(); + } + if (testMap) + { + MapManager.instance.isTestingMap = true; + } + if (base.gameObject.activeSelf) + { + if (!testMap) + { + MapManager.instance.LoadNextLevel(callInImidetly: true, forceLoad: true); + } + else + { + MapManager.instance.currentMap = new MapWrapper(UnityEngine.Object.FindObjectOfType<Map>(), UnityEngine.Object.FindObjectOfType<Map>().gameObject.scene); + ArtHandler.instance.NextArt(); + } + PlayerAssigner.instance.SetPlayersCanJoin(canJoin: true); + TimeHandler.instance.StartGame(); + PlayerManager playerManager = PlayerManager.instance; + playerManager.PlayerJoinedAction = (Action<Player>)Delegate.Combine(playerManager.PlayerJoinedAction, new Action<Player>(PlayerWasAdded)); + PlayerManager.instance.AddPlayerDiedAction(PlayerDied); + GameManager.instance.isPlaying = true; + GameManager.instance.battleOngoing = true; + } + } + + private void PlayerWasAdded(Player player) + { + PlayerManager.instance.SetPlayersSimulated(simulated: true); + player.data.GetComponent<PlayerCollision>().IgnoreWallForFrames(2); + player.transform.position = MapManager.instance.currentMap.Map.GetRandomSpawnPos(); + PlayerManager.instance.SetPlayersSimulated(simulated: true); + PlayerManager.instance.SetPlayersPlaying(playing: true); + } + + private void PlayerDied(Player player, int unused) + { + StartCoroutine(DelayRevive(player)); + } + + private IEnumerator DelayRevive(Player player) + { + yield return new WaitForSecondsRealtime(2.5f); + PlayerWasAdded(player); + player.data.healthHandler.Revive(); + } +} diff --git a/GameCode/GameAnalytics.cs b/GameCode/GameAnalytics.cs new file mode 100644 index 0000000..4451ccb --- /dev/null +++ b/GameCode/GameAnalytics.cs @@ -0,0 +1,17 @@ +using UnityEngine; +using UnityEngine.Analytics; + +public class GameAnalytics : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.P)) + { + Analytics.SendEvent("PlayerKills", 5); + } + } +} diff --git a/GameCode/GameCrownHandler.cs b/GameCode/GameCrownHandler.cs new file mode 100644 index 0000000..8e555d5 --- /dev/null +++ b/GameCode/GameCrownHandler.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections; +using UnityEngine; + +public class GameCrownHandler : MonoBehaviour +{ + private float crownPos; + + public AnimationCurve transitionCurve; + + private GM_ArmsRace gm; + + private int currentCrownHolder = -1; + + private void Start() + { + gm = GetComponentInParent<GM_ArmsRace>(); + GM_ArmsRace gM_ArmsRace = gm; + gM_ArmsRace.pointOverAction = (Action)Delegate.Combine(gM_ArmsRace.pointOverAction, new Action(PointOver)); + } + + public void PointOver() + { + int num = -1; + int num2 = -1; + if (gm.p1Rounds > gm.p2Rounds) + { + num2 = 0; + } + if (gm.p1Rounds < gm.p2Rounds) + { + num2 = 1; + } + if (num2 == -1) + { + int num3 = -1; + if (gm.p1Points > gm.p2Points) + { + num3 = 0; + } + if (gm.p1Points < gm.p2Points) + { + num3 = 1; + } + if (num3 != -1) + { + num = num3; + } + } + else + { + num = num2; + } + if (num != -1 && num != currentCrownHolder) + { + if (currentCrownHolder == -1) + { + currentCrownHolder = num; + crownPos = currentCrownHolder; + GetComponent<CurveAnimation>().PlayIn(); + } + else + { + GiveCrownToPlayer(num); + } + } + } + + private void LateUpdate() + { + if (currentCrownHolder == -1) + { + return; + } + if (PlayerManager.instance.players[currentCrownHolder].gameObject.activeInHierarchy) + { + if (!base.transform.GetChild(0).gameObject.activeSelf) + { + base.transform.GetChild(0).gameObject.SetActive(value: true); + } + } + else if (base.transform.GetChild(0).gameObject.activeSelf) + { + base.transform.GetChild(0).gameObject.SetActive(value: false); + } + Vector3 position = Vector3.LerpUnclamped(PlayerManager.instance.players[0].data.GetCrownPos(), PlayerManager.instance.players[1].data.GetCrownPos(), crownPos); + base.transform.position = position; + } + + private void GiveCrownToPlayer(int playerID) + { + currentCrownHolder = playerID; + StartCoroutine(IGiveCrownToPlayer(playerID)); + } + + private IEnumerator IGiveCrownToPlayer(int playerID) + { + int fromInt; + int toInt; + if (playerID == 0) + { + fromInt = 1; + toInt = 0; + } + else + { + fromInt = 0; + toInt = 1; + } + for (float i = 0f; i < transitionCurve.keys[transitionCurve.keys.Length - 1].time; i += Time.unscaledDeltaTime) + { + crownPos = Mathf.LerpUnclamped(fromInt, toInt, transitionCurve.Evaluate(i)); + yield return null; + } + } +} diff --git a/GameCode/GameFeeler.cs b/GameCode/GameFeeler.cs new file mode 100644 index 0000000..7021a3e --- /dev/null +++ b/GameCode/GameFeeler.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public abstract class GameFeeler : MonoBehaviour +{ + private void Awake() + { + GamefeelManager.RegisterGamefeeler(this); + OnAwake(); + } + + public abstract void OnGameFeel(Vector2 feelDirection); + + public abstract void OnUIGameFeel(Vector2 feelDirection); + + public virtual void OnAwake() + { + } +} diff --git a/GameCode/GameManager.cs b/GameCode/GameManager.cs new file mode 100644 index 0000000..45aaeee --- /dev/null +++ b/GameCode/GameManager.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +public class GameManager : MonoBehaviour +{ + [Header("Settings")] + public static bool lockInput; + + public static GameManager instance; + + public bool isPlaying; + + public bool battleOngoing; + + public Action<int, int> GameOverAction; + + public void Awake() + { + instance = this; + } + + private void Start() + { + lockInput = false; + } + + private void Update() + { + } + + public void GameOver(int winingTeamID, int killedTeamID) + { + if (GameOverAction != null) + { + GameOverAction(winingTeamID, killedTeamID); + } + } +} diff --git a/GameCode/GamefeelManager.cs b/GameCode/GamefeelManager.cs new file mode 100644 index 0000000..ac99a47 --- /dev/null +++ b/GameCode/GamefeelManager.cs @@ -0,0 +1,60 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class GamefeelManager : MonoBehaviour +{ + public static GamefeelManager instance; + + private List<GameFeeler> m_GameFeelers = new List<GameFeeler>(); + + private void Awake() + { + instance = this; + } + + public static void RegisterGamefeeler(GameFeeler gameFeeler) + { + instance.m_GameFeelers.Add(gameFeeler); + } + + public void AddUIGameFeel(Vector2 directionForce) + { + for (int i = 0; i < instance.m_GameFeelers.Count; i++) + { + instance.m_GameFeelers[i].OnUIGameFeel(directionForce); + } + } + + public void AddGameFeel(Vector2 directionForce) + { + for (int i = 0; i < instance.m_GameFeelers.Count; i++) + { + instance.m_GameFeelers[i].OnGameFeel(directionForce); + } + } + + public static void GameFeel(Vector2 directionForce) + { + for (int i = 0; i < instance.m_GameFeelers.Count; i++) + { + instance.m_GameFeelers[i].OnGameFeel(directionForce); + } + } + + public void AddUIGameFeelOverTime(float amount, float time) + { + StartCoroutine(DoUIGameFeelOverTime(amount, time)); + } + + private IEnumerator DoUIGameFeelOverTime(float amount, float time) + { + float startTime = time; + while (time > 0f) + { + instance.AddUIGameFeel(amount * (Vector2)Random.onUnitSphere * Time.unscaledDeltaTime * (time / startTime)); + time -= Time.unscaledDeltaTime; + yield return null; + } + } +} diff --git a/GameCode/GeneralInput.cs b/GameCode/GeneralInput.cs new file mode 100644 index 0000000..0487def --- /dev/null +++ b/GameCode/GeneralInput.cs @@ -0,0 +1,274 @@ +using System.Collections; +using UnityEngine; + +public class GeneralInput : MonoBehaviour +{ + public enum InputType + { + Controller, + Keyboard, + Either + } + + public enum StickDirection + { + Left, + Right, + None + } + + public bool controlledElseWhere; + + public bool stunnedInput; + + public bool silencedInput; + + public KeyCode left; + + public KeyCode right; + + public KeyCode up; + + public KeyCode down; + + public KeyCode jump; + + public KeyCode shoot; + + public KeyCode shield; + + public Vector3 direction; + + public Vector3 latestPressedDirection; + + public Vector3 aimDirection; + + public Vector3 lastAimDirection; + + public bool jumpWasPressed; + + public bool jumpIsPressed; + + public bool shootWasPressed; + + public bool shootIsPressed; + + public bool shootWasReleased; + + public bool shieldWasPressed; + + public bool acceptWasPressed; + + public InputType inputType; + + private StickDirection lastStickDirection; + + public StickDirection stickPressDir = StickDirection.None; + + private CharacterData data; + + private int snapNumber = 16; + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + public void ResetInput() + { + direction = Vector3.zero; + aimDirection = Vector3.zero; + jumpIsPressed = false; + jumpWasPressed = false; + shootIsPressed = false; + shootWasPressed = false; + shootWasReleased = false; + shieldWasPressed = false; + acceptWasPressed = false; + } + + private void Update() + { + if (controlledElseWhere) + { + return; + } + ResetInput(); + DoUIInput(); + if (GameManager.lockInput || stunnedInput || !data.isPlaying || data.playerActions == null) + { + return; + } + direction += (Vector3)data.playerActions.Move; + direction = MakeEightDirections(direction); + if (direction != Vector3.zero) + { + latestPressedDirection = direction; + } + if (data.playerActions.Device == null) + { + aimDirection = MainCam.instance.cam.ScreenToWorldPoint(Input.mousePosition) - base.transform.position; + aimDirection.z = 0f; + aimDirection.Normalize(); + if (Optionshandler.lockMouse) + { + aimDirection = MakeEightDirections(aimDirection); + } + } + else + { + aimDirection.x += data.playerActions.Aim.X; + aimDirection.y += data.playerActions.Aim.Y; + if (Optionshandler.lockStick) + { + aimDirection = MakeEightDirections(aimDirection); + } + } + if (aimDirection != Vector3.zero) + { + aimDirection += Vector3.up * 0.13f / Mathf.Clamp(data.weaponHandler.gun.projectileSpeed, 1f, 100f); + } + if (aimDirection != Vector3.zero) + { + lastAimDirection = aimDirection; + } + if (data.playerActions.Jump.IsPressed) + { + jumpIsPressed = true; + } + if (data.playerActions.Jump.WasPressed) + { + jumpWasPressed = true; + } + if (!silencedInput) + { + if (data.playerActions.Fire.IsPressed) + { + shootIsPressed = true; + } + if (data.playerActions.Fire.WasPressed) + { + shootWasPressed = true; + } + if (data.playerActions.Fire.WasReleased) + { + shootWasReleased = true; + } + if (data.playerActions.Block.WasPressed) + { + shieldWasPressed = true; + } + } + } + + private void DoUIInput() + { + StickDirection stickDirection = StickDirection.None; + if (data.playerActions.Move.X > 0.7f) + { + stickDirection = StickDirection.Right; + } + if (data.playerActions.Move.X < -0.7f) + { + stickDirection = StickDirection.Left; + } + if (stickDirection != lastStickDirection) + { + stickPressDir = stickDirection; + lastStickDirection = stickDirection; + } + else + { + stickPressDir = StickDirection.None; + } + if (data.playerActions.Jump.WasPressed) + { + acceptWasPressed = true; + } + } + + public void DoStun(float stun) + { + if (base.gameObject.activeSelf) + { + StartCoroutine(Stun(stun)); + } + } + + private IEnumerator Stun(float stun) + { + base.enabled = false; + ResetInput(); + yield return new WaitForSeconds(stun); + base.enabled = true; + } + + public void SetState(Vector3 pos, bool isGrounded) + { + base.transform.position = pos; + } + + public void Move(bool right, bool left, bool up, bool down, bool jump) + { + ResetInput(); + if (left) + { + direction += Vector3.left; + } + if (right) + { + direction += Vector3.right; + } + if (up) + { + direction += Vector3.up; + } + if (down) + { + direction += Vector3.down; + } + if (jump) + { + jumpWasPressed = true; + } + Debug.Log("Move: Right: " + right + " Left: " + left + " Jump: " + jump); + if (Input.GetKey(shoot)) + { + shootIsPressed = true; + } + if (Input.GetKeyDown(shoot)) + { + shootWasPressed = true; + } + if (Input.GetKeyUp(shoot)) + { + shootWasReleased = true; + } + } + + private Vector3 MakeEightDirections(Vector3 dir) + { + _ = Vector3.zero; + float num = 360f / (float)snapNumber; + Vector3 vector = Vector3.up; + Vector3 vector2 = vector; + float num2 = 999f; + Vector3 result = dir; + for (int i = 0; i < snapNumber; i++) + { + vector2 = Quaternion.Euler(Vector3.forward * num * i) * vector; + float num3 = Vector3.Angle(dir, vector2); + if (num3 < num2) + { + num2 = num3; + result = vector2; + } + } + if (dir == Vector3.zero) + { + return Vector3.zero; + } + dir = dir.normalized; + return result; + } +} diff --git a/GameCode/GeneralParticleSystem.cs b/GameCode/GeneralParticleSystem.cs new file mode 100644 index 0000000..8f3203a --- /dev/null +++ b/GameCode/GeneralParticleSystem.cs @@ -0,0 +1,304 @@ +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; + +public class GeneralParticleSystem : MonoBehaviour +{ + public GameObject particleObject; + + public bool useTimeScale; + + private ObjectPool particlePool; + + [FoldoutGroup("Spawn settings", 0)] + public float randomXPos; + + [FoldoutGroup("Spawn settings", 0)] + public float randomYPos; + + [FoldoutGroup("Spawn settings", 0)] + public float rate = 10f; + + [FoldoutGroup("Spawn settings", 0)] + public bool playOnAwake = true; + + [FoldoutGroup("Spawn settings", 0)] + public bool playOnEnablee; + + [FoldoutGroup("Spawn settings", 0)] + public bool loop; + + [FoldoutGroup("Spawn settings", 0)] + public float duration = 2f; + + [FoldoutGroup("Spawn settings", 0)] + public AnimationCurve sizeMultiplierOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + public AnimationCurve emissionMultiplierOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + public ObjectParticle particleSettings; + + [FoldoutGroup("Global settings", 0)] + public float simulationSpeed = 1f; + + [HideInInspector] + public float simulationSpeedMultiplier = 1f; + + [FoldoutGroup("Global settings", 0)] + public float saturationMultiplier = 1f; + + [FoldoutGroup("Events", 0)] + public UnityEvent startEvent; + + [FoldoutGroup("Events", 0)] + public float startEventDelay; + + [FoldoutGroup("Events", 0)] + public UnityEvent endEvent; + + [FoldoutGroup("Events", 0)] + public float endEventDelay; + + private float sizeOverTimeAnimationCurveLength; + + private float sizeMultiplierOverTimeAnimationCurveLength; + + private float alphaOverTimeAnimationCurveLength; + + private float emissionOverTimeAnimationCurveLength; + + private bool inited; + + private Coroutine emissionLoop; + + private float lastEmissionTime; + + private bool isPlaying; + + private void OnEnable() + { + isPlaying = false; + if (playOnEnablee) + { + Play(); + } + } + + private void Start() + { + if (playOnAwake) + { + Play(); + } + Mask component = base.transform.parent.GetComponent<Mask>(); + if ((bool)component) + { + component.showMaskGraphic = false; + } + } + + private void Init() + { + if (!inited) + { + inited = true; + if (particleSettings.sizeOverTime.keys.Length > 1) + { + sizeOverTimeAnimationCurveLength = particleSettings.sizeOverTime.keys[particleSettings.sizeOverTime.keys.Length - 1].time - particleSettings.sizeOverTime.keys[0].time; + } + if (particleSettings.alphaOverTime.keys.Length > 1) + { + alphaOverTimeAnimationCurveLength = particleSettings.alphaOverTime.keys[particleSettings.alphaOverTime.keys.Length - 1].time - particleSettings.alphaOverTime.keys[0].time; + } + if (sizeMultiplierOverTime.keys.Length > 1) + { + sizeMultiplierOverTimeAnimationCurveLength = sizeMultiplierOverTime.keys[sizeMultiplierOverTime.keys.Length - 1].time - sizeMultiplierOverTime.keys[0].time; + } + if (emissionMultiplierOverTime.keys.Length > 1) + { + emissionOverTimeAnimationCurveLength = emissionMultiplierOverTime.keys[emissionMultiplierOverTime.keys.Length - 1].time - emissionMultiplierOverTime.keys[0].time; + } + particleObject.SetActive(value: false); + particlePool = new ObjectPool(particleObject, 100, base.transform); + } + } + + public void StartLooping() + { + loop = true; + Play(); + } + + public void EndLooping() + { + loop = false; + if (emissionLoop != null) + { + StopCoroutine(emissionLoop); + } + } + + [Button] + public void Play() + { + Init(); + if (!isPlaying) + { + emissionLoop = StartCoroutine(DoPlay()); + } + } + + private void OnDisable() + { + Stop(); + } + + public void Stop() + { + isPlaying = false; + DisableAllParticles(); + if (emissionLoop != null) + { + StopCoroutine(emissionLoop); + } + } + + private void DisableAllParticles() + { + if (base.transform.childCount > 0) + { + for (int i = 0; i < base.transform.GetChild(0).childCount; i++) + { + base.transform.GetChild(0).GetChild(i).gameObject.SetActive(value: false); + } + } + } + + private IEnumerator DoPlay() + { + isPlaying = true; + if (startEvent != null) + { + if (startEventDelay != 0f) + { + StartCoroutine(DelayEvent(startEvent, startEventDelay)); + } + else + { + startEvent.Invoke(); + } + } + float counter = 0f; + while (counter < duration) + { + CheckIfShouldEmit(counter / duration); + counter += (useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime) * (simulationSpeed * simulationSpeedMultiplier); + yield return null; + } + isPlaying = false; + if (loop) + { + Play(); + } + else if (endEvent != null) + { + if (endEventDelay != 0f) + { + StartCoroutine(DelayEvent(endEvent, endEventDelay)); + } + else + { + endEvent.Invoke(); + } + } + } + + private void CheckIfShouldEmit(float currentAnimationTime) + { + if ((useTimeScale ? Time.time : Time.unscaledTime) > lastEmissionTime + 1f / rate / (simulationSpeed * simulationSpeedMultiplier) / emissionMultiplierOverTime.Evaluate(currentAnimationTime * emissionOverTimeAnimationCurveLength) * Time.timeScale) + { + StartCoroutine(DoPlarticleLife(currentAnimationTime)); + lastEmissionTime = Time.time; + } + } + + private IEnumerator DoPlarticleLife(float currentAnimationTime) + { + GameObject spawned = particlePool.GetObject(); + float counter = 0f; + float t = particleSettings.lifetime; + Vector3 startSize = spawned.transform.localScale; + Vector3 modifiedStartSize = spawned.transform.localScale * particleSettings.size * sizeMultiplierOverTime.Evaluate(currentAnimationTime * sizeMultiplierOverTimeAnimationCurveLength); + Image img = spawned.GetComponent<Image>(); + Color startColor = Color.magenta; + if ((bool)img) + { + startColor = img.color; + } + if ((bool)img) + { + float value = Random.value; + if (particleSettings.color != Color.magenta) + { + img.color = particleSettings.color; + } + if (particleSettings.randomColor != Color.magenta) + { + img.color = Color.Lerp(img.color, particleSettings.randomColor, value); + } + if (!particleSettings.singleRandomValueColor) + { + value = Random.value; + } + if (particleSettings.randomAddedColor != Color.black) + { + img.color += Color.Lerp(Color.black, particleSettings.randomAddedColor, value); + } + if (!particleSettings.singleRandomValueColor) + { + value = Random.value; + } + if (particleSettings.randomAddedSaturation != 0f || saturationMultiplier != 1f) + { + Color.RGBToHSV(img.color, out var H, out var S, out var V); + S += value * particleSettings.randomAddedSaturation; + S *= saturationMultiplier; + img.color = Color.HSVToRGB(H, S, V); + } + } + spawned.transform.Rotate(base.transform.forward * particleSettings.rotation); + spawned.transform.Rotate(base.transform.forward * Random.Range(0f - particleSettings.randomRotation, particleSettings.randomRotation)); + spawned.transform.localPosition = Vector3.zero; + spawned.transform.position += base.transform.up * Random.Range(0f - randomYPos, randomYPos); + spawned.transform.position += base.transform.right * Random.Range(0f - randomXPos, randomXPos); + spawned.transform.position += base.transform.forward * Random.Range(-0.1f, 0.1f); + while (counter < t) + { + if (particleSettings.sizeOverTime.keys.Length > 1) + { + spawned.transform.localScale = modifiedStartSize * particleSettings.sizeOverTime.Evaluate(counter / t * sizeOverTimeAnimationCurveLength); + } + float num = particleSettings.alphaOverTime.Evaluate(counter / t * alphaOverTimeAnimationCurveLength); + if ((bool)img && img.color.a != num) + { + img.color = new Color(img.color.r, img.color.g, img.color.b, num); + } + counter += (useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime) * (simulationSpeed * simulationSpeedMultiplier); + yield return null; + } + if ((bool)img) + { + img.color = startColor; + } + spawned.transform.localScale = startSize; + particlePool.ReleaseObject(spawned); + } + + private IEnumerator DelayEvent(UnityEvent e, float t) + { + yield return new WaitForSeconds(t); + e?.Invoke(); + } +} diff --git a/GameCode/GeneralShooter.cs b/GameCode/GeneralShooter.cs new file mode 100644 index 0000000..3d39423 --- /dev/null +++ b/GameCode/GeneralShooter.cs @@ -0,0 +1,43 @@ +using System.Collections; +using UnityEngine; + +public class GeneralShooter : MonoBehaviour +{ + private Gun gun; + + [HideInInspector] + public float charge; + + public Transform[] shooters; + + private void Start() + { + gun = GetComponent<Gun>(); + } + + public void Attack() + { + if (base.enabled) + { + StartCoroutine(DoAttack()); + } + } + + private IEnumerator DoAttack() + { + int shotsToMake = Mathf.Clamp(Mathf.RoundToInt(0.5f / gun.attackSpeed), 1, 5); + for (int i = 0; i < shotsToMake; i++) + { + for (int j = 0; j < shooters.Length; j++) + { + gun.transform.position = shooters[j].position; + gun.transform.rotation = shooters[j].rotation; + gun.Attack(gun.currentCharge, forceAttack: true); + } + if (shotsToMake > i) + { + yield return new WaitForSeconds(0.1f); + } + } + } +} diff --git a/GameCode/GetColor.cs b/GameCode/GetColor.cs new file mode 100644 index 0000000..89dad00 --- /dev/null +++ b/GameCode/GetColor.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class GetColor : MonoBehaviour +{ + public ColorHandler.ColorType colorType; + + private bool inited; + + public void Start() + { + if (!inited) + { + inited = true; + SpriteRenderer component = GetComponent<SpriteRenderer>(); + if ((bool)component) + { + component.color = ColorHandler.instance.GetColor(colorType); + } + } + } +} diff --git a/GameCode/GetControllerButton.cs b/GameCode/GetControllerButton.cs new file mode 100644 index 0000000..bcb331e --- /dev/null +++ b/GameCode/GetControllerButton.cs @@ -0,0 +1,3 @@ +public class GetControllerButton +{ +} diff --git a/GameCode/GifCam.cs b/GameCode/GifCam.cs new file mode 100644 index 0000000..d7152c4 --- /dev/null +++ b/GameCode/GifCam.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class GifCam : MonoBehaviour +{ + public static bool isGifCam; + + private Camera[] cameras; + + private Vector3 camStartPos; + + private float cameraStartSize; + + private bool follow = true; + + private void Start() + { + cameras = GetComponentsInChildren<Camera>(); + camStartPos = cameras[0].transform.position; + cameraStartSize = cameras[0].orthographicSize; + } + + private void Update() + { + } +} diff --git a/GameCode/GoBack.cs b/GameCode/GoBack.cs new file mode 100644 index 0000000..2853d6d --- /dev/null +++ b/GameCode/GoBack.cs @@ -0,0 +1,31 @@ +using InControl; +using UnityEngine; +using UnityEngine.Events; + +public class GoBack : MonoBehaviour +{ + public UnityEvent goBackEvent; + + public ListMenuPage target; + + private void Start() + { + } + + private void Update() + { + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].Action2.WasPressed) + { + goBackEvent.Invoke(); + target.Open(); + } + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + goBackEvent.Invoke(); + target.Open(); + } + } +} diff --git a/GameCode/Grass.cs b/GameCode/Grass.cs new file mode 100644 index 0000000..0557f48 --- /dev/null +++ b/GameCode/Grass.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +public class Grass : MonoBehaviour +{ + public float target; + + private float velocity; + + private float currentRot; + + public float minSpring; + + public float maxSpring; + + public float minDrag; + + public float maxDrag; + + private float spring; + + private float drag; + + public float minPlayerEffect; + + public float maxPlayerEffect; + + private float playerEffect; + + public Sprite[] sprites; + + private void Start() + { + if (Random.value > 0.5f) + { + Object.Destroy(base.gameObject); + return; + } + GetComponentInChildren<SpriteRenderer>().sprite = sprites[Random.Range(0, sprites.Length)]; + spring = Random.Range(minSpring, maxSpring); + drag = Random.Range(minDrag, maxDrag); + playerEffect = Random.Range(minPlayerEffect, maxPlayerEffect); + currentRot = base.transform.localEulerAngles.z; + } + + private void Update() + { + velocity = Mathf.Lerp(velocity, (target - currentRot) * spring, CappedDeltaTime.time * drag); + currentRot += velocity * CappedDeltaTime.time; + base.transform.localEulerAngles = new Vector3(0f, 0f, currentRot); + if (PlayerManager.instance.players != null && PlayerManager.instance.players.Count > 0 && Vector2.Distance(PlayerManager.instance.players[0].data.playerVel.position, base.transform.position) < 1.5f) + { + AddForce(PlayerManager.instance.players[0].data.playerVel.velocity.x * playerEffect * CappedDeltaTime.time * 60f); + } + float num = 0.5f; + float num2 = 0.05f; + AddForce((Mathf.PerlinNoise(base.transform.position.x * num2 + Time.time * num, base.transform.position.y * num2 + Time.time * num) - 0.5f) * 30f * playerEffect * CappedDeltaTime.time * 60f); + } + + public void AddForce(float f) + { + velocity += f; + } +} diff --git a/GameCode/Gravity.cs b/GameCode/Gravity.cs new file mode 100644 index 0000000..1d9cb83 --- /dev/null +++ b/GameCode/Gravity.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +public class Gravity : MonoBehaviour +{ + public float gravityForce; + + public float exponent = 1f; + + private PlayerVelocity rig; + + private CharacterData data; + + private void Start() + { + data = GetComponent<CharacterData>(); + rig = GetComponent<PlayerVelocity>(); + } + + private void FixedUpdate() + { + float num = data.sinceGrounded; + if (data.sinceWallGrab < num) + { + num = data.sinceWallGrab; + } + if (num > 0f) + { + rig.AddForce(Vector3.down * TimeHandler.timeScale * Mathf.Pow(num, exponent) * gravityForce * rig.mass, ForceMode2D.Force); + } + else + { + rig.AddForce(Vector3.down * TimeHandler.timeScale * num * gravityForce * rig.mass, ForceMode2D.Force); + } + } +} diff --git a/GameCode/GridBounceCircle.cs b/GameCode/GridBounceCircle.cs new file mode 100644 index 0000000..f0c6b53 --- /dev/null +++ b/GameCode/GridBounceCircle.cs @@ -0,0 +1,57 @@ +using System.Collections; +using UnityEngine; + +public class GridBounceCircle : GridObject +{ + private float m_startSize; + + private bool isBlooping; + + private float currentDistance; + + private void Start() + { + m_startSize = base.transform.localScale.x; + } + + public override void BopCall(float power) + { + if (!isBlooping || (isBlooping && power > currentDistance)) + { + StopAllCoroutines(); + StartCoroutine(Blop(power)); + } + } + + public override void OnSetSize(float size) + { + if (!isBlooping) + { + base.transform.localScale = Vector3.one * size * m_startSize; + } + } + + private IEnumerator Blop(float power) + { + isBlooping = true; + currentDistance = power; + float maxSize = Mathf.Lerp(1f * m_startSize, 3f * m_startSize, power); + float timer2 = 0f; + while (timer2 < 1f) + { + timer2 += TimeHandler.deltaTime * 10f; + base.transform.localScale = Vector3.one * Mathf.Lerp(m_startSize, maxSize, timer2); + yield return null; + } + yield return new WaitForSeconds(0.2f); + timer2 = 0f; + while (timer2 < 1f) + { + timer2 += TimeHandler.deltaTime * 6f; + base.transform.localScale = Vector3.one * Mathf.Lerp(maxSize, m_startSize, timer2); + yield return null; + } + base.transform.localScale = Vector3.one * m_startSize; + isBlooping = false; + } +} diff --git a/GameCode/GridLightBulb.cs b/GameCode/GridLightBulb.cs new file mode 100644 index 0000000..8fa2523 --- /dev/null +++ b/GameCode/GridLightBulb.cs @@ -0,0 +1,57 @@ +using System.Collections; +using UnityEngine; + +public class GridLightBulb : GridObject +{ + private SpriteRenderer rend; + + public Color maxLightColor; + + private Color baseColor; + + private bool isLitUp; + + private float currentDistance; + + private void Start() + { + rend = GetComponent<SpriteRenderer>(); + baseColor = rend.color; + } + + public override void BopCall(float distance) + { + distance = 1f - distance; + if (!isLitUp || (isLitUp && distance > currentDistance)) + { + StopAllCoroutines(); + StartCoroutine(LightUp(distance)); + } + } + + private IEnumerator LightUp(float distance) + { + isLitUp = true; + currentDistance = distance; + Color lightColor = Color.Lerp(maxLightColor, baseColor, distance); + rend.color = lightColor; + yield return new WaitForSeconds(Random.Range(0.5f, 2f)); + int blinks = Random.Range(0, 8); + bool isOn = true; + for (int i = 0; i < blinks; i++) + { + if (isOn) + { + rend.color = baseColor; + } + else + { + rend.color = lightColor; + } + isOn = !isOn; + yield return new WaitForSeconds(Random.Range(0.05f, 0.1f)); + } + rend.color = baseColor; + isLitUp = false; + } +} diff --git a/GameCode/GridObject.cs b/GameCode/GridObject.cs new file mode 100644 index 0000000..6b4fcdd --- /dev/null +++ b/GameCode/GridObject.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class GridObject : MonoBehaviour +{ + public virtual void BopCall(float power) + { + } + + public virtual void BulletCall(float distance) + { + distance = Mathf.Clamp(0f, 1f, distance); + BopCall(1f - distance); + } + + public virtual void OnPlayerKilled(float distance) + { + } + + public virtual void OnGameOverOver(float distance) + { + } + + public virtual void OnSetSize(float size) + { + } +} diff --git a/GameCode/GridVisualizer.cs b/GameCode/GridVisualizer.cs new file mode 100644 index 0000000..ed73bf2 --- /dev/null +++ b/GameCode/GridVisualizer.cs @@ -0,0 +1,56 @@ +using UnityEngine; + +public class GridVisualizer : MonoBehaviour +{ + public Vector2 min; + + public Vector2 max; + + public GameObject prefab; + + public Vector2Int numberOfObjects; + + internal GridObject[,] spawnedObjects; + + public static GridVisualizer instance; + + private void Start() + { + instance = this; + SpawnGrid(); + } + + public void BulletCall(Vector2 worldSpacePosition) + { + Vector2Int gridPos = WorldToGridSpace(worldSpacePosition); + float power = Vector2.Distance(worldSpacePosition, GridToWorldSpace(gridPos)); + spawnedObjects[gridPos.x, gridPos.y].BopCall(power); + } + + public Vector2 GridToWorldSpace(int x, int y) + { + return GridToWorldSpace(new Vector2Int(x, y)); + } + + public Vector2 GridToWorldSpace(Vector2Int gridPos) + { + return new Vector2(Mathf.Lerp(min.x, max.x, (float)gridPos.x / (float)numberOfObjects.x), Mathf.Lerp(min.y, max.y, (float)gridPos.y / (float)numberOfObjects.y)); + } + + public Vector2Int WorldToGridSpace(Vector2 pos) + { + return new Vector2Int((int)(Mathf.InverseLerp(min.x, max.x, pos.x) * (float)numberOfObjects.x), (int)(Mathf.InverseLerp(min.y, max.y, pos.y) * (float)numberOfObjects.y)); + } + + private void SpawnGrid() + { + spawnedObjects = new GridObject[numberOfObjects.x, numberOfObjects.y]; + for (int i = 0; i < numberOfObjects.x; i++) + { + for (int j = 0; j < numberOfObjects.y; j++) + { + spawnedObjects[i, j] = Object.Instantiate(prefab, GridToWorldSpace(i, j), Quaternion.identity).GetComponent<GridObject>(); + } + } + } +} diff --git a/GameCode/Gun.cs b/GameCode/Gun.cs new file mode 100644 index 0000000..36e8df2 --- /dev/null +++ b/GameCode/Gun.cs @@ -0,0 +1,698 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sirenix.OdinInspector; +using SoundImplementation; +using UnityEngine; + +public class Gun : Weapon +{ + [Header("Sound Player Settings")] + public SoundGun soundGun = new SoundGun(); + + [Header("Sound Card Settings")] + public SoundShotModifier soundShotModifier; + + public SoundImpactModifier soundImpactModifier; + + public bool soundDisableRayHitBulletSound; + + [Header("Settings")] + public float recoil; + + public float bodyRecoil; + + public float shake; + + public bool forceSpecificShake; + + public ProjectilesToSpawn[] projectiles; + + private Rigidbody2D rig; + + public Transform shootPosition; + + [HideInInspector] + public Player player; + + [HideInInspector] + public bool isReloading; + + [Header("Multiply")] + [FoldoutGroup("Stats", 0)] + public float damage = 1f; + + [FoldoutGroup("Stats", 0)] + public float reloadTime = 1f; + + [FoldoutGroup("Stats", 0)] + public float reloadTimeAdd; + + [FoldoutGroup("Stats", 0)] + public float recoilMuiltiplier = 1f; + + [FoldoutGroup("Stats", 0)] + public float knockback = 1f; + + [FoldoutGroup("Stats", 0)] + public float attackSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float projectileSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float projectielSimulatonSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float gravity = 1f; + + [FoldoutGroup("Stats", 0)] + public float damageAfterDistanceMultiplier = 1f; + + [FoldoutGroup("Stats", 0)] + public float bulletDamageMultiplier = 1f; + + [FoldoutGroup("Stats", 0)] + public float multiplySpread = 1f; + + [FoldoutGroup("Stats", 0)] + public float shakeM = 1f; + + [Header("Add")] + [FoldoutGroup("Stats", 0)] + public int ammo; + + [FoldoutGroup("Stats", 0)] + public float ammoReg; + + [FoldoutGroup("Stats", 0)] + public float size; + + [FoldoutGroup("Stats", 0)] + public float overheatMultiplier; + + [FoldoutGroup("Stats", 0)] + public float timeToReachFullMovementMultiplier; + + [FoldoutGroup("Stats", 0)] + public int numberOfProjectiles; + + [FoldoutGroup("Stats", 0)] + public int bursts; + + [FoldoutGroup("Stats", 0)] + public int reflects; + + [FoldoutGroup("Stats", 0)] + public int smartBounce; + + [FoldoutGroup("Stats", 0)] + public int bulletPortal; + + [FoldoutGroup("Stats", 0)] + public int randomBounces; + + [FoldoutGroup("Stats", 0)] + public float timeBetweenBullets; + + [FoldoutGroup("Stats", 0)] + public float projectileSize; + + [FoldoutGroup("Stats", 0)] + public float speedMOnBounce = 1f; + + [FoldoutGroup("Stats", 0)] + public float dmgMOnBounce = 1f; + + [FoldoutGroup("Stats", 0)] + public float drag; + + [FoldoutGroup("Stats", 0)] + public float dragMinSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float spread; + + [FoldoutGroup("Stats", 0)] + public float evenSpread; + + [FoldoutGroup("Stats", 0)] + public float percentageDamage; + + [FoldoutGroup("Stats", 0)] + public float cos; + + [FoldoutGroup("Stats", 0)] + public float slow; + + [FoldoutGroup("Stats", 0)] + [Header("Charge Multiply")] + public float chargeDamageMultiplier = 1f; + + [FoldoutGroup("Stats", 0)] + [Header("(1 + Charge * x) Multiply")] + public float chargeSpreadTo; + + [FoldoutGroup("Stats", 0)] + public float chargeEvenSpreadTo; + + [FoldoutGroup("Stats", 0)] + public float chargeSpeedTo; + + [FoldoutGroup("Stats", 0)] + public float chargeRecoilTo; + + [FoldoutGroup("Stats", 0)] + [Header("(1 + Charge * x) Add")] + public float chargeNumberOfProjectilesTo; + + [FoldoutGroup("Stats", 0)] + [Header("Special")] + public float destroyBulletAfter; + + [FoldoutGroup("Stats", 0)] + public float forceSpecificAttackSpeed; + + [FoldoutGroup("Stats", 0)] + public bool lockGunToDefault; + + [FoldoutGroup("Stats", 0)] + public bool unblockable; + + [FoldoutGroup("Stats", 0)] + public bool ignoreWalls; + + [HideInInspector] + public float currentCharge; + + public bool useCharge; + + public bool dontAllowAutoFire; + + public ObjectsToSpawn[] objectsToSpawn; + + public Color projectileColor = Color.black; + + public bool waveMovement; + + public bool teleport; + + public bool spawnSkelletonSquare; + + public float explodeNearEnemyRange; + + public float explodeNearEnemyDamage; + + public float hitMovementMultiplier = 1f; + + private Action attackAction; + + [HideInInspector] + public bool isProjectileGun; + + [HideInInspector] + public float defaultCooldown = 1f; + + [HideInInspector] + public int attackID = -1; + + public float attackSpeedMultiplier = 1f; + + private int gunID = -1; + + private GunAmmo gunAmmo; + + private Vector3 spawnPos; + + public Action<GameObject> ShootPojectileAction; + + private float spreadOfLastBullet; + + private SpawnedAttack spawnedAttack; + + [HideInInspector] + internal Vector3 forceShootDir; + + private float usedCooldown + { + get + { + if (!lockGunToDefault) + { + return attackSpeed; + } + return defaultCooldown; + } + } + + internal float GetRangeCompensation(float distance) + { + return Mathf.Pow(distance, 2f) * 0.015f / projectileSpeed; + } + + internal void ResetStats() + { + isReloading = false; + damage = 1f; + reloadTime = 1f; + reloadTimeAdd = 0f; + recoilMuiltiplier = 1f; + gunAmmo.reloadTimeMultiplier = 1f; + gunAmmo.reloadTimeAdd = 0f; + knockback = 1f; + attackSpeed = 0.3f; + projectileSpeed = 1f; + projectielSimulatonSpeed = 1f; + gravity = 1f; + damageAfterDistanceMultiplier = 1f; + bulletDamageMultiplier = 1f; + multiplySpread = 1f; + shakeM = 1f; + ammo = 0; + ammoReg = 0f; + size = 0f; + overheatMultiplier = 0f; + timeToReachFullMovementMultiplier = 0f; + numberOfProjectiles = 1; + bursts = 0; + reflects = 0; + smartBounce = 0; + bulletPortal = 0; + randomBounces = 0; + timeBetweenBullets = 0f; + projectileSize = 0f; + speedMOnBounce = 1f; + dmgMOnBounce = 1f; + drag = 0f; + dragMinSpeed = 1f; + spread = 0f; + evenSpread = 0f; + percentageDamage = 0f; + cos = 0f; + slow = 0f; + chargeNumberOfProjectilesTo = 0f; + destroyBulletAfter = 0f; + forceSpecificAttackSpeed = 0f; + lockGunToDefault = false; + unblockable = false; + ignoreWalls = false; + currentCharge = 0f; + useCharge = false; + waveMovement = false; + teleport = false; + spawnSkelletonSquare = false; + explodeNearEnemyRange = 0f; + explodeNearEnemyDamage = 0f; + hitMovementMultiplier = 1f; + isProjectileGun = false; + defaultCooldown = 1f; + attackSpeedMultiplier = 1f; + objectsToSpawn = new ObjectsToSpawn[0]; + GetComponentInChildren<GunAmmo>().maxAmmo = 3; + GetComponentInChildren<GunAmmo>().ReDrawTotalBullets(); + projectileColor = Color.black; + } + + private void Start() + { + gunAmmo = GetComponentInChildren<GunAmmo>(); + Gun[] componentsInChildren = base.transform.root.GetComponentsInChildren<Gun>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i] == this) + { + gunID = i; + } + } + if (!player) + { + player = GetComponentInParent<Player>(); + } + if (!player) + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + if ((bool)componentInParent) + { + player = componentInParent.ownPlayer; + } + } + if (!player) + { + SpawnedAttack component = base.transform.root.GetComponent<SpawnedAttack>(); + if ((bool)component) + { + player = component.spawner; + } + } + holdable = GetComponent<Holdable>(); + defaultCooldown = usedCooldown; + ShootPos componentInChildren = GetComponentInChildren<ShootPos>(); + if ((bool)componentInChildren) + { + shootPosition = componentInChildren.transform; + } + else + { + shootPosition = base.transform; + } + rig = GetComponent<Rigidbody2D>(); + soundGun.SetGun(this); + soundGun.SetGunTransform(base.transform); + soundGun.RefreshSoundModifiers(); + } + + private void Update() + { + if ((bool)holdable && (bool)holdable.holder && (bool)holdable.holder.player) + { + player = holdable.holder.player; + } + sinceAttack += TimeHandler.deltaTime * attackSpeedMultiplier; + if (!GameManager.instance.battleOngoing || (player != null && (!player.data.isPlaying || player.data.dead))) + { + soundGun.StopAutoPlayTail(); + } + } + + private void OnDestroy() + { + soundGun.StopAutoPlayTail(); + } + + public bool IsReady(float readuIn = 0f) + { + return sinceAttack + readuIn * attackSpeedMultiplier > usedCooldown; + } + + public float ReadyAmount() + { + return sinceAttack / usedCooldown; + } + + public override bool Attack(float charge, bool forceAttack = false, float damageM = 1f, float recoilM = 1f, bool useAmmo = true) + { + if (sinceAttack < usedCooldown && !forceAttack) + { + return false; + } + if (isReloading && !forceAttack) + { + return false; + } + sinceAttack = 0f; + int attacks = Mathf.Clamp(Mathf.RoundToInt(0.5f * charge / attackSpeed), 1, 10); + if (lockGunToDefault) + { + attacks = 1; + } + StartCoroutine(DoAttacks(charge, forceAttack, damageM, attacks, recoilM, useAmmo)); + return true; + } + + private IEnumerator DoAttacks(float charge, bool forceAttack = false, float damageM = 1f, int attacks = 1, float recoilM = 1f, bool useAmmo = true) + { + for (int i = 0; i < attacks; i++) + { + DoAttack(charge, forceAttack, damageM, recoilM, useAmmo); + yield return new WaitForSeconds(0.3f / (float)attacks); + } + } + + private void DoAttack(float charge, bool forceAttack = false, float damageM = 1f, float recoilM = 1f, bool useAmmo = true) + { + float num = 1f * (1f + charge * chargeRecoilTo) * recoilM; + if ((bool)rig) + { + rig.AddForce(rig.mass * recoil * Mathf.Clamp(usedCooldown, 0f, 1f) * -base.transform.up, ForceMode2D.Impulse); + } + _ = (bool)holdable; + if (attackAction != null) + { + attackAction(); + } + StartCoroutine(FireBurst(charge, forceAttack, damageM, recoilM, useAmmo)); + } + + private bool CheckIsMine() + { + bool result = false; + if ((bool)holdable && (bool)holdable.holder) + { + result = holdable.holder.player.data.view.IsMine; + } + else + { + Player componentInParent = GetComponentInParent<Player>(); + if ((bool)componentInParent) + { + result = componentInParent.data.view.IsMine; + } + } + return result; + } + + private IEnumerator FireBurst(float charge, bool forceAttack = false, float damageM = 1f, float recoilM = 1f, bool useAmmo = true) + { + int currentNumberOfProjectiles = (lockGunToDefault ? 1 : (numberOfProjectiles + Mathf.RoundToInt(chargeNumberOfProjectilesTo * charge))); + if (!lockGunToDefault) + { + _ = currentNumberOfProjectiles; + } + if (timeBetweenBullets == 0f) + { + GamefeelManager.GameFeel(base.transform.up * shake); + soundGun.PlayShot(currentNumberOfProjectiles); + } + for (int ii = 0; ii < Mathf.Clamp(bursts, 1, 100); ii++) + { + for (int i = 0; i < projectiles.Length; i++) + { + for (int j = 0; j < currentNumberOfProjectiles; j++) + { + if (CheckIsMine()) + { + spawnPos = base.transform.position; + if ((bool)player) + { + player.GetComponent<PlayerAudioModifyers>().SetStacks(); + if ((bool)holdable) + { + spawnPos = player.transform.position; + } + } + GameObject gameObject = PhotonNetwork.Instantiate(projectiles[i].objectToSpawn.gameObject.name, spawnPos, getShootRotation(j, currentNumberOfProjectiles, charge), 0); + if ((bool)holdable) + { + if (useAmmo) + { + if (PhotonNetwork.OfflineMode) + { + gameObject.GetComponent<ProjectileInit>().OFFLINE_Init(holdable.holder.player.playerID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + else + { + gameObject.GetComponent<PhotonView>().RPC("RPCA_Init", RpcTarget.All, holdable.holder.view.OwnerActorNr, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + } + else if (PhotonNetwork.OfflineMode) + { + gameObject.GetComponent<ProjectileInit>().OFFLINE_Init_noAmmoUse(holdable.holder.player.playerID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + else + { + gameObject.GetComponent<PhotonView>().RPC("RPCA_Init_noAmmoUse", RpcTarget.All, holdable.holder.view.OwnerActorNr, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + } + else if (PhotonNetwork.OfflineMode) + { + gameObject.GetComponent<ProjectileInit>().OFFLINE_Init_SeparateGun(GetComponentInParent<Player>().playerID, gunID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + else + { + gameObject.GetComponent<PhotonView>().RPC("RPCA_Init_SeparateGun", RpcTarget.All, GetComponentInParent<CharacterData>().view.OwnerActorNr, gunID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + } + if (timeBetweenBullets != 0f) + { + GamefeelManager.GameFeel(base.transform.up * shake); + soundGun.PlayShot(currentNumberOfProjectiles); + } + } + } + if (bursts > 1 && ii + 1 == Mathf.Clamp(bursts, 1, 100)) + { + soundGun.StopAutoPlayTail(); + } + if (timeBetweenBullets > 0f) + { + yield return new WaitForSeconds(timeBetweenBullets); + } + } + } + + public void BulletInit(GameObject bullet, int usedNumberOfProjectiles, float damageM, float randomSeed, bool useAmmo = true) + { + spawnedAttack = bullet.GetComponent<SpawnedAttack>(); + if (!spawnedAttack) + { + spawnedAttack = bullet.AddComponent<SpawnedAttack>(); + } + if (!bullet.GetComponentInChildren<DontChangeMe>()) + { + ApplyProjectileStats(bullet, usedNumberOfProjectiles, damageM, randomSeed); + } + if (soundDisableRayHitBulletSound) + { + RayHitBulletSound component = bullet.GetComponent<RayHitBulletSound>(); + if (component != null) + { + component.disableImpact = true; + } + } + ApplyPlayerStuff(bullet); + if (ShootPojectileAction != null) + { + ShootPojectileAction(bullet); + } + if (useAmmo && (bool)gunAmmo) + { + gunAmmo.Shoot(bullet); + } + } + + private Quaternion getShootRotation(int bulletID, int numOfProj, float charge) + { + Vector3 forward = shootPosition.forward; + if (forceShootDir != Vector3.zero) + { + forward = forceShootDir; + } + float num = multiplySpread * Mathf.Clamp(1f + charge * chargeSpreadTo, 0f, float.PositiveInfinity); + float num2 = UnityEngine.Random.Range(0f - spread, spread); + num2 /= (1f + projectileSpeed * 0.5f) * 0.5f; + forward += Vector3.Cross(forward, Vector3.forward) * num2 * num; + return Quaternion.LookRotation(lockGunToDefault ? shootPosition.forward : forward); + } + + private void ApplyPlayerStuff(GameObject obj) + { + ProjectileHit component = obj.GetComponent<ProjectileHit>(); + component.ownWeapon = base.gameObject; + if ((bool)player) + { + component.ownPlayer = player; + } + spawnedAttack.spawner = player; + spawnedAttack.attackID = attackID; + } + + private void ApplyProjectileStats(GameObject obj, int numOfProj = 1, float damageM = 1f, float randomSeed = 0f) + { + ProjectileHit component = obj.GetComponent<ProjectileHit>(); + component.dealDamageMultiplierr *= bulletDamageMultiplier; + component.damage *= damage * damageM; + component.percentageDamage = percentageDamage; + component.stun = component.damage / 150f; + component.force *= knockback; + component.movementSlow = slow; + component.hasControl = CheckIsMine(); + component.projectileColor = projectileColor; + component.unblockable = unblockable; + RayCastTrail component2 = obj.GetComponent<RayCastTrail>(); + if (ignoreWalls) + { + component2.mask = component2.ignoreWallsMask; + } + if ((bool)component2) + { + component2.extraSize += size; + } + if ((bool)player) + { + PlayerSkin teamColor = (component.team = PlayerSkinBank.GetPlayerSkinColors(player.playerID)); + obj.GetComponent<RayCastTrail>().teamID = player.playerID; + SetTeamColor.TeamColorThis(obj, teamColor); + } + List<ObjectsToSpawn> list = new List<ObjectsToSpawn>(); + for (int i = 0; i < objectsToSpawn.Length; i++) + { + list.Add(objectsToSpawn[i]); + if (!objectsToSpawn[i].AddToProjectile || ((bool)objectsToSpawn[i].AddToProjectile.gameObject.GetComponent<StopRecursion>() && isProjectileGun)) + { + continue; + } + GameObject gameObject = UnityEngine.Object.Instantiate(objectsToSpawn[i].AddToProjectile, component.transform.position, component.transform.rotation, component.transform); + gameObject.transform.localScale *= 1f * (1f - objectsToSpawn[i].scaleFromDamage) + component.damage / 55f * objectsToSpawn[i].scaleFromDamage; + if (objectsToSpawn[i].scaleStacks) + { + gameObject.transform.localScale *= 1f + (float)objectsToSpawn[i].stacks * objectsToSpawn[i].scaleStackM; + } + if (!objectsToSpawn[i].removeScriptsFromProjectileObject) + { + continue; + } + MonoBehaviour[] componentsInChildren = gameObject.GetComponentsInChildren<MonoBehaviour>(); + for (int j = 0; j < componentsInChildren.Length; j++) + { + if (componentsInChildren[j].GetType().ToString() != "SoundImplementation.SoundUnityEventPlayer") + { + UnityEngine.Object.Destroy(componentsInChildren[j]); + } + Debug.Log(componentsInChildren[j].GetType().ToString()); + } + } + component.objectsToSpawn = list.ToArray(); + if (reflects > 0) + { + RayHitReflect rayHitReflect = obj.gameObject.AddComponent<RayHitReflect>(); + rayHitReflect.reflects = reflects; + rayHitReflect.speedM = speedMOnBounce; + rayHitReflect.dmgM = dmgMOnBounce; + } + if (!forceSpecificShake) + { + float num = component.damage / 100f * ((1f + usedCooldown) / 2f) / ((1f + (float)numOfProj) / 2f) * 2f; + float num2 = Mathf.Clamp((0.2f + component.damage * (((float)numberOfProjectiles + 2f) / 2f) / 100f * ((1f + usedCooldown) / 2f)) * 1f, 0f, 3f); + component.shake = num * shakeM; + shake = num2; + } + MoveTransform component3 = obj.GetComponent<MoveTransform>(); + component3.localForce *= projectileSpeed; + component3.simulationSpeed *= projectielSimulatonSpeed; + component3.gravity *= gravity; + component3.worldForce *= gravity; + component3.drag = drag; + component3.drag = Mathf.Clamp(component3.drag, 0f, 45f); + component3.velocitySpread = Mathf.Clamp(spread * 50f, 0f, 50f); + component3.dragMinSpeed = dragMinSpeed; + component3.localForce *= Mathf.Lerp(1f - component3.velocitySpread * 0.01f, 1f + component3.velocitySpread * 0.01f, randomSeed); + component3.selectedSpread = 0f; + if (damageAfterDistanceMultiplier != 1f) + { + obj.AddComponent<ChangeDamageMultiplierAfterDistanceTravelled>().muiltiplier = damageAfterDistanceMultiplier; + } + if (cos > 0f) + { + obj.gameObject.AddComponent<Cos>().multiplier = cos; + } + if (destroyBulletAfter != 0f) + { + obj.GetComponent<RemoveAfterSeconds>().seconds = destroyBulletAfter; + } + if ((bool)spawnedAttack && projectileColor != Color.black) + { + spawnedAttack.SetColor(projectileColor); + } + } + + public void AddAttackAction(Action action) + { + attackAction = (Action)Delegate.Combine(attackAction, action); + } + + internal void RemoveAttackAction(Action action) + { + attackAction = (Action)Delegate.Remove(attackAction, action); + } +} diff --git a/GameCode/GunAmmo.cs b/GameCode/GunAmmo.cs new file mode 100644 index 0000000..102b4d4 --- /dev/null +++ b/GameCode/GunAmmo.cs @@ -0,0 +1,212 @@ +using Sonigon; +using UnityEngine; +using UnityEngine.UI; + +public class GunAmmo : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundReloadInProgressLoop; + + public SoundEvent soundReloadComplete; + + private SoundParameterIntensity soundReloadInProgressIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + private bool soundReloadInProgressPlaying; + + private float soundReloadTime; + + [Header("Settings")] + public int maxAmmo = 3; + + private int lastMaxAmmo; + + private int currentAmmo; + + public float reloadTime = 1.5f; + + public float reloadTimeMultiplier = 1f; + + public float reloadTimeAdd; + + private Gun gun; + + public CurveAnimation reloadAnim; + + private Image reloadRing; + + public Image cooldownRing; + + private float reloadCounter; + + private float freeReloadCounter; + + public Populate populate; + + public float ammoReg; + + private float currentRegCounter; + + private void Start() + { + reloadRing = reloadAnim.GetComponent<Image>(); + lastMaxAmmo = maxAmmo; + currentAmmo = maxAmmo; + gun = GetComponentInParent<Gun>(); + ReDrawTotalBullets(); + } + + private void OnDisable() + { + SoundStopReloadInProgress(); + } + + private void OnDestroy() + { + SoundStopReloadInProgress(); + } + + private void SoundStopReloadInProgress() + { + if (soundReloadInProgressPlaying) + { + soundReloadInProgressPlaying = false; + SoundManager.Instance.Stop(soundReloadInProgressLoop, base.transform); + } + } + + private float ReloadTime() + { + return (reloadTime + reloadTimeAdd) * reloadTimeMultiplier; + } + + private void Update() + { + if (!gun.isReloading) + { + SoundStopReloadInProgress(); + } + if (gun.isReloading) + { + reloadCounter -= TimeHandler.deltaTime; + if (!soundReloadInProgressPlaying) + { + soundReloadInProgressPlaying = true; + soundReloadTime = ReloadTime(); + soundReloadInProgressIntensity.intensity = 0f; + SoundManager.Instance.Play(soundReloadInProgressLoop, base.transform, soundReloadInProgressIntensity); + } + if (soundReloadInProgressPlaying && soundReloadTime > 0f) + { + soundReloadInProgressIntensity.intensity = 1f - reloadCounter / soundReloadTime; + } + if (reloadCounter < 0f) + { + ReloadAmmo(); + } + } + else if (currentAmmo != maxAmmo) + { + freeReloadCounter += TimeHandler.deltaTime; + if (freeReloadCounter > ReloadTime() && gun.player.data.stats.automaticReload) + { + currentAmmo = maxAmmo; + SetActiveBullets(); + } + currentRegCounter += ammoReg * TimeHandler.deltaTime * (float)maxAmmo; + if (currentRegCounter > 1f) + { + currentAmmo++; + currentRegCounter = 0f; + SetActiveBullets(); + } + } + if (currentAmmo <= 0) + { + if (reloadAnim.currentState != 0) + { + reloadAnim.PlayIn(); + } + } + else if (reloadAnim.currentState != CurveAnimationUse.Out) + { + reloadAnim.PlayOut(); + } + reloadRing.fillAmount = (ReloadTime() - reloadCounter) / ReloadTime(); + if (gun.attackSpeed > 0.4f) + { + cooldownRing.fillAmount = gun.ReadyAmount(); + if (gun.ReadyAmount() >= 1f) + { + cooldownRing.fillAmount = 0f; + } + } + else + { + cooldownRing.fillAmount = 0f; + } + if (maxAmmo != lastMaxAmmo) + { + ReDrawTotalBullets(); + } + lastMaxAmmo = maxAmmo; + } + + public void ReloadAmmo(bool playSound = true) + { + gun.player.data.stats.OnReload(maxAmmo - currentAmmo); + gun.isReloading = false; + currentAmmo = maxAmmo; + SoundStopReloadInProgress(); + if (playSound) + { + SoundManager.Instance.Play(soundReloadComplete, base.transform); + } + SetActiveBullets(); + } + + public void Shoot(GameObject projectile) + { + currentAmmo--; + freeReloadCounter = 0f; + SetActiveBullets(); + if (currentAmmo <= 0) + { + reloadCounter = ReloadTime(); + gun.isReloading = true; + gun.player.data.stats.OnOutOfAmmp(maxAmmo); + } + } + + public void ReDrawTotalBullets() + { + currentAmmo = maxAmmo; + for (int num = populate.transform.childCount - 1; num >= 0; num--) + { + if (populate.transform.GetChild(num).gameObject.activeSelf) + { + Object.Destroy(populate.transform.GetChild(num).gameObject); + } + } + populate.times = maxAmmo; + populate.DoPopulate(); + SetActiveBullets(forceTurnOn: true); + } + + private void SetActiveBullets(bool forceTurnOn = false) + { + for (int i = 1; i < populate.transform.childCount; i++) + { + if (i <= currentAmmo || forceTurnOn) + { + if (populate.transform.GetChild(i).GetComponent<CurveAnimation>().currentState != CurveAnimationUse.In || forceTurnOn) + { + populate.transform.GetChild(i).GetComponent<CurveAnimation>().PlayIn(); + } + } + else if (populate.transform.GetChild(i).GetComponent<CurveAnimation>().currentState != CurveAnimationUse.Out) + { + populate.transform.GetChild(i).GetComponent<CurveAnimation>().PlayOut(); + } + } + } +} diff --git a/GameCode/GunLevel.cs b/GameCode/GunLevel.cs new file mode 100644 index 0000000..427e442 --- /dev/null +++ b/GameCode/GunLevel.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +public class GunLevel : MonoBehaviour +{ + public Gun copyTo; + + private Gun copyFrom; + + private void Start() + { + copyFrom = GetComponent<Gun>(); + AttackLevel componentInParent = GetComponentInParent<AttackLevel>(); + componentInParent.LevelUpAction = (Action<int>)Delegate.Combine(componentInParent.LevelUpAction, new Action<int>(BuffGun)); + } + + public void BuffGun(int level) + { + ApplyCardStats.CopyGunStats(copyFrom, copyTo); + } +} diff --git a/GameCode/HandPos.cs b/GameCode/HandPos.cs new file mode 100644 index 0000000..a0e6af6 --- /dev/null +++ b/GameCode/HandPos.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class HandPos : MonoBehaviour +{ +} diff --git a/GameCode/HasToReturn.cs b/GameCode/HasToReturn.cs new file mode 100644 index 0000000..4cf01d8 --- /dev/null +++ b/GameCode/HasToReturn.cs @@ -0,0 +1,6 @@ +public enum HasToReturn +{ + hasToReturn, + canContinue, + hasToReturnNow +} diff --git a/GameCode/HealthBar.cs b/GameCode/HealthBar.cs new file mode 100644 index 0000000..98e08ec --- /dev/null +++ b/GameCode/HealthBar.cs @@ -0,0 +1,58 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +public class HealthBar : MonoBehaviour +{ + public Image hp; + + public Image white; + + private float drag = 25f; + + private float spring = 25f; + + private float hpCur; + + private float hpVel; + + private float hpTarg; + + private float whiteCur; + + private float whiteVel; + + private float whiteTarg; + + private float sinceDamage; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + CharacterStatModifiers componentInParent = GetComponentInParent<CharacterStatModifiers>(); + componentInParent.WasDealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(componentInParent.WasDealtDamageAction, new Action<Vector2, bool>(TakeDamage)); + } + + private void Update() + { + hpTarg = data.health / data.maxHealth; + sinceDamage += TimeHandler.deltaTime; + hpVel = FRILerp.Lerp(hpVel, (hpTarg - hpCur) * spring, drag); + whiteVel = FRILerp.Lerp(whiteVel, (whiteTarg - whiteCur) * spring, drag); + hpCur += hpVel * TimeHandler.deltaTime; + whiteCur += whiteVel * TimeHandler.deltaTime; + hp.fillAmount = hpCur; + white.fillAmount = whiteCur; + if (sinceDamage > 0.5f) + { + whiteTarg = hpTarg; + } + } + + public void TakeDamage(Vector2 dmg, bool selfDmg) + { + sinceDamage = 0f; + } +} diff --git a/GameCode/HealthHandler.cs b/GameCode/HealthHandler.cs new file mode 100644 index 0000000..bbc739f --- /dev/null +++ b/GameCode/HealthHandler.cs @@ -0,0 +1,362 @@ +using System; +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class HealthHandler : Damagable +{ + [Header("Sounds")] + public SoundEvent soundDie; + + public SoundEvent soundHeal; + + public SoundEvent soundDamagePassive; + + public SoundEvent soundDamageLifeSteal; + + public SoundEvent soundBounce; + + [Header("Settings")] + public SpriteRenderer hpSprite; + + public GameObject deathEffect; + + public float regeneration; + + private CharacterData data; + + private CodeAnimation anim; + + private Player player; + + private CharacterStatModifiers stats; + + public ParticleSystem healPart; + + private DamageOverTime dot; + + private Vector3 startHealthSpriteScale; + + public float flyingFor; + + private float lastDamaged; + + public Action delayedReviveAction; + + public Action reviveAction; + + [HideInInspector] + public bool DestroyOnDeath; + + public bool isRespawning; + + public GameObject deathEffectPhoenix; + + private void Awake() + { + dot = GetComponent<DamageOverTime>(); + data = GetComponent<CharacterData>(); + anim = GetComponentInChildren<CodeAnimation>(); + player = GetComponent<Player>(); + stats = GetComponent<CharacterStatModifiers>(); + } + + private void Start() + { + startHealthSpriteScale = hpSprite.transform.localScale; + } + + private void Update() + { + flyingFor -= TimeHandler.deltaTime; + if (regeneration > 0f) + { + Heal(regeneration * TimeHandler.deltaTime); + } + } + + public void Heal(float healAmount) + { + if (healAmount != 0f && data.health != data.maxHealth) + { + SoundManager.Instance.Play(soundHeal, base.transform); + data.health += healAmount; + data.health = Mathf.Clamp(data.health, float.NegativeInfinity, data.maxHealth); + healPart.Emit((int)Mathf.Clamp(healAmount * 0.2f, 1f, 10f)); + } + } + + public void CallTakeForce(Vector2 force, ForceMode2D forceMode = ForceMode2D.Impulse, bool forceIgnoreMass = false, bool ignoreBlock = false, float setFlying = 0f) + { + if (data.isPlaying && (!data.block.IsBlocking() || ignoreBlock)) + { + data.view.RPC("RPCA_SendTakeForce", RpcTarget.All, force, (int)forceMode, forceIgnoreMass, true, setFlying); + } + } + + [PunRPC] + public void RPCA_SendTakeForce(Vector2 force, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false, float setFlying = 0f) + { + TakeForce(force, (ForceMode2D)forceMode, forceIgnoreMass, ignoreBlock, setFlying); + data.GetComponent<SyncPlayerMovement>().SetDontSyncFor((float)PhotonNetwork.GetPing() * 0.001f + 0.2f); + } + + [PunRPC] + public void RPCA_SendForceOverTime(Vector2 force, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + StartCoroutine(IForceOverTime(force, time, forceMode, forceIgnoreMass, ignoreBlock)); + } + + private IEnumerator IForceOverTime(Vector2 force, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + for (float i = 0f; i < time; i += TimeHandler.deltaTime) + { + TakeForce(force, (ForceMode2D)forceMode, forceIgnoreMass, ignoreBlock); + data.GetComponent<SyncPlayerMovement>().SetDontSyncFor((float)PhotonNetwork.GetPing() * 0.001f + 0.2f); + yield return new WaitForFixedUpdate(); + } + } + + [PunRPC] + public void RPCA_SendForceTowardsPointOverTime(float force, float drag, float clampDistancce, Vector2 point, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + StartCoroutine(IForceTowardsPointOverTime(force, drag, clampDistancce, point, time, forceMode, forceIgnoreMass, ignoreBlock)); + } + + private IEnumerator IForceTowardsPointOverTime(float force, float drag, float clampDistancce, Vector2 point, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + for (float i = 0f; i < time; i += TimeHandler.fixedDeltaTime) + { + Vector2 vector = point - (Vector2)base.transform.position; + vector = Vector2.ClampMagnitude(vector, clampDistancce); + Vector2 vector2 = data.playerVel.velocity * (0f - drag) * TimeHandler.fixedDeltaTime; + TakeForce(force * vector + vector2 * drag * TimeHandler.timeScale, (ForceMode2D)forceMode, forceIgnoreMass, ignoreBlock); + data.GetComponent<SyncPlayerMovement>().SetDontSyncFor((float)PhotonNetwork.GetPing() * 0.001f + 0.2f); + yield return new WaitForFixedUpdate(); + } + } + + public void TakeForce(Vector2 force, ForceMode2D forceMode = ForceMode2D.Impulse, bool forceIgnoreMass = false, bool ignoreBlock = false, float setFlying = 0f) + { + if (!data.isPlaying || !data.playerVel.simulated) + { + return; + } + bool flag = data.block.IsBlocking(); + if (flag && !ignoreBlock) + { + return; + } + if (!flag) + { + if (setFlying > flyingFor && setFlying > 0.25f) + { + flyingFor = setFlying; + SoundManager.Instance.Play(soundBounce, base.transform); + } + } + if (forceIgnoreMass) + { + force *= data.playerVel.mass / 100f; + } + data.playerVel.AddForce(force, forceMode); + if (force.y > 0f) + { + if (!forceIgnoreMass) + { + force.y /= data.playerVel.mass / 100f; + } + if (forceMode == ForceMode2D.Force) + { + force *= 0.003f; + } + data.sinceGrounded -= force.y * 0.003f; + } + data.sinceGrounded = Mathf.Clamp(data.sinceGrounded, -0.5f, 100f); + } + + public override void CallTakeDamage(Vector2 damage, Vector2 position, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + if (!(damage == Vector2.zero) && !data.block.IsBlocking()) + { + data.view.RPC("RPCA_SendTakeDamage", RpcTarget.All, damage, position, lethal, (damagingPlayer != null) ? damagingPlayer.playerID : (-1)); + } + } + + [PunRPC] + public void RPCA_SendTakeDamage(Vector2 damage, Vector2 position, bool lethal = true, int playerID = -1) + { + if (!(damage == Vector2.zero)) + { + Player playerWithID = PlayerManager.instance.GetPlayerWithID(playerID); + GameObject damagingWeapon = null; + if ((bool)playerWithID) + { + damagingWeapon = playerWithID.data.weaponHandler.gun.gameObject; + } + TakeDamage(damage, position, damagingWeapon, playerWithID, lethal, ignoreBlock: true); + } + } + + public override void TakeDamage(Vector2 damage, Vector2 position, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (!(damage == Vector2.zero)) + { + TakeDamage(damage, position, Color.white * 0.85f, damagingWeapon, damagingPlayer, lethal, ignoreBlock); + } + } + + public override void TakeDamage(Vector2 damage, Vector2 position, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (!(damage == Vector2.zero) && data.isPlaying && data.playerVel.simulated && !data.dead && (!data.block.IsBlocking() || ignoreBlock)) + { + if (dmgColor == Color.black) + { + dmgColor = Color.white * 0.85f; + } + if (stats.secondsToTakeDamageOver == 0f) + { + DoDamage(damage, position, dmgColor, damagingWeapon, damagingPlayer, healthRemoval: false, lethal, ignoreBlock); + } + else + { + TakeDamageOverTime(damage, position, stats.secondsToTakeDamageOver, 0.25f, dmgColor, damagingWeapon, damagingPlayer, lethal); + } + } + } + + public void DoDamage(Vector2 damage, Vector2 position, Color blinkColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool healthRemoval = false, bool lethal = true, bool ignoreBlock = false) + { + if (damage == Vector2.zero || !data.isPlaying || data.dead || (data.block.IsBlocking() && !ignoreBlock) || isRespawning) + { + return; + } + if ((bool)damagingPlayer) + { + damagingPlayer.GetComponent<CharacterStatModifiers>().DealtDamage(damage, damagingPlayer != null && damagingPlayer.transform.root == base.transform, data.player); + } + StopAllCoroutines(); + DisplayDamage(blinkColor); + data.lastSourceOfDamage = damagingPlayer; + data.health -= damage.magnitude; + stats.WasDealtDamage(damage, damagingPlayer != null && damagingPlayer.transform.root == base.transform); + if (!lethal) + { + data.health = Mathf.Clamp(data.health, 1f, data.maxHealth); + } + if (data.health < 0f && !data.dead) + { + if (data.stats.remainingRespawns > 0) + { + data.view.RPC("RPCA_Die_Phoenix", RpcTarget.All, damage); + } + else + { + data.view.RPC("RPCA_Die", RpcTarget.All, damage); + } + } + if (lastDamaged + 0.15f < Time.time && damagingPlayer != null && damagingPlayer.data.stats.lifeSteal != 0f) + { + SoundManager.Instance.Play(soundDamageLifeSteal, base.transform); + } + lastDamaged = Time.time; + } + + public void TakeDamageOverTime(Vector2 damage, Vector2 position, float time, float interval, Color color, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + dot.TakeDamageOverTime(damage, position, time, interval, color, soundDamagePassive, damagingWeapon, damagingPlayer, lethal); + } + + private void DisplayDamage(Color blinkColor) + { + GetComponentInChildren<PlayerSkinHandler>().BlinkColor(blinkColor); + } + + private IEnumerator DelayReviveAction() + { + yield return new WaitForSecondsRealtime(2f); + delayedReviveAction?.Invoke(); + } + + public void Revive(bool isFullRevive = true) + { + reviveAction?.Invoke(); + if (base.gameObject.activeInHierarchy) + { + StartCoroutine(DelayReviveAction()); + } + flyingFor = 0f; + if (isFullRevive) + { + data.stats.remainingRespawns = data.stats.respawns; + } + data.healthHandler.isRespawning = false; + data.health = data.maxHealth; + data.playerVel.velocity = Vector2.zero; + data.playerVel.angularVelocity = 0f; + data.stunTime = 0f; + data.block.ResetCD(soundPlay: false); + data.weaponHandler.gun.GetComponentInChildren<GunAmmo>().ReloadAmmo(playSound: false); + data.GetComponent<PlayerCollision>().IgnoreWallForFrames(5); + base.gameObject.SetActive(value: true); + if ((bool)deathEffect && data.dead) + { + anim.PlayIn(); + } + data.dead = false; + hpSprite.color = PlayerSkinBank.GetPlayerSkinColors(player.playerID).color; + data.stunHandler.StopStun(); + data.silenceHandler.StopSilence(); + GetComponent<CharacterStatModifiers>().slow = 0f; + GetComponent<CharacterStatModifiers>().slowSlow = 0f; + GetComponent<CharacterStatModifiers>().fastSlow = 0f; + GetComponent<WeaponHandler>().isOverHeated = false; + GetComponent<Block>().sinceBlock = float.PositiveInfinity; + dot.StopAllCoroutines(); + } + + [PunRPC] + private void RPCA_Die(Vector2 deathDirection) + { + if (data.isPlaying && !data.dead) + { + SoundManager.Instance.Play(soundDie, base.transform); + data.dead = true; + if (!DestroyOnDeath) + { + base.gameObject.SetActive(value: false); + GamefeelManager.GameFeel(deathDirection.normalized * 3f); + UnityEngine.Object.Instantiate(deathEffect, base.transform.position, base.transform.rotation).GetComponent<DeathEffect>().PlayDeath(PlayerSkinBank.GetPlayerSkinColors(player.playerID).color, data.playerVel, deathDirection); + dot.StopAllCoroutines(); + data.stunHandler.StopStun(); + data.silenceHandler.StopSilence(); + PlayerManager.instance.PlayerDied(player); + } + else + { + UnityEngine.Object.Destroy(base.transform.root.gameObject); + } + } + } + + [PunRPC] + private void RPCA_Die_Phoenix(Vector2 deathDirection) + { + if (data.isPlaying && !data.dead) + { + data.stats.remainingRespawns--; + isRespawning = true; + SoundManager.Instance.Play(soundDie, base.transform); + if (!DestroyOnDeath) + { + base.gameObject.SetActive(value: false); + GamefeelManager.GameFeel(deathDirection.normalized * 3f); + UnityEngine.Object.Instantiate(deathEffectPhoenix, base.transform.position, base.transform.rotation).GetComponent<DeathEffect>().PlayDeath(PlayerSkinBank.GetPlayerSkinColors(player.playerID).color, data.playerVel, deathDirection, player.playerID); + dot.StopAllCoroutines(); + data.stunHandler.StopStun(); + data.silenceHandler.StopSilence(); + } + } + } +} diff --git a/GameCode/HitInfo.cs b/GameCode/HitInfo.cs new file mode 100644 index 0000000..782dce3 --- /dev/null +++ b/GameCode/HitInfo.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class HitInfo +{ + public Vector2 point; + + public Vector2 normal; + + public Collider2D collider; + + public Transform transform; + + public Rigidbody2D rigidbody; + + internal static HitInfo GetHitInfo(RaycastHit2D raycastHit2D) + { + return new HitInfo + { + point = raycastHit2D.point, + normal = raycastHit2D.normal, + transform = raycastHit2D.transform, + collider = raycastHit2D.collider, + rigidbody = raycastHit2D.rigidbody + }; + } +} diff --git a/GameCode/Holdable.cs b/GameCode/Holdable.cs new file mode 100644 index 0000000..c2329b5 --- /dev/null +++ b/GameCode/Holdable.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class Holdable : MonoBehaviour +{ + public Rigidbody2D rig; + + public CharacterData holder; + + private void Awake() + { + rig = GetComponent<Rigidbody2D>(); + } + + private void Start() + { + } + + public void SetTeamColors(PlayerSkin teamColor, Player player) + { + SetTeamColor.TeamColorThis(base.gameObject, teamColor); + } +} diff --git a/GameCode/Holding.cs b/GameCode/Holding.cs new file mode 100644 index 0000000..1f1839f --- /dev/null +++ b/GameCode/Holding.cs @@ -0,0 +1,75 @@ +using UnityEngine; + +public class Holding : MonoBehaviour +{ + public float force; + + public float drag; + + public Holdable holdable; + + private Transform handPos; + + private PlayerVelocity rig; + + private GeneralInput input; + + private CharacterData data; + + private Player player; + + private Gun gun; + + private bool hasSpawnedGun; + + public void Awake() + { + if (hasSpawnedGun) + { + Object.Destroy(holdable.gameObject); + } + hasSpawnedGun = true; + holdable = Object.Instantiate(holdable, base.transform.position, Quaternion.identity); + player = GetComponent<Player>(); + holdable.GetComponent<Holdable>().holder = player.data; + handPos = GetComponentInChildren<HandPos>().transform; + rig = GetComponent<PlayerVelocity>(); + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + if ((bool)holdable) + { + gun = holdable.GetComponent<Gun>(); + GetComponentInChildren<WeaponHandler>().gun = holdable.GetComponent<Gun>(); + } + } + + private void Start() + { + if ((bool)holdable) + { + holdable.SetTeamColors(PlayerSkinBank.GetPlayerSkinColors(player.playerID), player); + } + } + + private void FixedUpdate() + { + if ((bool)holdable && (bool)holdable.rig) + { + holdable.rig.AddForce((handPos.transform.position + (Vector3)rig.velocity * 0.04f - holdable.transform.position) * force * holdable.rig.mass, ForceMode2D.Force); + holdable.rig.AddForce(holdable.rig.velocity * (0f - drag) * holdable.rig.mass, ForceMode2D.Force); + holdable.rig.transform.rotation = Quaternion.LookRotation(Vector3.forward, handPos.transform.forward); + } + } + + private void Update() + { + } + + private void OnDestroy() + { + if ((bool)holdable) + { + Object.Destroy(holdable.gameObject); + } + } +} diff --git a/GameCode/HoldingObject.cs b/GameCode/HoldingObject.cs new file mode 100644 index 0000000..c06d79f --- /dev/null +++ b/GameCode/HoldingObject.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class HoldingObject : MonoBehaviour +{ + public Holding holder; + + private void Start() + { + } + + private void Update() + { + if (CardChoice.instance.IsPicking) + { + base.transform.position = Vector3.up * 10000f; + } + else if (Vector3.Distance(holder.transform.position, base.transform.position) > 100f) + { + base.transform.position = holder.transform.position; + } + } +} diff --git a/GameCode/Homing.cs b/GameCode/Homing.cs new file mode 100644 index 0000000..39a12c1 --- /dev/null +++ b/GameCode/Homing.cs @@ -0,0 +1,104 @@ +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class Homing : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundHomingFound; + + private bool soundHomingCanPlay = true; + + [Header("Settings")] + public float amount = 1f; + + public float scalingDrag = 1f; + + public float drag = 1f; + + public float spread = 1f; + + private MoveTransform move; + + private bool isOn; + + public RotSpring rot1; + + public RotSpring rot2; + + private FlickerEvent[] flicks; + + private PhotonView view; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + flicks = GetComponentsInChildren<FlickerEvent>(); + view = GetComponentInParent<PhotonView>(); + GetComponentInParent<SyncProjectile>().active = true; + } + + private void Update() + { + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true); + if ((bool)closestPlayer) + { + Vector3 vector = closestPlayer.transform.position + base.transform.right * move.selectedSpread * Vector3.Distance(base.transform.position, closestPlayer.transform.position) * spread; + float num = Vector3.Angle(base.transform.root.forward, vector - base.transform.position); + if (num < 70f) + { + move.velocity -= move.velocity * num * TimeHandler.deltaTime * scalingDrag; + move.velocity -= move.velocity * TimeHandler.deltaTime * drag; + move.velocity += Vector3.ClampMagnitude(vector - base.transform.position, 1f) * TimeHandler.deltaTime * move.localForce.magnitude * 0.025f * amount; + move.velocity.z = 0f; + move.velocity += Vector3.up * TimeHandler.deltaTime * move.gravity * move.multiplier; + if (!isOn) + { + move.simulateGravity++; + if (soundHomingCanPlay) + { + soundHomingCanPlay = false; + SoundManager.Instance.PlayAtPosition(soundHomingFound, SoundManager.Instance.GetTransform(), base.transform); + } + } + isOn = true; + for (int i = 0; i < flicks.Length; i++) + { + flicks[i].isOn = true; + } + rot1.target = 10f; + rot2.target = -10f; + } + else + { + if (isOn) + { + move.simulateGravity--; + soundHomingCanPlay = true; + } + isOn = false; + for (int j = 0; j < flicks.Length; j++) + { + flicks[j].isOn = false; + } + rot1.target = 50f; + rot2.target = -50f; + } + } + else + { + if (isOn) + { + move.simulateGravity--; + soundHomingCanPlay = true; + } + isOn = false; + for (int k = 0; k < flicks.Length; k++) + { + flicks[k].isOn = false; + } + rot1.target = 50f; + rot2.target = -50f; + } + } +} diff --git a/GameCode/HoverEvent.cs b/GameCode/HoverEvent.cs new file mode 100644 index 0000000..6e9f332 --- /dev/null +++ b/GameCode/HoverEvent.cs @@ -0,0 +1,38 @@ +using SoundImplementation; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.EventSystems; + +public class HoverEvent : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler +{ + public UnityEvent enterEvent; + + public UnityEvent exitEvent; + + public bool isHovered; + + public bool isSelected; + + public void OnPointerEnter(PointerEventData eventData) + { + SoundPlayerStatic.Instance.PlayButtonHover(); + enterEvent.Invoke(); + isHovered = true; + } + + public void OnPointerExit(PointerEventData eventData) + { + exitEvent.Invoke(); + isHovered = false; + } + + private void Update() + { + isSelected = EventSystem.current.currentSelectedGameObject == base.gameObject; + } + + private void OnDisable() + { + isHovered = false; + } +} diff --git a/GameCode/HoverEventColor.cs b/GameCode/HoverEventColor.cs new file mode 100644 index 0000000..d6fa9c3 --- /dev/null +++ b/GameCode/HoverEventColor.cs @@ -0,0 +1,32 @@ +using UnityEngine; +using UnityEngine.UI; + +public class HoverEventColor : MonoBehaviour +{ + public Color hoverColor; + + private Color defaultColor; + + private HoverEvent hover; + + private Image img; + + private void Start() + { + img = GetComponent<Image>(); + defaultColor = img.color; + hover = GetComponent<HoverEvent>(); + hover.enterEvent.AddListener(Enter); + hover.exitEvent.AddListener(Exit); + } + + private void Enter() + { + img.color = hoverColor; + } + + private void Exit() + { + img.color = defaultColor; + } +} diff --git a/GameCode/HoverEvent_WobbleButton.cs b/GameCode/HoverEvent_WobbleButton.cs new file mode 100644 index 0000000..83e6079 --- /dev/null +++ b/GameCode/HoverEvent_WobbleButton.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; + +public class HoverEvent_WobbleButton : MonoBehaviour +{ + public float min = 1f; + + public float max = 1.1f; + + public float spring = 1f; + + public float drag = 1f; + + public float force = -0.1f; + + private ScaleShake sh; + + private void Awake() + { + HoverEvent hoverEvent = base.gameObject.AddComponent<HoverEvent>(); + sh = base.gameObject.AddComponent<ScaleShake>(); + Button component = GetComponent<Button>(); + sh.spring = spring; + sh.drag = drag; + sh.multiplier = force; + sh.high = max; + sh.low = min; + sh.useTimeScale = false; + sh.SetTarget(min); + UnityEvent unityEvent = new UnityEvent(); + unityEvent.AddListener(sh.SetHigh); + hoverEvent.enterEvent = unityEvent; + UnityEvent unityEvent2 = new UnityEvent(); + unityEvent2.AddListener(sh.SetLow); + hoverEvent.exitEvent = unityEvent2; + component.onClick.AddListener(sh.AddForce); + } + + private void OnDisable() + { + base.transform.localScale = Vector3.one * min; + sh.SetTarget(min); + } +} diff --git a/GameCode/HoveredTooltip.cs b/GameCode/HoveredTooltip.cs new file mode 100644 index 0000000..4fa3cb7 --- /dev/null +++ b/GameCode/HoveredTooltip.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +public class HoveredTooltip : MonoBehaviour +{ + private CurveAnimation anim; + + private HoverEvent hoverEvent; + + private void Start() + { + anim = GetComponent<CurveAnimation>(); + hoverEvent = GetComponentInParent<HoverEvent>(); + } + + private void Update() + { + if (!anim.IsPlaying()) + { + if ((hoverEvent.isHovered || hoverEvent.isSelected) && anim.currentState != 0) + { + anim.PlayIn(); + } + if (!hoverEvent.isHovered && !hoverEvent.isSelected && anim.currentState != CurveAnimationUse.Out) + { + anim.PlayOut(); + } + } + } + + private void OnEnable() + { + if ((bool)anim) + { + anim.currentState = CurveAnimationUse.Out; + anim.transform.localScale = Vector3.zero; + } + } + + private void OnDisable() + { + if ((bool)anim) + { + anim.currentState = CurveAnimationUse.Out; + anim.transform.localScale = Vector3.zero; + } + } +} diff --git a/GameCode/IKArmMove.cs b/GameCode/IKArmMove.cs new file mode 100644 index 0000000..ee14990 --- /dev/null +++ b/GameCode/IKArmMove.cs @@ -0,0 +1,56 @@ +using UnityEngine; + +public class IKArmMove : MonoBehaviour +{ + private CharacterData data; + + private PlayerVelocity rig; + + public Transform target; + + private Vector3 startPos; + + private Holding holding; + + private bool isActive; + + private Vector3 velolcity; + + private float sinceRaise = 10f; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + rig = GetComponentInParent<PlayerVelocity>(); + startPos = target.localPosition; + holding = GetComponentInParent<Holding>(); + } + + private void Update() + { + isActive = false; + sinceRaise += TimeHandler.deltaTime; + if ((bool)holding.holdable && (bool)holding.holdable.rig && holding.holdable.rig.transform.position.x > rig.transform.position.x == base.transform.position.x > rig.transform.position.x) + { + target.position = holding.holdable.rig.transform.position; + velolcity = Vector3.zero; + isActive = true; + return; + } + Vector3 vector = base.transform.parent.TransformPoint(startPos) + ((sinceRaise < 0.3f) ? Vector3.up : Vector3.zero); + Vector3 vector2 = rig.velocity; + vector2.x *= 0.3f; + velolcity = FRILerp.Lerp(velolcity, (vector - target.position) * 15f, 15f); + target.position += velolcity * TimeHandler.deltaTime; + target.position += vector2 * -0.3f * TimeHandler.deltaTime; + } + + public void RaiseHands() + { + if (!isActive) + { + sinceRaise = 0f; + velolcity += Vector3.up * 20f; + } + } +} diff --git a/GameCode/IKLegMove.cs b/GameCode/IKLegMove.cs new file mode 100644 index 0000000..cc6d6e6 --- /dev/null +++ b/GameCode/IKLegMove.cs @@ -0,0 +1,142 @@ +using UnityEngine; + +public class IKLegMove : MonoBehaviour +{ + private Rigidbody2D rig; + + public bool touchesGround; + + public IKLegMove otherLeg; + + public Transform target; + + public Transform foot; + + private Vector3 transformGroundPos; + + private Vector3 currentTransformGroundPos; + + private Vector3 previousTransformGroundPos; + + private Transform hitTransform; + + private Transform currentHitTransform; + + [HideInInspector] + public float allowedFootDistance; + + private float defaultAllowedFootDistance; + + public AnimationCurve footCurveUp; + + private float distanceToFoot; + + public LayerMask mask; + + [HideInInspector] + public float animationTime = 1f; + + private Vector3 velocity; + + private CharacterData data; + + private float animationLength; + + private bool hasLanded; + + private void Start() + { + rig = GetComponentInParent<Rigidbody2D>(); + data = GetComponentInParent<CharacterData>(); + defaultAllowedFootDistance = Vector3.Distance(base.transform.position, foot.position); + } + + private void LateUpdate() + { + allowedFootDistance = (defaultAllowedFootDistance = base.transform.root.localScale.x); + animationLength = footCurveUp.keys[footCurveUp.keys.Length - 1].time; + if (!data.isGrounded) + { + animationTime = 1f; + hasLanded = false; + } + distanceToFoot = Vector3.Distance(base.transform.position + (Vector3)rig.velocity * 0.01f, target.position); + velocity = rig.velocity; + if (velocity.y > 0f) + { + velocity.y *= -1f; + } + animationTime += TimeHandler.deltaTime; + RayCastForFootPosition(); + touchesGround = footCurveUp.Evaluate(animationTime) < 0.1f; + DoSteps(); + MoveFoot(); + } + + private void DoSteps() + { + float num = 0f; + if (target.position.x > base.transform.position.x == rig.velocity.x > 0f) + { + num += Mathf.Abs(rig.velocity.x) * 0.25f; + } + float num2 = Mathf.Clamp(animationTime * 0.4f - 0.23f, 0f, 0.2f); + if ((distanceToFoot > allowedFootDistance + num - num2 && data.isGrounded && (otherLeg.animationTime > animationLength * 0.5f || animationLength > 2f) && animationTime > animationLength) || !hasLanded) + { + hasLanded = true; + currentHitTransform = hitTransform; + previousTransformGroundPos = currentTransformGroundPos; + currentTransformGroundPos = transformGroundPos; + animationTime = 0f; + } + else + { + Vector3 vector = transformGroundPos - currentTransformGroundPos; + vector *= Mathf.Clamp(footCurveUp.Evaluate(animationTime) * 1f, 0f, 1f); + previousTransformGroundPos += vector; + currentTransformGroundPos += vector; + } + } + + private void MoveFoot() + { + if (!data.isGrounded) + { + target.position = Vector3.Lerp(target.position, base.transform.position + Vector3.down * allowedFootDistance * 0.5f, TimeHandler.deltaTime * 1f); + target.position += (Vector3)rig.velocity * 0.1f * TimeHandler.deltaTime; + } + else if ((bool)currentHitTransform) + { + Vector3 vector = currentHitTransform.TransformPoint(currentTransformGroundPos); + Vector3 a = currentHitTransform.TransformPoint(previousTransformGroundPos); + Vector3 vector2 = vector; + float num = 0f; + if (animationTime < animationLength) + { + vector2 = Vector3.Lerp(a, vector, animationTime / animationLength); + num = footCurveUp.Evaluate(animationTime); + } + target.position = vector2 + Vector3.up * num; + } + } + + private void RayCastForFootPosition() + { + RaycastHit2D[] array = Physics2D.RaycastAll(base.transform.position, Vector3.down + velocity * 0.2f, 3f, mask); + RaycastHit2D raycastHit2D = default(RaycastHit2D); + float num = float.PositiveInfinity; + for (int i = 0; i < array.Length; i++) + { + if (array[i].transform.root != base.transform.root && array[i].distance < num) + { + raycastHit2D = array[i]; + num = array[i].distance; + } + } + if ((bool)raycastHit2D.transform) + { + hitTransform = raycastHit2D.transform; + transformGroundPos = hitTransform.InverseTransformPoint(raycastHit2D.point); + } + } +} diff --git a/GameCode/IkLeg.cs b/GameCode/IkLeg.cs new file mode 100644 index 0000000..d8dd137 --- /dev/null +++ b/GameCode/IkLeg.cs @@ -0,0 +1,290 @@ +using Sonigon; +using UnityEngine; + +public class IkLeg : MonoBehaviour +{ + [Header("Sounds")] + [SerializeField] + private SoundEvent soundCharacterStep; + + [SerializeField] + private SoundEvent soundCharacterStepBig; + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(); + + private CharacterData data; + + private float legLenth; + + public Transform legRoot; + + public Transform footTarget; + + public LayerMask mask; + + public AnimationCurve upCurve; + + public AnimationCurve forwardCurve; + + public Transform moveDeltaTransform; + + [HideInInspector] + public float stepTime; + + public float stepSpeed = 1f; + + private float footDownTime; + + [HideInInspector] + public bool footDown = true; + + public IkLeg otherLeg; + + private Vector2 restPosition; + + private Vector2 startOffset; + + private Vector2 legRootOffset; + + private float scale = 1f; + + public float prediction = 1f; + + private Vector2 raycastPosLocal; + + private Vector2 raycastPosWorld; + + private Vector2 previousRaycastPosLocal; + + private Vector2 previousRaycastPosWorld; + + private Transform raycastTransform; + + private Transform previousRaycastTransform; + + private Vector2 footPosition; + + private Vector2 deltaPos; + + private Vector2 lastPos; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + legLenth = Vector3.Distance(base.transform.position, footTarget.position); + startOffset = footTarget.position - data.transform.position; + legRootOffset = legRoot.position - data.transform.position; + } + + private void FixedUpdate() + { + if ((bool)data) + { + SetValuesFixed(); + } + } + + private void LateUpdate() + { + if ((bool)data) + { + DoRayCast(); + UpdateRayCastWorldPos(); + DoStep(); + UpdatePreviousRayCastWorldPos(); + UpdateMiscVariables(); + SetFootPos(); + Apply(); + } + } + + private void AirFootMovement() + { + footPosition = Vector3.Lerp(footPosition, restPosition + data.playerVel.velocity * 0.08f, TimeHandler.deltaTime * 15f); + raycastTransform = null; + } + + private bool stepWasLost() + { + if (Vector3.Distance(footPosition, legRoot.position) > legLenth * 0.5f) + { + return true; + } + return false; + } + + private void DoStep() + { + if (footDown) + { + footDownTime += TimeHandler.deltaTime * stepSpeed / scale; + if (!(footDownTime > 1f) || !otherLeg.footDown || (!(Mathf.Abs(data.playerVel.velocity.x) > 1f) && !stepWasLost())) + { + return; + } + StartStep(); + footDownTime = 0f; + footDown = false; + if (!data.dead && data.isPlaying && data.isGrounded && !data.isWallGrab) + { + soundParameterIntensity.intensity = Mathf.Abs(data.playerVel.velocity.x); + if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterStepBig, data.transform, soundParameterIntensity); + } + else + { + SoundManager.Instance.Play(soundCharacterStep, data.transform, soundParameterIntensity); + } + } + } + else + { + stepTime += TimeHandler.deltaTime * stepSpeed / scale; + if (stepTime > 1f) + { + EndStep(); + stepTime = 0f; + footDown = true; + } + } + } + + private void EndStep() + { + if ((bool)raycastTransform) + { + previousRaycastTransform = raycastTransform; + previousRaycastPosLocal = raycastPosLocal; + } + } + + private void StartStep() + { + } + + private void SetFootPos() + { + if (data.isGrounded) + { + if ((bool)raycastTransform) + { + if (footDown) + { + footPosition = previousRaycastPosWorld; + } + else + { + footPosition = Vector3.Lerp(previousRaycastPosWorld, raycastPosWorld, forwardCurve.Evaluate(stepTime)) + Vector3.up * upCurve.Evaluate(stepTime); + } + } + } + else + { + AirFootMovement(); + } + } + + private void Apply() + { + legRoot.position = (Vector2)data.transform.position + legRootOffset * scale; + footTarget.position = footPosition; + } + + private void DoRayCast() + { + Vector2 vector = deltaPos * prediction; + Vector2 origin = data.transform.position + base.transform.right * base.transform.localPosition.x; + Vector2 direction = Vector2.down + vector; + float distance = legLenth * 1.5f * scale + vector.magnitude; + RaycastHit2D[] array = Physics2D.RaycastAll(origin, direction, distance, mask); + RaycastHit2D hit = default(RaycastHit2D); + for (int i = 0; i < array.Length; i++) + { + if (!(array[i].transform.root == data.transform) && (bool)array[i].transform) + { + if (!hit.transform) + { + hit = array[i]; + } + else if (array[i].distance < hit.distance) + { + hit = array[i]; + } + } + } + if ((bool)hit.transform) + { + HitGround(hit); + } + else + { + HitNothing(); + } + } + + private void HitNothing() + { + } + + private void HitGround(RaycastHit2D hit) + { + bool flag = false; + if (!raycastTransform && (bool)hit.transform) + { + flag = true; + } + if ((bool)raycastTransform && raycastTransform != hit.transform) + { + MigrateGroundHit(raycastTransform, hit.transform, hit); + } + raycastTransform = hit.transform; + raycastPosLocal = raycastTransform.InverseTransformPoint(hit.point); + if (flag) + { + Land(hit); + } + } + + private void MigrateGroundHit(Transform from, Transform to, RaycastHit2D hit) + { + } + + private void Land(RaycastHit2D hit) + { + EndStep(); + UpdatePreviousRayCastWorldPos(); + } + + private void UpdateRayCastWorldPos() + { + if ((bool)raycastTransform) + { + raycastPosWorld = raycastTransform.TransformPoint(raycastPosLocal); + } + } + + private void UpdatePreviousRayCastWorldPos() + { + if ((bool)previousRaycastTransform) + { + previousRaycastPosWorld = previousRaycastTransform.TransformPoint(previousRaycastPosLocal); + } + } + + private void UpdateMiscVariables() + { + scale = data.transform.localScale.x; + restPosition = (Vector2)data.transform.position + startOffset * 0.7f * scale; + } + + private void SetValuesFixed() + { + if ((bool)moveDeltaTransform) + { + deltaPos = Vector3.Lerp(deltaPos, (Vector2)moveDeltaTransform.position - lastPos, TimeHandler.deltaTime * 15f); + lastPos = moveDeltaTransform.position; + deltaPos.y = 0f; + } + } +} diff --git a/GameCode/Immunities.cs b/GameCode/Immunities.cs new file mode 100644 index 0000000..e35e4dd --- /dev/null +++ b/GameCode/Immunities.cs @@ -0,0 +1,15 @@ +public class Immunities +{ + public float time; + + public float dmg; + + public string name; + + public Immunities(float time, float dmg, string name) + { + this.time = time; + this.dmg = dmg; + this.name = name; + } +} diff --git a/GameCode/Implosion.cs b/GameCode/Implosion.cs new file mode 100644 index 0000000..080936a --- /dev/null +++ b/GameCode/Implosion.cs @@ -0,0 +1,39 @@ +using System; +using Photon.Pun; +using UnityEngine; + +public class Implosion : MonoBehaviour +{ + public float force; + + public float drag; + + public float time; + + public float clampDist; + + private void Start() + { + Explosion component = GetComponent<Explosion>(); + component.HitTargetAction = (Action<Damagable, float>)Delegate.Combine(component.HitTargetAction, new Action<Damagable, float>(HitTarget)); + clampDist *= base.transform.localScale.x; + force *= base.transform.localScale.x; + } + + public void HitTarget(Damagable damageble, float distance) + { + DoPull(damageble, distance); + } + + private void DoPull(Damagable damageble, float distance) + { + bool num = GetComponent<SpawnedAttack>().IsMine(); + HealthHandler component = damageble.GetComponent<HealthHandler>(); + CharacterData component2 = damageble.GetComponent<CharacterData>(); + _ = (Vector2)((base.transform.position - component.transform.position) * 0.25f); + if (num) + { + component2.view.RPC("RPCA_SendForceTowardsPointOverTime", RpcTarget.All, force, drag, clampDist, (Vector2)base.transform.position, time, 0, false, false); + } + } +} diff --git a/GameCode/InitPackage.cs b/GameCode/InitPackage.cs new file mode 100644 index 0000000..8014287 --- /dev/null +++ b/GameCode/InitPackage.cs @@ -0,0 +1,4 @@ +public class InitPackage +{ + public int currentMapID; +} diff --git a/GameCode/IsMineEvent.cs b/GameCode/IsMineEvent.cs new file mode 100644 index 0000000..11e2ce3 --- /dev/null +++ b/GameCode/IsMineEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class IsMineEvent : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/JustEvent.cs b/GameCode/JustEvent.cs new file mode 100644 index 0000000..2ca4c81 --- /dev/null +++ b/GameCode/JustEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class JustEvent : MonoBehaviour +{ + public UnityEvent justEvent; + + public void Go() + { + justEvent.Invoke(); + } +} diff --git a/GameCode/KillBox.cs b/GameCode/KillBox.cs new file mode 100644 index 0000000..eb69a56 --- /dev/null +++ b/GameCode/KillBox.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +public class KillBox : MonoBehaviour +{ + public bool alwaysOn; + + public float toggleTime = 0.3f; + + private float timeActivated = -10f; + + public bool readyToKill; + + private BoxCollider2D box; + + private void Start() + { + box = GetComponent<BoxCollider2D>(); + } + + private void Update() + { + readyToKill = timeActivated + toggleTime > Time.time; + if (!readyToKill) + { + return; + } + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + if (box.OverlapPoint(PlayerManager.instance.players[i].transform.position)) + { + PlayerManager.instance.players[i].data.healthHandler.TakeDamage(Vector2.up * 1000f, base.transform.position); + } + } + } + + public void Activate() + { + timeActivated = Time.time; + } +} diff --git a/GameCode/LeftRight.cs b/GameCode/LeftRight.cs new file mode 100644 index 0000000..d4777ee --- /dev/null +++ b/GameCode/LeftRight.cs @@ -0,0 +1,5 @@ +public enum LeftRight +{ + Left, + Right +} diff --git a/GameCode/LegRaycasters.cs b/GameCode/LegRaycasters.cs new file mode 100644 index 0000000..db676b0 --- /dev/null +++ b/GameCode/LegRaycasters.cs @@ -0,0 +1,77 @@ +using UnityEngine; + +public class LegRaycasters : MonoBehaviour +{ + public LayerMask mask; + + public float force; + + public float drag; + + public Transform[] legCastPositions; + + public AnimationCurve animationCurve; + + private PlayerVelocity rig; + + private CharacterData data; + + public AnimationCurve wobbleCurve; + + public AnimationCurve forceCurve; + + private IkLeg[] legs; + + private float totalStepTime; + + private void Awake() + { + legs = base.transform.root.GetComponentsInChildren<IkLeg>(); + } + + private void Start() + { + rig = GetComponentInParent<PlayerVelocity>(); + data = GetComponentInParent<CharacterData>(); + } + + private void FixedUpdate() + { + totalStepTime = 0f; + for (int i = 0; i < legs.Length; i++) + { + if (!legs[i].footDown) + { + totalStepTime += legs[i].stepTime; + } + } + for (int j = 0; j < legCastPositions.Length; j++) + { + RaycastHit2D[] array = Physics2D.RaycastAll(legCastPositions[j].transform.position + Vector3.up * 0.5f, Vector2.down, 1f * base.transform.root.localScale.x, mask); + for (int k = 0; k < array.Length; k++) + { + if ((bool)array[k].transform && array[k].transform.root != base.transform.root) + { + HitGround(legCastPositions[j], array[k]); + break; + } + } + } + } + + private void HitGround(Transform leg, RaycastHit2D hit) + { + if (!(data.sinceJump < 0.2f) && !(Vector3.Angle(Vector3.up, hit.normal) > 70f)) + { + data.TouchGround(hit.point, hit.normal, hit.rigidbody); + Vector3 vector = ((Vector3)hit.point - leg.transform.position) / base.transform.root.localScale.x; + if (data.input.direction.x != 0f) + { + vector.y += wobbleCurve.Evaluate(totalStepTime) * base.transform.root.localScale.x; + rig.AddForce(Vector3.up * forceCurve.Evaluate(totalStepTime) * rig.mass); + } + rig.AddForce(animationCurve.Evaluate(Mathf.Abs(vector.y)) * Vector3.up * rig.mass * force); + rig.AddForce(animationCurve.Evaluate(Mathf.Abs(vector.y)) * (0f - rig.velocity.y) * Vector2.up * rig.mass * drag); + } + } +} diff --git a/GameCode/LegRenderer.cs b/GameCode/LegRenderer.cs new file mode 100644 index 0000000..094b0c9 --- /dev/null +++ b/GameCode/LegRenderer.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using UnityEngine; + +public class LegRenderer : MonoBehaviour +{ + public Transform start; + + public Transform mid; + + public Transform end; + + public int segmentCount = 10; + + public GameObject segment; + + public float segmentLength = 1f; + + private List<Transform> segments = new List<Transform>(); + + private void Awake() + { + for (int i = 0; i < segmentCount; i++) + { + GameObject gameObject = Object.Instantiate(segment, base.transform); + gameObject.SetActive(value: true); + segments.Add(gameObject.transform); + if (i == segmentCount - 1) + { + gameObject.transform.localScale *= 0f; + } + } + } + + private void LateUpdate() + { + for (int i = 0; i < segments.Count; i++) + { + float t = (float)i / ((float)segments.Count - 1f); + _ = Vector3.zero; + if (i == 0) + { + _ = segments[i + 1].position - segments[i].position; + } + else if (i == segments.Count - 1) + { + _ = segments[i].position - segments[i - 1].position; + } + else + { + Vector3 vector = segments[i].position - segments[i - 1].position; + Vector3 vector2 = segments[i + 1].position - segments[i].position; + _ = (vector + vector2) * 0.5f; + } + segments[i].position = BezierCurve.QuadraticBezier(start.position, mid.position, end.position, t); + } + for (int j = 0; j < segments.Count; j++) + { + _ = (float)j / ((float)segments.Count - 1f); + Vector3 zero = Vector3.zero; + if (j == 0) + { + zero = segments[j + 1].position - segments[j].position; + } + else if (j == segments.Count - 1) + { + zero = segments[j].position - segments[j - 1].position; + } + else + { + Vector3 vector3 = segments[j].position - segments[j - 1].position; + Vector3 vector4 = segments[j + 1].position - segments[j].position; + zero = (vector3 + vector4) * 0.5f; + } + segments[j].rotation = Quaternion.LookRotation(Vector3.forward, zero); + } + } +} diff --git a/GameCode/LegRotator.cs b/GameCode/LegRotator.cs new file mode 100644 index 0000000..35e95b7 --- /dev/null +++ b/GameCode/LegRotator.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class LegRotator : MonoBehaviour +{ + private PlayerVelocity rig; + + private void Start() + { + rig = GetComponentInParent<PlayerVelocity>(); + } + + private void Update() + { + if ((bool)rig) + { + if (rig.velocity.x < 0f) + { + base.transform.localEulerAngles = Vector3.Lerp(base.transform.localEulerAngles, new Vector3(0f, 0f, 0f), TimeHandler.deltaTime * 15f * Mathf.Clamp(Mathf.Abs(rig.velocity.x), 0f, 1f)); + } + else + { + base.transform.localEulerAngles = Vector3.Lerp(base.transform.localEulerAngles, new Vector3(0f, 180f, 0f), TimeHandler.deltaTime * 15f * Mathf.Clamp(Mathf.Abs(rig.velocity.x), 0f, 1f)); + } + } + } +} diff --git a/GameCode/LerpBackToStartPos.cs b/GameCode/LerpBackToStartPos.cs new file mode 100644 index 0000000..cf73c0b --- /dev/null +++ b/GameCode/LerpBackToStartPos.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class LerpBackToStartPos : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/LevelMapper.cs b/GameCode/LevelMapper.cs new file mode 100644 index 0000000..63e1e06 --- /dev/null +++ b/GameCode/LevelMapper.cs @@ -0,0 +1,132 @@ +using System; +using UnityEngine; + +public class LevelMapper : MonoBehaviour +{ + private CharacterData data; + + private PlayerJump jump; + + private PlayerMovement movement; + + private bool isJumping; + + private bool isRunning; + + public GameObject node; + + public GameObject line; + + public GameObject line2; + + private Vector3 jumpPos; + + private Vector3 landPos; + + private Vector3 startRunPos; + + private Vector3 leaveGroundPos; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + jump = data.jump; + movement = data.movement; + PlayerJump playerJump = jump; + playerJump.JumpAction = (Action)Delegate.Combine(playerJump.JumpAction, new Action(Jump)); + CharacterData characterData = data; + characterData.TouchGroundAction = (Action<float, Vector3, Vector3, Transform>)Delegate.Combine(characterData.TouchGroundAction, new Action<float, Vector3, Vector3, Transform>(Ground)); + CharacterData characterData2 = data; + characterData2.TouchWallAction = (Action<float, Vector3, Vector3>)Delegate.Combine(characterData2.TouchWallAction, new Action<float, Vector3, Vector3>(Wall)); + } + + private void Update() + { + if (!data.isGrounded) + { + LeaveGround(); + } + } + + private void Jump() + { + isJumping = true; + jumpPos = base.transform.position; + } + + private void Wall(float sinceWall, Vector3 pos, Vector3 normal) + { + if (!data.isWallGrab) + { + if (data.sinceJump < 0.1f) + { + isJumping = false; + } + else + { + Land(); + } + } + } + + private void Ground(float sinceGround, Vector3 pos, Vector3 groundNormal, Transform groundTransform = null) + { + if (!isRunning) + { + startRunPos = pos; + isRunning = true; + } + if (!data.isGrounded) + { + if (data.sinceJump < 0.1f) + { + isJumping = false; + } + else + { + Land(); + } + } + } + + private void Land() + { + landPos = base.transform.position; + if (Vector3.Distance(landPos, jumpPos) > 3f && isJumping) + { + SaveJump(); + } + isJumping = false; + } + + private void LeaveGround() + { + if (isRunning) + { + leaveGroundPos = data.groundPos; + SaveRun(); + isRunning = false; + } + } + + private void SaveJump() + { + UnityEngine.Object.Instantiate(node, jumpPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.green; + UnityEngine.Object.Instantiate(node, landPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.red; + LineRenderer component = UnityEngine.Object.Instantiate(line, Vector3.zero, Quaternion.identity).GetComponent<LineRenderer>(); + component.SetPosition(0, jumpPos); + component.SetPosition(1, landPos); + } + + private void SaveRun() + { + if (!(Vector3.Distance(startRunPos, jumpPos) < 2f)) + { + UnityEngine.Object.Instantiate(node, startRunPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.blue; + UnityEngine.Object.Instantiate(node, leaveGroundPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.blue; + LineRenderer component = UnityEngine.Object.Instantiate(line2, Vector3.zero, Quaternion.identity).GetComponent<LineRenderer>(); + component.SetPosition(0, startRunPos); + component.SetPosition(1, leaveGroundPos); + } + } +} diff --git a/GameCode/LevelScale.cs b/GameCode/LevelScale.cs new file mode 100644 index 0000000..39969ca --- /dev/null +++ b/GameCode/LevelScale.cs @@ -0,0 +1,45 @@ +using System; +using UnityEngine; + +public class LevelScale : MonoBehaviour +{ + public bool onLevelUp = true; + + public bool onStart; + + private AttackLevel level; + + private Vector3 startScale; + + private bool inited; + + private void Init() + { + if (!inited) + { + inited = true; + startScale = base.transform.localScale; + } + } + + private void Start() + { + Init(); + level = GetComponent<AttackLevel>(); + if (onStart) + { + base.transform.localScale *= level.LevelScale(); + } + if (onLevelUp) + { + AttackLevel attackLevel = level; + attackLevel.LevelUpAction = (Action<int>)Delegate.Combine(attackLevel.LevelUpAction, new Action<int>(LevelUp)); + } + } + + public void LevelUp(int lvl) + { + Init(); + base.transform.localScale = startScale * level.LevelScale(); + } +} diff --git a/GameCode/LifeSteal.cs b/GameCode/LifeSteal.cs new file mode 100644 index 0000000..6608cdb --- /dev/null +++ b/GameCode/LifeSteal.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class LifeSteal : DealtDamageEffect +{ + private HealthHandler health; + + public float multiplier; + + public override void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null) + { + if (!selfDamage) + { + if (!health) + { + health = GetComponentInParent<HealthHandler>(); + } + health.Heal(damage.magnitude * multiplier); + } + } +} diff --git a/GameCode/LineEffect.cs b/GameCode/LineEffect.cs new file mode 100644 index 0000000..ee2cd03 --- /dev/null +++ b/GameCode/LineEffect.cs @@ -0,0 +1,454 @@ +using System; +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; + +public class LineEffect : MonoBehaviour +{ + public enum LineType + { + Line, + Ring + } + + public enum AnimType + { + Width, + Offset + } + + public bool playOnAwake; + + public bool loop; + + public LineType lineType; + + public int segments = 20; + + public float globalTimeSpeed = 1f; + + public bool raycastCollision; + + [FoldoutGroup("Animation", 0)] + public AnimationCurve lineWidthOverTimeCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [Space(10f)] + [FoldoutGroup("Animation", 0)] + public bool useColorOverTime; + + [FoldoutGroup("Animation", 0)] + [ShowIf("useColorOverTime", true)] + public Gradient colorOverTime; + + [Space(10f)] + [FoldoutGroup("Animation", 0)] + [ShowIf("lineType", LineType.Ring, true)] + public float radius = 5f; + + [FoldoutGroup("Animation", 0)] + [ShowIf("lineType", LineType.Ring, true)] + public AnimationCurve radiusOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [Space(10f)] + [FoldoutGroup("Special", 0)] + public float inheritScaleFactor; + + [Space(10f)] + public LineEffectInstance[] effects; + + private LineRenderer line; + + [HideInInspector] + public float counter; + + private float startWidth; + + [HideInInspector] + public float currentWidth; + + [FoldoutGroup("Debug", 0)] + public bool debug; + + [FoldoutGroup("Debug", 0)] + public Transform fromPos; + + [FoldoutGroup("Debug", 0)] + public Transform toPos; + + [FoldoutGroup("Debug", 0)] + public Transform bezierPos; + + [HideInInspector] + public float offsetMultiplier = 1f; + + [HideInInspector] + public float widthMultiplier = 1f; + + private float scaleMultiplier = 1f; + + private bool inited; + + public bool isPlaying; + + private Coroutine widthAnim; + + private Coroutine offsetAnim; + + private void Start() + { + globalTimeSpeed *= UnityEngine.Random.Range(0.95f, 1.05f); + } + + private void OnEnable() + { + if (!inited) + { + Init(); + } + if (playOnAwake && lineType == LineType.Ring) + { + Play(base.transform); + } + } + + private void Init() + { + if (!inited) + { + line = GetComponent<LineRenderer>(); + line.positionCount = segments; + line.useWorldSpace = true; + startWidth = line.widthMultiplier; + inited = true; + scaleMultiplier = 1f - inheritScaleFactor + base.transform.lossyScale.x * inheritScaleFactor; + } + } + + private void Update() + { + if (!debug) + { + return; + } + if (lineType == LineType.Line && (bool)fromPos && (bool)toPos) + { + if ((bool)bezierPos) + { + DrawLine(fromPos.position, toPos.position, bezierPos.position); + } + else + { + DrawLine(fromPos.position, toPos.position); + } + } + if (lineType == LineType.Ring && (bool)fromPos) + { + DrawLine(fromPos.position, Vector3.zero); + } + } + + public void StartDraw() + { + if (!base.gameObject.activeSelf) + { + base.gameObject.SetActive(value: true); + } + counter = 0f; + } + + public void DrawLine(Vector3 start, Vector3 end) + { + DrawLine(start, end, Vector3.one * 100f); + } + + public void DrawLine(Vector3 start, Vector3 end, Vector3 bezier) + { + Init(); + Vector3 vector = Vector3.zero; + for (int i = 0; i < line.positionCount; i++) + { + float num = 0f; + for (int j = 0; j < effects.Length; j++) + { + if (!effects[j].active) + { + continue; + } + float num2 = 0f; + float num3 = (float)i / ((float)line.positionCount - 1f); + float time = num3; + float num4 = effects[j].mainCurveTiling; + if (effects[j].tilingPerMeter) + { + if (lineType == LineType.Line) + { + num4 *= (start - end).magnitude; + } + if (lineType == LineType.Ring) + { + num4 *= radius; + } + } + num3 *= num4; + if (effects[j].mainCurveScrollSpeed > 0f) + { + num3 += effects[j].mainCurveScrollSpeed * Time.unscaledTime; + } + if (effects[j].mainCurveScrollSpeed < 0f) + { + num3 += (0f - effects[j].mainCurveScrollSpeed) * (100000f - Time.unscaledTime); + } + num3 %= 1f; + num2 = effects[j].mainCurve.Evaluate(num3); + num2 *= effects[j].mainCurveMultiplier; + num2 *= effects[j].effectOverLineCurve.Evaluate(time); + num2 *= effects[j].effectOverTimeCurve.Evaluate(counter); + if (effects[j].curveType == LineEffectInstance.CurveType.Add) + { + num += num2; + } + else if (effects[j].curveType == LineEffectInstance.CurveType.Multiply) + { + num *= num2; + } + } + float t = (float)i / ((float)line.positionCount - 1f); + Vector3 vector2 = Vector3.zero; + Vector3 vector3 = Vector3.zero; + if (lineType == LineType.Ring) + { + float f = (float)Math.PI / 180f * ((float)i * 360f / (float)(segments - 1)); + vector2 = start + new Vector3(Mathf.Sin(f) * (radius * base.transform.root.localScale.x * radiusOverTime.Evaluate(counter)), Mathf.Cos(f) * (radius * base.transform.root.localScale.x * radiusOverTime.Evaluate(counter)), 0f); + vector3 = ((!(vector != Vector3.zero)) ? Vector3.up : Vector3.Cross(Vector3.forward, vector2 - vector).normalized); + } + if (lineType == LineType.Line) + { + vector2 = Vector3.Lerp(start, end, t); + vector3 = Vector3.Cross(start - end, Vector3.forward).normalized; + if (bezier != Vector3.one * 100f) + { + vector2 = BezierCurve.QuadraticBezier(start, bezier, end, t); + } + } + vector = vector2; + line.SetPosition(i, vector2 + vector3 * num * offsetMultiplier); + } + if (raycastCollision) + { + RaycastPositions(); + } + if (lineType == LineType.Ring) + { + SmoothSeam(); + } + line.widthMultiplier = lineWidthOverTimeCurve.Evaluate(counter) * startWidth * scaleMultiplier * widthMultiplier; + currentWidth = line.widthMultiplier; + if (useColorOverTime) + { + line.startColor = colorOverTime.Evaluate(counter); + line.endColor = colorOverTime.Evaluate(counter); + } + counter += Time.unscaledDeltaTime * globalTimeSpeed; + if (counter > 1f) + { + if (debug || loop) + { + StartDraw(); + } + else + { + base.gameObject.SetActive(value: false); + } + } + } + + private void RaycastPositions() + { + for (int i = 0; i < line.positionCount; i++) + { + line.SetPosition(i, PhysicsFunctions.ObstructionPoint(base.transform.position, line.GetPosition(i))); + } + } + + private void SmoothSeam() + { + float num = 0.1f; + Vector3 b = (line.GetPosition(0) + line.GetPosition(line.positionCount - 1)) * 0.5f; + for (int i = 0; i < line.positionCount; i++) + { + float num2 = (float)i / ((float)line.positionCount - 1f); + _ = Vector3.zero; + Vector3 zero = Vector3.zero; + Vector3 position = line.GetPosition(i); + float t; + if (num2 > 0.5f) + { + t = Mathf.Clamp((num2 - (1f - num)) / num, 0f, 1f); + } + else + { + t = Mathf.Clamp(num2 * (1f / num), 0f, 1f); + t = 1f - t; + } + zero = Vector3.Lerp(position, b, t) - position; + zero.x *= 0.5f; + line.SetPosition(i, position + zero); + } + line.SetPosition(1, new Vector3(line.GetPosition(1).x, b.y)); + line.SetPosition(line.positionCount - 2, new Vector3(line.GetPosition(line.positionCount - 2).x, b.y)); + } + + public void Stop() + { + StopAllCoroutines(); + if (!loop) + { + base.gameObject.SetActive(value: false); + } + } + + public void Play() + { + Play(base.transform); + } + + private void OnDisable() + { + Stop(); + } + + public void ResetMultipliers() + { + offsetMultiplier = 1f; + scaleMultiplier = 1f; + widthMultiplier = 1f; + } + + public void Play(Transform fromTransform, Transform toTransform, float bezierOffset = 0f) + { + StartDraw(); + StopAllCoroutines(); + StartCoroutine(DoPlay(fromTransform, toTransform, bezierOffset)); + } + + private IEnumerator DoPlay(Transform fromTransform, Transform toTransform, float bezierOffset = 0f) + { + isPlaying = true; + Vector3 currentBez = Vector3.zero; + while (base.gameObject.activeSelf && (bool)fromTransform && (bool)toTransform) + { + if (bezierOffset != 0f) + { + float num = 1f; + if (toTransform.position.x < fromTransform.position.x) + { + num = -1f; + } + Vector3 vector = Vector3.Cross(Vector3.forward, toTransform.position - fromTransform.position).normalized * bezierOffset * num; + currentBez = ((!(currentBez == Vector3.zero)) ? Vector3.Lerp(currentBez, vector, TimeHandler.deltaTime * 5f) : vector); + Vector3 bezier = currentBez + (fromTransform.position + toTransform.position) * 0.5f; + DrawLine(fromTransform.position, toTransform.position, bezier); + } + else + { + DrawLine(fromTransform.position, toTransform.position); + } + yield return null; + } + isPlaying = false; + } + + public void Play(Transform fromTransform, Vector3 toPosition, float bezierOffset = 0f) + { + StartDraw(); + StopAllCoroutines(); + StartCoroutine(DoPlay(fromTransform, toPosition, bezierOffset)); + } + + private IEnumerator DoPlay(Transform fromTransform, Vector3 toPosition, float bezierOffset = 0f) + { + Vector3 currentBezOffset = Vector3.zero; + while (base.gameObject.activeSelf && (bool)fromTransform) + { + if (bezierOffset != 0f) + { + float num = 1f; + if (toPosition.x < fromTransform.position.x) + { + num = -1f; + } + Vector3 vector = Vector3.Cross(Vector3.forward, toPosition - fromTransform.position).normalized * bezierOffset * num; + currentBezOffset = ((!(currentBezOffset == Vector3.zero)) ? Vector3.Lerp(currentBezOffset, vector, TimeHandler.deltaTime * 2f) : vector); + _ = currentBezOffset + (fromTransform.position + toPosition) * 0.5f; + Vector3 bezier = (fromTransform.position + toPosition) * 0.5f; + DrawLine(fromTransform.position, toPosition, bezier); + } + else + { + DrawLine(fromTransform.position, toPosition); + } + yield return null; + } + } + + public void Play(Transform fromTransform) + { + StartDraw(); + StopAllCoroutines(); + StartCoroutine(DoPlay(fromTransform)); + } + + private IEnumerator DoPlay(Transform fromTransform) + { + while (base.gameObject.activeSelf && (bool)fromTransform) + { + DrawLine(fromTransform.position, Vector3.zero); + yield return null; + } + } + + public void PlayAnim(AnimType animType, AnimationCurve curve, float speed = 1f) + { + if (animType == AnimType.Offset && offsetAnim != null) + { + StopCoroutine(offsetAnim); + } + if (animType == AnimType.Width && widthAnim != null) + { + StopCoroutine(widthAnim); + } + Coroutine coroutine = StartCoroutine(DoPlayAnim(animType, curve, speed)); + if (animType == AnimType.Offset) + { + offsetAnim = coroutine; + } + if (animType == AnimType.Width) + { + widthAnim = coroutine; + } + } + + private IEnumerator DoPlayAnim(AnimType animType, AnimationCurve curve, float speed = 1f) + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + if (animType == AnimType.Offset) + { + offsetMultiplier = curve.Evaluate(c); + } + if (animType == AnimType.Width) + { + widthMultiplier = curve.Evaluate(c); + } + c += TimeHandler.deltaTime * speed; + yield return null; + } + } + + internal float GetRadius() + { + return radius * base.transform.root.localScale.x * radiusOverTime.Evaluate(counter); + } +} diff --git a/GameCode/LineEffectExplosionModifier.cs b/GameCode/LineEffectExplosionModifier.cs new file mode 100644 index 0000000..3f1c66b --- /dev/null +++ b/GameCode/LineEffectExplosionModifier.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using UnityEngine; + +public class LineEffectExplosionModifier : MonoBehaviour +{ + public AnimationCurve curve; + + public float speed = 1f; + + private LineEffect effect; + + private Coroutine corutine; + + private void Start() + { + effect = GetComponent<LineEffect>(); + Explosion componentInParent = GetComponentInParent<Explosion>(); + componentInParent.DealDamageAction = (Action<Damagable>)Delegate.Combine(componentInParent.DealDamageAction, new Action<Damagable>(DealDamage)); + Explosion componentInParent2 = GetComponentInParent<Explosion>(); + componentInParent2.DealHealAction = (Action<Damagable>)Delegate.Combine(componentInParent2.DealHealAction, new Action<Damagable>(DealDamage)); + } + + public void DealDamage(Damagable damagable) + { + if (corutine != null) + { + StopCoroutine(corutine); + } + corutine = StartCoroutine(DoCurve()); + } + + private IEnumerator DoCurve() + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + effect.offsetMultiplier = curve.Evaluate(c); + c += TimeHandler.deltaTime * speed; + yield return null; + } + } +} diff --git a/GameCode/LineEffectInstance.cs b/GameCode/LineEffectInstance.cs new file mode 100644 index 0000000..a154130 --- /dev/null +++ b/GameCode/LineEffectInstance.cs @@ -0,0 +1,40 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; + +[Serializable] +public class LineEffectInstance +{ + public enum CurveType + { + Add, + Multiply + } + + [Space(20f)] + public bool active = true; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public CurveType curveType; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public AnimationCurve mainCurve = AnimationCurve.Linear(0f, 0f, 1f, 0f); + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public float mainCurveMultiplier = 1f; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public float mainCurveTiling = 1f; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public bool tilingPerMeter = true; + + [FoldoutGroup("Modifiers", 0)] + public AnimationCurve effectOverLineCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [FoldoutGroup("Animation", 0)] + public float mainCurveScrollSpeed; + + [FoldoutGroup("Animation", 0)] + public AnimationCurve effectOverTimeCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f); +} diff --git a/GameCode/LineOfSightTrigger.cs b/GameCode/LineOfSightTrigger.cs new file mode 100644 index 0000000..99fca28 --- /dev/null +++ b/GameCode/LineOfSightTrigger.cs @@ -0,0 +1,59 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class LineOfSightTrigger : MonoBehaviour +{ + public UnityEvent turnOnEvent; + + public UnityEvent turnOffEvent; + + public UnityEvent switchTargetEvent; + + public Action<Player> turnOnAction; + + public Action<Player> switchTargetAction; + + public Action turnOffAction; + + private Player player; + + private bool isOn; + + private Player currentTarget; + + private void Start() + { + player = GetComponentInParent<Player>(); + } + + private void Update() + { + Player closestPlayerInTeam = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(player.teamID)); + if ((bool)closestPlayerInTeam) + { + if (currentTarget != player) + { + switchTargetEvent.Invoke(); + switchTargetAction?.Invoke(player); + currentTarget = closestPlayerInTeam; + } + if (!isOn) + { + isOn = true; + turnOnAction?.Invoke(player); + turnOnEvent.Invoke(); + } + } + else + { + if (isOn) + { + isOn = false; + turnOffAction?.Invoke(); + turnOffEvent.Invoke(); + } + currentTarget = null; + } + } +} diff --git a/GameCode/LineRangeEffect.cs b/GameCode/LineRangeEffect.cs new file mode 100644 index 0000000..6671fcc --- /dev/null +++ b/GameCode/LineRangeEffect.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +public class LineRangeEffect : MonoBehaviour +{ + public float dmg; + + public float knockback; + + private LineEffect lineEffect; + + private Player owner; + + private SpawnedAttack spawned; + + private bool done; + + private void Start() + { + spawned = GetComponent<SpawnedAttack>(); + owner = GetComponent<SpawnedAttack>().spawner; + lineEffect = GetComponentInChildren<LineEffect>(); + } + + private void Update() + { + if (done || !spawned.IsMine()) + { + return; + } + Player closestPlayerInTeam = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(owner.teamID), needVision: true); + if ((bool)closestPlayerInTeam) + { + float num = 2f; + float radius = lineEffect.GetRadius(); + float num2 = Vector2.Distance(base.transform.position, closestPlayerInTeam.transform.position); + if (num2 < radius + num && num2 > radius - num) + { + done = true; + closestPlayerInTeam.data.healthHandler.CallTakeDamage(dmg * base.transform.localScale.x * (closestPlayerInTeam.transform.position - base.transform.position).normalized, closestPlayerInTeam.transform.position, null, owner); + closestPlayerInTeam.data.healthHandler.CallTakeForce(knockback * base.transform.localScale.x * (closestPlayerInTeam.transform.position - base.transform.position).normalized); + } + } + } +} diff --git a/GameCode/ListMenu.cs b/GameCode/ListMenu.cs new file mode 100644 index 0000000..1ed98f6 --- /dev/null +++ b/GameCode/ListMenu.cs @@ -0,0 +1,136 @@ +using System.Collections; +using SoundImplementation; +using UnityEngine; +using UnityEngine.EventSystems; + +public class ListMenu : MonoBehaviour +{ + [Header("Settings")] + public GameObject bar; + + [Header("Settings")] + public GameObject particle; + + public ListMenuButton selectedButton; + + public ListMenuPage selectedPage; + + public static ListMenu instance; + + public GameObject menuCanvas; + + private bool isActive = true; + + private Vector3 lastPos; + + private bool playButtonHoverFirst = true; + + private void Awake() + { + instance = this; + } + + private void Start() + { + GetComponentInChildren<ListMenuPage>(includeInactive: true).Open(); + } + + private void Update() + { + if ((lastPos - bar.transform.position).sqrMagnitude > 0.5f && (MainMenuHandler.instance.isOpen || EscapeMenuHandler.isEscMenu)) + { + if (!playButtonHoverFirst) + { + SoundPlayerStatic.Instance.PlayButtonHover(); + } + else + { + playButtonHoverFirst = false; + } + } + lastPos = bar.transform.position; + if ((bool)selectedButton && EventSystem.current.currentSelectedGameObject == null) + { + EventSystem.current.SetSelectedGameObject(selectedButton.gameObject); + } + if (EscapeMenuHandler.isEscMenu || menuCanvas.activeInHierarchy) + { + if (!bar.activeSelf) + { + bar.SetActive(value: true); + particle.SetActive(value: true); + } + } + else if (bar.activeSelf) + { + bar.SetActive(value: false); + particle.SetActive(value: false); + } + } + + internal void DeselectButton() + { + if ((bool)selectedButton) + { + selectedButton.Deselect(); + } + } + + public void OpenPage(ListMenuPage pageToOpen) + { + if ((bool)selectedPage) + { + selectedPage.Close(); + } + bar.transform.localScale = new Vector3(bar.transform.localScale.x, pageToOpen.barHeight, 1f); + selectedPage = pageToOpen; + if (MenuControllerHandler.menuControl == MenuControllerHandler.MenuControl.Controller) + { + SelectButton(selectedPage.firstSelected); + } + else + { + bar.transform.position = Vector3.up * 10000f; + } + } + + public void SelectButton(ListMenuButton buttonToSelect) + { + if (!buttonToSelect || buttonToSelect.hideBar) + { + bar.transform.position = Vector3.up * 10000f; + } + else + { + StartCoroutine(ISelectButton(buttonToSelect)); + } + } + + public IEnumerator ISelectButton(ListMenuButton buttonToSelect) + { + if ((bool)selectedButton) + { + selectedButton.Deselect(); + } + yield return new WaitForEndOfFrame(); + buttonToSelect.Select(); + selectedButton = buttonToSelect; + bar.transform.position = buttonToSelect.transform.position; + if (EventSystem.current.currentSelectedGameObject != selectedButton.gameObject) + { + EventSystem.current.SetSelectedGameObject(selectedButton.gameObject); + } + if (buttonToSelect.setBarHeight != 0f) + { + bar.transform.localScale = new Vector3(bar.transform.localScale.x, buttonToSelect.setBarHeight, 1f); + } + } + + public void ClearBar() + { + if (MenuControllerHandler.menuControl != 0) + { + bar.transform.position = Vector3.up * 10000f; + } + } +} diff --git a/GameCode/ListMenuButton.cs b/GameCode/ListMenuButton.cs new file mode 100644 index 0000000..b208a12 --- /dev/null +++ b/GameCode/ListMenuButton.cs @@ -0,0 +1,102 @@ +using SoundImplementation; +using TMPro; +using UnityEngine; +using UnityEngine.EventSystems; + +public class ListMenuButton : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler, IUpdateSelectedHandler, ISelectHandler +{ + private TextMeshProUGUI text; + + private Color defaultColor; + + private Vector3 defaultPos; + + public bool changeFontSize = true; + + public bool hideBar; + + public float setBarHeight; + + public bool toggleTextColor; + + public Color selectedTextColor; + + public Color defaultTextColor; + + private float smallFont = 40f; + + private bool inited; + + private void Awake() + { + } + + private void Start() + { + Init(); + smallFont = text.fontSize; + defaultPos = text.transform.localPosition; + defaultColor = text.color; + } + + public void Nope() + { + Init(); + MenuEffects.instance.BlinkInColor(text, MenuEffects.instance.nopeColor, defaultColor, 0.15f); + MenuEffects.instance.ShakeObject(text.gameObject, defaultPos, 15f, 0.2f); + } + + public void Deselect() + { + Init(); + text.fontStyle = FontStyles.Normal; + _ = changeFontSize; + if (toggleTextColor) + { + GetComponentInChildren<TextMeshProUGUI>().color = defaultTextColor; + } + } + + public void Select() + { + Init(); + text.fontStyle = FontStyles.Bold; + _ = changeFontSize; + if (toggleTextColor) + { + GetComponentInChildren<TextMeshProUGUI>().color = selectedTextColor; + } + } + + public void OnPointerClick(PointerEventData eventData) + { + SoundPlayerStatic.Instance.PlayButtonClick(); + } + + public void OnPointerEnter(PointerEventData eventData) + { + ListMenu.instance.SelectButton(this); + } + + public void OnPointerExit(PointerEventData eventData) + { + } + + public void OnUpdateSelected(BaseEventData eventData) + { + } + + public void OnSelect(BaseEventData eventData) + { + ListMenu.instance.SelectButton(this); + } + + private void Init() + { + if (!inited) + { + inited = true; + text = GetComponentInChildren<TextMeshProUGUI>(); + } + } +} diff --git a/GameCode/ListMenuPage.cs b/GameCode/ListMenuPage.cs new file mode 100644 index 0000000..e4735b4 --- /dev/null +++ b/GameCode/ListMenuPage.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +public class ListMenuPage : MonoBehaviour +{ + public ListMenuButton firstSelected; + + public float barHeight = 92f; + + private GameObject grid; + + private void Awake() + { + grid = base.transform.GetChild(0).gameObject; + } + + public void Open() + { + ListMenu.instance.OpenPage(this); + grid.SetActive(value: true); + } + + public void Close() + { + DeselectAll(); + grid.SetActive(value: false); + } + + private void DeselectAll() + { + ListMenuButton[] componentsInChildren = GetComponentsInChildren<ListMenuButton>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].Deselect(); + } + } +} diff --git a/GameCode/LoadingScreen.cs b/GameCode/LoadingScreen.cs new file mode 100644 index 0000000..72d65fd --- /dev/null +++ b/GameCode/LoadingScreen.cs @@ -0,0 +1,81 @@ +using System.Collections; +using SoundImplementation; +using TMPro; +using UnityEngine; + +public class LoadingScreen : MonoBehaviour +{ + private const string SEARCHING_TEXT = "SEARCHING"; + + private const string SEARCHING_PRIVATE_TEXT = "WAITING FOR FRIEND"; + + [SerializeField] + private TextMeshProUGUI m_SearchingText; + + public GameObject gameMode; + + public GeneralParticleSystem searchingSystem; + + public GeneralParticleSystem matchFoundSystem; + + public GeneralParticleSystem[] playerNamesSystem; + + public float matchFoundTime = 0.5f; + + public float playerNameTime = 2f; + + public static LoadingScreen instance; + + private void Awake() + { + instance = this; + } + + public void StartLoading(bool privateGame = false) + { + StopAllCoroutines(); + matchFoundSystem.Stop(); + for (int i = 0; i < playerNamesSystem.Length; i++) + { + playerNamesSystem[i].Stop(); + } + searchingSystem.Play(); + m_SearchingText.text = GetSearchingString(privateGame); + } + + private string GetSearchingString(bool privGame) + { + if (privGame) + { + return "WAITING FOR FRIEND"; + } + return "SEARCHING"; + } + + private IEnumerator IDoLoading() + { + SoundPlayerStatic.Instance.PlayMatchFound(); + matchFoundSystem.Play(); + yield return new WaitForSeconds(matchFoundTime); + matchFoundSystem.Stop(); + GetComponentInChildren<DisplayMatchPlayerNames>().ShowNames(); + for (int i = 0; i < playerNamesSystem.Length; i++) + { + playerNamesSystem[i].Play(); + } + yield return new WaitForSeconds(playerNameTime); + for (int j = 0; j < playerNamesSystem.Length; j++) + { + playerNamesSystem[j].Stop(); + playerNamesSystem[j].GetComponentInParent<TextMeshProUGUI>().text = ""; + } + gameMode.SetActive(value: true); + } + + public void StopLoading() + { + StopAllCoroutines(); + searchingSystem.Stop(); + StartCoroutine(IDoLoading()); + } +} diff --git a/GameCode/LobbyHandler.cs b/GameCode/LobbyHandler.cs new file mode 100644 index 0000000..acf5511 --- /dev/null +++ b/GameCode/LobbyHandler.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class LobbyHandler : MonoBehaviour +{ + private void Start() + { + } +} diff --git a/GameCode/Looper.cs b/GameCode/Looper.cs new file mode 100644 index 0000000..ec7f469 --- /dev/null +++ b/GameCode/Looper.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +public class Looper : MonoBehaviour +{ + private float sinceLoop = 1f; + + private Camera mainCam; + + private TrailRenderer trail; + + private RayCastTrail rayTrail; + + private int loops = 3; + + private void Awake() + { + mainCam = MainCam.instance.transform.GetComponent<Camera>(); + trail = base.transform.root.GetComponentInChildren<TrailRenderer>(); + rayTrail = GetComponentInParent<RayCastTrail>(); + } + + private void Update() + { + if (loops <= 0 && sinceLoop > 0.3f) + { + Object.Destroy(this); + } + Vector3 vector = mainCam.WorldToScreenPoint(base.transform.position); + vector.x /= Screen.width; + vector.y /= Screen.height; + vector = new Vector3(Mathf.Clamp(vector.x, 0f, 1f), Mathf.Clamp(vector.y, 0f, 1f), vector.z); + if ((vector.x == 0f || vector.x == 1f || vector.y == 1f || vector.y == 0f) && sinceLoop > 0.1f) + { + if (vector.x == 0f) + { + vector.x = 1f; + } + else if (vector.x == 1f) + { + vector.x = 0f; + } + if (vector.y == 0f) + { + vector.y = 1f; + } + else if (vector.y == 1f) + { + vector.y = 0f; + } + vector.x *= Screen.width; + vector.y *= Screen.height; + base.transform.root.position = mainCam.ScreenToWorldPoint(vector); + rayTrail.MoveRay(); + for (int i = 0; i < trail.positionCount; i++) + { + trail.SetPosition(i, base.transform.position); + } + sinceLoop = 0f; + loops--; + } + else + { + sinceLoop += TimeHandler.deltaTime; + } + } +} diff --git a/GameCode/LowFrameRate.cs b/GameCode/LowFrameRate.cs new file mode 100644 index 0000000..1c86586 --- /dev/null +++ b/GameCode/LowFrameRate.cs @@ -0,0 +1,30 @@ +using Photon.Pun; +using UnityEngine; + +public class LowFrameRate : MonoBehaviourPunCallbacks +{ + public enum SlowWhat + { + Both, + Server, + Client + } + + public SlowWhat slowWhat = SlowWhat.Server; + + public int targetFrameRate = 10; + + public override void OnJoinedRoom() + { + base.OnJoinedRoom(); + if (slowWhat == SlowWhat.Both || (PhotonNetwork.IsMasterClient && slowWhat == SlowWhat.Server) || (!PhotonNetwork.IsMasterClient && slowWhat == SlowWhat.Client)) + { + Application.targetFrameRate = targetFrameRate; + QualitySettings.vSyncCount = 0; + } + else + { + Application.targetFrameRate = 100; + } + } +} diff --git a/GameCode/LowerScreenshakePerPlayer.cs b/GameCode/LowerScreenshakePerPlayer.cs new file mode 100644 index 0000000..77d6814 --- /dev/null +++ b/GameCode/LowerScreenshakePerPlayer.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class LowerScreenshakePerPlayer : MonoBehaviour +{ + public Screenshaker shake; + + private void Update() + { + if (PlayerManager.instance.players.Count > 2) + { + shake.shakeforce *= 0.5f; + Object.Destroy(this); + } + } +} diff --git a/GameCode/MainCam.cs b/GameCode/MainCam.cs new file mode 100644 index 0000000..fc79454 --- /dev/null +++ b/GameCode/MainCam.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class MainCam : MonoBehaviour +{ + public static MainCam instance; + + public Camera cam; + + private void Awake() + { + cam = GetComponent<Camera>(); + instance = this; + } +} diff --git a/GameCode/MainMenuHandler.cs b/GameCode/MainMenuHandler.cs new file mode 100644 index 0000000..2be5e82 --- /dev/null +++ b/GameCode/MainMenuHandler.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class MainMenuHandler : MonoBehaviour +{ + public static MainMenuHandler instance; + + public bool isOpen = true; + + private void Awake() + { + instance = this; + } + + public void Close() + { + isOpen = false; + base.transform.GetChild(0).gameObject.SetActive(value: false); + } + + public void Open() + { + isOpen = true; + base.transform.GetChild(0).gameObject.SetActive(value: true); + } +} diff --git a/GameCode/Map.cs b/GameCode/Map.cs new file mode 100644 index 0000000..c5a6c94 --- /dev/null +++ b/GameCode/Map.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class Map : MonoBehaviour +{ + public bool wasSpawned; + + public float size = 15f; + + public bool hasEntered; + + internal int levelID; + + internal int missingObjects; + + private float counter; + + private int readyForFrames; + + private bool hasCalledReady; + + public Rigidbody2D[] allRigs; + + private SpawnPoint[] spawnPoints; + + public Action mapIsReadyAction; + + public Action mapIsReadyEarlyAction; + + public Action mapMovingOutAction; + + internal bool hasRope; + + internal bool LoadedForAll() + { + return MapManager.instance.otherPlayersMostRecentlyLoadedLevel == levelID; + } + + private void Awake() + { + if (!GameManager.instance || !GameManager.instance.isPlaying) + { + GM_Test componentInChildren = GameManager.instance.transform.root.GetComponentInChildren<GM_Test>(includeInactive: true); + componentInChildren.gameObject.SetActive(value: true); + componentInChildren.testMap = true; + MapManager.instance.isTestingMap = true; + componentInChildren.transform.root.Find("UI/UI_MainMenu").gameObject.SetActive(value: false); + hasEntered = true; + } + } + + private void Update() + { + counter += Time.deltaTime; + if (!hasCalledReady && ((PhotonNetwork.OfflineMode && counter > 1f && hasEntered) || (hasEntered && LoadedForAll()))) + { + if (missingObjects <= 0) + { + readyForFrames++; + } + if (readyForFrames > 2) + { + StartCoroutine(StartMatch()); + } + } + } + + public void MapMoveOut() + { + mapMovingOutAction?.Invoke(); + } + + internal Vector3 GetRandomSpawnPos() + { + if (spawnPoints == null) + { + spawnPoints = GetComponentsInChildren<SpawnPoint>(); + } + return spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)].transform.position; + } + + private IEnumerator StartMatch() + { + hasCalledReady = true; + mapIsReadyEarlyAction?.Invoke(); + yield return new WaitForSecondsRealtime(0f); + allRigs = GetComponentsInChildren<Rigidbody2D>(); + mapIsReadyAction?.Invoke(); + } + + private void Start() + { + if (!PhotonNetwork.OfflineMode) + { + MapManager.instance.ReportMapLoaded(levelID); + } + if (MapManager.instance.isTestingMap) + { + wasSpawned = true; + } + if (!wasSpawned) + { + MapManager.instance.UnloadScene(base.gameObject.scene); + } + SpriteRenderer[] componentsInChildren = GetComponentsInChildren<SpriteRenderer>(includeInactive: true); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if ((double)componentsInChildren[i].color.a < 0.5) + { + continue; + } + componentsInChildren[i].transform.position = new Vector3(componentsInChildren[i].transform.position.x, componentsInChildren[i].transform.position.y, -3f); + if (!(componentsInChildren[i].gameObject.tag == "NoMask")) + { + componentsInChildren[i].color = new Color(11f / 51f, 11f / 51f, 11f / 51f); + if (!componentsInChildren[i].GetComponent<SpriteMask>()) + { + componentsInChildren[i].gameObject.AddComponent<SpriteMask>().sprite = componentsInChildren[i].sprite; + } + } + } + SpriteMask[] componentsInChildren2 = GetComponentsInChildren<SpriteMask>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + if (!(componentsInChildren2[j].gameObject.tag == "NoMask")) + { + componentsInChildren2[j].isCustomRangeActive = true; + componentsInChildren2[j].frontSortingLayerID = SortingLayer.NameToID("MapParticle"); + componentsInChildren2[j].frontSortingOrder = 1; + componentsInChildren2[j].backSortingLayerID = SortingLayer.NameToID("MapParticle"); + componentsInChildren2[j].backSortingOrder = 0; + } + } + } +} diff --git a/GameCode/MapManager.cs b/GameCode/MapManager.cs new file mode 100644 index 0000000..ace02f0 --- /dev/null +++ b/GameCode/MapManager.cs @@ -0,0 +1,200 @@ +using System.Collections; +using Photon.Pun; +using UnityEngine; +using UnityEngine.SceneManagement; + +public class MapManager : MonoBehaviour +{ + [SerializeField] + public string[] levels; + + public int currentLevelID; + + public static MapManager instance; + + [HideInInspector] + public bool isTestingMap; + + public MapWrapper currentMap; + + private PhotonView view; + + internal int otherPlayersMostRecentlyLoadedLevel = -1; + + public string forceMap = ""; + + private bool callInNextMap; + + private void Awake() + { + instance = this; + view = GetComponent<PhotonView>(); + } + + internal void ReportMapLoaded(int levelID) + { + view.RPC("RPCA_ReportMapLoaded", RpcTarget.Others, levelID); + } + + [PunRPC] + internal void RPCA_ReportMapLoaded(int levelID) + { + otherPlayersMostRecentlyLoadedLevel = levelID; + } + + private string GetRandomMap() + { + if (forceMap != "") + { + return forceMap; + } + int num = Random.Range(0, levels.Length); + while (num == currentLevelID && levels.Length > 1) + { + num = Random.Range(0, levels.Length); + } + return levels[num]; + } + + public void LoadNextLevel(bool callInImidetly = false, bool forceLoad = false) + { + if (forceLoad || PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode) + { + view.RPC("RPCA_SetCallInNextMap", RpcTarget.All, callInImidetly); + view.RPC("RPCA_LoadLevel", RpcTarget.All, GetRandomMap()); + } + } + + [PunRPC] + private void RPCA_SetCallInNextMap(bool toSet) + { + callInNextMap = toSet; + } + + public void LoadLevelFromID(int ID, bool onlyMaster = false, bool callInImidetly = false) + { + if (!(!PhotonNetwork.IsMasterClient && onlyMaster)) + { + callInNextMap = callInImidetly; + RPCA_LoadLevel(levels[ID]); + } + } + + [PunRPC] + public void RPCA_CallInNewMapAndMovePlayers(int mapID) + { + StartCoroutine(WaitForMapToBeLoaded(mapID)); + } + + private IEnumerator WaitForMapToBeLoaded(int mapID) + { + while (currentLevelID != mapID) + { + yield return null; + } + Debug.Log("CALL IN NEW MAP AND MOVE PLAYERS"); + if (currentMap != null) + { + MapTransition.instance.Enter(currentMap.Map); + } + MapTransition.instance.ClearObjects(); + PlayerManager.instance.RPCA_MovePlayers(); + } + + public void CallInNewMapAndMovePlayers(int mapID) + { + if (PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode) + { + view.RPC("RPCA_CallInNewMapAndMovePlayers", RpcTarget.All, mapID); + } + } + + [PunRPC] + public void RPCA_CallInNewMap() + { + if (currentMap != null) + { + MapTransition.instance.Enter(currentMap.Map); + } + MapTransition.instance.ClearObjects(); + } + + public void CallInNewMap() + { + if (PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode) + { + view.RPC("RPCA_CallInNewMap", RpcTarget.All); + } + } + + public SpawnPoint[] GetSpawnPoints() + { + return currentMap.Map.GetComponentsInChildren<SpawnPoint>(); + } + + private void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode) + { + Map map = null; + for (int i = 0; i < scene.GetRootGameObjects().Length; i++) + { + map = scene.GetRootGameObjects()[i].GetComponent<Map>(); + if ((bool)map) + { + break; + } + } + if (!map) + { + Debug.LogError("NO MAP WAS FOUND WHEN LOADING NEW MAP"); + } + map.wasSpawned = true; + SceneManager.sceneLoaded -= OnLevelFinishedLoading; + if (currentMap != null) + { + StartCoroutine(UnloadAfterSeconds(currentMap.Scene)); + MapTransition.instance.Exit(currentMap.Map); + } + MapTransition.instance.SetStartPos(map); + map.levelID = currentLevelID; + currentMap = new MapWrapper(map, scene); + currentLevelID = GetIDFromScene(scene); + if (callInNextMap) + { + CallInNewMap(); + callInNextMap = false; + } + Debug.Log("FINISHED LOADING SCENE"); + } + + private int GetIDFromScene(Scene scene) + { + int result = -1; + for (int i = 0; i < levels.Length; i++) + { + if (levels[i] == scene.name) + { + result = i; + } + } + return result; + } + + [PunRPC] + public void RPCA_LoadLevel(string sceneName) + { + Debug.Log("LOADING SCENE"); + SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); + SceneManager.sceneLoaded += OnLevelFinishedLoading; + } + + private IEnumerator UnloadAfterSeconds(Scene scene) + { + yield return new WaitForSecondsRealtime(2f); + SceneManager.UnloadSceneAsync(scene); + } + + public void UnloadScene(Scene scene) + { + SceneManager.UnloadSceneAsync(scene); + } +} diff --git a/GameCode/MapObjet_Rope.cs b/GameCode/MapObjet_Rope.cs new file mode 100644 index 0000000..463a1ec --- /dev/null +++ b/GameCode/MapObjet_Rope.cs @@ -0,0 +1,274 @@ +using System; +using System.Collections; +using Sonigon; +using UnityEngine; + +public class MapObjet_Rope : MonoBehaviour +{ + public enum JointType + { + spring, + Distance + } + + [Header("Sound")] + public bool soundRopePlay; + + public SoundEvent soundRopeLoop; + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + private bool soundIsPlaying; + + private bool soundInitialized; + + private float soundRopeLengthCurrent; + + private float soundRopeLengthLast; + + private float soundRopeLengthVelocity; + + [Header("Settings")] + public JointType jointType; + + private Map map; + + private LineRenderer lineRenderer; + + private AnchoredJoint2D joint; + + private Vector3 lastPos; + + private Vector3 vel1; + + private Vector3 vel2; + + private Vector3 postSnapPos1; + + private Vector3 postSnapPos2; + + private float sinceBreak; + + private void Start() + { + map = GetComponentInParent<Map>(); + map.hasRope = true; + lineRenderer = GetComponent<LineRenderer>(); + Map obj = map; + obj.mapIsReadyAction = (Action)Delegate.Combine(obj.mapIsReadyAction, new Action(Go)); + Map obj2 = map; + obj2.mapMovingOutAction = (Action)Delegate.Combine(obj2.mapMovingOutAction, new Action(Leave)); + } + + private void Leave() + { + if ((bool)joint) + { + UnityEngine.Object.Destroy(joint); + } + } + + public void Go() + { + StartCoroutine(IGo()); + } + + private IEnumerator IGo() + { + yield return new WaitForSeconds(0f); + Rigidbody2D rigidbody2D = null; + Rigidbody2D rigidbody2D2 = null; + for (int i = 0; i < map.allRigs.Length; i++) + { + Collider2D component = map.allRigs[i].GetComponent<Collider2D>(); + if ((bool)component) + { + if (component.OverlapPoint(base.transform.position)) + { + rigidbody2D = map.allRigs[i]; + } + if (component.OverlapPoint(base.transform.GetChild(0).position)) + { + rigidbody2D2 = map.allRigs[i]; + } + } + } + if ((bool)rigidbody2D) + { + AddJoint(rigidbody2D); + if ((bool)rigidbody2D2) + { + joint.connectedBody = rigidbody2D2; + joint.anchor = rigidbody2D.transform.InverseTransformPoint(base.transform.position); + joint.connectedAnchor = rigidbody2D2.transform.InverseTransformPoint(base.transform.GetChild(0).position); + } + else + { + joint.anchor = rigidbody2D.transform.InverseTransformPoint(base.transform.position); + joint.connectedAnchor = base.transform.GetChild(0).position; + } + joint.enableCollision = true; + } + else if ((bool)rigidbody2D2) + { + AddJoint(rigidbody2D2); + joint.anchor = rigidbody2D2.transform.InverseTransformPoint(base.transform.GetChild(0).position); + joint.connectedAnchor = base.transform.position; + joint.enableCollision = true; + } + else + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + private void AddJoint(Rigidbody2D target) + { + switch (jointType) + { + case JointType.spring: + joint = target.gameObject.AddComponent<SpringJoint2D>(); + break; + case JointType.Distance: + joint = target.gameObject.AddComponent<DistanceJoint2D>(); + break; + } + } + + private void OnDrawGizmos() + { + if (!joint) + { + if (!lineRenderer) + { + lineRenderer = GetComponent<LineRenderer>(); + } + lineRenderer.SetPosition(0, base.transform.position); + lineRenderer.SetPosition(1, base.transform.GetChild(0).position); + if (Event.current.shift) + { + base.transform.GetChild(0).position = lastPos; + } + lastPos = base.transform.GetChild(0).position; + } + } + + private void OnDestroy() + { + soundIsPlaying = false; + soundInitialized = false; + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + + private void OnDisable() + { + soundIsPlaying = false; + soundInitialized = false; + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + + private void Update() + { + if ((bool)joint) + { + if ((bool)joint.attachedRigidbody && !joint.attachedRigidbody.gameObject.activeSelf) + { + postSnapPos1 = lineRenderer.GetPosition(0); + } + if ((bool)joint.connectedBody && !joint.connectedBody.gameObject.activeSelf) + { + postSnapPos2 = lineRenderer.GetPosition(1); + } + if (((bool)joint.attachedRigidbody && !joint.attachedRigidbody.gameObject.activeSelf) || ((bool)joint.connectedBody && !joint.connectedBody.gameObject.activeSelf)) + { + sinceBreak += Time.deltaTime; + if (Vector2.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)) < 0.2f) + { + if (soundIsPlaying) + { + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + lineRenderer.enabled = false; + return; + } + } + if ((bool)joint.attachedRigidbody && joint.attachedRigidbody.gameObject.activeSelf) + { + vel1 = joint.attachedRigidbody.velocity * 1.5f; + } + if ((bool)joint.attachedRigidbody && !joint.attachedRigidbody.gameObject.activeSelf) + { + vel1 = FRILerp.Lerp(vel1, (lineRenderer.GetPosition(1) - lineRenderer.GetPosition(0)) * 15f * Mathf.Clamp(sinceBreak * 2f, 0f, 1f), 10f); + postSnapPos1 += vel1 * Time.deltaTime; + } + if (postSnapPos1 == Vector3.zero) + { + lineRenderer.SetPosition(0, joint.attachedRigidbody.transform.TransformPoint(joint.anchor)); + } + else + { + lineRenderer.SetPosition(0, postSnapPos1); + } + if ((bool)joint.connectedBody) + { + if (!joint.connectedBody.gameObject.activeSelf) + { + vel2 = FRILerp.Lerp(vel2, (lineRenderer.GetPosition(0) - lineRenderer.GetPosition(1)) * 15f * Mathf.Clamp(sinceBreak * 2f, 0f, 1f), 10f); + postSnapPos2 += vel2 * Time.deltaTime; + } + else + { + vel2 = joint.connectedBody.velocity * 1.5f; + } + if (postSnapPos2 == Vector3.zero) + { + lineRenderer.SetPosition(1, joint.connectedBody.transform.TransformPoint(joint.connectedAnchor)); + } + else + { + lineRenderer.SetPosition(1, postSnapPos2); + } + } + else if (postSnapPos2 == Vector3.zero) + { + lineRenderer.SetPosition(1, joint.connectedAnchor); + } + else + { + lineRenderer.SetPosition(1, postSnapPos2); + } + } + else + { + lineRenderer.SetPosition(0, Vector3.up * 200f); + lineRenderer.SetPosition(1, Vector3.up * 200f); + } + if (!soundRopePlay || lineRenderer.positionCount < 1) + { + return; + } + if (!soundInitialized) + { + soundInitialized = true; + soundRopeLengthLast = Vector3.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)); + } + soundRopeLengthCurrent = Vector3.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)); + soundRopeLengthVelocity = Mathf.Abs(soundRopeLengthLast - soundRopeLengthCurrent); + soundParameterIntensity.intensity = soundRopeLengthVelocity; + if (soundRopeLengthVelocity > 0.03f) + { + if (!soundIsPlaying) + { + soundIsPlaying = true; + SoundManager.Instance.PlayAtPosition(soundRopeLoop, SoundManager.Instance.transform, base.transform, soundParameterIntensity); + } + } + else if (soundIsPlaying) + { + soundIsPlaying = false; + soundInitialized = false; + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + soundRopeLengthLast = Vector3.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)); + } +} diff --git a/GameCode/MapTransition.cs b/GameCode/MapTransition.cs new file mode 100644 index 0000000..bb238da --- /dev/null +++ b/GameCode/MapTransition.cs @@ -0,0 +1,145 @@ +using System.Collections; +using SoundImplementation; +using UnityEngine; +using UnityEngine.Events; + +public class MapTransition : MonoBehaviour +{ + [Header("Settings")] + public UnityEvent switchMapEvent; + + public AnimationCurve curve; + + public AnimationCurve gravityCurve; + + public static MapTransition instance; + + private const float mapPadding = 90f; + + public static bool isTransitioning; + + private void Awake() + { + instance = this; + } + + private void Start() + { + } + + public void SetStartPos(Map map) + { + map.transform.position = Vector3.right * 90f; + } + + public void Enter(Map map) + { + MoveObject(map.gameObject, Vector3.zero); + StartCoroutine(DelayEvent(0.1f)); + SoundPlayerStatic.Instance.PlayLevelTransitionIn(); + SoundMusicManager.Instance.PlayIngame(isCard: false); + } + + public void Exit(Map map) + { + SoundPlayerStatic.Instance.PlayLevelTransitionOut(); + map.MapMoveOut(); + MoveObject(map.gameObject, Vector3.right * -90f); + StartCoroutine(ClearObjectsAfterSeconds(1f)); + } + + private void MoveObject(GameObject target, Vector3 targetPos) + { + for (int i = 0; i < target.transform.childCount; i++) + { + Toggle(target.transform.GetChild(i).gameObject, enabled: false); + StartCoroutine(Move(target.transform.GetChild(i).gameObject, targetPos - target.transform.position, (i == 0) ? target.GetComponent<Map>() : null)); + } + } + + private void Toggle(GameObject obj, bool enabled) + { + Rigidbody2D component = obj.GetComponent<Rigidbody2D>(); + if ((bool)component) + { + component.simulated = enabled; + if (enabled) + { + StartCoroutine(LerpDrag(component)); + } + } + Collider2D component2 = obj.GetComponent<Collider2D>(); + if ((bool)component2) + { + component2.enabled = enabled; + } + CodeAnimation component3 = obj.GetComponent<CodeAnimation>(); + if ((bool)component3) + { + component3.enabled = enabled; + } + } + + private IEnumerator DelayEvent(float delay) + { + yield return new WaitForSecondsRealtime(delay); + switchMapEvent.Invoke(); + } + + private IEnumerator Move(GameObject target, Vector3 distance, Map targetMap = null) + { + isTransitioning = true; + float maxRandomDelay = 0.25f; + float randomDelay = Random.Range(0f, maxRandomDelay); + yield return new WaitForSecondsRealtime(randomDelay); + Vector3 targetStartPos = target.transform.position; + float t = curve.keys[curve.keys.Length - 1].time; + float c = 0f; + while (c < t) + { + c += Time.unscaledDeltaTime; + target.transform.position = targetStartPos + distance * curve.Evaluate(c); + yield return null; + } + target.transform.position = targetStartPos + distance; + Toggle(target, enabled: true); + yield return new WaitForSecondsRealtime(maxRandomDelay - randomDelay); + isTransitioning = false; + if ((bool)targetMap) + { + targetMap.hasEntered = true; + } + } + + private IEnumerator LerpDrag(Rigidbody2D target) + { + target.gravityScale = 0f; + float t = gravityCurve.keys[gravityCurve.keys.Length - 1].time; + float c = 0f; + while (c < t && (bool)target) + { + target.gravityScale = gravityCurve.Evaluate(c); + c += Time.unscaledDeltaTime; + yield return null; + } + if ((bool)target) + { + target.gravityScale = 1f; + } + } + + private IEnumerator ClearObjectsAfterSeconds(float time) + { + yield return new WaitForSecondsRealtime(time); + ClearObjects(); + } + + public void ClearObjects() + { + RemoveAfterSeconds[] array = Object.FindObjectsOfType<RemoveAfterSeconds>(); + for (int i = 0; i < array.Length; i++) + { + Object.Destroy(array[i].gameObject); + } + } +} diff --git a/GameCode/MapWrapper.cs b/GameCode/MapWrapper.cs new file mode 100644 index 0000000..9a6fe7d --- /dev/null +++ b/GameCode/MapWrapper.cs @@ -0,0 +1,14 @@ +using UnityEngine.SceneManagement; + +public class MapWrapper +{ + public Map Map { get; private set; } + + public Scene Scene { get; private set; } + + public MapWrapper(Map map, Scene scene) + { + Map = map; + Scene = scene; + } +} diff --git a/GameCode/MenuControllerEvent.cs b/GameCode/MenuControllerEvent.cs new file mode 100644 index 0000000..edd60c6 --- /dev/null +++ b/GameCode/MenuControllerEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class MenuControllerEvent : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/MenuControllerHandler.cs b/GameCode/MenuControllerHandler.cs new file mode 100644 index 0000000..4f399bd --- /dev/null +++ b/GameCode/MenuControllerHandler.cs @@ -0,0 +1,75 @@ +using System; +using InControl; +using UnityEngine; +using UnityEngine.EventSystems; + +public class MenuControllerHandler : MonoBehaviour +{ + public enum MenuControl + { + Controller, + Mouse, + Unassigned + } + + public static MenuControl menuControl; + + public MenuControl lastMenuControl; + + public Action<MenuControl> switchControlAction; + + public static MenuControllerHandler instance; + + private void Awake() + { + instance = this; + } + + private void Start() + { + Switch(); + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.Mouse0)) + { + menuControl = MenuControl.Mouse; + } + if (Input.GetKeyDown(KeyCode.Mouse1)) + { + menuControl = MenuControl.Mouse; + } + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + InputDevice inputDevice = InputManager.ActiveDevices[i]; + if (!inputDevice.AnyButtonWasPressed && !(Mathf.Abs(inputDevice.LeftStick.Value.y) > 0.1f)) + { + continue; + } + menuControl = MenuControl.Controller; + if (EventSystem.current.currentSelectedGameObject.activeInHierarchy) + { + continue; + } + ListMenuButton[] array = UnityEngine.Object.FindObjectsOfType<ListMenuButton>(); + for (int j = 0; j < array.Length; j++) + { + if (array[j].enabled) + { + ListMenu.instance.SelectButton(array[j]); + } + } + } + if (menuControl != lastMenuControl) + { + Switch(); + } + lastMenuControl = menuControl; + } + + private void Switch() + { + switchControlAction?.Invoke(menuControl); + } +} diff --git a/GameCode/MenuControllerToggler.cs b/GameCode/MenuControllerToggler.cs new file mode 100644 index 0000000..465cf16 --- /dev/null +++ b/GameCode/MenuControllerToggler.cs @@ -0,0 +1,75 @@ +using System; +using UnityEngine; + +public class MenuControllerToggler : MonoBehaviour +{ + public bool creatorControl; + + public GameObject controllerObject; + + public GameObject keyboardObject; + + private CharacterCreator creator; + + private void Awake() + { + CharacterCreator componentInParent = GetComponentInParent<CharacterCreator>(); + if (componentInParent.playerActions == null) + { + if (creatorControl) + { + componentInParent.SwitchAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(componentInParent.SwitchAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + Switch(GetComponentInParent<CharacterCreator>().currentControl); + } + else + { + MenuControllerHandler instance = MenuControllerHandler.instance; + instance.switchControlAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(instance.switchControlAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + Switch(MenuControllerHandler.menuControl); + } + } + } + + private void OnEnable() + { + CharacterCreator componentInParent = GetComponentInParent<CharacterCreator>(); + if (componentInParent.playerActions != null) + { + componentInParent.SwitchAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(componentInParent.SwitchAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + if (componentInParent.inputType == GeneralInput.InputType.Controller) + { + Switch(MenuControllerHandler.MenuControl.Controller); + } + if (componentInParent.inputType == GeneralInput.InputType.Keyboard) + { + Switch(MenuControllerHandler.MenuControl.Mouse); + } + } + } + + private void Switch(MenuControllerHandler.MenuControl control) + { + if (control == MenuControllerHandler.MenuControl.Controller) + { + if ((bool)controllerObject) + { + controllerObject.SetActive(value: true); + } + if ((bool)keyboardObject) + { + keyboardObject.SetActive(value: false); + } + } + else + { + if ((bool)controllerObject) + { + controllerObject.SetActive(value: false); + } + if ((bool)keyboardObject) + { + keyboardObject.SetActive(value: true); + } + } + } +} diff --git a/GameCode/MenuEffects.cs b/GameCode/MenuEffects.cs new file mode 100644 index 0000000..5345984 --- /dev/null +++ b/GameCode/MenuEffects.cs @@ -0,0 +1,51 @@ +using System.Collections; +using TMPro; +using UnityEngine; + +public class MenuEffects : MonoBehaviour +{ + public static MenuEffects instance; + + public Color nopeColor; + + private void Awake() + { + instance = this; + } + + public void ShakeObject(GameObject objectToShake, Vector3 defaultPos, float amount, float time) + { + StartCoroutine(DoShakeObject(objectToShake, defaultPos, amount, time)); + } + + private IEnumerator DoShakeObject(GameObject objectToShake, Vector3 defaultPos, float amount, float time) + { + float c = 0f; + while (c < time) + { + Vector3 localPosition = defaultPos + Random.onUnitSphere * amount * ((time - c) / time); + localPosition.z = defaultPos.z; + objectToShake.transform.localPosition = localPosition; + c += Time.unscaledDeltaTime; + yield return null; + } + objectToShake.transform.localPosition = defaultPos; + } + + public void BlinkInColor(TextMeshProUGUI textToBlink, Color blinkColor, Color defaultColor, float seconds) + { + StartCoroutine(DoTextColorBlink(textToBlink, blinkColor, defaultColor, seconds)); + } + + private IEnumerator DoTextColorBlink(TextMeshProUGUI textToBlink, Color blinkColor, Color defaultColor, float seconds) + { + float c = 0f; + while (c < seconds) + { + textToBlink.color = blinkColor; + c += Time.unscaledDeltaTime; + yield return null; + } + textToBlink.color = defaultColor; + } +} diff --git a/GameCode/MoveForward.cs b/GameCode/MoveForward.cs new file mode 100644 index 0000000..4171a26 --- /dev/null +++ b/GameCode/MoveForward.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class MoveForward : MonoBehaviour +{ + public float amount = 3f; + + private void Start() + { + base.transform.position += Vector3.forward * amount; + } +} diff --git a/GameCode/MoveSequence.cs b/GameCode/MoveSequence.cs new file mode 100644 index 0000000..1437614 --- /dev/null +++ b/GameCode/MoveSequence.cs @@ -0,0 +1,99 @@ +using Photon.Pun; +using UnityEngine; + +public class MoveSequence : MonoBehaviour +{ + private int targetID; + + public Vector2[] positions; + + public float drag = 1f; + + public float spring = 1f; + + public float cap = 1f; + + public float threshold = 1f; + + public float timeAtPos; + + private float counter; + + private Vector2 startPos; + + private Vector2 velocity; + + private Rigidbody2D rig; + + private Map map; + + private string myKey; + + private void Start() + { + base.gameObject.layer = 17; + startPos = base.transform.localPosition; + rig = GetComponent<Rigidbody2D>(); + map = GetComponentInParent<Map>(); + myKey = "MapObect " + GetComponentInParent<Map>().levelID + " " + base.transform.GetSiblingIndex(); + MapManager.instance.GetComponent<ChildRPC>().childRPCsInt.Add(myKey, RPCA_SetTargetID); + } + + private void OnDestroy() + { + if ((bool)MapManager.instance) + { + MapManager.instance.GetComponent<ChildRPC>().childRPCsInt.Remove(myKey); + } + } + + private void OnDrawGizmos() + { + for (int i = 0; i < positions.Length; i++) + { + Gizmos.DrawSphere((Vector2)base.transform.position + positions[i], 0.25f + (float)i * 0.15f); + } + } + + private void Update() + { + if (MapTransition.isTransitioning || !map.hasEntered) + { + return; + } + Vector2 vector = positions[targetID] + startPos; + Vector2 vector2 = vector - (Vector2)base.transform.position; + vector2 = Vector3.ClampMagnitude(vector2, cap); + if ((bool)rig) + { + rig.gravityScale = 0f; + rig.AddForce(vector2 * spring * CappedDeltaTime.time * rig.mass); + } + else + { + velocity += vector2 * spring * CappedDeltaTime.time; + velocity -= velocity * drag * CappedDeltaTime.time; + base.transform.position += (Vector3)velocity * TimeHandler.deltaTime; + } + if (!PhotonNetwork.IsMasterClient || !(Vector2.Distance(base.transform.position, vector) < threshold)) + { + return; + } + counter += TimeHandler.deltaTime; + if (counter > timeAtPos) + { + targetID++; + if (targetID >= positions.Length) + { + targetID = 0; + } + MapManager.instance.GetComponent<ChildRPC>().CallFunction(myKey, targetID); + counter = 0f; + } + } + + private void RPCA_SetTargetID(int setValue) + { + targetID = setValue; + } +} diff --git a/GameCode/MoveTransform.cs b/GameCode/MoveTransform.cs new file mode 100644 index 0000000..e6b8d0f --- /dev/null +++ b/GameCode/MoveTransform.cs @@ -0,0 +1,78 @@ +using UnityEngine; + +public class MoveTransform : MonoBehaviour +{ + public float gravity = 30f; + + public float drag; + + public float dragMinSpeed = 1f; + + public float velocitySpread; + + public float spread; + + public Vector3 localForce; + + public Vector3 worldForce; + + public float multiplier = 1f; + + public Vector3 velocity; + + [HideInInspector] + public float distanceTravelled; + + [HideInInspector] + public bool DontRunStart; + + public float selectedSpread; + + public bool allowStop; + + public int simulateGravity; + + private int randomSeed; + + [HideInInspector] + internal float simulationSpeed = 1f; + + private void Start() + { + if (!DontRunStart) + { + velocity += base.transform.TransformDirection(localForce) + worldForce; + base.transform.rotation = Quaternion.LookRotation(velocity, Vector3.forward); + if (spread != 0f) + { + velocity += base.transform.up * selectedSpread; + } + } + } + + private void Update() + { + float num = Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.02f); + float deltaTime = TimeHandler.deltaTime; + num *= simulationSpeed; + deltaTime *= simulationSpeed; + if (simulateGravity == 0) + { + velocity += gravity * Vector3.down * deltaTime * multiplier; + } + if ((velocity.magnitude > 2f || allowStop) && velocity.magnitude > dragMinSpeed) + { + velocity -= velocity * Mathf.Clamp(drag * num * Mathf.Clamp(multiplier, 0f, 1f), 0f, 1f); + } + base.transform.position += velocity * deltaTime * multiplier; + distanceTravelled += velocity.magnitude * deltaTime * multiplier; + base.transform.rotation = Quaternion.LookRotation(velocity, Vector3.forward); + } + + public float GetUpwardsCompensation(Vector2 start, Vector2 end) + { + start.y = 0.5f; + end.y = 0.5f; + return Mathf.Pow(Vector3.Distance(start, end), 2.06f) * gravity / velocity.magnitude * 0.012f; + } +} diff --git a/GameCode/MoveTransformGravity.cs b/GameCode/MoveTransformGravity.cs new file mode 100644 index 0000000..fd822fe --- /dev/null +++ b/GameCode/MoveTransformGravity.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class MoveTransformGravity : MonoBehaviour +{ + public float amount = 1f; + + public float pow = 1.5f; + + private MoveTransform move; + + private float counter; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + } + + private void Update() + { + counter += TimeHandler.deltaTime; + move.velocity += Vector3.down * Mathf.Pow(amount * counter, pow); + } +} diff --git a/GameCode/Movement.cs b/GameCode/Movement.cs new file mode 100644 index 0000000..17d7b11 --- /dev/null +++ b/GameCode/Movement.cs @@ -0,0 +1,137 @@ +using UnityEngine; + +public class Movement : MonoBehaviour +{ + public float jumpForce; + + public float force; + + public float torque; + + public float drag = 1f; + + public float Angulardrag = 1f; + + public ParticleSystem[] jumpPart; + + private GeneralInput input; + + private Rigidbody2D rig; + + private CharacterData data; + + private CharacterStatModifiers stats; + + public Vector2 knockBack; + + private HealthHandler health; + + private Vector3 moveDir; + + private Vector3 idleForce; + + private void Start() + { + rig = GetComponent<Rigidbody2D>(); + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + stats = GetComponent<CharacterStatModifiers>(); + health = GetComponent<HealthHandler>(); + } + + private void FixedUpdate() + { + if (input.direction != Vector3.zero) + { + moveDir = input.direction; + idleForce = Vector3.Lerp(idleForce, moveDir, Time.fixedDeltaTime * 6f); + } + else if (data.isGrounded || data.isWallGrab) + { + idleForce = Vector3.Lerp(idleForce, Vector3.zero, 15f * Time.fixedDeltaTime); + } + else + { + idleForce = Vector3.Lerp(idleForce, Vector3.zero, 3f * Time.fixedDeltaTime); + } + if (input.direction == Vector3.zero) + { + moveDir = idleForce; + } + if (data.isGrounded || data.isWallGrab) + { + knockBack = Vector3.Lerp(knockBack, Vector3.zero, 10f * Time.fixedDeltaTime); + } + else + { + knockBack = Vector3.Lerp(knockBack, Vector3.zero, 7f * Time.fixedDeltaTime); + } + rig.AddForce(knockBack * 0.1f * rig.mass, ForceMode2D.Force); + if (moveDir.y > 0f) + { + moveDir.y = 0f; + } + rig.AddForce(-rig.velocity * 0.01f * drag * rig.mass, ForceMode2D.Force); + rig.AddTorque((0f - rig.angularVelocity) * 0.01f * Angulardrag * rig.mass, ForceMode2D.Force); + if (input.jumpIsPressed) + { + rig.AddForce(Vector2.up * 20f * rig.mass, ForceMode2D.Force); + } + rig.AddForce(moveDir * force * (1f - stats.GetSlow()) * rig.mass, ForceMode2D.Force); + } + + private void Update() + { + if (input.jumpWasPressed) + { + Jump(); + } + if (data.isGrounded && data.sinceJump > 0.2f) + { + data.currentJumps = data.jumps; + } + } + + private void Jump() + { + if (data.sinceJump < 0.15f) + { + return; + } + Vector3 vector = Vector3.up; + Vector3 vector2 = data.groundPos; + if (data.sinceGrounded < 0.1f) + { + if (data.sinceGrounded > 0.05f) + { + vector2 = base.transform.position; + } + data.currentJumps = data.jumps; + } + else if (data.sinceWallGrab < 0.1f) + { + vector = Vector2.up + data.wallNormal; + vector2 = data.wallPos; + data.currentJumps = data.jumps; + } + else + { + if (data.currentJumps <= 0) + { + return; + } + vector2 = base.transform.position; + } + data.currentJumps--; + rig.velocity = new Vector3(rig.velocity.x, 0f); + health.TakeForce(Vector2.up * jumpForce * 1f * (1f - stats.GetSlow()) * rig.mass); + data.sinceJump = 0f; + data.sinceGrounded = 0f; + for (int i = 0; i < jumpPart.Length; i++) + { + jumpPart[i].transform.position = new Vector3(vector2.x, vector2.y, 5f) - vector * 0f; + jumpPart[i].transform.rotation = Quaternion.LookRotation(rig.velocity); + jumpPart[i].Play(); + } + } +} diff --git a/GameCode/MultiOptions.cs b/GameCode/MultiOptions.cs new file mode 100644 index 0000000..82bb9e0 --- /dev/null +++ b/GameCode/MultiOptions.cs @@ -0,0 +1,168 @@ +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; + +public class MultiOptions : MonoBehaviour +{ + private GameObject source; + + private OptionsButton targetButton; + + private void Start() + { + } + + private void Update() + { + if (Input.GetKeyUp(KeyCode.Mouse0) || Input.GetKeyDown(KeyCode.Escape)) + { + Close(); + } + } + + internal void ClickRessButton(MultiOptionsButton buttonPressed) + { + targetButton.SetResolutionAndFullscreen(buttonPressed.currentRess, buttonPressed.currentFull); + Close(); + } + + public void Open(OptionsButton.SettingsTarget settingsTarget, Vector3 pos, OptionsButton askingButton) + { + targetButton = askingButton; + base.transform.position = pos; + source = base.transform.GetChild(0).gameObject; + if (settingsTarget == OptionsButton.SettingsTarget.Resolution) + { + PopulateRess(Screen.resolutions); + } + else + { + PopulateFullScreens(new Optionshandler.FullScreenOption[3] + { + Optionshandler.FullScreenOption.FullScreen, + Optionshandler.FullScreenOption.WindowedFullScreen, + Optionshandler.FullScreenOption.Windowed + }); + } + base.gameObject.SetActive(value: true); + ListMenuButton[] componentsInChildren = base.transform.parent.GetComponentsInChildren<ListMenuButton>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].transform.parent != base.transform) + { + componentsInChildren[i].enabled = false; + } + } + CanvasGroup[] componentsInChildren2 = base.transform.parent.GetComponentsInChildren<CanvasGroup>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + componentsInChildren2[j].alpha = 0.05f; + componentsInChildren2[j].interactable = false; + } + if (MenuControllerHandler.menuControl == MenuControllerHandler.MenuControl.Controller) + { + StartCoroutine(WaitFrame()); + } + else + { + ListMenu.instance.ClearBar(); + } + } + + private IEnumerator WaitFrame() + { + yield return new WaitForSecondsRealtime(0f); + ListMenu.instance.SelectButton(GetComponentInChildren<ListMenuButton>()); + } + + public void Close() + { + base.gameObject.SetActive(value: false); + ListMenuButton[] componentsInChildren = base.transform.parent.GetComponentsInChildren<ListMenuButton>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].transform.parent != base.transform) + { + componentsInChildren[i].enabled = true; + } + } + CanvasGroup[] componentsInChildren2 = base.transform.parent.GetComponentsInChildren<CanvasGroup>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + componentsInChildren2[j].alpha = 1f; + componentsInChildren2[j].interactable = true; + } + if (MenuControllerHandler.menuControl == MenuControllerHandler.MenuControl.Controller) + { + ListMenu.instance.SelectButton(targetButton.transform.GetComponent<ListMenuButton>()); + } + else + { + ListMenu.instance.ClearBar(); + } + } + + private void PopulateRess(Resolution[] allRess) + { + for (int num = base.transform.childCount - 1; num > 0; num--) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + allRess = GetBestResolutions(); + for (int i = 0; i < allRess.Length; i++) + { + GameObject obj = Object.Instantiate(source, source.transform.position, source.transform.rotation, source.transform.parent); + obj.GetComponentInChildren<TextMeshProUGUI>().text = allRess[i].width + " x " + allRess[i].height; + obj.GetComponent<MultiOptionsButton>().currentRess = allRess[i]; + obj.gameObject.SetActive(value: true); + } + } + + private Resolution[] GetBestResolutions() + { + List<Resolution> list = new List<Resolution>(); + for (int i = 0; i < Screen.resolutions.Length; i++) + { + if (IsBestRess(Screen.resolutions[i])) + { + list.Add(Screen.resolutions[i]); + } + } + return list.ToArray(); + } + + private bool IsBestRess(Resolution newRess) + { + for (int i = 0; i < Screen.resolutions.Length; i++) + { + if (Screen.resolutions[i].width == newRess.width && Screen.resolutions[i].height == newRess.height && newRess.refreshRate < Screen.resolutions[i].refreshRate) + { + return false; + } + } + return true; + } + + private void PopulateFullScreens(Optionshandler.FullScreenOption[] allScreens) + { + for (int num = base.transform.childCount - 1; num > 0; num--) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + for (int i = 0; i < allScreens.Length; i++) + { + GameObject gameObject = Object.Instantiate(source, source.transform.position, source.transform.rotation, source.transform.parent); + if (allScreens[i] == Optionshandler.FullScreenOption.WindowedFullScreen) + { + gameObject.GetComponentInChildren<TextMeshProUGUI>().text = "WINDOWED FULLSCREEN"; + } + else + { + gameObject.GetComponentInChildren<TextMeshProUGUI>().text = allScreens[i].ToString().ToUpper(); + } + gameObject.GetComponent<MultiOptionsButton>().currentFull = allScreens[i]; + gameObject.gameObject.SetActive(value: true); + } + } +} diff --git a/GameCode/MultiOptionsButton.cs b/GameCode/MultiOptionsButton.cs new file mode 100644 index 0000000..7b8bf79 --- /dev/null +++ b/GameCode/MultiOptionsButton.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class MultiOptionsButton : MonoBehaviour +{ + public Resolution currentRess; + + public Optionshandler.FullScreenOption currentFull; + + public void Click() + { + GetComponentInParent<MultiOptions>().ClickRessButton(this); + } +} diff --git a/GameCode/MusicGridVisualizer.cs b/GameCode/MusicGridVisualizer.cs new file mode 100644 index 0000000..c7fc064 --- /dev/null +++ b/GameCode/MusicGridVisualizer.cs @@ -0,0 +1,13 @@ +public class MusicGridVisualizer : GridVisualizer +{ + private void Update() + { + for (int i = 0; i < numberOfObjects.x; i++) + { + for (int j = 0; j < numberOfObjects.y; j++) + { + spawnedObjects[i, j].OnSetSize(MusicVisualizerData.Samples[i + j] * 200f); + } + } + } +} diff --git a/GameCode/MusicVisualizerData.cs b/GameCode/MusicVisualizerData.cs new file mode 100644 index 0000000..078940e --- /dev/null +++ b/GameCode/MusicVisualizerData.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class MusicVisualizerData : MonoBehaviour +{ + public static float[] Samples = new float[512]; + + private AudioSource m_audioSource; + + private void Awake() + { + m_audioSource = GetComponent<AudioSource>(); + } + + private void Update() + { + m_audioSource.GetSpectrumData(Samples, 0, FFTWindow.Blackman); + } +} diff --git a/GameCode/NetworkConnectionHandler.cs b/GameCode/NetworkConnectionHandler.cs new file mode 100644 index 0000000..b55d8bc --- /dev/null +++ b/GameCode/NetworkConnectionHandler.cs @@ -0,0 +1,450 @@ +using System; +using System.Collections; +using ExitGames.Client.Photon; +using Landfall.Network; +using Photon.Pun; +using Photon.Realtime; +using SoundImplementation; +using Steamworks; +using UnityEngine; + +public class NetworkConnectionHandler : MonoBehaviourPunCallbacks +{ + public static readonly string TWITCH_PLAYER_SCORE_KEY = "TwitchScore"; + + public static readonly string TWITCH_ROOM_AUDIENCE_RATING_KEY = "C0"; + + public static NetworkConnectionHandler instance; + + private static ClientSteamLobby m_SteamLobby; + + private bool m_SearchingQuickMatch; + + private bool m_SearchingTwitch; + + private int currentViewers = 100; + + private TypedLobby sqlLobby = new TypedLobby("customSqlLobby", LobbyType.SqlLobby); + + public bool hasRegionSelect; + + private bool m_ForceRegion; + + private bool isConnectedToMaster; + + private float untilTryOtherRegionCounter; + + private void Start() + { + instance = this; + PhotonNetwork.ServerPortOverrides = PhotonPortDefinition.AlternativeUdpPorts; + PhotonNetwork.CrcCheckEnabled = true; + PhotonNetwork.NetworkingClient.LoadBalancingPeer.DisconnectTimeout = 30000; + if (m_SteamLobby == null) + { + m_SteamLobby = new ClientSteamLobby(); + } + else + { + m_SteamLobby.LeaveLobby(); + } + } + + private void Update() + { + if (m_SearchingQuickMatch && PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode && !GM_ArmsRace.instance) + { + untilTryOtherRegionCounter -= Time.deltaTime; + if (untilTryOtherRegionCounter < 0f) + { + StartCoroutine(PlayOnBestActiveRegion()); + } + } + } + + public void QuickMatch() + { + m_SearchingQuickMatch = true; + m_SearchingTwitch = false; + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(); + StartCoroutine(DoActionWhenConnected(JoinRandomRoom)); + } + + public void TwitchJoin(int score) + { + currentViewers = Mathf.Clamp(score, 1, score); + m_SearchingQuickMatch = false; + m_SearchingTwitch = true; + ExitGames.Client.Photon.Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; + if (customProperties.ContainsKey(TWITCH_PLAYER_SCORE_KEY)) + { + customProperties[TWITCH_PLAYER_SCORE_KEY] = score; + } + else + { + customProperties.Add(TWITCH_PLAYER_SCORE_KEY, score); + } + PhotonNetwork.LocalPlayer.SetCustomProperties(customProperties); + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(); + StartCoroutine(DoActionWhenConnected(JoinSpecificTWITCHRoom)); + } + + public void HostPrivateAndInviteFriend() + { + m_SearchingQuickMatch = false; + m_SearchingTwitch = false; + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(privateGame: true); + RoomOptions options = new RoomOptions(); + options.MaxPlayers = 2; + options.IsOpen = true; + options.IsVisible = false; + m_SteamLobby.ShowInviteScreenWhenConnected(); + StartCoroutine(DoActionWhenConnected(delegate + { + CreateRoom(options); + })); + } + + private void JoinRandomRoom() + { + Debug.Log("Joining random room"); + PhotonNetwork.JoinRandomRoom(); + } + + private void CreateSpecificTWITCHRoom() + { + Debug.Log("Creating SPECIFIC TWITCH ROOM!"); + RoomOptions roomOptions = new RoomOptions(); + roomOptions.CustomRoomProperties = new ExitGames.Client.Photon.Hashtable { { TWITCH_ROOM_AUDIENCE_RATING_KEY, currentViewers } }; + roomOptions.CustomRoomPropertiesForLobby = new string[1] { TWITCH_ROOM_AUDIENCE_RATING_KEY }; + PhotonNetwork.CreateRoom(null, roomOptions, sqlLobby); + } + + private void JoinSpecificTWITCHRoom() + { + Debug.Log("JOINING SPECIFIC TWITCH ROOM!"); + int num = 5; + int num2 = currentViewers * num; + int num3 = currentViewers / num; + int num4 = 10; + int num5 = currentViewers * num4; + int num6 = currentViewers / num4; + int num7 = 10000000; + int num8 = currentViewers * num7; + int num9 = currentViewers / num7; + string text = ""; + text = text + "C0 BETWEEN " + num3 + " AND " + num2 + ";"; + text = text + "C0 BETWEEN " + num6 + " AND " + num5 + ";"; + text = text + "C0 BETWEEN " + num9 + " AND " + num8; + PhotonNetwork.JoinRandomRoom(null, 0, MatchmakingMode.FillRoom, sqlLobby, text); + } + + public override void OnJoinRoomFailed(short returnCode, string message) + { + Debug.Log("JOINED RANDOM ROOM FAILED!"); + if (!m_SearchingTwitch) + { + JoinRandomRoom(); + } + else + { + CreateSpecificTWITCHRoom(); + } + } + + private IEnumerator DoActionWhenConnected(Action action) + { + yield return WaitForConnect(); + action(); + } + + private IEnumerator PlayOnBestActiveRegion() + { + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + while (PhotonNetwork.InRoom) + { + yield return null; + } + } + string[] regionsToTry = new string[13] + { + "usw", "eu", "us", "au", "ru", "za", "asia", "cae", "in", "jp", + "rue", "sa", "kr" + }; + float bestRegionScore = 0f; + string bestRegion = ""; + for (int i = 0; i < regionsToTry.Length; i++) + { + isConnectedToMaster = false; + PhotonNetwork.Disconnect(); + while (PhotonNetwork.IsConnected) + { + yield return null; + } + PhotonNetwork.ConnectToRegion(regionsToTry[i]); + Debug.Log("connectToRegion " + regionsToTry[i]); + isConnectedToMaster = false; + while (!isConnectedToMaster) + { + yield return null; + } + int countOfPlayersInRooms = PhotonNetwork.CountOfPlayersInRooms; + int ping = PhotonNetwork.GetPing(); + float num = (float)Mathf.Clamp(countOfPlayersInRooms, 0, 50) / Mathf.Clamp(ping, 10f, 1E+11f); + Debug.Log("Ping: " + Mathf.Clamp(PhotonNetwork.GetPing(), 10f, 1E+11f)); + Debug.Log(regionsToTry[i] + ": " + PhotonNetwork.CountOfPlayersInRooms); + if (num > bestRegionScore) + { + bestRegion = regionsToTry[i]; + bestRegionScore = num; + if (ping < 50 && countOfPlayersInRooms > 50) + { + break; + } + } + } + isConnectedToMaster = false; + PhotonNetwork.Disconnect(); + PhotonNetwork.LocalPlayer.NickName = "PlayerName"; + if (bestRegion == "") + { + PhotonNetwork.ConnectToBestCloudServer(); + } + else + { + Debug.Log("Connecting to " + bestRegion); + PhotonNetwork.ConnectToRegion(bestRegion); + } + while (!isConnectedToMaster) + { + yield return null; + } + JoinRandomRoom(); + } + + private IEnumerator WaitForConnect() + { + if (!PhotonNetwork.IsConnectedAndReady) + { + PhotonNetwork.LocalPlayer.NickName = "PlayerName"; + PhotonNetwork.ConnectUsingSettings(); + if (hasRegionSelect || m_ForceRegion) + { + PhotonNetwork.ConnectToRegion(RegionSelector.region); + } + else + { + PhotonNetwork.ConnectToBestCloudServer(); + } + } + while (!isConnectedToMaster) + { + Debug.Log("Trying to connect to photon"); + yield return null; + } + Debug.Log("Is connected"); + } + + public void ForceRegionJoin(string region, string room) + { + Debug.Log("CREEASDSSD"); + if (PhotonNetwork.InRoom) + { + PhotonNetwork.Disconnect(); + } + CharacterCreatorHandler.instance.CloseMenus(); + MainMenuHandler.instance.Close(); + RegionSelector.region = region; + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(); + m_ForceRegion = true; + StartCoroutine(DoActionWhenConnected(delegate + { + JoinSpecificRoom(room); + })); + } + + private void JoinSpecificRoom(string room) + { + PhotonNetwork.JoinRoom(room); + m_ForceRegion = false; + } + + public override void OnEnable() + { + base.OnEnable(); + Debug.Log("Add me!"); + PhotonNetwork.AddCallbackTarget(this); + } + + public override void OnDisable() + { + base.OnDisable(); + Debug.Log("Remove me!"); + PhotonNetwork.RemoveCallbackTarget(this); + } + + public override void OnConnectedToMaster() + { + isConnectedToMaster = true; + } + + public override void OnJoinRandomFailed(short returnCode, string message) + { + Debug.Log("JOINED RANDOM ROOM FAILED!"); + if (m_SearchingTwitch) + { + CreateSpecificTWITCHRoom(); + return; + } + RoomOptions roomOptions = new RoomOptions(); + roomOptions.MaxPlayers = 2; + roomOptions.IsOpen = true; + roomOptions.IsVisible = true; + if (!SteamManager.Initialized) + { + Debug.LogError("SteamManager is not initialized!"); + } + else + { + CreateRoom(roomOptions); + } + } + + private void CreateRoom(RoomOptions roomOptions) + { + m_SteamLobby.CreateLobby(roomOptions.MaxPlayers, delegate(string RoomName) + { + PhotonNetwork.CreateRoom(RoomName, roomOptions); + }); + } + + public override void OnJoinedRoom() + { + if (!PhotonNetwork.OfflineMode) + { + isConnectedToMaster = false; + Debug.Log("Room joined successfully"); + Debug.Log(PhotonNetwork.CloudRegion); + untilTryOtherRegionCounter = 15f; + PhotonNetwork.LocalPlayer.NickName = (m_SearchingTwitch ? TwitchUIHandler.TWITCH_NAME_KEY : SteamFriends.GetPersonaName()); + } + } + + public override void OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer) + { + SoundPlayerStatic.Instance.PlayPlayerAdded(); + if (PhotonNetwork.PlayerList.Length == 2) + { + if (PhotonNetwork.IsMasterClient) + { + GetComponent<PhotonView>().RPC("RPCA_FoundGame", RpcTarget.All); + } + if (m_SteamLobby != null) + { + m_SteamLobby.HideLobby(); + } + } + Debug.Log("PlayerJoined"); + base.OnPlayerEnteredRoom(newPlayer); + } + + [PunRPC] + private void RPCA_FoundGame() + { + LoadingScreen.instance?.StopLoading(); + } + + public override void OnLeftRoom() + { + isConnectedToMaster = false; + } + + public override void OnPlayerLeftRoom(Photon.Realtime.Player otherPlayer) + { + _ = GM_ArmsRace.instance == null; + StartCoroutine(DoDisconnect("DISCONNECTED", "Other player left")); + base.OnPlayerLeftRoom(otherPlayer); + } + + public override void OnDisconnected(DisconnectCause cause) + { + if (cause != 0 && cause != DisconnectCause.DisconnectByClientLogic) + { + StartCoroutine(DoDisconnect("DISCONNECTED", cause.ToString())); + isConnectedToMaster = false; + } + } + + private IEnumerator DoRetry() + { + LoadingScreen.instance.StartLoading(); + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + while (PhotonNetwork.InRoom) + { + yield return null; + } + } + JoinRandomRoom(); + } + + private IEnumerator DoDisconnect(string context, string reason) + { + ErrorHandler.instance.ShowError(context, reason); + yield return new WaitForSecondsRealtime(2f); + ErrorHandler.instance.HideError(); + NetworkRestart(); + } + + public override void OnRegionListReceived(RegionHandler regionHandler) + { + Debug.Log(regionHandler); + } + + public void NetworkRestart() + { + isConnectedToMaster = false; + if (PhotonNetwork.OfflineMode) + { + Application.LoadLevel(Application.loadedLevel); + } + else + { + StartCoroutine(WaitForRestart()); + } + } + + private IEnumerator WaitForRestart() + { + if (m_SteamLobby != null) + { + m_SteamLobby.LeaveLobby(); + } + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + while (PhotonNetwork.InRoom) + { + yield return null; + } + } + if (PhotonNetwork.IsConnected) + { + PhotonNetwork.Disconnect(); + while (PhotonNetwork.IsConnected) + { + yield return null; + } + } + EscapeMenuHandler.isEscMenu = false; + DevConsole.isTyping = false; + Application.LoadLevel(Application.loadedLevel); + } +} diff --git a/GameCode/NetworkData.cs b/GameCode/NetworkData.cs new file mode 100644 index 0000000..293da46 --- /dev/null +++ b/GameCode/NetworkData.cs @@ -0,0 +1,58 @@ +using Photon.Pun; +using UnityEngine; + +public class NetworkData : MonoBehaviour +{ + private PhotonView photonView; + + private bool inited; + + private void Start() + { + photonView = GetComponent<PhotonView>(); + } + + private void Init() + { + if (!inited) + { + inited = true; + if (PhotonNetwork.IsMasterClient) + { + Debug.Log("Why am i the master?"); + } + } + } + + private void Update() + { + if (PhotonNetwork.InRoom) + { + Init(); + } + } + + private void RequestJoin() + { + photonView.RPC("RequestJoinMaster", RpcTarget.MasterClient); + Debug.Log("Request join"); + } + + [PunRPC] + public void RequestJoinMaster() + { + string text = JsonUtility.ToJson(new InitPackage + { + currentMapID = MapManager.instance.currentLevelID + }); + photonView.RPC("RequestJoinResponse", RpcTarget.Others, text); + } + + [PunRPC] + public void RequestJoinResponse(string jsonResponse) + { + InitPackage initPackage = (InitPackage)JsonUtility.FromJson(jsonResponse, typeof(InitPackage)); + MapManager.instance.LoadLevelFromID(initPackage.currentMapID, onlyMaster: false, callInImidetly: true); + Debug.Log("Got response"); + } +} diff --git a/GameCode/NetworkPhysicsObject.cs b/GameCode/NetworkPhysicsObject.cs new file mode 100644 index 0000000..9ffb4d6 --- /dev/null +++ b/GameCode/NetworkPhysicsObject.cs @@ -0,0 +1,248 @@ +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class NetworkPhysicsObject : MonoBehaviour, IPunObservable +{ + [Header("Sounds")] + public SoundEvent soundBoxImpact; + + public float soundPitchSemitone; + + private SoundParameterPitchSemitone soundParameterPitchSemitone = new SoundParameterPitchSemitone(); + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(); + + [Header("Settings")] + public PhotonView photonView; + + private Rigidbody2D rig2D; + + private Collider2D col; + + public int sendFreq = 5; + + private int currentFrame; + + private float lastTime; + + private List<ObjectSyncPackage> syncPackages = new List<ObjectSyncPackage>(); + + private float sinceCol; + + public float collisionThreshold; + + public float shakeAmount; + + public float maxShake; + + public float playerColThreshold = 1f; + + public float dmgAmount = 1f; + + public float forceAmount = 1f; + + private float sinceDealDMG; + + private List<Player> hitPlayers = new List<Player>(); + + public float speed = 100f; + + private float sinceRequest; + + private float sincePushed; + + public float bulletPushMultiplier = 1f; + + private Vector2 currentForceToSend; + + private Vector2 currentForcePos; + + private float sendForceRate = 0.1f; + + private float sendForceCounter; + + public float sleepThreshold = 1f; + + public void Awake() + { + soundParameterPitchSemitone.pitchSemitone = soundPitchSemitone; + currentFrame = Random.Range(0, sendFreq); + photonView = GetComponent<PhotonView>(); + col = GetComponent<Collider2D>(); + rig2D = GetComponent<Rigidbody2D>(); + } + + private void Update() + { + if (!photonView) + { + return; + } + sinceRequest += Time.deltaTime; + sinceDealDMG += Time.deltaTime; + sendForceCounter += Time.deltaTime; + if (sendForceCounter > sendForceRate) + { + _ = photonView.IsMine; + if (currentForceToSend != Vector2.zero) + { + photonView.RPC("RPCA_SendForce", photonView.Owner, currentForceToSend, currentForcePos); + sendForceCounter = 0f; + currentForceToSend = Vector2.zero; + } + } + if (syncPackages.Count > 0) + { + if (syncPackages[0].timeDelta > 0f) + { + syncPackages[0].timeDelta -= Time.deltaTime * 1.5f * (1f + (float)syncPackages.Count * 0.5f); + } + else + { + if (syncPackages.Count > 2) + { + syncPackages.RemoveAt(0); + } + rig2D.isKinematic = false; + base.transform.position = syncPackages[0].pos; + base.transform.rotation = Quaternion.LookRotation(Vector3.forward, syncPackages[0].rot); + rig2D.velocity = syncPackages[0].vel; + rig2D.angularVelocity = syncPackages[0].angularVel; + syncPackages.RemoveAt(0); + } + } + sinceCol += Time.deltaTime; + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + currentFrame++; + if (stream.IsWriting) + { + if (currentFrame >= sendFreq) + { + currentFrame = 0; + stream.SendNext((Vector2)base.transform.position); + stream.SendNext((Vector2)base.transform.up); + stream.SendNext(rig2D.velocity); + stream.SendNext(rig2D.angularVelocity); + if (lastTime == 0f) + { + lastTime = Time.time; + } + stream.SendNext(Time.time - lastTime); + lastTime = Time.time; + } + } + else + { + ObjectSyncPackage objectSyncPackage = new ObjectSyncPackage(); + objectSyncPackage.pos = (Vector2)stream.ReceiveNext(); + objectSyncPackage.rot = (Vector2)stream.ReceiveNext(); + objectSyncPackage.vel = (Vector2)stream.ReceiveNext(); + objectSyncPackage.angularVel = (float)stream.ReceiveNext(); + objectSyncPackage.timeDelta = (float)stream.ReceiveNext(); + syncPackages.Add(objectSyncPackage); + } + } + + [PunRPC] + public void RPCA_Collide(Vector2 colForce) + { + soundParameterIntensity.intensity = colForce.magnitude; + SoundManager.Instance.PlayAtPosition(soundBoxImpact, SoundManager.Instance.GetTransform(), base.transform, soundParameterIntensity, soundParameterPitchSemitone); + GamefeelManager.instance.AddGameFeel(colForce); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + if (photonView.IsMine && !(collision.contacts[0].normalImpulse < collisionThreshold) && !(sinceCol < 0.1f)) + { + sinceCol = 0f; + photonView.RPC("RPCA_Collide", RpcTarget.All, Mathf.Clamp(collision.contacts[0].normalImpulse, 0f, maxShake) * collision.contacts[0].normal * shakeAmount); + } + } + + private void OnPlayerCollision(Vector2 collision, CharacterData player) + { + if (!player.view.IsMine || sinceDealDMG < 1f) + { + return; + } + Vector3 vector = collision * dmgAmount; + if (!(vector.magnitude < playerColThreshold)) + { + float num = Mathf.Pow(rig2D.mass / 20000f, 2f); + float num2 = Mathf.Pow(rig2D.mass / 20000f, 0.5f); + player.healthHandler.CallTakeDamage(vector * 0.3f * num, player.transform.position); + player.healthHandler.CallTakeForce(collision * forceAmount * num2, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: false, vector.magnitude * 0.05f); + if (player.block.IsBlocking()) + { + rig2D.velocity *= -1.1f; + rig2D.angularVelocity *= -1.1f; + } + else if (rig2D.mass < 80000f) + { + rig2D.velocity *= -0.5f * (20000f / rig2D.mass); + rig2D.angularVelocity *= -0.5f * (20000f / rig2D.mass); + } + sinceDealDMG = 0f; + photonView.RPC("RPCA_PlayerCollision", RpcTarget.AllViaServer, collision, rig2D.velocity, base.transform.position, player.view.ViewID); + } + } + + [PunRPC] + public void RPCM_RequestCollide(Vector2 collision, Vector2 afterVel, Vector3 position, int playerId) + { + photonView.RPC("RPCA_PlayerCollision", RpcTarget.AllViaServer, collision, afterVel, position, playerId); + } + + [PunRPC] + private void RPCA_PlayerCollision(Vector2 collision, Vector2 velAfter, Vector3 position, int playerID) + { + CharacterData component = PhotonNetwork.GetPhotonView(playerID).GetComponent<CharacterData>(); + base.transform.position = position; + rig2D.velocity = velAfter; + sinceDealDMG = 0f; + StartCoroutine(component.GetComponent<PlayerCollision>().IDoBounce(component.playerVel.velocity)); + } + + public void BulletPush(Vector2 force, Vector2 localPoint, CharacterData asker) + { + if (photonView.IsMine) + { + rig2D.AddForceAtPosition(force * bulletPushMultiplier, base.transform.TransformPoint(localPoint), ForceMode2D.Impulse); + } + } + + [PunRPC] + public void RPCA_SendForce(Vector2 forceSent, Vector2 sentForcePos) + { + rig2D.AddForceAtPosition(forceSent, base.transform.TransformPoint(currentForcePos)); + } + + public Vector3 Push(CharacterData data) + { + if (!data.view.IsMine) + { + return Vector3.zero; + } + sincePushed = 0f; + Vector2 vector = data.input.direction * 8f; + Vector2 vector2 = col.bounds.ClosestPoint(data.transform.position); + float num = Vector2.Angle(vector, vector2 - (Vector2)data.transform.position); + float num2 = (90f - num) / 90f; + Vector2 vector3 = TimeHandler.fixedDeltaTime * vector * num2 * speed * 1000f; + currentForceToSend += vector3; + currentForcePos = base.transform.InverseTransformPoint(vector2); + float num3 = Mathf.Clamp((Vector2.Angle(rig2D.velocity, (Vector2)base.transform.position - (Vector2)data.transform.position) - 90f) / 90f, 0f, 1f); + OnPlayerCollision(rig2D.velocity * num3, data); + return -vector; + } + + public void RequestOwnership(CharacterData player) + { + } +} diff --git a/GameCode/NetworkPlayer.cs b/GameCode/NetworkPlayer.cs new file mode 100644 index 0000000..47619c9 --- /dev/null +++ b/GameCode/NetworkPlayer.cs @@ -0,0 +1,4 @@ +public class NetworkPlayer +{ + private int playerID; +} diff --git a/GameCode/NetworkSettings.cs b/GameCode/NetworkSettings.cs new file mode 100644 index 0000000..1375488 --- /dev/null +++ b/GameCode/NetworkSettings.cs @@ -0,0 +1,11 @@ +using Photon.Pun; +using UnityEngine; + +public class NetworkSettings : MonoBehaviour +{ + private void Start() + { + PhotonNetwork.SendRate = 30; + PhotonNetwork.SerializationRate = 30; + } +} diff --git a/GameCode/NewScript.cs b/GameCode/NewScript.cs new file mode 100644 index 0000000..8bde104 --- /dev/null +++ b/GameCode/NewScript.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class NewScript : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/NextArt.cs b/GameCode/NextArt.cs new file mode 100644 index 0000000..9300887 --- /dev/null +++ b/GameCode/NextArt.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class NextArt : MonoBehaviour +{ + private void Start() + { + ArtHandler.instance.NextArt(); + } +} diff --git a/GameCode/ObjectParticle.cs b/GameCode/ObjectParticle.cs new file mode 100644 index 0000000..5e3927b --- /dev/null +++ b/GameCode/ObjectParticle.cs @@ -0,0 +1,34 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; + +[Serializable] +public class ObjectParticle +{ + public float size = 1f; + + public AnimationCurve sizeOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + public float lifetime = 1f; + + public float rotation; + + public float randomRotation; + + [FoldoutGroup("Color", 0)] + public Color color = Color.magenta; + + [FoldoutGroup("Color", 0)] + public Color randomColor = Color.magenta; + + [FoldoutGroup("Color", 0)] + public Color randomAddedColor = Color.black; + + [FoldoutGroup("Color", 0)] + public float randomAddedSaturation; + + [FoldoutGroup("Color", 0)] + public bool singleRandomValueColor = true; + + public AnimationCurve alphaOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); +} diff --git a/GameCode/ObjectPool.cs b/GameCode/ObjectPool.cs new file mode 100644 index 0000000..b17adae --- /dev/null +++ b/GameCode/ObjectPool.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using UnityEngine; + +public class ObjectPool +{ + private Stack<GameObject> m_availableObjects = new Stack<GameObject>(); + + private List<GameObject> m_usedObjects = new List<GameObject>(); + + private GameObject m_objectPrefab; + + private Transform m_objectRoot; + + private int testCounter = 1; + + public ObjectPool(GameObject prefab, int initSpawn = 0, Transform parent = null) + { + m_objectPrefab = prefab; + m_objectRoot = new GameObject(prefab.name + "_root").transform; + m_objectRoot.transform.position = parent.position; + m_objectRoot.transform.rotation = parent.rotation; + m_objectRoot.transform.SetParent(parent, worldPositionStays: true); + m_objectRoot.transform.localScale = Vector3.one; + for (int i = 0; i < initSpawn; i++) + { + GameObject gameObject = Object.Instantiate(m_objectPrefab, m_objectRoot); + gameObject.SetActive(value: false); + m_availableObjects.Push(gameObject); + } + } + + public GameObject GetObject() + { + if (m_availableObjects.Count > 0) + { + GameObject gameObject = m_availableObjects.Pop(); + m_usedObjects.Add(gameObject); + gameObject.SetActive(value: true); + return gameObject; + } + GameObject gameObject2 = Object.Instantiate(m_objectPrefab, m_objectRoot); + m_usedObjects.Add(gameObject2); + gameObject2.SetActive(value: true); + return gameObject2; + } + + public bool ReleaseObject(GameObject obj) + { + bool num = m_usedObjects.Remove(obj); + if (num) + { + m_availableObjects.Push(obj); + obj.SetActive(value: false); + } + return num; + } + + public void ClearPool() + { + while (m_availableObjects.Count > 0) + { + Object.Destroy(m_availableObjects.Pop()); + } + for (int i = 0; i < m_usedObjects.Count; i++) + { + Object.Destroy(m_usedObjects[i]); + } + m_usedObjects.Clear(); + } +} diff --git a/GameCode/ObjectScaleToBulletStats.cs b/GameCode/ObjectScaleToBulletStats.cs new file mode 100644 index 0000000..da5e7d6 --- /dev/null +++ b/GameCode/ObjectScaleToBulletStats.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class ObjectScaleToBulletStats : MonoBehaviour +{ + public GameObject target; + + public float dmgAmount = 1f; + + public float speedAmount = 1f; + + private void Start() + { + ProjectileHit component = GetComponent<ProjectileHit>(); + MoveTransform component2 = GetComponent<MoveTransform>(); + if ((bool)component) + { + component.damage = Mathf.Lerp(component.damage, component.damage * target.transform.localScale.x, dmgAmount); + } + if ((bool)component2) + { + component2.localForce.z = Mathf.Lerp(component2.localForce.z, component2.localForce.z * target.transform.localScale.x, speedAmount); + } + } +} diff --git a/GameCode/ObjectShake.cs b/GameCode/ObjectShake.cs new file mode 100644 index 0000000..f4e8059 --- /dev/null +++ b/GameCode/ObjectShake.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class ObjectShake : MonoBehaviour +{ + public float globalMultiplier = 1f; + + public float interval = 0.1f; + + public float movementMultiplier = 1f; + + public float rotationMultiplier = 1f; + + private float counter; + + private void Start() + { + } + + private void Update() + { + counter += TimeHandler.deltaTime; + if (counter > interval) + { + base.transform.localPosition = Random.insideUnitCircle * movementMultiplier * globalMultiplier * 0.1f; + base.transform.localEulerAngles = new Vector3(base.transform.localEulerAngles.x, base.transform.localEulerAngles.y, (float)Random.Range(-10, 10) * globalMultiplier * rotationMultiplier); + counter = 0f; + } + } +} diff --git a/GameCode/ObjectSyncPackage.cs b/GameCode/ObjectSyncPackage.cs new file mode 100644 index 0000000..7affc5f --- /dev/null +++ b/GameCode/ObjectSyncPackage.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class ObjectSyncPackage +{ + public Vector2 pos; + + public Vector2 rot; + + public Vector2 vel; + + public float angularVel; + + public float timeDelta; +} diff --git a/GameCode/ObjectsToSpawn.cs b/GameCode/ObjectsToSpawn.cs new file mode 100644 index 0000000..cf688ce --- /dev/null +++ b/GameCode/ObjectsToSpawn.cs @@ -0,0 +1,123 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; + +[Serializable] +public class ObjectsToSpawn +{ + public enum Direction + { + forward, + normal, + identity + } + + public enum SpawnOn + { + all, + player, + notPlayer + } + + [FoldoutGroup("OnHit", 0)] + public GameObject effect; + + [FoldoutGroup("OnHit", 0)] + public Direction direction; + + [FoldoutGroup("OnHit", 0)] + public SpawnOn spawnOn; + + [FoldoutGroup("OnHit", 0)] + public bool spawnAsChild; + + [FoldoutGroup("OnHit", 0)] + public int numberOfSpawns = 1; + + [FoldoutGroup("OnHit", 0)] + public float normalOffset; + + [FoldoutGroup("OnHit", 0)] + public bool stickToBigTargets; + + [FoldoutGroup("OnHit", 0)] + public bool stickToAllTargets; + + [FoldoutGroup("OnHit", 0)] + public bool zeroZ; + + [FoldoutGroup("OnProjectile", 0)] + public GameObject AddToProjectile; + + [FoldoutGroup("OnProjectile", 0)] + public bool removeScriptsFromProjectileObject; + + [FoldoutGroup("Stacking", 0)] + public bool scaleStacks; + + [FoldoutGroup("Stacking", 0)] + public float scaleStackM = 0.5f; + + [FoldoutGroup("Scaling", 0)] + public float scaleFromDamage; + + [HideInInspector] + public int stacks; + + public static GameObject[] SpawnObject(Transform spawnerTransform, HitInfo hit, ObjectsToSpawn objectToSpawn, HealthHandler playerHealth, PlayerSkin playerSkins, float damage = 55f, SpawnedAttack spawnedAttack = null, bool wasBlocked = false) + { + GameObject[] array = new GameObject[objectToSpawn.numberOfSpawns]; + for (int i = 0; i < objectToSpawn.numberOfSpawns; i++) + { + if (wasBlocked && objectToSpawn.stickToAllTargets) + { + continue; + } + Vector3 position = (Vector3)hit.point + (Vector3)hit.normal * objectToSpawn.normalOffset + (objectToSpawn.zeroZ ? Vector3.zero : (Vector3.forward * 5f)); + Quaternion rotation = Quaternion.LookRotation(spawnerTransform.forward); + if (objectToSpawn.direction == Direction.normal) + { + rotation = Quaternion.LookRotation(hit.normal + Vector2.right * 0.005f); + } + if (objectToSpawn.direction == Direction.identity) + { + rotation = Quaternion.identity; + } + if ((objectToSpawn.spawnOn != SpawnOn.notPlayer || !playerHealth) && (objectToSpawn.spawnOn != SpawnOn.player || (bool)playerHealth) && (bool)objectToSpawn.effect) + { + GameObject gameObject = UnityEngine.Object.Instantiate(objectToSpawn.effect, position, rotation); + if (objectToSpawn.spawnAsChild && (bool)hit.transform) + { + gameObject.transform.SetParent(hit.transform, worldPositionStays: true); + } + if ((bool)spawnedAttack) + { + spawnedAttack.CopySpawnedAttackTo(gameObject); + } + array[i] = gameObject; + SetTeamColor.TeamColorThis(gameObject, playerSkins); + if ((objectToSpawn.stickToBigTargets && !playerHealth && (!hit.rigidbody || hit.rigidbody.mass > 500f)) || objectToSpawn.stickToAllTargets) + { + gameObject.AddComponent<FollowLocalPos>().Follow(hit.transform); + } + if (objectToSpawn.scaleFromDamage != 0f) + { + gameObject.transform.localScale *= 1f * (1f - objectToSpawn.scaleFromDamage) + damage / 55f * objectToSpawn.scaleFromDamage; + } + if (objectToSpawn.scaleStacks) + { + gameObject.transform.localScale *= 1f + (float)objectToSpawn.stacks * objectToSpawn.scaleStackM; + } + } + } + return array; + } + + public static void SpawnObject(ObjectsToSpawn objectToSpawn, Vector3 position, Quaternion rotation) + { + for (int i = 0; i < objectToSpawn.numberOfSpawns; i++) + { + UnityEngine.Object.Instantiate(objectToSpawn.effect, position, rotation); + } + } +} diff --git a/GameCode/OnlineNameSelect.cs b/GameCode/OnlineNameSelect.cs new file mode 100644 index 0000000..c9fd43a --- /dev/null +++ b/GameCode/OnlineNameSelect.cs @@ -0,0 +1,21 @@ +using Photon.Pun; +using TMPro; +using UnityEngine; + +public class OnlineNameSelect : MonoBehaviour +{ + private TMP_InputField nameField; + + private void Start() + { + nameField = GetComponentInChildren<TMP_InputField>(); + nameField.text = PlayerPrefs.GetString("PlayerName", ""); + PhotonNetwork.LocalPlayer.NickName = nameField.text; + } + + public void OnChangedVal(string newVal) + { + PlayerPrefs.SetString("PlayerName", nameField.text); + PhotonNetwork.LocalPlayer.NickName = nameField.text; + } +} diff --git a/GameCode/OnlyOneEdgeModifier.cs b/GameCode/OnlyOneEdgeModifier.cs new file mode 100644 index 0000000..080423c --- /dev/null +++ b/GameCode/OnlyOneEdgeModifier.cs @@ -0,0 +1,57 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Only One Edge")] +public class OnlyOneEdgeModifier : ProceduralImageModifier +{ + public enum ProceduralImageEdge + { + Top, + Bottom, + Left, + Right + } + + [SerializeField] + private float radius; + + [SerializeField] + private ProceduralImageEdge side; + + public float Radius + { + get + { + return radius; + } + set + { + radius = value; + base._Graphic.SetVerticesDirty(); + } + } + + public ProceduralImageEdge Side + { + get + { + return side; + } + set + { + side = value; + } + } + + public override Vector4 CalculateRadius(Rect imageRect) + { + return side switch + { + ProceduralImageEdge.Top => new Vector4(radius, radius, 0f, 0f), + ProceduralImageEdge.Right => new Vector4(0f, radius, radius, 0f), + ProceduralImageEdge.Bottom => new Vector4(0f, 0f, radius, radius), + ProceduralImageEdge.Left => new Vector4(radius, 0f, 0f, radius), + _ => new Vector4(0f, 0f, 0f, 0f), + }; + } +} diff --git a/GameCode/OptionsButton.cs b/GameCode/OptionsButton.cs new file mode 100644 index 0000000..f33bfc6 --- /dev/null +++ b/GameCode/OptionsButton.cs @@ -0,0 +1,204 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class OptionsButton : MonoBehaviour +{ + public enum SettingsTarget + { + Resolution, + Vol_Master, + Vol_SFX, + Vol_Music, + CharacterPattern, + MapPattern, + leftStickAim, + lockAimDirections, + ShowCardStarts, + FullScreen, + FreeStickAim, + Vsync + } + + public enum SettingsType + { + Binary, + Slider, + MultiOption + } + + public SettingsTarget settingsTarget; + + public SettingsType settingsType; + + public bool currentBoolValue; + + public Resolution currentResolutionValue; + + public Optionshandler.FullScreenOption currentFullscreenValue; + + public float currentFloatValue; + + private TextMeshProUGUI text; + + public Slider slider; + + private void Awake() + { + text = GetComponentsInChildren<TextMeshProUGUI>(includeInactive: true)[1]; + if (settingsType == SettingsType.Slider) + { + slider = GetComponentInChildren<Slider>(includeInactive: true); + slider.onValueChanged.AddListener(SliderSlide); + } + else + { + GetComponent<Button>().onClick.AddListener(ClickButton); + } + } + + private void OnEnable() + { + switch (settingsTarget) + { + case SettingsTarget.Resolution: + currentResolutionValue = Optionshandler.resolution; + break; + case SettingsTarget.Vol_Master: + currentFloatValue = Optionshandler.vol_Master; + break; + case SettingsTarget.Vol_SFX: + currentFloatValue = Optionshandler.vol_Sfx; + break; + case SettingsTarget.Vol_Music: + currentFloatValue = Optionshandler.vol_Music; + break; + case SettingsTarget.CharacterPattern: + currentBoolValue = Optionshandler.characterPattrens; + break; + case SettingsTarget.MapPattern: + currentBoolValue = Optionshandler.mapPatterns; + break; + case SettingsTarget.leftStickAim: + currentBoolValue = Optionshandler.leftStickAim; + break; + case SettingsTarget.lockAimDirections: + currentBoolValue = Optionshandler.lockMouse; + break; + case SettingsTarget.FreeStickAim: + currentBoolValue = Optionshandler.lockStick; + break; + case SettingsTarget.ShowCardStarts: + currentBoolValue = Optionshandler.showCardStatNumbers; + break; + case SettingsTarget.FullScreen: + currentFullscreenValue = Optionshandler.fullScreen; + break; + case SettingsTarget.Vsync: + currentBoolValue = Optionshandler.vSync; + break; + } + if (settingsType == SettingsType.Slider) + { + slider.value = currentFloatValue; + } + ReDraw(); + } + + public void SetResolutionAndFullscreen(Resolution newRess, Optionshandler.FullScreenOption fullScreen) + { + currentResolutionValue = newRess; + currentFullscreenValue = fullScreen; + ClickButton(); + if (settingsTarget == SettingsTarget.Resolution) + { + Optionshandler.instance.SetResolution(newRess); + } + if (settingsTarget == SettingsTarget.FullScreen) + { + Optionshandler.instance.SetFullScreen(fullScreen); + } + } + + public void SliderChanged() + { + currentFloatValue = slider.value; + } + + private void SliderSlide(float newVal) + { + currentFloatValue = newVal; + ClickButton(); + } + + public void ClickButton() + { + if (settingsType == SettingsType.Binary) + { + currentBoolValue = !currentBoolValue; + } + switch (settingsTarget) + { + case SettingsTarget.Resolution: + base.transform.parent.parent.GetComponentInChildren<MultiOptions>(includeInactive: true).Open(settingsTarget, base.transform.GetChild(1).position, this); + break; + case SettingsTarget.Vol_Master: + Optionshandler.instance.SetVolMaster(currentFloatValue); + break; + case SettingsTarget.Vol_SFX: + Optionshandler.instance.SetVolSFX(currentFloatValue); + break; + case SettingsTarget.Vol_Music: + Optionshandler.instance.SetVolMusic(currentFloatValue); + break; + case SettingsTarget.CharacterPattern: + Optionshandler.instance.SetCharacterPatterns(currentBoolValue); + break; + case SettingsTarget.MapPattern: + Optionshandler.instance.SetMapPatterns(currentBoolValue); + break; + case SettingsTarget.leftStickAim: + Optionshandler.instance.SetLeftStickAim(currentBoolValue); + break; + case SettingsTarget.lockAimDirections: + Optionshandler.instance.lockMouseAim(currentBoolValue); + break; + case SettingsTarget.FreeStickAim: + Optionshandler.instance.lockStickAim(currentBoolValue); + break; + case SettingsTarget.ShowCardStarts: + Optionshandler.instance.SetShowCardStatNumbers(currentBoolValue); + break; + case SettingsTarget.FullScreen: + base.transform.parent.parent.GetComponentInChildren<MultiOptions>(includeInactive: true).Open(settingsTarget, base.transform.GetChild(1).position, this); + break; + case SettingsTarget.Vsync: + Optionshandler.instance.SetVSync(currentBoolValue); + break; + } + ReDraw(); + } + + private void ReDraw() + { + if (settingsType == SettingsType.Binary) + { + text.text = (currentBoolValue ? "YES" : "NO"); + } + if (settingsType == SettingsType.MultiOption) + { + if (settingsTarget == SettingsTarget.Resolution) + { + text.text = currentResolutionValue.width + " X " + currentResolutionValue.height; + } + else if (currentFullscreenValue == Optionshandler.FullScreenOption.WindowedFullScreen) + { + text.text = "WINDOWED FULLSCREEN"; + } + else + { + text.text = currentFullscreenValue.ToString().ToUpper(); + } + } + } +} diff --git a/GameCode/Optionshandler.cs b/GameCode/Optionshandler.cs new file mode 100644 index 0000000..21130c1 --- /dev/null +++ b/GameCode/Optionshandler.cs @@ -0,0 +1,187 @@ +using SoundImplementation; +using UnityEngine; + +public class Optionshandler : MonoBehaviour +{ + public enum FullScreenOption + { + FullScreen, + WindowedFullScreen, + MaximizedWindow, + Windowed + } + + public static Resolution resolution; + + public static float vol_Master; + + public static float vol_Sfx; + + public static float vol_Music; + + public static FullScreenOption fullScreen; + + public static bool characterPattrens; + + public static bool mapPatterns; + + public static bool vSync; + + public static bool leftStickAim; + + public static bool lockMouse; + + public static bool showCardStatNumbers; + + public static bool lockStick; + + public static Optionshandler instance; + + private void Start() + { + instance = this; + LoadOptions(); + ApplyOptions(); + } + + private void LoadOptions() + { + vol_Master = PlayerPrefs.GetFloat("Vol_Master", 1f); + vol_Sfx = PlayerPrefs.GetFloat("vol_Sfx", 1f); + vol_Music = PlayerPrefs.GetFloat("vol_Music", 1f); + resolution.width = PlayerPrefs.GetInt("res_X", 0); + resolution.height = PlayerPrefs.GetInt("res_Y", 0); + fullScreen = (FullScreenOption)PlayerPrefs.GetInt("fullScreen", 1); + characterPattrens = GetBool(PlayerPrefs.GetInt("characterPattrens", 1)); + mapPatterns = GetBool(PlayerPrefs.GetInt("mapPatterns", 1)); + leftStickAim = GetBool(PlayerPrefs.GetInt("leftStickAim", 1)); + vSync = GetBool(PlayerPrefs.GetInt("vSync", 0)); + lockStick = GetBool(PlayerPrefs.GetInt("lockStick", 0)); + lockMouse = GetBool(PlayerPrefs.GetInt("lockMouse", 0)); + showCardStatNumbers = GetBool(PlayerPrefs.GetInt("showCardStatNumbers", 0)); + if (resolution.height == 0 || resolution.width == 0) + { + resolution = Screen.currentResolution; + SaveOptions(); + } + else + { + ApplyOptions(); + } + } + + private void SaveOptions() + { + PlayerPrefs.SetFloat("Vol_Master", vol_Master); + PlayerPrefs.SetFloat("vol_Sfx", vol_Sfx); + PlayerPrefs.SetFloat("vol_Music", vol_Music); + PlayerPrefs.SetInt("res_X", resolution.width); + PlayerPrefs.SetInt("res_Y", resolution.height); + PlayerPrefs.SetInt("fullScreen", (int)fullScreen); + PlayerPrefs.SetInt("characterPattrens", GetInt(characterPattrens)); + PlayerPrefs.SetInt("mapPatterns", GetInt(mapPatterns)); + PlayerPrefs.SetInt("leftStickAim", GetInt(leftStickAim)); + PlayerPrefs.SetInt("vSync", GetInt(vSync)); + PlayerPrefs.SetInt("lockMouse", GetInt(lockMouse)); + PlayerPrefs.SetInt("lockStick", GetInt(lockStick)); + PlayerPrefs.SetInt("showCardStatNumbers", GetInt(showCardStatNumbers)); + ApplyOptions(); + } + + private void ApplyOptions() + { + Screen.SetResolution(resolution.width, resolution.height, (FullScreenMode)fullScreen); + QualitySettings.vSyncCount = (vSync ? 1 : 0); + SoundVolumeManager.Instance.SetAudioMixerVolumes(vol_Master, vol_Music, vol_Sfx); + } + + private bool GetBool(int value) + { + if (value != 1) + { + return false; + } + return true; + } + + private int GetInt(bool value) + { + if (!value) + { + return 0; + } + return 1; + } + + public void SetResolution(Resolution resolutionToSet) + { + resolution = resolutionToSet; + SaveOptions(); + } + + public void SetVSync(bool vSyncToSet) + { + vSync = vSyncToSet; + SaveOptions(); + } + + public void SetVolMaster(float vol_Master_ToSet) + { + vol_Master = vol_Master_ToSet; + SaveOptions(); + } + + public void SetVolSFX(float vol_SFX_ToSet) + { + vol_Sfx = vol_SFX_ToSet; + SaveOptions(); + } + + public void SetVolMusic(float vol_Music_ToSet) + { + vol_Music = vol_Music_ToSet; + SaveOptions(); + } + + public void SetCharacterPatterns(bool characterPatternsToSet) + { + characterPattrens = characterPatternsToSet; + SaveOptions(); + } + + public void SetMapPatterns(bool mapPatternsToSet) + { + mapPatterns = mapPatternsToSet; + SaveOptions(); + } + + public void SetLeftStickAim(bool leftStickAimToSet) + { + leftStickAim = leftStickAimToSet; + SaveOptions(); + } + + public void lockMouseAim(bool setLockMouse) + { + lockMouse = setLockMouse; + SaveOptions(); + } + + public void lockStickAim(bool setLockStick) + { + lockStick = setLockStick; + SaveOptions(); + } + + public void SetShowCardStatNumbers(bool showCardStatNumbersToSet) + { + showCardStatNumbers = showCardStatNumbersToSet; + SaveOptions(); + } + + public void SetFullScreen(FullScreenOption fullscreenToSet) + { + fullScreen = fullscreenToSet; + SaveOptions(); + } +} diff --git a/GameCode/Orbit.cs b/GameCode/Orbit.cs new file mode 100644 index 0000000..0e63f89 --- /dev/null +++ b/GameCode/Orbit.cs @@ -0,0 +1,24 @@ +using System; +using UnityEngine; + +public class Orbit : MonoBehaviour +{ + public GameObject[] objectsPerLevel; + + private void Start() + { + AttackLevel component = GetComponent<AttackLevel>(); + component.LevelUpAction = (Action<int>)Delegate.Combine(component.LevelUpAction, new Action<int>(UpdateLevel)); + } + + private void UpdateLevel(int newLevel) + { + for (int i = 0; i < objectsPerLevel.Length; i++) + { + if (i <= newLevel - 1) + { + objectsPerLevel[i].SetActive(value: true); + } + } + } +} diff --git a/GameCode/OutOfBoundsHandler.cs b/GameCode/OutOfBoundsHandler.cs new file mode 100644 index 0000000..a7ed350 --- /dev/null +++ b/GameCode/OutOfBoundsHandler.cs @@ -0,0 +1,149 @@ +using Sonigon; +using UnityEngine; + +public class OutOfBoundsHandler : MonoBehaviour +{ + private bool outOfBounds; + + private bool almostOutOfBounds; + + private Camera mainCam; + + private CharacterData data; + + public ParticleSystem wall; + + public ParticleSystem burst; + + public ParticleSystem burstBig; + + public ParticleSystem warning; + + public ParticleSystem shieldWall; + + public ParticleSystem shieldBurst; + + public ParticleSystem shieldBurstBig; + + private ChildRPC rpc; + + private float counter; + + private float warningPercentage = 0.1f; + + private void Start() + { + base.transform.position = Vector3.up * 200f; + data = base.transform.root.GetComponent<CharacterData>(); + rpc = data.GetComponent<ChildRPC>(); + rpc.childRPCs.Add("OutOfBounds", RPCA_DisplayOutOfBounds); + rpc.childRPCs.Add("ShieldOutOfBounds", RPCA_DisplayOutOfBoundsShield); + mainCam = MainCam.instance.transform.GetComponent<Camera>(); + base.transform.SetParent(null); + } + + private void LateUpdate() + { + if (!data) + { + Object.Destroy(base.gameObject); + } + else + { + if (!data.playerVel.simulated || !data.isPlaying) + { + return; + } + float x = Mathf.InverseLerp(-35.56f, 35.56f, data.transform.position.x); + float y = Mathf.InverseLerp(-20f, 20f, data.transform.position.y); + Vector3 vector = new Vector3(x, y, 0f); + vector = new Vector3(Mathf.Clamp(vector.x, 0f, 1f), Mathf.Clamp(vector.y, 0f, 1f), vector.z); + almostOutOfBounds = false; + outOfBounds = false; + if (vector.x <= 0f || vector.x >= 1f || vector.y >= 1f || vector.y <= 0f) + { + outOfBounds = true; + } + else if (vector.x < warningPercentage || vector.x > 1f - warningPercentage || vector.y > 1f - warningPercentage || vector.y < warningPercentage) + { + almostOutOfBounds = true; + if (vector.x < warningPercentage) + { + vector.x = 0f; + } + if (vector.x > 1f - warningPercentage) + { + vector.x = 1f; + } + if (vector.y < warningPercentage) + { + vector.y = 0f; + } + if (vector.y > 1f - warningPercentage) + { + vector.y = 1f; + } + } + counter += TimeHandler.deltaTime; + if (almostOutOfBounds && !data.dead) + { + base.transform.position = GetPoint(vector); + base.transform.rotation = Quaternion.LookRotation(Vector3.forward, -(data.transform.position - base.transform.position)); + if (counter > 0.1f) + { + counter = 0f; + warning.Play(); + } + } + if (!outOfBounds || data.dead) + { + return; + } + data.sinceGrounded = 0f; + base.transform.position = GetPoint(vector); + base.transform.rotation = Quaternion.LookRotation(Vector3.forward, -(data.transform.position - base.transform.position)); + if (counter > 0.1f && data.view.IsMine) + { + counter = 0f; + if (data.block.IsBlocking()) + { + rpc.CallFunction("ShieldOutOfBounds"); + data.playerVel.velocity *= 0f; + data.healthHandler.CallTakeForce(base.transform.up * 400f * data.playerVel.mass, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: true); + data.transform.position = base.transform.position; + } + else + { + rpc.CallFunction("OutOfBounds"); + data.healthHandler.CallTakeForce(base.transform.up * 200f * data.playerVel.mass, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: true); + data.healthHandler.CallTakeDamage(51f * base.transform.up, data.transform.position); + } + } + } + } + + private Vector3 GetPoint(Vector3 p) + { + float x = Mathf.Lerp(-35.56f, 35.56f, p.x); + float y = Mathf.Lerp(-20f, 20f, p.y); + return new Vector3(x, y, 0f); + } + + private void RPCA_DisplayOutOfBounds() + { + SoundManager.Instance.Play(data.playerSounds.soundCharacterDamageScreenEdge, data.transform); + burst.Play(); + wall.Play(); + burstBig.Play(); + data.sinceGrounded = 0f; + } + + private void RPCA_DisplayOutOfBoundsShield() + { + SoundManager.Instance.Play(data.playerSounds.soundCharacterDamageScreenEdge, data.transform); + shieldBurst.Play(); + shieldWall.Play(); + shieldBurstBig.Play(); + data.sinceGrounded = 0f; + } +} diff --git a/GameCode/ParticleExplosionModifier.cs b/GameCode/ParticleExplosionModifier.cs new file mode 100644 index 0000000..ca3a6f6 --- /dev/null +++ b/GameCode/ParticleExplosionModifier.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections; +using UnityEngine; + +public class ParticleExplosionModifier : MonoBehaviour +{ + public AnimationCurve curve; + + public float speed = 1f; + + private ParticleSystem effect; + + private ParticleSystem.MainModule main; + + private Coroutine corutine; + + private void Start() + { + effect = GetComponent<ParticleSystem>(); + main = effect.main; + Explosion componentInParent = GetComponentInParent<Explosion>(); + componentInParent.DealDamageAction = (Action<Damagable>)Delegate.Combine(componentInParent.DealDamageAction, new Action<Damagable>(DealDamage)); + Explosion componentInParent2 = GetComponentInParent<Explosion>(); + componentInParent2.DealHealAction = (Action<Damagable>)Delegate.Combine(componentInParent2.DealHealAction, new Action<Damagable>(DealDamage)); + } + + public void DealDamage(Damagable damagable) + { + if (corutine != null) + { + StopCoroutine(corutine); + } + corutine = StartCoroutine(DoCurve()); + } + + private IEnumerator DoCurve() + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + ParticleSystem.MinMaxCurve startSize = main.startSize; + startSize.constantMin = curve.Evaluate(c) * 0.5f; + startSize.constantMax = curve.Evaluate(c); + main.startSize = startSize; + c += TimeHandler.deltaTime * speed; + yield return null; + } + } +} diff --git a/GameCode/ParticlePlayer.cs b/GameCode/ParticlePlayer.cs new file mode 100644 index 0000000..c834a68 --- /dev/null +++ b/GameCode/ParticlePlayer.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +public class ParticlePlayer : MonoBehaviour +{ + public static ParticlePlayer instance; + + private int spawnsThisFrame; + + private void Awake() + { + instance = this; + } + + private void Update() + { + spawnsThisFrame = 0; + } + + public void PlayEffect(string effectName, Vector3 position, Quaternion rotation, float scale = 1f, Transform followTransform = null) + { + if ((float)spawnsThisFrame > 5f) + { + return; + } + spawnsThisFrame++; + Transform transform = base.transform.Find(effectName); + if (!transform) + { + return; + } + if ((bool)followTransform) + { + transform = Object.Instantiate(transform.gameObject, null).transform; + } + transform.transform.position = position; + transform.transform.localScale = scale * Vector3.one; + transform.transform.rotation = rotation; + if ((bool)followTransform) + { + transform.gameObject.AddComponent<FollowLocalPos>().Follow(followTransform); + } + ParticleSystem[] componentsInChildren = transform.GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if ((bool)followTransform) + { + ParticleSystem.MainModule main = componentsInChildren[i].main; + main.simulationSpace = ParticleSystemSimulationSpace.Local; + } + componentsInChildren[i].Play(); + } + } +} diff --git a/GameCode/ParticleTime.cs b/GameCode/ParticleTime.cs new file mode 100644 index 0000000..a3daa16 --- /dev/null +++ b/GameCode/ParticleTime.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public class ParticleTime : MonoBehaviour +{ + private float startTime = 1f; + + private ParticleSystem.MainModule main; + + private void Start() + { + main = GetComponentInParent<ParticleSystem>().main; + startTime = main.simulationSpeed; + } + + private void Update() + { + main.simulationSpeed = startTime * TimeHandler.timeScale; + } +} diff --git a/GameCode/PerlinWordScale.cs b/GameCode/PerlinWordScale.cs new file mode 100644 index 0000000..f59f4c2 --- /dev/null +++ b/GameCode/PerlinWordScale.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class PerlinWordScale : MonoBehaviour +{ + public float scale = 1f; + + public float min = 0.5f; + + public float max = 2f; + + private void Start() + { + float t = Mathf.PerlinNoise(base.transform.position.x * scale, base.transform.position.y * scale); + base.transform.localScale *= Mathf.Lerp(min, max, t); + } +} diff --git a/GameCode/PhotonMapObject.cs b/GameCode/PhotonMapObject.cs new file mode 100644 index 0000000..8bfe674 --- /dev/null +++ b/GameCode/PhotonMapObject.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class PhotonMapObject : MonoBehaviour +{ + private Map map; + + private bool photonSpawned; + + private float counter; + + private bool waitingToBeRemoved; + + private void Awake() + { + if (base.transform.parent != null) + { + UnityEngine.Object.DestroyImmediate(GetComponent<PhotonView>()); + } + } + + private void Start() + { + Rigidbody2D component = GetComponent<Rigidbody2D>(); + component.isKinematic = true; + component.simulated = false; + if (base.transform.parent == null) + { + photonSpawned = true; + base.transform.SetParent(MapManager.instance.currentMap.Map.transform, worldPositionStays: true); + map = GetComponentInParent<Map>(); + map.missingObjects--; + Map obj = map; + obj.mapIsReadyAction = (Action)Delegate.Combine(obj.mapIsReadyAction, new Action(Go)); + if (map.hasRope && !GetComponent<PhotonView>().IsMine) + { + component.gravityScale = 0f; + } + } + else + { + map = GetComponentInParent<Map>(); + Map obj2 = map; + obj2.mapIsReadyEarlyAction = (Action)Delegate.Combine(obj2.mapIsReadyEarlyAction, new Action(GoEarly)); + } + } + + private void GoEarly() + { + if (waitingToBeRemoved) + { + UnityEngine.Object.DestroyImmediate(base.gameObject); + } + } + + private void Go() + { + StartCoroutine(IGo()); + } + + private IEnumerator IGo() + { + Rigidbody2D rig = GetComponent<Rigidbody2D>(); + yield return new WaitForSeconds(0f); + yield return new WaitForSeconds(0f); + yield return new WaitForSeconds(0f); + rig.isKinematic = false; + rig.simulated = true; + if ((bool)rig) + { + for (float i = 0f; i < 1f; i += Time.deltaTime * 1f) + { + rig.velocity -= rig.velocity * i * 0.05f; + yield return null; + } + } + } + + private void Update() + { + if (waitingToBeRemoved || photonSpawned) + { + return; + } + counter += Mathf.Clamp(Time.deltaTime, 0f, 0.1f); + if ((PhotonNetwork.OfflineMode && counter > 1f && map.hasEntered) || ((bool)map && map.hasEntered && map.LoadedForAll())) + { + if (PhotonNetwork.IsMasterClient) + { + PhotonNetwork.Instantiate("4 Map Objects/" + base.gameObject.name.Split(char.Parse(" "))[0], base.transform.position, base.transform.rotation, 0); + } + map.missingObjects++; + waitingToBeRemoved = true; + } + } +} diff --git a/GameCode/PhysicsFunctions.cs b/GameCode/PhysicsFunctions.cs new file mode 100644 index 0000000..61cad4c --- /dev/null +++ b/GameCode/PhysicsFunctions.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class PhysicsFunctions : MonoBehaviour +{ + private static LayerMask mask = LayerMask.GetMask("Default", "IgnorePlayer", "IgnoreMap"); + + public static Vector2 ObstructionPoint(Vector2 from, Vector2 to) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(from, to - from, Vector2.Distance(from, to), mask); + if ((bool)raycastHit2D.transform) + { + return raycastHit2D.point; + } + return to; + } +} diff --git a/GameCode/PickerType.cs b/GameCode/PickerType.cs new file mode 100644 index 0000000..b4f79a2 --- /dev/null +++ b/GameCode/PickerType.cs @@ -0,0 +1,5 @@ +public enum PickerType +{ + Team, + Player +} diff --git a/GameCode/Platform.cs b/GameCode/Platform.cs new file mode 100644 index 0000000..9d25a0b --- /dev/null +++ b/GameCode/Platform.cs @@ -0,0 +1,203 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +public class Platform +{ + private List<BoxCollider2D> m_boxColliders = new List<BoxCollider2D>(); + + private List<Vector2> m_platformPoints = new List<Vector2>(); + + public List<Vector2> m_edges = new List<Vector2>(); + + private static float EPSILON = Mathf.Epsilon * 10f; + + private int m_lastCalculatedClosestPoint = -1; + + public List<BoxCollider2D> BoxColliders => m_boxColliders; + + public List<Vector2> PlatformPoints + { + get + { + return m_platformPoints; + } + set + { + m_platformPoints = value; + } + } + + public List<Vector2> Edges => m_edges; + + public Color Color { get; set; } + + public Platform() + { + Color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)); + } + + public bool ContainsCollider(BoxCollider2D collider) + { + foreach (BoxCollider2D boxCollider in m_boxColliders) + { + if (collider == boxCollider) + { + return true; + } + } + return false; + } + + public void AddCollider(BoxCollider2D collider) + { + m_boxColliders.Add(collider); + } + + public void AddPlatformPoint(Vector2 point) + { + m_platformPoints.Add(point); + } + + public float GetClosestDistance(Vector2 position) + { + float num = float.MaxValue; + for (int i = 0; i < m_edges.Count; i++) + { + float num2 = Vector2.Distance(position, m_edges[i]); + if (num2 < num) + { + m_lastCalculatedClosestPoint = i; + num = num2; + } + } + return num; + } + + public bool IsPositionOutsidePlatform(Vector2 position) + { + Vector2 vector = m_edges[m_lastCalculatedClosestPoint]; + if (position.x > vector.x && m_lastCalculatedClosestPoint == m_edges.Count - 1) + { + return true; + } + if (position.x < vector.x && m_lastCalculatedClosestPoint == 0) + { + return true; + } + return false; + } + + public Vector2 GetPointOnPath(Vector2 position) + { + Vector2 vector = m_edges[m_lastCalculatedClosestPoint]; + if (position.x > vector.x && m_lastCalculatedClosestPoint == m_edges.Count - 1) + { + return vector; + } + if (position.x < vector.x && m_lastCalculatedClosestPoint == 0) + { + return vector; + } + int index = -1; + int num = 0; + if (position.x > vector.x) + { + index = m_lastCalculatedClosestPoint + 1; + num = 1; + } + else if (position.x <= vector.x) + { + index = m_lastCalculatedClosestPoint - 1; + num = -1; + } + if (num == 1) + { + return GetClosestPointOnLineSegment(vector, m_edges[index], position); + } + return GetClosestPointOnLineSegment(m_edges[index], vector, position); + } + + private Vector2 Project(Vector2 line1, Vector2 line2, Vector2 toProject) + { + float num = (line2.y - line1.y) / (line2.x - line1.x); + float num2 = line1.y - num * line1.x; + float x = (num * toProject.y + toProject.x - num * num2) / (num * num + 1f); + float y = (num * num * toProject.y + num * toProject.x + num2) / (num * num + 1f); + return new Vector2(x, y); + } + + public static Vector2 GetClosestPointOnLineSegment(Vector2 A, Vector2 B, Vector2 P) + { + Vector2 lhs = P - A; + Vector2 vector = B - A; + float sqrMagnitude = vector.sqrMagnitude; + float num = Vector2.Dot(lhs, vector) / sqrMagnitude; + if (num < 0f) + { + return A; + } + if (num > 1f) + { + return B; + } + return A + vector * num; + } + + public void PostProcessPlatformPoints() + { + int mask = LayerMask.GetMask("Default"); + List<Vector2> list = new List<Vector2>(m_platformPoints.OrderBy((Vector2 v) => v.x).ToArray()); + new HashSet<int>(); + for (int num = list.Count - 1; num > 0; num--) + { + if (Physics2D.OverlapCircle(list[num] + new Vector2(0f, 0.25f), 0.2f, mask) != null) + { + list.RemoveAt(num); + } + } + m_platformPoints = list; + DetectEdges(); + } + + public void DetectEdges() + { + if (m_platformPoints.Count == 0) + { + return; + } + List<Vector2> list = new List<Vector2>(); + for (int i = 0; i < m_platformPoints.Count - 2; i++) + { + Vector2 item = m_platformPoints[i]; + Vector2 item2 = m_platformPoints[i + 1]; + if (i == 0) + { + list.Add(item); + } + else if (i == m_platformPoints.Count - 3) + { + list.Add(item2); + } + else if (item2.y - item.y > Mathf.Epsilon) + { + list.Add(item); + list.Add(item2); + } + } + m_edges = list; + } + + public void DrawGizmos() + { + Gizmos.color = Color; + for (int i = 0; i < m_edges.Count; i++) + { + Gizmos.DrawSphere(m_edges[i], 0.2f); + } + for (int j = 0; j < m_edges.Count - 1; j++) + { + Gizmos.DrawLine(m_edges[j], m_edges[j + 1]); + } + } +} diff --git a/GameCode/PlayLineAnimation.cs b/GameCode/PlayLineAnimation.cs new file mode 100644 index 0000000..01cea4d --- /dev/null +++ b/GameCode/PlayLineAnimation.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class PlayLineAnimation : MonoBehaviour +{ + private LineEffect lineEffect; + + public AnimationCurve offsetCurve; + + public float offsetSpeed = 1f; + + public AnimationCurve widthCurve; + + public float widthSpeed = 1f; + + private void Start() + { + lineEffect = GetComponent<LineEffect>(); + } + + public void PlayOffset() + { + lineEffect.PlayAnim(LineEffect.AnimType.Offset, offsetCurve, offsetSpeed); + } + + public void PlayWidth() + { + lineEffect.PlayAnim(LineEffect.AnimType.Width, widthCurve, widthSpeed); + } +} diff --git a/GameCode/Player.cs b/GameCode/Player.cs new file mode 100644 index 0000000..d912f63 --- /dev/null +++ b/GameCode/Player.cs @@ -0,0 +1,153 @@ +using System; +using ExitGames.Client.Photon; +using Photon.Pun; +using UnityEngine; + +public class Player : MonoBehaviour +{ + public int playerID; + + public int teamID; + + [HideInInspector] + public CharacterData data; + + public PlayerSkinBank colors; + + private void Awake() + { + data = GetComponent<CharacterData>(); + } + + private void Start() + { + if (!data.view.IsMine) + { + ReadPlayerID(); + ReadTeamID(); + PlayerAssigner.instance.OtherPlayerWasCreated(); + } + else + { + int num = 0; + if (!PhotonNetwork.OfflineMode) + { + try + { + num = 0; + PlayerFace playerFace = CharacterCreatorHandler.instance.selectedPlayerFaces[num]; + data.view.RPC("RPCA_SetFace", RpcTarget.All, playerFace.eyeID, playerFace.eyeOffset, playerFace.mouthID, playerFace.mouthOffset, playerFace.detailID, playerFace.detailOffset, playerFace.detail2ID, playerFace.detail2Offset); + } + catch + { + } + } + else if (GM_ArmsRace.instance != null) + { + GM_ArmsRace instance = GM_ArmsRace.instance; + instance.StartGameAction = (Action)Delegate.Combine(instance.StartGameAction, new Action(GetFaceOffline)); + } + } + PlayerManager.instance.PlayerJoined(this); + } + + public void GetFaceOffline() + { + PlayerFace playerFace = CharacterCreatorHandler.instance.selectedPlayerFaces[playerID]; + data.view.RPC("RPCA_SetFace", RpcTarget.All, playerFace.eyeID, playerFace.eyeOffset, playerFace.mouthID, playerFace.mouthOffset, playerFace.detailID, playerFace.detailOffset, playerFace.detail2ID, playerFace.detail2Offset); + } + + [PunRPC] + public void RPCA_SetFace(int eyeID, Vector2 eyeOffset, int mouthID, Vector2 mouthOffset, int detailID, Vector2 detailOffset, int detail2ID, Vector2 detail2Offset) + { + PlayerFace face = PlayerFace.CreateFace(eyeID, eyeOffset, mouthID, mouthOffset, detailID, detailOffset, detail2ID, detail2Offset); + GetComponentInChildren<CharacterCreatorItemEquipper>().EquipFace(face); + } + + internal void Call_AllGameFeel(Vector2 vector2) + { + data.view.RPC("RPCA_AllGameFeel", RpcTarget.All, vector2); + } + + [PunRPC] + internal void RPCA_AllGameFeel(Vector2 vector2) + { + GamefeelManager.instance.AddGameFeel(vector2); + } + + public void AssignPlayerID(int ID) + { + playerID = ID; + SetColors(); + if (!PhotonNetwork.OfflineMode) + { + Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; + if (customProperties.ContainsKey("PlayerID")) + { + customProperties["PlayerID"] = playerID; + } + else + { + customProperties.Add("PlayerID", playerID); + } + PhotonNetwork.LocalPlayer.SetCustomProperties(customProperties); + } + } + + internal float GetRadius() + { + return 5f; + } + + private void ReadPlayerID() + { + if (!PhotonNetwork.OfflineMode) + { + playerID = (int)data.view.Owner.CustomProperties["PlayerID"]; + SetColors(); + } + } + + public void AssignTeamID(int ID) + { + teamID = ID; + if (!PhotonNetwork.OfflineMode) + { + Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; + if (customProperties.ContainsKey("TeamID")) + { + customProperties["TeamID"] = playerID; + } + else + { + customProperties.Add("TeamID", teamID); + } + PhotonNetwork.LocalPlayer.SetCustomProperties(customProperties); + } + } + + private void ReadTeamID() + { + if (!PhotonNetwork.OfflineMode) + { + teamID = (int)data.view.Owner.CustomProperties["TeamID"]; + } + } + + public void SetColors() + { + SetTeamColor.TeamColorThis(base.gameObject, PlayerSkinBank.GetPlayerSkinColors(playerID)); + } + + public PlayerSkin GetTeamColors() + { + return PlayerSkinBank.GetPlayerSkinColors(playerID); + } + + internal void FullReset() + { + data.weaponHandler.NewGun(); + data.stats.ResetStats(); + data.block.ResetStats(); + } +} diff --git a/GameCode/PlayerAI.cs b/GameCode/PlayerAI.cs new file mode 100644 index 0000000..f7a3d38 --- /dev/null +++ b/GameCode/PlayerAI.cs @@ -0,0 +1,119 @@ +using UnityEngine; + +public class PlayerAI : MonoBehaviour +{ + private float range = 6f; + + private CharacterData data; + + private GeneralInput input; + + private Vector3 moveDir = Vector3.zero; + + private Vector3 aimDir = Vector3.zero; + + private Vector3 targetPos; + + private Player target; + + private bool canSeeTarget; + + private float untilNextDataUpdate; + + private float getRandomTargetPosCounter; + + private bool isShooting; + + private float distanceToTarget = 5f; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + input = data.input; + } + + private void Update() + { + target = PlayerManager.instance.GetOtherPlayer(data.player); + untilNextDataUpdate -= TimeHandler.deltaTime; + if (!target) + { + return; + } + canSeeTarget = PlayerManager.instance.CanSeePlayer(base.transform.position, target).canSee; + input.ResetInput(); + if (!canSeeTarget) + { + getRandomTargetPosCounter -= TimeHandler.deltaTime; + if (getRandomTargetPosCounter < 0f) + { + getRandomTargetPosCounter = Random.Range(0.5f, 2f); + GetRandomPos(); + } + } + if (untilNextDataUpdate <= 0f) + { + if (Random.value < 0.25f / Mathf.Clamp(distanceToTarget * 0.1f, 0.1f, 10f) && canSeeTarget) + { + input.shieldWasPressed = true; + } + if (Random.value < 0.4f && canSeeTarget) + { + isShooting = true; + } + else + { + isShooting = false; + } + if (Random.value < 0.2f || data.isWallGrab) + { + input.jumpWasPressed = true; + } + untilNextDataUpdate = Random.Range(0f, 0.25f); + UpdateData(); + } + input.shootIsPressed = isShooting; + input.shootWasPressed = isShooting; + input.aimDirection = aimDir; + input.direction = moveDir; + } + + private void GetRandomPos() + { + Vector3 vector = Vector3.zero; + int num = 200; + while (vector == Vector3.zero && num > 0) + { + num--; + Vector3 vector2 = base.transform.position + Vector3.up * 5f + (Vector3)Random.insideUnitCircle * 15f; + if (data.ThereIsGroundBelow(vector2, 8f)) + { + vector = vector2; + } + } + targetPos = vector; + } + + private void UpdateData() + { + if (canSeeTarget) + { + targetPos = target.transform.position; + } + distanceToTarget = Vector3.Distance(base.transform.position, target.transform.position); + aimDir = (targetPos - base.transform.position).normalized; + moveDir = aimDir; + if (moveDir.x > 0f) + { + moveDir.x = 1f; + } + if (moveDir.x < 0f) + { + moveDir.x = -1f; + } + if (canSeeTarget && distanceToTarget < range && data.ThereIsGroundBelow(base.transform.position, 10f)) + { + moveDir = Vector3.zero; + } + } +} diff --git a/GameCode/PlayerAIDavid.cs b/GameCode/PlayerAIDavid.cs new file mode 100644 index 0000000..bb0b654 --- /dev/null +++ b/GameCode/PlayerAIDavid.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using Landfall.AI; +using UnityEngine; + +public class PlayerAIDavid : MonoBehaviour +{ + public static int[] topology = new int[4] { 2, 10, 16, 5 }; + + [SerializeField] + private bool m_useWeights; + + [SerializeField] + private WeightDataAsset m_weightData; + + private PlayerAPI m_api; + + private NeuralNet m_neuralNet; + + private double[] m_cachedInput; + + private float m_startTime; + + private Vector2 m_movement = Vector2.zero; + + private float m_aiTimer; + + private void Awake() + { + m_api = GetComponentInParent<PlayerAPI>(); + m_cachedInput = new double[2]; + m_neuralNet = new NeuralNet(topology); + if (m_weightData != null && m_useWeights) + { + m_neuralNet.SetWeights(m_weightData.m_weightDatas[m_weightData.m_weightDatas.Count - 1].m_weights); + } + m_startTime = Time.time + 0.8f; + } + + public void SetWeights(double[] weights) + { + m_neuralNet.SetWeights(new List<double>(weights)); + } + + public void SetWeights(List<double> weights) + { + m_neuralNet.SetWeights(weights); + } + + private void Update() + { + if (Time.time < m_startTime) + { + return; + } + if (m_aiTimer >= 0.1f) + { + m_aiTimer -= 0.1f; + Vector3 vector = m_api.OtherPlayerPosition() - m_api.PlayerPosition(); + m_cachedInput[0] = vector.x; + m_cachedInput[1] = vector.y; + m_neuralNet.FeedForward(m_cachedInput, 1.0); + double[] results = m_neuralNet.GetResults(); + m_api.SetAimDirection(new Vector2((float)results[3], (float)results[4])); + if (results[0] > 0.5) + { + m_api.Jump(); + } + if (results[1] > 0.5) + { + m_api.Attack(); + } + Vector2 zero = Vector2.zero; + if (results[2] > 0.5) + { + zero.x = 1f; + } + else if (results[2] < -0.5) + { + zero.x = -1f; + } + m_movement = zero; + } + m_api.Move(m_movement); + m_aiTimer += TimeHandler.deltaTime; + } +} diff --git a/GameCode/PlayerAIMinion.cs b/GameCode/PlayerAIMinion.cs new file mode 100644 index 0000000..8aea87b --- /dev/null +++ b/GameCode/PlayerAIMinion.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +public class PlayerAIMinion : MonoBehaviour +{ + public AnimationCurve m_AimCompensastionCurve; + + public float range = 5f; + + private PlayerAPI api; + + private Vector2 moveDirection; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + moveDirection = api.data.master.data.aimDirection; + if (moveDirection.x > 0.5f) + { + moveDirection.x = 1f; + } + else if (moveDirection.x < -0.5f) + { + moveDirection.x = -1f; + } + else + { + moveDirection.x = 0f; + } + moveDirection.y = 0f; + base.transform.root.gameObject.AddComponent<RemoveAfterSeconds>().seconds = 4f; + } + + private void Update() + { + Player otherPlayer = PlayerManager.instance.GetOtherPlayer(api.data.master); + api.Move(moveDirection); + if (api.data.isWallGrab) + { + api.Jump(); + } + if (!api.data.isGrounded) + { + api.Jump(); + } + if ((bool)otherPlayer) + { + api.SetAimDirection(GetAimDirForHitting(otherPlayer.transform.position)); + if (PlayerManager.instance.CanSeePlayer(base.transform.position, otherPlayer).canSee && Vector2.Distance(base.transform.position, otherPlayer.transform.position) < range) + { + api.Attack(); + } + } + } + + private Vector2 GetAimDirForHitting(Vector3 point) + { + Vector3 vector = point - base.transform.position; + api.SetAimDirection(vector); + api.GetMyBullet(); + float time = Mathf.Abs(point.x - base.transform.position.x); + return point + Vector3.up * m_AimCompensastionCurve.Evaluate(time) - base.transform.position; + } +} diff --git a/GameCode/PlayerAIPetter.cs b/GameCode/PlayerAIPetter.cs new file mode 100644 index 0000000..0c235f5 --- /dev/null +++ b/GameCode/PlayerAIPetter.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +public class PlayerAIPetter : MonoBehaviour +{ + private PlayerAPI api; + + public LayerMask m_layer; + + public AnimationCurve aimCurve; + + public float m_shootRandom = 0.9f; + + public float m_predDist = 1f; + + public float m_timeSinceGround = 0.1f; + + private BoxCollider2D m_collider; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + m_collider = api.GetComponentInChildren<BoxCollider2D>(); + } + + private void Update() + { + if ((double)Random.Range(0f, 1f) > 0.9) + { + api.Move(api.TowardsOtherPlayer() * -1f); + } + else + { + api.Move(api.TowardsOtherPlayer()); + } + PredictionHit(); + api.Attack(); + if ((double)Random.Range(0f, 1f) > 0.9) + { + api.Jump(); + } + AutoBlock(); + } + + private void AutoBlock() + { + foreach (BulletWrapper allBullet in api.GetAllBullets()) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(allBullet.projectileMovement.transform.position, ((Vector2)allBullet.projectileMovement.velocity).normalized, allBullet.velocity.magnitude * 5f * TimeHandler.deltaTime, m_layer); + if ((bool)raycastHit2D.transform && (!allBullet.projectileHit.ownPlayer || allBullet.projectileHit.ownPlayer != api.player) && raycastHit2D.transform.root == base.transform.root) + { + Debug.Log("BLICOK"); + api.Block(); + } + } + } + + private void PredictionHit() + { + if ((bool)api.GetOtherPlayer()) + { + float magnitude = (api.OtherPlayerPosition() - base.transform.position).magnitude; + Vector2 vector = api.GetOtherPlayer().data.playerVel.velocity * m_predDist * 0.1f * magnitude * 0.05f; + api.SetAimDirection(api.TowardsOtherPlayer() + Vector2.up * aimCurve.Evaluate(magnitude) + vector); + } + } +} diff --git a/GameCode/PlayerAIPhilip.cs b/GameCode/PlayerAIPhilip.cs new file mode 100644 index 0000000..25e6c79 --- /dev/null +++ b/GameCode/PlayerAIPhilip.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAIPhilip : MonoBehaviour +{ + private enum BattleMorale : byte + { + Blood, + Coward, + Defend + } + + private enum BattleBehaviour : byte + { + Attack, + HighGround, + MoveSegments + } + + private PlayerAPI m_PlayerAPI; + + private Player m_Enemy; + + private BattleMorale m_CurrentMorale; + + private BattleBehaviour m_CurrentBehaviour; + + private Vector2 m_Direction; + + private Vector2 m_TargetPos; + + private Vector2[] m_Boundaries; + + private Vector2[] m_Segments; + + private int m_CurrentSegment; + + private float m_Tick; + + private int m_BehaviourChangeTick; + + private int m_BehaviourTimeMin = 3; + + private int m_BehaviourTimeMax = 8; + + private float m_AttackDistance = 15f; + + private void Awake() + { + InitReferences(); + MakeBoundaries(); + NextBehaviour(); + } + + private void InitReferences() + { + m_PlayerAPI = GetComponentInParent<PlayerAPI>(); + } + + private void MakeBoundaries() + { + int num = 20; + int num2 = 35; + Vector2 vector = new Vector2(num2, num); + Vector2 vector2 = new Vector2(-num2, num); + Vector2 vector3 = new Vector2(num2, -num); + Vector2 vector4 = new Vector2(-num2, -num); + m_Boundaries = new Vector2[4] { vector, vector2, vector3, vector4 }; + m_Segments = new Vector2[4] + { + vector / 2f, + vector2 / 2f, + vector3 / 2f, + vector4 / 2f + }; + } + + private bool CheckForValidEnemy() + { + m_Enemy = m_PlayerAPI.GetOtherPlayer(); + return m_Enemy != null; + } + + private void Start() + { + CheckForValidEnemy(); + } + + private void Update() + { + if (CheckForValidEnemy()) + { + CheckMorale(); + CheckDirection(); + CheckGround(); + Move(); + Jump(); + DoAim(); + ShouldAttack(); + ShouldBlock(); + TickBehaviour(); + } + } + + private void SeedBehaviourChange() + { + m_BehaviourChangeTick = UnityEngine.Random.Range(m_BehaviourTimeMin, m_BehaviourTimeMax); + } + + private void TickBehaviour() + { + m_Tick += TimeHandler.deltaTime; + if (m_Tick >= (float)m_BehaviourChangeTick) + { + NextBehaviour(); + } + } + + private void NextBehaviour() + { + ResetTick(); + int length = Enum.GetValues(typeof(BattleBehaviour)).Length; + m_CurrentBehaviour = (BattleBehaviour)UnityEngine.Random.Range(0, length); + SeedBehaviourChange(); + CheckBehaviour(); + } + + private void ResetTick() + { + m_Tick = 0f; + } + + private void ShouldBlock() + { + if (CheckIncommingBullets()) + { + m_PlayerAPI.Block(); + } + } + + private bool CheckIncommingBullets() + { + Vector3 vector = m_PlayerAPI.PlayerPosition(); + Vector2 a = new Vector2(vector.x, vector.y); + float num = 1.5f; + List<BulletWrapper> allBullets = m_PlayerAPI.GetAllBullets(); + int count = allBullets.Count; + for (int i = 0; i < count; i++) + { + Vector2 vector2 = allBullets[i].projectileHit.transform.position; + float num2 = Vector2.Distance(a, vector2); + if (num2 <= num && Vector2.Distance(a, vector2 + allBullets[i].velocity.normalized) < num2) + { + return true; + } + } + return false; + } + + private void ShouldAttack() + { + if (CanSee() && Vector3.Distance(m_PlayerAPI.PlayerPosition(), m_PlayerAPI.OtherPlayerPosition()) <= m_AttackDistance) + { + m_PlayerAPI.Attack(); + } + } + + private bool CanSee() + { + Vector2 vector = m_PlayerAPI.TowardsOtherPlayer(); + Vector3 vector2 = new Vector3(vector.x, vector.y, 0f); + vector2.Normalize(); + Collider2D collider = Physics2D.Raycast(base.transform.position + vector2, vector2, 20f).collider; + if ((bool)collider && (bool)collider.GetComponent<Player>()) + { + return true; + } + return false; + } + + private void DoAim() + { + m_PlayerAPI.SetAimDirection(m_PlayerAPI.TowardsOtherPlayer() + m_PlayerAPI.GetOtherPlayer().data.playerVel.velocity * 0.1f); + } + + private void Move() + { + m_PlayerAPI.Move(m_Direction); + } + + private void Jump() + { + m_PlayerAPI.Jump(); + } + + private void CheckGround() + { + Vector2 vector = m_PlayerAPI.PlayerPosition(); + if (!(vector.y < 0f) || m_PlayerAPI.CheckGroundBelow(vector + Vector2.down * 0.5f, 10f)) + { + return; + } + m_Direction = Vector2.right; + float num = float.PositiveInfinity; + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position + Vector3.right, Vector2.right, 5f); + if ((bool)raycastHit2D.collider) + { + num = raycastHit2D.distance; + } + raycastHit2D = Physics2D.Raycast(base.transform.position + Vector3.left, Vector2.left, 5f); + if ((bool)raycastHit2D.collider) + { + if (raycastHit2D.distance < num) + { + m_Direction = Vector2.left; + } + } + else + { + m_Direction = Vector2.right; + } + } + + private void CheckDirection() + { + if (m_CurrentBehaviour == BattleBehaviour.Attack) + { + switch (m_CurrentMorale) + { + case BattleMorale.Blood: + m_Direction = m_PlayerAPI.TowardsOtherPlayer(); + break; + case BattleMorale.Coward: + m_Direction = -m_PlayerAPI.TowardsOtherPlayer(); + break; + case BattleMorale.Defend: + m_Direction = -m_PlayerAPI.TowardsOtherPlayer(); + break; + } + } + else + { + Vector3 vector = m_PlayerAPI.PlayerPosition(); + Vector2 vector2 = new Vector2(vector.x, vector.y); + m_Direction = m_TargetPos - vector2; + } + } + + private void CheckBehaviour() + { + switch (m_CurrentBehaviour) + { + case BattleBehaviour.HighGround: + m_TargetPos = m_Segments[0]; + break; + case BattleBehaviour.MoveSegments: + { + int max = m_Segments.Length; + int num; + for (num = UnityEngine.Random.Range(0, max); num == m_CurrentSegment; num = UnityEngine.Random.Range(0, max)) + { + } + m_CurrentSegment = num; + m_TargetPos = m_Segments[m_CurrentSegment]; + break; + } + case BattleBehaviour.Attack: + break; + } + } + + private void CheckMorale() + { + if (m_PlayerAPI.CanShoot()) + { + m_CurrentMorale = BattleMorale.Blood; + } + } +} diff --git a/GameCode/PlayerAIWilhelm.cs b/GameCode/PlayerAIWilhelm.cs new file mode 100644 index 0000000..b71a530 --- /dev/null +++ b/GameCode/PlayerAIWilhelm.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class PlayerAIWilhelm : MonoBehaviour +{ + private PlayerAPI api; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + } + + private void Update() + { + api.Move(api.TowardsOtherPlayer()); + api.SetAimDirection(api.TowardsOtherPlayer() + api.GetOtherPlayer().data.playerVel.velocity * 0.1f); + api.Attack(); + api.Jump(); + api.Block(); + } +} diff --git a/GameCode/PlayerAIZorro.cs b/GameCode/PlayerAIZorro.cs new file mode 100644 index 0000000..c475f3f --- /dev/null +++ b/GameCode/PlayerAIZorro.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAIZorro : MonoBehaviour +{ + public AnimationCurve m_AimCompensastionCurve; + + public LayerMask m_MapMask; + + public LayerMask m_PlayerMask; + + private PlayerAPI api; + + private Camera m_camera; + + private int framesSinceShot; + + private Vector3[] surfacesToHideOn; + + private Vector3 m_CurrentHidePos; + + private float tiemSpentOverDeath; + + private float timeSinceCouldShoot; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + m_camera = Camera.main; + HealthHandler healthHandler = api.player.data.healthHandler; + healthHandler.delayedReviveAction = (Action)Delegate.Combine(healthHandler.delayedReviveAction, new Action(Init)); + } + + public void Init() + { + StopAllCoroutines(); + BakeMapSurfaces(); + StartCoroutine(GetNewPos()); + } + + private void Update() + { + framesSinceShot++; + if (api.CanShoot()) + { + timeSinceCouldShoot += TimeHandler.deltaTime; + } + else + { + timeSinceCouldShoot = 0f; + } + Vector3 vector = api.OtherPlayerPosition() + (Vector3)api.GetOtherPlayer().data.playerVel.velocity * Vector3.Distance(base.transform.position, api.OtherPlayerPosition()) * 0.01f + Vector3.down * api.GetOtherPlayer().data.playerVel.velocity.y * Vector3.Distance(base.transform.position, api.OtherPlayerPosition()) * 0.005f; + bool flag = false; + if (Physics2D.Raycast(base.transform.position, Vector3.down, 18f, m_MapMask).transform == null) + { + flag = false; + tiemSpentOverDeath += TimeHandler.deltaTime; + } + else + { + flag = true; + tiemSpentOverDeath = 0f; + } + if (api.CanBlock() && Vector3.Distance(base.transform.position, api.OtherPlayerPosition()) > 5f && (flag || tiemSpentOverDeath < 0.25f)) + { + api.Move(vector - base.transform.position + new Vector3(Mathf.PerlinNoise(Time.time, 0f) * 5f * Mathf.Sin(Time.time * 2f), 0f, 0f)); + } + else + { + api.Move(m_CurrentHidePos - base.transform.position + new Vector3(Mathf.PerlinNoise(Time.time, 0f) * 8f * Mathf.Sin(Time.time * 3f), 0f, 0f)); + } + api.Jump(); + ShootAt(vector); + MakeSureToBlock(); + } + + public void MakeSureToBlock() + { + BulletWrapper[] array = api.GetAllBullets().ToArray(); + for (int i = 0; i < array.Length; i++) + { + float num = Vector3.Distance(array[i].projectileMovement.transform.position, base.transform.position); + float num2 = Vector3.Angle(array[i].velocity.normalized, base.transform.position - array[i].projectileMovement.transform.position); + if (num < 1.3f && num2 < 65f && framesSinceShot >= 4) + { + api.Block(); + } + } + } + + public BulletWrapper GetMostDangerousBullet(BulletWrapper[] bullets, out bool exsists) + { + float num = 999999f; + int num2 = -1; + for (int i = 0; i < bullets.Length; i++) + { + float num3 = Vector3.Distance(bullets[i].projectileMovement.transform.position, base.transform.position); + if (num3 < num && num3 < 5f) + { + num = num3; + num2 = i; + } + } + if (num2 != -1) + { + exsists = true; + return bullets[num2]; + } + exsists = false; + return new BulletWrapper(); + } + + public BulletWrapper[] GetAllBulletsComingAtMe() + { + List<BulletWrapper> list = new List<BulletWrapper>(); + BulletWrapper[] array = api.GetAllBullets().ToArray(); + for (int i = 0; i < array.Length; i++) + { + if (Vector3.Angle(array[i].velocity.normalized, base.transform.position - array[i].projectileMovement.transform.position) < 35f) + { + list.Add(array[i]); + } + } + return list.ToArray(); + } + + public void ShootAt(Vector3 point) + { + api.SetAimDirection(GetAimDirForHitting(point)); + api.Attack(); + } + + private Vector2 GetAimDirForHitting(Vector3 point) + { + Vector3 vector = point - base.transform.position; + api.SetAimDirection(vector); + api.GetMyBullet(); + float time = Mathf.Abs(point.x - base.transform.position.x); + Vector3 vector2 = point + Vector3.up * m_AimCompensastionCurve.Evaluate(time); + Debug.DrawLine(point, vector2, Color.red, 0.2f); + return vector2 - base.transform.position; + } + + public void BakeMapSurfaces() + { + Vector2 vector = m_camera.ViewportToWorldPoint(new Vector3(1f, 1f)); + Vector2 vector2 = m_camera.ViewportToWorldPoint(new Vector3(0f, 1f)); + Vector2 vector3 = m_camera.ViewportToWorldPoint(new Vector3(1f, 0f)); + Vector2 vector4 = m_camera.ViewportToWorldPoint(new Vector3(0f, 0f)); + Vector3 v = m_camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f)); + Debug.DrawLine(vector, v, Color.cyan); + Debug.DrawLine(vector2, v, Color.cyan); + Debug.DrawLine(vector3, v, Color.cyan); + Debug.DrawLine(vector4, v, Color.cyan); + List<Vector3> list = new List<Vector3>(); + for (int i = 0; i < 360; i++) + { + for (int j = 0; j < 40; j++) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(new Vector2(Mathf.Lerp(vector2.x, vector.x, (float)i / 359f), Mathf.Lerp(vector3.y, vector.y, (float)j / 39f)), Vector3.down, 6f, m_MapMask); + if ((bool)raycastHit2D.transform) + { + list.Add(raycastHit2D.point); + } + } + } + List<Vector3> list2 = new List<Vector3>(); + for (int k = 0; k < list.Count; k++) + { + if (Physics2D.OverlapCircleAll(list[k] + Vector3.up * 0.26f, 0.1f, m_MapMask).Length != 0) + { + list2.Add(list[k]); + } + } + for (int l = 0; l < list2.Count; l++) + { + list.Remove(list2[l]); + } + Debug.Log("Points: " + list.Count); + for (int m = 0; m < list.Count; m++) + { + Debug.DrawLine(list[m], list[m] + Vector3.up * 0.2f, Color.magenta, 1000f); + } + surfacesToHideOn = list.ToArray(); + } + + private IEnumerator GetNewPos() + { + while (true) + { + m_CurrentHidePos = GetPosAwayFrom(api.OtherPlayerPosition()); + yield return new WaitForSeconds(4f); + } + } + + public Vector3 GetPosAwayFrom(Vector3 point) + { + Vector3 result; + do + { + result = surfacesToHideOn[UnityEngine.Random.Range(0, surfacesToHideOn.Length)]; + } + while (!(Mathf.Abs(result.x - point.x) > 13f)); + return result; + } +} diff --git a/GameCode/PlayerAPI.cs b/GameCode/PlayerAPI.cs new file mode 100644 index 0000000..3edf9c5 --- /dev/null +++ b/GameCode/PlayerAPI.cs @@ -0,0 +1,172 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAPI : MonoBehaviour +{ + public Player player; + + public CharacterData data; + + private GeneralInput input; + + private bool movedThisFrame; + + private bool attackedThisFrame; + + private bool blockedThisFrame; + + private void Awake() + { + player = GetComponent<Player>(); + data = GetComponent<CharacterData>(); + input = GetComponent<GeneralInput>(); + } + + public void Move(Vector2 direction) + { + direction = Vector2.ClampMagnitude(direction, 1f); + movedThisFrame = true; + data.input.direction = direction; + } + + public void Jump() + { + data.jump.Jump(); + } + + public void Attack() + { + attackedThisFrame = true; + data.input.shootWasPressed = true; + data.input.shootIsPressed = true; + } + + public void Block() + { + data.input.shieldWasPressed = true; + } + + public void SetAimDirection(Vector2 direction) + { + data.input.aimDirection = direction; + } + + public void AimForOtherPlayer() + { + Player otherPlayer = PlayerManager.instance.GetOtherPlayer(player); + if ((bool)otherPlayer) + { + data.input.aimDirection = otherPlayer.transform.position - base.transform.position; + } + } + + public Vector2 TowardsOtherPlayer() + { + if (PlayerManager.instance.players.Count < 2) + { + return Vector2.zero; + } + return PlayerManager.instance.GetOtherPlayer(player).transform.position - base.transform.position; + } + + public RaycastHit2D RayCastDirection(Vector2 direction, float distance) + { + return Physics2D.Raycast(base.transform.position, direction, distance); + } + + public bool CheckGroundBelow(Vector2 pos, float range) + { + return data.ThereIsGroundBelow(pos, range); + } + + public bool CanBlock() + { + return !data.block.IsOnCD(); + } + + public Player GetOtherPlayer() + { + return PlayerManager.instance.GetOtherPlayer(player); + } + + public Vector3 OtherPlayerPosition() + { + Player otherPlayer = PlayerManager.instance.GetOtherPlayer(player); + if ((bool)otherPlayer) + { + return otherPlayer.transform.position; + } + return Vector3.zero; + } + + public Vector3 PlayerPosition() + { + return base.transform.position; + } + + public List<BulletWrapper> GetAllBullets() + { + List<BulletWrapper> list = new List<BulletWrapper>(); + ProjectileHit[] array = Object.FindObjectsOfType<ProjectileHit>(); + for (int i = 0; i < array.Length; i++) + { + BulletWrapper bulletWrapper = new BulletWrapper(); + bulletWrapper.projectileHit = array[i].GetComponent<ProjectileHit>(); + bulletWrapper.projectileMovement = array[i].GetComponent<MoveTransform>(); + bulletWrapper.damage = bulletWrapper.projectileHit.damage; + bulletWrapper.velocity = bulletWrapper.projectileMovement.velocity; + list.Add(bulletWrapper); + } + return list; + } + + public SpawnedAttack[] GetAllSpawnedAttacks() + { + return Object.FindObjectsOfType<SpawnedAttack>(); + } + + public bool CanShoot() + { + return player.data.weaponHandler.gun.IsReady(); + } + + public BulletWrapper GetMyBullet() + { + BulletWrapper bulletWrapper = new BulletWrapper(); + GameObject objectToSpawn = player.data.weaponHandler.gun.projectiles[0].objectToSpawn; + MoveTransform component = objectToSpawn.GetComponent<MoveTransform>(); + ProjectileHit component2 = objectToSpawn.GetComponent<ProjectileHit>(); + bulletWrapper.projectileMovement = component; + bulletWrapper.projectileHit = component2; + bulletWrapper.damage = component2.damage; + bulletWrapper.velocity = player.data.aimDirection.normalized * component.localForce.magnitude + component.worldForce; + return bulletWrapper; + } + + private void Update() + { + if (blockedThisFrame) + { + blockedThisFrame = false; + } + else + { + data.input.shieldWasPressed = false; + } + if (movedThisFrame) + { + movedThisFrame = false; + } + else + { + data.input.direction = Vector3.zero; + } + if (attackedThisFrame) + { + attackedThisFrame = false; + return; + } + data.input.shootWasPressed = false; + data.input.shootIsPressed = false; + } +} diff --git a/GameCode/PlayerActions.cs b/GameCode/PlayerActions.cs new file mode 100644 index 0000000..8c6d6f1 --- /dev/null +++ b/GameCode/PlayerActions.cs @@ -0,0 +1,131 @@ +using System; +using InControl; + +public class PlayerActions : PlayerActionSet +{ + public PlayerAction Fire; + + public PlayerAction Block; + + public PlayerAction Jump; + + public PlayerAction Left; + + public PlayerAction Right; + + public PlayerAction Up; + + public PlayerAction Down; + + public PlayerTwoAxisAction Move; + + public PlayerTwoAxisAction Aim; + + public PlayerAction AimLeft; + + public PlayerAction AimRight; + + public PlayerAction AimUp; + + public PlayerAction AimDown; + + public PlayerAction Start; + + public PlayerActions() + { + Fire = CreatePlayerAction("Fire"); + Start = CreatePlayerAction("Start"); + Block = CreatePlayerAction("Block"); + Jump = CreatePlayerAction("Jump"); + Left = CreatePlayerAction("Move Left"); + Right = CreatePlayerAction("Move Right"); + Up = CreatePlayerAction("Move Up"); + Down = CreatePlayerAction("Move Down"); + AimLeft = CreatePlayerAction("Aim Left"); + AimRight = CreatePlayerAction("Aim Right"); + AimUp = CreatePlayerAction("Aim Up"); + AimDown = CreatePlayerAction("Aim Down"); + Move = CreateTwoAxisPlayerAction(Left, Right, Down, Up); + Aim = CreateTwoAxisPlayerAction(AimLeft, AimRight, AimDown, AimUp); + } + + public static PlayerActions CreateWithKeyboardBindings() + { + PlayerActions playerActions = new PlayerActions(); + playerActions.Fire.AddDefaultBinding(Mouse.LeftButton); + playerActions.Block.AddDefaultBinding(Mouse.RightButton); + playerActions.Jump.AddDefaultBinding(Key.Space); + playerActions.Up.AddDefaultBinding(Key.W); + playerActions.Down.AddDefaultBinding(Key.S); + playerActions.Left.AddDefaultBinding(Key.A); + playerActions.Right.AddDefaultBinding(Key.D); + playerActions.Start.AddDefaultBinding(Key.Return); + playerActions.ListenOptions.IncludeUnknownControllers = true; + playerActions.ListenOptions.MaxAllowedBindings = 4u; + playerActions.ListenOptions.UnsetDuplicateBindingsOnSet = true; + playerActions.ListenOptions.OnBindingFound = delegate(PlayerAction action, BindingSource binding) + { + if (binding == new KeyBindingSource(Key.Escape)) + { + action.StopListeningForBinding(); + return false; + } + return true; + }; + BindingListenOptions bindingListenOptions = playerActions.ListenOptions; + bindingListenOptions.OnBindingAdded = (Action<PlayerAction, BindingSource>)Delegate.Combine(bindingListenOptions.OnBindingAdded, (Action<PlayerAction, BindingSource>)delegate(PlayerAction action, BindingSource binding) + { + Debug.Log("Binding added... " + binding.DeviceName + ": " + binding.Name); + }); + BindingListenOptions bindingListenOptions2 = playerActions.ListenOptions; + bindingListenOptions2.OnBindingRejected = (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)Delegate.Combine(bindingListenOptions2.OnBindingRejected, (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)delegate(PlayerAction action, BindingSource binding, BindingSourceRejectionType reason) + { + Debug.Log("Binding rejected... " + reason); + }); + return playerActions; + } + + public static PlayerActions CreateWithControllerBindings() + { + PlayerActions playerActions = new PlayerActions(); + playerActions.Fire.AddDefaultBinding(InputControlType.Action3); + playerActions.Fire.AddDefaultBinding(InputControlType.RightTrigger); + playerActions.Block.AddDefaultBinding(InputControlType.Action2); + playerActions.Block.AddDefaultBinding(InputControlType.LeftTrigger); + playerActions.Jump.AddDefaultBinding(InputControlType.Action1); + playerActions.Jump.AddDefaultBinding(InputControlType.LeftBumper); + playerActions.Jump.AddDefaultBinding(InputControlType.RightBumper); + playerActions.Start.AddDefaultBinding(InputControlType.Start); + playerActions.Left.AddDefaultBinding(InputControlType.LeftStickLeft); + playerActions.Right.AddDefaultBinding(InputControlType.LeftStickRight); + playerActions.Up.AddDefaultBinding(InputControlType.LeftStickUp); + playerActions.Down.AddDefaultBinding(InputControlType.LeftStickDown); + playerActions.AimLeft.AddDefaultBinding(InputControlType.RightStickLeft); + playerActions.AimRight.AddDefaultBinding(InputControlType.RightStickRight); + playerActions.AimUp.AddDefaultBinding(InputControlType.RightStickUp); + playerActions.AimDown.AddDefaultBinding(InputControlType.RightStickDown); + playerActions.ListenOptions.IncludeUnknownControllers = true; + playerActions.ListenOptions.MaxAllowedBindings = 4u; + playerActions.ListenOptions.UnsetDuplicateBindingsOnSet = true; + playerActions.ListenOptions.OnBindingFound = delegate(PlayerAction action, BindingSource binding) + { + if (binding == new KeyBindingSource(Key.Escape)) + { + action.StopListeningForBinding(); + return false; + } + return true; + }; + BindingListenOptions bindingListenOptions = playerActions.ListenOptions; + bindingListenOptions.OnBindingAdded = (Action<PlayerAction, BindingSource>)Delegate.Combine(bindingListenOptions.OnBindingAdded, (Action<PlayerAction, BindingSource>)delegate(PlayerAction action, BindingSource binding) + { + Debug.Log("Binding added... " + binding.DeviceName + ": " + binding.Name); + }); + BindingListenOptions bindingListenOptions2 = playerActions.ListenOptions; + bindingListenOptions2.OnBindingRejected = (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)Delegate.Combine(bindingListenOptions2.OnBindingRejected, (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)delegate(PlayerAction action, BindingSource binding, BindingSourceRejectionType reason) + { + Debug.Log("Binding rejected... " + reason); + }); + return playerActions; + } +} diff --git a/GameCode/PlayerAssigner.cs b/GameCode/PlayerAssigner.cs new file mode 100644 index 0000000..d4c4880 --- /dev/null +++ b/GameCode/PlayerAssigner.cs @@ -0,0 +1,220 @@ +using System.Collections; +using System.Collections.Generic; +using InControl; +using Photon.Pun; +using SoundImplementation; +using UnityEngine; + +public class PlayerAssigner : MonoBehaviour +{ + public GameObject player1AI; + + public GameObject player2AI; + + public static PlayerAssigner instance; + + public GameObject playerPrefab; + + public int maxPlayers = 4; + + public List<CharacterData> players = new List<CharacterData>(4); + + private bool playersCanJoin; + + private int playerIDToSet = -1; + + private int teamIDToSet = -1; + + private bool waitingForRegisterResponse; + + private bool hasCreatedLocalPlayer; + + private void Awake() + { + instance = this; + } + + internal void SetPlayersCanJoin(bool canJoin) + { + playersCanJoin = canJoin; + } + + private void Start() + { + InputManager.OnDeviceDetached += OnDeviceDetached; + } + + private void LateUpdate() + { + if (!playersCanJoin || players.Count >= maxPlayers || DevConsole.isTyping) + { + return; + } + if (Input.GetKeyDown(KeyCode.B) && !GameManager.lockInput) + { + StartCoroutine(CreatePlayer(null, isAI: true)); + } + if (Input.GetKey(KeyCode.Space)) + { + bool flag = true; + for (int i = 0; i < players.Count; i++) + { + if (players[i].playerActions.Device == null) + { + flag = false; + } + } + if (flag) + { + StartCoroutine(CreatePlayer(null)); + } + } + for (int j = 0; j < InputManager.ActiveDevices.Count; j++) + { + InputDevice inputDevice = InputManager.ActiveDevices[j]; + if (JoinButtonWasPressedOnDevice(inputDevice) && ThereIsNoPlayerUsingDevice(inputDevice)) + { + StartCoroutine(CreatePlayer(inputDevice)); + } + } + } + + private bool JoinButtonWasPressedOnDevice(InputDevice inputDevice) + { + if (!inputDevice.Action1.WasPressed && !inputDevice.Action2.WasPressed && !inputDevice.Action3.WasPressed) + { + return inputDevice.Action4.WasPressed; + } + return true; + } + + private CharacterData FindPlayerUsingDevice(InputDevice inputDevice) + { + int count = players.Count; + for (int i = 0; i < count; i++) + { + CharacterData characterData = players[i]; + if (characterData.playerActions.Device == inputDevice) + { + return characterData; + } + } + return null; + } + + public void ClearPlayers() + { + players.Clear(); + } + + private bool ThereIsNoPlayerUsingDevice(InputDevice inputDevice) + { + return FindPlayerUsingDevice(inputDevice) == null; + } + + private void OnDeviceDetached(InputDevice inputDevice) + { + CharacterData characterData = FindPlayerUsingDevice(inputDevice); + if (characterData != null) + { + RemovePlayer(characterData); + } + } + + [PunRPC] + public void RPCM_RequestTeamAndPlayerID(int askingPlayer) + { + int count = PlayerManager.instance.players.Count; + int num = ((count % 2 != 0) ? 1 : 0); + GetComponent<PhotonView>().RPC("RPC_ReturnPlayerAndTeamID", PhotonNetwork.CurrentRoom.GetPlayer(askingPlayer), count, num); + waitingForRegisterResponse = true; + } + + [PunRPC] + public void RPC_ReturnPlayerAndTeamID(int teamId, int playerID) + { + waitingForRegisterResponse = false; + playerIDToSet = playerID; + teamIDToSet = teamId; + } + + public void OtherPlayerWasCreated() + { + waitingForRegisterResponse = false; + } + + public IEnumerator CreatePlayer(InputDevice inputDevice, bool isAI = false) + { + if (waitingForRegisterResponse || (!PhotonNetwork.OfflineMode && hasCreatedLocalPlayer) || players.Count >= maxPlayers) + { + yield break; + } + if (!PhotonNetwork.OfflineMode && !PhotonNetwork.IsMasterClient) + { + GetComponent<PhotonView>().RPC("RPCM_RequestTeamAndPlayerID", RpcTarget.MasterClient, PhotonNetwork.LocalPlayer.ActorNumber); + waitingForRegisterResponse = true; + } + while (waitingForRegisterResponse) + { + yield return null; + } + if (!PhotonNetwork.OfflineMode) + { + if (PhotonNetwork.IsMasterClient) + { + playerIDToSet = PlayerManager.instance.players.Count; + teamIDToSet = ((playerIDToSet % 2 != 0) ? 1 : 0); + } + } + else + { + playerIDToSet = PlayerManager.instance.players.Count; + teamIDToSet = ((playerIDToSet % 2 != 0) ? 1 : 0); + } + hasCreatedLocalPlayer = true; + SoundPlayerStatic.Instance.PlayPlayerAdded(); + Vector3 position = Vector3.up * 100f; + CharacterData component = PhotonNetwork.Instantiate(playerPrefab.name, position, Quaternion.identity, 0).GetComponent<CharacterData>(); + if (isAI) + { + GameObject original = player1AI; + if (players.Count > 0) + { + original = player2AI; + } + component.GetComponent<CharacterData>().SetAI(); + Object.Instantiate(original, component.transform.position, component.transform.rotation, component.transform); + } + else + { + if (inputDevice != null) + { + component.input.inputType = GeneralInput.InputType.Controller; + component.playerActions = PlayerActions.CreateWithControllerBindings(); + } + else + { + component.input.inputType = GeneralInput.InputType.Keyboard; + component.playerActions = PlayerActions.CreateWithKeyboardBindings(); + } + component.playerActions.Device = inputDevice; + } + players.Add(component); + RegisterPlayer(component, teamIDToSet, playerIDToSet); + } + + private void RegisterPlayer(CharacterData player, int teamID, int playerID) + { + PlayerManager.RegisterPlayer(player.player); + player.player.AssignPlayerID(playerID); + player.player.AssignTeamID(teamID); + } + + private void RemovePlayer(CharacterData player) + { + } + + private void AssignPlayer(CharacterData player, InputDevice device) + { + } +} diff --git a/GameCode/PlayerAudioModifyers.cs b/GameCode/PlayerAudioModifyers.cs new file mode 100644 index 0000000..7f82b58 --- /dev/null +++ b/GameCode/PlayerAudioModifyers.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAudioModifyers : MonoBehaviour +{ + public List<AudioModifyer> modifyers = new List<AudioModifyer>(); + + public static List<CardAudioModifier> activeModifyer = new List<CardAudioModifier>(); + + public void AddToStack(CardAudioModifier mod) + { + int num = -1; + for (int i = 0; i < modifyers.Count; i++) + { + if (modifyers[i].modifier.stackName == mod.stackName) + { + num = i; + break; + } + } + if (num != -1) + { + modifyers[num].stacks++; + return; + } + AudioModifyer audioModifyer = new AudioModifyer(); + audioModifyer.modifier = new CardAudioModifier(); + audioModifyer.modifier.stackName = mod.stackName; + audioModifyer.modifier.stackType = mod.stackType; + audioModifyer.stacks = 1; + activeModifyer.Add(audioModifyer.modifier); + modifyers.Add(audioModifyer); + } + + public void SetStacks() + { + for (int i = 0; i < activeModifyer.Count; i++) + { + _ = activeModifyer[i].stackType; + _ = 1; + _ = activeModifyer[i].stackType; + } + for (int j = 0; j < modifyers.Count; j++) + { + _ = modifyers[j].modifier.stackType; + _ = 1; + _ = modifyers[j].modifier.stackType; + } + } +} diff --git a/GameCode/PlayerChat.cs b/GameCode/PlayerChat.cs new file mode 100644 index 0000000..61c9578 --- /dev/null +++ b/GameCode/PlayerChat.cs @@ -0,0 +1,87 @@ +using System.Collections; +using TMPro; +using UnityEngine; + +public class PlayerChat : MonoBehaviour +{ + public float spring = 15f; + + public float damper = 15f; + + public float impulse; + + public float targetScale; + + private TextMeshProUGUI messageText; + + private ScaleShake scaleShake; + + private float currentScale; + + private float vel; + + public Transform target; + + private Screenshaker shaker; + + private float sinceType; + + public float shakeAmount; + + public float shakeSpeed = 1f; + + private void Start() + { + messageText = target.GetComponentInChildren<TextMeshProUGUI>(); + shaker = target.GetComponentInChildren<Screenshaker>(); + target.transform.localScale = Vector3.zero; + } + + private void Update() + { + sinceType -= Time.unscaledDeltaTime; + if (sinceType < 0f) + { + targetScale = 0f; + } + else + { + targetScale = 1f; + } + vel = FRILerp.Lerp(vel, (targetScale - currentScale) * spring, damper); + currentScale += Time.unscaledDeltaTime * vel; + if (currentScale < 0f) + { + vel = 0f; + currentScale = 0f; + } + target.transform.localScale = Vector3.one * currentScale; + } + + public void Send(string message) + { + message = ChatFilter.instance.FilterMessage(message); + messageText.text = message; + if (sinceType > 0f) + { + vel += impulse; + } + sinceType = 2f + (float)message.Length * 0.05f; + targetScale = 1f; + if (message.ToUpper() == message) + { + StartCoroutine(ShakeOverTime(sinceType)); + } + } + + private IEnumerator ShakeOverTime(float t) + { + float a = t; + while (a > 0f) + { + shaker.OnUIGameFeel(shakeAmount * Random.insideUnitCircle); + a -= Time.unscaledDeltaTime * shakeSpeed; + yield return null; + } + } +} diff --git a/GameCode/PlayerCollision.cs b/GameCode/PlayerCollision.cs new file mode 100644 index 0000000..6055a69 --- /dev/null +++ b/GameCode/PlayerCollision.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class PlayerCollision : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundBounce; + + [Header("Settings")] + public LayerMask mask; + + private Vector2 lastPos; + + public bool checkForGoThroughWall = true; + + private int ignoreWallFor; + + private Collider2D col; + + private CircleCollider2D cirCol; + + private PlayerVelocity vel; + + private CharacterData data; + + public Action<Vector2, Vector2, Player> collideWithPlayerAction; + + public float bounceTreshold = 1f; + + private bool isBounce; + + public void IgnoreWallForFrames(int frames) + { + ignoreWallFor = frames; + } + + private void Start() + { + data = GetComponent<CharacterData>(); + col = GetComponent<Collider2D>(); + cirCol = GetComponent<CircleCollider2D>(); + vel = GetComponent<PlayerVelocity>(); + } + + private void FixedUpdate() + { + if (checkForGoThroughWall && ignoreWallFor <= 0) + { + RaycastHit2D raycastHit2D = default(RaycastHit2D); + RaycastHit2D[] array = Physics2D.RaycastAll(lastPos, (Vector2)base.transform.position - lastPos, Vector2.Distance(base.transform.position, lastPos), mask); + for (int i = 0; i < array.Length; i++) + { + if (!(array[i].transform.root == base.transform.root)) + { + Debug.DrawLine(lastPos, array[i].point, Color.green, 1f); + if (!(Vector2.Angle(array[i].normal, (Vector2)base.transform.position - lastPos) < 90f) && (!raycastHit2D.transform || array[i].distance < raycastHit2D.distance)) + { + raycastHit2D = array[i]; + } + } + } + if ((bool)raycastHit2D) + { + base.transform.position = raycastHit2D.point + raycastHit2D.normal * 0.5f; + if (data.healthHandler.flyingFor > 0f) + { + DoBounce(raycastHit2D); + } + } + } + ignoreWallFor--; + lastPos = base.transform.position; + float num = cirCol.radius * base.transform.localScale.x; + float num2 = cirCol.radius * base.transform.localScale.x * 0.75f; + RaycastHit2D[] array2 = Physics2D.CircleCastAll(lastPos, num, (Vector2)base.transform.position - lastPos, Vector2.Distance(base.transform.position, lastPos), mask); + for (int j = 0; j < array2.Length; j++) + { + if (array2[j].transform.root == base.transform.root) + { + continue; + } + Vector2 vector = base.transform.position; + Vector2 point = array2[j].point; + float num3 = Vector2.Distance(vector, point); + Vector2 normalized = (vector - point).normalized; + float value = num + (0f - num3); + float value2 = num2 + (0f - num3); + value = Mathf.Clamp(value, 0f, 10f); + value2 = Mathf.Clamp(value2, 0f, 10f); + NetworkPhysicsObject component = array2[j].transform.GetComponent<NetworkPhysicsObject>(); + if ((bool)component) + { + component.Push(data); + } + if (vel.simulated || !vel.isKinematic) + { + vel.transform.position += (Vector3)normalized * value2; + if (Mathf.Abs(normalized.y) < 0.45f && Mathf.Abs(data.input.direction.x) > 0.1f && Vector3.Angle(data.input.direction, normalized) > 90f) + { + data.TouchWall(normalized, point); + } + vel.velocity += normalized * value * 10f * TimeHandler.timeScale; + vel.velocity -= vel.velocity * value * 1f * TimeHandler.timeScale; + } + Player componentInParent = array2[j].transform.GetComponentInParent<Player>(); + if (componentInParent != null && collideWithPlayerAction != null) + { + collideWithPlayerAction(point, value * normalized, componentInParent); + } + if (data.healthHandler.flyingFor > 0f) + { + DoBounce(array2[j]); + } + } + lastPos = base.transform.position; + } + + private void DoBounce(RaycastHit2D hit) + { + if (!(Vector2.Angle(data.playerVel.velocity, hit.normal) < 90f) && !isBounce && data.view.IsMine && data.playerVel.velocity.magnitude > bounceTreshold) + { + data.view.RPC("RPCADoBounce", RpcTarget.All, hit.normal, base.transform.position); + } + } + + [PunRPC] + private void RPCADoBounce(Vector2 hit, Vector3 playerPos) + { + base.transform.position = playerPos; + StartCoroutine(IDoBounce(Vector2.Reflect(data.playerVel.velocity, hit))); + SoundManager.Instance.Play(soundBounce, base.transform); + } + + public IEnumerator IDoBounce(Vector2 targetVel) + { + isBounce = true; + data.stunHandler.AddStun(0.2f); + data.healthHandler.CallTakeDamage(targetVel.normalized * 5f, base.transform.position); + GamefeelManager.instance.AddGameFeel(targetVel.normalized * 4f); + yield return new WaitForSeconds(0.25f); + data.playerVel.velocity = targetVel; + isBounce = false; + } + + private void OnDisable() + { + isBounce = false; + } +} diff --git a/GameCode/PlayerDoBlock.cs b/GameCode/PlayerDoBlock.cs new file mode 100644 index 0000000..5f14851 --- /dev/null +++ b/GameCode/PlayerDoBlock.cs @@ -0,0 +1,23 @@ +using Photon.Pun; +using UnityEngine; + +public class PlayerDoBlock : MonoBehaviour +{ + private CharacterData data; + + private SyncPlayerMovement sync; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + sync = GetComponentInParent<SyncPlayerMovement>(); + } + + public void DoBlock() + { + if (data.view.IsMine) + { + sync.SendBlock(BlockTrigger.BlockTriggerType.Default, firstBlock: true, dontSetCD: true); + } + } +} diff --git a/GameCode/PlayerDoJump.cs b/GameCode/PlayerDoJump.cs new file mode 100644 index 0000000..9d718be --- /dev/null +++ b/GameCode/PlayerDoJump.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class PlayerDoJump : MonoBehaviour +{ + private PlayerJump jump; + + public float multiplier = 0.25f; + + private void Start() + { + jump = GetComponentInParent<PlayerJump>(); + } + + public void DoJump() + { + jump.Jump(forceJump: true, multiplier); + } +} diff --git a/GameCode/PlayerEffects.cs b/GameCode/PlayerEffects.cs new file mode 100644 index 0000000..c122706 --- /dev/null +++ b/GameCode/PlayerEffects.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public class PlayerEffects : MonoBehaviour +{ + public float lifeSteal; + + private void Start() + { + } +} diff --git a/GameCode/PlayerFace.cs b/GameCode/PlayerFace.cs new file mode 100644 index 0000000..f6e69f3 --- /dev/null +++ b/GameCode/PlayerFace.cs @@ -0,0 +1,84 @@ +using System; +using UnityEngine; + +[Serializable] +public class PlayerFace +{ + public int eyeID; + + public Vector2 eyeOffset; + + public int mouthID; + + public Vector2 mouthOffset; + + public int detailID; + + public Vector2 detailOffset; + + public int detail2ID; + + public Vector2 detail2Offset; + + public void LoadFace(string key) + { + eyeID = PlayerPrefs.GetInt("eyeID-" + key); + eyeOffset.x = PlayerPrefs.GetFloat("eyeOffsetX-" + key); + eyeOffset.y = PlayerPrefs.GetFloat("eyeOffsetY-" + key); + mouthID = PlayerPrefs.GetInt("mouthID-" + key); + mouthOffset.x = PlayerPrefs.GetFloat("mouthOffsetX-" + key); + mouthOffset.y = PlayerPrefs.GetFloat("mouthOffsetY-" + key); + detailID = PlayerPrefs.GetInt("detailID-" + key); + detailOffset.x = PlayerPrefs.GetFloat("detailOffsetX-" + key); + detailOffset.y = PlayerPrefs.GetFloat("detailOffsetY-" + key); + detail2ID = PlayerPrefs.GetInt("detail2ID-" + key); + detail2Offset.x = PlayerPrefs.GetFloat("detail2OffsetX-" + key); + detail2Offset.y = PlayerPrefs.GetFloat("detail2OffsetY-" + key); + } + + internal static PlayerFace CopyFace(PlayerFace currentPlayerFace) + { + return new PlayerFace + { + eyeID = currentPlayerFace.eyeID, + eyeOffset = currentPlayerFace.eyeOffset, + mouthID = currentPlayerFace.mouthID, + mouthOffset = currentPlayerFace.mouthOffset, + detailID = currentPlayerFace.detailID, + detailOffset = currentPlayerFace.detailOffset, + detail2ID = currentPlayerFace.detail2ID, + detail2Offset = currentPlayerFace.detail2Offset + }; + } + + internal static PlayerFace CreateFace(int eyeID, Vector2 eyeOffset, int mouthID, Vector2 mouthOffset, int detailID, Vector2 detailOffset, int detail2ID, Vector2 detail2Offset) + { + return new PlayerFace + { + eyeID = eyeID, + eyeOffset = eyeOffset, + mouthID = mouthID, + mouthOffset = mouthOffset, + detailID = detailID, + detailOffset = detailOffset, + detail2ID = detail2ID, + detail2Offset = detail2Offset + }; + } + + public void SaveFace(string key) + { + PlayerPrefs.SetInt("eyeID-" + key, eyeID); + PlayerPrefs.SetFloat("eyeOffsetX-" + key, eyeOffset.x); + PlayerPrefs.SetFloat("eyeOffsetY-" + key, eyeOffset.y); + PlayerPrefs.SetInt("mouthID-" + key, mouthID); + PlayerPrefs.SetFloat("mouthOffsetX-" + key, mouthOffset.x); + PlayerPrefs.SetFloat("mouthOffsetY-" + key, mouthOffset.y); + PlayerPrefs.SetInt("detailID-" + key, detailID); + PlayerPrefs.SetFloat("detailOffsetX-" + key, detailOffset.x); + PlayerPrefs.SetFloat("detailOffsetY-" + key, detailOffset.y); + PlayerPrefs.SetInt("detail2ID-" + key, detail2ID); + PlayerPrefs.SetFloat("detail2OffsetX-" + key, detail2Offset.x); + PlayerPrefs.SetFloat("detail2OffsetY-" + key, detail2Offset.y); + } +} diff --git a/GameCode/PlayerFlyParticle.cs b/GameCode/PlayerFlyParticle.cs new file mode 100644 index 0000000..a58db02 --- /dev/null +++ b/GameCode/PlayerFlyParticle.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class PlayerFlyParticle : MonoBehaviour +{ + private ParticleSystem part; + + private HealthHandler health; + + private void Start() + { + part = GetComponent<ParticleSystem>(); + health = GetComponentInParent<HealthHandler>(); + } + + private void Update() + { + if (part.isPlaying) + { + if (health.flyingFor < 0f) + { + part.Stop(); + } + } + else if (health.flyingFor > 0f) + { + part.Play(); + } + } +} diff --git a/GameCode/PlayerFollowGround.cs b/GameCode/PlayerFollowGround.cs new file mode 100644 index 0000000..c200f89 --- /dev/null +++ b/GameCode/PlayerFollowGround.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +public class PlayerFollowGround : MonoBehaviour +{ + private CharacterData data; + + private Vector2 lastPos; + + private Rigidbody2D lastRig; + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + private void FixedUpdate() + { + if (data.standOnRig == null || !data.isGrounded) + { + lastPos = Vector2.zero; + return; + } + if (lastPos != Vector2.zero && data.standOnRig == lastRig) + { + data.playerVel.transform.position = data.playerVel.position + (data.standOnRig.position - lastPos); + } + lastPos = data.standOnRig.position; + lastRig = data.standOnRig; + } +} diff --git a/GameCode/PlayerImmunity.cs b/GameCode/PlayerImmunity.cs new file mode 100644 index 0000000..791fadf --- /dev/null +++ b/GameCode/PlayerImmunity.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerImmunity : MonoBehaviour +{ + private List<Immunities> immunities = new List<Immunities>(); + + private void Start() + { + } + + private void Update() + { + for (int num = immunities.Count - 1; num >= 0; num--) + { + immunities[num].time -= TimeHandler.deltaTime; + if (immunities[num].time <= 0f) + { + immunities.RemoveAt(num); + } + } + } + + public bool IsImune(float time, float dmg, string name) + { + for (int i = 0; i < immunities.Count; i++) + { + if (immunities[i].name == name) + { + if (dmg > immunities[i].dmg) + { + immunities[i].dmg = dmg; + immunities[i].name = name; + immunities[i].time = time; + return false; + } + return true; + } + } + immunities.Add(new Immunities(time, dmg, name)); + return false; + } +} diff --git a/GameCode/PlayerInRangeSlow.cs b/GameCode/PlayerInRangeSlow.cs new file mode 100644 index 0000000..dd1f0cf --- /dev/null +++ b/GameCode/PlayerInRangeSlow.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class PlayerInRangeSlow : MonoBehaviour +{ + public float slowAmount = 0.1f; + + public float maxSlow = 0.5f; + + private PlayerInRangeTrigger trigger; + + private AttackLevel level; + + private void Start() + { + trigger = GetComponent<PlayerInRangeTrigger>(); + level = GetComponent<AttackLevel>(); + } + + private void Update() + { + if (trigger.inRange) + { + trigger.target.data.stats.AddSlowAddative(slowAmount * (float)level.attackLevel, maxSlow + ((float)level.attackLevel - 1f) * 0.25f); + } + } +} diff --git a/GameCode/PlayerInRangeTrigger.cs b/GameCode/PlayerInRangeTrigger.cs new file mode 100644 index 0000000..a6bad07 --- /dev/null +++ b/GameCode/PlayerInRangeTrigger.cs @@ -0,0 +1,79 @@ +using UnityEngine; +using UnityEngine.Events; + +public class PlayerInRangeTrigger : MonoBehaviour +{ + public enum TargetType + { + Any, + OtherPlayer + } + + public TargetType targetType; + + public float range = 5f; + + public float cooldown; + + public bool repeating; + + private float counter; + + private bool done; + + [HideInInspector] + public bool inRange; + + public UnityEvent triggerEvent; + + [HideInInspector] + public Player target; + + private Player ownPlayer; + + public bool scaleWithRange; + + private void Start() + { + ownPlayer = base.transform.root.GetComponent<Player>(); + if (!ownPlayer) + { + ownPlayer = base.transform.root.GetComponentInParent<SpawnedAttack>().spawner; + } + if (scaleWithRange) + { + range *= base.transform.localScale.x; + } + } + + private void Update() + { + counter += TimeHandler.deltaTime; + inRange = false; + target = null; + if (done) + { + return; + } + Player player = null; + if (targetType == TargetType.OtherPlayer) + { + player = PlayerManager.instance.GetOtherPlayer(ownPlayer); + } + if (targetType == TargetType.Any) + { + player = PlayerManager.instance.GetClosestPlayer(base.transform.position); + } + if (PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee && Vector3.Distance(base.transform.position, player.transform.position) < range * base.transform.root.localScale.x && !player.data.dead && counter >= cooldown) + { + counter = 0f; + triggerEvent.Invoke(); + inRange = true; + target = player; + if (!repeating) + { + done = true; + } + } + } +} diff --git a/GameCode/PlayerJump.cs b/GameCode/PlayerJump.cs new file mode 100644 index 0000000..3bad574 --- /dev/null +++ b/GameCode/PlayerJump.cs @@ -0,0 +1,85 @@ +using System; +using UnityEngine; + +public class PlayerJump : MonoBehaviour +{ + private CharacterData data; + + public float upForce; + + private CharacterStatModifiers stats; + + public ParticleSystem[] jumpPart; + + public float sideForce = 1f; + + public Action JumpAction; + + private void Start() + { + stats = GetComponent<CharacterStatModifiers>(); + data = GetComponent<CharacterData>(); + } + + private void Update() + { + if (data.input.jumpWasPressed) + { + Jump(); + } + if (data.input.jumpIsPressed && data.sinceJump < 0.2f) + { + data.playerVel.AddForce(Vector2.up * TimeHandler.deltaTime * 2f * data.stats.jump * data.playerVel.mass * (1f - stats.GetSlow()) * upForce, ForceMode2D.Force); + } + } + + public void Jump(bool forceJump = false, float multiplier = 1f) + { + if (!forceJump && (data.sinceJump < 0.1f || (data.currentJumps <= 0 && data.sinceWallGrab > 0.1f))) + { + return; + } + Vector3 vector = Vector3.up; + Vector3 vector2 = data.groundPos; + if (JumpAction != null) + { + JumpAction(); + } + bool flag = false; + if (data.sinceWallGrab < 0.1f && !data.isGrounded) + { + vector = Vector2.up * 0.8f + data.wallNormal * 0.4f; + vector2 = data.wallPos; + data.currentJumps = data.jumps; + flag = true; + } + else + { + if (data.sinceGrounded > 0.05f) + { + vector2 = base.transform.position; + } + data.currentJumps = data.jumps; + } + if (data.playerVel.velocity.y < 0f) + { + data.playerVel.velocity = new Vector2(data.playerVel.velocity.x, 0f); + } + data.sinceGrounded = 0f; + data.sinceJump = 0f; + data.isGrounded = false; + data.isWallGrab = false; + data.currentJumps--; + data.playerVel.AddForce(vector * multiplier * 0.01f * data.stats.jump * data.playerVel.mass * (1f - stats.GetSlow()) * upForce, ForceMode2D.Impulse); + if (!flag) + { + data.playerVel.AddForce(Vector2.right * multiplier * sideForce * 0.01f * data.stats.jump * data.playerVel.mass * (1f - stats.GetSlow()) * data.playerVel.velocity.x, ForceMode2D.Impulse); + } + for (int i = 0; i < jumpPart.Length; i++) + { + jumpPart[i].transform.position = new Vector3(vector2.x, vector2.y, 5f) - vector * 0f; + jumpPart[i].transform.rotation = Quaternion.LookRotation(data.playerVel.velocity); + jumpPart[i].Play(); + } + } +} diff --git a/GameCode/PlayerManager.cs b/GameCode/PlayerManager.cs new file mode 100644 index 0000000..1c72689 --- /dev/null +++ b/GameCode/PlayerManager.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class PlayerManager : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent[] soundCharacterSpawn; + + public static PlayerManager instance; + + public LayerMask canSeePlayerMask; + + public List<Player> players = new List<Player>(); + + public PhotonView view; + + private Action<Player, int> PlayerDiedAction; + + private bool playersShouldBeActive; + + public AnimationCurve playerMoveCurve; + + public Action<Player> PlayerJoinedAction { get; internal set; } + + private void Awake() + { + instance = this; + view = GetComponent<PhotonView>(); + } + + public Player GetOtherPlayer(Player asker) + { + return GetClosestPlayerInTeam(asker.transform.position, GetOtherTeam(asker.teamID)); + } + + public Player GetClosestPlayer(Vector2 refPos, bool needVision = false) + { + Player result = null; + float num = float.PositiveInfinity; + for (int i = 0; i < players.Count; i++) + { + if (!players[i].data.dead) + { + float num2 = Vector2.Distance(refPos, players[i].data.playerVel.position); + if ((!needVision || CanSeePlayer(refPos, players[i]).canSee) && num2 < num) + { + num = num2; + result = players[i]; + } + } + } + return result; + } + + internal Player GetPlayerWithActorID(int actorID) + { + for (int i = 0; i < players.Count; i++) + { + if (players[i].data.view.OwnerActorNr == actorID) + { + return players[i]; + } + } + return null; + } + + public Player GetClosestPlayerInTeam(Vector3 position, int team, bool needVision = false) + { + float num = float.MaxValue; + Player[] playersInTeam = GetPlayersInTeam(team); + Player result = null; + for (int i = 0; i < playersInTeam.Length; i++) + { + if (!players[i].data.dead) + { + float num2 = Vector2.Distance(position, playersInTeam[i].transform.position); + if ((!needVision || CanSeePlayer(position, playersInTeam[i]).canSee) && num2 < num) + { + num = num2; + result = playersInTeam[i]; + } + } + } + return result; + } + + public Player GetClosestPlayer(Vector2 refPos, Vector2 forward) + { + Player result = null; + float num = float.PositiveInfinity; + for (int i = 0; i < players.Count; i++) + { + if (!players[i].data.dead && CanSeePlayer(refPos, players[i]).canSee) + { + float num2 = Vector2.Distance(refPos, players[i].data.playerVel.position); + num2 += Vector2.Angle(forward, players[i].data.playerVel.position - refPos); + if (num2 < num) + { + num = num2; + result = players[i]; + } + } + } + return result; + } + + public CanSeeInfo CanSeePlayer(Vector2 from, Player player) + { + CanSeeInfo canSeeInfo = new CanSeeInfo(); + canSeeInfo.canSee = true; + canSeeInfo.distance = float.PositiveInfinity; + if (!player) + { + canSeeInfo.canSee = false; + return canSeeInfo; + } + RaycastHit2D[] array = Physics2D.RaycastAll(from, (player.data.playerVel.position - from).normalized, Vector2.Distance(from, player.data.playerVel.position), canSeePlayerMask); + for (int i = 0; i < array.Length; i++) + { + if ((bool)array[i].transform && !array[i].transform.root.GetComponent<SpawnedAttack>() && !array[i].transform.root.GetComponent<Player>() && array[i].distance < canSeeInfo.distance) + { + canSeeInfo.canSee = false; + canSeeInfo.hitPoint = array[i].point; + canSeeInfo.distance = array[i].distance; + } + } + return canSeeInfo; + } + + internal Player GetPlayerWithID(int playerID) + { + for (int i = 0; i < players.Count; i++) + { + if (players[i].playerID == playerID) + { + return players[i]; + } + } + return null; + } + + public Player GetLastPlayerAlive() + { + Player result = null; + for (int i = 0; i < players.Count; i++) + { + if (!players[i].data.dead) + { + result = players[i]; + break; + } + } + return result; + } + + public int GetLastTeamAlive() + { + return GetLastPlayerAlive().teamID; + } + + public int TeamsAlive() + { + bool flag = false; + bool flag2 = false; + for (int i = 0; i < players.Count; i++) + { + if (players[i].teamID == 0 && !players[i].data.dead) + { + flag = true; + } + if (players[i].teamID == 1 && !players[i].data.dead) + { + flag2 = true; + } + } + int num = 0; + if (flag) + { + num++; + } + if (flag2) + { + num++; + } + return num; + } + + public static void RegisterPlayer(Player player) + { + instance.players.Add(player); + if (instance.playersShouldBeActive) + { + player.data.isPlaying = true; + } + } + + public void RemovePlayer(Player player) + { + players.Remove(player); + UnityEngine.Object.Destroy(player.gameObject); + } + + public void RemovePlayers() + { + for (int num = players.Count - 1; num >= 0; num--) + { + if ((bool)players[num]) + { + UnityEngine.Object.Destroy(players[num].gameObject); + } + } + players.Clear(); + PlayerAssigner.instance.ClearPlayers(); + } + + public void RevivePlayers() + { + for (int i = 0; i < players.Count; i++) + { + players[i].data.healthHandler.Revive(); + players[i].GetComponent<GeneralInput>().enabled = true; + } + } + + [PunRPC] + public void RPCA_MovePlayers() + { + MovePlayers(MapManager.instance.GetSpawnPoints()); + } + + public void MovePlayers(SpawnPoint[] spawnPoints) + { + for (int i = 0; i < players.Count; i++) + { + StartCoroutine(Move(players[i].data.playerVel, spawnPoints[i].localStartPos)); + int num; + for (num = i; num >= soundCharacterSpawn.Length; num -= soundCharacterSpawn.Length) + { + } + SoundManager.Instance.Play(soundCharacterSpawn[num], players[i].transform); + } + } + + public void AddPlayerDiedAction(Action<Player, int> action) + { + PlayerDiedAction = (Action<Player, int>)Delegate.Combine(PlayerDiedAction, action); + } + + public void PlayerDied(Player player) + { + int num = 0; + for (int i = 0; i < players.Count; i++) + { + if (!instance.players[i].data.dead) + { + num++; + } + } + if (PlayerDiedAction != null) + { + PlayerDiedAction(player, num); + } + } + + public PlayerSkin GetColorFromTeam(int teamID) + { + return PlayerSkinBank.GetPlayerSkinColors(GetPlayersInTeam(teamID)[0].playerID); + } + + public PlayerSkin GetColorFromPlayer(int playerID) + { + return PlayerSkinBank.GetPlayerSkinColors(playerID); + } + + public Player[] GetPlayersInTeam(int teamID) + { + List<Player> list = new List<Player>(); + for (int i = 0; i < players.Count; i++) + { + if (players[i].teamID == teamID) + { + list.Add(players[i]); + } + } + return list.ToArray(); + } + + internal Player GetFirstPlayerInTeam(int teamID) + { + return GetPlayersInTeam(teamID)[0]; + } + + public int GetOtherTeam(int team) + { + if (team == 0) + { + return 1; + } + return 0; + } + + public void SetPlayersPlaying(bool playing) + { + playersShouldBeActive = playing; + for (int i = 0; i < players.Count; i++) + { + players[i].data.isPlaying = playing; + } + } + + public void SetPlayersSimulated(bool simulated) + { + playersShouldBeActive = simulated; + for (int i = 0; i < players.Count; i++) + { + players[i].data.playerVel.simulated = simulated; + } + } + + internal void SetPlayersVisible(bool visible) + { + for (int i = 0; i < players.Count; i++) + { + players[i].data.gameObject.transform.position = Vector3.up * 200f; + } + } + + public void PlayerJoined(Player player) + { + if (PlayerJoinedAction != null) + { + PlayerJoinedAction(player); + } + } + + private IEnumerator Move(PlayerVelocity player, Vector3 targetPos) + { + Debug.Log("MOVE PLAYERS START " + Time.unscaledTime); + player.GetComponent<Player>().data.isPlaying = false; + player.simulated = false; + player.isKinematic = true; + Vector3 distance = targetPos - player.transform.position; + Vector3 targetStartPos = player.transform.position; + PlayerCollision col = player.GetComponent<PlayerCollision>(); + float t = playerMoveCurve.keys[playerMoveCurve.keys.Length - 1].time; + float c = 0f; + while (c < t) + { + col.IgnoreWallForFrames(2); + c += Mathf.Clamp(Time.unscaledDeltaTime, 0f, 0.02f); + player.transform.position = targetStartPos + distance * playerMoveCurve.Evaluate(c); + yield return null; + } + int frames = 0; + while (frames < 10) + { + player.transform.position = targetStartPos + distance; + frames++; + yield return null; + } + player.simulated = true; + player.isKinematic = false; + Debug.Log("MOVE PLAYERS END " + Time.unscaledTime); + player.GetComponent<Player>().data.isPlaying = true; + player.GetComponent<Player>().data.healthHandler.Revive(); + CardChoiceVisuals.instance.Hide(); + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.R) && !DevConsole.isTyping && Application.isEditor) + { + ResetCharacters(); + } + } + + internal void ResetCharacters() + { + CardBarHandler.instance.ResetCardBards(); + for (int i = 0; i < players.Count; i++) + { + players[i].FullReset(); + } + } + + public PlayerActions[] GetActionsFromTeam(int selectingTeamID) + { + List<PlayerActions> list = new List<PlayerActions>(); + for (int i = 0; i < players.Count; i++) + { + if (players[i].teamID == selectingTeamID) + { + list.Add(players[i].data.playerActions); + } + } + return list.ToArray(); + } + + public PlayerActions[] GetActionsFromPlayer(int selectingPlayerID) + { + List<PlayerActions> list = new List<PlayerActions>(); + for (int i = 0; i < players.Count; i++) + { + if (players[i].playerID == selectingPlayerID) + { + list.Add(players[i].data.playerActions); + } + } + return list.ToArray(); + } +} diff --git a/GameCode/PlayerMovement.cs b/GameCode/PlayerMovement.cs new file mode 100644 index 0000000..d3af00e --- /dev/null +++ b/GameCode/PlayerMovement.cs @@ -0,0 +1,71 @@ +using UnityEngine; + +public class PlayerMovement : MonoBehaviour +{ + public float force; + + public float airControl = 0.3f; + + public float extraDrag; + + public float extraAngularDrag; + + public float wallGrabDrag; + + private CharacterData data; + + private CharacterStatModifiers stats; + + private float multiplier = 1f; + + private void Start() + { + data = GetComponent<CharacterData>(); + stats = GetComponent<CharacterStatModifiers>(); + } + + private void FixedUpdate() + { + if (!data.isPlaying) + { + return; + } + Move(data.input.direction); + if (data.isWallGrab && data.wallDistance < 0.7f) + { + Vector2 velocity = data.playerVel.velocity; + if (data.input.direction.y >= 0f) + { + _ = data.input.direction.x; + _ = 0f; + } + data.playerVel.velocity = velocity; + } + data.playerVel.velocity -= data.playerVel.velocity * TimeHandler.timeScale * 0.01f * 0.1f * extraDrag * multiplier; + data.playerVel.angularVelocity -= data.playerVel.angularVelocity * TimeHandler.timeScale * 0.01f * 0.1f * extraAngularDrag * multiplier; + } + + private void Update() + { + } + + public void Move(Vector2 direction) + { + UpdateMultiplier(); + if (!data.isStunned) + { + direction.y = Mathf.Clamp(direction.y, -1f, 0f); + direction.y *= 2f; + data.playerVel.AddForce(direction * TimeHandler.timeScale * (1f - stats.GetSlow()) * stats.movementSpeed * force * data.playerVel.mass * 0.01f * multiplier, ForceMode2D.Force); + } + } + + private void UpdateMultiplier() + { + multiplier = 1f; + if (!data.isGrounded) + { + multiplier = airControl; + } + } +} diff --git a/GameCode/PlayerName.cs b/GameCode/PlayerName.cs new file mode 100644 index 0000000..30fc4cc --- /dev/null +++ b/GameCode/PlayerName.cs @@ -0,0 +1,11 @@ +using Photon.Pun; +using TMPro; +using UnityEngine; + +public class PlayerName : MonoBehaviour +{ + private void Start() + { + GetComponentInParent<TextMeshProUGUI>().text = GetComponentInParent<PhotonView>().Owner.NickName; + } +} diff --git a/GameCode/PlayerSkin.cs b/GameCode/PlayerSkin.cs new file mode 100644 index 0000000..446a0cd --- /dev/null +++ b/GameCode/PlayerSkin.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class PlayerSkin : MonoBehaviour +{ + public Color color; + + public Color backgroundColor; + + public Color winText; + + public Color particleEffect; +} diff --git a/GameCode/PlayerSkinBank.cs b/GameCode/PlayerSkinBank.cs new file mode 100644 index 0000000..0a5bcd5 --- /dev/null +++ b/GameCode/PlayerSkinBank.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +[CreateAssetMenu(fileName = "Skin Bank", menuName = "Custom/Skin Bank", order = 99999)] +public class PlayerSkinBank : ScriptableObject +{ + [Serializable] + public struct PlayerSkinInstance + { + public PlayerSkin currentPlayerSkin; + } + + private static PlayerSkinBank instance; + + public PlayerSkinInstance[] skins = new PlayerSkinInstance[0]; + + private static PlayerSkinBank Instance + { + get + { + if (instance == null) + { + instance = Resources.Load("SkinBank") as PlayerSkinBank; + } + return instance; + } + } + + public static PlayerSkin GetPlayerSkinColors(int team) + { + return Instance.skins[team].currentPlayerSkin; + } + + public static PlayerSkinInstance GetPlayerSkin(int team) + { + return Instance.skins[team]; + } +} diff --git a/GameCode/PlayerSkinHandler.cs b/GameCode/PlayerSkinHandler.cs new file mode 100644 index 0000000..3c23236 --- /dev/null +++ b/GameCode/PlayerSkinHandler.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +public class PlayerSkinHandler : MonoBehaviour +{ + public bool simpleSkin; + + private PlayerSkinParticle[] skins; + + private CharacterData data; + + private bool inited; + + private void Start() + { + Init(); + } + + private void Init() + { + if (!inited) + { + inited = true; + ToggleSimpleSkin(simpleSkin); + data = GetComponentInParent<CharacterData>(); + if (!simpleSkin) + { + GameObject gameObject = Object.Instantiate(PlayerSkinBank.GetPlayerSkinColors(data.player.playerID).gameObject, base.transform.position, base.transform.rotation, base.transform); + skins = gameObject.GetComponentsInChildren<PlayerSkinParticle>(); + } + } + } + + public void TakeDamageBlink(Vector2 damage, bool selfDamage) + { + BlinkColor(Color.white * 0.95f); + } + + public void BlinkColor(Color blinkColor) + { + if (skins != null) + { + for (int i = 0; i < skins.Length; i++) + { + skins[i].BlinkColor(blinkColor); + } + } + } + + public void InitSpriteMask(int spriteLayerID) + { + Init(); + for (int i = 0; i < skins.Length; i++) + { + skins[i].Init(spriteLayerID); + } + } + + public void ToggleSimpleSkin(bool isSimple) + { + simpleSkin = isSimple; + GetComponent<SetPlayerSpriteLayer>().ToggleSimple(isSimple); + } +} diff --git a/GameCode/PlayerSkinParticle.cs b/GameCode/PlayerSkinParticle.cs new file mode 100644 index 0000000..22c2f99 --- /dev/null +++ b/GameCode/PlayerSkinParticle.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +public class PlayerSkinParticle : MonoBehaviour +{ + private Color startColor1; + + private Color startColor2; + + private ParticleSystem.MainModule main; + + private ParticleSystem part; + + private ParticleSystem.Particle[] particles; + + private float counter; + + public void Init(int spriteLayerID) + { + part = GetComponent<ParticleSystem>(); + part.GetComponent<ParticleSystemRenderer>().sortingLayerID = spriteLayerID; + main = part.main; + startColor1 = main.startColor.colorMin; + startColor2 = main.startColor.colorMax; + part.Play(); + } + + private void Update() + { + counter += TimeHandler.deltaTime; + } + + private void OnEnable() + { + if ((bool)part) + { + part.Play(); + } + } + + public void BlinkColor(Color blinkColor) + { + if (!(counter < 0.1f)) + { + counter = 0f; + particles = new ParticleSystem.Particle[part.main.maxParticles]; + int num = part.GetParticles(particles); + for (int i = 0; i < num; i++) + { + particles[i].startColor = blinkColor; + } + part.SetParticles(particles, num); + } + } +} diff --git a/GameCode/PlayerSounds.cs b/GameCode/PlayerSounds.cs new file mode 100644 index 0000000..aeffb32 --- /dev/null +++ b/GameCode/PlayerSounds.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using Sonigon; +using UnityEngine; + +public class PlayerSounds : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterJump; + + public SoundEvent soundCharacterJumpBig; + + public SoundEvent soundCharacterJumpEnsnare; + + public SoundEvent soundCharacterLand; + + public SoundEvent soundCharacterLandBig; + + private SoundParameterIntensity parameterIntensityLand = new SoundParameterIntensity(0f); + + public SoundEvent soundCharacterStickWall; + + public SoundEvent soundCharacterStickWallBig; + + private SoundParameterIntensity parameterIntensityStickWall = new SoundParameterIntensity(0f); + + public SoundEvent soundCharacterDamageScreenEdge; + + private CharacterData data; + + private List<EnsnareEffect> ensnareEffectList = new List<EnsnareEffect>(); + + private bool ensnareEnabled; + + public void AddEnsnareEffect(EnsnareEffect ensnareEffect) + { + ensnareEffectList.Add(ensnareEffect); + } + + public void RemoveEnsnareEffect(EnsnareEffect ensnareEffect) + { + ensnareEffectList.Remove(ensnareEffect); + } + + private void Start() + { + data = GetComponent<CharacterData>(); + CharacterData characterData = data; + characterData.TouchGroundAction = (Action<float, Vector3, Vector3, Transform>)Delegate.Combine(characterData.TouchGroundAction, new Action<float, Vector3, Vector3, Transform>(TouchGround)); + CharacterData characterData2 = data; + characterData2.TouchWallAction = (Action<float, Vector3, Vector3>)Delegate.Combine(characterData2.TouchWallAction, new Action<float, Vector3, Vector3>(TouchWall)); + PlayerJump jump = data.jump; + jump.JumpAction = (Action)Delegate.Combine(jump.JumpAction, new Action(Jump)); + } + + public void Jump() + { + ensnareEnabled = false; + for (int num = ensnareEffectList.Count - 1; num >= 0; num--) + { + if (ensnareEffectList[num] == null) + { + ensnareEffectList.RemoveAt(num); + } + } + for (int i = 0; i < ensnareEffectList.Count; i++) + { + if (ensnareEffectList[i].soundEnsnareJumpChange) + { + ensnareEnabled = true; + } + } + if (ensnareEnabled) + { + if (ensnareEnabled) + { + SoundManager.Instance.Play(soundCharacterJumpEnsnare, base.transform); + } + } + else if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterJumpBig, base.transform); + } + else + { + SoundManager.Instance.Play(soundCharacterJump, base.transform); + } + } + + public void TouchGround(float sinceGrounded, Vector3 pos, Vector3 normal, Transform ground) + { + if (sinceGrounded > 0.05f) + { + parameterIntensityLand.intensity = sinceGrounded; + if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterLandBig, base.transform, parameterIntensityLand); + } + else + { + SoundManager.Instance.Play(soundCharacterLand, base.transform, parameterIntensityLand); + } + } + } + + public void TouchWall(float sinceWall, Vector3 pos, Vector3 normal) + { + float num = sinceWall; + if (data.sinceGrounded < num) + { + num = data.sinceGrounded; + } + if (num > 0.05f) + { + parameterIntensityStickWall.intensity = num; + if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterStickWallBig, base.transform, parameterIntensityStickWall); + } + else + { + SoundManager.Instance.Play(soundCharacterStickWall, base.transform, parameterIntensityStickWall); + } + } + } +} diff --git a/GameCode/PlayerSpawnVisualEffect.cs b/GameCode/PlayerSpawnVisualEffect.cs new file mode 100644 index 0000000..a0f86ba --- /dev/null +++ b/GameCode/PlayerSpawnVisualEffect.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerSpawnVisualEffect : MonoBehaviour +{ + public Dictionary<string, GameObject> visualEffects; + + public void RPCA_SpawnVisualEffect(string effect) + { + Object.Instantiate(visualEffects[effect], base.transform.position, base.transform.rotation, base.transform); + } +} diff --git a/GameCode/PlayerVelocity.cs b/GameCode/PlayerVelocity.cs new file mode 100644 index 0000000..47822f6 --- /dev/null +++ b/GameCode/PlayerVelocity.cs @@ -0,0 +1,82 @@ +using UnityEngine; + +public class PlayerVelocity : MonoBehaviour +{ + internal bool simulated = true; + + internal bool isKinematic; + + internal Vector2 velocity; + + internal float mass = 100f; + + internal float angularVelocity; + + private CharacterData data; + + public Vector2 position + { + get + { + return base.transform.position; + } + set + { + base.transform.position = value; + } + } + + internal void AddTorque(float v) + { + } + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + private void FixedUpdate() + { + if (data.isPlaying) + { + if (isKinematic) + { + velocity *= 0f; + } + if (simulated && !isKinematic) + { + velocity += Vector2.down * Time.fixedDeltaTime * TimeHandler.timeScale * 20f; + base.transform.position += Time.fixedDeltaTime * TimeHandler.timeScale * (Vector3)velocity; + base.transform.position = new Vector3(base.transform.position.x, base.transform.position.y, 0f); + } + } + } + + internal void AddForce(Vector2 force, ForceMode2D forceMode) + { + if (forceMode == ForceMode2D.Force) + { + force *= 0.02f; + } + else + { + force *= 1f; + } + velocity += force / mass; + } + + internal void AddForce(Vector3 force, ForceMode2D forceMode) + { + AddForce((Vector2)force, forceMode); + } + + internal void AddForce(Vector2 force) + { + AddForce(force, ForceMode2D.Force); + } + + internal void AddForce(Vector3 force) + { + AddForce((Vector2)force, ForceMode2D.Force); + } +} diff --git a/GameCode/PlayerWobblePosition.cs b/GameCode/PlayerWobblePosition.cs new file mode 100644 index 0000000..6d05434 --- /dev/null +++ b/GameCode/PlayerWobblePosition.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +public class PlayerWobblePosition : MonoBehaviour +{ + private Vector3 physicsPos; + + public float drag = 15f; + + public float spring = 1000f; + + public float multiplier = 1f; + + public float prediction; + + private Vector3 velocity; + + private Player player; + + private void Start() + { + physicsPos = base.transform.position; + player = GetComponentInParent<Player>(); + } + + private void Update() + { + float num = Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.03f); + Vector3 position = player.transform.position; + if (prediction > 0f) + { + position += (Vector3)player.data.playerVel.velocity * prediction; + } + velocity += (position - physicsPos) * num * spring; + velocity -= velocity * drag * num; + physicsPos += num * multiplier * velocity; + base.transform.position = physicsPos; + } +} diff --git a/GameCode/Point.cs b/GameCode/Point.cs new file mode 100644 index 0000000..aa901d5 --- /dev/null +++ b/GameCode/Point.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class Point : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/PointVisualizer.cs b/GameCode/PointVisualizer.cs new file mode 100644 index 0000000..dc2e55b --- /dev/null +++ b/GameCode/PointVisualizer.cs @@ -0,0 +1,292 @@ +using System.Collections; +using Sirenix.OdinInspector; +using Sonigon; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class PointVisualizer : MonoBehaviour +{ + public SoundEvent soundWinRound; + + public SoundEvent sound_UI_Arms_Race_A_Ball_Shrink_Go_To_Left_Corner; + + public SoundEvent sound_UI_Arms_Race_B_Ball_Go_Down_Then_Expand; + + public SoundEvent sound_UI_Arms_Race_C_Ball_Pop_Shake; + + public static PointVisualizer instance; + + public AnimationCurve moveCurve; + + public AnimationCurve scaleCurve; + + public float timeBetween; + + public float timeToMove = 0.2f; + + public float timeToScale = 0.2f; + + public TextMeshProUGUI text; + + public GameObject bg; + + public Transform orangeBall; + + public Transform blueBall; + + private RectTransform orangeBallRT; + + private RectTransform blueBallRT; + + public Image orangeFill; + + public Image blueFill; + + private Vector3 orangeVel; + + private Vector3 blueVel; + + private Vector3 orangeSP; + + private Vector3 blueSP; + + private float ballBaseSize = 200f; + + private float ballSmallSize = 20f; + + private float bigBallScale = 900f; + + private void Awake() + { + instance = this; + } + + private void Start() + { + orangeBallRT = orangeBall.GetComponent<RectTransform>(); + blueBallRT = blueBall.GetComponent<RectTransform>(); + orangeSP = orangeBall.GetComponent<RectTransform>().anchoredPosition; + blueSP = blueBall.GetComponent<RectTransform>().anchoredPosition; + Close(); + } + + [Button] + private void TestWinSequence() + { + StartCoroutine(DoWinSequence(2, 1, 2, 1, orangeWinner: true)); + } + + [Button] + private void TestPoint() + { + StartCoroutine(DoSequence(1, 0, orangeWinner: true)); + } + + [Button] + private void Reset() + { + StartCoroutine(DoSequence(0, 0, orangeWinner: true)); + } + + public void ResetPoints() + { + orangeFill.fillAmount = 0f; + blueFill.fillAmount = 0f; + } + + private void ResetBalls() + { + orangeBallRT.sizeDelta = Vector2.one * ballBaseSize; + blueBallRT.sizeDelta = Vector2.one * ballBaseSize; + orangeBall.GetComponent<RectTransform>().anchoredPosition = orangeSP; + blueBall.GetComponent<RectTransform>().anchoredPosition = blueSP; + orangeVel = Vector3.zero; + blueVel = Vector3.zero; + } + + public IEnumerator DoWinSequence(int orangePoints, int bluePoints, int orangeRounds, int blueRounds, bool orangeWinner) + { + yield return new WaitForSecondsRealtime(0.35f); + SoundManager.Instance.Play(soundWinRound, base.transform); + ResetBalls(); + bg.SetActive(value: true); + blueBall.gameObject.SetActive(value: true); + orangeBall.gameObject.SetActive(value: true); + yield return new WaitForSecondsRealtime(0.2f); + GamefeelManager.instance.AddUIGameFeelOverTime(10f, 0.1f); + DoShowPoints(orangePoints, bluePoints, orangeWinner); + yield return new WaitForSecondsRealtime(0.35f); + SoundManager.Instance.Play(sound_UI_Arms_Race_A_Ball_Shrink_Go_To_Left_Corner, base.transform); + float c3 = 0f; + while (c3 < timeToScale) + { + if (orangeWinner) + { + orangeBallRT.sizeDelta = Vector2.LerpUnclamped(orangeBallRT.sizeDelta, Vector2.one * ballSmallSize, scaleCurve.Evaluate(c3 / timeToScale)); + } + else + { + blueBallRT.sizeDelta = Vector2.LerpUnclamped(blueBallRT.sizeDelta, Vector2.one * ballSmallSize, scaleCurve.Evaluate(c3 / timeToScale)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + yield return new WaitForSecondsRealtime(timeBetween); + c3 = 0f; + while (c3 < timeToMove) + { + if (orangeWinner) + { + orangeBall.position = Vector3.LerpUnclamped(orangeBall.position, UIHandler.instance.roundCounterSmall.GetPointPos(0), scaleCurve.Evaluate(c3 / timeToMove)); + } + else + { + blueBall.position = Vector3.LerpUnclamped(blueBall.position, UIHandler.instance.roundCounterSmall.GetPointPos(1), scaleCurve.Evaluate(c3 / timeToMove)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + SoundManager.Instance.Play(sound_UI_Arms_Race_B_Ball_Go_Down_Then_Expand, base.transform); + if (orangeWinner) + { + orangeBall.position = UIHandler.instance.roundCounterSmall.GetPointPos(0); + } + else + { + blueBall.position = UIHandler.instance.roundCounterSmall.GetPointPos(1); + } + yield return new WaitForSecondsRealtime(timeBetween); + c3 = 0f; + while (c3 < timeToMove) + { + if (!orangeWinner) + { + orangeBall.position = Vector3.LerpUnclamped(orangeBall.position, CardChoiceVisuals.instance.transform.position, scaleCurve.Evaluate(c3 / timeToMove)); + } + else + { + blueBall.position = Vector3.LerpUnclamped(blueBall.position, CardChoiceVisuals.instance.transform.position, scaleCurve.Evaluate(c3 / timeToMove)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + if (!orangeWinner) + { + orangeBall.position = CardChoiceVisuals.instance.transform.position; + } + else + { + blueBall.position = CardChoiceVisuals.instance.transform.position; + } + yield return new WaitForSecondsRealtime(timeBetween); + c3 = 0f; + while (c3 < timeToScale) + { + if (!orangeWinner) + { + orangeBallRT.sizeDelta = Vector2.LerpUnclamped(orangeBallRT.sizeDelta, Vector2.one * bigBallScale, scaleCurve.Evaluate(c3 / timeToScale)); + } + else + { + blueBallRT.sizeDelta = Vector2.LerpUnclamped(blueBallRT.sizeDelta, Vector2.one * bigBallScale, scaleCurve.Evaluate(c3 / timeToScale)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + SoundManager.Instance.Play(sound_UI_Arms_Race_C_Ball_Pop_Shake, base.transform); + GamefeelManager.instance.AddUIGameFeelOverTime(10f, 0.2f); + CardChoiceVisuals.instance.Show(orangeWinner ? 1 : 0); + UIHandler.instance.roundCounterSmall.UpdateRounds(orangeRounds, blueRounds); + UIHandler.instance.roundCounterSmall.UpdatePoints(0, 0); + DoShowPoints(0, 0, orangeWinner); + Close(); + } + + private void MoveTowards() + { + } + + public IEnumerator DoSequence(int currentOrange, int currentBlue, bool orangeWinner) + { + yield return new WaitForSecondsRealtime(0.45f); + SoundManager.Instance.Play(soundWinRound, base.transform); + ResetBalls(); + bg.SetActive(value: true); + blueBall.gameObject.SetActive(value: true); + orangeBall.gameObject.SetActive(value: true); + yield return new WaitForSecondsRealtime(0.2f); + GamefeelManager.instance.AddUIGameFeelOverTime(10f, 0.1f); + DoShowPoints(currentOrange, currentBlue, orangeWinner); + yield return new WaitForSecondsRealtime(1.8f); + orangeBall.GetComponent<CurveAnimation>().PlayOut(); + blueBall.GetComponent<CurveAnimation>().PlayOut(); + yield return new WaitForSecondsRealtime(0.25f); + Close(); + } + + public void DoShowPoints(int currentOrange, int currentBlue, bool orangeWinner) + { + orangeFill.fillAmount = (float)currentOrange * 0.5f; + blueFill.fillAmount = (float)currentBlue * 0.5f; + if (orangeWinner) + { + text.color = PlayerSkinBank.GetPlayerSkinColors(0).winText; + } + else + { + text.color = PlayerSkinBank.GetPlayerSkinColors(1).winText; + } + if (orangeWinner) + { + if (currentOrange > 1) + { + RoundOrange(); + } + else + { + HalfOrange(); + } + } + else if (currentBlue > 1) + { + RoundOBlue(); + } + else + { + HalfBlue(); + } + } + + private void Close() + { + text.text = ""; + bg.SetActive(value: false); + blueBall.gameObject.SetActive(value: false); + orangeBall.gameObject.SetActive(value: false); + } + + private void HalfOrange() + { + text.text = "HALF ORANGE"; + } + + private void RoundOrange() + { + text.text = "ROUND ORANGE"; + } + + private void HalfBlue() + { + text.text = "HALF BLUE"; + } + + private void RoundOBlue() + { + text.text = "ROUND BLUE"; + } + + private void Update() + { + } +} diff --git a/GameCode/PopUpHandler.cs b/GameCode/PopUpHandler.cs new file mode 100644 index 0000000..198c9b8 --- /dev/null +++ b/GameCode/PopUpHandler.cs @@ -0,0 +1,97 @@ +using System; +using UnityEngine; + +public class PopUpHandler : MonoBehaviour +{ + public enum YesNo + { + Yes, + No + } + + public CurveAnimation yesAnim; + + public CurveAnimation noAnim; + + public bool isPicking; + + public GeneralParticleSystem yesPart; + + public GeneralParticleSystem noPart; + + public GeneralInput playerInput; + + private Action<YesNo> fToCall; + + private YesNo currentYesNo; + + private void Start() + { + } + + public void StartPicking(Player player, Action<YesNo> functionToCall) + { + PlayerManager.instance.RevivePlayers(); + PlayerManager.instance.SetPlayersSimulated(simulated: true); + isPicking = true; + fToCall = functionToCall; + yesPart.particleSettings.color = PlayerManager.instance.GetColorFromTeam(player.teamID).winText; + noPart.particleSettings.color = PlayerManager.instance.GetColorFromTeam(player.teamID).winText; + yesPart.loop = true; + yesPart.Play(); + yesAnim.PlayIn(); + noPart.loop = true; + noPart.Play(); + } + + private void DonePicking() + { + fToCall(currentYesNo); + isPicking = false; + noPart.loop = false; + yesPart.loop = false; + } + + private void Update() + { + if (!isPicking) + { + return; + } + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + if (PlayerManager.instance.players[i].data.view.IsMine) + { + playerInput = PlayerManager.instance.players[i].data.input; + if (playerInput.stickPressDir == GeneralInput.StickDirection.Left && currentYesNo != 0) + { + currentYesNo = YesNo.Yes; + UpdateUI(); + } + if (playerInput.stickPressDir == GeneralInput.StickDirection.Right && currentYesNo != YesNo.No) + { + currentYesNo = YesNo.No; + UpdateUI(); + } + if (playerInput.acceptWasPressed) + { + DonePicking(); + } + } + } + } + + private void UpdateUI() + { + if (currentYesNo == YesNo.Yes) + { + yesAnim.PlayIn(); + noAnim.PlayOut(); + } + else + { + yesAnim.PlayOut(); + noAnim.PlayIn(); + } + } +} diff --git a/GameCode/Populate.cs b/GameCode/Populate.cs new file mode 100644 index 0000000..b59ce59 --- /dev/null +++ b/GameCode/Populate.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using UnityEngine; + +public class Populate : MonoBehaviour +{ + public GameObject target; + + public bool setTargetsActive; + + public bool includeTargetInList = true; + + public int times = 5; + + public List<GameObject> DoPopulate() + { + List<GameObject> list = new List<GameObject>(); + if (includeTargetInList) + { + list.Add(target); + } + for (int i = 0; i < times; i++) + { + GameObject gameObject = Object.Instantiate(target, target.transform.position, base.transform.transform.rotation, base.transform); + gameObject.transform.localScale = target.transform.localScale; + list.Add(gameObject); + if (setTargetsActive) + { + gameObject.SetActive(value: true); + } + } + return list; + } + + public List<T> DoPopulate<T>(bool addComponentIfMissing = true) where T : MonoBehaviour + { + List<T> list = new List<T>(); + if (includeTargetInList && target != null) + { + T val = target.GetComponent<T>(); + if ((Object)val == (Object)null && addComponentIfMissing) + { + val = target.AddComponent<T>(); + } + if (!((Object)val != (Object)null)) + { + Debug.LogError("Could not find component"); + return null; + } + list.Add(val); + } + for (int i = 0; i < times; i++) + { + GameObject gameObject = Object.Instantiate(target, target.transform.position, base.transform.transform.rotation, target.transform.transform.parent); + gameObject.transform.localScale = target.transform.localScale; + T val2 = gameObject.GetComponent<T>(); + if ((Object)val2 == (Object)null && addComponentIfMissing) + { + val2 = gameObject.AddComponent<T>(); + } + if ((Object)val2 != (Object)null) + { + list.Add(val2); + } + if (setTargetsActive) + { + gameObject.SetActive(value: true); + } + } + return list; + } +} diff --git a/GameCode/PositionNoise.cs b/GameCode/PositionNoise.cs new file mode 100644 index 0000000..07b6d8a --- /dev/null +++ b/GameCode/PositionNoise.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class PositionNoise : CardAnimation +{ + public float amount; + + public float speed = 1f; + + private float startSeed; + + private Vector3 startPos; + + private void Start() + { + startPos = base.transform.localPosition; + startSeed = Random.Range(0f, 100000f); + } + + private void Update() + { + Vector2 vector = new Vector2(Mathf.PerlinNoise(startSeed + Time.unscaledTime * speed, startSeed + Time.unscaledTime * speed - 0.5f), Mathf.PerlinNoise(startSeed + Time.unscaledTime * speed, startSeed + Time.unscaledTime * speed) - 0.5f); + base.transform.localPosition = startPos + (Vector3)vector * amount; + } +} diff --git a/GameCode/PowerUps.cs b/GameCode/PowerUps.cs new file mode 100644 index 0000000..64f3ae7 --- /dev/null +++ b/GameCode/PowerUps.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +public class PowerUps : MonoBehaviour +{ + public GameObject weapon; + + public float damage = 1f; + + public float knockback = 1f; + + public float attackSpeed = 1f; + + public float projectileSpeed = 1f; + + public float spread; + + public float evenSpread; + + public float gravity = 1f; + + public int projectiles = 1; + + public int reflects; + + public int smartBounce; + + public int bulletPortal; + + public int randomBounces; + + public int bursts = 1; + + public float lifeSteal; + + public float projectileSize; + + public float damageAfterDistanceMultiplier = 1f; + + public float distancceForDamageAfterDistanceMultiplier = 5f; + + public float timeToReachFullMovementMultiplier; + + public ObjectsToSpawn[] objectsToSpawn; + + public bool waveMovement; + + public bool teleport; + + public bool spawnSkelletonSquare; + + public float explodeNearEnemyRange; + + public float explodeNearEnemyDamage; + + public float hitMovementMultiplier = 1f; + + private void Start() + { + EffectWeapon(weapon); + } + + private void EffectWeapon(GameObject weapon) + { + weapon.GetComponent<Gun>(); + } +} diff --git a/GameCode/ProjectileCollision.cs b/GameCode/ProjectileCollision.cs new file mode 100644 index 0000000..8833660 --- /dev/null +++ b/GameCode/ProjectileCollision.cs @@ -0,0 +1,86 @@ +using UnityEngine; + +public class ProjectileCollision : ProjectileHitSurface +{ + public bool scaleWithDMG; + + public float health; + + private float deathThreshold; + + private RayHitReflect reflect; + + private ChildRPC rpc; + + private float startDMG; + + private bool hasCollided; + + public GameObject sparkObject; + + private void Start() + { + rpc = GetComponentInParent<ChildRPC>(); + rpc.childRPCs.Add("KillBullet", Die); + reflect = GetComponentInParent<RayHitReflect>(); + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + if (scaleWithDMG) + { + base.transform.localScale *= (componentInParent.damage / 55f + 1f) * 0.5f; + health = componentInParent.damage; + } + startDMG = componentInParent.damage; + deathThreshold = health * 0.1f; + } + + public override HasToStop HitSurface(HitInfo hit, GameObject projectile) + { + if (Vector2.Angle(base.transform.root.forward, projectile.transform.forward) < 45f) + { + return HasToStop.HasToStop; + } + if ((bool)reflect && reflect.timeOfBounce + 0.5f > Time.time) + { + return HasToStop.HasToStop; + } + ProjectileCollision componentInChildren = projectile.GetComponentInChildren<ProjectileCollision>(); + if ((bool)componentInChildren) + { + reflect = componentInChildren.GetComponentInParent<RayHitReflect>(); + if ((bool)reflect && reflect.timeOfBounce + 0.5f > Time.time) + { + return HasToStop.HasToStop; + } + float dmg = health; + float dmg2 = componentInChildren.health; + componentInChildren.TakeDamage(dmg); + TakeDamage(dmg2); + } + return HasToStop.HasToStop; + } + + public void TakeDamage(float dmg) + { + if (!hasCollided) + { + health -= dmg; + if ((bool)rpc && health < deathThreshold) + { + rpc.CallFunction("KillBullet"); + } + } + } + + public void Die() + { + if (!hasCollided) + { + hasCollided = true; + RaycastHit2D raycastHit2D = default(RaycastHit2D); + raycastHit2D.normal = -base.transform.root.forward; + raycastHit2D.point = base.transform.position; + Object.Instantiate(sparkObject, base.transform.position, base.transform.rotation).transform.localScale = Vector3.one * ((startDMG / 55f + 1f) * 0.5f); + GetComponentInParent<ProjectileHit>().Hit(HitInfo.GetHitInfo(raycastHit2D), forceCall: true); + } + } +} diff --git a/GameCode/ProjectileHit.cs b/GameCode/ProjectileHit.cs new file mode 100644 index 0000000..1bb6175 --- /dev/null +++ b/GameCode/ProjectileHit.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +public class ProjectileHit : RayHit +{ + [HideInInspector] + public bool canPushBox = true; + + public float force; + + public float damage; + + public float stun; + + public float percentageDamage; + + public float movementSlow; + + public float shake; + + public ObjectsToSpawn[] objectsToSpawn; + + public PlayerSkin team; + + [HideInInspector] + public Player ownPlayer; + + [HideInInspector] + public GameObject ownWeapon; + + public AnimationCurve effectOverTimeCurve; + + [HideInInspector] + public List<RayHitEffect> effects; + + private List<HealthHandler> playersHit = new List<HealthHandler>(); + + public Color projectileColor = Color.black; + + private Action hitAction; + + private Action<HitInfo> hitActionWithData; + + [HideInInspector] + public bool unblockable; + + [HideInInspector] + public bool fullSelfDamage; + + [FoldoutGroup("Special", 0)] + public UnityEvent deathEvent; + + [FoldoutGroup("Special", 0)] + public bool destroyOnBlock; + + [FoldoutGroup("Special", 0)] + public float holdPlayerFor = 0.5f; + + [FoldoutGroup("Special", 0)] + public string bulletImmunity = ""; + + private SpawnedAttack spawnedAttack; + + [HideInInspector] + public float sinceReflect = 10f; + + [HideInInspector] + public float dealDamageMultiplierr = 1f; + + internal bool hasControl; + + [HideInInspector] + public PhotonView view; + + private MoveTransform move; + + [HideInInspector] + public bool bulletCanDealDeamage = true; + + [HideInInspector] + public bool isAllowedToSpawnObjects = true; + + public bool sendCollisions = true; + + public Dictionary<string, Action> customActions = new Dictionary<string, Action>(); + + public Dictionary<string, Action<Vector2, Vector2>> customActionsV2V2 = new Dictionary<string, Action<Vector2, Vector2>>(); + + private void Start() + { + move = GetComponent<MoveTransform>(); + view = GetComponent<PhotonView>(); + effects.AddRange(GetComponentsInChildren<RayHitEffect>()); + effects.Sort((RayHitEffect p1, RayHitEffect p2) => p2.priority.CompareTo(p1.priority)); + spawnedAttack = GetComponent<SpawnedAttack>(); + if ((bool)spawnedAttack && !ownPlayer) + { + ownPlayer = spawnedAttack.spawner; + } + if ((bool)ownPlayer && !fullSelfDamage) + { + StartCoroutine(HoldPlayer(ownPlayer.GetComponent<HealthHandler>())); + } + damage *= base.transform.localScale.x; + force *= Mathf.Pow(damage / 55f, 2f); + } + + public void ResortHitEffects() + { + effects.Sort((RayHitEffect p1, RayHitEffect p2) => p2.priority.CompareTo(p1.priority)); + } + + private IEnumerator HoldPlayer(HealthHandler player) + { + if ((bool)player) + { + playersHit.Add(player); + } + yield return new WaitForSeconds(holdPlayerFor); + if (playersHit.Contains(player)) + { + playersHit.Remove(player); + } + } + + private void Update() + { + sinceReflect += TimeHandler.deltaTime; + } + + public void AddPlayerToHeld(HealthHandler health) + { + StartCoroutine(HoldPlayer(health)); + } + + public void RemoveOwnPlayerFromPlayersHit() + { + if ((bool)ownPlayer && playersHit.Contains(ownPlayer.GetComponent<HealthHandler>())) + { + playersHit.Remove(ownPlayer.GetComponent<HealthHandler>()); + } + } + + public override void Hit(HitInfo hit, bool forceCall = false) + { + int num = -1; + if ((bool)hit.transform) + { + PhotonView component = hit.transform.root.GetComponent<PhotonView>(); + if ((bool)component) + { + num = component.ViewID; + } + } + int num2 = -1; + if (num == -1) + { + Collider2D[] componentsInChildren = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i] == hit.collider) + { + num2 = i; + } + } + } + HealthHandler healthHandler = null; + if ((bool)hit.transform) + { + healthHandler = hit.transform.GetComponent<HealthHandler>(); + } + bool flag = false; + if ((bool)healthHandler) + { + if (playersHit.Contains(healthHandler)) + { + return; + } + if (view.IsMine && healthHandler.GetComponent<Block>().IsBlocking()) + { + flag = true; + } + StartCoroutine(HoldPlayer(healthHandler)); + } + if (view.IsMine || forceCall) + { + if (sendCollisions) + { + view.RPC("RPCA_DoHit", RpcTarget.All, hit.point, hit.normal, (Vector2)move.velocity, num, num2, flag); + } + else + { + RPCA_DoHit(hit.point, hit.normal, move.velocity, num, num2, flag); + } + } + } + + [PunRPC] + public void RPCA_DoHit(Vector2 hitPoint, Vector2 hitNormal, Vector2 vel, int viewID = -1, int colliderID = -1, bool wasBlocked = false) + { + HitInfo hitInfo = new HitInfo(); + if ((bool)move) + { + move.velocity = vel; + } + hitInfo.point = hitPoint; + hitInfo.normal = hitNormal; + hitInfo.collider = null; + if (viewID != -1) + { + PhotonView photonView = PhotonNetwork.GetPhotonView(viewID); + hitInfo.collider = photonView.GetComponentInChildren<Collider2D>(); + hitInfo.transform = photonView.transform; + } + else if (colliderID != -1) + { + hitInfo.collider = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>()[colliderID]; + hitInfo.transform = hitInfo.collider.transform; + } + HealthHandler healthHandler = null; + if ((bool)hitInfo.transform) + { + healthHandler = hitInfo.transform.GetComponent<HealthHandler>(); + } + if (isAllowedToSpawnObjects) + { + base.transform.position = hitInfo.point; + } + if ((bool)hitInfo.collider) + { + ProjectileHitSurface component = hitInfo.collider.GetComponent<ProjectileHitSurface>(); + if ((bool)component && component.HitSurface(hitInfo, base.gameObject) == ProjectileHitSurface.HasToStop.HasToStop) + { + return; + } + } + if ((bool)healthHandler) + { + Block component2 = healthHandler.GetComponent<Block>(); + if (wasBlocked) + { + component2.DoBlock(base.gameObject, base.transform.forward, hitInfo.point); + if (destroyOnBlock) + { + DestroyMe(); + } + sinceReflect = 0f; + return; + } + CharacterStatModifiers component3 = healthHandler.GetComponent<CharacterStatModifiers>(); + if (movementSlow != 0f && !wasBlocked) + { + component3.RPCA_AddSlow(movementSlow); + } + } + float num = 1f; + PlayerVelocity playerVelocity = null; + if ((bool)hitInfo.transform) + { + playerVelocity = hitInfo.transform.GetComponentInParent<PlayerVelocity>(); + } + if ((bool)hitInfo.collider) + { + Damagable componentInParent = hitInfo.collider.GetComponentInParent<Damagable>(); + if ((bool)componentInParent) + { + if ((bool)healthHandler && percentageDamage != 0f) + { + damage += healthHandler.GetComponent<CharacterData>().maxHealth * percentageDamage; + } + if (hasControl) + { + if (bulletImmunity != "" && (bool)healthHandler) + { + healthHandler.GetComponent<PlayerImmunity>().IsImune(0.1f, (bulletCanDealDeamage ? damage : 1f) * dealDamageMultiplierr, bulletImmunity); + } + if ((bool)componentInParent.GetComponent<DamagableEvent>()) + { + componentInParent.CallTakeDamage(base.transform.forward * damage * dealDamageMultiplierr, hitInfo.point, ownWeapon, ownPlayer); + } + else + { + componentInParent.CallTakeDamage(base.transform.forward * (bulletCanDealDeamage ? damage : 1f) * dealDamageMultiplierr, hitInfo.point, ownWeapon, ownPlayer); + } + } + } + } + if ((bool)playerVelocity) + { + float num2 = 1f; + float num3 = Mathf.Clamp(playerVelocity.mass / 100f * num2, 0f, 1f) * num2; + float num4 = 1f; + playerVelocity.AddForce(-playerVelocity.velocity * 0.1f * playerVelocity.mass, ForceMode2D.Impulse); + if ((bool)healthHandler) + { + num *= 3f; + if (hasControl) + { + healthHandler.CallTakeForce(base.transform.forward * num4 * num3 * force); + } + } + } + if (isAllowedToSpawnObjects && !wasBlocked) + { + GamefeelManager.GameFeel(base.transform.forward * num * shake); + DynamicParticles.instance.PlayBulletHit(damage, base.transform, hitInfo, projectileColor); + for (int i = 0; i < objectsToSpawn.Length; i++) + { + ObjectsToSpawn.SpawnObject(base.transform, hitInfo, objectsToSpawn[i], healthHandler, team, damage, spawnedAttack, wasBlocked); + } + base.transform.position = hitInfo.point + hitInfo.normal * 0.01f; + } + if ((bool)hitInfo.transform) + { + NetworkPhysicsObject component4 = hitInfo.transform.GetComponent<NetworkPhysicsObject>(); + if ((bool)component4 && canPushBox) + { + component4.BulletPush(base.transform.forward * (force * 0.5f + damage * 100f), hitInfo.transform.InverseTransformPoint(hitInfo.point), spawnedAttack.spawner.data); + } + } + bool flag = false; + if (effects != null && effects.Count != 0) + { + for (int j = 0; j < effects.Count; j++) + { + HasToReturn num5 = effects[j].DoHitEffect(hitInfo); + if (num5 == HasToReturn.hasToReturn) + { + flag = true; + } + if (num5 == HasToReturn.hasToReturnNow) + { + return; + } + } + } + if (!flag) + { + if (hitAction != null) + { + hitAction(); + } + if (hitActionWithData != null) + { + hitActionWithData(hitInfo); + } + deathEvent.Invoke(); + DestroyMe(); + } + } + + private void DestroyMe() + { + if ((bool)view) + { + if (view.IsMine) + { + PhotonNetwork.Destroy(base.gameObject); + } + } + else + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + [PunRPC] + public void RPCA_CallCustomAction(string actionKey) + { + customActions[actionKey](); + } + + [PunRPC] + public void RPCA_CallCustomActionV2V2(string actionKey, Vector2 v1, Vector2 v2) + { + customActionsV2V2[actionKey](v1, v2); + } + + public void AddHitAction(Action action) + { + hitAction = (Action)Delegate.Combine(hitAction, action); + } + + public void AddHitActionWithData(Action<HitInfo> action) + { + hitActionWithData = (Action<HitInfo>)Delegate.Combine(hitActionWithData, action); + } +} diff --git a/GameCode/ProjectileHitEmpower.cs b/GameCode/ProjectileHitEmpower.cs new file mode 100644 index 0000000..3672ce1 --- /dev/null +++ b/GameCode/ProjectileHitEmpower.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +public class ProjectileHitEmpower : RayHitEffect +{ + private bool done; + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (done) + { + return HasToReturn.canContinue; + } + GetComponentInParent<SpawnedAttack>().spawner.data.block.DoBlockAtPosition(firstBlock: true, dontSetCD: true, BlockTrigger.BlockTriggerType.Empower, hit.point - (Vector2)base.transform.forward * 0.05f, onlyBlockEffects: true); + done = true; + return HasToReturn.canContinue; + } +} diff --git a/GameCode/ProjectileHitSurface.cs b/GameCode/ProjectileHitSurface.cs new file mode 100644 index 0000000..04ae8f6 --- /dev/null +++ b/GameCode/ProjectileHitSurface.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public abstract class ProjectileHitSurface : MonoBehaviour +{ + public enum HasToStop + { + HasToStop, + CanKeepGoing + } + + public abstract HasToStop HitSurface(HitInfo hit, GameObject projectile); +} diff --git a/GameCode/ProjectileHitSurfaceShield.cs b/GameCode/ProjectileHitSurfaceShield.cs new file mode 100644 index 0000000..1587a0c --- /dev/null +++ b/GameCode/ProjectileHitSurfaceShield.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class ProjectileHitSurfaceShield : ProjectileHitSurface +{ + public override HasToStop HitSurface(HitInfo hit, GameObject projectile) + { + if (Vector3.Angle(base.transform.parent.forward, projectile.transform.forward) < 90f) + { + return HasToStop.HasToStop; + } + return HasToStop.CanKeepGoing; + } +} diff --git a/GameCode/ProjectileInit.cs b/GameCode/ProjectileInit.cs new file mode 100644 index 0000000..3200eac --- /dev/null +++ b/GameCode/ProjectileInit.cs @@ -0,0 +1,49 @@ +using Photon.Pun; +using UnityEngine; + +public class ProjectileInit : MonoBehaviour +{ + private Gun[] guns; + + [PunRPC] + internal void RPCA_Init(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.GetPlayerWithActorID(senderID).data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + internal void OFFLINE_Init(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.players[senderID].data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + [PunRPC] + internal void RPCA_Init_SeparateGun(int senderID, int gunID, int nrOfProj, float dmgM, float randomSeed) + { + GetChildGunWithID(gunID, PlayerManager.instance.GetPlayerWithActorID(senderID).gameObject).BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + internal void OFFLINE_Init_SeparateGun(int senderID, int gunID, int nrOfProj, float dmgM, float randomSeed) + { + GetChildGunWithID(gunID, PlayerManager.instance.players[senderID].gameObject).BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + private Gun GetChildGunWithID(int id, GameObject player) + { + if (guns == null) + { + guns = player.GetComponentsInChildren<Gun>(); + } + return guns[id]; + } + + [PunRPC] + internal void RPCA_Init_noAmmoUse(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.GetPlayerWithActorID(senderID).data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed, useAmmo: false); + } + + internal void OFFLINE_Init_noAmmoUse(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.players[senderID].data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed, useAmmo: false); + } +} diff --git a/GameCode/ProjectilesToSpawn.cs b/GameCode/ProjectilesToSpawn.cs new file mode 100644 index 0000000..e92840b --- /dev/null +++ b/GameCode/ProjectilesToSpawn.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine; + +[Serializable] +public class ProjectilesToSpawn +{ + public GameObject objectToSpawn; + + public int numberOfSpawns = 1; +} diff --git a/GameCode/PublicInt.cs b/GameCode/PublicInt.cs new file mode 100644 index 0000000..98472b9 --- /dev/null +++ b/GameCode/PublicInt.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class PublicInt : MonoBehaviour +{ + public int theInt; +} diff --git a/GameCode/QuitButton.cs b/GameCode/QuitButton.cs new file mode 100644 index 0000000..a441c3e --- /dev/null +++ b/GameCode/QuitButton.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class QuitButton : MonoBehaviour +{ + public void Quit() + { + Application.Quit(); + } +} diff --git a/GameCode/RadarShot.cs b/GameCode/RadarShot.cs new file mode 100644 index 0000000..ad589db --- /dev/null +++ b/GameCode/RadarShot.cs @@ -0,0 +1,61 @@ +using System.Collections; +using UnityEngine; + +public class RadarShot : MonoBehaviour +{ + private WeaponHandler wh; + + private Player player; + + public ParticleSystem[] boops; + + public float range = 12f; + + private void Start() + { + wh = GetComponentInParent<WeaponHandler>(); + player = GetComponentInParent<Player>(); + } + + public void Go() + { + Player closestPlayerInTeam = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(player.teamID), needVision: true); + if ((bool)closestPlayerInTeam && Vector2.Distance(player.transform.position, closestPlayerInTeam.transform.position) < range) + { + StartCoroutine(FollowTarget(closestPlayerInTeam)); + if (player.data.view.IsMine) + { + StartCoroutine(ShootAttacks(closestPlayerInTeam, GetComponent<AttackLevel>().attackLevel)); + } + } + } + + private IEnumerator ShootAttacks(Player target, int shots) + { + for (int i = 0; i < shots; i++) + { + yield return new WaitForSeconds(0.1f); + wh.gun.forceShootDir = wh.gun.GetRangeCompensation(Vector3.Distance(target.transform.position, player.transform.position)) * Vector3.up + target.transform.position - player.transform.position; + wh.gun.Attack(0f, forceAttack: true, 1f, 1f, useAmmo: false); + wh.gun.forceShootDir = Vector3.zero; + } + } + + private IEnumerator FollowTarget(Player target) + { + for (int i = 0; i < boops.Length; i++) + { + boops[i].Play(); + } + float c = 0f; + while (c < 1f) + { + c += TimeHandler.deltaTime; + for (int j = 0; j < boops.Length; j++) + { + boops[j].transform.position = target.transform.position; + } + yield return null; + } + } +} diff --git a/GameCode/Rage.cs b/GameCode/Rage.cs new file mode 100644 index 0000000..0e514dd --- /dev/null +++ b/GameCode/Rage.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class Rage : MonoBehaviour +{ + private Player player; + + private AttackLevel level; + + public AnimationCurve curve; + + public AnimationCurve partCurve; + + private ParticleSystem.EmissionModule part; + + private void Start() + { + player = GetComponentInParent<Player>(); + level = GetComponentInParent<AttackLevel>(); + part = GetComponentInChildren<ParticleSystem>().emission; + player.data.SetWobbleObjectChild(GetComponentInChildren<ParticleSystem>().transform); + } + + private void Update() + { + float healthPercentage = player.data.HealthPercentage; + player.data.stats.rageSpeed = Mathf.Pow(curve.Evaluate(healthPercentage), level.LevelScale()); + part.rateOverTime = partCurve.Evaluate(player.data.stats.rageSpeed); + } +} diff --git a/GameCode/RayCastTrail.cs b/GameCode/RayCastTrail.cs new file mode 100644 index 0000000..4d508bd --- /dev/null +++ b/GameCode/RayCastTrail.cs @@ -0,0 +1,106 @@ +using System.Collections; +using System.Linq; +using UnityEngine; + +public class RayCastTrail : MonoBehaviour +{ + public LayerMask mask; + + public LayerMask playerMask; + + public LayerMask ignoreWallsMask; + + public int teamID = -1; + + private float timeAtSpawn; + + public float size; + + public float extraSize; + + private MoveTransform move; + + private Vector3 lastPos; + + private RayHit rayHit; + + private Rigidbody2D ignoredRig; + + private void Awake() + { + timeAtSpawn = Time.time; + } + + private void Start() + { + rayHit = GetComponent<RayHit>(); + ProjectileHit component = GetComponent<ProjectileHit>(); + if ((bool)component) + { + size = Mathf.Clamp(Mathf.Pow(component.damage, 0.85f) / 400f, 0f, 100f) + 0.3f + extraSize; + } + move = GetComponent<MoveTransform>(); + lastPos = base.transform.position; + } + + private void OnEnable() + { + lastPos = base.transform.position; + } + + private void Update() + { + RaycastHit2D[] first = Physics2D.RaycastAll(lastPos, base.transform.position - lastPos, Vector3.Distance(base.transform.position, lastPos), mask); + RaycastHit2D[] second = Physics2D.CircleCastAll(lastPos, size, base.transform.position - lastPos, Vector3.Distance(base.transform.position, lastPos), playerMask); + RaycastHit2D[] array = first.Concat(second).ToArray(); + RaycastHit2D raycastHit2D = default(RaycastHit2D); + raycastHit2D.distance = float.PositiveInfinity; + for (int i = 0; i < array.Length; i++) + { + if (!array[i] || array[i].transform.root == base.transform.root) + { + continue; + } + Player component = array[i].transform.root.GetComponent<Player>(); + if ((!component || component.playerID != teamID || !(timeAtSpawn + 0.2f >= Time.time)) && (!ignoredRig || !(ignoredRig == array[i].rigidbody))) + { + ProjectileHitSurface component2 = array[i].collider.GetComponent<ProjectileHitSurface>(); + if ((!component2 || component2.HitSurface(HitInfo.GetHitInfo(array[i]), base.gameObject) != 0) && array[i].distance < raycastHit2D.distance) + { + raycastHit2D = array[i]; + } + } + } + if ((bool)raycastHit2D.transform) + { + rayHit.Hit(HitInfo.GetHitInfo(raycastHit2D)); + } + if ((bool)GridVisualizer.instance) + { + GridVisualizer.instance.BulletCall(base.transform.position); + } + lastPos = base.transform.position; + } + + public void WasBlocked() + { + timeAtSpawn = 0f; + } + + public void MoveRay() + { + lastPos = base.transform.position; + } + + public void IgnoreRigFor(Rigidbody2D rig, float time) + { + StartCoroutine(DoIgnoreRigFor(rig, time)); + } + + private IEnumerator DoIgnoreRigFor(Rigidbody2D rig, float time) + { + ignoredRig = rig; + yield return new WaitForSeconds(time); + ignoredRig = null; + } +} diff --git a/GameCode/RayHit.cs b/GameCode/RayHit.cs new file mode 100644 index 0000000..22dce01 --- /dev/null +++ b/GameCode/RayHit.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class RayHit : MonoBehaviour +{ + public abstract void Hit(HitInfo hit, bool forceCall = false); +} diff --git a/GameCode/RayHitBash.cs b/GameCode/RayHitBash.cs new file mode 100644 index 0000000..e56603e --- /dev/null +++ b/GameCode/RayHitBash.cs @@ -0,0 +1,80 @@ +using UnityEngine; + +public class RayHitBash : RayHitEffect +{ + public float triggerChancePerTenDamage = 0.1f; + + public float baseTriggerChance = 0.2f; + + [Space(15f)] + public float stunMultiplier = 1f; + + public float stunTimePerTenDamage = 0.1f; + + public float baseStunTime = 1f; + + public bool cannotPermaStun; + + [Space(15f)] + public float stunTimeThreshold = 0.2f; + + public float stunTimeExponent = 1f; + + public float multiplierPerTenMeterTravelled; + + private MoveTransform move; + + private float multiplier = 1f; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + multiplier = base.transform.localScale.x; + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (!hit.transform) + { + return HasToReturn.canContinue; + } + StunHandler component = hit.transform.GetComponent<StunHandler>(); + if ((bool)component) + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + float num = 25f; + if ((bool)componentInParent) + { + num = componentInParent.damage; + } + float num2 = triggerChancePerTenDamage * num * 0.1f; + num2 += baseTriggerChance; + if (Random.value < num2) + { + float num3 = baseStunTime + stunTimePerTenDamage * num * 0.1f; + SetMultiplier(); + num3 *= stunMultiplier; + num3 = Mathf.Pow(num3, stunTimeExponent); + num3 *= multiplier; + if (cannotPermaStun) + { + num3 = Mathf.Clamp(num3, 0f, GetComponentInParent<SpawnedAttack>().spawner.data.weaponHandler.gun.attackSpeed * GetComponentInParent<SpawnedAttack>().spawner.data.stats.attackSpeedMultiplier + 0.3f); + } + if (num3 > stunTimeThreshold) + { + component.AddStun(num3); + } + } + } + return HasToReturn.canContinue; + } + + private void SetMultiplier() + { + float distanceTravelled = move.distanceTravelled; + if (multiplierPerTenMeterTravelled != 0f) + { + stunMultiplier = distanceTravelled * multiplierPerTenMeterTravelled * 0.1f; + } + } +} diff --git a/GameCode/RayHitBulletSound.cs b/GameCode/RayHitBulletSound.cs new file mode 100644 index 0000000..0e3d86c --- /dev/null +++ b/GameCode/RayHitBulletSound.cs @@ -0,0 +1,60 @@ +using Sonigon; +using UnityEngine; + +public class RayHitBulletSound : RayHitEffect +{ + [Header("Sound Settings")] + public bool disableImpact; + + public bool playLocalImpact; + + public SoundEvent soundLocalImpact; + + public bool localImpactVelocityToIntensity; + + private ProjectileHit projectileHit; + + private RayHitReflect rayHitReflect; + + private MoveTransform moveTransform; + + private SoundParameterIntensity soundIntensity = new SoundParameterIntensity(); + + private void Start() + { + projectileHit = GetComponent<ProjectileHit>(); + rayHitReflect = GetComponent<RayHitReflect>(); + moveTransform = GetComponent<MoveTransform>(); + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (disableImpact) + { + return HasToReturn.canContinue; + } + if (localImpactVelocityToIntensity) + { + soundIntensity.intensity = moveTransform.velocity.magnitude; + } + if (playLocalImpact) + { + if (soundLocalImpact != null && hit.collider != null && hit.collider.tag != "Player") + { + if (localImpactVelocityToIntensity) + { + SoundManager.Instance.PlayAtPosition(soundLocalImpact, SoundManager.Instance.GetTransform(), hit.point, soundIntensity); + } + else + { + SoundManager.Instance.PlayAtPosition(soundLocalImpact, SoundManager.Instance.GetTransform(), hit.point); + } + } + } + else + { + projectileHit.ownPlayer.data.weaponHandler.gun.soundGun.PlayImpact(hit, rayHitReflect); + } + return HasToReturn.canContinue; + } +} diff --git a/GameCode/RayHitDrill.cs b/GameCode/RayHitDrill.cs new file mode 100644 index 0000000..db2ee90 --- /dev/null +++ b/GameCode/RayHitDrill.cs @@ -0,0 +1,124 @@ +using UnityEngine; + +public class RayHitDrill : RayHitEffect +{ + public float metersOfDrilling = 1f; + + private MoveTransform move; + + private ProjectileHit proj; + + public bool mainDrill; + + private ChildRPC rpc; + + private int sinceDrill = 10; + + public float speedModFlat = 0.5f; + + public float speedMod = 0.1f; + + private bool done; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + proj = GetComponentInParent<ProjectileHit>(); + proj.canPushBox = false; + RayHitDrill[] componentsInChildren = base.transform.root.GetComponentsInChildren<RayHitDrill>(); + if (componentsInChildren.Length == 1) + { + mainDrill = true; + } + bool flag = false; + int num = -1; + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].mainDrill) + { + flag = true; + num = i; + } + } + if (flag) + { + if (componentsInChildren[num] != this) + { + componentsInChildren[num].metersOfDrilling += metersOfDrilling; + } + } + else + { + mainDrill = true; + } + if (mainDrill) + { + rpc = GetComponentInParent<ChildRPC>(); + rpc.childRPCsVector2.Add("DrillStop", RPCA_Deactivate); + } + } + + private void Update() + { + if (mainDrill && proj.view.IsMine) + { + if (sinceDrill > 2 && !proj.isAllowedToSpawnObjects) + { + rpc.CallFunction("DrillStop", base.transform.position); + } + sinceDrill++; + } + } + + public void RPCA_Deactivate(Vector2 tpPos) + { + base.transform.position = tpPos; + proj.isAllowedToSpawnObjects = true; + move.simulationSpeed /= speedModFlat; + move.simulationSpeed *= move.localForce.magnitude * speedMod; + proj.sendCollisions = true; + base.transform.GetChild(0).gameObject.SetActive(value: false); + if (metersOfDrilling < 2f) + { + metersOfDrilling = -1f; + } + } + + private void OnDestroy() + { + if (mainDrill && !proj.isAllowedToSpawnObjects) + { + Object.Instantiate(GetComponentInChildren<ParticleSystem>(includeInactive: true).gameObject, base.transform.position, base.transform.rotation).SetActive(value: true); + } + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (!mainDrill) + { + return HasToReturn.canContinue; + } + if (proj.isAllowedToSpawnObjects) + { + base.transform.root.position = hit.point; + move.simulationSpeed *= speedModFlat; + move.simulationSpeed /= move.localForce.magnitude * speedMod; + base.transform.GetChild(0).gameObject.SetActive(value: true); + base.transform.GetComponentInChildren<TrailRenderer>().Clear(); + } + sinceDrill = 0; + proj.isAllowedToSpawnObjects = false; + proj.sendCollisions = false; + metersOfDrilling -= move.velocity.magnitude * TimeHandler.deltaTime * move.simulationSpeed; + if (metersOfDrilling <= 0f) + { + done = true; + return HasToReturn.canContinue; + } + if (!hit.transform || (bool)hit.transform.root.GetComponent<Player>()) + { + return HasToReturn.canContinue; + } + return HasToReturn.hasToReturnNow; + } +} diff --git a/GameCode/RayHitEffect.cs b/GameCode/RayHitEffect.cs new file mode 100644 index 0000000..647dfa8 --- /dev/null +++ b/GameCode/RayHitEffect.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public abstract class RayHitEffect : MonoBehaviour +{ + public int priority; + + public abstract HasToReturn DoHitEffect(HitInfo hit); +} diff --git a/GameCode/RayHitPoison.cs b/GameCode/RayHitPoison.cs new file mode 100644 index 0000000..240f2eb --- /dev/null +++ b/GameCode/RayHitPoison.cs @@ -0,0 +1,36 @@ +using Sonigon; +using UnityEngine; + +public class RayHitPoison : RayHitEffect +{ + [Header("Sounds")] + public SoundEvent soundEventDamageOverTime; + + [Header("Settings")] + public float time = 2f; + + public float interval = 0.5f; + + public Color color = Color.red; + + private void Start() + { + GetComponentInParent<ProjectileHit>().bulletCanDealDeamage = false; + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (!hit.transform) + { + return HasToReturn.canContinue; + } + RayHitPoison[] componentsInChildren = base.transform.root.GetComponentsInChildren<RayHitPoison>(); + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + DamageOverTime component = hit.transform.GetComponent<DamageOverTime>(); + if ((bool)component) + { + component.TakeDamageOverTime(componentInParent.damage * base.transform.forward / componentsInChildren.Length, base.transform.position, time, interval, color, soundEventDamageOverTime, GetComponentInParent<ProjectileHit>().ownWeapon, GetComponentInParent<ProjectileHit>().ownPlayer); + } + return HasToReturn.canContinue; + } +} diff --git a/GameCode/RayHitReflect.cs b/GameCode/RayHitReflect.cs new file mode 100644 index 0000000..182aa73 --- /dev/null +++ b/GameCode/RayHitReflect.cs @@ -0,0 +1,61 @@ +using System; +using UnityEngine; + +public class RayHitReflect : RayHitEffect +{ + private MoveTransform move; + + private ProjectileHit projHit; + + public int reflects = 1; + + public float speedM = 1f; + + public float dmgM = 1f; + + [HideInInspector] + public float timeOfBounce = -10000f; + + public Action<HitInfo> reflectAction; + + private void Start() + { + move = GetComponent<MoveTransform>(); + projHit = GetComponent<ProjectileHit>(); + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if ((bool)hit.transform && (bool)hit.transform.GetComponent<Player>()) + { + reflects -= 10; + } + if (reflects <= 0) + { + return HasToReturn.canContinue; + } + if (reflectAction != null) + { + reflectAction(hit); + } + move.velocity = Vector2.Reflect(move.velocity, hit.normal); + move.velocity *= speedM; + projHit.damage *= dmgM; + projHit.shake *= dmgM; + if (dmgM > 1f) + { + float num = dmgM - 1f; + num *= 0.6f; + dmgM = num + 1f; + ScaleTrailFromDamage componentInChildren = GetComponentInChildren<ScaleTrailFromDamage>(); + if ((bool)componentInChildren) + { + componentInChildren.Rescale(); + } + } + timeOfBounce = Time.time; + base.transform.position = (Vector3)hit.point + move.velocity.normalized * 0.1f; + reflects--; + return HasToReturn.hasToReturn; + } +} diff --git a/GameCode/RaycastForward.cs b/GameCode/RaycastForward.cs new file mode 100644 index 0000000..14d176f --- /dev/null +++ b/GameCode/RaycastForward.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class RaycastForward : MonoBehaviour +{ + public LayerMask mask; + + public float distance = 100f; + + public RaycastHit2D hit; + + private void LateUpdate() + { + hit = Physics2D.Raycast(base.transform.position, base.transform.forward, distance, mask); + } +} diff --git a/GameCode/RaycastSetScale.cs b/GameCode/RaycastSetScale.cs new file mode 100644 index 0000000..5c60b4c --- /dev/null +++ b/GameCode/RaycastSetScale.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class RaycastSetScale : MonoBehaviour +{ + private RaycastForward raycast; + + private void Start() + { + raycast = GetComponent<RaycastForward>(); + } + + private void LateUpdate() + { + if ((bool)raycast.hit.transform) + { + base.transform.localScale = new Vector3(base.transform.localScale.x, base.transform.localScale.y, raycast.hit.distance); + } + else + { + base.transform.localScale = new Vector3(base.transform.localScale.x, base.transform.localScale.y, raycast.distance); + } + } +} diff --git a/GameCode/ReflectEvent.cs b/GameCode/ReflectEvent.cs new file mode 100644 index 0000000..eb3dab6 --- /dev/null +++ b/GameCode/ReflectEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine.Events; + +public class ReflectEvent : RayHitEffect +{ + public UnityEvent bounceEvent; + + public override HasToReturn DoHitEffect(HitInfo hit) + { + bounceEvent.Invoke(); + return HasToReturn.canContinue; + } +} diff --git a/GameCode/RegenerateAfterStandStill.cs b/GameCode/RegenerateAfterStandStill.cs new file mode 100644 index 0000000..471aa10 --- /dev/null +++ b/GameCode/RegenerateAfterStandStill.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class RegenerateAfterStandStill : MonoBehaviour +{ + private CharacterData data; + + public float heal = 2f; + + private PlayerInRangeTrigger trigger; + + private void Start() + { + trigger = GetComponent<PlayerInRangeTrigger>(); + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + if (trigger.inRange) + { + data.healthHandler.Heal(heal); + } + } +} diff --git a/GameCode/RegionSelector.cs b/GameCode/RegionSelector.cs new file mode 100644 index 0000000..439279d --- /dev/null +++ b/GameCode/RegionSelector.cs @@ -0,0 +1,23 @@ +using TMPro; +using UnityEngine; + +public class RegionSelector : MonoBehaviour +{ + private TMP_Dropdown dropDown; + + public static string region = ""; + + private void Start() + { + dropDown = GetComponent<TMP_Dropdown>(); + region = dropDown.options[PlayerPrefs.GetInt("Region", 0)].text; + dropDown.value = PlayerPrefs.GetInt("Region", 0); + NetworkConnectionHandler.instance.hasRegionSelect = true; + } + + public void OnValueChanged() + { + PlayerPrefs.SetInt("Region", dropDown.value); + region = dropDown.options[dropDown.value].text; + } +} diff --git a/GameCode/ReloadTigger.cs b/GameCode/ReloadTigger.cs new file mode 100644 index 0000000..3a4c093 --- /dev/null +++ b/GameCode/ReloadTigger.cs @@ -0,0 +1,40 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class ReloadTigger : MonoBehaviour +{ + public UnityEvent reloadDoneEvent; + + public UnityEvent outOfAmmoEvent; + + private void Start() + { + CharacterStatModifiers componentInParent = GetComponentInParent<CharacterStatModifiers>(); + componentInParent.OnReloadDoneAction = (Action<int>)Delegate.Combine(componentInParent.OnReloadDoneAction, new Action<int>(OnReloadDone)); + CharacterStatModifiers componentInParent2 = GetComponentInParent<CharacterStatModifiers>(); + componentInParent2.OutOfAmmpAction = (Action<int>)Delegate.Combine(componentInParent2.OutOfAmmpAction, new Action<int>(OnOutOfAmmo)); + } + + private void OnDestroy() + { + CharacterStatModifiers componentInParent = GetComponentInParent<CharacterStatModifiers>(); + componentInParent.OnReloadDoneAction = (Action<int>)Delegate.Remove(componentInParent.OnReloadDoneAction, new Action<int>(OnReloadDone)); + CharacterStatModifiers componentInParent2 = GetComponentInParent<CharacterStatModifiers>(); + componentInParent2.OutOfAmmpAction = (Action<int>)Delegate.Remove(componentInParent2.OutOfAmmpAction, new Action<int>(OnOutOfAmmo)); + } + + private void OnReloadDone(int bulletsReloaded) + { + reloadDoneEvent.Invoke(); + } + + private void OnOutOfAmmo(int bulletsReloaded) + { + outOfAmmoEvent.Invoke(); + } + + private void Update() + { + } +} diff --git a/GameCode/RemoteControl.cs b/GameCode/RemoteControl.cs new file mode 100644 index 0000000..c0049bb --- /dev/null +++ b/GameCode/RemoteControl.cs @@ -0,0 +1,128 @@ +using Photon.Pun; +using Sonigon; +using SoundImplementation; +using UnityEngine; + +public class RemoteControl : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundRemoteSteeringLoop; + + private bool soundIsPlaying; + + [Header("Settings")] + public bool snap; + + public float rotateSpeed = 1f; + + private SpawnedAttack spawned; + + private MoveTransform move; + + private float startVelocity; + + private bool isOn; + + private ProjectileHit hit; + + private ParticleSystem part; + + public ParticleSystem boopPart; + + private float c; + + private PhotonView view; + + private ChildRPC childRPC; + + private void OnDestroy() + { + if (soundRemoteSteeringLoop != null && spawned != null && spawned.spawner != null && soundIsPlaying) + { + soundIsPlaying = false; + SoundStaticRemoteControl.remoteControl.AddNumberOf(spawned.spawner.transform, -1); + if (SoundStaticRemoteControl.remoteControl.GetNumberOf(spawned.spawner.transform) <= 0) + { + SoundManager.Instance.Stop(soundRemoteSteeringLoop, spawned.spawner.transform); + } + } + } + + private void Start() + { + childRPC = GetComponentInParent<ChildRPC>(); + view = GetComponentInParent<PhotonView>(); + hit = GetComponentInParent<ProjectileHit>(); + move = GetComponentInParent<MoveTransform>(); + spawned = GetComponentInParent<SpawnedAttack>(); + startVelocity = move.velocity.magnitude; + part = GetComponentInChildren<ParticleSystem>(); + GetComponentInParent<SyncProjectile>().active = true; + if (soundRemoteSteeringLoop != null && spawned != null && spawned.spawner != null && !soundIsPlaying) + { + soundIsPlaying = true; + if (SoundStaticRemoteControl.remoteControl.GetNumberOf(spawned.spawner.transform) <= 0) + { + SoundManager.Instance.Play(soundRemoteSteeringLoop, spawned.spawner.transform); + } + SoundStaticRemoteControl.remoteControl.AddNumberOf(spawned.spawner.transform, 1); + } + } + + public void ToggleOn(bool isOn) + { + } + + private void Update() + { + if (!view.IsMine) + { + return; + } + Vector3 zero = Vector3.zero; + if (spawned.spawner.data.playerActions.Device != null) + { + zero = spawned.spawner.data.input.aimDirection; + } + else + { + zero = MainCam.instance.cam.ScreenToWorldPoint(Input.mousePosition) - base.transform.position; + zero.z = 0f; + zero.Normalize(); + } + zero += Vector3.Cross(Vector3.forward, zero) * move.selectedSpread; + c += TimeHandler.deltaTime; + if (snap) + { + if (spawned.spawner.data.block.blockedThisFrame) + { + part.Play(); + move.velocity *= -1f; + base.enabled = false; + } + } + else if (zero.magnitude > 0.2f && hit.sinceReflect > 2f) + { + move.velocity = Vector3.RotateTowards(move.velocity, zero.normalized * startVelocity, rotateSpeed * TimeHandler.deltaTime, rotateSpeed * TimeHandler.deltaTime * 10f); + if (c > 0.1f) + { + boopPart.transform.parent.rotation = Quaternion.LookRotation(zero); + boopPart?.Emit(1); + c = 0f; + } + if (!isOn) + { + move.simulateGravity++; + } + isOn = true; + } + else + { + if (isOn) + { + move.simulateGravity--; + } + isOn = false; + } + } +} diff --git a/GameCode/RemoveAfterSeconds.cs b/GameCode/RemoveAfterSeconds.cs new file mode 100644 index 0000000..8232562 --- /dev/null +++ b/GameCode/RemoveAfterSeconds.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +public class RemoveAfterSeconds : MonoBehaviour +{ + public float seconds = 3f; + + private float startSeconds; + + public bool shrink; + + public bool scaleWithScale; + + private float shrinkSpeed = 1f; + + private Vector3 startScale; + + private AnimationCurve curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + + private float counter; + + private void Start() + { + startSeconds = seconds; + startScale = base.transform.localScale; + shrinkSpeed = Random.Range(1.5f, 2.5f); + } + + private void Update() + { + seconds -= TimeHandler.deltaTime * (scaleWithScale ? (1f / base.transform.localScale.x) : 1f); + if (!(seconds < 0f)) + { + return; + } + if (shrink) + { + counter += Time.deltaTime * shrinkSpeed; + base.transform.localScale = Vector3.Lerp(startScale, Vector3.zero, curve.Evaluate(counter)); + if (counter > 1f) + { + Object.Destroy(base.gameObject); + } + } + else + { + Object.Destroy(base.gameObject); + } + } + + public void ResetCounter() + { + seconds = startSeconds; + } +} diff --git a/GameCode/RemoveAfterSecondsScale.cs b/GameCode/RemoveAfterSecondsScale.cs new file mode 100644 index 0000000..967091c --- /dev/null +++ b/GameCode/RemoveAfterSecondsScale.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class RemoveAfterSecondsScale : MonoBehaviour +{ + private void Start() + { + GetComponent<RemoveAfterSeconds>().seconds *= base.transform.localScale.x; + } +} diff --git a/GameCode/RescaleFromDamage.cs b/GameCode/RescaleFromDamage.cs new file mode 100644 index 0000000..f9e8a29 --- /dev/null +++ b/GameCode/RescaleFromDamage.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class RescaleFromDamage : MonoBehaviour +{ + private ProjectileHit hit; + + private float startScale; + + private void Start() + { + startScale = base.transform.localScale.x; + } + + public void Rescale() + { + if (!hit) + { + hit = GetComponentInParent<ProjectileHit>(); + } + if ((bool)hit) + { + base.transform.localScale = Vector3.one * startScale * (hit.damage / 55f); + } + } +} diff --git a/GameCode/RescaleFromDamagePart.cs b/GameCode/RescaleFromDamagePart.cs new file mode 100644 index 0000000..ebc37f7 --- /dev/null +++ b/GameCode/RescaleFromDamagePart.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +public class RescaleFromDamagePart : MonoBehaviour +{ + private ProjectileHit hit; + + private float startSize; + + private ParticleSystem part; + + private void Start() + { + part = GetComponent<ParticleSystem>(); + startSize = part.startSize; + } + + public void Rescale() + { + if (!hit) + { + hit = GetComponentInParent<ProjectileHit>(); + } + if ((bool)hit) + { + part.startSize = startSize * (hit.damage / 55f); + } + } +} diff --git a/GameCode/ResetBlock.cs b/GameCode/ResetBlock.cs new file mode 100644 index 0000000..9371a2f --- /dev/null +++ b/GameCode/ResetBlock.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class ResetBlock : MonoBehaviour +{ + private Block block; + + private void Start() + { + block = base.transform.root.GetComponent<Block>(); + } + + public void Go() + { + block.ResetCD(soundPlay: false); + } +} diff --git a/GameCode/RespawnEvent.cs b/GameCode/RespawnEvent.cs new file mode 100644 index 0000000..7abb88d --- /dev/null +++ b/GameCode/RespawnEvent.cs @@ -0,0 +1,19 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class RespawnEvent : MonoBehaviour +{ + public UnityEvent reviveEvent; + + private void Start() + { + HealthHandler healthHandler = GetComponentInParent<Player>().data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(DoEvent)); + } + + public void DoEvent() + { + reviveEvent.Invoke(); + } +} diff --git a/GameCode/RigLookUp.cs b/GameCode/RigLookUp.cs new file mode 100644 index 0000000..2f62a80 --- /dev/null +++ b/GameCode/RigLookUp.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class RigLookUp : MonoBehaviour +{ + private Rigidbody2D rig; + + public float force; + + private void Start() + { + rig = GetComponent<Rigidbody2D>(); + } + + private void FixedUpdate() + { + rig.AddTorque(Vector3.Cross(base.transform.up, Vector3.up).normalized.z * force * rig.mass * Vector3.Angle(base.transform.up, Vector3.up), ForceMode2D.Force); + } +} diff --git a/GameCode/RightLeftMirrorSpring.cs b/GameCode/RightLeftMirrorSpring.cs new file mode 100644 index 0000000..b13966c --- /dev/null +++ b/GameCode/RightLeftMirrorSpring.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +public class RightLeftMirrorSpring : MonoBehaviour +{ + public Vector3 leftPos; + + private Vector3 rightPos; + + public float leftRot; + + public float rightRot; + + private Vector3 posVel; + + private float rotVel; + + public float drag = 25f; + + public float spring = 25f; + + private Holdable holdable; + + private float currentRot; + + private void Start() + { + currentRot = base.transform.localEulerAngles.z; + holdable = base.transform.root.GetComponent<Holdable>(); + rightPos = base.transform.localPosition; + } + + private void Update() + { + if ((bool)holdable && (bool)holdable.holder) + { + bool num = base.transform.root.position.x - 0.1f < holdable.holder.transform.position.x; + Vector3 vector = (num ? leftPos : rightPos); + float num2 = (num ? leftRot : rightRot); + posVel = FRILerp.Lerp(posVel, (vector - base.transform.localPosition) * spring, drag); + rotVel = FRILerp.Lerp(rotVel, (num2 - currentRot) * spring, drag); + currentRot += rotVel * TimeHandler.deltaTime; + base.transform.localPosition += posVel * TimeHandler.deltaTime; + base.transform.localEulerAngles = new Vector3(0f, 0f, currentRot); + } + } +} diff --git a/GameCode/RingHandler.cs b/GameCode/RingHandler.cs new file mode 100644 index 0000000..10ac321 --- /dev/null +++ b/GameCode/RingHandler.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class RingHandler : MonoBehaviour +{ + public float timeBeforeRing = 30f; + + public static RingHandler instance; + + private CodeAnimation code; + + private float counter; + + private void Awake() + { + instance = this; + } + + private void Start() + { + code = GetComponent<CodeAnimation>(); + } + + private void Update() + { + if (GameManager.instance.isPlaying) + { + if (code.currentState != 0 && counter > timeBeforeRing && !code.isPlaying) + { + code.PlayIn(); + } + counter += TimeHandler.deltaTime; + } + else + { + if (code.currentState != CodeAnimationInstance.AnimationUse.Out && !code.isPlaying) + { + code.PlayOut(); + } + counter = 0f; + } + } + + public Vector2 ClosestPoint(Vector2 pos) + { + return pos.normalized * Radius(); + } + + public float Radius() + { + return base.transform.localScale.x * 95f; + } +} diff --git a/GameCode/RotSpring.cs b/GameCode/RotSpring.cs new file mode 100644 index 0000000..402fa90 --- /dev/null +++ b/GameCode/RotSpring.cs @@ -0,0 +1,43 @@ +using UnityEngine; + +public class RotSpring : MonoBehaviour +{ + public bool x; + + public bool y; + + public bool z; + + public float target; + + public float spring; + + public float damper; + + private float currentValue; + + private float vel; + + private void Start() + { + if (x) + { + currentValue = base.transform.localEulerAngles.x; + } + else if (y) + { + currentValue = base.transform.localEulerAngles.y; + } + else if (z) + { + currentValue = base.transform.localEulerAngles.z; + } + } + + private void Update() + { + vel = FRILerp.Lerp(vel, (target - currentValue) * spring, damper); + currentValue += vel * TimeHandler.deltaTime; + base.transform.localEulerAngles = new Vector3(x ? currentValue : 0f, y ? currentValue : 0f, z ? currentValue : 0f); + } +} diff --git a/GameCode/Rotate.cs b/GameCode/Rotate.cs new file mode 100644 index 0000000..04f9889 --- /dev/null +++ b/GameCode/Rotate.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class Rotate : MonoBehaviour +{ + public float speed; + + private void Update() + { + base.transform.Rotate(Vector3.forward * speed * TimeHandler.deltaTime, Space.World); + } +} diff --git a/GameCode/RotatingShooter.cs b/GameCode/RotatingShooter.cs new file mode 100644 index 0000000..cdeef51 --- /dev/null +++ b/GameCode/RotatingShooter.cs @@ -0,0 +1,69 @@ +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; + +public class RotatingShooter : MonoBehaviour +{ + private Gun gun; + + [HideInInspector] + public float charge; + + public int bulletsToFire = 10; + + private int currentBulletsToFire = 10; + + private float degreesPerBullet; + + [FoldoutGroup("Weird settings", 0)] + public bool destroyAfterAttack = true; + + [FoldoutGroup("Weird settings", 0)] + public bool disableTrailRenderer = true; + + private AttackLevel level; + + private void Start() + { + level = GetComponentInParent<AttackLevel>(); + gun = GetComponent<Gun>(); + if (disableTrailRenderer) + { + base.transform.root.GetComponentInChildren<TrailRenderer>(includeInactive: true).enabled = false; + } + } + + public void Attack() + { + currentBulletsToFire = bulletsToFire; + if ((bool)level) + { + currentBulletsToFire = bulletsToFire * level.attackLevel; + } + degreesPerBullet = 360f / (float)currentBulletsToFire; + StartCoroutine(RotateAndShoot()); + } + + private IEnumerator RotateAndShoot() + { + int shotsToMake = Mathf.Clamp(Mathf.RoundToInt(0.5f / gun.attackSpeed), 1, 5); + for (int i = 0; i < shotsToMake; i++) + { + for (int num = currentBulletsToFire; num > 0; num--) + { + base.transform.localEulerAngles = new Vector3(0f, (float)num * degreesPerBullet, 0f); + gun.Attack(gun.currentCharge, forceAttack: true); + } + if (shotsToMake > i) + { + yield return new WaitForSeconds(0.1f); + } + } + base.transform.localEulerAngles = new Vector3(0f, 0f, 0f); + yield return null; + if (destroyAfterAttack) + { + Object.Destroy(base.transform.root.gameObject); + } + } +} diff --git a/GameCode/RotationHandler.cs b/GameCode/RotationHandler.cs new file mode 100644 index 0000000..121bda8 --- /dev/null +++ b/GameCode/RotationHandler.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class RotationHandler : MonoBehaviour +{ + private CharacterData data; + + private PlayerVelocity rig; + + public float torque; + + private void Start() + { + data = GetComponent<CharacterData>(); + rig = GetComponent<PlayerVelocity>(); + } + + private void FixedUpdate() + { + rig.AddTorque(torque * TimeHandler.timeScale * (Vector3.Angle(Vector3.up, base.transform.up) * Vector3.Cross(Vector3.up, base.transform.up).normalized).z); + } +} diff --git a/GameCode/RoundCounter.cs b/GameCode/RoundCounter.cs new file mode 100644 index 0000000..6666a25 --- /dev/null +++ b/GameCode/RoundCounter.cs @@ -0,0 +1,124 @@ +using UnityEngine; +using UnityEngine.UI; + +public class RoundCounter : MonoBehaviour +{ + public int p1Rounds; + + public int p2Rounds; + + public int p1Points; + + public int p2Points; + + public Transform p1Parent; + + public Transform p2Parent; + + public Color offColor; + + public Populate p1Populate; + + public Populate p2Populate; + + private int roundsNeeded; + + private void Start() + { + p1Parent.gameObject.SetActive(value: true); + p2Parent.gameObject.SetActive(value: true); + } + + public void UpdateRounds(int r1, int r2) + { + p1Rounds = r1; + p2Rounds = r2; + ReDraw(); + } + + private void Clear() + { + for (int i = 0; i < p1Parent.childCount; i++) + { + if (p1Populate.transform.GetChild(i).gameObject.activeSelf) + { + Object.Destroy(p1Populate.transform.GetChild(i).gameObject); + } + } + for (int j = 0; j < p2Parent.childCount; j++) + { + if (p2Populate.transform.GetChild(j).gameObject.activeSelf) + { + Object.Destroy(p2Populate.transform.GetChild(j).gameObject); + } + } + } + + private void Populate() + { + p1Populate.times = roundsNeeded; + p1Populate.DoPopulate(); + p2Populate.times = roundsNeeded; + p2Populate.DoPopulate(); + } + + public void UpdatePoints(int p1, int p2) + { + p1Points = p1; + p2Points = p2; + ReDraw(); + } + + private void ReDraw() + { + for (int i = 0; i < p1Parent.childCount; i++) + { + if (p1Rounds + p1Points > i) + { + p1Parent.GetChild(i).GetComponentInChildren<Image>().color = PlayerSkinBank.GetPlayerSkinColors(0).winText; + if (p1Rounds > i) + { + p1Parent.GetChild(i).localScale = Vector3.one; + } + } + else + { + p1Parent.GetChild(i).GetComponentInChildren<Image>().color = offColor; + p1Parent.GetChild(i).localScale = Vector3.one * 0.3f; + } + } + for (int j = 0; j < p2Parent.childCount; j++) + { + if (p2Rounds + p2Points > j) + { + p2Parent.GetChild(j).GetComponentInChildren<Image>().color = PlayerSkinBank.GetPlayerSkinColors(1).winText; + if (p2Rounds > j) + { + p2Parent.GetChild(j).localScale = Vector3.one; + } + } + else + { + p2Parent.GetChild(j).GetComponentInChildren<Image>().color = offColor; + p2Parent.GetChild(j).localScale = Vector3.one * 0.3f; + } + } + } + + internal Vector3 GetPointPos(int teamID) + { + if (teamID == 0) + { + return p1Parent.GetChild(p1Rounds).transform.position; + } + return p2Parent.GetChild(p2Rounds).transform.position; + } + + internal void SetNumberOfRounds(int roundsToWinGame) + { + roundsNeeded = roundsToWinGame; + Clear(); + Populate(); + ReDraw(); + } +} diff --git a/GameCode/RoundModifier.cs b/GameCode/RoundModifier.cs new file mode 100644 index 0000000..d1c1ac6 --- /dev/null +++ b/GameCode/RoundModifier.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Round")] +public class RoundModifier : ProceduralImageModifier +{ + public override Vector4 CalculateRadius(Rect imageRect) + { + float num = Mathf.Min(imageRect.width, imageRect.height) * 0.5f; + return new Vector4(num, num, num, num); + } +} diff --git a/GameCode/RunSmoke.cs b/GameCode/RunSmoke.cs new file mode 100644 index 0000000..6e45d62 --- /dev/null +++ b/GameCode/RunSmoke.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +public class RunSmoke : MonoBehaviour +{ + private CharacterData data; + + private ParticleSystem part; + + private float c; + + private bool groundedLastFrame; + + private ParticleSystem.MainModule partVel; + + private bool didTryToEmit; + + private Vector3 vel; + + private void Start() + { + part = GetComponent<ParticleSystem>(); + data = GetComponentInParent<CharacterData>(); + partVel = part.main; + } + + private void Update() + { + didTryToEmit = false; + if (data.isGrounded && Mathf.Abs(data.playerVel.velocity.x) > 5f) + { + base.transform.position = new Vector3(data.transform.position.x, data.groundPos.y, 5f); + Go(); + } + else if (data.isWallGrab && data.wallDistance < 0.7f && data.playerVel.velocity.magnitude > 5f) + { + base.transform.position = new Vector3(data.wallPos.x, data.transform.position.y, 5f); + Go(); + } + if (didTryToEmit) + { + vel = Vector3.Lerp(vel, data.playerVel.velocity, TimeHandler.deltaTime * 2f); + } + else + { + vel = Vector3.Lerp(vel, Vector3.zero, TimeHandler.deltaTime * 10f); + } + } + + private void Go() + { + didTryToEmit = true; + c += TimeHandler.deltaTime; + if (c > 0.02f) + { + c = 0f; + float num = 2f; + part.transform.rotation = Quaternion.LookRotation(vel); + partVel.startSpeedMultiplier = data.playerVel.velocity.magnitude * num; + part.Emit(2); + } + } +} diff --git a/GameCode/SFLight.cs b/GameCode/SFLight.cs new file mode 100644 index 0000000..8ff6e38 --- /dev/null +++ b/GameCode/SFLight.cs @@ -0,0 +1,350 @@ +using System.Collections.Generic; +using UnityEngine; + +[RequireComponent(typeof(RectTransform))] +public class SFLight : MonoBehaviour +{ + private class VertexArray + { + public int capacity; + + public int size; + + public Vector3[] verts; + + public Vector4[] tangents; + + public Vector2[] uvs; + + public int[] tris; + + public VertexArray(int segments) + { + capacity = segments; + size = 0; + verts = new Vector3[segments * 4]; + tangents = new Vector4[segments * 4]; + uvs = new Vector2[segments * 4]; + tris = new int[segments * 6]; + } + } + + [Tooltip("The radius of the light source. Larger lights cast softer shadows.")] + public float _radius = 0.5f; + + [Tooltip("The brightness of the light. (Ignored when using non-linear light blending.) Allows for colors brighter than 1.0 in HDR lighting situations.")] + public float _intensity = 1f; + + [Tooltip("The color of the light.")] + public Color _color = Color.white; + + [Tooltip("The shape of the light.")] + public Texture2D _cookieTexture; + + [Tooltip("Which layers cast shadows.")] + public LayerMask _shadowLayers = -1; + + [Tooltip("Allows the light cookie to move off the light plane. Use gently as it can cause shadows to look weird.")] + public bool _parallaxLight; + + private RectTransform _rt; + + public static List<SFLight> _lights = new List<SFLight>(); + + private Rect _cullBounds; + + private static int GROWTH_NUM = 4; + + private static int GROWTH_DENOM = 3; + + private static VertexArray[] vertexArrays = new VertexArray[40]; + + public float radius + { + get + { + return _radius; + } + set + { + _radius = value; + } + } + + public float intensity + { + get + { + return _intensity; + } + set + { + _intensity = value; + } + } + + public Color color + { + get + { + return _color; + } + set + { + _color = value; + } + } + + public Texture2D cookieTexture + { + get + { + return _cookieTexture; + } + set + { + _cookieTexture = value; + } + } + + public LayerMask shadowLayers + { + get + { + return _shadowLayers; + } + set + { + _shadowLayers = value; + } + } + + public bool parallaxLight + { + get + { + return _parallaxLight; + } + set + { + _parallaxLight = value; + } + } + + public Rect _bounds => _rt.rect; + + public Rect _CullBounds => _cullBounds; + + private void OnEnable() + { + _lights.Add(this); + } + + private void OnDisable() + { + _lights.Remove(this); + } + + public Matrix4x4 _ModelMatrix(bool forceProjection) + { + if (!_rt) + { + _rt = GetComponent<RectTransform>(); + } + Matrix4x4 localToWorldMatrix = _rt.localToWorldMatrix; + if (!_parallaxLight || forceProjection) + { + localToWorldMatrix.SetRow(2, new Vector4(0f, 0f, 1f, 0f)); + } + return localToWorldMatrix; + } + + public Matrix4x4 _CookieMatrix() + { + if (!_rt) + { + _rt = GetComponent<RectTransform>(); + } + Vector2 vector = _rt.sizeDelta / 2f; + Vector2 vector2 = Vector2.one - 2f * _rt.pivot; + Matrix4x4 identity = Matrix4x4.identity; + identity.SetRow(0, new Vector4(vector.x, 0f, 0f, vector2.x * vector.x)); + identity.SetRow(1, new Vector4(0f, vector.y, 0f, vector2.y * vector.y)); + return identity; + } + + private static Rect Union(Rect r1, Rect r2) + { + return Rect.MinMaxRect(Mathf.Min(r1.xMin, r2.xMin), Mathf.Min(r1.yMin, r2.yMin), Mathf.Max(r1.xMax, r2.xMax), Mathf.Max(r1.yMax, r2.yMax)); + } + + private static Rect QuadrantCull(Rect cull, Matrix4x4 mvp, Rect r) + { + if (!SFRenderer._FastCull(mvp, r)) + { + return cull; + } + return Union(cull, r); + } + + public Rect _CalcCullBounds(Matrix4x4 vpMatrix) + { + Matrix4x4 matrix4x = _ModelMatrix(forceProjection: true); + Matrix4x4 mvp = vpMatrix * matrix4x; + Rect rect = new Rect(0f - _radius, 0f - _radius, 2f * _radius, 2f * _radius); + Rect rect2 = _rt.rect; + Rect cull = rect; + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect2.xMin, rect2.yMin, rect.xMax, rect.yMax)); + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect.xMin, rect2.yMin, rect2.xMax, rect.yMax)); + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect2.xMin, rect.yMin, rect.xMax, rect2.yMax)); + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect.xMin, rect.yMin, rect2.xMax, rect2.yMax)); + return _cullBounds = SFRenderer._TransformRect(matrix4x, cull); + } + + private VertexArray GetVertexArray(int segments) + { + int num = 0; + int num2 = 4; + while (segments > num2) + { + num2 = num2 * GROWTH_NUM / GROWTH_DENOM; + num++; + } + if (num >= vertexArrays.Length) + { + Debug.LogError("SFSS: Maximum vertexes per light exceeded. (" + num2 + ")"); + return null; + } + if (vertexArrays[num] == null) + { + vertexArrays[num] = new VertexArray(num2); + } + return vertexArrays[num]; + } + + private void BatchPath(SFPolygon poly, int pathIndex, Matrix4x4 t, ref int j, bool flipped, Vector3 properties, Vector3[] verts, Vector4[] tangents, Vector2[] uvs, int[] tris) + { + Vector2[] path = poly.GetPath(pathIndex); + int num; + Vector2 vector; + if (poly.looped) + { + num = 0; + vector = Transform(t, path[^1]); + } + else + { + num = 1; + vector = Transform(t, path[0]); + } + for (int i = num; i < path.Length; i++) + { + Vector2 vector2 = Transform(t, path[i]); + Vector4 vector3 = (flipped ? new Vector4(vector2.x, vector2.y, vector.x, vector.y) : new Vector4(vector.x, vector.y, vector2.x, vector2.y)); + verts[j * 4] = properties; + tangents[j * 4] = vector3; + uvs[j * 4] = new Vector2(0f, 0f); + verts[j * 4 + 1] = properties; + tangents[j * 4 + 1] = vector3; + uvs[j * 4 + 1] = new Vector2(1f, 0f); + verts[j * 4 + 2] = properties; + tangents[j * 4 + 2] = vector3; + uvs[j * 4 + 2] = new Vector2(0f, 1f); + verts[j * 4 + 3] = properties; + tangents[j * 4 + 3] = vector3; + uvs[j * 4 + 3] = new Vector2(1f, 1f); + tris[j * 6] = j * 4; + tris[j * 6 + 1] = j * 4 + 1; + tris[j * 6 + 2] = j * 4 + 2; + tris[j * 6 + 3] = j * 4 + 1; + tris[j * 6 + 4] = j * 4 + 3; + tris[j * 6 + 5] = j * 4 + 2; + j++; + vector = vector2; + } + } + + public Mesh _BuildShadowMesh(Mesh mesh, List<SFPolygon> polys, float minLightPenetration) + { + int num = 0; + for (int i = 0; i < polys.Count; i++) + { + if (((int)polys[i].shadowLayers & (int)shadowLayers) == 0) + { + continue; + } + SFPolygon sFPolygon = polys[i]; + int activePath = sFPolygon.activePath; + bool looped = sFPolygon.looped; + if (activePath >= 0) + { + num += sFPolygon.GetPath(activePath).Length - ((!looped) ? 1 : 0); + continue; + } + int pathCount = sFPolygon.pathCount; + for (int j = 0; j < pathCount; j++) + { + num += sFPolygon.GetPath(j).Length - ((!looped) ? 1 : 0); + } + } + VertexArray vertexArray = GetVertexArray(num); + Vector3[] verts = vertexArray.verts; + Vector4[] tangents = vertexArray.tangents; + Vector2[] uvs = vertexArray.uvs; + int[] tris = vertexArray.tris; + if (num == 0 || vertexArray.capacity == 0) + { + return null; + } + if (!_rt) + { + _rt = GetComponent<RectTransform>(); + } + Matrix4x4 worldToLocalMatrix = _rt.worldToLocalMatrix; + int j2 = 0; + for (int k = 0; k < polys.Count; k++) + { + SFPolygon sFPolygon2 = polys[k]; + if (((int)sFPolygon2.shadowLayers & (int)shadowLayers) == 0) + { + continue; + } + Matrix4x4 matrix4x = sFPolygon2._GetMatrix(); + Matrix4x4 t = worldToLocalMatrix * matrix4x; + bool flipped = Det2x3(matrix4x) < 0f; + float y = Mathf.Max(sFPolygon2._lightPenetration, minLightPenetration); + Vector3 properties = new Vector3(_radius, y, sFPolygon2._opacity); + int activePath2 = sFPolygon2.activePath; + if (activePath2 >= 0) + { + BatchPath(sFPolygon2, activePath2, t, ref j2, flipped, properties, verts, tangents, uvs, tris); + continue; + } + int pathCount2 = sFPolygon2.pathCount; + for (int l = 0; l < pathCount2; l++) + { + BatchPath(sFPolygon2, l, t, ref j2, flipped, properties, verts, tangents, uvs, tris); + } + } + for (int m = 6 * num; m < 6 * vertexArray.size; m++) + { + vertexArray.tris[m] = 0; + } + mesh.vertices = verts; + mesh.tangents = tangents; + mesh.uv = uvs; + mesh.triangles = tris; + vertexArray.size = num; + return mesh; + } + + private static float Det2x3(Matrix4x4 m) + { + return m[0] * m[5] - m[1] * m[4]; + } + + private static Vector2 Transform(Matrix4x4 m, Vector2 p) + { + return new Vector2(p.x * m[0] + p.y * m[4] + m[12], p.x * m[1] + p.y * m[5] + m[13]); + } +} diff --git a/GameCode/SFPolygon.cs b/GameCode/SFPolygon.cs new file mode 100644 index 0000000..c806c1c --- /dev/null +++ b/GameCode/SFPolygon.cs @@ -0,0 +1,338 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class SFPolygon : MonoBehaviour +{ + private Transform _t; + + private Rect _bounds; + + private Rect _worldBounds; + + [SerializeField] + private Vector2[] _verts = new Vector2[3]; + + [SerializeField] + private Vector2[][] _paths; + + public int _activePath; + + public bool _looped; + + public LayerMask _shadowLayers = -1; + + public float _lightPenetration; + + public float _opacity = 1f; + + public static List<SFPolygon> _polygons = new List<SFPolygon>(); + + public Rect _WorldBounds => _worldBounds; + + public int pathCount + { + get + { + if (_paths != null) + { + return _paths.Length + 1; + } + return 1; + } + set + { + int num = value - 1; + if (value == pathCount) + { + return; + } + if (value < 1) + { + Debug.LogError("pathCount must be positive."); + return; + } + if (value == 1) + { + _paths = null; + } + else if (_paths == null) + { + _paths = new Vector2[num][]; + for (int i = 0; i < _paths.Length; i++) + { + _paths[i] = _verts; + } + } + else + { + Vector2[][] paths = _paths; + _paths = new Vector2[num][]; + if (num > paths.Length) + { + int j; + for (j = 0; j < paths.Length; j++) + { + _paths[j] = paths[j]; + } + for (; j < num; j++) + { + _paths[j] = _verts; + } + } + else + { + for (int k = 0; k < num; k++) + { + _paths[k] = paths[k]; + } + } + } + _UpdateBounds(); + } + } + + public Vector2[] verts + { + get + { + return _verts; + } + set + { + _verts = value; + } + } + + public int activePath + { + get + { + return _activePath; + } + set + { + _activePath = value; + } + } + + public bool looped + { + get + { + return _looped; + } + set + { + _looped = value; + } + } + + public LayerMask shadowLayers + { + get + { + return _shadowLayers; + } + set + { + _shadowLayers = value; + } + } + + public float lightPenetration + { + get + { + return _lightPenetration; + } + set + { + _lightPenetration = value; + } + } + + public float opacity + { + get + { + return _opacity; + } + set + { + _opacity = value; + } + } + + public Matrix4x4 _GetMatrix() + { + if (!_t) + { + _t = base.transform; + } + return _t.localToWorldMatrix; + } + + private void PathBounds(Vector2[] path, int i0, ref float l, ref float b, ref float r, ref float t) + { + for (int j = i0; j < path.Length; j++) + { + Vector2 vector = path[j]; + l = Mathf.Min(vector.x, l); + r = Mathf.Max(vector.x, r); + b = Mathf.Min(vector.y, b); + t = Mathf.Max(vector.y, t); + } + } + + public void _UpdateBounds() + { + float l; + float r; + float b; + float t; + if (_activePath > 0) + { + Vector2 vector = GetPath(_activePath)[0]; + l = (r = vector.x); + b = (t = vector.y); + PathBounds(_verts, 1, ref l, ref b, ref r, ref t); + } + else + { + Vector2 vector2 = _verts[0]; + l = (r = vector2.x); + b = (t = vector2.y); + PathBounds(_verts, 1, ref l, ref b, ref r, ref t); + int num = pathCount; + for (int i = 1; i < num; i++) + { + PathBounds(GetPath(i), 0, ref l, ref b, ref r, ref t); + } + } + _bounds = Rect.MinMaxRect(l, b, r, t); + } + + public void _CacheWorldBounds() + { + if (!_t) + { + _t = base.transform; + } + _worldBounds = SFRenderer._TransformRect(_t.localToWorldMatrix, _bounds); + } + + public Vector2[] GetPath(int index) + { + if (index != 0) + { + return _paths[index - 1]; + } + return _verts; + } + + public void SetPath(int index, Vector2[] path) + { + SetPathRaw(index, path); + _UpdateBounds(); + } + + private void SetPathRaw(int index, Vector2[] path) + { + if (index == 0) + { + _verts = path; + } + else + { + _paths[index - 1] = path; + } + } + + private void OnEnable() + { + _polygons.Add(this); + } + + private void OnDisable() + { + _polygons.Remove(this); + } + + private void Start() + { + _UpdateBounds(); + } + + public void CopyFromCollider(Collider2D collider) + { + PolygonCollider2D polygonCollider2D = collider as PolygonCollider2D; + BoxCollider2D boxCollider2D = collider as BoxCollider2D; + if ((bool)polygonCollider2D) + { + looped = true; + int num2 = (pathCount = polygonCollider2D.pathCount); + int num3 = num2; + for (int i = 0; i < num3; i++) + { + Vector2[] path = polygonCollider2D.GetPath(i); + for (int j = 0; j < path.Length; j++) + { + path[j] += polygonCollider2D.offset; + } + Array.Reverse((Array)path); + SetPathRaw(i, path); + } + _UpdateBounds(); + } + else if ((bool)boxCollider2D) + { + SetBoxVerts(boxCollider2D.offset - 0.5f * boxCollider2D.size, boxCollider2D.offset + 0.5f * boxCollider2D.size); + } + else + { + Debug.LogWarning("CopyFromCollider() only works with polygon and box colliders."); + } + } + + public void _CopyFromCollider() + { + Collider2D component = GetComponent<Collider2D>(); + if ((bool)component) + { + CopyFromCollider(component); + return; + } + Debug.LogWarning("GameObject has no polygon or box collider. Adding default SFPolygon shape instead."); + SetBoxVerts(-Vector2.one, Vector2.one); + } + + private void SetBoxVerts(Vector2 min, Vector2 max) + { + looped = true; + pathCount = 1; + verts = new Vector2[4] + { + new Vector2(max.x, max.y), + new Vector2(max.x, min.y), + new Vector2(min.x, min.y), + new Vector2(min.x, max.y) + }; + } + + public void _FlipInsideOut(int index) + { + if (index == -1) + { + int num = pathCount; + for (int i = 0; i < num; i++) + { + Array.Reverse((Array)GetPath(i)); + } + } + else + { + Array.Reverse((Array)GetPath(index)); + } + } +} diff --git a/GameCode/SFRenderer.cs b/GameCode/SFRenderer.cs new file mode 100644 index 0000000..e19e13b --- /dev/null +++ b/GameCode/SFRenderer.cs @@ -0,0 +1,621 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +[ExecuteInEditMode] +public class SFRenderer : MonoBehaviour +{ + public bool _renderInSceneView = true; + + private RenderTexture _lightMap; + + private RenderTexture _ShadowMap; + + [Tooltip("Blend the lights in linear space rather than gamma space. Nonlinear blending prevents oversaturation, but can cause draw order artifacts.")] + public bool _linearLightBlending = true; + + public bool _shadows = true; + + [Tooltip("The global ambient light color- the ambient light is used to light your scene when no lights are affecting part of it. A darker grey, blue, or yellow is often a good place to start. Alpha unused. ")] + public Color _ambientLight = Color.black; + + [Tooltip("Exposure is a multiplier applied to all lights in this renderer. Use to adjust all your lights at once. Particularly useful if you're using HDR lighting, otherwise it can be used to cause oversaturation.")] + [FormerlySerializedAs("_globalDynamicRange")] + public float _exposure = 1f; + + [Tooltip("Scale of the render texture for the colored lights. Larger numbers will give you blockier lights, but will run faster. Since lighting tends to be pretty diffuse, high numbers like 8 usually look good here. Recommended values are between 8 - 32.")] + public float _lightMapScale = 8f; + + [Tooltip("Scale of the render texture for the colored lights. Larger numbers will give you blockier shadows, but will run faster. Blocky shadows tend to look worse than blocky lights, so this should usually be lower than the light map scale. Recommended values are between 2 - 8. Less if you have a lot of sharp shadows.")] + public float _shadowMapScale = 4f; + + [Tooltip("How far will light penetrate into each shadow casting object. Makes it look like objects that are casting shadows are illuminated by the lights.")] + public float _minLightPenetration = 0.2f; + + [Tooltip("Extra darkening to apply to shadows to hide precision artifacts in the seams.")] + public float _shadowCompensation = 1.01f; + + [Tooltip("The color of the fog color. The alpha controls the fog's strength.")] + public Color _fogColor = new Color(1f, 1f, 1f, 0f); + + [Tooltip("The scatter color is the color that the fog will glow when it is lit. Alpha is unused. Black disables illumination effects on the fog.")] + public Color _scatterColor = new Color(0f, 0f, 0f, 0f); + + [Tooltip("What percentage of unshadowed/shadowed light should apply to the fog. At 1.0, your shadows will be fully applied to the scattered light in your fog.")] + public float _softHardMix; + + private Rect _extents = Rect.MinMaxRect(-1f, -1f, 1f, 1f); + + private Material _shadowMaskMaterial; + + private Material _linearLightMaterial; + + private Material _softLightMaterial; + + private Material _HDRClampMaterial; + + private Material _fogMaterial; + + private Mesh _mesh; + + private bool UV_STARTS_AT_TOP; + + private static Matrix4x4 TEXTURE_FLIP_MATRIX = Matrix4x4.Scale(new Vector3(1f, -1f, 1f)); + + private RenderTextureFormat lightmapFormat = RenderTextureFormat.ARGB1555; + + private RenderTextureFormat lightmapFormatHDR = RenderTextureFormat.ARGB1555; + + private List<SFPolygon> _perLightCulledPolygons = new List<SFPolygon>(); + + private List<SFLight> _culledLights = new List<SFLight>(); + + private List<SFPolygon> _culledPolygons = new List<SFPolygon>(); + + public bool linearLightBlending + { + get + { + return _linearLightBlending; + } + set + { + _linearLightBlending = value; + } + } + + public bool shadows + { + get + { + return _shadows; + } + set + { + _shadows = value; + } + } + + public Color ambientLight + { + get + { + return _ambientLight; + } + set + { + _ambientLight = value; + } + } + + public float exposure + { + get + { + return _exposure; + } + set + { + _exposure = value; + } + } + + public float lightMapScale + { + get + { + return _lightMapScale; + } + set + { + _lightMapScale = value; + } + } + + public float shadowMapScale + { + get + { + return _shadowMapScale; + } + set + { + _shadowMapScale = value; + } + } + + public float minLightPenetration + { + get + { + return _minLightPenetration; + } + set + { + _minLightPenetration = value; + } + } + + public float shadowCompensation + { + get + { + return _shadowCompensation; + } + set + { + _shadowCompensation = Mathf.Clamp(value, 1f, 2f); + } + } + + public Color fogColor + { + get + { + return _fogColor; + } + set + { + _fogColor = value; + } + } + + public Color scatterColor + { + get + { + return _scatterColor; + } + set + { + _scatterColor = value; + } + } + + public float softHardMix + { + get + { + return _softHardMix; + } + set + { + _softHardMix = value; + } + } + + [Obsolete("Please use SFRenderer.exposure instead.")] + public float globalIlluminationScale + { + get + { + return _exposure; + } + set + { + _exposure = value; + } + } + + [Obsolete("Please use SFRenderer.exposure instead.")] + public float globalDynamicRange + { + get + { + return _exposure; + } + set + { + _exposure = value; + } + } + + public Rect extents + { + get + { + return _extents; + } + set + { + _extents = value; + } + } + + private Material shadowMaskMaterial + { + get + { + if (_shadowMaskMaterial == null) + { + _shadowMaskMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/ShadowMask")); + _shadowMaskMaterial.hideFlags = HideFlags.HideAndDontSave; + } + return _shadowMaskMaterial; + } + } + + private Material lightMaterial + { + get + { + if (_linearLightMaterial == null) + { + _linearLightMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/LightBlendLinear")); + _linearLightMaterial.hideFlags = HideFlags.HideAndDontSave; + _softLightMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/LightBlendSoft")); + _softLightMaterial.hideFlags = HideFlags.HideAndDontSave; + } + if (!_linearLightBlending) + { + return _softLightMaterial; + } + return _linearLightMaterial; + } + } + + private Material HDRClampMaterial + { + get + { + if (_HDRClampMaterial == null) + { + _HDRClampMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/HDRClamp")); + _HDRClampMaterial.hideFlags = HideFlags.HideAndDontSave; + } + return _HDRClampMaterial; + } + } + + private Material fogMaterial + { + get + { + if (_fogMaterial == null) + { + _fogMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/FogLayer")); + _fogMaterial.hideFlags = HideFlags.HideAndDontSave; + } + return _fogMaterial; + } + } + + private Mesh sharedMesh + { + get + { + if (_mesh == null) + { + _mesh = new Mesh(); + _mesh.MarkDynamic(); + _mesh.hideFlags = HideFlags.HideAndDontSave; + } + return _mesh; + } + } + + private void ScenePreRender(Camera camera) + { + if (_renderInSceneView && camera.cameraType == CameraType.SceneView) + { + OnPreRender(); + } + } + + private void ScenePostRender(Camera camera) + { + if (_renderInSceneView && camera.cameraType == CameraType.SceneView) + { + OnPostRender(); + } + } + + private void OnEnable() + { + if (Application.isEditor) + { + Camera.onPreRender = (Camera.CameraCallback)Delegate.Combine(Camera.onPreRender, new Camera.CameraCallback(ScenePreRender)); + Camera.onPostRender = (Camera.CameraCallback)Delegate.Combine(Camera.onPostRender, new Camera.CameraCallback(ScenePostRender)); + } + } + + private void OnDisable() + { + if (Application.isEditor) + { + Camera.onPreRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPreRender, new Camera.CameraCallback(ScenePreRender)); + Camera.onPostRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPostRender, new Camera.CameraCallback(ScenePostRender)); + } + } + + private void Start() + { + GraphicsDeviceType graphicsDeviceType = SystemInfo.graphicsDeviceType; + UV_STARTS_AT_TOP = graphicsDeviceType == GraphicsDeviceType.Direct3D9 || graphicsDeviceType == GraphicsDeviceType.Direct3D11 || graphicsDeviceType == GraphicsDeviceType.Direct3D12 || graphicsDeviceType == GraphicsDeviceType.Metal; + if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32)) + { + lightmapFormat = RenderTextureFormat.ARGB32; + } + else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.BGRA32)) + { + lightmapFormat = RenderTextureFormat.BGRA32; + } + if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) + { + lightmapFormatHDR = RenderTextureFormat.ARGBHalf; + } + else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)) + { + lightmapFormatHDR = RenderTextureFormat.ARGBFloat; + } + Debug.Log(string.Concat("SFSS init: ", graphicsDeviceType, ", ", UV_STARTS_AT_TOP ? "UV_STARTS_AT_TOP, " : "", lightmapFormat, ", ", lightmapFormatHDR)); + } + + private void OnDestroy() + { + if ((bool)_mesh) + { + UnityEngine.Object.DestroyImmediate(_mesh); + } + } + + public static Rect _TransformRect(Matrix4x4 m, Rect r) + { + Vector4 vector = m.MultiplyPoint3x4(new Vector4(r.x + 0.5f * r.width, r.y + 0.5f * r.height, 0f, 1f)); + float num = 0.5f * Mathf.Max(Mathf.Abs(r.width * m[0] + r.height * m[4]), Mathf.Abs(r.width * m[0] - r.height * m[4])); + float num2 = 0.5f * Mathf.Max(Mathf.Abs(r.width * m[1] + r.height * m[5]), Mathf.Abs(r.width * m[1] - r.height * m[5])); + return new Rect(vector.x - num, vector.y - num2, 2f * num, 2f * num2); + } + + private static Vector2 ClampedProjection(Matrix4x4 m, float x, float y) + { + float num = Math.Max(0f, x * m[3] + y * m[7] + m[15]); + return new Vector2((x * m[0] + y * m[4] + m[12]) / num, (x * m[1] + y * m[5] + m[13]) / num); + } + + private static Rect ScissorRect(Matrix4x4 mvp, float w, float h) + { + Vector2 vector = ClampedProjection(mvp, -1f, -1f); + Vector2 vector2 = ClampedProjection(mvp, 1f, -1f); + Vector2 vector3 = ClampedProjection(mvp, 1f, 1f); + Vector2 vector4 = ClampedProjection(mvp, -1f, 1f); + float num = Mathf.Min(Mathf.Min(vector.x, vector2.x), Mathf.Min(vector3.x, vector4.x)); + float num2 = Mathf.Min(Mathf.Min(vector.y, vector2.y), Mathf.Min(vector3.y, vector4.y)); + float num3 = Mathf.Max(Mathf.Max(vector.x, vector2.x), Mathf.Max(vector3.x, vector4.x)); + float num4 = Mathf.Max(Mathf.Max(vector.y, vector2.y), Mathf.Max(vector3.y, vector4.y)); + return Rect.MinMaxRect(Mathf.Max(0f, Mathf.Floor((0.5f * num + 0.5f) * w)), Mathf.Max(0f, Mathf.Floor((0.5f * num2 + 0.5f) * h)), Mathf.Min(w, Mathf.Ceil((0.5f * num3 + 0.5f) * w)), Mathf.Min(h, Mathf.Ceil((0.5f * num4 + 0.5f) * h))); + } + + private static Matrix4x4 ClipMatrix(Rect r, float dw, float dh) + { + float num = r.x * dw - 1f; + float num2 = r.y * dh - 1f; + return Matrix4x4.Ortho(num, num + r.width * dw, num2, num2 + r.height * dh, -1f, 1f); + } + + private static void CullPolys(List<SFPolygon> polys, Rect bounds, List<SFPolygon> culledPolygons) + { + for (int i = 0; i < polys.Count; i++) + { + SFPolygon sFPolygon = polys[i]; + if (bounds.Overlaps(sFPolygon._WorldBounds)) + { + culledPolygons.Add(sFPolygon); + } + } + } + + private Matrix4x4 TextureProjectionMatrix(Matrix4x4 m) + { + m.SetRow(2, new Vector4(0f, 0f, 1f, 0f)); + Matrix4x4 matrix4x = m.inverse; + if (UV_STARTS_AT_TOP) + { + matrix4x = TEXTURE_FLIP_MATRIX * matrix4x * TEXTURE_FLIP_MATRIX; + } + return matrix4x; + } + + private void RenderLightMap(Matrix4x4 viewMatrix, Matrix4x4 projection, Matrix4x4 vpMatrix, RenderTexture target, List<SFLight> lights, List<SFPolygon> polys, Color ambient, bool hdr) + { + int width = target.width; + int height = target.height; + Rect screenRect = new Rect(-1f, -1f, 2f, 2f); + Rect sourceRect = new Rect(0f, 0f, 1f, 1f); + Graphics.SetRenderTarget(target); + GL.Clear(clearDepth: false, clearColor: true, ambient); + for (int i = 0; i < lights.Count; i++) + { + SFLight sFLight = lights[i]; + if (!sFLight.enabled) + { + continue; + } + Matrix4x4 matrix4x = sFLight._ModelMatrix(forceProjection: false) * sFLight._CookieMatrix(); + Rect rect = ScissorRect(vpMatrix * matrix4x, width, height); + Matrix4x4 matrix4x2 = ClipMatrix(rect, 2f / (float)width, 2f / (float)height) * projection; + GL.Viewport(rect); + GL.LoadProjectionMatrix(matrix4x2); + if (polys != null && (int)sFLight._shadowLayers != 0) + { + CullPolys(polys, sFLight._CalcCullBounds(vpMatrix), _perLightCulledPolygons); + Mesh mesh = sFLight._BuildShadowMesh(sharedMesh, _perLightCulledPolygons, _minLightPenetration); + _perLightCulledPolygons.Clear(); + if (mesh != null) + { + shadowMaskMaterial.SetPass(0); + Graphics.DrawMeshNow(mesh, sFLight._ModelMatrix(forceProjection: true)); + mesh.Clear(); + } + if (hdr) + { + Graphics.DrawTexture(screenRect, Texture2D.blackTexture, HDRClampMaterial); + } + } + Texture2D texture2D = sFLight._cookieTexture; + if (!texture2D) + { + texture2D = Texture2D.whiteTexture; + } + Material material = lightMaterial; + if (_linearLightBlending) + { + material.SetFloat("_intensity", sFLight._intensity); + } + GL.LoadProjectionMatrix(TextureProjectionMatrix(matrix4x2 * viewMatrix * matrix4x)); + Graphics.DrawTexture(screenRect, texture2D, sourceRect, 0, 0, 0, 0, sFLight._color, material); + } + } + + private RenderTexture GetTexture(Camera cam, Matrix4x4 extensionInv, float downscale) + { + Vector4 vector = extensionInv * cam.pixelRect.size / downscale; + RenderTextureFormat format = (cam.allowHDR ? lightmapFormatHDR : lightmapFormat); + return RenderTexture.GetTemporary((int)vector.x, (int)vector.y, 0, format); + } + + public static bool _FastCull(Matrix4x4 mvp, Rect bounds) + { + Vector2 center = bounds.center; + Vector2 vector = 0.5f * bounds.size; + Vector4 vector2 = mvp * new Vector4(center.x, center.y, 0f, 1f); + float num = vector.x * Mathf.Abs(mvp[0]) + vector.y * Mathf.Abs(mvp[4]); + float num2 = vector.x * Mathf.Abs(mvp[1]) + vector.y * Mathf.Abs(mvp[5]); + float num3 = vector.x * Mathf.Abs(mvp[2]) + vector.y * Mathf.Abs(mvp[6]); + float num4 = Mathf.Max(0f, vector2.w + vector.x * Mathf.Abs(mvp[3]) + vector.y * Mathf.Abs(mvp[7])); + if (Mathf.Abs(vector2.x) - num < num4 && Mathf.Abs(vector2.y) - num2 < num4) + { + return Mathf.Abs(vector2.z) - num3 < num4; + } + return false; + } + + private static Rect CullLights(Matrix4x4 vpMatrix, List<SFLight> lights, List<SFLight> culledLights) + { + float num = float.PositiveInfinity; + float num2 = float.PositiveInfinity; + float num3 = float.NegativeInfinity; + float num4 = float.NegativeInfinity; + for (int i = 0; i < lights.Count; i++) + { + SFLight sFLight = lights[i]; + if (_FastCull(vpMatrix * sFLight._ModelMatrix(forceProjection: false), sFLight._bounds)) + { + culledLights.Add(sFLight); + if ((int)sFLight._shadowLayers != 0) + { + Rect rect = sFLight._CalcCullBounds(vpMatrix); + num = Mathf.Min(num, rect.xMin); + num2 = Mathf.Min(num2, rect.yMin); + num3 = Mathf.Max(num3, rect.xMax); + num4 = Mathf.Max(num4, rect.yMax); + } + } + } + return Rect.MinMaxRect(num, num2, num3, num4); + } + + private void OnPreRender() + { + Color color = _ambientLight; + color.a = 1f; + Matrix4x4 matrix4x = Matrix4x4.Ortho(_extents.xMin, _extents.xMax, _extents.yMin, _extents.yMax, 1f, -1f); + Matrix4x4 inverse = matrix4x.inverse; + RenderBuffer activeColorBuffer = Graphics.activeColorBuffer; + RenderBuffer activeDepthBuffer = Graphics.activeDepthBuffer; + Camera current = Camera.current; + bool allowHDR = current.allowHDR; + Matrix4x4 worldToCameraMatrix = current.worldToCameraMatrix; + Matrix4x4 matrix4x2 = matrix4x * current.projectionMatrix; + Matrix4x4 vpMatrix = matrix4x2 * worldToCameraMatrix; + List<SFLight> lights = SFLight._lights; + List<SFPolygon> list = SFPolygon._polygons; + if (!Application.isPlaying) + { + lights = new List<SFLight>(from o in UnityEngine.Object.FindObjectsOfType<SFLight>() + where o.isActiveAndEnabled + select o); + list = new List<SFPolygon>(from o in UnityEngine.Object.FindObjectsOfType<SFPolygon>() + where o.isActiveAndEnabled + select o); + foreach (SFPolygon item in list) + { + item._UpdateBounds(); + } + } + Rect bounds = CullLights(vpMatrix, lights, _culledLights); + GL.PushMatrix(); + _lightMap = GetTexture(current, inverse, _lightMapScale); + RenderLightMap(worldToCameraMatrix, matrix4x2, vpMatrix, _lightMap, _culledLights, null, color, allowHDR); + if (_shadows) + { + for (int i = 0; i < list.Count; i++) + { + list[i]._CacheWorldBounds(); + } + CullPolys(list, bounds, _culledPolygons); + Shader.SetGlobalFloat("_SFShadowCompensation", _shadowCompensation); + _ShadowMap = GetTexture(current, inverse, _shadowMapScale); + RenderLightMap(worldToCameraMatrix, matrix4x2, vpMatrix, _ShadowMap, _culledLights, _culledPolygons, color, allowHDR); + _culledPolygons.Clear(); + } + GL.PopMatrix(); + _culledLights.Clear(); + Graphics.SetRenderTarget(null); + GL.Viewport(current.pixelRect); + Shader.SetGlobalMatrix("_SFProjection", matrix4x * Camera.current.projectionMatrix); + Shader.SetGlobalColor("_SFAmbientLight", color); + Shader.SetGlobalFloat("_SFExposure", _exposure); + Shader.SetGlobalTexture("_SFLightMap", _lightMap); + Shader.SetGlobalTexture("_SFLightMapWithShadows", _shadows ? _ShadowMap : _lightMap); + Graphics.SetRenderTarget(activeColorBuffer, activeDepthBuffer); + } + + private void OnPostRender() + { + if (_fogColor.a + _scatterColor.r + _scatterColor.g + _scatterColor.b > 0f) + { + GL.PushMatrix(); + GL.LoadProjectionMatrix(Matrix4x4.identity); + Color value = _scatterColor; + value.a = _softHardMix; + Material material = fogMaterial; + material.SetColor("_FogColor", _fogColor); + material.SetColor("_Scatter", value); + material.SetPass(0); + Graphics.DrawTexture(new Rect(-1f, -1f, 2f, 2f), Texture2D.blackTexture, material); + GL.PopMatrix(); + } + Shader.SetGlobalColor("_SFAmbientLight", Color.white); + Shader.SetGlobalFloat("_SFExposure", 1f); + Shader.SetGlobalTexture("_SFLightMap", Texture2D.whiteTexture); + Shader.SetGlobalTexture("_SFLightMapWithShadows", Texture2D.whiteTexture); + RenderTexture.ReleaseTemporary(_lightMap); + _lightMap = null; + RenderTexture.ReleaseTemporary(_ShadowMap); + _ShadowMap = null; + } +} diff --git a/GameCode/SFSample.cs b/GameCode/SFSample.cs new file mode 100644 index 0000000..8a0d194 --- /dev/null +++ b/GameCode/SFSample.cs @@ -0,0 +1,73 @@ +using UnityEngine; + +[RequireComponent(typeof(Renderer))] +public class SFSample : MonoBehaviour +{ + private Material _material; + + public Vector2 _samplePosition = Vector2.zero; + + public bool _lineSample; + + public Vector2 samplePosition + { + get + { + return _samplePosition; + } + set + { + _samplePosition = value; + if ((bool)_material) + { + _material.SetVector("_SamplePosition", _samplePosition); + } + } + } + + public bool lineSample + { + get + { + return _lineSample; + } + set + { + _lineSample = value; + if ((bool)_material) + { + if (value) + { + _material.EnableKeyword("LINESAMPLE_ON"); + _material.DisableKeyword("FIXEDSAMPLEPOINT_ON"); + } + else + { + _material.DisableKeyword("LINESAMPLE_ON"); + _material.EnableKeyword("FIXEDSAMPLEPOINT_ON"); + } + } + } + } + + private void Start() + { + Renderer component = GetComponent<Renderer>(); + Material sharedMaterial = component.sharedMaterial; + if (sharedMaterial == null || sharedMaterial.shader.name != "Sprites/SFSoftShadow") + { + Debug.LogError("SFSample requires the attached renderer to be using the Sprites/SFSoftShadow shader."); + return; + } + _material = new Material(sharedMaterial); + component.material = _material; + _material.SetFloat("_SoftHardMix", sharedMaterial.GetFloat("_SoftHardMix")); + samplePosition = _samplePosition; + lineSample = _lineSample; + } + + private void OnDrawGizmosSelected() + { + Gizmos.DrawIcon(base.transform.TransformPoint(_samplePosition), "SFDotGizmo.psd"); + } +} diff --git a/GameCode/Saw.cs b/GameCode/Saw.cs new file mode 100644 index 0000000..19ebe25 --- /dev/null +++ b/GameCode/Saw.cs @@ -0,0 +1,83 @@ +using UnityEngine; + +public class Saw : MonoBehaviour +{ + public Player owner; + + public float range = 3f; + + public float damage = 10f; + + public float force; + + public float shake = 1f; + + public ParticleSystem[] parts; + + public Transform sparkTransform; + + private Vector3 forceDir; + + private void Start() + { + owner = base.transform.root.GetComponent<SpawnedAttack>().spawner; + } + + private void Update() + { + Player player = null; + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + Player player2 = PlayerManager.instance.players[i]; + if (player2 != owner && Vector3.Distance(player2.transform.position, base.transform.transform.position) < range * base.transform.localScale.x) + { + player = player2; + } + } + if ((bool)player && PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee) + { + Vector3 normalized = (player.transform.position - base.transform.position).normalized; + if (damage != 0f) + { + player.data.healthHandler.TakeDamage(TimeHandler.deltaTime * damage * normalized, base.transform.position, null, owner); + } + if (force != 0f) + { + float num = Mathf.Clamp(1f - Vector2.Distance(base.transform.position, player.transform.position) / range, 0f, 1f); + ForceMultiplier component = player.GetComponent<ForceMultiplier>(); + if ((bool)component) + { + num *= component.multiplier; + } + forceDir = normalized; + forceDir.y *= 0.5f; + player.data.playerVel.AddForce(forceDir * base.transform.localScale.x * num * TimeHandler.deltaTime * force, ForceMode2D.Force); + player.data.healthHandler.TakeForce(forceDir * num * 0.0005f * TimeHandler.deltaTime * force); + } + for (int j = 0; j < parts.Length; j++) + { + if (!parts[j].isPlaying) + { + parts[j].Play(); + } + } + if ((bool)sparkTransform) + { + sparkTransform.transform.position = player.transform.position; + if (normalized != Vector3.zero) + { + sparkTransform.rotation = Quaternion.LookRotation(normalized); + } + } + GamefeelManager.GameFeel((normalized + Random.onUnitSphere).normalized * shake * TimeHandler.deltaTime * 20f); + return; + } + for (int k = 0; k < parts.Length; k++) + { + if (parts[k].isPlaying) + { + parts[k].Stop(); + } + } + } +} diff --git a/GameCode/ScaleEvent.cs b/GameCode/ScaleEvent.cs new file mode 100644 index 0000000..923132d --- /dev/null +++ b/GameCode/ScaleEvent.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class ScaleEvent : MonoBehaviour +{ + public ScaleEventInstace[] events; + + private void Start() + { + ScaleEventInstace scaleEventInstace = null; + float num = 0f; + for (int i = 0; i < events.Length; i++) + { + if (base.transform.localScale.x > events[i].threshold && events[i].threshold > num) + { + num = events[i].threshold; + scaleEventInstace = events[i]; + } + } + scaleEventInstace?.scaleEvent.Invoke(); + } +} diff --git a/GameCode/ScaleEventInstace.cs b/GameCode/ScaleEventInstace.cs new file mode 100644 index 0000000..391d8f7 --- /dev/null +++ b/GameCode/ScaleEventInstace.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine.Events; + +[Serializable] +public class ScaleEventInstace +{ + public UnityEvent scaleEvent; + + public float threshold = 1f; +} diff --git a/GameCode/ScaleShake.cs b/GameCode/ScaleShake.cs new file mode 100644 index 0000000..b2a25b2 --- /dev/null +++ b/GameCode/ScaleShake.cs @@ -0,0 +1,76 @@ +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class ScaleShake : MonoBehaviour +{ + public bool useTimeScale = true; + + public float targetScale = 1f; + + public float multiplier = 1f; + + private float velocity; + + public float drag = 1f; + + public float spring = 1f; + + public float clampVelocity; + + internal float high; + + internal float low; + + private void Update() + { + float num = Mathf.Clamp(useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime, 0f, 0.02f); + if (clampVelocity != 0f) + { + velocity = Mathf.Clamp(velocity, 0f - clampVelocity, clampVelocity); + } + velocity += (targetScale - base.transform.localScale.x) * num * 50f * spring; + velocity -= drag * velocity * 20f * num; + base.transform.localScale += Vector3.one * (velocity * 10f * num); + } + + public void AddForce(float force) + { + velocity += force * multiplier * 5f; + } + + public void AddForce() + { + velocity += 1f * multiplier * 5f; + } + + public void SetTarget(float target) + { + targetScale = target; + } + + public void SetHigh() + { + targetScale = high; + } + + public void SetLow() + { + targetScale = low; + } + + public void ScaleOutRootPhoton() + { + StartCoroutine(GoAwayOutRootPhoton()); + } + + private IEnumerator GoAwayOutRootPhoton() + { + while (base.transform.localScale.x > 0f) + { + targetScale = 0f; + yield return null; + } + PhotonNetwork.Destroy(base.transform.root.gameObject); + } +} diff --git a/GameCode/ScaleTrailFromDamage.cs b/GameCode/ScaleTrailFromDamage.cs new file mode 100644 index 0000000..ffe41a8 --- /dev/null +++ b/GameCode/ScaleTrailFromDamage.cs @@ -0,0 +1,61 @@ +using UnityEngine; + +public class ScaleTrailFromDamage : MonoBehaviour +{ + private float startWidth; + + private float startTime; + + private void Start() + { + float num = 55f; + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + GetComponentInParent<RayCastTrail>(); + if ((bool)componentInParent) + { + num = componentInParent.damage; + } + TrailRenderer componentInChildren = GetComponentInChildren<TrailRenderer>(); + startWidth = componentInChildren.widthMultiplier; + startTime = componentInChildren.time; + if ((bool)componentInChildren) + { + componentInChildren.widthMultiplier *= (1f + num / 55f) / 2f; + componentInChildren.time *= Mathf.Clamp((1f + num / 55f) / 2f, 0f, 25f); + if (num > 100f) + { + componentInChildren.numCapVertices = 5; + } + if (num > 500f) + { + componentInChildren.numCapVertices = 10; + } + } + } + + public void Rescale() + { + float num = 55f; + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + RayCastTrail componentInParent2 = GetComponentInParent<RayCastTrail>(); + if ((bool)componentInParent) + { + num = componentInParent.damage; + } + TrailRenderer componentInChildren = GetComponentInChildren<TrailRenderer>(); + if ((bool)componentInChildren) + { + _ = componentInParent2.extraSize; + componentInChildren.widthMultiplier = startWidth * ((1f + num / 55f) / 2f); + componentInChildren.time = startTime * Mathf.Clamp((1f + num / 55f) / 2f, 0f, 25f); + if (num > 100f) + { + componentInChildren.numCapVertices = 5; + } + if (num > 100f) + { + componentInChildren.numCapVertices = 10; + } + } + } +} diff --git a/GameCode/ScaleWithHp.cs b/GameCode/ScaleWithHp.cs new file mode 100644 index 0000000..5649021 --- /dev/null +++ b/GameCode/ScaleWithHp.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class ScaleWithHp : MonoBehaviour +{ + private DamagableEvent dmg; + + public AnimationCurve curve; + + private void Start() + { + dmg = GetComponentInParent<DamagableEvent>(); + } + + private void Update() + { + base.transform.localScale = Vector3.one * curve.Evaluate(dmg.currentHP); + } +} diff --git a/GameCode/ScreenEdgeBounce.cs b/GameCode/ScreenEdgeBounce.cs new file mode 100644 index 0000000..21c8b69 --- /dev/null +++ b/GameCode/ScreenEdgeBounce.cs @@ -0,0 +1,132 @@ +using Photon.Pun; +using UnityEngine; + +public class ScreenEdgeBounce : MonoBehaviour +{ + private float sinceBounce = 1f; + + private Camera mainCam; + + private RayHitReflect reflect; + + private Vector2 lastNormal; + + private ProjectileHit projHit; + + private bool done; + + private RayHitBulletSound bulletSound; + + private PhotonView view; + + private void Start() + { + GetComponentInParent<ChildRPC>().childRPCsVector2Vector2IntInt.Add("ScreenBounce", DoHit); + view = GetComponentInParent<PhotonView>(); + bulletSound = GetComponentInParent<RayHitBulletSound>(); + projHit = GetComponentInParent<ProjectileHit>(); + ScreenEdgeBounce[] componentsInChildren = base.transform.root.GetComponentsInChildren<ScreenEdgeBounce>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (i > 0) + { + Object.Destroy(componentsInChildren[i]); + } + } + mainCam = MainCam.instance.transform.GetComponent<Camera>(); + reflect = GetComponentInParent<RayHitReflect>(); + } + + private void Update() + { + if (!view.IsMine || done) + { + return; + } + Vector3 vector = mainCam.WorldToScreenPoint(base.transform.position); + vector.x /= Screen.width; + vector.y /= Screen.height; + vector = new Vector3(Mathf.Clamp(vector.x, 0f, 1f), Mathf.Clamp(vector.y, 0f, 1f), vector.z); + if (vector.x != 0f && vector.x != 1f && vector.y != 1f && vector.y != 0f) + { + return; + } + Vector2 vector2 = Vector2.zero; + if (vector.x == 0f) + { + vector2 = Vector2.right; + } + else if (vector.x == 1f) + { + vector2 = -Vector2.right; + } + if (vector.y == 0f) + { + vector2 = Vector2.up; + } + else if (vector.y == 1f) + { + vector2 = -Vector2.up; + } + if (lastNormal == vector2 && Vector2.Angle(vector2, base.transform.forward) < 90f) + { + lastNormal = vector2; + return; + } + lastNormal = vector2; + vector.x *= Screen.width; + vector.y *= Screen.height; + RaycastHit2D raycastHit2D = default(RaycastHit2D); + raycastHit2D.normal = vector2; + raycastHit2D.point = mainCam.ScreenToWorldPoint(vector); + int num = -1; + if ((bool)raycastHit2D.transform) + { + PhotonView component = raycastHit2D.transform.root.GetComponent<PhotonView>(); + if ((bool)component) + { + num = component.ViewID; + } + } + int intData = -1; + if (num == -1) + { + Collider2D[] componentsInChildren = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i] == raycastHit2D.collider) + { + intData = i; + } + } + } + GetComponentInParent<ChildRPC>().CallFunction("ScreenBounce", raycastHit2D.point, raycastHit2D.normal, num, intData); + if (reflect.reflects <= 0) + { + done = true; + } + sinceBounce = 0f; + } + + private void DoHit(Vector2 hitPos, Vector2 hitNormal, int viewID = -1, int colliderID = -1) + { + HitInfo hitInfo = new HitInfo(); + hitInfo.point = hitPos; + hitInfo.normal = hitNormal; + hitInfo.collider = null; + if (viewID != -1) + { + PhotonView photonView = PhotonNetwork.GetPhotonView(viewID); + hitInfo.collider = photonView.GetComponentInChildren<Collider2D>(); + hitInfo.transform = photonView.transform; + } + else if (colliderID != -1) + { + hitInfo.collider = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>()[colliderID]; + hitInfo.transform = hitInfo.collider.transform; + } + DynamicParticles.instance.PlayBulletHit(projHit.damage, base.transform, hitInfo, projHit.projectileColor); + bulletSound.DoHitEffect(hitInfo); + reflect.DoHitEffect(hitInfo); + } +} diff --git a/GameCode/Screenshaker.cs b/GameCode/Screenshaker.cs new file mode 100644 index 0000000..d845eae --- /dev/null +++ b/GameCode/Screenshaker.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +public class Screenshaker : GameFeeler +{ + public bool ignoreTimeScale; + + public float spring = 100f; + + public float damper = 100f; + + public float shakeforce = 10f; + + public float threshold; + + private Vector2 velocity; + + private float clamp = 100f; + + private void Update() + { + float num = Mathf.Clamp(ignoreTimeScale ? Time.unscaledDeltaTime : TimeHandler.deltaTime, 0f, 0.015f); + velocity -= velocity.normalized * Mathf.Pow(velocity.magnitude, 0.8f) * damper * num; + velocity -= (Vector2)base.transform.localPosition * num * spring; + base.transform.position += (Vector3)velocity * num; + } + + private void ShakeInternal(Vector2 direction) + { + if (!(direction.magnitude < threshold)) + { + direction = Vector2.ClampMagnitude(direction, clamp); + velocity += direction * shakeforce; + } + } + + public override void OnGameFeel(Vector2 feelDirection) + { + if (!ignoreTimeScale) + { + feelDirection = Vector2.ClampMagnitude(feelDirection, clamp); + ShakeInternal(feelDirection); + } + } + + public override void OnUIGameFeel(Vector2 feelDirection) + { + if (ignoreTimeScale) + { + feelDirection = Vector2.ClampMagnitude(feelDirection, clamp); + ShakeInternal(feelDirection); + } + } +} diff --git a/GameCode/ServerMessage.cs b/GameCode/ServerMessage.cs new file mode 100644 index 0000000..71a6921 --- /dev/null +++ b/GameCode/ServerMessage.cs @@ -0,0 +1 @@ +public delegate void ServerMessage(string message); diff --git a/GameCode/SetActive.cs b/GameCode/SetActive.cs new file mode 100644 index 0000000..5856366 --- /dev/null +++ b/GameCode/SetActive.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SetActive : MonoBehaviour +{ + public void DoSetActive(bool active) + { + base.gameObject.SetActive(active); + } +} diff --git a/GameCode/SetColorByBlockCD.cs b/GameCode/SetColorByBlockCD.cs new file mode 100644 index 0000000..05e0083 --- /dev/null +++ b/GameCode/SetColorByBlockCD.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +public class SetColorByBlockCD : MonoBehaviour +{ + private Block block; + + private SpriteRenderer spriteRend; + + public Color onCDColor; + + public Color offCDColor; + + private bool isOnCD; + + private void Start() + { + block = GetComponentInParent<Block>(); + spriteRend = GetComponent<SpriteRenderer>(); + } + + private void Update() + { + if (isOnCD != block.IsOnCD()) + { + isOnCD = block.IsOnCD(); + if (isOnCD) + { + spriteRend.color = onCDColor; + } + else + { + spriteRend.color = offCDColor; + } + } + } +} diff --git a/GameCode/SetEmissionOverTimeByVelocity.cs b/GameCode/SetEmissionOverTimeByVelocity.cs new file mode 100644 index 0000000..f8aa877 --- /dev/null +++ b/GameCode/SetEmissionOverTimeByVelocity.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class SetEmissionOverTimeByVelocity : MonoBehaviour +{ + private ParticleSystem part; + + public AnimationCurve curve; + + private PlayerVelocity rig; + + private void Start() + { + rig = GetComponentInParent<PlayerVelocity>(); + part = GetComponent<ParticleSystem>(); + } + + private void Update() + { + ParticleSystem.EmissionModule emission = part.emission; + emission.rateOverDistance = curve.Evaluate(rig.velocity.magnitude); + } +} diff --git a/GameCode/SetLocalScale.cs b/GameCode/SetLocalScale.cs new file mode 100644 index 0000000..4f97804 --- /dev/null +++ b/GameCode/SetLocalScale.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class SetLocalScale : MonoBehaviour +{ + public Vector3 localScale = Vector3.one; + + public void Set() + { + base.transform.localScale = localScale; + } +} diff --git a/GameCode/SetOfflineMode.cs b/GameCode/SetOfflineMode.cs new file mode 100644 index 0000000..bc6a98e --- /dev/null +++ b/GameCode/SetOfflineMode.cs @@ -0,0 +1,30 @@ +using Photon.Pun; +using UnityEngine; + +public class SetOfflineMode : MonoBehaviour +{ + public bool doIt = true; + + private void Awake() + { + if (doIt) + { + SetOffline(); + } + } + + public void SetOffline() + { + PhotonNetwork.OfflineMode = true; + PhotonNetwork.JoinRandomRoom(); + } + + public void SetOnline() + { + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + } + PhotonNetwork.OfflineMode = false; + } +} diff --git a/GameCode/SetParticleTimeAfterSecondsToRemove.cs b/GameCode/SetParticleTimeAfterSecondsToRemove.cs new file mode 100644 index 0000000..8229d6a --- /dev/null +++ b/GameCode/SetParticleTimeAfterSecondsToRemove.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class SetParticleTimeAfterSecondsToRemove : MonoBehaviour +{ + private void Start() + { + ParticleSystem component = GetComponent<ParticleSystem>(); + component.Stop(); + ParticleSystem.MainModule main = component.main; + main.duration = GetComponentInParent<RemoveAfterSeconds>().seconds - main.startLifetime.constant; + component.Play(); + } +} diff --git a/GameCode/SetPlayerSpriteLayer.cs b/GameCode/SetPlayerSpriteLayer.cs new file mode 100644 index 0000000..cd0ba36 --- /dev/null +++ b/GameCode/SetPlayerSpriteLayer.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +public class SetPlayerSpriteLayer : MonoBehaviour +{ + private SpriteMask[] sprites; + + private bool simpleSkin; + + private void Start() + { + simpleSkin = GetComponent<PlayerSkinHandler>().simpleSkin; + Player componentInParent = GetComponentInParent<Player>(); + int num = SortingLayer.NameToID("Player" + (componentInParent.playerID + 1)); + setSpriteLayerOfChildren(GetComponentInParent<Holding>().holdable.gameObject, num); + setSpriteLayerOfChildren(base.gameObject, num); + if (!simpleSkin) + { + GetComponent<PlayerSkinHandler>().InitSpriteMask(num); + } + } + + private void setSpriteLayerOfChildren(GameObject obj, int layer) + { + sprites = obj.transform.root.GetComponentsInChildren<SpriteMask>(); + for (int i = 0; i < sprites.Length; i++) + { + if (simpleSkin) + { + sprites[i].enabled = false; + sprites[i].GetComponent<SpriteRenderer>().enabled = true; + } + else + { + sprites[i].frontSortingLayerID = layer; + sprites[i].backSortingLayerID = layer; + } + } + } + + public void ToggleSimple(bool isSimple) + { + simpleSkin = isSimple; + } +} diff --git a/GameCode/SetRotation.cs b/GameCode/SetRotation.cs new file mode 100644 index 0000000..284ccf4 --- /dev/null +++ b/GameCode/SetRotation.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +public class SetRotation : MonoBehaviour +{ + public float setRot; + + public float addRot; + + public float extraSetPerLevel; + + private float rot; + + private bool inited; + + private void Init() + { + if (!inited) + { + inited = true; + int attackLevel = GetComponentInParent<AttackLevel>().attackLevel; + setRot += (float)attackLevel * extraSetPerLevel; + } + } + + public void Set() + { + Init(); + rot = setRot; + base.transform.localRotation = Quaternion.Euler(new Vector3(rot, 0f, 0f)); + } + + public void Add() + { + Init(); + rot += addRot; + base.transform.localRotation = Quaternion.Euler(new Vector3(rot, 0f, 0f)); + } +} diff --git a/GameCode/SetScaleFromSizeAndExtraSize.cs b/GameCode/SetScaleFromSizeAndExtraSize.cs new file mode 100644 index 0000000..22b2849 --- /dev/null +++ b/GameCode/SetScaleFromSizeAndExtraSize.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class SetScaleFromSizeAndExtraSize : MonoBehaviour +{ + public float scalePerSize; + + private void Start() + { + float size = GetComponentInParent<RayCastTrail>().size; + base.transform.localScale *= size * scalePerSize; + } +} diff --git a/GameCode/SetScaleToZero.cs b/GameCode/SetScaleToZero.cs new file mode 100644 index 0000000..e72085e --- /dev/null +++ b/GameCode/SetScaleToZero.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SetScaleToZero : MonoBehaviour +{ + private void Start() + { + base.transform.localScale = Vector3.zero; + } +} diff --git a/GameCode/SetSpawnedParticleColor.cs b/GameCode/SetSpawnedParticleColor.cs new file mode 100644 index 0000000..fc9052b --- /dev/null +++ b/GameCode/SetSpawnedParticleColor.cs @@ -0,0 +1,30 @@ +using System; +using UnityEngine; + +public class SetSpawnedParticleColor : MonoBehaviour +{ + private Color myColor; + + private void Start() + { + SpawnObjects component = GetComponent<SpawnObjects>(); + component.SpawnedAction = (Action<GameObject>)Delegate.Combine(component.SpawnedAction, new Action<GameObject>(Go)); + myColor = PlayerSkinBank.GetPlayerSkinColors(GetComponentInParent<SpawnedAttack>().spawner.playerID).particleEffect; + } + + private void Go(GameObject spawned) + { + ParticleSystem[] componentsInChildren = spawned.GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].startColor = myColor; + } + LineEffect[] componentsInChildren2 = spawned.GetComponentsInChildren<LineEffect>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + componentsInChildren2[j].useColorOverTime = false; + componentsInChildren2[j].GetComponent<LineRenderer>().startColor = myColor; + componentsInChildren2[j].GetComponent<LineRenderer>().endColor = myColor; + } + } +} diff --git a/GameCode/SetSpecificArt.cs b/GameCode/SetSpecificArt.cs new file mode 100644 index 0000000..b673df8 --- /dev/null +++ b/GameCode/SetSpecificArt.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class SetSpecificArt : MonoBehaviour +{ + public PostProcessProfile profile; + + public string artName; + + public bool playOnStart; + + private void Start() + { + if (playOnStart) + { + if ((bool)profile) + { + ArtHandler.instance.ApplyPost(profile); + } + if (artName != "") + { + ArtHandler.instance.SetSpecificArt(artName); + } + } + } + + public void Go() + { + if ((bool)profile) + { + ArtHandler.instance.ApplyPost(profile); + } + if (artName != "") + { + ArtHandler.instance.SetSpecificArt(artName); + } + } +} diff --git a/GameCode/SetSpriteColor.cs b/GameCode/SetSpriteColor.cs new file mode 100644 index 0000000..8b27d60 --- /dev/null +++ b/GameCode/SetSpriteColor.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class SetSpriteColor : MonoBehaviour +{ + private SpriteRenderer sprite; + + public Color[] cols; + + private void Start() + { + sprite = GetComponent<SpriteRenderer>(); + } + + public void SetColor(int id) + { + sprite.color = cols[id]; + } +} diff --git a/GameCode/SetTeamColor.cs b/GameCode/SetTeamColor.cs new file mode 100644 index 0000000..479c1d3 --- /dev/null +++ b/GameCode/SetTeamColor.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEngine.Events; + +public class SetTeamColor : MonoBehaviour +{ + public enum ColorType + { + Main, + Background, + Particle, + WinText + } + + private SpriteRenderer m_spriteRenderer; + + private ParticleSystem m_particleSystem; + + private LineRenderer m_lineRenderer; + + public UnityEvent SetColorEvent; + + private MeshRenderer meshRend; + + public ColorType colorType; + + private void Awake() + { + m_spriteRenderer = GetComponent<SpriteRenderer>(); + meshRend = GetComponent<MeshRenderer>(); + m_lineRenderer = GetComponent<LineRenderer>(); + } + + public void Set(PlayerSkin teamColor) + { + Color color = teamColor.color; + if (colorType == ColorType.Background) + { + color = teamColor.backgroundColor; + } + if (colorType == ColorType.Particle) + { + color = teamColor.particleEffect; + } + if (colorType == ColorType.WinText) + { + color = teamColor.winText; + } + if ((bool)m_lineRenderer) + { + m_lineRenderer.startColor = color; + m_lineRenderer.endColor = color; + } + else if ((bool)m_spriteRenderer) + { + m_spriteRenderer.color = color; + } + else if ((bool)meshRend) + { + meshRend.material.color = color; + } + else + { + m_particleSystem = GetComponent<ParticleSystem>(); + if ((bool)m_particleSystem) + { + ParticleSystem.MainModule main = m_particleSystem.main; + main.startColor = color; + } + } + SetColorEvent.Invoke(); + } + + public static void TeamColorThis(GameObject go, PlayerSkin teamColor) + { + if (!(teamColor == null)) + { + SetTeamColor[] componentsInChildren = go.GetComponentsInChildren<SetTeamColor>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].Set(teamColor); + } + } + } +} diff --git a/GameCode/SetTeamColorFromParentPlayer.cs b/GameCode/SetTeamColorFromParentPlayer.cs new file mode 100644 index 0000000..26e6615 --- /dev/null +++ b/GameCode/SetTeamColorFromParentPlayer.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class SetTeamColorFromParentPlayer : MonoBehaviour +{ + private void Start() + { + Player player = GetComponentInParent<Player>(); + if (!player) + { + player = GetComponentInParent<SpawnedAttack>().spawner; + } + GetComponent<SetTeamColor>().Set(PlayerSkinBank.GetPlayerSkinColors(player.playerID)); + } +} diff --git a/GameCode/SetTeamColorFromSpawnedAttack.cs b/GameCode/SetTeamColorFromSpawnedAttack.cs new file mode 100644 index 0000000..6130323 --- /dev/null +++ b/GameCode/SetTeamColorFromSpawnedAttack.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SetTeamColorFromSpawnedAttack : MonoBehaviour +{ + private void Start() + { + GetComponent<SetTeamColor>().Set(PlayerSkinBank.GetPlayerSkinColors(GetComponentInParent<SpawnedAttack>().spawner.playerID)); + } +} diff --git a/GameCode/SetTeamColorSpecific.cs b/GameCode/SetTeamColorSpecific.cs new file mode 100644 index 0000000..d5e9fe8 --- /dev/null +++ b/GameCode/SetTeamColorSpecific.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class SetTeamColorSpecific : MonoBehaviour +{ + public Color[] colors; + + private void Start() + { + Player player = GetComponentInParent<Player>(); + if (!player) + { + player = GetComponentInParent<SpawnedAttack>().spawner; + } + ParticleSystem component = GetComponent<ParticleSystem>(); + if ((bool)component) + { + _ = component.main; + component.startColor = colors[player.playerID]; + } + LineRenderer component2 = GetComponent<LineRenderer>(); + if ((bool)component2) + { + component2.startColor = colors[player.playerID]; + component2.endColor = colors[player.playerID]; + } + } +} diff --git a/GameCode/SetTextColor.cs b/GameCode/SetTextColor.cs new file mode 100644 index 0000000..16e8a70 --- /dev/null +++ b/GameCode/SetTextColor.cs @@ -0,0 +1,12 @@ +using TMPro; +using UnityEngine; + +public class SetTextColor : MonoBehaviour +{ + public Color[] colors; + + public void SetColor(int id) + { + GetComponent<TextMeshProUGUI>().color = colors[id]; + } +} diff --git a/GameCode/ShieldCharge.cs b/GameCode/ShieldCharge.cs new file mode 100644 index 0000000..a2860d1 --- /dev/null +++ b/GameCode/ShieldCharge.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Sonigon; +using UnityEngine; + +public class ShieldCharge : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundShieldCharge; + + [Header("Settings")] + public float damagePerLevel; + + [Header("Settings")] + public float knockBackPerLevel; + + public float forcePerLevel; + + public float timePerLevel; + + public ParticleSystem hitPart; + + public float shake; + + public float damage; + + public float knockBack; + + public float stopForce; + + public AnimationCurve forceCurve; + + public float force; + + public float drag; + + public float time; + + private CharacterData data; + + private AttackLevel level; + + private Vector3 dir; + + private bool cancelForce; + + private List<CharacterData> hitDatas = new List<CharacterData>(); + + private float blockTime; + + private void Start() + { + level = GetComponent<AttackLevel>(); + data = GetComponentInParent<CharacterData>(); + PlayerCollision component = data.GetComponent<PlayerCollision>(); + component.collideWithPlayerAction = (Action<Vector2, Vector2, Player>)Delegate.Combine(component.collideWithPlayerAction, new Action<Vector2, Vector2, Player>(Collide)); + GetComponentInParent<ChildRPC>().childRPCsVector2Vector2Int.Add("ShieldChargeCollide", RPCA_Collide); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(DoBlock)); + } + + private void OnDestroy() + { + PlayerCollision component = data.GetComponent<PlayerCollision>(); + component.collideWithPlayerAction = (Action<Vector2, Vector2, Player>)Delegate.Remove(component.collideWithPlayerAction, new Action<Vector2, Vector2, Player>(Collide)); + GetComponentInParent<ChildRPC>().childRPCsVector2Vector2Int.Remove("ShieldChargeCollide"); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(DoBlock)); + } + + private void Update() + { + blockTime -= TimeHandler.deltaTime; + } + + public void DoBlock(BlockTrigger.BlockTriggerType trigger) + { + if (trigger != BlockTrigger.BlockTriggerType.ShieldCharge) + { + Charge(trigger); + } + } + + public void Charge(BlockTrigger.BlockTriggerType trigger) + { + StartCoroutine(DoCharge(trigger)); + } + + private IEnumerator DoCharge(BlockTrigger.BlockTriggerType trigger) + { + SoundManager.Instance.Play(soundShieldCharge, base.transform); + cancelForce = false; + hitDatas.Clear(); + if (trigger == BlockTrigger.BlockTriggerType.Empower) + { + Vector3 currentPos = base.transform.position; + yield return new WaitForSeconds(0f); + dir = (currentPos - base.transform.position).normalized; + } + else + { + dir = data.aimDirection; + } + float usedTime = (blockTime = time + (float)level.LevelsUp() * timePerLevel); + float num = time * 0.1f + (float)level.LevelsUp() * time * 0.15f; + for (int i = 0; i < level.LevelsUp(); i++) + { + float num2 = time / (float)level.attackLevel; + _ = time; + num += num2; + StartCoroutine(DelayBlock(num)); + } + float c = 0f; + while (c < 1f) + { + c += Time.fixedDeltaTime / usedTime; + if (!cancelForce) + { + data.healthHandler.TakeForce(dir * forceCurve.Evaluate(c) * (force + (float)level.LevelsUp() * forcePerLevel), ForceMode2D.Force, forceIgnoreMass: true, ignoreBlock: true); + data.healthHandler.TakeForce(-data.playerVel.velocity * drag * Time.fixedDeltaTime, ForceMode2D.Force, forceIgnoreMass: true, ignoreBlock: true); + } + data.sinceGrounded = 0f; + yield return new WaitForFixedUpdate(); + } + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.ShieldCharge); + } + + private IEnumerator DelayBlock(float delay) + { + yield return new WaitForSeconds(delay); + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.ShieldCharge); + } + + public void RPCA_Collide(Vector2 pos, Vector2 colDir, int playerID) + { + CharacterData componentInParent = PlayerManager.instance.GetPlayerWithID(playerID).gameObject.GetComponentInParent<CharacterData>(); + if ((bool)componentInParent) + { + cancelForce = true; + hitPart.transform.rotation = Quaternion.LookRotation(dir); + hitPart.Play(); + componentInParent.healthHandler.TakeDamage(dir * (damage + (float)level.LevelsUp() * damagePerLevel), base.transform.position, null, data.player); + componentInParent.healthHandler.TakeForce(dir * (knockBack + (float)level.LevelsUp() * knockBackPerLevel)); + data.healthHandler.TakeForce(-dir * knockBack, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: true); + data.healthHandler.TakeForce(-dir * stopForce, ForceMode2D.Impulse, forceIgnoreMass: true, ignoreBlock: true); + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.ShieldCharge); + GamefeelManager.GameFeel(dir * shake); + } + } + + public void Collide(Vector2 pos, Vector2 colDir, Player player) + { + if (!data.view.IsMine || blockTime < 0f) + { + return; + } + CharacterData componentInParent = player.gameObject.GetComponentInParent<CharacterData>(); + if (!hitDatas.Contains(componentInParent)) + { + hitDatas.Add(componentInParent); + if ((bool)componentInParent) + { + GetComponentInParent<ChildRPC>().CallFunction("ShieldChargeCollide", pos, colDir, player.playerID); + } + } + } +} diff --git a/GameCode/ShootPos.cs b/GameCode/ShootPos.cs new file mode 100644 index 0000000..ca75170 --- /dev/null +++ b/GameCode/ShootPos.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class ShootPos : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/SilenceHandler.cs b/GameCode/SilenceHandler.cs new file mode 100644 index 0000000..a1cab30 --- /dev/null +++ b/GameCode/SilenceHandler.cs @@ -0,0 +1,70 @@ +using Photon.Pun; +using UnityEngine; + +public class SilenceHandler : MonoBehaviour +{ + [Header("Settings")] + public CodeAnimation codeAnim; + + private Player player; + + private CharacterData data; + + private void Start() + { + player = GetComponent<Player>(); + data = player.data; + } + + private void Update() + { + if (data.silenceTime > 0f) + { + data.silenceTime -= TimeHandler.deltaTime; + if (!data.isSilenced) + { + StartSilence(); + } + } + else if (data.isSilenced) + { + StopSilence(); + } + } + + private void StartSilence() + { + player.data.input.silencedInput = true; + codeAnim.PlayIn(); + data.isSilenced = true; + } + + public void StopSilence() + { + player.data.input.silencedInput = false; + if (codeAnim.currentState == CodeAnimationInstance.AnimationUse.In) + { + codeAnim.PlayOut(); + } + data.isSilenced = false; + data.silenceTime = 0f; + } + + private void OnDisable() + { + codeAnim.transform.localScale = Vector3.zero; + } + + [PunRPC] + public void RPCA_AddSilence(float f) + { + if (f > data.silenceTime) + { + data.silenceTime = f; + } + if (!data.isSilenced) + { + StartSilence(); + } + } +} diff --git a/GameCode/SimulatedSelection.cs b/GameCode/SimulatedSelection.cs new file mode 100644 index 0000000..d80866b --- /dev/null +++ b/GameCode/SimulatedSelection.cs @@ -0,0 +1,33 @@ +using UnityEngine; +using UnityEngine.UI; + +public class SimulatedSelection : MonoBehaviour +{ + private HoverEvent hoverEvent; + + private Button button; + + private void Start() + { + hoverEvent = GetComponent<HoverEvent>(); + button = GetComponent<Button>(); + } + + private void OnDisable() + { + Deselect(); + } + + public void Select() + { + hoverEvent.OnPointerEnter(null); + button.targetGraphic.color = button.colors.highlightedColor; + } + + public void Deselect() + { + hoverEvent.OnPointerExit(null); + button.OnDeselect(null); + button.targetGraphic.color = button.colors.normalColor; + } +} diff --git a/GameCode/SkipIntro.cs b/GameCode/SkipIntro.cs new file mode 100644 index 0000000..809d294 --- /dev/null +++ b/GameCode/SkipIntro.cs @@ -0,0 +1,38 @@ +using InControl; +using UnityEngine; + +public class SkipIntro : MonoBehaviour +{ + public static bool hasShown; + + public ListMenuPage target; + + private void Start() + { + if (hasShown) + { + Skip(); + } + hasShown = true; + } + + private void Update() + { + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].AnyButton.WasPressed) + { + Skip(); + } + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + Skip(); + } + } + + private void Skip() + { + target.Open(); + } +} diff --git a/GameCode/SliceEffect.cs b/GameCode/SliceEffect.cs new file mode 100644 index 0000000..e8f1021 --- /dev/null +++ b/GameCode/SliceEffect.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class SliceEffect : MonoBehaviour +{ +} diff --git a/GameCode/SoundAudioListenerPosition.cs b/GameCode/SoundAudioListenerPosition.cs new file mode 100644 index 0000000..be8fbd3 --- /dev/null +++ b/GameCode/SoundAudioListenerPosition.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +public class SoundAudioListenerPosition : MonoBehaviour +{ + private float positionZaxis = -50f; + + private AudioListener audioListener; + + private Transform audioListenerTransform; + + private Transform cachedTransform; + + private Vector3 postion; + + private void Awake() + { + audioListener = Object.FindObjectOfType<AudioListener>(); + if (audioListener == null) + { + Debug.LogError("No AudioListener Found"); + } + else + { + audioListenerTransform = audioListener.transform; + } + cachedTransform = base.transform; + } + + private void Update() + { + if (audioListenerTransform != null) + { + postion = cachedTransform.position; + postion.z = positionZaxis; + audioListenerTransform.position = postion; + } + } +} diff --git a/GameCode/SpawnBulletHit.cs b/GameCode/SpawnBulletHit.cs new file mode 100644 index 0000000..27ba4e7 --- /dev/null +++ b/GameCode/SpawnBulletHit.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class SpawnBulletHit : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/GameCode/SpawnMinion.cs b/GameCode/SpawnMinion.cs new file mode 100644 index 0000000..2b28914 --- /dev/null +++ b/GameCode/SpawnMinion.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +public class SpawnMinion : MonoBehaviour +{ + public GameObject card; + + public GameObject minionAI; + + public GameObject minion; + + private CharacterData data; + + private AttackLevel level; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + level = GetComponentInParent<AttackLevel>(); + } + + public void Go() + { + for (int i = 0; i < level.attackLevel; i++) + { + GameObject gameObject = Object.Instantiate(minion, base.transform.position + Vector3.up * (((float)i + 1f) * 0.5f), base.transform.rotation); + Object.Instantiate(minionAI, gameObject.transform.position, gameObject.transform.rotation, gameObject.transform); + CharacterData component = gameObject.GetComponent<CharacterData>(); + component.SetAI(data.player); + component.player.playerID = data.player.playerID; + component.isPlaying = true; + card.GetComponent<ApplyCardStats>().Pick(component.player.teamID, forcePick: true); + gameObject.GetComponentInChildren<PlayerSkinHandler>().ToggleSimpleSkin(isSimple: true); + component.healthHandler.DestroyOnDeath = true; + } + } +} diff --git a/GameCode/SpawnObjectEffect.cs b/GameCode/SpawnObjectEffect.cs new file mode 100644 index 0000000..a383ff9 --- /dev/null +++ b/GameCode/SpawnObjectEffect.cs @@ -0,0 +1,101 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +public class SpawnObjectEffect : MonoBehaviour +{ + public enum Dir + { + TowardsEnemy, + DamageDirction, + ReverseDamageDir, + TowardsRecentlyDamaged + } + + public Dir dir; + + [FoldoutGroup("Gun", 0)] + public bool spawnAttack; + + [FoldoutGroup("Gun", 0)] + public float bulletDamageMultiplier = 0.5f; + + [FoldoutGroup("Gun", 0)] + public int numberOfattacks = 1; + + [FoldoutGroup("Gun", 0)] + public float spread; + + [FoldoutGroup("Gun", 0)] + public float gravityMultiplier = 1f; + + [FoldoutGroup("Gun", 0)] + public float speedMultiplier = 1f; + + [FoldoutGroup("Gun", 0)] + public float extraSpread; + + [FoldoutGroup("Gun", 0)] + public float recoilMultiplier = 1f; + + [FoldoutGroup("Gun", 0)] + public int maxBullets = 100; + + private Holding holding; + + private Gun gun; + + private Player player; + + private void Start() + { + holding = GetComponentInParent<Holding>(); + player = GetComponentInParent<Player>(); + } + + public void DoEffect(Vector2 dmg) + { + int num = 0; + if (!spawnAttack) + { + return; + } + for (int i = 0; i < numberOfattacks; i++) + { + if (!gun && (bool)holding && (bool)holding.holdable) + { + gun = holding.holdable.GetComponent<Gun>(); + } + if ((bool)gun) + { + Quaternion rotation = gun.transform.rotation; + Vector3 vector = (PlayerManager.instance.GetOtherPlayer(player).transform.position - base.transform.position).normalized; + if (dir == Dir.DamageDirction) + { + vector = dmg.normalized; + } + if (dir == Dir.ReverseDamageDir) + { + vector = -dmg.normalized; + } + if (dir == Dir.TowardsRecentlyDamaged) + { + vector = (player.data.lastDamagedPlayer.transform.position - base.transform.position).normalized; + } + gun.transform.rotation = Quaternion.LookRotation(Vector3.forward, vector + gun.transform.right * Random.Range(0f - spread, spread)); + gun.projectileSpeed *= speedMultiplier; + gun.gravity *= gravityMultiplier; + gun.spread += extraSpread; + gun.Attack(1f, forceAttack: true, bulletDamageMultiplier, recoilMultiplier); + num += (int)((float)gun.numberOfProjectiles + gun.chargeNumberOfProjectilesTo); + gun.projectileSpeed /= speedMultiplier; + gun.gravity /= gravityMultiplier; + gun.spread -= extraSpread; + gun.transform.rotation = rotation; + if (num > maxBullets) + { + break; + } + } + } + } +} diff --git a/GameCode/SpawnObjectOnDealDamage.cs b/GameCode/SpawnObjectOnDealDamage.cs new file mode 100644 index 0000000..be5b365 --- /dev/null +++ b/GameCode/SpawnObjectOnDealDamage.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using UnityEngine.Events; + +public class SpawnObjectOnDealDamage : DealtDamageEffect +{ + public UnityEvent triggerEvent; + + public float damageNeeded = 25f; + + public float cd = 0.2f; + + private float time; + + private float damageDealt; + + private SpawnObjectEffect spawn; + + private DamageEffect dmgEffect; + + public bool allowSelfDmg; + + private void Start() + { + spawn = GetComponent<SpawnObjectEffect>(); + dmgEffect = GetComponent<DamageEffect>(); + } + + public override void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null) + { + if (selfDamage && !allowSelfDmg) + { + return; + } + damageDealt += damage.magnitude; + if (damageDealt > damageNeeded && Time.time > time + cd) + { + time = Time.time; + damageDealt = 0f; + if ((bool)spawn) + { + spawn.DoEffect(damage); + } + if ((bool)dmgEffect) + { + dmgEffect.DoDamageEffect(damage, selfDamage, damagedPlayer); + } + triggerEvent.Invoke(); + } + } +} diff --git a/GameCode/SpawnObjectOnDealtDamage.cs b/GameCode/SpawnObjectOnDealtDamage.cs new file mode 100644 index 0000000..0c4d8cf --- /dev/null +++ b/GameCode/SpawnObjectOnDealtDamage.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +public class SpawnObjectOnDealtDamage : WasDealtDamageEffect +{ + public float damageNeeded = 25f; + + public float cd = 0.2f; + + public bool allowSelfDamage; + + private float time; + + private float damageDealt; + + private SpawnObjectEffect spawn; + + private void Start() + { + spawn = GetComponent<SpawnObjectEffect>(); + } + + public override void WasDealtDamage(Vector2 damage, bool selfDamage) + { + if (!selfDamage || allowSelfDamage) + { + damageDealt += damage.magnitude; + if (damageDealt > damageNeeded && Time.time > time + cd) + { + time = Time.time; + damageDealt = 0f; + spawn.DoEffect(damage); + } + } + } +} diff --git a/GameCode/SpawnObjects.cs b/GameCode/SpawnObjects.cs new file mode 100644 index 0000000..8f00c7a --- /dev/null +++ b/GameCode/SpawnObjects.cs @@ -0,0 +1,83 @@ +using System; +using Photon.Pun; +using UnityEngine; + +public class SpawnObjects : MonoBehaviour +{ + public enum SpawnRot + { + Identity, + TransformRotation + } + + public GameObject[] objectToSpawn; + + public SpawnRot spawnRot; + + public bool inheritScale; + + public bool destroyObject; + + public bool destroyRoot; + + private PhotonView view; + + public Action<GameObject> SpawnedAction; + + [HideInInspector] + public GameObject mostRecentlySpawnedObject; + + private void ConfigureObject(GameObject go) + { + SpawnedAttack spawnedAttack = go.GetComponent<SpawnedAttack>(); + if (!spawnedAttack) + { + spawnedAttack = go.AddComponent<SpawnedAttack>(); + } + spawnedAttack.spawner = base.transform.root.GetComponent<Player>(); + if (!spawnedAttack.spawner) + { + SpawnedAttack componentInParent = base.transform.GetComponentInParent<SpawnedAttack>(); + if ((bool)componentInParent) + { + componentInParent.CopySpawnedAttackTo(go); + } + } + AttackLevel componentInParent2 = GetComponentInParent<AttackLevel>(); + if ((bool)componentInParent2) + { + spawnedAttack.attackLevel = componentInParent2.attackLevel; + } + if (inheritScale) + { + go.transform.localScale *= base.transform.localScale.x; + } + if (SpawnedAction != null) + { + SpawnedAction(go); + } + } + + public void Spawn() + { + for (int i = 0; i < objectToSpawn.Length; i++) + { + Quaternion rotation = Quaternion.identity; + if (spawnRot == SpawnRot.TransformRotation) + { + rotation = base.transform.rotation; + } + GameObject go = UnityEngine.Object.Instantiate(objectToSpawn[i], base.transform.position, rotation); + ConfigureObject(go); + mostRecentlySpawnedObject = go; + } + if (destroyObject) + { + UnityEngine.Object.Destroy(base.gameObject); + } + if (destroyRoot) + { + UnityEngine.Object.Destroy(base.transform.root.gameObject); + } + } +} diff --git a/GameCode/SpawnPoint.cs b/GameCode/SpawnPoint.cs new file mode 100644 index 0000000..5a4a0cf --- /dev/null +++ b/GameCode/SpawnPoint.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class SpawnPoint : MonoBehaviour +{ + public int ID; + + public int TEAMID; + + public Vector3 localStartPos; + + private void Awake() + { + localStartPos = base.transform.localPosition; + } +} diff --git a/GameCode/SpawnStaticRemnant.cs b/GameCode/SpawnStaticRemnant.cs new file mode 100644 index 0000000..9e0a67e --- /dev/null +++ b/GameCode/SpawnStaticRemnant.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class SpawnStaticRemnant : MonoBehaviour +{ + public GameObject remnantSource; + + private AttackLevel level; + + private Color remnantColor; + + private void Start() + { + remnantColor = PlayerSkinBank.GetPlayerSkinColors(base.transform.GetComponentInParent<Player>().playerID).winText; + level = GetComponent<AttackLevel>(); + } + + public void Go() + { + GameObject gameObject = Object.Instantiate(remnantSource, base.transform.position, base.transform.rotation); + SpriteRenderer[] componentsInChildren = base.transform.root.GetComponentsInChildren<SpriteRenderer>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].transform.lossyScale.x != 0f && componentsInChildren[i].transform.lossyScale.y != 0f && componentsInChildren[i].transform.lossyScale.z != 0f && (!(componentsInChildren[i].transform.parent.name != "Art") || !(componentsInChildren[i].transform.parent.parent.name != "Face"))) + { + Vector3 lossyScale = componentsInChildren[i].transform.lossyScale; + GameObject gameObject2 = Object.Instantiate(componentsInChildren[i].gameObject, componentsInChildren[i].transform.position, componentsInChildren[i].transform.rotation, gameObject.transform.GetChild(0)); + gameObject2.transform.localScale = lossyScale; + Strip(gameObject2); + SpriteRenderer component = gameObject2.GetComponent<SpriteRenderer>(); + component.enabled = true; + component.color = remnantColor; + SpriteMask component2 = gameObject2.GetComponent<SpriteMask>(); + if ((bool)component2) + { + Object.Destroy(component2); + } + } + } + gameObject.GetComponentInChildren<ParticleSystem>().startColor = PlayerSkinBank.GetPlayerSkinColors(base.transform.GetComponentInParent<Player>().playerID).particleEffect; + gameObject.AddComponent<SpawnedAttack>().spawner = base.transform.root.GetComponent<Player>(); + gameObject.transform.localScale *= 1f + (float)(level.attackLevel - 1) * 0.3f; + } + + private void Strip(GameObject go) + { + MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + Object.Destroy(componentsInChildren[i]); + } + } +} diff --git a/GameCode/SpawnedAttack.cs b/GameCode/SpawnedAttack.cs new file mode 100644 index 0000000..8a4a096 --- /dev/null +++ b/GameCode/SpawnedAttack.cs @@ -0,0 +1,63 @@ +using Photon.Pun; +using UnityEngine; + +public class SpawnedAttack : MonoBehaviour +{ + public Player spawner; + + public int attackLevel; + + public int attackID; + + public PhotonView view; + + private void Awake() + { + view = GetComponent<PhotonView>(); + } + + [PunRPC] + public void RPCA_SetSpawner(int spawnerID) + { + spawner = PhotonNetwork.GetPhotonView(spawnerID).GetComponent<Player>(); + } + + public void CopySpawnedAttackTo(GameObject to) + { + SpawnedAttack spawnedAttack = to.GetComponent<SpawnedAttack>(); + if (!spawnedAttack) + { + spawnedAttack = to.AddComponent<SpawnedAttack>(); + } + spawnedAttack.spawner = spawner; + spawnedAttack.attackLevel = attackLevel; + } + + public void SetColor(Color color) + { + TrailRenderer[] componentsInChildren = GetComponentsInChildren<TrailRenderer>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].startColor = color; + componentsInChildren[i].endColor = color; + } + ProjectileHit component = GetComponent<ProjectileHit>(); + if ((bool)component) + { + component.projectileColor = color; + } + } + + public bool IsMine() + { + if ((bool)view) + { + return view.IsMine; + } + if ((bool)spawner) + { + return spawner.data.view.IsMine; + } + return false; + } +} diff --git a/GameCode/SpawnedAttack_ParentPlayer.cs b/GameCode/SpawnedAttack_ParentPlayer.cs new file mode 100644 index 0000000..f77247f --- /dev/null +++ b/GameCode/SpawnedAttack_ParentPlayer.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SpawnedAttack_ParentPlayer : MonoBehaviour +{ + private void Start() + { + GetComponent<SpawnedAttack>().spawner = GetComponentInParent<Player>(); + } +} diff --git a/GameCode/Spring.cs b/GameCode/Spring.cs new file mode 100644 index 0000000..35cb057 --- /dev/null +++ b/GameCode/Spring.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class Spring : MonoBehaviour +{ + public float spring = 1f; + + private Rigidbody2D rig; + + private Vector3 up; + + private void Start() + { + rig = GetComponent<Rigidbody2D>(); + up = base.transform.up; + } + + private void FixedUpdate() + { + if ((bool)rig) + { + rig.AddTorque((Vector3.Cross(base.transform.up, up).normalized * Vector3.Angle(base.transform.up, up)).z * spring * rig.mass); + } + } +} diff --git a/GameCode/StandStillTrigger.cs b/GameCode/StandStillTrigger.cs new file mode 100644 index 0000000..b5dc487 --- /dev/null +++ b/GameCode/StandStillTrigger.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class StandStillTrigger : MonoBehaviour +{ + public float sinceStandStill; + + private CharacterData data; + + private void Start() + { + data = base.transform.GetComponentInParent<CharacterData>(); + } + + private void Update() + { + if (data.isGrounded && data.input.direction.magnitude < 0.1f) + { + sinceStandStill += TimeHandler.deltaTime; + } + else + { + sinceStandStill = 0f; + } + } +} diff --git a/GameCode/StartEvent.cs b/GameCode/StartEvent.cs new file mode 100644 index 0000000..b05cd6e --- /dev/null +++ b/GameCode/StartEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class StartEvent : MonoBehaviour +{ + public UnityEvent startEvent; + + private void Start() + { + startEvent.Invoke(); + } +} diff --git a/GameCode/StatsAfterDealingDamage.cs b/GameCode/StatsAfterDealingDamage.cs new file mode 100644 index 0000000..d228813 --- /dev/null +++ b/GameCode/StatsAfterDealingDamage.cs @@ -0,0 +1,68 @@ +using UnityEngine; +using UnityEngine.Events; + +public class StatsAfterDealingDamage : MonoBehaviour +{ + public float duration = 3f; + + public float movementSpeedMultiplier = 1f; + + public float jumpMultiplier = 1f; + + public float hpMultiplier = 1f; + + public UnityEvent startEvent; + + public UnityEvent endEvent; + + private bool isOn; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + bool flag = data.stats.sinceDealtDamage < duration; + if (isOn != flag) + { + isOn = flag; + _ = base.transform.localScale; + if (isOn) + { + data.health *= hpMultiplier; + data.maxHealth *= hpMultiplier; + data.stats.movementSpeed *= movementSpeedMultiplier; + data.stats.jump *= jumpMultiplier; + data.stats.ConfigureMassAndSize(); + startEvent.Invoke(); + } + else + { + data.health /= hpMultiplier; + data.maxHealth /= hpMultiplier; + data.stats.movementSpeed /= movementSpeedMultiplier; + data.stats.jump /= jumpMultiplier; + data.stats.ConfigureMassAndSize(); + endEvent.Invoke(); + } + } + } + + public void Interupt() + { + if (isOn) + { + data.health /= hpMultiplier; + data.maxHealth /= hpMultiplier; + data.stats.movementSpeed /= movementSpeedMultiplier; + data.stats.jump /= jumpMultiplier; + data.stats.ConfigureMassAndSize(); + endEvent.Invoke(); + isOn = false; + } + } +} diff --git a/GameCode/StatsWhenFullHP.cs b/GameCode/StatsWhenFullHP.cs new file mode 100644 index 0000000..21166c7 --- /dev/null +++ b/GameCode/StatsWhenFullHP.cs @@ -0,0 +1,58 @@ +using Sonigon; +using UnityEngine; + +public class StatsWhenFullHP : MonoBehaviour +{ + public bool playSound; + + public SoundEvent soundPristineGrow; + + public SoundEvent soundPristineShrink; + + public float healthMultiplier = 1f; + + public float sizeMultiplier = 1f; + + public float healthThreshold = 0.95f; + + private CharacterData data; + + private bool isOn; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + bool flag = data.health / data.maxHealth >= healthThreshold; + if (flag == isOn) + { + return; + } + isOn = flag; + if (isOn) + { + if (playSound) + { + SoundManager.Instance.PlayAtPosition(soundPristineGrow, SoundManager.Instance.GetTransform(), base.transform); + } + data.health *= healthMultiplier; + data.maxHealth *= healthMultiplier; + data.stats.sizeMultiplier *= sizeMultiplier; + data.stats.ConfigureMassAndSize(); + } + else + { + if (playSound) + { + SoundManager.Instance.PlayAtPosition(soundPristineShrink, SoundManager.Instance.GetTransform(), base.transform); + } + data.health /= healthMultiplier; + data.maxHealth /= healthMultiplier; + data.stats.sizeMultiplier /= sizeMultiplier; + data.stats.ConfigureMassAndSize(); + } + } +} diff --git a/GameCode/SteamManager.cs b/GameCode/SteamManager.cs new file mode 100644 index 0000000..9f30390 --- /dev/null +++ b/GameCode/SteamManager.cs @@ -0,0 +1,99 @@ +using System; +using System.Text; +using Steamworks; +using UnityEngine; + +[DisallowMultipleComponent] +public class SteamManager : MonoBehaviour +{ + protected static bool s_EverInitialized; + + protected static SteamManager s_instance; + + protected bool m_bInitialized; + + protected SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook; + + protected static SteamManager Instance + { + get + { + if (s_instance == null) + { + return new GameObject("SteamManager").AddComponent<SteamManager>(); + } + return s_instance; + } + } + + public static bool Initialized => Instance.m_bInitialized; + + protected static void SteamAPIDebugTextHook(int nSeverity, StringBuilder pchDebugText) + { + } + + protected virtual void Awake() + { + if (s_instance != null) + { + UnityEngine.Object.Destroy(base.gameObject); + return; + } + s_instance = this; + if (s_EverInitialized) + { + throw new Exception("Tried to Initialize the SteamAPI twice in one session!"); + } + UnityEngine.Object.DontDestroyOnLoad(base.gameObject); + if (!Packsize.Test()) + { + Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this); + } + if (!DllCheck.Test()) + { + Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this); + } + m_bInitialized = SteamAPI.Init(); + if (!m_bInitialized) + { + Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this); + } + else + { + s_EverInitialized = true; + } + } + + protected virtual void OnEnable() + { + if (s_instance == null) + { + s_instance = this; + } + if (m_bInitialized && m_SteamAPIWarningMessageHook == null) + { + m_SteamAPIWarningMessageHook = SteamAPIDebugTextHook; + SteamClient.SetWarningMessageHook(m_SteamAPIWarningMessageHook); + } + } + + protected virtual void OnDestroy() + { + if (!(s_instance != this)) + { + s_instance = null; + if (m_bInitialized) + { + SteamAPI.Shutdown(); + } + } + } + + protected virtual void Update() + { + if (m_bInitialized) + { + SteamAPI.RunCallbacks(); + } + } +} diff --git a/GameCode/StopRecursion.cs b/GameCode/StopRecursion.cs new file mode 100644 index 0000000..e77fbb7 --- /dev/null +++ b/GameCode/StopRecursion.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class StopRecursion : MonoBehaviour +{ +} diff --git a/GameCode/StunHandler.cs b/GameCode/StunHandler.cs new file mode 100644 index 0000000..bb3f93e --- /dev/null +++ b/GameCode/StunHandler.cs @@ -0,0 +1,102 @@ +using Sonigon; +using UnityEngine; + +public class StunHandler : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterStunLoop; + + private bool soundStunIsPlaying; + + [Header("Settings")] + public CodeAnimation codeAnim; + + private Player player; + + private CharacterData data; + + private void Start() + { + player = GetComponent<Player>(); + data = player.data; + } + + private void Update() + { + if (data.stunTime > 0f) + { + data.stunTime -= TimeHandler.deltaTime; + data.sinceGrounded = 0f; + if (!data.isStunned) + { + StartStun(); + } + } + else if (data.isStunned) + { + StopStun(); + } + if (data.isStunned && data.isPlaying && !data.dead) + { + if (!soundStunIsPlaying) + { + soundStunIsPlaying = true; + SoundManager.Instance.Play(soundCharacterStunLoop, base.transform); + } + } + else if (soundStunIsPlaying) + { + soundStunIsPlaying = false; + SoundManager.Instance.Stop(soundCharacterStunLoop, base.transform); + } + } + + private void StartStun() + { + player.data.playerVel.velocity *= 0f; + player.data.playerVel.isKinematic = true; + player.data.input.stunnedInput = true; + codeAnim.PlayIn(); + data.isStunned = true; + } + + public void StopStun() + { + player.data.playerVel.isKinematic = false; + player.data.input.stunnedInput = false; + if (codeAnim.currentState == CodeAnimationInstance.AnimationUse.In) + { + codeAnim.PlayOut(); + } + data.isStunned = false; + data.stunTime = 0f; + } + + private void OnDisable() + { + codeAnim.transform.localScale = Vector3.zero; + soundStunIsPlaying = false; + SoundManager.Instance.Stop(soundCharacterStunLoop, base.transform); + } + + private void OnDestroy() + { + soundStunIsPlaying = false; + SoundManager.Instance.Stop(soundCharacterStunLoop, base.transform); + } + + public void AddStun(float f) + { + if (!data.block.IsBlocking()) + { + if (f > data.stunTime) + { + data.stunTime = f; + } + if (!data.isStunned) + { + StartStun(); + } + } + } +} diff --git a/GameCode/StunPlayer.cs b/GameCode/StunPlayer.cs new file mode 100644 index 0000000..c131626 --- /dev/null +++ b/GameCode/StunPlayer.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class StunPlayer : MonoBehaviour +{ + public enum TargetPlayer + { + OtherPlayer, + Self + } + + public TargetPlayer targetPlayer; + + public float time = 0.5f; + + private Player target; + + public void Go() + { + if (!target) + { + target = GetComponentInParent<Player>(); + if (targetPlayer == TargetPlayer.OtherPlayer) + { + target = PlayerManager.instance.GetOtherPlayer(target); + } + } + target.data.stunHandler.AddStun(time); + } +} diff --git a/GameCode/SuperBasicController.cs b/GameCode/SuperBasicController.cs new file mode 100644 index 0000000..6456afc --- /dev/null +++ b/GameCode/SuperBasicController.cs @@ -0,0 +1,327 @@ +using Photon.Pun; +using Photon.Pun.Simple; +using UnityEngine; + +public class SuperBasicController : NetComponent +{ + public bool is2D; + + [Range(0f, 300f)] + public float turnSpeed = 150f; + + [Range(0f, 4f)] + public float moveSpeed = 4f; + + public bool autoMove = true; + + private Vector3 targRotDelta; + + private Vector3 targPosDelta; + + private float appliedDeltaT; + + private Animator animator; + + private SyncAnimator syncAnimator; + + private SyncTransform syncTransform; + + private SyncCannon syncLauncher; + + private SyncContactScan syncHitscan; + + private bool triggerJump; + + private bool triggerFade; + + private bool triggerTurnLeft; + + private bool triggerUpperBodyRun; + + private bool triggerUpperBodyIdle; + + private bool triggerTeleport; + + private bool freakingOut; + + private bool triggerHitscan; + + private bool triggerProjectile; + + private bool triggerBlend; + + public override void OnAwake() + { + base.OnAwake(); + animator = base.transform.GetNestedComponentInChildren<Animator, NetObject>(includeInactive: true); + syncAnimator = base.transform.GetNestedComponentInChildren<SyncAnimator, NetObject>(includeInactive: true); + syncTransform = GetComponent<SyncTransform>(); + syncLauncher = base.transform.GetNestedComponentInChildren<SyncCannon, NetObject>(includeInactive: true); + syncHitscan = base.transform.GetNestedComponentInChildren<SyncContactScan, NetObject>(includeInactive: true); + } + + private void Update() + { + if (!base.IsMine) + { + return; + } + float t = (Time.time - Time.fixedTime) / Time.fixedDeltaTime; + Interpolate(t); + if (Input.GetKeyDown(KeyCode.Space)) + { + triggerJump = true; + } + if (Input.GetKeyDown(KeyCode.Alpha2)) + { + triggerFade = true; + } + if (Input.GetKeyDown(KeyCode.Alpha1)) + { + triggerTurnLeft = true; + } + if (Input.GetKeyDown(KeyCode.Alpha4)) + { + if (freakingOut) + { + triggerUpperBodyIdle = true; + } + else + { + triggerUpperBodyRun = true; + } + freakingOut = !freakingOut; + } + if (Input.GetKeyDown(KeyCode.F)) + { + triggerProjectile = true; + } + if (Input.GetKeyDown(KeyCode.R)) + { + triggerHitscan = true; + } + if (Input.GetKeyDown(KeyCode.T)) + { + triggerTeleport = true; + } + if (Input.GetKeyDown(KeyCode.B)) + { + triggerBlend = true; + } + } + + private void FixedUpdate() + { + if (!base.IsMine) + { + return; + } + Vector3 move = new Vector3(0f, 0f, 0f); + Vector3 turn = new Vector3(0f, 0f, 0f); + if ((bool)animator && animator.isActiveAndEnabled) + { + if (Input.GetKey(KeyCode.W)) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", 1f); + } + else if (Input.GetKey(KeyCode.S)) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", -0.5f); + } + else + { + animator.SetBool("walking", value: false); + animator.SetFloat("speed", 0f); + } + if (triggerJump) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("jump"); + } + triggerJump = false; + } + else if (triggerTurnLeft) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("turnLeft"); + } + triggerTurnLeft = false; + } + if (triggerFade) + { + if ((bool)syncAnimator) + { + syncAnimator.CrossFadeInFixedTime("Jump", 0.25f); + } + triggerFade = false; + } + if (triggerBlend) + { + animator.SetFloat("blender", Mathf.Abs(Mathf.Sin(Time.time))); + } + else + { + animator.SetFloat("blender", -1f); + } + if (triggerUpperBodyRun) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("upperBodyRun"); + } + triggerUpperBodyRun = false; + } + else if (triggerUpperBodyIdle) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("upperBodyIdle"); + } + triggerUpperBodyIdle = false; + } + } + if (!animator || !animator.applyRootMotion) + { + if (Input.GetKey(KeyCode.W)) + { + move += Vector3.forward; + } + else if (Input.GetKey(KeyCode.S)) + { + move -= Vector3.forward; + } + } + if (Input.GetKey(KeyCode.A)) + { + move -= Vector3.right; + } + if (Input.GetKey(KeyCode.D)) + { + move += Vector3.right; + } + if (Input.GetKey(KeyCode.E)) + { + turn += Vector3.up; + } + if (Input.GetKey(KeyCode.Q)) + { + turn -= Vector3.up; + } + if (Input.touchCount > 0) + { + Touch touch = Input.GetTouch(0); + Vector2 vector = new Vector2(touch.rawPosition.x / (float)Screen.width, touch.rawPosition.y / (float)Screen.height); + if (vector.y > 0.66f) + { + if (vector.x > 0.66f) + { + triggerHitscan = true; + } + else if (vector.x < 0.33f) + { + triggerJump = true; + } + } + else if (vector.y < 0.33f) + { + if (vector.x > 0.66f) + { + move += Vector3.right; + } + else if (vector.x < 0.33f) + { + move -= Vector3.right; + } + else if ((bool)animator) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", -0.5f); + } + } + else if (vector.x > 0.66f) + { + turn += Vector3.up; + } + else if (vector.x < 0.33f) + { + turn -= Vector3.up; + } + else if ((bool)animator) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", 1f); + } + } + if (autoMove && !Application.isFocused) + { + turn += new Vector3(0f, Mathf.Sin(Time.time * 0.5f), 0f); + if ((bool)animator) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", Mathf.Sin(Time.time) * 0.5f); + } + } + Interpolate(1f); + Move(move, turn); + appliedDeltaT = 0f; + if (triggerHitscan) + { + if ((bool)syncHitscan) + { + syncHitscan.QueueTrigger(); + } + triggerHitscan = false; + } + if (triggerProjectile) + { + if ((bool)syncLauncher) + { + syncLauncher.QueueTrigger(); + } + triggerProjectile = false; + } + if (triggerTeleport) + { + if ((bool)syncTransform) + { + syncTransform.FlagTeleport(); + base.transform.localPosition = default(Vector3); + base.transform.localRotation = default(Quaternion); + } + triggerTeleport = false; + } + } + + private void OnAnimatorMove() + { + if (base.IsMine) + { + animator.ApplyBuiltinRootMotion(); + base.transform.rotation = animator.rootRotation; + base.transform.position = animator.rootPosition; + } + } + + private void Move(Vector3 move, Vector3 turn) + { + if (is2D) + { + move = new Vector3(move.x, move.z, 0f); + turn = new Vector3(0f, 0f, turn.y); + } + targRotDelta = turn * turnSpeed * Time.fixedDeltaTime; + targPosDelta = move * moveSpeed * Time.fixedDeltaTime; + } + + private void Interpolate(float t) + { + t -= appliedDeltaT; + appliedDeltaT += t; + base.transform.rotation = base.transform.rotation * Quaternion.Euler(targRotDelta * t); + base.transform.position += base.transform.rotation * (targPosDelta * t); + } +} diff --git a/GameCode/SwordArtMove.cs b/GameCode/SwordArtMove.cs new file mode 100644 index 0000000..b521e51 --- /dev/null +++ b/GameCode/SwordArtMove.cs @@ -0,0 +1,61 @@ +using UnityEngine; + +public class SwordArtMove : MonoBehaviour +{ + private MoveTransform move; + + public LayerMask mask; + + public AnimationCurve heightCurve; + + public AnimationCurve AwayCurve; + + private Vector3 startUp; + + private Vector3 startForward; + + private Vector3 startPos; + + public float multiplier = 1f; + + public float heightMultiplier = 1f; + + public float awayMultiplier = 1f; + + public float speed = 1f; + + private float counter; + + private ParticleSystem[] parts; + + private void Start() + { + parts = GetComponentsInChildren<ParticleSystem>(); + move = GetComponentInParent<MoveTransform>(); + move.enabled = false; + startForward = base.transform.forward; + startUp = Vector3.Cross(base.transform.forward, Vector3.forward); + startPos = base.transform.position; + awayMultiplier *= Mathf.Pow(move.localForce.magnitude / 40f * 2f, 0.45f); + awayMultiplier /= 1f + move.drag * 0.05f; + speed *= Mathf.Pow(awayMultiplier, 0.3f); + } + + private void Update() + { + counter += TimeHandler.deltaTime * speed; + Vector3 vector = startPos + (heightCurve.Evaluate(counter) * heightMultiplier * startUp + AwayCurve.Evaluate(counter) * awayMultiplier * startForward) * multiplier; + RaycastHit2D raycastHit2D = Physics2D.Raycast(startPos, (vector - startPos).normalized, Vector3.Distance(vector, startPos), mask); + if ((bool)raycastHit2D.transform && !raycastHit2D.collider.GetComponent<Damagable>()) + { + vector = raycastHit2D.point + raycastHit2D.normal * 0.1f; + for (int i = 0; i < parts.Length; i++) + { + parts[i].transform.position = (Vector3)raycastHit2D.point + Vector3.forward * 8f; + parts[i].transform.rotation = Quaternion.LookRotation(raycastHit2D.normal); + parts[i].Emit(1); + } + } + base.transform.root.position = vector; + } +} diff --git a/GameCode/TasteOfBlood.cs b/GameCode/TasteOfBlood.cs new file mode 100644 index 0000000..1a7ed41 --- /dev/null +++ b/GameCode/TasteOfBlood.cs @@ -0,0 +1,66 @@ +using System; +using UnityEngine; + +public class TasteOfBlood : MonoBehaviour +{ + public AnimationCurve attackSpeedCurve; + + public float decaySpeed = 1f; + + private float damageValue; + + private CharacterStatModifiers stats; + + private ParticleSystem part; + + private CharacterData data; + + private bool isOn; + + private void Start() + { + part = GetComponentInChildren<ParticleSystem>(); + stats = GetComponentInParent<CharacterStatModifiers>(); + CharacterStatModifiers characterStatModifiers = stats; + characterStatModifiers.DealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(characterStatModifiers.DealtDamageAction, new Action<Vector2, bool>(DealtDamage)); + data = GetComponentInParent<CharacterData>(); + } + + public void DealtDamage(Vector2 damage, bool selfDamage) + { + if (!selfDamage) + { + damageValue += damage.magnitude; + } + damageValue = Mathf.Clamp(damageValue, 0f, 50f); + } + + private void Update() + { + if (!data.isPlaying) + { + damageValue = 0f; + } + if (damageValue > 0f) + { + damageValue -= TimeHandler.deltaTime * decaySpeed; + isOn = true; + } + else + { + isOn = false; + } + if (damageValue > 10f) + { + if (!part.isPlaying) + { + part.Play(); + } + } + else if (part.isPlaying) + { + part.Stop(); + } + stats.tasteOfBloodSpeed = attackSpeedCurve.Evaluate(damageValue); + } +} diff --git a/GameCode/Teleport.cs b/GameCode/Teleport.cs new file mode 100644 index 0000000..614ccdc --- /dev/null +++ b/GameCode/Teleport.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections; +using UnityEngine; + +public class Teleport : MonoBehaviour +{ + public ParticleSystem[] parts; + + public ParticleSystem[] remainParts; + + public float distance = 10f; + + public LayerMask mask; + + private CharacterData data; + + private AttackLevel level; + + private void Start() + { + parts = GetComponentsInChildren<ParticleSystem>(); + data = GetComponentInParent<CharacterData>(); + level = GetComponentInParent<AttackLevel>(); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(Go)); + } + + private void OnDestroy() + { + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(Go)); + } + + public void Go(BlockTrigger.BlockTriggerType triggerType) + { + StartCoroutine(DelayMove(triggerType, base.transform.position)); + } + + private IEnumerator DelayMove(BlockTrigger.BlockTriggerType triggerType, Vector3 beforePos) + { + if (triggerType == BlockTrigger.BlockTriggerType.Empower) + { + yield return new WaitForSeconds(0f); + } + Vector3 position = base.transform.position; + Vector3 position2 = base.transform.position; + int num = 10; + float num2 = distance * (float)level.attackLevel / (float)num; + for (int i = 0; i < num; i++) + { + position += num2 * data.aimDirection; + if (!Physics2D.OverlapCircle(position, 0.5f)) + { + position2 = position; + } + } + for (int j = 0; j < remainParts.Length; j++) + { + remainParts[j].transform.position = base.transform.root.position; + remainParts[j].Play(); + } + GetComponentInParent<PlayerCollision>().IgnoreWallForFrames(2); + if (triggerType == BlockTrigger.BlockTriggerType.Empower) + { + position2 = beforePos; + } + base.transform.root.position = position2; + for (int k = 0; k < parts.Length; k++) + { + parts[k].transform.position = position2; + parts[k].Play(); + } + data.playerVel.velocity *= 0f; + data.sinceGrounded = 0f; + } +} diff --git a/GameCode/TeleportToOpponent.cs b/GameCode/TeleportToOpponent.cs new file mode 100644 index 0000000..193c632 --- /dev/null +++ b/GameCode/TeleportToOpponent.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class TeleportToOpponent : MonoBehaviour +{ + public float time = 0.5f; + + public ParticleSystem from; + + public ParticleSystem to; + + private Player target; + + private void Start() + { + } + + public void Go() + { + if (!target) + { + target = PlayerManager.instance.GetOtherPlayer(GetComponentInParent<Player>()); + } + from.Play(); + base.transform.root.transform.position = target.transform.position + (target.transform.position - base.transform.position).normalized; + to.Play(); + } +} diff --git a/GameCode/TextFlicker.cs b/GameCode/TextFlicker.cs new file mode 100644 index 0000000..e710a43 --- /dev/null +++ b/GameCode/TextFlicker.cs @@ -0,0 +1,35 @@ +using TMPro; +using UnityEngine; + +public class TextFlicker : MonoBehaviour +{ + public string[] strings; + + public float rate = 0.2f; + + private float counter; + + private int currentID; + + private TextMeshProUGUI text; + + private void Start() + { + text = GetComponent<TextMeshProUGUI>(); + } + + private void Update() + { + counter += Time.deltaTime; + if (counter > rate) + { + counter = 0f; + currentID++; + if (currentID >= strings.Length) + { + currentID = 0; + } + text.text = strings[currentID]; + } + } +} diff --git a/GameCode/ThereCanOnlyBeOne.cs b/GameCode/ThereCanOnlyBeOne.cs new file mode 100644 index 0000000..78dd68d --- /dev/null +++ b/GameCode/ThereCanOnlyBeOne.cs @@ -0,0 +1,30 @@ +using UnityEngine; +using UnityEngine.Events; + +public class ThereCanOnlyBeOne : MonoBehaviour +{ + public UnityEvent PokeEvent; + + private void Start() + { + bool flag = false; + ThereCanOnlyBeOne[] componentsInChildren = base.transform.root.GetComponentsInChildren<ThereCanOnlyBeOne>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (!(componentsInChildren[i] == this)) + { + flag = true; + componentsInChildren[i].Poke(); + } + } + if (flag) + { + Object.Destroy(base.gameObject); + } + } + + public void Poke() + { + PokeEvent.Invoke(); + } +} diff --git a/GameCode/Thruster.cs b/GameCode/Thruster.cs new file mode 100644 index 0000000..0c595d1 --- /dev/null +++ b/GameCode/Thruster.cs @@ -0,0 +1,84 @@ +using UnityEngine; + +public class Thruster : MonoBehaviour +{ + public float force; + + public float drag; + + public float pow = 1f; + + public float physicsObjectM = 1f; + + private FollowLocalPos follow; + + private Rigidbody2D rig; + + private Vector2 startForward; + + private NetworkPhysicsObject pushed; + + private Player player; + + private bool checkedForPlayer; + + private void Start() + { + force *= Mathf.Pow(base.transform.localScale.x, pow); + drag *= Mathf.Pow(base.transform.localScale.x, pow); + follow = GetComponent<FollowLocalPos>(); + if ((bool)follow.target) + { + pushed = follow.target.gameObject.GetComponent<NetworkPhysicsObject>(); + } + float num = 1f; + if (!follow.targetPlayer) + { + num = 0.2f; + } + else if ((bool)pushed) + { + num = 0.5f; + } + ParticleSystem.MainModule main = GetComponentInChildren<ParticleSystem>().main; + main.duration *= num; + GetComponent<DelayEvent>().time *= num; + GetComponent<RemoveAfterSeconds>().seconds *= num; + startForward = base.transform.forward; + } + + private void FixedUpdate() + { + if (!follow) + { + return; + } + if ((bool)follow.target) + { + if ((bool)player) + { + if ((bool)player) + { + player.data.healthHandler.TakeForce(startForward * force, ForceMode2D.Force); + } + else + { + rig.AddForce(startForward * force, ForceMode2D.Force); + } + } + else if (!checkedForPlayer) + { + player = follow.target.transform.root.GetComponent<Player>(); + checkedForPlayer = true; + if (!player && !pushed) + { + base.enabled = false; + } + } + } + if ((bool)pushed && pushed.photonView.IsMine) + { + pushed.RPCA_SendForce(base.transform.forward * force * physicsObjectM, pushed.transform.InverseTransformPoint(base.transform.position)); + } + } +} diff --git a/GameCode/TickMover.cs b/GameCode/TickMover.cs new file mode 100644 index 0000000..841ffc4 --- /dev/null +++ b/GameCode/TickMover.cs @@ -0,0 +1,41 @@ +using Photon.Pun.Simple; +using UnityEngine; + +public class TickMover : MonoBehaviour, IOnPostSimulate +{ + private Vector3 rotationPerTick; + + private TextMesh tickText; + + private void Awake() + { + NetMasterCallbacks.RegisterCallbackInterfaces(this); + rotationPerTick = new Vector3(0f, 0f, 360f * (Time.fixedDeltaTime * (float)TickEngineSettings.sendEveryXTick)); + tickText = GetComponentInChildren<TextMesh>(); + if (!tickText) + { + tickText = GetComponentInParent<TextMesh>(); + } + if ((bool)tickText) + { + tickText.text = ""; + } + } + + private void OnDestroy() + { + NetMasterCallbacks.RegisterCallbackInterfaces(this, register: false, delay: true); + } + + public void OnPostSimulate(int frameId, int subFrameId, bool isNetTick) + { + if (isNetTick) + { + base.transform.eulerAngles -= rotationPerTick; + if ((bool)tickText) + { + tickText.text = frameId.ToString(); + } + } + } +} diff --git a/GameCode/TimeHandler.cs b/GameCode/TimeHandler.cs new file mode 100644 index 0000000..f038df5 --- /dev/null +++ b/GameCode/TimeHandler.cs @@ -0,0 +1,96 @@ +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class TimeHandler : MonoBehaviour +{ + public AnimationCurve slowDown; + + public AnimationCurve speedUp; + + public float baseTimeScale = 0.85f; + + public float gameOverTime = 1f; + + public float gameStartTime; + + public float timeStop = 1f; + + public static float timeScale = 1f; + + public static TimeHandler instance; + + public static float deltaTime; + + public static float fixedDeltaTime; + + private void Awake() + { + instance = this; + } + + private void Update() + { + float num = baseTimeScale; + if (gameOverTime < 1f) + { + num *= gameOverTime; + } + if (gameStartTime < 1f) + { + num *= gameStartTime; + } + if (timeStop < 1f) + { + num *= timeStop; + } + if (PhotonNetwork.OfflineMode && EscapeMenuHandler.isEscMenu) + { + num *= 0f; + } + timeScale = num; + deltaTime = Time.deltaTime * timeScale; + fixedDeltaTime = Time.fixedDeltaTime * timeScale; + Time.timeScale = 1f; + } + + public void StartGame() + { + gameStartTime = 1f; + } + + public void DoSpeedUp() + { + StartCoroutine(DoCurve(speedUp)); + } + + public void DoSlowDown() + { + StartCoroutine(DoCurve(slowDown)); + } + + private IEnumerator DoCurve(AnimationCurve curve) + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + gameOverTime = curve.Evaluate(c); + c += Time.unscaledDeltaTime; + yield return null; + } + gameOverTime = curve.Evaluate(t); + } + + public void HitStop() + { + StartCoroutine(DoHitStop()); + } + + private IEnumerator DoHitStop() + { + timeStop = 0f; + yield return new WaitForSeconds(0.3f); + timeStop = 1f; + } +} diff --git a/GameCode/ToggleStats.cs b/GameCode/ToggleStats.cs new file mode 100644 index 0000000..726a307 --- /dev/null +++ b/GameCode/ToggleStats.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +public class ToggleStats : MonoBehaviour +{ + public float movementSpeedMultiplier = 1f; + + public float hpMultiplier = 1f; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + public void TurnOn() + { + data.health *= hpMultiplier; + data.maxHealth *= hpMultiplier; + data.stats.movementSpeed *= movementSpeedMultiplier; + data.stats.ConfigureMassAndSize(); + } + + public void TurnOff() + { + data.health /= hpMultiplier; + data.maxHealth /= hpMultiplier; + data.stats.movementSpeed /= movementSpeedMultiplier; + data.stats.ConfigureMassAndSize(); + } +} diff --git a/GameCode/ToggleUnparented.cs b/GameCode/ToggleUnparented.cs new file mode 100644 index 0000000..bacb60a --- /dev/null +++ b/GameCode/ToggleUnparented.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class ToggleUnparented : MonoBehaviour +{ + private Unparent[] unparents; + + private void Awake() + { + unparents = GetComponentsInChildren<Unparent>(); + } + + private void OnDisable() + { + for (int i = 0; i < unparents.Length; i++) + { + unparents[i].gameObject.SetActive(value: false); + } + GetComponent<Holding>().holdable.gameObject.SetActive(value: false); + } + + private void OnEnable() + { + for (int i = 0; i < unparents.Length; i++) + { + unparents[i].gameObject.SetActive(value: true); + } + GetComponent<Holding>().holdable.gameObject.SetActive(value: false); + } +} diff --git a/GameCode/TracerRound.cs b/GameCode/TracerRound.cs new file mode 100644 index 0000000..201a5f7 --- /dev/null +++ b/GameCode/TracerRound.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +public class TracerRound : MonoBehaviour +{ + public GameObject bullet; + + public GameObject bulletSpawnPos; + + private TracerTarget target; + + private MoveTransform move; + + private bool done; + + private void Start() + { + move = GetComponent<MoveTransform>(); + bullet = Object.Instantiate(bullet, bulletSpawnPos.transform.position, bulletSpawnPos.transform.rotation); + bullet.GetComponent<ProjectileHit>().damage *= base.transform.localScale.x; + GetComponentInParent<SpawnedAttack>().CopySpawnedAttackTo(bullet); + target = bullet.GetComponent<TracerTarget>(); + GetComponentInParent<ProjectileHit>().AddHitActionWithData(Hit); + bullet.GetComponentInParent<ProjectileHit>().AddHitActionWithData(Hit); + } + + public void Hit(HitInfo hit) + { + if ((bool)hit.transform.root.GetComponent<Player>()) + { + base.transform.SetParent(null); + base.gameObject.AddComponent<RemoveAfterSeconds>().seconds = 10f; + base.gameObject.AddComponent<FollowTransform>().target = hit.transform; + } + } + + private void Update() + { + if (target != null) + { + target.SetPos(base.transform.position, Vector3.Cross(Vector3.forward, base.transform.forward), move); + } + if (bullet == null && !done) + { + done = true; + GetComponentInChildren<ParticleSystem>().Stop(); + } + } +} diff --git a/GameCode/TracerTarget.cs b/GameCode/TracerTarget.cs new file mode 100644 index 0000000..19b6b67 --- /dev/null +++ b/GameCode/TracerTarget.cs @@ -0,0 +1,65 @@ +using UnityEngine; + +public class TracerTarget : MonoBehaviour +{ + private MoveTransform move; + + public bool hasPos; + + public float drag; + + public float spring; + + public AnimationCurve curve; + + public float cosScale = 1f; + + public float cosAmount; + + private float random; + + private float c; + + private bool done; + + private Vector3 tPos; + + private Vector3 upDir; + + private MoveTransform mTrans; + + private void Start() + { + move = GetComponent<MoveTransform>(); + random = Random.Range(0f, 1000f); + SetPos(base.transform.forward * 100f, base.transform.up, null); + } + + private void Update() + { + float num = 1f; + if ((bool)mTrans) + { + num += mTrans.velocity.magnitude * 0.1f; + } + if ((bool)mTrans && !done) + { + tPos += base.transform.forward + base.transform.forward * 10f; + } + c += TimeHandler.deltaTime; + if (hasPos) + { + move.velocity += cosAmount * Mathf.Cos((Time.time + random) * cosScale) * upDir * CappedDeltaTime.time / num; + move.velocity += (tPos - base.transform.position).normalized * spring * CappedDeltaTime.time * curve.Evaluate(c) * num; + move.velocity -= move.velocity * CappedDeltaTime.time * drag * curve.Evaluate(c); + } + } + + public void SetPos(Vector3 targetPos, Vector3 up, MoveTransform move) + { + mTrans = move; + hasPos = true; + tPos = targetPos; + upDir = up; + } +} diff --git a/GameCode/TrickShot.cs b/GameCode/TrickShot.cs new file mode 100644 index 0000000..cdb0b0e --- /dev/null +++ b/GameCode/TrickShot.cs @@ -0,0 +1,87 @@ +using Sonigon; +using UnityEngine; + +public class TrickShot : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundGrowExplosion; + + public SoundEvent soundGrowWail; + + private bool soundGrowExplosionPlayed; + + private bool soundGrowWailPlayed; + + private SoundParameterIntensity soundIntensity = new SoundParameterIntensity(0f); + + [Header("Settings")] + public float muiltiplier = 1f; + + public float removeAt = 30f; + + private ProjectileHit projectileHit; + + private MoveTransform move; + + private ScaleTrailFromDamage trail; + + private float lastDistanceTravelled; + + private void Awake() + { + trail = base.transform.root.GetComponentInChildren<ScaleTrailFromDamage>(); + } + + private void Start() + { + projectileHit = GetComponentInParent<ProjectileHit>(); + move = GetComponentInParent<MoveTransform>(); + if (projectileHit != null) + { + if (soundGrowExplosion != null) + { + projectileHit.AddHitActionWithData(SoundPlayGrowExplosion); + } + if (soundGrowWail != null) + { + soundGrowWailPlayed = true; + SoundManager.Instance.Play(soundGrowWail, projectileHit.ownPlayer.transform); + } + } + } + + public void SoundPlayGrowExplosion(HitInfo hit) + { + if (!soundGrowExplosionPlayed) + { + soundGrowExplosionPlayed = true; + if (soundGrowExplosion != null) + { + SoundManager.Instance.PlayAtPosition(soundGrowExplosion, projectileHit.ownPlayer.transform, hit.point, soundIntensity); + } + if (soundGrowWailPlayed) + { + SoundManager.Instance.Stop(soundGrowWail, projectileHit.ownPlayer.transform); + } + } + } + + private void Update() + { + if (move.distanceTravelled > removeAt) + { + Object.Destroy(this); + return; + } + soundIntensity.intensity = move.distanceTravelled / removeAt; + float num = move.distanceTravelled - lastDistanceTravelled; + lastDistanceTravelled = move.distanceTravelled; + float num2 = 1f + num * TimeHandler.deltaTime * base.transform.localScale.x * muiltiplier; + projectileHit.damage *= num2; + projectileHit.shake *= num2; + if ((bool)trail) + { + trail.Rescale(); + } + } +} diff --git a/GameCode/TwitchAudienceVisualizer.cs b/GameCode/TwitchAudienceVisualizer.cs new file mode 100644 index 0000000..db00690 --- /dev/null +++ b/GameCode/TwitchAudienceVisualizer.cs @@ -0,0 +1,147 @@ +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +public class TwitchAudienceVisualizer : MonoBehaviour +{ + private const int MAXIMUM_MSG_PER_PLAYER_IN_AUDIENCE = 100; + + private const int MAXIMUM_MSG_PER_SECOND = 10; + + private float m_RecieveRate; + + private float m_LastRecievedTime; + + public float countDownSpeed = 2f; + + public float totalAmountOfTime = 30f; + + [SerializeField] + private GameObject m_TwitchChatObject; + + public ProceduralImage border; + + public TextMeshProUGUI audioenceText; + + private Screenshaker shake; + + private bool m_IsAudition; + + private bool m_IsReadyToSpawnChatObjects; + + private ListMenuPage m_Page; + + public static TwitchAudienceVisualizer instance; + + private Dictionary<string, int> m_MsgsPerTwitchUser = new Dictionary<string, int>(); + + private int currentViewerScore; + + private void Awake() + { + instance = this; + m_RecieveRate = 0.1f; + } + + private void Start() + { + m_Page = GetComponentInParent<ListMenuPage>(); + shake = GetComponentInChildren<Screenshaker>(); + TwitchUIHandler.Instance.AddMsgAction(Chat); + StartAudition(); + } + + public void Chat(string msg, string from) + { + if (!m_IsAudition) + { + return; + } + if (!m_MsgsPerTwitchUser.ContainsKey(from)) + { + m_MsgsPerTwitchUser.Add(from, 0); + } + if (m_MsgsPerTwitchUser[from] >= 100) + { + return; + } + m_MsgsPerTwitchUser[from]++; + if (Time.unscaledTime >= m_LastRecievedTime + m_RecieveRate) + { + m_LastRecievedTime = Time.unscaledTime; + if (m_IsReadyToSpawnChatObjects) + { + SpawnChatObject(msg, from); + } + } + currentViewerScore += 100; + shake.OnUIGameFeel(Random.insideUnitCircle.normalized); + } + + private void SpawnChatObject(string msg, string from) + { + Object.Instantiate(m_TwitchChatObject).GetComponentInChildren<TextMeshProUGUI>().text = msg; + } + + private void StartAudition() + { + m_IsAudition = true; + m_MsgsPerTwitchUser = new Dictionary<string, int>(); + StartCoroutine(DoAudition()); + } + + private void Shake(float m = 1f) + { + shake.OnUIGameFeel(Random.insideUnitCircle.normalized * m); + } + + private IEnumerator DoAudition() + { + border.fillAmount = 0f; + audioenceText.text = ""; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(3f); + audioenceText.text = "3"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(3f); + audioenceText.text = "2"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(3f); + audioenceText.text = "1"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(10f); + audioenceText.text = "CHAT"; + yield return new WaitForSecondsRealtime(2f / countDownSpeed); + Shake(10f); + audioenceText.text = "MAKE"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(10f); + audioenceText.text = "SOME"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(10f); + audioenceText.text = "NOISE"; + float t = 0f; + while (t < 1f) + { + t += Time.unscaledDeltaTime; + Shake(3f - t); + yield return null; + } + yield return new WaitForSecondsRealtime(0.5f / countDownSpeed); + m_IsReadyToSpawnChatObjects = true; + float c = totalAmountOfTime; + while (c > 0f) + { + border.fillAmount = c / totalAmountOfTime; + c -= Time.unscaledDeltaTime; + audioenceText.text = currentViewerScore + "\n<size=50>AUDIENCE RATING</size>"; + yield return null; + } + m_IsAudition = false; + m_IsReadyToSpawnChatObjects = false; + m_Page.Close(); + NetworkConnectionHandler.instance.TwitchJoin(currentViewerScore); + } +} diff --git a/GameCode/TwitchChatMessage.cs b/GameCode/TwitchChatMessage.cs new file mode 100644 index 0000000..e82fb14 --- /dev/null +++ b/GameCode/TwitchChatMessage.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class TwitchChatMessage : MonoBehaviour +{ + private void Start() + { + base.transform.SetParent(TwitchAudienceVisualizer.instance.transform); + base.transform.localScale = Vector3.one; + GetComponent<RectTransform>().anchoredPosition = new Vector2(Random.Range(-850, 850), Random.Range(-475, 475)); + } +} diff --git a/GameCode/TwitchIrc.cs b/GameCode/TwitchIrc.cs new file mode 100644 index 0000000..8c062c0 --- /dev/null +++ b/GameCode/TwitchIrc.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections; +using System.IO; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using Irc; +using UnityEngine; + +public class TwitchIrc : MonoBehaviour +{ + public UserJoined OnUserJoined; + + public UserLeft OnUserLeft; + + public ChannelMessage OnChannelMessage; + + public ServerMessage OnServerMessage; + + public Connected OnConnected; + + public ExceptionThrown OnExceptionThrown; + + private const string ServerName = "irc.twitch.tv"; + + private const int ServerPort = 6667; + + public static TwitchIrc Instance; + + public bool ConnectOnAwake; + + public string Username; + + public string OauthToken; + + public string Channel; + + private TcpClient irc; + + private NetworkStream stream; + + private string inputLine; + + private StreamReader reader; + + private StreamWriter writer; + + public void Connect() + { + if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(OauthToken)) + { + return; + } + try + { + irc = new TcpClient("irc.twitch.tv", 6667); + stream = irc.GetStream(); + reader = new StreamReader(stream); + writer = new StreamWriter(stream); + Send("USER " + Username + "tmi twitch :" + Username); + Send("PASS " + OauthToken); + Send("NICK " + Username); + StartCoroutine("Listen"); + } + catch (Exception exeption) + { + if (OnExceptionThrown != null) + { + OnExceptionThrown(exeption); + } + } + } + + public void Disconnect() + { + irc = null; + StopCoroutine("Listen"); + if (stream != null) + { + stream.Dispose(); + } + if (writer != null) + { + writer.Dispose(); + } + if (reader != null) + { + reader.Dispose(); + } + } + + public void JoinChannel() + { + if (!string.IsNullOrEmpty(Channel)) + { + if (Channel[0] != '#') + { + Channel = "#" + Channel; + } + if (irc != null && irc.Connected) + { + Send("JOIN " + Channel); + } + } + } + + public void LeaveChannel() + { + Send("PART " + Channel); + } + + public void Message(string message) + { + Send("PRIVMSG " + Channel + " :" + message); + } + + private IEnumerator Listen() + { + while (true) + { + if (stream.DataAvailable && (inputLine = reader.ReadLine()) != null) + { + ParseData(inputLine); + } + yield return null; + } + } + + private void ParseData(string data) + { + string[] array = data.Split(' '); + if (data.Length > 4 && data.Substring(0, 4) == "PING") + { + Send("PONG " + array[1]); + return; + } + switch (array[1]) + { + case "001": + Send("MODE " + Username + " +B"); + OnConnected(); + break; + case "JOIN": + if (Instance.OnUserJoined != null) + { + Instance.OnUserJoined(new UserJoinedEventArgs(array[2], array[0].Substring(1, array[0].IndexOf("!") - 1))); + } + break; + case "PRIVMSG": + if (array[2].ToLower() != Username.ToLower() && OnChannelMessage != null) + { + OnChannelMessage(new ChannelMessageEventArgs(array[2], array[0].Substring(1, array[0].IndexOf('!') - 1), JoinArray(array, 3))); + } + break; + case "PART": + case "QUIT": + if (OnUserLeft != null) + { + OnUserLeft(new UserLeftEventArgs(array[2], array[0].Substring(1, data.IndexOf("!") - 1))); + } + break; + default: + if (array.Length > 3 && OnServerMessage != null) + { + OnServerMessage(JoinArray(array, 3)); + } + break; + } + } + + private string StripMessage(string message) + { + foreach (Match item in new Regex("\u0003(?:\\d{1,2}(?:,\\d{1,2})?)?").Matches(message)) + { + message = message.Replace(item.Value, ""); + } + if (message == "") + { + return ""; + } + if (message.Substring(0, 1) == ":" && message.Length > 2) + { + return message.Substring(1, message.Length - 1); + } + return message; + } + + private string JoinArray(string[] strArray, int startIndex) + { + return StripMessage(string.Join(" ", strArray, startIndex, strArray.Length - startIndex)); + } + + private void Send(string message) + { + writer.WriteLine(message); + writer.Flush(); + } + + private void OnConnectedToServer() + { + JoinChannel(); + } + + private void Awake() + { + Instance = this; + OnConnected = (Connected)Delegate.Combine(OnConnected, new Connected(OnConnectedToServer)); + if (ConnectOnAwake) + { + Connect(); + } + } + + private void OnDisable() + { + Disconnect(); + } +} diff --git a/GameCode/TwitchIrcExample.cs b/GameCode/TwitchIrcExample.cs new file mode 100644 index 0000000..dc08227 --- /dev/null +++ b/GameCode/TwitchIrcExample.cs @@ -0,0 +1,88 @@ +using System; +using Irc; +using UnityEngine; +using UnityEngine.UI; + +public class TwitchIrcExample : MonoBehaviour +{ + public InputField UsernameText; + + public InputField TokenText; + + public InputField ChannelText; + + public Text ChatText; + + public InputField MessageText; + + private void Start() + { + TwitchIrc instance = TwitchIrc.Instance; + instance.OnChannelMessage = (ChannelMessage)Delegate.Combine(instance.OnChannelMessage, new ChannelMessage(OnChannelMessage)); + TwitchIrc instance2 = TwitchIrc.Instance; + instance2.OnUserLeft = (UserLeft)Delegate.Combine(instance2.OnUserLeft, new UserLeft(OnUserLeft)); + TwitchIrc instance3 = TwitchIrc.Instance; + instance3.OnUserJoined = (UserJoined)Delegate.Combine(instance3.OnUserJoined, new UserJoined(OnUserJoined)); + TwitchIrc instance4 = TwitchIrc.Instance; + instance4.OnServerMessage = (ServerMessage)Delegate.Combine(instance4.OnServerMessage, new ServerMessage(OnServerMessage)); + TwitchIrc instance5 = TwitchIrc.Instance; + instance5.OnExceptionThrown = (ExceptionThrown)Delegate.Combine(instance5.OnExceptionThrown, new ExceptionThrown(OnExceptionThrown)); + } + + public void Connect() + { + TwitchIrc.Instance.Username = UsernameText.text; + TwitchIrc.Instance.OauthToken = TokenText.text; + TwitchIrc.Instance.Channel = ChannelText.text; + TwitchIrc.Instance.Connect(); + } + + public void MessageSend() + { + if (!string.IsNullOrEmpty(MessageText.text)) + { + TwitchIrc.Instance.Message(MessageText.text); + Text chatText = ChatText; + chatText.text = chatText.text + "<b>" + TwitchIrc.Instance.Username + "</b>: " + MessageText.text + "\n"; + MessageText.text = ""; + } + } + + public void GoUrl(string url) + { + Application.OpenURL(url); + } + + private void OnServerMessage(string message) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>SERVER:</b> " + message + "\n"; + Debug.Log(message); + } + + private void OnChannelMessage(ChannelMessageEventArgs channelMessageArgs) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>" + channelMessageArgs.From + ":</b> " + channelMessageArgs.Message + "\n"; + Debug.Log("MESSAGE: " + channelMessageArgs.From + ": " + channelMessageArgs.Message); + } + + private void OnUserJoined(UserJoinedEventArgs userJoinedArgs) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>USER JOINED:</b> " + userJoinedArgs.User + "\n"; + Debug.Log("USER JOINED: " + userJoinedArgs.User); + } + + private void OnUserLeft(UserLeftEventArgs userLeftArgs) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>USER JOINED:</b> " + userLeftArgs.User + "\n"; + Debug.Log("USER JOINED: " + userLeftArgs.User); + } + + private void OnExceptionThrown(Exception exeption) + { + Debug.Log(exeption); + } +} diff --git a/GameCode/TwitchUIHandler.cs b/GameCode/TwitchUIHandler.cs new file mode 100644 index 0000000..c69fc7a --- /dev/null +++ b/GameCode/TwitchUIHandler.cs @@ -0,0 +1,154 @@ +using System; +using Irc; +using Steamworks; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class TwitchUIHandler : MonoBehaviour +{ + private const string TWITCH_OAUTH_PLAYERPREF_KEY = "TwitchOauth"; + + private const string TWITCH_NAME_PLAYERPREF_KEY = "TwitchName"; + + [SerializeField] + private TMP_InputField m_UserNameText; + + [SerializeField] + private TMP_InputField m_OauthText; + + [SerializeField] + private Button m_GetOAuthButton; + + [SerializeField] + private ListMenuPage m_TwitchBar; + + private Action<string, string> m_OnMsgAction; + + private bool m_Connected; + + public static string OAUTH_KEY + { + get + { + return PlayerPrefs.GetString("TwitchOauth" + SteamUser.GetSteamID().ToString(), string.Empty); + } + private set + { + PlayerPrefs.SetString("TwitchOauth" + SteamUser.GetSteamID().ToString(), value); + } + } + + public static string TWITCH_NAME_KEY + { + get + { + return PlayerPrefs.GetString("TwitchName" + SteamUser.GetSteamID().ToString(), string.Empty); + } + private set + { + PlayerPrefs.SetString("TwitchName" + SteamUser.GetSteamID().ToString(), value); + } + } + + public static TwitchUIHandler Instance { get; private set; } + + private void Awake() + { + Instance = this; + InitListeners(); + } + + private void Start() + { + TwitchIrc instance = TwitchIrc.Instance; + instance.OnChannelMessage = (ChannelMessage)Delegate.Combine(instance.OnChannelMessage, new ChannelMessage(OnChannelMessage)); + TwitchIrc instance2 = TwitchIrc.Instance; + instance2.OnUserLeft = (UserLeft)Delegate.Combine(instance2.OnUserLeft, new UserLeft(OnUserLeft)); + TwitchIrc instance3 = TwitchIrc.Instance; + instance3.OnUserJoined = (UserJoined)Delegate.Combine(instance3.OnUserJoined, new UserJoined(OnUserJoined)); + TwitchIrc instance4 = TwitchIrc.Instance; + instance4.OnServerMessage = (ServerMessage)Delegate.Combine(instance4.OnServerMessage, new ServerMessage(OnServerMessage)); + TwitchIrc instance5 = TwitchIrc.Instance; + instance5.OnExceptionThrown = (ExceptionThrown)Delegate.Combine(instance5.OnExceptionThrown, new ExceptionThrown(OnExceptionThrown)); + if (!string.IsNullOrEmpty(OAUTH_KEY)) + { + m_OauthText.text = OAUTH_KEY; + } + if (!string.IsNullOrEmpty(TWITCH_NAME_KEY)) + { + m_UserNameText.text = TWITCH_NAME_KEY; + } + } + + private void InitListeners() + { + m_GetOAuthButton.onClick.AddListener(GetOauth); + } + + public void AddMsgAction(Action<string, string> a) + { + m_OnMsgAction = (Action<string, string>)Delegate.Combine(m_OnMsgAction, a); + } + + public void OnContinueClick() + { + OAUTH_KEY = m_OauthText.text; + TWITCH_NAME_KEY = m_UserNameText.text.ToLower(); + TwitchIrc.Instance.Username = TWITCH_NAME_KEY; + TwitchIrc.Instance.OauthToken = OAUTH_KEY; + TwitchIrc.Instance.Channel = TWITCH_NAME_KEY; + TwitchIrc.Instance.Connect(); + } + + private void GetOauth() + { + Application.OpenURL("http://twitchapps.com/tmi/"); + } + + public void MessageSend() + { + } + + public void GoUrl(string url) + { + Application.OpenURL(url); + } + + private void OnServerMessage(string message) + { + Debug.Log(message); + } + + private void OnChannelMessage(ChannelMessageEventArgs channelMessageArgs) + { + m_OnMsgAction?.Invoke(channelMessageArgs.Message, channelMessageArgs.From); + } + + private void OnUserJoined(UserJoinedEventArgs userJoinedArgs) + { + if (userJoinedArgs.User.ToUpper() == TwitchIrc.Instance.Username.ToUpper()) + { + Debug.Log("LOCAL USER JOINED!"); + ConnectedToTwitch(); + } + } + + private void ConnectedToTwitch() + { + if (!m_Connected) + { + m_Connected = true; + m_TwitchBar.Open(); + } + } + + private void OnUserLeft(UserLeftEventArgs userLeftArgs) + { + } + + private void OnExceptionThrown(Exception exeption) + { + Debug.Log(exeption); + } +} diff --git a/GameCode/UIHandler.cs b/GameCode/UIHandler.cs new file mode 100644 index 0000000..72d0b63 --- /dev/null +++ b/GameCode/UIHandler.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections; +using Sonigon; +using TMPro; +using UnityEngine; + +public class UIHandler : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundTextAppear; + + public SoundEvent soundTextDisappear; + + public static UIHandler instance; + + [Header("Settings")] + public TextMeshProUGUI gameOverText; + + public GeneralParticleSystem gameOverTextPart; + + public GeneralParticleSystem roundBackgroundPart; + + public GeneralParticleSystem roundTextPart; + + public CodeAnimation roundCounterAnim; + + public RoundCounter roundCounter; + + public RoundCounter roundCounterSmall; + + public CodeAnimation roundCounterAnimSmall; + + public GameObject pickerObject; + + public GeneralParticleSystem pickerPart; + + public GeneralParticleSystem joinGamePart; + + public TextMeshProUGUI jointGameText; + + public PopUpHandler popUpHandler; + + private void Awake() + { + instance = this; + popUpHandler = base.transform.root.GetComponentInChildren<PopUpHandler>(); + } + + public void ShowJoinGameText(string text, Color color) + { + SoundManager.Instance.Play(soundTextAppear, base.transform); + if (text != "") + { + jointGameText.text = text; + } + if (color != Color.black) + { + joinGamePart.particleSettings.color = color; + } + joinGamePart.loop = true; + joinGamePart.Play(); + } + + internal void SetNumberOfRounds(int roundsToWinGame) + { + roundCounter.SetNumberOfRounds(roundsToWinGame); + roundCounterSmall.SetNumberOfRounds(roundsToWinGame); + } + + public void HideJoinGameText() + { + SoundManager.Instance.Play(soundTextDisappear, base.transform); + joinGamePart.Stop(); + } + + public void DisplayScreenText(Color color, string text, float speed) + { + gameOverTextPart.particleSettings.color = color; + gameOverTextPart.duration = 60f / speed; + gameOverTextPart.Play(); + gameOverText.text = text; + } + + public void DisplayScreenTextLoop(string text) + { + gameOverTextPart.duration = 60f; + gameOverTextPart.loop = true; + gameOverTextPart.Play(); + gameOverText.text = text; + } + + public void DisplayScreenTextLoop(Color color, string text) + { + gameOverTextPart.particleSettings.color = color; + gameOverTextPart.duration = 60f; + gameOverTextPart.loop = true; + gameOverTextPart.Play(); + gameOverText.text = text; + } + + public void StopScreenTextLoop() + { + gameOverTextPart.loop = false; + } + + public void ShowAddPoint(Color color, string winTextBefore, string text, float speed) + { + gameOverTextPart.particleSettings.color = color; + gameOverTextPart.duration = 60f / speed; + gameOverTextPart.Play(); + StartCoroutine(DoShowAddPoint(winTextBefore, text)); + } + + private IEnumerator DoShowAddPoint(string winTextBefore, string text) + { + gameOverText.text = winTextBefore; + yield return new WaitForSecondsRealtime(0.7f); + gameOverText.text = text; + } + + public void ShowRoundOver(int p1Rounds, int p2Rounds) + { + roundCounter.gameObject.SetActive(value: true); + roundBackgroundPart.Play(); + roundTextPart.Play(); + roundCounterAnim.PlayIn(); + roundCounter.UpdateRounds(p1Rounds, p2Rounds); + } + + public void ShowRoundCounterSmall(int p1Rounds, int p2Rounds, int p1Points, int p2Points) + { + roundCounterSmall.gameObject.SetActive(value: true); + roundCounterSmall.UpdateRounds(p1Rounds, p2Rounds); + roundCounterSmall.UpdatePoints(p1Points, p2Points); + if (roundCounterAnimSmall.currentState != 0) + { + roundCounterAnimSmall.PlayIn(); + } + } + + public void HideRoundCounterSmall() + { + roundCounterAnimSmall.PlayOut(); + } + + public void ShowPicker(int pickerID, PickerType pickerType = PickerType.Team) + { + pickerObject.SetActive(value: true); + if (pickerType == PickerType.Team) + { + pickerPart.particleSettings.color = PlayerManager.instance.GetColorFromTeam(pickerID).winText; + } + if (pickerType == PickerType.Player) + { + pickerPart.particleSettings.color = PlayerManager.instance.GetColorFromPlayer(pickerID).winText; + } + pickerPart.loop = true; + pickerPart.Play(); + } + + public void StopShowPicker() + { + StartCoroutine(DoStopShowPicker()); + } + + private IEnumerator DoStopShowPicker() + { + pickerPart.loop = false; + yield return new WaitForSeconds(0.3f); + pickerObject.SetActive(value: false); + } + + internal void DisplayYesNoLoop(Player pickingPlayer, Action<PopUpHandler.YesNo> functionToCall) + { + popUpHandler.StartPicking(pickingPlayer, functionToCall); + } +} diff --git a/GameCode/UniformModifier.cs b/GameCode/UniformModifier.cs new file mode 100644 index 0000000..9278ed7 --- /dev/null +++ b/GameCode/UniformModifier.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Uniform")] +public class UniformModifier : ProceduralImageModifier +{ + [SerializeField] + private float radius; + + public float Radius + { + get + { + return radius; + } + set + { + radius = value; + base._Graphic.SetVerticesDirty(); + } + } + + public override Vector4 CalculateRadius(Rect imageRect) + { + float num = radius; + return new Vector4(num, num, num, num); + } +} diff --git a/GameCode/Unparent.cs b/GameCode/Unparent.cs new file mode 100644 index 0000000..cc69c83 --- /dev/null +++ b/GameCode/Unparent.cs @@ -0,0 +1,44 @@ +using System.Collections; +using UnityEngine; + +public class Unparent : MonoBehaviour +{ + public Transform parent; + + public bool follow; + + public float destroyDelay; + + private bool done; + + private void Start() + { + parent = base.transform.root; + } + + private void LateUpdate() + { + if (!done) + { + if (base.transform.root != null) + { + base.transform.SetParent(null, worldPositionStays: true); + } + if (follow && (bool)parent) + { + base.transform.position = parent.transform.position; + } + if (!parent) + { + StartCoroutine(DelayRemove()); + done = true; + } + } + } + + private IEnumerator DelayRemove() + { + yield return new WaitForSeconds(destroyDelay); + Object.Destroy(base.gameObject); + } +} diff --git a/GameCode/UnparentObject.cs b/GameCode/UnparentObject.cs new file mode 100644 index 0000000..258fafa --- /dev/null +++ b/GameCode/UnparentObject.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class UnparentObject : MonoBehaviour +{ + public void Unparent() + { + base.transform.SetParent(base.transform.root); + } +} diff --git a/GameCode/UnparentOnHit.cs b/GameCode/UnparentOnHit.cs new file mode 100644 index 0000000..50266c7 --- /dev/null +++ b/GameCode/UnparentOnHit.cs @@ -0,0 +1,38 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Events; + +public class UnparentOnHit : MonoBehaviour +{ + public float destroyAfterSeconds = 2f; + + public UnityEvent unparentEvent; + + private bool done; + + private void Start() + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + if ((bool)componentInParent) + { + componentInParent.AddHitAction(Unparent); + } + } + + public void Unparent() + { + if (!done) + { + done = true; + base.transform.SetParent(null, worldPositionStays: true); + StartCoroutine(DelayDestroy()); + unparentEvent.Invoke(); + } + } + + private IEnumerator DelayDestroy() + { + yield return new WaitForSeconds(destroyAfterSeconds); + Object.Destroy(base.gameObject); + } +} diff --git a/GameCode/UserJoined.cs b/GameCode/UserJoined.cs new file mode 100644 index 0000000..8c1335f --- /dev/null +++ b/GameCode/UserJoined.cs @@ -0,0 +1,3 @@ +using Irc; + +public delegate void UserJoined(UserJoinedEventArgs userJoinedArgs); diff --git a/GameCode/UserLeft.cs b/GameCode/UserLeft.cs new file mode 100644 index 0000000..4527020 --- /dev/null +++ b/GameCode/UserLeft.cs @@ -0,0 +1,3 @@ +using Irc; + +public delegate void UserLeft(UserLeftEventArgs userLeftArgs); diff --git a/GameCode/VelocityStretch.cs b/GameCode/VelocityStretch.cs new file mode 100644 index 0000000..2875de5 --- /dev/null +++ b/GameCode/VelocityStretch.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class VelocityStretch : MonoBehaviour +{ + private Rigidbody2D rig; + + public float amount = 1f; + + private void Start() + { + rig = GetComponentInParent<Rigidbody2D>(); + } + + private void Update() + { + base.transform.localScale = Vector3.one + new Vector3(Mathf.Abs(rig.velocity.x), Mathf.Abs(rig.velocity.y), 0f) * amount; + } +} diff --git a/GameCode/WallRayCaster.cs b/GameCode/WallRayCaster.cs new file mode 100644 index 0000000..b7d5c52 --- /dev/null +++ b/GameCode/WallRayCaster.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +public class WallRayCaster : MonoBehaviour +{ + public float rayLength = 0.7f; + + public LayerMask mask; + + private GeneralInput input; + + private CharacterData data; + + private Rigidbody2D rig; + + private void Start() + { + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + rig = GetComponent<Rigidbody2D>(); + } + + private void Update() + { + } + + public void RayCast(Vector3 dir, float offset = 0f) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position + base.transform.up * offset, dir, rayLength * base.transform.localScale.x, mask); + if ((bool)raycastHit2D.transform && !raycastHit2D.collider.GetComponent<DamageBox>() && Vector3.Angle(raycastHit2D.normal, Vector3.up) > 70f && Vector3.Angle(raycastHit2D.normal, Vector3.up) < 110f) + { + data.TouchWall(raycastHit2D.normal, raycastHit2D.point); + } + } +} diff --git a/GameCode/WasDealtDamageEffect.cs b/GameCode/WasDealtDamageEffect.cs new file mode 100644 index 0000000..58d0ea4 --- /dev/null +++ b/GameCode/WasDealtDamageEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class WasDealtDamageEffect : MonoBehaviour +{ + public abstract void WasDealtDamage(Vector2 damage, bool selfDamage); +} diff --git a/GameCode/WasDealtDamageTrigger.cs b/GameCode/WasDealtDamageTrigger.cs new file mode 100644 index 0000000..a8fdcd4 --- /dev/null +++ b/GameCode/WasDealtDamageTrigger.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using UnityEngine.Events; + +public class WasDealtDamageTrigger : WasDealtDamageEffect +{ + public float damageNeeded = 25f; + + public float cd = 0.2f; + + public bool allowSelfDamage; + + private float time; + + private float damageDealt; + + public UnityEvent triggerEvent; + + private void Start() + { + } + + public override void WasDealtDamage(Vector2 damage, bool selfDamage) + { + if (!selfDamage || allowSelfDamage) + { + damageDealt += damage.magnitude; + if (damageDealt > damageNeeded && Time.time > time + cd) + { + time = Time.time; + damageDealt = 0f; + triggerEvent.Invoke(); + } + } + } +} diff --git a/GameCode/Weapon.cs b/GameCode/Weapon.cs new file mode 100644 index 0000000..d7b81f2 --- /dev/null +++ b/GameCode/Weapon.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public abstract class Weapon : MonoBehaviour +{ + public Holdable holdable; + + [HideInInspector] + public float sinceAttack = 10f; + + private void Start() + { + holdable = GetComponent<Holdable>(); + } + + private void Update() + { + } + + public abstract bool Attack(float charge, bool forceAttack = false, float damageM = 1f, float recoilMultiplier = 1f, bool useAmmo = true); +} diff --git a/GameCode/WeaponHandler.cs b/GameCode/WeaponHandler.cs new file mode 100644 index 0000000..35be82f --- /dev/null +++ b/GameCode/WeaponHandler.cs @@ -0,0 +1,173 @@ +using System.Collections; +using Sonigon; +using UnityEngine; + +public class WeaponHandler : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterCantShoot; + + private bool soundFireHold; + + [Header("Settings")] + public Gun gun; + + private Holding holding; + + private GeneralInput input; + + private CharacterData data; + + private float heatSinceAttack; + + private float heat; + + public float heatPerBullet = 0.1f; + + public float secondsBeforeStartToCool = 0.1f; + + public float coolPerSecond = 0.2f; + + public float overHeatTime = 1f; + + public float resetSpeed = 2f; + + public bool isOverHeated; + + private bool hasBeenHeated; + + public SpriteRenderer heatRenderer; + + private Transform overHeatPivot; + + public Color overHeatColor; + + private Color baseHeatColor; + + internal void DoReload() + { + gun.GetComponentInChildren<GunAmmo>().ReloadAmmo(); + } + + private void Awake() + { + holding = GetComponent<Holding>(); + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + } + + private void Start() + { + overHeatPivot = heatRenderer.transform.parent; + baseHeatColor = heatRenderer.color; + } + + private void Update() + { + if (!gun.holdable.holder && (bool)data) + { + gun.holdable.holder = data; + } + if (data.playerVel.simulated) + { + gun.attackSpeedMultiplier = data.stats.attackSpeedMultiplier; + heatSinceAttack += TimeHandler.deltaTime; + Attack(); + OverHeat(); + } + } + + private void Attack() + { + if (!gun || !gun.IsReady()) + { + return; + } + if (input.shootIsPressed) + { + if (!soundFireHold) + { + soundFireHold = true; + if (gun.isReloading || data.isSilenced) + { + SoundManager.Instance.Play(soundCharacterCantShoot, base.transform); + } + } + } + else + { + soundFireHold = false; + } + if (gun.bursts == 0 && (!soundFireHold || gun.isReloading || data.isSilenced)) + { + gun.soundGun.StopAutoPlayTail(); + } + if ((!input.shootWasPressed || gun.useCharge) && (!input.shootWasReleased || !gun.useCharge) && (!(gun.attackSpeed / data.stats.attackSpeedMultiplier < 0.3f) || !input.shootIsPressed || gun.useCharge || gun.dontAllowAutoFire)) + { + return; + } + if (isOverHeated) + { + heatRenderer.GetComponent<CodeAnimation>().PlayBoop(); + gun.sinceAttack = 0f; + return; + } + gun.Attack(0f); + if (heat >= 1f) + { + StartCoroutine(DoOverHeat()); + isOverHeated = true; + } + heatSinceAttack = 0f; + } + + internal void NewGun() + { + gun.ResetStats(); + gun.soundGun.ClearSoundModifiers(); + } + + private void OverHeat() + { + if (!isOverHeated) + { + if (heatSinceAttack > secondsBeforeStartToCool) + { + heat -= TimeHandler.deltaTime * coolPerSecond; + } + SetOverHeatColor(); + } + } + + private IEnumerator DoOverHeat() + { + SetOverHeatColor(); + yield return new WaitForSeconds(overHeatTime); + while (heat > 0f) + { + heat -= resetSpeed * TimeHandler.deltaTime; + SetOverHeatColor(); + yield return null; + } + isOverHeated = false; + } + + private void SetOverHeatColor() + { + heat = Mathf.Clamp(heat, 0f, 1f); + heatRenderer.color = Color.Lerp(baseHeatColor, overHeatColor, heat); + if (heat > 0.25f || hasBeenHeated) + { + hasBeenHeated = true; + overHeatPivot.transform.localScale = new Vector3(heat, 1f, 1f); + } + else + { + overHeatPivot.transform.localScale = new Vector3(0f, 1f, 1f); + } + if (heat == 0f) + { + hasBeenHeated = false; + } + } +} diff --git a/GameCode/ZapEffect.cs b/GameCode/ZapEffect.cs new file mode 100644 index 0000000..9215e60 --- /dev/null +++ b/GameCode/ZapEffect.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class ZapEffect : MonoBehaviour +{ + public float damage; + + public float range = 1f; + + private void Start() + { + damage *= base.transform.localScale.x; + range *= (1f + base.transform.localScale.x) * 0.5f; + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true); + if ((bool)closestPlayer && Vector3.Distance(base.transform.position, closestPlayer.transform.position) < range) + { + closestPlayer.data.healthHandler.TakeDamage(damage * (closestPlayer.transform.position - base.transform.position).normalized, base.transform.position, null, PlayerManager.instance.GetOtherPlayer(closestPlayer)); + GetComponentInChildren<LineEffect>(includeInactive: true).Play(base.transform, closestPlayer.transform, 2f); + } + } +} diff --git a/GameCode/Zip.cs b/GameCode/Zip.cs new file mode 100644 index 0000000..1f2c02c --- /dev/null +++ b/GameCode/Zip.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class Zip : MonoBehaviour +{ + public float multiplier = 1f; + + public float turn = 0.2f; + + private float count; + + private int up = 1; + + private void Start() + { + } + + private void Update() + { + count += TimeHandler.deltaTime; + if (count > turn) + { + count = 0f; + up *= -1; + } + base.transform.root.position += base.transform.up * multiplier * up * Time.smoothDeltaTime; + } +} diff --git a/GameCode/Zop.cs b/GameCode/Zop.cs new file mode 100644 index 0000000..b167832 --- /dev/null +++ b/GameCode/Zop.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class Zop : MonoBehaviour +{ + public float turn = 0.2f; + + private float count; + + private int sinceSwitch = 1; + + private bool up; + + private MoveTransform move; + + public bool randomZop; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + if (base.transform.forward.x < 0f) + { + up = true; + } + } + + private void Update() + { + count += TimeHandler.deltaTime; + if (!(count > turn)) + { + return; + } + if (up) + { + move.velocity = move.velocity.magnitude * Vector3.Cross(base.transform.forward, Vector3.forward); + } + else + { + move.velocity = move.velocity.magnitude * -Vector3.Cross(base.transform.forward, Vector3.forward); + } + count = 0f; + if (!randomZop || !(Random.value > 0.8f)) + { + sinceSwitch++; + if (sinceSwitch == 2) + { + up = !up; + sinceSwitch = 0; + } + } + } +} diff --git a/ROUNDS/.vs/ProjectEvaluation/rounds.metadata.v5.2 b/ROUNDS/.vs/ProjectEvaluation/rounds.metadata.v5.2 Binary files differnew file mode 100644 index 0000000..a401b05 --- /dev/null +++ b/ROUNDS/.vs/ProjectEvaluation/rounds.metadata.v5.2 diff --git a/ROUNDS/.vs/ProjectEvaluation/rounds.projects.v5.2 b/ROUNDS/.vs/ProjectEvaluation/rounds.projects.v5.2 Binary files differnew file mode 100644 index 0000000..49baff2 --- /dev/null +++ b/ROUNDS/.vs/ProjectEvaluation/rounds.projects.v5.2 diff --git a/ROUNDS/.vs/ROUNDS/DesignTimeBuild/.dtbcache.v2 b/ROUNDS/.vs/ROUNDS/DesignTimeBuild/.dtbcache.v2 Binary files differnew file mode 100644 index 0000000..6adddea --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/DesignTimeBuild/.dtbcache.v2 diff --git a/ROUNDS/.vs/ROUNDS/FileContentIndex/0ab1bff2-041a-4d95-ac3d-bb1664d9e3dd.vsidx b/ROUNDS/.vs/ROUNDS/FileContentIndex/0ab1bff2-041a-4d95-ac3d-bb1664d9e3dd.vsidx Binary files differnew file mode 100644 index 0000000..866c979 --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/FileContentIndex/0ab1bff2-041a-4d95-ac3d-bb1664d9e3dd.vsidx diff --git a/ROUNDS/.vs/ROUNDS/FileContentIndex/137f2f53-0b71-4a63-9ade-cfe5b28588f0.vsidx b/ROUNDS/.vs/ROUNDS/FileContentIndex/137f2f53-0b71-4a63-9ade-cfe5b28588f0.vsidx Binary files differnew file mode 100644 index 0000000..b724439 --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/FileContentIndex/137f2f53-0b71-4a63-9ade-cfe5b28588f0.vsidx diff --git a/ROUNDS/.vs/ROUNDS/FileContentIndex/5fe23c0d-3068-40a6-b6bf-0cac71fd5f2a.vsidx b/ROUNDS/.vs/ROUNDS/FileContentIndex/5fe23c0d-3068-40a6-b6bf-0cac71fd5f2a.vsidx Binary files differnew file mode 100644 index 0000000..b0b9cf7 --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/FileContentIndex/5fe23c0d-3068-40a6-b6bf-0cac71fd5f2a.vsidx diff --git a/ROUNDS/.vs/ROUNDS/FileContentIndex/d1c173dd-2134-446a-a456-1fd2c7db044c.vsidx b/ROUNDS/.vs/ROUNDS/FileContentIndex/d1c173dd-2134-446a-a456-1fd2c7db044c.vsidx Binary files differnew file mode 100644 index 0000000..3753c3a --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/FileContentIndex/d1c173dd-2134-446a-a456-1fd2c7db044c.vsidx diff --git a/ROUNDS/.vs/ROUNDS/FileContentIndex/read.lock b/ROUNDS/.vs/ROUNDS/FileContentIndex/read.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/FileContentIndex/read.lock diff --git a/ROUNDS/.vs/ROUNDS/v17/.futdcache.v2 b/ROUNDS/.vs/ROUNDS/v17/.futdcache.v2 Binary files differnew file mode 100644 index 0000000..a15e647 --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/v17/.futdcache.v2 diff --git a/ROUNDS/.vs/ROUNDS/v17/.suo b/ROUNDS/.vs/ROUNDS/v17/.suo Binary files differnew file mode 100644 index 0000000..32c628f --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/v17/.suo diff --git a/ROUNDS/.vs/ROUNDS/v17/fileList.bin b/ROUNDS/.vs/ROUNDS/v17/fileList.bin Binary files differnew file mode 100644 index 0000000..635a39d --- /dev/null +++ b/ROUNDS/.vs/ROUNDS/v17/fileList.bin diff --git a/ROUNDS/AbyssalCountdown.cs b/ROUNDS/AbyssalCountdown.cs new file mode 100644 index 0000000..062e920 --- /dev/null +++ b/ROUNDS/AbyssalCountdown.cs @@ -0,0 +1,189 @@ +using System; +using Sonigon; +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +public class AbyssalCountdown : MonoBehaviour +{ + public SoundEvent soundAbyssalChargeLoop; + + private bool soundChargeIsPlaying; + + private float soundCounterLast; + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + [Range(0f, 1f)] + public float counter; + + public float timeToFill = 10f; + + public float timeToEmpty = 3f; + + public float duration; + + public float hpMultiplier = 2f; + + public ProceduralImage outerRing; + + public ProceduralImage fill; + + public Transform rotator; + + public Transform still; + + private CharacterData data; + + public GameObject[] abyssalObjects; + + private float remainingDuration; + + private bool isAbyssalForm; + + private float startCounter; + + private void Start() + { + soundCounterLast = counter; + data = GetComponentInParent<CharacterData>(); + HealthHandler healthHandler = data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(ResetStuff)); + GetComponentInParent<ChildRPC>().childRPCs.Add("Abyssal", RPCA_Activate); + } + + private void OnDestroy() + { + HealthHandler healthHandler = data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(ResetStuff)); + GetComponentInParent<ChildRPC>().childRPCs.Remove("Abyssal"); + SoundStop(); + } + + private void OnDisable() + { + SoundStop(); + } + + private void SoundPlay() + { + if (!soundChargeIsPlaying) + { + soundChargeIsPlaying = true; + SoundManager.Instance.Play(soundAbyssalChargeLoop, base.transform, soundParameterIntensity); + } + } + + private void SoundStop() + { + if (soundChargeIsPlaying) + { + soundChargeIsPlaying = false; + SoundManager.Instance.Stop(soundAbyssalChargeLoop, base.transform); + } + } + + private void ResetStuff() + { + SoundStop(); + remainingDuration = 0f; + counter = 0f; + if (isAbyssalForm) + { + for (int i = 0; i < abyssalObjects.Length; i++) + { + abyssalObjects[i].gameObject.SetActive(value: false); + } + data.maxHealth /= hpMultiplier; + data.health /= hpMultiplier; + data.stats.ConfigureMassAndSize(); + isAbyssalForm = false; + rotator.gameObject.SetActive(value: false); + still.gameObject.SetActive(value: false); + } + SoundStop(); + } + + private void RPCA_Activate() + { + remainingDuration = duration; + } + + private void Update() + { + if (soundCounterLast < counter) + { + SoundPlay(); + } + else + { + SoundStop(); + } + soundCounterLast = counter; + soundParameterIntensity.intensity = counter; + outerRing.fillAmount = counter; + fill.fillAmount = counter; + rotator.transform.localEulerAngles = new Vector3(0f, 0f, 0f - Mathf.Lerp(0f, 360f, counter)); + if (!data.playerVel.simulated) + { + startCounter = 1f; + return; + } + startCounter -= TimeHandler.deltaTime; + if (startCounter > 0f) + { + return; + } + if (remainingDuration > 0f) + { + if (!isAbyssalForm) + { + for (int i = 0; i < abyssalObjects.Length; i++) + { + abyssalObjects[i].gameObject.SetActive(value: true); + } + data.maxHealth *= hpMultiplier; + data.health *= hpMultiplier; + data.stats.ConfigureMassAndSize(); + isAbyssalForm = true; + } + remainingDuration -= TimeHandler.deltaTime; + counter = remainingDuration / duration; + return; + } + if (isAbyssalForm) + { + for (int j = 0; j < abyssalObjects.Length; j++) + { + abyssalObjects[j].gameObject.SetActive(value: false); + } + data.maxHealth /= hpMultiplier; + data.health /= hpMultiplier; + data.stats.ConfigureMassAndSize(); + isAbyssalForm = false; + } + if (data.input.direction == Vector3.zero || data.input.direction == Vector3.down) + { + counter += TimeHandler.deltaTime / timeToFill; + } + else + { + counter -= TimeHandler.deltaTime / timeToEmpty; + } + counter = Mathf.Clamp(counter, -0.1f / timeToFill, 1f); + if (counter >= 1f && data.view.IsMine) + { + remainingDuration = duration; + GetComponentInParent<ChildRPC>().CallFunction("Abyssal"); + } + if (counter <= 0f) + { + rotator.gameObject.SetActive(value: false); + still.gameObject.SetActive(value: false); + } + else + { + rotator.gameObject.SetActive(value: true); + still.gameObject.SetActive(value: true); + } + } +} diff --git a/ROUNDS/Accelerate.cs b/ROUNDS/Accelerate.cs new file mode 100644 index 0000000..9bc086b --- /dev/null +++ b/ROUNDS/Accelerate.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class Accelerate : MonoBehaviour +{ + private MoveTransform move; + + public float startMultiplier = 0.5f; + + public float acceleratonPerSecond = 2f; + + public float pow = 1f; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + move.multiplier *= startMultiplier; + move.multiplier = Mathf.Clamp(move.multiplier, 0.01f, float.PositiveInfinity); + } + + private void Update() + { + move.multiplier = Mathf.Clamp(move.multiplier + TimeHandler.deltaTime * acceleratonPerSecond * Mathf.Pow(move.multiplier, pow), 0f, 25f); + } +} diff --git a/ROUNDS/ActivateSciptWhenCanSeeOtherPlayer.cs b/ROUNDS/ActivateSciptWhenCanSeeOtherPlayer.cs new file mode 100644 index 0000000..5a527fc --- /dev/null +++ b/ROUNDS/ActivateSciptWhenCanSeeOtherPlayer.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class ActivateSciptWhenCanSeeOtherPlayer : MonoBehaviour +{ + public enum Target + { + OtherPlayer, + Closest + } + + public Target target; + + private SpawnedAttack spawned; + + public MonoBehaviour script; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + } + + private void Update() + { + Player player = null; + player = ((target != 0) ? PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true) : PlayerManager.instance.GetOtherPlayer(spawned.spawner)); + if ((bool)player) + { + if (PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee) + { + script.enabled = true; + } + else + { + script.enabled = false; + } + } + else + { + script.enabled = false; + } + } +} diff --git a/ROUNDS/AddShake.cs b/ROUNDS/AddShake.cs new file mode 100644 index 0000000..227a243 --- /dev/null +++ b/ROUNDS/AddShake.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class AddShake : MonoBehaviour +{ + public Vector2 shake; + + public bool auto = true; + + public bool inheritScale; + + public float max = float.PositiveInfinity; + + private void Start() + { + if (auto) + { + DoShake(); + } + } + + public void DoShake() + { + GamefeelManager.GameFeel(shake * Mathf.Clamp(inheritScale ? base.transform.localScale.x : 1f, 0f, max)); + } +} diff --git a/ROUNDS/Aim.cs b/ROUNDS/Aim.cs new file mode 100644 index 0000000..45288a5 --- /dev/null +++ b/ROUNDS/Aim.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class Aim : MonoBehaviour +{ + private GeneralInput input; + + private HoldingObject holdingObject; + + private CharacterData data; + + private Vector3 aimDirection; + + private void Awake() + { + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + holdingObject = GetComponentInChildren<HoldingObject>(); + } + + private void Update() + { + if ((double)input.aimDirection.magnitude > 0.2) + { + aimDirection = input.aimDirection; + } + if (input.direction.magnitude > 0.2f && Optionshandler.leftStickAim && input.aimDirection == Vector3.zero) + { + aimDirection = input.direction; + } + if ((bool)holdingObject) + { + if (aimDirection != Vector3.zero) + { + holdingObject.transform.rotation = Quaternion.LookRotation(aimDirection); + } + data.aimDirection = aimDirection; + } + } +} diff --git a/ROUNDS/AimForPlayer.cs b/ROUNDS/AimForPlayer.cs new file mode 100644 index 0000000..5a9ab24 --- /dev/null +++ b/ROUNDS/AimForPlayer.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +public class AimForPlayer : MonoBehaviour +{ + public enum Target + { + OtherPlayer, + Closest + } + + public float upOffset; + + public Target target; + + private SpawnedAttack spawned; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + } + + private void Update() + { + Player player = null; + player = ((target != 0) ? PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true) : PlayerManager.instance.GetOtherPlayer(spawned.spawner)); + if ((bool)player && PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee) + { + base.transform.rotation = Quaternion.LookRotation(player.transform.position + Vector3.up * Vector3.Distance(player.transform.position, base.transform.position) * 0.1f * upOffset - base.transform.position, Vector3.forward); + } + } +} diff --git a/ROUNDS/AmplifyColor/Quality.cs b/ROUNDS/AmplifyColor/Quality.cs new file mode 100644 index 0000000..c3d3853 --- /dev/null +++ b/ROUNDS/AmplifyColor/Quality.cs @@ -0,0 +1,7 @@ +namespace AmplifyColor; + +public enum Quality +{ + Mobile, + Standard +} diff --git a/ROUNDS/AmplifyColor/RenderLayer.cs b/ROUNDS/AmplifyColor/RenderLayer.cs new file mode 100644 index 0000000..df8ce29 --- /dev/null +++ b/ROUNDS/AmplifyColor/RenderLayer.cs @@ -0,0 +1,18 @@ +using System; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public struct RenderLayer +{ + public LayerMask mask; + + public Color color; + + public RenderLayer(LayerMask mask, Color color) + { + this.mask = mask; + this.color = color; + } +} diff --git a/ROUNDS/AmplifyColor/Tonemapping.cs b/ROUNDS/AmplifyColor/Tonemapping.cs new file mode 100644 index 0000000..9609fa3 --- /dev/null +++ b/ROUNDS/AmplifyColor/Tonemapping.cs @@ -0,0 +1,9 @@ +namespace AmplifyColor; + +public enum Tonemapping +{ + Disabled, + Photographic, + FilmicHable, + FilmicACES +} diff --git a/ROUNDS/AmplifyColor/VersionInfo.cs b/ROUNDS/AmplifyColor/VersionInfo.cs new file mode 100644 index 0000000..e6c15eb --- /dev/null +++ b/ROUNDS/AmplifyColor/VersionInfo.cs @@ -0,0 +1,67 @@ +using System; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public class VersionInfo +{ + public const byte Major = 1; + + public const byte Minor = 8; + + public const byte Release = 2; + + private static string StageSuffix = ""; + + private static string TrialSuffix = ""; + + [SerializeField] + private int m_major; + + [SerializeField] + private int m_minor; + + [SerializeField] + private int m_release; + + public int Number => m_major * 100 + m_minor * 10 + m_release; + + public static string StaticToString() + { + return $"{(byte)1}.{(byte)8}.{(byte)2}" + StageSuffix + TrialSuffix; + } + + public override string ToString() + { + return $"{m_major}.{m_minor}.{m_release}" + StageSuffix + TrialSuffix; + } + + private VersionInfo() + { + m_major = 1; + m_minor = 8; + m_release = 2; + } + + private VersionInfo(byte major, byte minor, byte release) + { + m_major = major; + m_minor = minor; + m_release = release; + } + + public static VersionInfo Current() + { + return new VersionInfo(1, 8, 2); + } + + public static bool Matches(VersionInfo version) + { + if (1 == version.m_major && 8 == version.m_minor) + { + return 2 == version.m_release; + } + return false; + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffect.cs b/ROUNDS/AmplifyColor/VolumeEffect.cs new file mode 100644 index 0000000..f4ee51b --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffect.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffect +{ + public AmplifyColorBase gameObject; + + public List<VolumeEffectComponent> components; + + public VolumeEffect(AmplifyColorBase effect) + { + gameObject = effect; + components = new List<VolumeEffectComponent>(); + } + + public static VolumeEffect BlendValuesToVolumeEffect(VolumeEffectFlags flags, VolumeEffect volume1, VolumeEffect volume2, float blend) + { + VolumeEffect volumeEffect = new VolumeEffect(volume1.gameObject); + foreach (VolumeEffectComponentFlags component in flags.components) + { + if (!component.blendFlag) + { + continue; + } + VolumeEffectComponent volumeEffectComponent = volume1.FindEffectComponent(component.componentName); + VolumeEffectComponent volumeEffectComponent2 = volume2.FindEffectComponent(component.componentName); + if (volumeEffectComponent == null || volumeEffectComponent2 == null) + { + continue; + } + VolumeEffectComponent volumeEffectComponent3 = new VolumeEffectComponent(volumeEffectComponent.componentName); + foreach (VolumeEffectFieldFlags componentField in component.componentFields) + { + if (!componentField.blendFlag) + { + continue; + } + VolumeEffectField volumeEffectField = volumeEffectComponent.FindEffectField(componentField.fieldName); + VolumeEffectField volumeEffectField2 = volumeEffectComponent2.FindEffectField(componentField.fieldName); + if (volumeEffectField != null && volumeEffectField2 != null) + { + VolumeEffectField volumeEffectField3 = new VolumeEffectField(volumeEffectField.fieldName, volumeEffectField.fieldType); + switch (volumeEffectField3.fieldType) + { + case "System.Single": + volumeEffectField3.valueSingle = Mathf.Lerp(volumeEffectField.valueSingle, volumeEffectField2.valueSingle, blend); + break; + case "System.Boolean": + volumeEffectField3.valueBoolean = volumeEffectField2.valueBoolean; + break; + case "UnityEngine.Vector2": + volumeEffectField3.valueVector2 = Vector2.Lerp(volumeEffectField.valueVector2, volumeEffectField2.valueVector2, blend); + break; + case "UnityEngine.Vector3": + volumeEffectField3.valueVector3 = Vector3.Lerp(volumeEffectField.valueVector3, volumeEffectField2.valueVector3, blend); + break; + case "UnityEngine.Vector4": + volumeEffectField3.valueVector4 = Vector4.Lerp(volumeEffectField.valueVector4, volumeEffectField2.valueVector4, blend); + break; + case "UnityEngine.Color": + volumeEffectField3.valueColor = Color.Lerp(volumeEffectField.valueColor, volumeEffectField2.valueColor, blend); + break; + } + volumeEffectComponent3.fields.Add(volumeEffectField3); + } + } + volumeEffect.components.Add(volumeEffectComponent3); + } + return volumeEffect; + } + + public VolumeEffectComponent AddComponent(Component c, VolumeEffectComponentFlags compFlags) + { + if (compFlags == null) + { + VolumeEffectComponent volumeEffectComponent = new VolumeEffectComponent(string.Concat(c.GetType())); + components.Add(volumeEffectComponent); + return volumeEffectComponent; + } + VolumeEffectComponent volumeEffectComponent2; + if ((volumeEffectComponent2 = FindEffectComponent(string.Concat(c.GetType()))) != null) + { + volumeEffectComponent2.UpdateComponent(c, compFlags); + return volumeEffectComponent2; + } + VolumeEffectComponent volumeEffectComponent3 = new VolumeEffectComponent(c, compFlags); + components.Add(volumeEffectComponent3); + return volumeEffectComponent3; + } + + public void RemoveEffectComponent(VolumeEffectComponent comp) + { + components.Remove(comp); + } + + public void UpdateVolume() + { + if (gameObject == null) + { + return; + } + foreach (VolumeEffectComponentFlags component2 in gameObject.EffectFlags.components) + { + if (component2.blendFlag) + { + Component component = gameObject.GetComponent(component2.componentName); + if (component != null) + { + AddComponent(component, component2); + } + } + } + } + + public void SetValues(AmplifyColorBase targetColor) + { + VolumeEffectFlags effectFlags = targetColor.EffectFlags; + GameObject gameObject = targetColor.gameObject; + foreach (VolumeEffectComponentFlags component2 in effectFlags.components) + { + if (!component2.blendFlag) + { + continue; + } + Component component = gameObject.GetComponent(component2.componentName); + VolumeEffectComponent volumeEffectComponent = FindEffectComponent(component2.componentName); + if (component == null || volumeEffectComponent == null) + { + continue; + } + foreach (VolumeEffectFieldFlags componentField in component2.componentFields) + { + if (!componentField.blendFlag) + { + continue; + } + FieldInfo field = component.GetType().GetField(componentField.fieldName); + VolumeEffectField volumeEffectField = volumeEffectComponent.FindEffectField(componentField.fieldName); + if (!(field == null) && volumeEffectField != null) + { + switch (field.FieldType.FullName) + { + case "System.Single": + field.SetValue(component, volumeEffectField.valueSingle); + break; + case "System.Boolean": + field.SetValue(component, volumeEffectField.valueBoolean); + break; + case "UnityEngine.Vector2": + field.SetValue(component, volumeEffectField.valueVector2); + break; + case "UnityEngine.Vector3": + field.SetValue(component, volumeEffectField.valueVector3); + break; + case "UnityEngine.Vector4": + field.SetValue(component, volumeEffectField.valueVector4); + break; + case "UnityEngine.Color": + field.SetValue(component, volumeEffectField.valueColor); + break; + } + } + } + } + } + + public void BlendValues(AmplifyColorBase targetColor, VolumeEffect other, float blendAmount) + { + VolumeEffectFlags effectFlags = targetColor.EffectFlags; + GameObject gameObject = targetColor.gameObject; + for (int i = 0; i < effectFlags.components.Count; i++) + { + VolumeEffectComponentFlags volumeEffectComponentFlags = effectFlags.components[i]; + if (!volumeEffectComponentFlags.blendFlag) + { + continue; + } + Component component = gameObject.GetComponent(volumeEffectComponentFlags.componentName); + VolumeEffectComponent volumeEffectComponent = FindEffectComponent(volumeEffectComponentFlags.componentName); + VolumeEffectComponent volumeEffectComponent2 = other.FindEffectComponent(volumeEffectComponentFlags.componentName); + if (component == null || volumeEffectComponent == null || volumeEffectComponent2 == null) + { + continue; + } + for (int j = 0; j < volumeEffectComponentFlags.componentFields.Count; j++) + { + VolumeEffectFieldFlags volumeEffectFieldFlags = volumeEffectComponentFlags.componentFields[j]; + if (!volumeEffectFieldFlags.blendFlag) + { + continue; + } + FieldInfo field = component.GetType().GetField(volumeEffectFieldFlags.fieldName); + VolumeEffectField volumeEffectField = volumeEffectComponent.FindEffectField(volumeEffectFieldFlags.fieldName); + VolumeEffectField volumeEffectField2 = volumeEffectComponent2.FindEffectField(volumeEffectFieldFlags.fieldName); + if (!(field == null) && volumeEffectField != null && volumeEffectField2 != null) + { + switch (field.FieldType.FullName) + { + case "System.Single": + field.SetValue(component, Mathf.Lerp(volumeEffectField.valueSingle, volumeEffectField2.valueSingle, blendAmount)); + break; + case "System.Boolean": + field.SetValue(component, volumeEffectField2.valueBoolean); + break; + case "UnityEngine.Vector2": + field.SetValue(component, Vector2.Lerp(volumeEffectField.valueVector2, volumeEffectField2.valueVector2, blendAmount)); + break; + case "UnityEngine.Vector3": + field.SetValue(component, Vector3.Lerp(volumeEffectField.valueVector3, volumeEffectField2.valueVector3, blendAmount)); + break; + case "UnityEngine.Vector4": + field.SetValue(component, Vector4.Lerp(volumeEffectField.valueVector4, volumeEffectField2.valueVector4, blendAmount)); + break; + case "UnityEngine.Color": + field.SetValue(component, Color.Lerp(volumeEffectField.valueColor, volumeEffectField2.valueColor, blendAmount)); + break; + } + } + } + } + } + + public VolumeEffectComponent FindEffectComponent(string compName) + { + for (int i = 0; i < components.Count; i++) + { + if (components[i].componentName == compName) + { + return components[i]; + } + } + return null; + } + + public static Component[] ListAcceptableComponents(AmplifyColorBase go) + { + if (go == null) + { + return new Component[0]; + } + return (from comp in go.GetComponents(typeof(Component)) + where comp != null && !string.Concat(comp.GetType()).StartsWith("UnityEngine.") && !(comp.GetType() == typeof(AmplifyColorBase)) + select comp).ToArray(); + } + + public string[] GetComponentNames() + { + return components.Select((VolumeEffectComponent r) => r.componentName).ToArray(); + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffectComponent.cs b/ROUNDS/AmplifyColor/VolumeEffectComponent.cs new file mode 100644 index 0000000..620ff5a --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffectComponent.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffectComponent +{ + public string componentName; + + public List<VolumeEffectField> fields; + + public VolumeEffectComponent(string name) + { + componentName = name; + fields = new List<VolumeEffectField>(); + } + + public VolumeEffectField AddField(FieldInfo pi, Component c) + { + return AddField(pi, c, -1); + } + + public VolumeEffectField AddField(FieldInfo pi, Component c, int position) + { + VolumeEffectField volumeEffectField = (VolumeEffectField.IsValidType(pi.FieldType.FullName) ? new VolumeEffectField(pi, c) : null); + if (volumeEffectField != null) + { + if (position < 0 || position >= fields.Count) + { + fields.Add(volumeEffectField); + } + else + { + fields.Insert(position, volumeEffectField); + } + } + return volumeEffectField; + } + + public void RemoveEffectField(VolumeEffectField field) + { + fields.Remove(field); + } + + public VolumeEffectComponent(Component c, VolumeEffectComponentFlags compFlags) + : this(compFlags.componentName) + { + foreach (VolumeEffectFieldFlags componentField in compFlags.componentFields) + { + if (componentField.blendFlag) + { + FieldInfo field = c.GetType().GetField(componentField.fieldName); + VolumeEffectField volumeEffectField = (VolumeEffectField.IsValidType(field.FieldType.FullName) ? new VolumeEffectField(field, c) : null); + if (volumeEffectField != null) + { + fields.Add(volumeEffectField); + } + } + } + } + + public void UpdateComponent(Component c, VolumeEffectComponentFlags compFlags) + { + foreach (VolumeEffectFieldFlags fieldFlags in compFlags.componentFields) + { + if (fieldFlags.blendFlag && !fields.Exists((VolumeEffectField s) => s.fieldName == fieldFlags.fieldName)) + { + FieldInfo field = c.GetType().GetField(fieldFlags.fieldName); + VolumeEffectField volumeEffectField = (VolumeEffectField.IsValidType(field.FieldType.FullName) ? new VolumeEffectField(field, c) : null); + if (volumeEffectField != null) + { + fields.Add(volumeEffectField); + } + } + } + } + + public VolumeEffectField FindEffectField(string fieldName) + { + for (int i = 0; i < fields.Count; i++) + { + if (fields[i].fieldName == fieldName) + { + return fields[i]; + } + } + return null; + } + + public static FieldInfo[] ListAcceptableFields(Component c) + { + if (c == null) + { + return new FieldInfo[0]; + } + return (from f in c.GetType().GetFields() + where VolumeEffectField.IsValidType(f.FieldType.FullName) + select f).ToArray(); + } + + public string[] GetFieldNames() + { + return fields.Select((VolumeEffectField r) => r.fieldName).ToArray(); + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffectComponentFlags.cs b/ROUNDS/AmplifyColor/VolumeEffectComponentFlags.cs new file mode 100644 index 0000000..1b54a69 --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffectComponentFlags.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffectComponentFlags +{ + public string componentName; + + public List<VolumeEffectFieldFlags> componentFields; + + public bool blendFlag; + + public VolumeEffectComponentFlags(string name) + { + componentName = name; + componentFields = new List<VolumeEffectFieldFlags>(); + } + + public VolumeEffectComponentFlags(VolumeEffectComponent comp) + : this(comp.componentName) + { + blendFlag = true; + foreach (VolumeEffectField field in comp.fields) + { + if (VolumeEffectField.IsValidType(field.fieldType)) + { + componentFields.Add(new VolumeEffectFieldFlags(field)); + } + } + } + + public VolumeEffectComponentFlags(Component c) + : this(string.Concat(c.GetType())) + { + FieldInfo[] fields = c.GetType().GetFields(); + foreach (FieldInfo fieldInfo in fields) + { + if (VolumeEffectField.IsValidType(fieldInfo.FieldType.FullName)) + { + componentFields.Add(new VolumeEffectFieldFlags(fieldInfo)); + } + } + } + + public void UpdateComponentFlags(VolumeEffectComponent comp) + { + foreach (VolumeEffectField field in comp.fields) + { + if (componentFields.Find((VolumeEffectFieldFlags s) => s.fieldName == field.fieldName) == null && VolumeEffectField.IsValidType(field.fieldType)) + { + componentFields.Add(new VolumeEffectFieldFlags(field)); + } + } + } + + public void UpdateComponentFlags(Component c) + { + FieldInfo[] fields = c.GetType().GetFields(); + foreach (FieldInfo pi in fields) + { + if (!componentFields.Exists((VolumeEffectFieldFlags s) => s.fieldName == pi.Name) && VolumeEffectField.IsValidType(pi.FieldType.FullName)) + { + componentFields.Add(new VolumeEffectFieldFlags(pi)); + } + } + } + + public string[] GetFieldNames() + { + return (from r in componentFields + where r.blendFlag + select r.fieldName).ToArray(); + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffectContainer.cs b/ROUNDS/AmplifyColor/VolumeEffectContainer.cs new file mode 100644 index 0000000..580fb20 --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffectContainer.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffectContainer +{ + public List<VolumeEffect> volumes; + + public VolumeEffectContainer() + { + volumes = new List<VolumeEffect>(); + } + + public void AddColorEffect(AmplifyColorBase colorEffect) + { + VolumeEffect volumeEffect; + if ((volumeEffect = FindVolumeEffect(colorEffect)) != null) + { + volumeEffect.UpdateVolume(); + return; + } + volumeEffect = new VolumeEffect(colorEffect); + volumes.Add(volumeEffect); + volumeEffect.UpdateVolume(); + } + + public VolumeEffect AddJustColorEffect(AmplifyColorBase colorEffect) + { + VolumeEffect volumeEffect = new VolumeEffect(colorEffect); + volumes.Add(volumeEffect); + return volumeEffect; + } + + public VolumeEffect FindVolumeEffect(AmplifyColorBase colorEffect) + { + for (int i = 0; i < volumes.Count; i++) + { + if (volumes[i].gameObject == colorEffect) + { + return volumes[i]; + } + } + for (int j = 0; j < volumes.Count; j++) + { + if (volumes[j].gameObject != null && volumes[j].gameObject.SharedInstanceID == colorEffect.SharedInstanceID) + { + return volumes[j]; + } + } + return null; + } + + public void RemoveVolumeEffect(VolumeEffect volume) + { + volumes.Remove(volume); + } + + public AmplifyColorBase[] GetStoredEffects() + { + return volumes.Select((VolumeEffect r) => r.gameObject).ToArray(); + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffectField.cs b/ROUNDS/AmplifyColor/VolumeEffectField.cs new file mode 100644 index 0000000..46fb745 --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffectField.cs @@ -0,0 +1,79 @@ +using System; +using System.Reflection; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffectField +{ + public string fieldName; + + public string fieldType; + + public float valueSingle; + + public Color valueColor; + + public bool valueBoolean; + + public Vector2 valueVector2; + + public Vector3 valueVector3; + + public Vector4 valueVector4; + + public VolumeEffectField(string fieldName, string fieldType) + { + this.fieldName = fieldName; + this.fieldType = fieldType; + } + + public VolumeEffectField(FieldInfo pi, Component c) + : this(pi.Name, pi.FieldType.FullName) + { + object value = pi.GetValue(c); + UpdateValue(value); + } + + public static bool IsValidType(string type) + { + switch (type) + { + case "System.Single": + case "System.Boolean": + case "UnityEngine.Color": + case "UnityEngine.Vector2": + case "UnityEngine.Vector3": + case "UnityEngine.Vector4": + return true; + default: + return false; + } + } + + public void UpdateValue(object val) + { + switch (fieldType) + { + case "System.Single": + valueSingle = (float)val; + break; + case "System.Boolean": + valueBoolean = (bool)val; + break; + case "UnityEngine.Color": + valueColor = (Color)val; + break; + case "UnityEngine.Vector2": + valueVector2 = (Vector2)val; + break; + case "UnityEngine.Vector3": + valueVector3 = (Vector3)val; + break; + case "UnityEngine.Vector4": + valueVector4 = (Vector4)val; + break; + } + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffectFieldFlags.cs b/ROUNDS/AmplifyColor/VolumeEffectFieldFlags.cs new file mode 100644 index 0000000..a433e59 --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffectFieldFlags.cs @@ -0,0 +1,27 @@ +using System; +using System.Reflection; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffectFieldFlags +{ + public string fieldName; + + public string fieldType; + + public bool blendFlag; + + public VolumeEffectFieldFlags(FieldInfo pi) + { + fieldName = pi.Name; + fieldType = pi.FieldType.FullName; + } + + public VolumeEffectFieldFlags(VolumeEffectField field) + { + fieldName = field.fieldName; + fieldType = field.fieldType; + blendFlag = true; + } +} diff --git a/ROUNDS/AmplifyColor/VolumeEffectFlags.cs b/ROUNDS/AmplifyColor/VolumeEffectFlags.cs new file mode 100644 index 0000000..b3737d6 --- /dev/null +++ b/ROUNDS/AmplifyColor/VolumeEffectFlags.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AmplifyColor; + +[Serializable] +public class VolumeEffectFlags +{ + public List<VolumeEffectComponentFlags> components; + + public VolumeEffectFlags() + { + components = new List<VolumeEffectComponentFlags>(); + } + + public void AddComponent(Component c) + { + VolumeEffectComponentFlags volumeEffectComponentFlags; + if ((volumeEffectComponentFlags = components.Find((VolumeEffectComponentFlags s) => s.componentName == string.Concat(c.GetType()))) != null) + { + volumeEffectComponentFlags.UpdateComponentFlags(c); + } + else + { + components.Add(new VolumeEffectComponentFlags(c)); + } + } + + public void UpdateFlags(VolumeEffect effectVol) + { + foreach (VolumeEffectComponent comp in effectVol.components) + { + VolumeEffectComponentFlags volumeEffectComponentFlags = null; + if ((volumeEffectComponentFlags = components.Find((VolumeEffectComponentFlags s) => s.componentName == comp.componentName)) == null) + { + components.Add(new VolumeEffectComponentFlags(comp)); + } + else + { + volumeEffectComponentFlags.UpdateComponentFlags(comp); + } + } + } + + public static void UpdateCamFlags(AmplifyColorBase[] effects, AmplifyColorVolumeBase[] volumes) + { + foreach (AmplifyColorBase amplifyColorBase in effects) + { + amplifyColorBase.EffectFlags = new VolumeEffectFlags(); + for (int j = 0; j < volumes.Length; j++) + { + VolumeEffect volumeEffect = volumes[j].EffectContainer.FindVolumeEffect(amplifyColorBase); + if (volumeEffect != null) + { + amplifyColorBase.EffectFlags.UpdateFlags(volumeEffect); + } + } + } + } + + public VolumeEffect GenerateEffectData(AmplifyColorBase go) + { + VolumeEffect volumeEffect = new VolumeEffect(go); + foreach (VolumeEffectComponentFlags component2 in components) + { + if (component2.blendFlag) + { + Component component = go.GetComponent(component2.componentName); + if (component != null) + { + volumeEffect.AddComponent(component, component2); + } + } + } + return volumeEffect; + } + + public VolumeEffectComponentFlags FindComponentFlags(string compName) + { + for (int i = 0; i < components.Count; i++) + { + if (components[i].componentName == compName) + { + return components[i]; + } + } + return null; + } + + public string[] GetComponentNames() + { + return (from r in components + where r.blendFlag + select r.componentName).ToArray(); + } +} diff --git a/ROUNDS/AmplifyColorBase.cs b/ROUNDS/AmplifyColorBase.cs new file mode 100644 index 0000000..214d0a4 --- /dev/null +++ b/ROUNDS/AmplifyColorBase.cs @@ -0,0 +1,879 @@ +using System; +using System.Collections.Generic; +using AmplifyColor; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +[AddComponentMenu("")] +public class AmplifyColorBase : MonoBehaviour +{ + public const int LutSize = 32; + + public const int LutWidth = 1024; + + public const int LutHeight = 32; + + private const int DepthCurveLutRange = 1024; + + public Tonemapping Tonemapper; + + public float Exposure = 1f; + + public float LinearWhitePoint = 11.2f; + + [FormerlySerializedAs("UseDithering")] + public bool ApplyDithering; + + public Quality QualityLevel = Quality.Standard; + + public float BlendAmount; + + public Texture LutTexture; + + public Texture LutBlendTexture; + + public Texture MaskTexture; + + public bool UseDepthMask; + + public AnimationCurve DepthMaskCurve = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 1f)); + + public bool UseVolumes; + + public float ExitVolumeBlendTime = 1f; + + public Transform TriggerVolumeProxy; + + public LayerMask VolumeCollisionMask = -1; + + private Camera ownerCamera; + + private Shader shaderBase; + + private Shader shaderBlend; + + private Shader shaderBlendCache; + + private Shader shaderMask; + + private Shader shaderMaskBlend; + + private Shader shaderDepthMask; + + private Shader shaderDepthMaskBlend; + + private Shader shaderProcessOnly; + + private RenderTexture blendCacheLut; + + private Texture2D defaultLut; + + private Texture2D depthCurveLut; + + private Color32[] depthCurveColors; + + private ColorSpace colorSpace = ColorSpace.Uninitialized; + + private Quality qualityLevel = Quality.Standard; + + private Material materialBase; + + private Material materialBlend; + + private Material materialBlendCache; + + private Material materialMask; + + private Material materialMaskBlend; + + private Material materialDepthMask; + + private Material materialDepthMaskBlend; + + private Material materialProcessOnly; + + private bool blending; + + private float blendingTime; + + private float blendingTimeCountdown; + + private Action onFinishBlend; + + private AnimationCurve prevDepthMaskCurve = new AnimationCurve(); + + private bool volumesBlending; + + private float volumesBlendingTime; + + private float volumesBlendingTimeCountdown; + + private Texture volumesLutBlendTexture; + + private float volumesBlendAmount; + + private Texture worldLUT; + + private AmplifyColorVolumeBase currentVolumeLut; + + private RenderTexture midBlendLUT; + + private bool blendingFromMidBlend; + + private VolumeEffect worldVolumeEffects; + + private VolumeEffect currentVolumeEffects; + + private VolumeEffect blendVolumeEffects; + + private float worldExposure = 1f; + + private float currentExposure = 1f; + + private float blendExposure = 1f; + + private float effectVolumesBlendAdjust; + + private List<AmplifyColorVolumeBase> enteredVolumes = new List<AmplifyColorVolumeBase>(); + + private AmplifyColorTriggerProxyBase actualTriggerProxy; + + [HideInInspector] + public VolumeEffectFlags EffectFlags = new VolumeEffectFlags(); + + [SerializeField] + [HideInInspector] + private string sharedInstanceID = ""; + + private bool silentError; + + public Texture2D DefaultLut + { + get + { + if (!(defaultLut == null)) + { + return defaultLut; + } + return CreateDefaultLut(); + } + } + + public bool IsBlending => blending; + + private float effectVolumesBlendAdjusted => Mathf.Clamp01((effectVolumesBlendAdjust < 0.99f) ? ((volumesBlendAmount - effectVolumesBlendAdjust) / (1f - effectVolumesBlendAdjust)) : 1f); + + public string SharedInstanceID => sharedInstanceID; + + public bool WillItBlend + { + get + { + if (LutTexture != null && LutBlendTexture != null) + { + return !blending; + } + return false; + } + } + + public void NewSharedInstanceID() + { + sharedInstanceID = Guid.NewGuid().ToString(); + } + + private void ReportMissingShaders() + { + Debug.LogError("[AmplifyColor] Failed to initialize shaders. Please attempt to re-enable the Amplify Color Effect component. If that fails, please reinstall Amplify Color."); + base.enabled = false; + } + + private void ReportNotSupported() + { + Debug.LogError("[AmplifyColor] This image effect is not supported on this platform."); + base.enabled = false; + } + + private bool CheckShader(Shader s) + { + if (s == null) + { + ReportMissingShaders(); + return false; + } + if (!s.isSupported) + { + ReportNotSupported(); + return false; + } + return true; + } + + private bool CheckShaders() + { + if (CheckShader(shaderBase) && CheckShader(shaderBlend) && CheckShader(shaderBlendCache) && CheckShader(shaderMask) && CheckShader(shaderMaskBlend)) + { + return CheckShader(shaderProcessOnly); + } + return false; + } + + private bool CheckSupport() + { + if (!SystemInfo.supportsImageEffects) + { + ReportNotSupported(); + return false; + } + return true; + } + + private void OnEnable() + { + if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null) + { + Debug.LogWarning("[AmplifyColor] Null graphics device detected. Skipping effect silently."); + silentError = true; + } + else if (CheckSupport() && CreateMaterials()) + { + Texture2D texture2D = LutTexture as Texture2D; + Texture2D texture2D2 = LutBlendTexture as Texture2D; + if ((texture2D != null && texture2D.mipmapCount > 1) || (texture2D2 != null && texture2D2.mipmapCount > 1)) + { + Debug.LogError("[AmplifyColor] Please disable \"Generate Mip Maps\" import settings on all LUT textures to avoid visual glitches. Change Texture Type to \"Advanced\" to access Mip settings."); + } + } + } + + private void OnDisable() + { + if (actualTriggerProxy != null) + { + UnityEngine.Object.DestroyImmediate(actualTriggerProxy.gameObject); + actualTriggerProxy = null; + } + ReleaseMaterials(); + ReleaseTextures(); + } + + private void VolumesBlendTo(Texture blendTargetLUT, float blendTimeInSec) + { + volumesLutBlendTexture = blendTargetLUT; + volumesBlendAmount = 0f; + volumesBlendingTime = blendTimeInSec; + volumesBlendingTimeCountdown = blendTimeInSec; + volumesBlending = true; + } + + public void BlendTo(Texture blendTargetLUT, float blendTimeInSec, Action onFinishBlend) + { + LutBlendTexture = blendTargetLUT; + BlendAmount = 0f; + this.onFinishBlend = onFinishBlend; + blendingTime = blendTimeInSec; + blendingTimeCountdown = blendTimeInSec; + blending = true; + } + + private void CheckCamera() + { + if (ownerCamera == null) + { + ownerCamera = GetComponent<Camera>(); + } + if (UseDepthMask && (ownerCamera.depthTextureMode & DepthTextureMode.Depth) == 0) + { + ownerCamera.depthTextureMode |= DepthTextureMode.Depth; + } + } + + private void Start() + { + if (!silentError) + { + CheckCamera(); + worldLUT = LutTexture; + worldVolumeEffects = EffectFlags.GenerateEffectData(this); + blendVolumeEffects = (currentVolumeEffects = worldVolumeEffects); + worldExposure = Exposure; + blendExposure = (currentExposure = worldExposure); + } + } + + private void Update() + { + if (silentError) + { + return; + } + CheckCamera(); + bool flag = false; + if (volumesBlending) + { + volumesBlendAmount = (volumesBlendingTime - volumesBlendingTimeCountdown) / volumesBlendingTime; + volumesBlendingTimeCountdown -= Time.smoothDeltaTime; + if (volumesBlendAmount >= 1f) + { + volumesBlendAmount = 1f; + flag = true; + } + } + else + { + volumesBlendAmount = Mathf.Clamp01(volumesBlendAmount); + } + if (blending) + { + BlendAmount = (blendingTime - blendingTimeCountdown) / blendingTime; + blendingTimeCountdown -= Time.smoothDeltaTime; + if (BlendAmount >= 1f) + { + LutTexture = LutBlendTexture; + BlendAmount = 0f; + blending = false; + LutBlendTexture = null; + if (onFinishBlend != null) + { + onFinishBlend(); + } + } + } + else + { + BlendAmount = Mathf.Clamp01(BlendAmount); + } + if (UseVolumes) + { + if (actualTriggerProxy == null) + { + GameObject gameObject = new GameObject(base.name + "+ACVolumeProxy") + { + hideFlags = HideFlags.HideAndDontSave + }; + if (TriggerVolumeProxy != null && TriggerVolumeProxy.GetComponent<Collider2D>() != null) + { + actualTriggerProxy = gameObject.AddComponent<AmplifyColorTriggerProxy2D>(); + } + else + { + actualTriggerProxy = gameObject.AddComponent<AmplifyColorTriggerProxy>(); + } + actualTriggerProxy.OwnerEffect = this; + } + UpdateVolumes(); + } + else if (actualTriggerProxy != null) + { + UnityEngine.Object.DestroyImmediate(actualTriggerProxy.gameObject); + actualTriggerProxy = null; + } + if (flag) + { + LutTexture = volumesLutBlendTexture; + volumesBlendAmount = 0f; + volumesBlending = false; + volumesLutBlendTexture = null; + effectVolumesBlendAdjust = 0f; + currentVolumeEffects = blendVolumeEffects; + currentVolumeEffects.SetValues(this); + currentExposure = blendExposure; + if (blendingFromMidBlend && midBlendLUT != null) + { + midBlendLUT.DiscardContents(); + } + blendingFromMidBlend = false; + } + } + + public void EnterVolume(AmplifyColorVolumeBase volume) + { + if (!enteredVolumes.Contains(volume)) + { + enteredVolumes.Insert(0, volume); + } + } + + public void ExitVolume(AmplifyColorVolumeBase volume) + { + if (enteredVolumes.Contains(volume)) + { + enteredVolumes.Remove(volume); + } + } + + private void UpdateVolumes() + { + if (volumesBlending) + { + currentVolumeEffects.BlendValues(this, blendVolumeEffects, effectVolumesBlendAdjusted); + } + if (volumesBlending) + { + Exposure = Mathf.Lerp(currentExposure, blendExposure, effectVolumesBlendAdjusted); + } + Transform transform = ((TriggerVolumeProxy == null) ? base.transform : TriggerVolumeProxy); + if (actualTriggerProxy.transform.parent != transform) + { + actualTriggerProxy.Reference = transform; + actualTriggerProxy.gameObject.layer = transform.gameObject.layer; + } + AmplifyColorVolumeBase amplifyColorVolumeBase = null; + int num = int.MinValue; + for (int i = 0; i < enteredVolumes.Count; i++) + { + AmplifyColorVolumeBase amplifyColorVolumeBase2 = enteredVolumes[i]; + if (amplifyColorVolumeBase2.Priority > num) + { + amplifyColorVolumeBase = amplifyColorVolumeBase2; + num = amplifyColorVolumeBase2.Priority; + } + } + if (!(amplifyColorVolumeBase != currentVolumeLut)) + { + return; + } + currentVolumeLut = amplifyColorVolumeBase; + Texture texture = ((amplifyColorVolumeBase == null) ? worldLUT : amplifyColorVolumeBase.LutTexture); + float num2 = ((amplifyColorVolumeBase == null) ? ExitVolumeBlendTime : amplifyColorVolumeBase.EnterBlendTime); + if (volumesBlending && !blendingFromMidBlend && texture == LutTexture) + { + LutTexture = volumesLutBlendTexture; + volumesLutBlendTexture = texture; + volumesBlendingTimeCountdown = num2 * ((volumesBlendingTime - volumesBlendingTimeCountdown) / volumesBlendingTime); + volumesBlendingTime = num2; + currentVolumeEffects = VolumeEffect.BlendValuesToVolumeEffect(EffectFlags, currentVolumeEffects, blendVolumeEffects, effectVolumesBlendAdjusted); + currentExposure = Mathf.Lerp(currentExposure, blendExposure, effectVolumesBlendAdjusted); + effectVolumesBlendAdjust = 1f - volumesBlendAmount; + volumesBlendAmount = 1f - volumesBlendAmount; + } + else + { + if (volumesBlending) + { + materialBlendCache.SetFloat("_LerpAmount", volumesBlendAmount); + if (blendingFromMidBlend) + { + Graphics.Blit(midBlendLUT, blendCacheLut); + materialBlendCache.SetTexture("_RgbTex", blendCacheLut); + } + else + { + materialBlendCache.SetTexture("_RgbTex", LutTexture); + } + materialBlendCache.SetTexture("_LerpRgbTex", (volumesLutBlendTexture != null) ? volumesLutBlendTexture : defaultLut); + Graphics.Blit(midBlendLUT, midBlendLUT, materialBlendCache); + blendCacheLut.DiscardContents(); + currentVolumeEffects = VolumeEffect.BlendValuesToVolumeEffect(EffectFlags, currentVolumeEffects, blendVolumeEffects, effectVolumesBlendAdjusted); + currentExposure = Mathf.Lerp(currentExposure, blendExposure, effectVolumesBlendAdjusted); + effectVolumesBlendAdjust = 0f; + blendingFromMidBlend = true; + } + VolumesBlendTo(texture, num2); + } + blendVolumeEffects = ((amplifyColorVolumeBase == null) ? worldVolumeEffects : amplifyColorVolumeBase.EffectContainer.FindVolumeEffect(this)); + blendExposure = ((amplifyColorVolumeBase == null) ? worldExposure : amplifyColorVolumeBase.Exposure); + if (blendVolumeEffects == null) + { + blendVolumeEffects = worldVolumeEffects; + } + } + + private void SetupShader() + { + colorSpace = QualitySettings.activeColorSpace; + qualityLevel = QualityLevel; + shaderBase = Shader.Find("Hidden/Amplify Color/Base"); + shaderBlend = Shader.Find("Hidden/Amplify Color/Blend"); + shaderBlendCache = Shader.Find("Hidden/Amplify Color/BlendCache"); + shaderMask = Shader.Find("Hidden/Amplify Color/Mask"); + shaderMaskBlend = Shader.Find("Hidden/Amplify Color/MaskBlend"); + shaderDepthMask = Shader.Find("Hidden/Amplify Color/DepthMask"); + shaderDepthMaskBlend = Shader.Find("Hidden/Amplify Color/DepthMaskBlend"); + shaderProcessOnly = Shader.Find("Hidden/Amplify Color/ProcessOnly"); + } + + private void ReleaseMaterials() + { + SafeRelease(ref materialBase); + SafeRelease(ref materialBlend); + SafeRelease(ref materialBlendCache); + SafeRelease(ref materialMask); + SafeRelease(ref materialMaskBlend); + SafeRelease(ref materialDepthMask); + SafeRelease(ref materialDepthMaskBlend); + SafeRelease(ref materialProcessOnly); + } + + private Texture2D CreateDefaultLut() + { + defaultLut = new Texture2D(1024, 32, TextureFormat.RGB24, mipChain: false, linear: true) + { + hideFlags = HideFlags.HideAndDontSave + }; + defaultLut.name = "DefaultLut"; + defaultLut.hideFlags = HideFlags.DontSave; + defaultLut.anisoLevel = 1; + defaultLut.filterMode = FilterMode.Bilinear; + Color32[] array = new Color32[32768]; + for (int i = 0; i < 32; i++) + { + int num = i * 32; + for (int j = 0; j < 32; j++) + { + int num2 = num + j * 1024; + for (int k = 0; k < 32; k++) + { + float num3 = (float)k / 31f; + float num4 = (float)j / 31f; + float num5 = (float)i / 31f; + byte r = (byte)(num3 * 255f); + byte g = (byte)(num4 * 255f); + byte b = (byte)(num5 * 255f); + array[num2 + k] = new Color32(r, g, b, byte.MaxValue); + } + } + } + defaultLut.SetPixels32(array); + defaultLut.Apply(); + return defaultLut; + } + + private Texture2D CreateDepthCurveLut() + { + SafeRelease(ref depthCurveLut); + depthCurveLut = new Texture2D(1024, 1, TextureFormat.Alpha8, mipChain: false, linear: true) + { + hideFlags = HideFlags.HideAndDontSave + }; + depthCurveLut.name = "DepthCurveLut"; + depthCurveLut.hideFlags = HideFlags.DontSave; + depthCurveLut.anisoLevel = 1; + depthCurveLut.wrapMode = TextureWrapMode.Clamp; + depthCurveLut.filterMode = FilterMode.Bilinear; + depthCurveColors = new Color32[1024]; + return depthCurveLut; + } + + private void UpdateDepthCurveLut() + { + if (depthCurveLut == null) + { + CreateDepthCurveLut(); + } + float num = 0f; + int num2 = 0; + while (num2 < 1024) + { + depthCurveColors[num2].a = (byte)Mathf.FloorToInt(Mathf.Clamp01(DepthMaskCurve.Evaluate(num)) * 255f); + num2++; + num += 0.0009775171f; + } + depthCurveLut.SetPixels32(depthCurveColors); + depthCurveLut.Apply(); + } + + private void CheckUpdateDepthCurveLut() + { + bool flag = false; + if (DepthMaskCurve.length != prevDepthMaskCurve.length) + { + flag = true; + } + else + { + float num = 0f; + int num2 = 0; + while (num2 < DepthMaskCurve.length) + { + if (Mathf.Abs(DepthMaskCurve.Evaluate(num) - prevDepthMaskCurve.Evaluate(num)) > float.Epsilon) + { + flag = true; + break; + } + num2++; + num += 0.0009775171f; + } + } + if (depthCurveLut == null || flag) + { + UpdateDepthCurveLut(); + prevDepthMaskCurve = new AnimationCurve(DepthMaskCurve.keys); + } + } + + private void CreateHelperTextures() + { + ReleaseTextures(); + blendCacheLut = new RenderTexture(1024, 32, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) + { + hideFlags = HideFlags.HideAndDontSave + }; + blendCacheLut.name = "BlendCacheLut"; + blendCacheLut.wrapMode = TextureWrapMode.Clamp; + blendCacheLut.useMipMap = false; + blendCacheLut.anisoLevel = 0; + blendCacheLut.Create(); + midBlendLUT = new RenderTexture(1024, 32, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) + { + hideFlags = HideFlags.HideAndDontSave + }; + midBlendLUT.name = "MidBlendLut"; + midBlendLUT.wrapMode = TextureWrapMode.Clamp; + midBlendLUT.useMipMap = false; + midBlendLUT.anisoLevel = 0; + midBlendLUT.Create(); + CreateDefaultLut(); + if (UseDepthMask) + { + CreateDepthCurveLut(); + } + } + + private bool CheckMaterialAndShader(Material material, string name) + { + if (material == null || material.shader == null) + { + Debug.LogWarning("[AmplifyColor] Error creating " + name + " material. Effect disabled."); + base.enabled = false; + } + else if (!material.shader.isSupported) + { + Debug.LogWarning("[AmplifyColor] " + name + " shader not supported on this platform. Effect disabled."); + base.enabled = false; + } + else + { + material.hideFlags = HideFlags.HideAndDontSave; + } + return base.enabled; + } + + private bool CreateMaterials() + { + SetupShader(); + if (!CheckShaders()) + { + return false; + } + ReleaseMaterials(); + materialBase = new Material(shaderBase); + materialBlend = new Material(shaderBlend); + materialBlendCache = new Material(shaderBlendCache); + materialMask = new Material(shaderMask); + materialMaskBlend = new Material(shaderMaskBlend); + materialDepthMask = new Material(shaderDepthMask); + materialDepthMaskBlend = new Material(shaderDepthMaskBlend); + materialProcessOnly = new Material(shaderProcessOnly); + if (1 == 0 || !CheckMaterialAndShader(materialBase, "BaseMaterial") || !CheckMaterialAndShader(materialBlend, "BlendMaterial") || !CheckMaterialAndShader(materialBlendCache, "BlendCacheMaterial") || !CheckMaterialAndShader(materialMask, "MaskMaterial") || !CheckMaterialAndShader(materialMaskBlend, "MaskBlendMaterial") || !CheckMaterialAndShader(materialDepthMask, "DepthMaskMaterial") || !CheckMaterialAndShader(materialDepthMaskBlend, "DepthMaskBlendMaterial") || !CheckMaterialAndShader(materialProcessOnly, "ProcessOnlyMaterial")) + { + return false; + } + CreateHelperTextures(); + return true; + } + + private void SetMaterialKeyword(string keyword, bool state) + { + bool flag = materialBase.IsKeywordEnabled(keyword); + if (state && !flag) + { + materialBase.EnableKeyword(keyword); + materialBlend.EnableKeyword(keyword); + materialBlendCache.EnableKeyword(keyword); + materialMask.EnableKeyword(keyword); + materialMaskBlend.EnableKeyword(keyword); + materialDepthMask.EnableKeyword(keyword); + materialDepthMaskBlend.EnableKeyword(keyword); + materialProcessOnly.EnableKeyword(keyword); + } + else if (!state && materialBase.IsKeywordEnabled(keyword)) + { + materialBase.DisableKeyword(keyword); + materialBlend.DisableKeyword(keyword); + materialBlendCache.DisableKeyword(keyword); + materialMask.DisableKeyword(keyword); + materialMaskBlend.DisableKeyword(keyword); + materialDepthMask.DisableKeyword(keyword); + materialDepthMaskBlend.DisableKeyword(keyword); + materialProcessOnly.DisableKeyword(keyword); + } + } + + private void SafeRelease<T>(ref T obj) where T : UnityEngine.Object + { + if ((UnityEngine.Object)obj != (UnityEngine.Object)null) + { + if (obj.GetType() == typeof(RenderTexture)) + { + (obj as RenderTexture).Release(); + } + UnityEngine.Object.DestroyImmediate(obj); + obj = null; + } + } + + private void ReleaseTextures() + { + RenderTexture.active = null; + SafeRelease(ref blendCacheLut); + SafeRelease(ref midBlendLUT); + SafeRelease(ref defaultLut); + SafeRelease(ref depthCurveLut); + } + + public static bool ValidateLutDimensions(Texture lut) + { + bool result = true; + if (lut != null) + { + if (lut.width / lut.height != lut.height) + { + Debug.LogWarning("[AmplifyColor] Lut " + lut.name + " has invalid dimensions."); + result = false; + } + else if (lut.anisoLevel != 0) + { + lut.anisoLevel = 0; + } + } + return result; + } + + private void UpdatePostEffectParams() + { + if (UseDepthMask) + { + CheckUpdateDepthCurveLut(); + } + Exposure = Mathf.Max(Exposure, 0f); + } + + private int ComputeShaderPass() + { + bool flag = QualityLevel == Quality.Mobile; + bool flag2 = colorSpace == ColorSpace.Linear; + bool allowHDR = ownerCamera.allowHDR; + int num = (flag ? 18 : 0); + if (allowHDR) + { + num += 2; + num += (flag2 ? 8 : 0); + num += (ApplyDithering ? 4 : 0); + return (int)(num + Tonemapper); + } + return num + (flag2 ? 1 : 0); + } + + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + if (silentError) + { + Graphics.Blit(source, destination); + return; + } + BlendAmount = Mathf.Clamp01(BlendAmount); + if (colorSpace != QualitySettings.activeColorSpace || qualityLevel != QualityLevel) + { + CreateMaterials(); + } + UpdatePostEffectParams(); + bool num = ValidateLutDimensions(LutTexture); + bool flag = ValidateLutDimensions(LutBlendTexture); + bool flag2 = LutTexture == null && LutBlendTexture == null && volumesLutBlendTexture == null; + Texture texture = ((LutTexture == null) ? defaultLut : LutTexture); + Texture lutBlendTexture = LutBlendTexture; + int pass = ComputeShaderPass(); + bool flag3 = BlendAmount != 0f || blending; + bool flag4 = flag3 || (flag3 && lutBlendTexture != null); + bool flag5 = flag4; + bool num2 = !num || !flag || flag2; + Material material = (num2 ? materialProcessOnly : ((flag4 || volumesBlending) ? ((!UseDepthMask) ? ((MaskTexture != null) ? materialMaskBlend : materialBlend) : materialDepthMaskBlend) : ((!UseDepthMask) ? ((MaskTexture != null) ? materialMask : materialBase) : materialDepthMask))); + material.SetFloat("_Exposure", Exposure); + material.SetFloat("_ShoulderStrength", 0.22f); + material.SetFloat("_LinearStrength", 0.3f); + material.SetFloat("_LinearAngle", 0.1f); + material.SetFloat("_ToeStrength", 0.2f); + material.SetFloat("_ToeNumerator", 0.01f); + material.SetFloat("_ToeDenominator", 0.3f); + material.SetFloat("_LinearWhite", LinearWhitePoint); + material.SetFloat("_LerpAmount", BlendAmount); + if (MaskTexture != null) + { + material.SetTexture("_MaskTex", MaskTexture); + } + if (UseDepthMask) + { + material.SetTexture("_DepthCurveLut", depthCurveLut); + } + if (MaskTexture != null && source.dimension == TextureDimension.Tex2DArray) + { + material.SetVector("_StereoScale", new Vector4(0.5f, 1f, 0.5f, 0f)); + } + else + { + material.SetVector("_StereoScale", new Vector4(1f, 1f, 0f, 0f)); + } + if (!num2) + { + if (volumesBlending) + { + volumesBlendAmount = Mathf.Clamp01(volumesBlendAmount); + materialBlendCache.SetFloat("_LerpAmount", volumesBlendAmount); + if (blendingFromMidBlend) + { + materialBlendCache.SetTexture("_RgbTex", midBlendLUT); + } + else + { + materialBlendCache.SetTexture("_RgbTex", texture); + } + materialBlendCache.SetTexture("_LerpRgbTex", (volumesLutBlendTexture != null) ? volumesLutBlendTexture : defaultLut); + Graphics.Blit(texture, blendCacheLut, materialBlendCache); + } + if (flag5) + { + materialBlendCache.SetFloat("_LerpAmount", BlendAmount); + RenderTexture renderTexture = null; + if (volumesBlending) + { + renderTexture = RenderTexture.GetTemporary(blendCacheLut.width, blendCacheLut.height, blendCacheLut.depth, blendCacheLut.format, RenderTextureReadWrite.Linear); + Graphics.Blit(blendCacheLut, renderTexture); + materialBlendCache.SetTexture("_RgbTex", renderTexture); + } + else + { + materialBlendCache.SetTexture("_RgbTex", texture); + } + materialBlendCache.SetTexture("_LerpRgbTex", (lutBlendTexture != null) ? lutBlendTexture : defaultLut); + Graphics.Blit(texture, blendCacheLut, materialBlendCache); + if (renderTexture != null) + { + RenderTexture.ReleaseTemporary(renderTexture); + } + material.SetTexture("_RgbBlendCacheTex", blendCacheLut); + } + else if (volumesBlending) + { + material.SetTexture("_RgbBlendCacheTex", blendCacheLut); + } + else + { + if (texture != null) + { + material.SetTexture("_RgbTex", texture); + } + if (lutBlendTexture != null) + { + material.SetTexture("_LerpRgbTex", lutBlendTexture); + } + } + } + Graphics.Blit(source, destination, material, pass); + if (flag5 || volumesBlending) + { + blendCacheLut.DiscardContents(); + } + } +} diff --git a/ROUNDS/AmplifyColorEffect.cs b/ROUNDS/AmplifyColorEffect.cs new file mode 100644 index 0000000..ca37822 --- /dev/null +++ b/ROUNDS/AmplifyColorEffect.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +[ImageEffectAllowedInSceneView] +[ImageEffectTransformsToLDR] +[ExecuteInEditMode] +[AddComponentMenu("Image Effects/Amplify Color")] +public sealed class AmplifyColorEffect : AmplifyColorBase +{ +} diff --git a/ROUNDS/AmplifyColorRenderMask.cs b/ROUNDS/AmplifyColorRenderMask.cs new file mode 100644 index 0000000..8890a0e --- /dev/null +++ b/ROUNDS/AmplifyColorRenderMask.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +[ExecuteInEditMode] +[RequireComponent(typeof(Camera))] +[RequireComponent(typeof(AmplifyColorEffect))] +[AddComponentMenu("Image Effects/Amplify Color Render Mask")] +public class AmplifyColorRenderMask : AmplifyColorRenderMaskBase +{ +} diff --git a/ROUNDS/AmplifyColorRenderMaskBase.cs b/ROUNDS/AmplifyColorRenderMaskBase.cs new file mode 100644 index 0000000..589c64a --- /dev/null +++ b/ROUNDS/AmplifyColorRenderMaskBase.cs @@ -0,0 +1,174 @@ +using AmplifyColor; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.XR; + +[ExecuteInEditMode] +[RequireComponent(typeof(Camera))] +[AddComponentMenu("")] +public class AmplifyColorRenderMaskBase : MonoBehaviour +{ + [FormerlySerializedAs("clearColor")] + public Color ClearColor = Color.black; + + [FormerlySerializedAs("renderLayers")] + public RenderLayer[] RenderLayers = new RenderLayer[0]; + + [FormerlySerializedAs("debug")] + public bool DebugMask; + + private Camera referenceCamera; + + private Camera maskCamera; + + private AmplifyColorBase colorEffect; + + private int width; + + private int height; + + private RenderTexture maskTexture; + + private Shader colorMaskShader; + + private bool singlePassStereo; + + private void OnEnable() + { + if (maskCamera == null) + { + GameObject gameObject = new GameObject("Mask Camera", typeof(Camera)) + { + hideFlags = HideFlags.HideAndDontSave + }; + gameObject.transform.parent = base.gameObject.transform; + maskCamera = gameObject.GetComponent<Camera>(); + } + referenceCamera = GetComponent<Camera>(); + colorEffect = GetComponent<AmplifyColorBase>(); + colorMaskShader = Shader.Find("Hidden/RenderMask"); + } + + private void OnDisable() + { + DestroyCamera(); + DestroyRenderTextures(); + } + + private void DestroyCamera() + { + if (maskCamera != null) + { + Object.DestroyImmediate(maskCamera.gameObject); + maskCamera = null; + } + } + + private void DestroyRenderTextures() + { + if (maskTexture != null) + { + RenderTexture.active = null; + Object.DestroyImmediate(maskTexture); + maskTexture = null; + } + } + + private void UpdateRenderTextures(bool singlePassStereo) + { + int num = referenceCamera.pixelWidth; + int num2 = referenceCamera.pixelHeight; + if (maskTexture == null || width != num || height != num2 || !maskTexture.IsCreated() || this.singlePassStereo != singlePassStereo) + { + width = num; + height = num2; + DestroyRenderTextures(); + if (XRSettings.enabled) + { + num = XRSettings.eyeTextureWidth * ((!singlePassStereo) ? 1 : 2); + num2 = XRSettings.eyeTextureHeight; + } + if (maskTexture == null) + { + maskTexture = new RenderTexture(num, num2, 24, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB) + { + hideFlags = HideFlags.HideAndDontSave, + name = "MaskTexture" + }; + maskTexture.name = "AmplifyColorMaskTexture"; + bool allowMSAA = maskCamera.allowMSAA; + maskTexture.antiAliasing = ((!allowMSAA || QualitySettings.antiAliasing <= 0) ? 1 : QualitySettings.antiAliasing); + } + maskTexture.Create(); + this.singlePassStereo = singlePassStereo; + } + if (colorEffect != null) + { + colorEffect.MaskTexture = maskTexture; + } + } + + private void UpdateCameraProperties() + { + maskCamera.CopyFrom(referenceCamera); + maskCamera.targetTexture = maskTexture; + maskCamera.clearFlags = CameraClearFlags.Nothing; + maskCamera.renderingPath = RenderingPath.VertexLit; + maskCamera.pixelRect = new Rect(0f, 0f, width, height); + maskCamera.depthTextureMode = DepthTextureMode.None; + maskCamera.allowHDR = false; + maskCamera.enabled = false; + } + + private void OnPreRender() + { + if (!(maskCamera != null)) + { + return; + } + RenderBuffer activeColorBuffer = Graphics.activeColorBuffer; + RenderBuffer activeDepthBuffer = Graphics.activeDepthBuffer; + bool flag = false; + if (referenceCamera.stereoEnabled) + { + flag = XRSettings.eyeTextureDesc.vrUsage == VRTextureUsage.TwoEyes; + maskCamera.SetStereoViewMatrix(Camera.StereoscopicEye.Left, referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Left)); + maskCamera.SetStereoViewMatrix(Camera.StereoscopicEye.Right, referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Right)); + maskCamera.SetStereoProjectionMatrix(Camera.StereoscopicEye.Left, referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left)); + maskCamera.SetStereoProjectionMatrix(Camera.StereoscopicEye.Right, referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right)); + } + UpdateRenderTextures(flag); + UpdateCameraProperties(); + Graphics.SetRenderTarget(maskTexture); + GL.Clear(clearDepth: true, clearColor: true, ClearColor); + if (flag) + { + maskCamera.worldToCameraMatrix = referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Left); + maskCamera.projectionMatrix = referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left); + maskCamera.rect = new Rect(0f, 0f, 0.5f, 1f); + } + RenderLayer[] renderLayers = RenderLayers; + for (int i = 0; i < renderLayers.Length; i++) + { + RenderLayer renderLayer = renderLayers[i]; + Shader.SetGlobalColor("_COLORMASK_Color", renderLayer.color); + maskCamera.cullingMask = renderLayer.mask; + maskCamera.RenderWithShader(colorMaskShader, "RenderType"); + } + if (flag) + { + maskCamera.worldToCameraMatrix = referenceCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Right); + maskCamera.projectionMatrix = referenceCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right); + maskCamera.rect = new Rect(0.5f, 0f, 0.5f, 1f); + renderLayers = RenderLayers; + for (int i = 0; i < renderLayers.Length; i++) + { + RenderLayer renderLayer2 = renderLayers[i]; + Shader.SetGlobalColor("_COLORMASK_Color", renderLayer2.color); + maskCamera.cullingMask = renderLayer2.mask; + maskCamera.RenderWithShader(colorMaskShader, "RenderType"); + } + } + Graphics.SetRenderTarget(activeColorBuffer, activeDepthBuffer); + } +} diff --git a/ROUNDS/AmplifyColorTriggerProxy.cs b/ROUNDS/AmplifyColorTriggerProxy.cs new file mode 100644 index 0000000..916f8f1 --- /dev/null +++ b/ROUNDS/AmplifyColorTriggerProxy.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +[RequireComponent(typeof(Rigidbody))] +[RequireComponent(typeof(SphereCollider))] +[AddComponentMenu("")] +public class AmplifyColorTriggerProxy : AmplifyColorTriggerProxyBase +{ + private SphereCollider sphereCollider; + + private Rigidbody rigidBody; + + private void Start() + { + sphereCollider = GetComponent<SphereCollider>(); + sphereCollider.radius = 0.01f; + sphereCollider.isTrigger = true; + rigidBody = GetComponent<Rigidbody>(); + rigidBody.useGravity = false; + rigidBody.isKinematic = true; + } + + private void LateUpdate() + { + base.transform.position = Reference.position; + base.transform.rotation = Reference.rotation; + } +} diff --git a/ROUNDS/AmplifyColorTriggerProxy2D.cs b/ROUNDS/AmplifyColorTriggerProxy2D.cs new file mode 100644 index 0000000..c4bc606 --- /dev/null +++ b/ROUNDS/AmplifyColorTriggerProxy2D.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +[RequireComponent(typeof(Rigidbody2D))] +[RequireComponent(typeof(CircleCollider2D))] +[AddComponentMenu("")] +public class AmplifyColorTriggerProxy2D : AmplifyColorTriggerProxyBase +{ + private CircleCollider2D circleCollider; + + private Rigidbody2D rigidBody; + + private void Start() + { + circleCollider = GetComponent<CircleCollider2D>(); + circleCollider.radius = 0.01f; + circleCollider.isTrigger = true; + rigidBody = GetComponent<Rigidbody2D>(); + rigidBody.gravityScale = 0f; + rigidBody.isKinematic = true; + } + + private void LateUpdate() + { + base.transform.position = Reference.position; + base.transform.rotation = Reference.rotation; + } +} diff --git a/ROUNDS/AmplifyColorTriggerProxyBase.cs b/ROUNDS/AmplifyColorTriggerProxyBase.cs new file mode 100644 index 0000000..efb1cac --- /dev/null +++ b/ROUNDS/AmplifyColorTriggerProxyBase.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +[AddComponentMenu("")] +public class AmplifyColorTriggerProxyBase : MonoBehaviour +{ + public Transform Reference; + + public AmplifyColorBase OwnerEffect; +} diff --git a/ROUNDS/AmplifyColorVolume.cs b/ROUNDS/AmplifyColorVolume.cs new file mode 100644 index 0000000..e616e57 --- /dev/null +++ b/ROUNDS/AmplifyColorVolume.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +[RequireComponent(typeof(BoxCollider))] +[AddComponentMenu("Image Effects/Amplify Color Volume")] +public class AmplifyColorVolume : AmplifyColorVolumeBase +{ + private void OnTriggerEnter(Collider other) + { + AmplifyColorTriggerProxy component = other.GetComponent<AmplifyColorTriggerProxy>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.EnterVolume(this); + } + } + + private void OnTriggerExit(Collider other) + { + AmplifyColorTriggerProxy component = other.GetComponent<AmplifyColorTriggerProxy>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.ExitVolume(this); + } + } +} diff --git a/ROUNDS/AmplifyColorVolume2D.cs b/ROUNDS/AmplifyColorVolume2D.cs new file mode 100644 index 0000000..3dd0bbd --- /dev/null +++ b/ROUNDS/AmplifyColorVolume2D.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +[RequireComponent(typeof(BoxCollider2D))] +[AddComponentMenu("Image Effects/Amplify Color Volume 2D")] +public class AmplifyColorVolume2D : AmplifyColorVolumeBase +{ + private void OnTriggerEnter2D(Collider2D other) + { + AmplifyColorTriggerProxy2D component = other.GetComponent<AmplifyColorTriggerProxy2D>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.EnterVolume(this); + } + } + + private void OnTriggerExit2D(Collider2D other) + { + AmplifyColorTriggerProxy2D component = other.GetComponent<AmplifyColorTriggerProxy2D>(); + if (component != null && component.OwnerEffect.UseVolumes && ((int)component.OwnerEffect.VolumeCollisionMask & (1 << base.gameObject.layer)) != 0) + { + component.OwnerEffect.ExitVolume(this); + } + } +} diff --git a/ROUNDS/AmplifyColorVolumeBase.cs b/ROUNDS/AmplifyColorVolumeBase.cs new file mode 100644 index 0000000..b241f7f --- /dev/null +++ b/ROUNDS/AmplifyColorVolumeBase.cs @@ -0,0 +1,74 @@ +using AmplifyColor; +using UnityEngine; + +[ExecuteInEditMode] +[AddComponentMenu("")] +public class AmplifyColorVolumeBase : MonoBehaviour +{ + public Texture2D LutTexture; + + public float Exposure = 1f; + + public float EnterBlendTime = 1f; + + public int Priority; + + public bool ShowInSceneView = true; + + [HideInInspector] + public VolumeEffectContainer EffectContainer = new VolumeEffectContainer(); + + private void OnDrawGizmos() + { + if (!ShowInSceneView) + { + return; + } + BoxCollider component = GetComponent<BoxCollider>(); + BoxCollider2D component2 = GetComponent<BoxCollider2D>(); + if (component != null || component2 != null) + { + Vector3 center; + Vector3 size; + if (component != null) + { + center = component.center; + size = component.size; + } + else + { + center = component2.offset; + size = component2.size; + } + Gizmos.color = Color.green; + Gizmos.matrix = base.transform.localToWorldMatrix; + Gizmos.DrawWireCube(center, size); + } + } + + private void OnDrawGizmosSelected() + { + BoxCollider component = GetComponent<BoxCollider>(); + BoxCollider2D component2 = GetComponent<BoxCollider2D>(); + if (component != null || component2 != null) + { + Color green = Color.green; + green.a = 0.2f; + Gizmos.color = green; + Gizmos.matrix = base.transform.localToWorldMatrix; + Vector3 center; + Vector3 size; + if (component != null) + { + center = component.center; + size = component.size; + } + else + { + center = component2.offset; + size = component2.size; + } + Gizmos.DrawCube(center, size); + } + } +} diff --git a/ROUNDS/ApplyCardStats.cs b/ROUNDS/ApplyCardStats.cs new file mode 100644 index 0000000..378db39 --- /dev/null +++ b/ROUNDS/ApplyCardStats.cs @@ -0,0 +1,305 @@ +using System.Collections.Generic; +using Photon.Pun; +using UnityEngine; + +public class ApplyCardStats : MonoBehaviour +{ + private Gun myGunStats; + + private CharacterStatModifiers myPlayerStats; + + private Block myBlock; + + private Player playerToUpgrade; + + private CardAudioModifier cardAudio; + + private bool done; + + private DamagableEvent damagable; + + public bool shootToPick; + + private void Start() + { + myGunStats = GetComponent<Gun>(); + myPlayerStats = GetComponent<CharacterStatModifiers>(); + myBlock = GetComponentInChildren<Block>(); + cardAudio = GetComponent<CardAudioModifier>(); + damagable = GetComponentInChildren<DamagableEvent>(); + } + + private void Update() + { + if (shootToPick && damagable.dead && (bool)damagable.lastPlayer) + { + Pick(damagable.lastPlayer.teamID); + Object.Destroy(base.gameObject); + } + } + + [PunRPC] + public void RPCA_Pick(int[] actorIDs) + { + for (int i = 0; i < actorIDs.Length; i++) + { + playerToUpgrade = PlayerManager.instance.GetPlayerWithActorID(actorIDs[i]); + ApplyStats(); + CardBarHandler.instance.AddCard(playerToUpgrade.playerID, GetComponent<CardInfo>().sourceCard); + } + } + + [PunRPC] + public void OFFLINE_Pick(Player[] players) + { + for (int i = 0; i < players.Length; i++) + { + playerToUpgrade = players[i]; + ApplyStats(); + CardBarHandler.instance.AddCard(playerToUpgrade.playerID, GetComponent<CardInfo>().sourceCard); + } + } + + public void Pick(int pickerID, bool forcePick = false, PickerType pickerType = PickerType.Team) + { + Start(); + if (done && !forcePick) + { + return; + } + done = true; + Player[] array = PlayerManager.instance.GetPlayersInTeam(pickerID); + if (pickerType == PickerType.Player) + { + array = new Player[1] { PlayerManager.instance.players[pickerID] }; + } + if (PhotonNetwork.OfflineMode) + { + OFFLINE_Pick(array); + return; + } + int[] array2 = new int[array.Length]; + for (int i = 0; i < array.Length; i++) + { + array2[i] = array[i].data.view.ControllerActorNr; + } + GetComponent<PhotonView>().RPC("RPCA_Pick", RpcTarget.All, array2); + } + + private void ApplyStats() + { + done = true; + PlayerAudioModifyers component = playerToUpgrade.GetComponent<PlayerAudioModifyers>(); + Gun component2 = playerToUpgrade.GetComponent<Holding>().holdable.GetComponent<Gun>(); + Player component3 = playerToUpgrade.GetComponent<Player>(); + CharacterData component4 = playerToUpgrade.GetComponent<CharacterData>(); + HealthHandler component5 = playerToUpgrade.GetComponent<HealthHandler>(); + playerToUpgrade.GetComponent<Movement>(); + Gravity component6 = playerToUpgrade.GetComponent<Gravity>(); + Block component7 = playerToUpgrade.GetComponent<Block>(); + CharacterStatModifiers component8 = component3.GetComponent<CharacterStatModifiers>(); + GunAmmo componentInChildren = component2.GetComponentInChildren<GunAmmo>(); + if ((bool)componentInChildren && (bool)myGunStats) + { + componentInChildren.ammoReg += myGunStats.ammoReg; + componentInChildren.maxAmmo += myGunStats.ammo; + componentInChildren.maxAmmo = Mathf.Clamp(componentInChildren.maxAmmo, 1, 90); + componentInChildren.reloadTimeMultiplier *= myGunStats.reloadTime; + componentInChildren.reloadTimeAdd += myGunStats.reloadTimeAdd; + } + component3.data.currentCards.Add(GetComponent<CardInfo>().sourceCard); + if ((bool)myGunStats) + { + if (myGunStats.lockGunToDefault) + { + component2.defaultCooldown = myGunStats.forceSpecificAttackSpeed; + component2.lockGunToDefault = myGunStats.lockGunToDefault; + } + if ((bool)myGunStats && myGunStats.projectiles.Length != 0) + { + component2.projectiles[0].objectToSpawn = myGunStats.projectiles[0].objectToSpawn; + } + if ((bool)myGunStats) + { + CopyGunStats(myGunStats, component2); + } + } + if ((bool)myPlayerStats) + { + component8.sizeMultiplier *= myPlayerStats.sizeMultiplier; + component4.maxHealth *= myPlayerStats.health; + component8.ConfigureMassAndSize(); + component8.movementSpeed *= myPlayerStats.movementSpeed; + component8.jump *= myPlayerStats.jump; + component4.jumps += myPlayerStats.numberOfJumps; + component6.gravityForce *= myPlayerStats.gravity; + component5.regeneration += myPlayerStats.regen; + if ((bool)myPlayerStats.AddObjectToPlayer) + { + component8.objectsAddedToPlayer.Add(Object.Instantiate(myPlayerStats.AddObjectToPlayer, component3.transform.position, component3.transform.rotation, component3.transform)); + } + component8.lifeSteal += myPlayerStats.lifeSteal; + component8.respawns += myPlayerStats.respawns; + component8.secondsToTakeDamageOver += myPlayerStats.secondsToTakeDamageOver; + if (myPlayerStats.refreshOnDamage) + { + component8.refreshOnDamage = true; + } + if (!myPlayerStats.automaticReload) + { + component8.automaticReload = false; + } + } + if ((bool)myBlock) + { + if (myBlock.objectsToSpawn != null) + { + for (int i = 0; i < myBlock.objectsToSpawn.Count; i++) + { + component7.objectsToSpawn.Add(myBlock.objectsToSpawn[i]); + } + } + component7.cdMultiplier *= myBlock.cdMultiplier; + component7.cdAdd += myBlock.cdAdd; + component7.forceToAdd += myBlock.forceToAdd; + component7.forceToAddUp += myBlock.forceToAddUp; + component7.additionalBlocks += myBlock.additionalBlocks; + component7.healing += myBlock.healing; + if (myBlock.autoBlock) + { + component7.autoBlock = myBlock.autoBlock; + } + } + if ((bool)component && (bool)cardAudio) + { + component.AddToStack(cardAudio); + } + component8.WasUpdated(); + component5.Revive(); + } + + public static void CopyGunStats(Gun copyFromGun, Gun copyToGun) + { + if (copyFromGun.unblockable) + { + copyToGun.unblockable = copyFromGun.unblockable; + } + if (copyFromGun.ignoreWalls) + { + copyToGun.ignoreWalls = copyFromGun.ignoreWalls; + } + float num = 1f; + if (copyFromGun.numberOfProjectiles != 0 && copyToGun.numberOfProjectiles != 1) + { + num = (float)copyFromGun.numberOfProjectiles / ((float)copyFromGun.numberOfProjectiles + (float)copyToGun.numberOfProjectiles); + } + copyToGun.damage *= 1f - num * (1f - copyFromGun.damage); + if (copyToGun.damage < 0.25f) + { + copyToGun.damage = 0.25f; + } + copyToGun.size += copyFromGun.size; + float num2 = 1f; + if (copyFromGun.chargeNumberOfProjectilesTo != 0f) + { + num2 = copyFromGun.chargeNumberOfProjectilesTo / (copyFromGun.chargeNumberOfProjectilesTo + copyToGun.chargeNumberOfProjectilesTo); + } + copyToGun.chargeDamageMultiplier *= 1f - num2 * (1f - copyFromGun.chargeDamageMultiplier); + copyToGun.knockback *= 1f - num * (1f - copyFromGun.knockback); + copyToGun.projectileSpeed *= copyFromGun.projectileSpeed; + copyToGun.projectielSimulatonSpeed *= copyFromGun.projectielSimulatonSpeed; + copyToGun.gravity *= copyFromGun.gravity; + copyToGun.multiplySpread *= copyFromGun.multiplySpread; + copyToGun.attackSpeed *= copyFromGun.attackSpeed; + copyToGun.bodyRecoil *= copyFromGun.recoilMuiltiplier; + copyToGun.speedMOnBounce *= copyFromGun.speedMOnBounce; + copyToGun.dmgMOnBounce *= copyFromGun.dmgMOnBounce; + copyToGun.bulletDamageMultiplier *= copyFromGun.bulletDamageMultiplier; + copyToGun.spread += copyFromGun.spread; + copyToGun.drag += copyFromGun.drag; + copyToGun.timeBetweenBullets += copyFromGun.timeBetweenBullets; + copyToGun.dragMinSpeed += copyFromGun.dragMinSpeed; + copyToGun.evenSpread += copyFromGun.evenSpread; + copyToGun.numberOfProjectiles += copyFromGun.numberOfProjectiles; + copyToGun.reflects += copyFromGun.reflects; + copyToGun.smartBounce += copyFromGun.smartBounce; + copyToGun.bulletPortal += copyFromGun.bulletPortal; + copyToGun.randomBounces += copyFromGun.randomBounces; + copyToGun.bursts += copyFromGun.bursts; + copyToGun.slow += copyFromGun.slow; + copyToGun.overheatMultiplier += copyFromGun.overheatMultiplier; + copyToGun.projectileSize += copyFromGun.projectileSize; + copyToGun.percentageDamage += copyFromGun.percentageDamage; + copyToGun.damageAfterDistanceMultiplier *= copyFromGun.damageAfterDistanceMultiplier; + copyToGun.timeToReachFullMovementMultiplier *= copyFromGun.timeToReachFullMovementMultiplier; + copyToGun.cos += copyFromGun.cos; + if (copyFromGun.dontAllowAutoFire) + { + copyToGun.dontAllowAutoFire = true; + } + if (copyFromGun.destroyBulletAfter != 0f) + { + copyToGun.destroyBulletAfter = copyFromGun.destroyBulletAfter; + } + copyToGun.chargeSpreadTo += copyFromGun.chargeSpreadTo; + copyToGun.chargeSpeedTo += copyFromGun.chargeSpeedTo; + copyToGun.chargeEvenSpreadTo += copyFromGun.chargeEvenSpreadTo; + copyToGun.chargeNumberOfProjectilesTo += copyFromGun.chargeNumberOfProjectilesTo; + copyToGun.chargeRecoilTo += copyFromGun.chargeRecoilTo; + if (copyFromGun.projectileColor != Color.black) + { + if (copyToGun.projectileColor == Color.black) + { + copyToGun.projectileColor = copyFromGun.projectileColor; + } + float r = Mathf.Pow((copyToGun.projectileColor.r * copyToGun.projectileColor.r + copyFromGun.projectileColor.r * copyFromGun.projectileColor.r) / 2f, 0.5f); + float g = Mathf.Pow((copyToGun.projectileColor.g * copyToGun.projectileColor.g + copyFromGun.projectileColor.g * copyFromGun.projectileColor.g) / 2f, 0.5f); + float b = Mathf.Pow((copyToGun.projectileColor.b * copyToGun.projectileColor.b + copyFromGun.projectileColor.b * copyFromGun.projectileColor.b) / 2f, 0.5f); + Color rgbColor = new Color(r, g, b, 1f); + float H = 0f; + float S = 0f; + float V = 0f; + Color.RGBToHSV(rgbColor, out H, out S, out V); + S = 1f; + V = 1f; + copyToGun.projectileColor = Color.HSVToRGB(H, S, V); + } + List<ObjectsToSpawn> list = new List<ObjectsToSpawn>(); + for (int i = 0; i < copyToGun.objectsToSpawn.Length; i++) + { + list.Add(copyToGun.objectsToSpawn[i]); + } + for (int j = 0; j < copyFromGun.objectsToSpawn.Length; j++) + { + bool flag = false; + for (int k = 0; k < list.Count; k++) + { + if ((bool)list[k].effect && (bool)copyFromGun.objectsToSpawn[j].effect) + { + if (list[k].effect.name == copyFromGun.objectsToSpawn[j].effect.name && list[k].scaleStacks) + { + list[k].stacks++; + flag = true; + } + } + else if ((bool)list[k].AddToProjectile && (bool)copyFromGun.objectsToSpawn[j].AddToProjectile && list[k].AddToProjectile.name == copyFromGun.objectsToSpawn[j].AddToProjectile.name && list[k].scaleStacks) + { + list[k].stacks++; + flag = true; + } + } + if (!flag) + { + list.Add(copyFromGun.objectsToSpawn[j]); + } + } + copyToGun.objectsToSpawn = list.ToArray(); + if (copyFromGun.useCharge) + { + copyToGun.useCharge = copyFromGun.useCharge; + } + copyToGun.soundGun.AddSoundShotModifier(copyFromGun.soundShotModifier); + copyToGun.soundGun.AddSoundImpactModifier(copyFromGun.soundImpactModifier); + copyToGun.soundGun.RefreshSoundModifiers(); + } +} diff --git a/ROUNDS/ApplyRootScale.cs b/ROUNDS/ApplyRootScale.cs new file mode 100644 index 0000000..36ef87a --- /dev/null +++ b/ROUNDS/ApplyRootScale.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class ApplyRootScale : MonoBehaviour +{ + public float amount = 0.5f; + + private void Start() + { + base.transform.localScale = Vector3.Lerp(base.transform.localScale, base.transform.root.localScale, amount); + } +} diff --git a/ROUNDS/ArmRotator.cs b/ROUNDS/ArmRotator.cs new file mode 100644 index 0000000..a8f02a9 --- /dev/null +++ b/ROUNDS/ArmRotator.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class ArmRotator : MonoBehaviour +{ + public Vector3 rotation; + + private void Start() + { + base.transform.localEulerAngles = rotation; + } +} diff --git a/ROUNDS/ArtHandler.cs b/ROUNDS/ArtHandler.cs new file mode 100644 index 0000000..1421de0 --- /dev/null +++ b/ROUNDS/ArtHandler.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class ArtHandler : MonoBehaviour +{ + public ArtInstance[] arts; + + public PostProcessVolume volume; + + public static ArtHandler instance; + + private ColorGrading colorGrading; + + private int currentArt = -1; + + private void Awake() + { + instance = this; + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.LeftShift)) + { + NextArt(); + } + } + + public void NextArt() + { + for (int i = 0; i < arts.Length; i++) + { + arts[i].TogglePart(on: false); + } + int num = Random.Range(0, arts.Length); + if (num >= arts.Length) + { + num = 0; + } + ApplyArt(arts[num]); + } + + private void ApplyArt(ArtInstance art) + { + art.TogglePart(on: true); + currentArt = GetArtID(art); + volume.profile = art.profile; + } + + public void SetSpecificArt(ArtInstance art) + { + ApplyArt(art); + } + + public void ApplyPost(PostProcessProfile profileToSet) + { + volume.profile = profileToSet; + } + + public void SetSpecificArt(string artName) + { + for (int i = 0; i < arts.Length; i++) + { + if (arts[i].profile.name == artName) + { + ApplyArt(arts[i]); + break; + } + } + } + + private int GetArtID(ArtInstance art) + { + int result = -1; + for (int i = 0; i < arts.Length; i++) + { + if (art == arts[i]) + { + result = i; + } + } + return result; + } +} diff --git a/ROUNDS/ArtInstance.cs b/ROUNDS/ArtInstance.cs new file mode 100644 index 0000000..49c24b3 --- /dev/null +++ b/ROUNDS/ArtInstance.cs @@ -0,0 +1,23 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +[Serializable] +public class ArtInstance +{ + [FoldoutGroup("$profile", 0)] + public PostProcessProfile profile; + + [FoldoutGroup("$profile", 0)] + public ParticleSystem[] parts; + + public void TogglePart(bool on) + { + for (int i = 0; i < parts.Length; i++) + { + parts[i].gameObject.SetActive(on); + parts[i].Play(); + } + } +} diff --git a/ROUNDS/AttackLevel.cs b/ROUNDS/AttackLevel.cs new file mode 100644 index 0000000..78c92dd --- /dev/null +++ b/ROUNDS/AttackLevel.cs @@ -0,0 +1,53 @@ +using System; +using UnityEngine; + +public class AttackLevel : MonoBehaviour +{ + public int attackLevel = 1; + + public float levelScaleM = 0.7f; + + public Action<int> LevelUpAction; + + private void Start() + { + SpawnedAttack componentInParent = GetComponentInParent<SpawnedAttack>(); + if ((bool)componentInParent) + { + attackLevel = componentInParent.attackLevel; + } + bool flag = false; + AttackLevel[] componentsInChildren = base.transform.root.GetComponentsInChildren<AttackLevel>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (!(componentsInChildren[i] == this) && componentsInChildren[i].gameObject.name == base.gameObject.name) + { + componentsInChildren[i].LevelUp(); + flag = true; + } + } + if (flag) + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + public float LevelScale() + { + return 1f + ((float)attackLevel - 1f) * levelScaleM; + } + + public int LevelsUp() + { + return attackLevel - 1; + } + + public void LevelUp() + { + attackLevel++; + if (LevelUpAction != null) + { + LevelUpAction(attackLevel); + } + } +} diff --git a/ROUNDS/AttackTrigger.cs b/ROUNDS/AttackTrigger.cs new file mode 100644 index 0000000..a452de0 --- /dev/null +++ b/ROUNDS/AttackTrigger.cs @@ -0,0 +1,43 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class AttackTrigger : MonoBehaviour +{ + public bool triggerOnEveryShot = true; + + public UnityEvent triggerEvent; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(gun.ShootPojectileAction, new Action<GameObject>(Shoot)); + data.weaponHandler.gun.AddAttackAction(Attack); + } + + private void OnDestroy() + { + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Remove(gun.ShootPojectileAction, new Action<GameObject>(Shoot)); + data.weaponHandler.gun.RemoveAttackAction(Attack); + } + + public void Attack() + { + if (!triggerOnEveryShot) + { + triggerEvent.Invoke(); + } + } + + public void Shoot(GameObject projectile) + { + if (triggerOnEveryShot) + { + triggerEvent.Invoke(); + } + } +} diff --git a/ROUNDS/AudioModifyer.cs b/ROUNDS/AudioModifyer.cs new file mode 100644 index 0000000..ddfaad9 --- /dev/null +++ b/ROUNDS/AudioModifyer.cs @@ -0,0 +1,9 @@ +using System; + +[Serializable] +public class AudioModifyer +{ + public CardAudioModifier modifier; + + public int stacks; +} diff --git a/ROUNDS/Background.cs b/ROUNDS/Background.cs new file mode 100644 index 0000000..0b694c7 --- /dev/null +++ b/ROUNDS/Background.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +public class Background : MonoBehaviour +{ + private ParticleSystem[] parts; + + private bool hasBeenInitiated; + + private void Init() + { + parts = GetComponentsInChildren<ParticleSystem>(); + hasBeenInitiated = true; + } + + public void ToggleBackground(bool on) + { + if (!hasBeenInitiated) + { + Init(); + } + for (int i = 0; i < parts.Length; i++) + { + if (on) + { + parts[i].Play(); + } + else + { + parts[i].Stop(); + } + } + } +} diff --git a/ROUNDS/BackgroundHandler.cs b/ROUNDS/BackgroundHandler.cs new file mode 100644 index 0000000..90823de --- /dev/null +++ b/ROUNDS/BackgroundHandler.cs @@ -0,0 +1,39 @@ +using System.Collections; +using UnityEngine; + +public class BackgroundHandler : MonoBehaviour +{ + private Background[] backgrounds; + + private float untilSwitch; + + private void Start() + { + backgrounds = GetComponentsInChildren<Background>(includeInactive: true); + } + + private void Update() + { + untilSwitch -= TimeHandler.deltaTime; + if (untilSwitch < 0f) + { + SwitchBackground(); + } + } + + private void SwitchBackground() + { + untilSwitch = Random.Range(30, 60); + for (int i = 0; i < backgrounds.Length; i++) + { + backgrounds[i].ToggleBackground(on: false); + } + StartCoroutine(StartBackGroundSoon()); + } + + private IEnumerator StartBackGroundSoon() + { + yield return new WaitForSeconds(5f); + backgrounds[Random.Range(0, backgrounds.Length)].ToggleBackground(on: true); + } +} diff --git a/ROUNDS/BeamAttack.cs b/ROUNDS/BeamAttack.cs new file mode 100644 index 0000000..a05ee28 --- /dev/null +++ b/ROUNDS/BeamAttack.cs @@ -0,0 +1,145 @@ +using System.Collections; +using UnityEngine; + +public class BeamAttack : MonoBehaviour +{ + public float selfHeal; + + public float damage = 8f; + + public float force = 2500f; + + public float scalingForce; + + public float overTimeForce; + + public float overTimeScalingForce; + + public float overTimeDrag; + + public float effectOverTimeTime = 0.1f; + + public float interval = 0.2f; + + public float slow; + + public float maxSlow = 1f; + + public Color dmgColor; + + private Player attacker; + + private Player thisPlayer; + + private LineEffect[] lineEffects; + + private ParticleSystem[] parts; + + private CharacterStatModifiers stats; + + private float scaleMultiplier = 1f; + + private SpawnedAttack spawnedAttack; + + private float counter; + + private void Start() + { + lineEffects = GetComponentsInChildren<LineEffect>(includeInactive: true); + parts = GetComponentsInChildren<ParticleSystem>(); + thisPlayer = GetComponentInParent<Player>(); + stats = thisPlayer.GetComponent<CharacterStatModifiers>(); + attacker = PlayerManager.instance.GetOtherPlayer(thisPlayer); + scaleMultiplier = base.transform.localScale.x; + spawnedAttack = GetComponentInParent<SpawnedAttack>(); + if (thisPlayer == spawnedAttack.spawner) + { + Object.Destroy(base.gameObject); + } + } + + private void Update() + { + if (!attacker || !thisPlayer) + { + return; + } + counter += TimeHandler.deltaTime; + if (!(counter > interval)) + { + return; + } + CanSeeInfo canSeeInfo = PlayerManager.instance.CanSeePlayer(attacker.transform.position, thisPlayer); + if (canSeeInfo.canSee) + { + Vector2 vector = thisPlayer.transform.position - attacker.transform.position; + Vector2 normalized = vector.normalized; + if (force != 0f) + { + thisPlayer.data.healthHandler.TakeForce(normalized * scaleMultiplier * force); + } + if (scalingForce != 0f) + { + thisPlayer.data.healthHandler.TakeForce(vector * scaleMultiplier * scalingForce); + } + if (damage != 0f) + { + thisPlayer.data.healthHandler.TakeDamage(damage * scaleMultiplier * normalized, base.transform.position, dmgColor, null, attacker); + } + if (selfHeal != 0f) + { + attacker.data.healthHandler.Heal(selfHeal * scaleMultiplier); + } + for (int i = 0; i < lineEffects.Length; i++) + { + lineEffects[i].Play(attacker.transform, thisPlayer.transform); + } + StartCoroutine(DoOverTimeEffects(attacker)); + if (slow > 0f && (bool)stats) + { + stats.AddSlowAddative(slow * scaleMultiplier, maxSlow); + } + } + else + { + for (int j = 0; j < lineEffects.Length; j++) + { + lineEffects[j].Play(attacker.transform, canSeeInfo.hitPoint); + } + for (int k = 0; k < parts.Length; k++) + { + parts[k].transform.position = canSeeInfo.hitPoint; + parts[k].transform.localScale = Vector3.one * scaleMultiplier; + parts[k].Play(); + } + } + counter = 0f; + } + + private IEnumerator DoOverTimeEffects(Player attacker) + { + float c = 0f; + while (c < effectOverTimeTime) + { + c += TimeHandler.deltaTime; + if ((bool)attacker && (bool)thisPlayer) + { + Vector2 vector = thisPlayer.transform.position - attacker.transform.position; + Vector2 normalized = vector.normalized; + if (overTimeForce != 0f) + { + thisPlayer.data.healthHandler.TakeForce(normalized * scaleMultiplier * TimeHandler.deltaTime * overTimeForce); + } + if (overTimeScalingForce != 0f) + { + thisPlayer.data.healthHandler.TakeForce(vector * scaleMultiplier * TimeHandler.deltaTime * overTimeScalingForce, ForceMode2D.Force); + } + if (overTimeDrag > 0f) + { + thisPlayer.data.playerVel.AddForce(-thisPlayer.data.playerVel.velocity * Mathf.Clamp(TimeHandler.deltaTime * scaleMultiplier * overTimeDrag, 0f, 0.95f), ForceMode2D.Force); + } + } + yield return null; + } + } +} diff --git a/ROUNDS/BezierCurve.cs b/ROUNDS/BezierCurve.cs new file mode 100644 index 0000000..5fb99b8 --- /dev/null +++ b/ROUNDS/BezierCurve.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public static class BezierCurve +{ + public static Vector3 CubicBezier(Vector3 Start, Vector3 _P1, Vector3 _P2, Vector3 end, float _t) + { + return (1f - _t) * QuadraticBezier(Start, _P1, _P2, _t) + _t * QuadraticBezier(_P1, _P2, end, _t); + } + + public static Vector3 QuadraticBezier(Vector3 start, Vector3 _P1, Vector3 end, float _t) + { + return (1f - _t) * LinearBezier(start, _P1, _t) + _t * LinearBezier(_P1, end, _t); + } + + public static Vector3 LinearBezier(Vector3 start, Vector3 end, float _t) + { + return (1f - _t) * start + _t * end; + } +} diff --git a/ROUNDS/BlinkStep.cs b/ROUNDS/BlinkStep.cs new file mode 100644 index 0000000..4a52737 --- /dev/null +++ b/ROUNDS/BlinkStep.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +public class BlinkStep : MonoBehaviour +{ + public float interval = 0.29f; + + private CharacterData data; + + private float counter; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + if (data.view.IsMine) + { + counter += TimeHandler.deltaTime; + if (counter > interval) + { + counter = 0f; + data.block.CallDoBlock(firstBlock: true, dontSetCD: true); + } + } + } +} diff --git a/ROUNDS/Block.cs b/ROUNDS/Block.cs new file mode 100644 index 0000000..b48d264 --- /dev/null +++ b/ROUNDS/Block.cs @@ -0,0 +1,353 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class Block : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundBlockStart; + + public SoundEvent soundBlockRecharged; + + public SoundEvent soundBlockBlocked; + + public SoundEvent soundBlockStatusEffect; + + [Header("Settings")] + public List<GameObject> objectsToSpawn = new List<GameObject>(); + + public float sinceBlock; + + private GeneralInput input; + + public ParticleSystem particle; + + public ParticleSystem reloadParticle; + + public ParticleSystem blockedPart; + + public float cooldown; + + public float counter = 1000f; + + public float cdMultiplier = 1f; + + public float cdAdd; + + public float forceToAdd; + + public float forceToAddUp; + + public bool autoBlock; + + public bool blockedThisFrame; + + public int additionalBlocks; + + public float healing; + + private float timeBetweenBlocks = 0.2f; + + private CharacterData data; + + private HealthHandler health; + + private bool active = true; + + public Action BlockRechargeAction; + + private bool blockedLastFrame; + + public Action<BlockTrigger.BlockTriggerType> BlockAction; + + public Action<BlockTrigger.BlockTriggerType> BlockActionEarly; + + public Action<BlockTrigger.BlockTriggerType> FirstBlockActionThatDelaysOthers; + + public Action<BlockTrigger.BlockTriggerType> SuperFirstBlockAction; + + public Vector3 blockedAtPos; + + public bool delayOtherActions; + + public ParticleSystem statusBlockPart; + + private float lastStatusBlock; + + public Action<GameObject, Vector3, Vector3> BlockProjectileAction; + + public float Cooldown() + { + return (cooldown + cdAdd) * cdMultiplier; + } + + private void Start() + { + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + health = GetComponent<HealthHandler>(); + sinceBlock = 100f; + } + + private void Update() + { + if ((bool)input && data.playerVel.simulated) + { + if (!blockedLastFrame) + { + blockedThisFrame = false; + } + blockedLastFrame = false; + sinceBlock += TimeHandler.deltaTime; + counter += TimeHandler.deltaTime; + if (counter > Cooldown() && !active) + { + active = true; + reloadParticle.Play(); + BlockRechargeAction(); + SoundManager.Instance.Play(soundBlockRecharged, base.transform); + } + if (input.shieldWasPressed) + { + TryBlock(); + } + } + } + + public void DoBlockAtPosition(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 blockPos = default(Vector3), bool onlyBlockEffects = false) + { + blockedAtPos = blockPos; + RPCA_DoBlock(firstBlock, dontSetCD, triggerType, blockPos, onlyBlockEffects); + } + + internal void ResetStats() + { + objectsToSpawn = new List<GameObject>(); + sinceBlock = 10f; + cooldown = 4f; + counter = 1000f; + cdMultiplier = 1f; + cdAdd = 0f; + forceToAdd = 0f; + forceToAddUp = 0f; + autoBlock = false; + blockedThisFrame = false; + additionalBlocks = 0; + healing = 0f; + delayOtherActions = false; + } + + public void CallDoBlock(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 useBlockPos = default(Vector3), bool onlyBlockEffects = false) + { + data.view.RPC("RPCA_DoBlock", RpcTarget.All, firstBlock, dontSetCD, (int)triggerType, useBlockPos, onlyBlockEffects); + } + + [PunRPC] + public void RPCA_DoBlock(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 useBlockPos = default(Vector3), bool onlyBlockEffects = false) + { + if (triggerType == BlockTrigger.BlockTriggerType.Default && firstBlock) + { + for (int i = 0; i < additionalBlocks; i++) + { + StartCoroutine(DelayBlock(((float)i + 1f) * timeBetweenBlocks)); + } + } + StartCoroutine(IDoBlock(firstBlock, dontSetCD, triggerType, useBlockPos, onlyBlockEffects)); + } + + private IEnumerator IDoBlock(bool firstBlock, bool dontSetCD = false, BlockTrigger.BlockTriggerType triggerType = BlockTrigger.BlockTriggerType.Default, Vector3 useBlockPos = default(Vector3), bool onlyBlockEffects = false) + { + active = false; + Vector3 position = base.transform.position; + if (useBlockPos != Vector3.zero) + { + base.transform.position = useBlockPos; + } + if (SuperFirstBlockAction != null) + { + SuperFirstBlockAction(triggerType); + } + if (FirstBlockActionThatDelaysOthers != null) + { + FirstBlockActionThatDelaysOthers(triggerType); + } + if (useBlockPos != Vector3.zero) + { + base.transform.position = position; + } + if (!onlyBlockEffects) + { + sinceBlock = 0f; + } + if (delayOtherActions) + { + yield return new WaitForSeconds(0.2f); + } + position = base.transform.position; + if (useBlockPos != Vector3.zero) + { + base.transform.position = useBlockPos; + } + if (BlockActionEarly != null) + { + BlockActionEarly(triggerType); + } + if (BlockAction != null) + { + BlockAction(triggerType); + } + if (firstBlock) + { + if (forceToAdd != 0f) + { + health.TakeForce(data.hand.transform.forward * forceToAdd * data.playerVel.mass * 0.01f); + } + if (forceToAddUp != 0f) + { + health.TakeForce(Vector3.up * forceToAddUp * data.playerVel.mass * 0.01f); + } + } + blockedLastFrame = true; + bool flag = false; + for (int i = 0; i < data.currentCards.Count; i++) + { + if (data.currentCards[i].soundDisableBlockBasic) + { + flag = true; + break; + } + } + if (!flag && triggerType != BlockTrigger.BlockTriggerType.ShieldCharge) + { + SoundManager.Instance.Play(soundBlockStart, base.transform); + } + if (!onlyBlockEffects) + { + particle.Play(); + } + if (!dontSetCD) + { + counter = 0f; + } + GamefeelManager.GameFeel(UnityEngine.Random.insideUnitCircle.normalized * 1f); + if (!onlyBlockEffects) + { + sinceBlock = 0f; + } + Spawn(); + health.Heal(healing); + if (useBlockPos != Vector3.zero) + { + base.transform.position = position; + } + } + + public void ShowStatusEffectBlock() + { + if (!(Time.unscaledTime < lastStatusBlock + 0.25f) && data.view.IsMine) + { + lastStatusBlock = Time.unscaledTime; + data.view.RPC("RPCA_ShowStatusEffectBlock", RpcTarget.All); + } + } + + [PunRPC] + public void RPCA_ShowStatusEffectBlock() + { + SoundManager.Instance.Play(soundBlockStatusEffect, base.transform); + statusBlockPart.Play(); + } + + public void TryBlock() + { + if (!(counter < Cooldown())) + { + RPCA_DoBlock(firstBlock: true); + counter = 0f; + } + } + + private IEnumerator DelayBlock(float t) + { + yield return new WaitForSeconds(t); + yield return new WaitForEndOfFrame(); + RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.Echo); + } + + public void Spawn() + { + for (int i = 0; i < objectsToSpawn.Count; i++) + { + SpawnedAttack component = UnityEngine.Object.Instantiate(objectsToSpawn[i], base.transform.position, Quaternion.identity).GetComponent<SpawnedAttack>(); + if ((bool)component) + { + component.spawner = GetComponent<Player>(); + } + } + } + + public void blocked(GameObject projectile, Vector3 forward, Vector3 hitPos) + { + SoundManager.Instance.Play(soundBlockBlocked, base.transform); + projectile.GetComponent<ProjectileHit>().RemoveOwnPlayerFromPlayersHit(); + projectile.GetComponent<ProjectileHit>().AddPlayerToHeld(GetComponent<HealthHandler>()); + projectile.GetComponent<MoveTransform>().velocity *= -1f; + projectile.GetComponent<RayCastTrail>().WasBlocked(); + blockedPart.transform.position = hitPos + base.transform.forward * 5f; + blockedPart.transform.rotation = Quaternion.LookRotation(-forward * 1.5f); + GamefeelManager.GameFeel(forward); + blockedPart.Play(); + SpawnedAttack componentInParent = projectile.GetComponentInParent<SpawnedAttack>(); + if ((!componentInParent || !(componentInParent.spawner.gameObject == base.transform.root.gameObject)) && BlockProjectileAction != null) + { + BlockProjectileAction(projectile, forward, hitPos); + } + } + + public void ResetCD(bool soundPlay) + { + active = true; + reloadParticle.Play(); + counter = Cooldown() + 1f; + if (soundPlay) + { + SoundManager.Instance.Play(soundBlockRecharged, base.transform); + } + } + + public bool TryBlockMe(GameObject toBlock, Vector3 forward, Vector3 hitPos) + { + if (sinceBlock < 0.3f) + { + blocked(toBlock, forward, hitPos); + sinceBlock = 0f; + particle.Play(); + return true; + } + return false; + } + + public void DoBlock(GameObject toBlock, Vector3 forward, Vector3 hitPos) + { + sinceBlock = 0f; + blocked(toBlock, forward, hitPos); + particle.Play(); + } + + public bool IsBlocking() + { + if (sinceBlock < 0.3f) + { + ShowStatusEffectBlock(); + } + return sinceBlock < 0.3f; + } + + public bool IsOnCD() + { + return counter < Cooldown(); + } +} diff --git a/ROUNDS/BlockEffect.cs b/ROUNDS/BlockEffect.cs new file mode 100644 index 0000000..3cc771c --- /dev/null +++ b/ROUNDS/BlockEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class BlockEffect : MonoBehaviour +{ + public abstract void DoBlockedProjectile(GameObject projectile, Vector3 forward, Vector3 hitPos); +} diff --git a/ROUNDS/BlockEffectCounter.cs b/ROUNDS/BlockEffectCounter.cs new file mode 100644 index 0000000..56c7e39 --- /dev/null +++ b/ROUNDS/BlockEffectCounter.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class BlockEffectCounter : BlockEffect +{ + public int ownAttacksToSendBack; + + private SpawnObjectEffect spawn; + + private void Start() + { + spawn = GetComponentInParent<SpawnObjectEffect>(); + } + + public override void DoBlockedProjectile(GameObject projectile, Vector3 forward, Vector3 hitPos) + { + for (int i = 0; i < ownAttacksToSendBack; i++) + { + spawn.DoEffect(forward); + } + } +} diff --git a/ROUNDS/BlockRechargeUI.cs b/ROUNDS/BlockRechargeUI.cs new file mode 100644 index 0000000..d2ad92a --- /dev/null +++ b/ROUNDS/BlockRechargeUI.cs @@ -0,0 +1,20 @@ +using UnityEngine; +using UnityEngine.UI; + +public class BlockRechargeUI : MonoBehaviour +{ + private Block block; + + private Image img; + + private void Start() + { + img = GetComponentInChildren<Image>(); + block = GetComponentInParent<Block>(); + } + + private void Update() + { + img.fillAmount = block.counter / block.Cooldown(); + } +} diff --git a/ROUNDS/BlockTrigger.cs b/ROUNDS/BlockTrigger.cs new file mode 100644 index 0000000..604c466 --- /dev/null +++ b/ROUNDS/BlockTrigger.cs @@ -0,0 +1,140 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class BlockTrigger : MonoBehaviour +{ + public enum BlockTriggerType + { + Default, + None, + ShieldCharge, + Echo, + Empower + } + + public UnityEvent triggerEvent; + + public UnityEvent triggerEventEarly; + + public bool delayOtherActions; + + public UnityEvent triggerFirstBlockThatDelaysOthers; + + public UnityEvent triggerSuperFirstBlock; + + public UnityEvent successfulBlockEvent; + + public UnityEvent blockRechargeEvent; + + private BlockEffect[] effects; + + public float cooldown; + + private float lastTriggerTime = -5f; + + public BlockTriggerType blackListedType = BlockTriggerType.None; + + public float cooldownSuccess; + + private float lastTriggerTimeSuccessful = -5f; + + private void Start() + { + effects = GetComponents<BlockEffect>(); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.SuperFirstBlockAction, new Action<BlockTriggerType>(DoSuperFirstBlock)); + componentInParent.FirstBlockActionThatDelaysOthers = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.FirstBlockActionThatDelaysOthers, new Action<BlockTriggerType>(DoFirstBlockThatDelaysOthers)); + componentInParent.BlockAction = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.BlockAction, new Action<BlockTriggerType>(DoBlock)); + componentInParent.BlockActionEarly = (Action<BlockTriggerType>)Delegate.Combine(componentInParent.BlockActionEarly, new Action<BlockTriggerType>(DoBlockEarly)); + componentInParent.BlockProjectileAction = (Action<GameObject, Vector3, Vector3>)Delegate.Combine(componentInParent.BlockProjectileAction, new Action<GameObject, Vector3, Vector3>(DoBlockedProjectile)); + componentInParent.BlockRechargeAction = (Action)Delegate.Combine(componentInParent.BlockRechargeAction, new Action(DoBlockRecharge)); + if (delayOtherActions) + { + GetComponentInParent<Block>().delayOtherActions = true; + } + } + + private void OnDestroy() + { + Block componentInParent = GetComponentInParent<Block>(); + if ((bool)componentInParent && componentInParent.SuperFirstBlockAction != null) + { + componentInParent.SuperFirstBlockAction = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.SuperFirstBlockAction, new Action<BlockTriggerType>(DoSuperFirstBlock)); + } + if ((bool)componentInParent && componentInParent.FirstBlockActionThatDelaysOthers != null) + { + componentInParent.FirstBlockActionThatDelaysOthers = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.FirstBlockActionThatDelaysOthers, new Action<BlockTriggerType>(DoFirstBlockThatDelaysOthers)); + } + if ((bool)componentInParent && componentInParent.BlockAction != null) + { + componentInParent.BlockAction = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.BlockAction, new Action<BlockTriggerType>(DoBlock)); + } + if ((bool)componentInParent && componentInParent.BlockActionEarly != null) + { + componentInParent.BlockActionEarly = (Action<BlockTriggerType>)Delegate.Remove(componentInParent.BlockActionEarly, new Action<BlockTriggerType>(DoBlockEarly)); + } + if ((bool)componentInParent && componentInParent.BlockProjectileAction != null) + { + componentInParent.BlockProjectileAction = (Action<GameObject, Vector3, Vector3>)Delegate.Remove(componentInParent.BlockProjectileAction, new Action<GameObject, Vector3, Vector3>(DoBlockedProjectile)); + } + if ((bool)componentInParent && componentInParent.BlockRechargeAction != null) + { + componentInParent.BlockRechargeAction = (Action)Delegate.Remove(componentInParent.BlockRechargeAction, new Action(DoBlockRecharge)); + } + } + + public void DoSuperFirstBlock(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerSuperFirstBlock.Invoke(); + } + } + + public void DoFirstBlockThatDelaysOthers(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerFirstBlockThatDelaysOthers.Invoke(); + } + } + + public void DoBlockEarly(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerEventEarly.Invoke(); + } + } + + public void DoBlock(BlockTriggerType triggerType) + { + if (triggerType != blackListedType && !(lastTriggerTime + cooldown > Time.time)) + { + lastTriggerTime = Time.time; + triggerEvent.Invoke(); + } + } + + public void DoBlockedProjectile(GameObject projectile, Vector3 forward, Vector3 hitPos) + { + if (!(lastTriggerTimeSuccessful + cooldownSuccess > Time.time)) + { + lastTriggerTimeSuccessful = Time.time; + successfulBlockEvent.Invoke(); + for (int i = 0; i < effects.Length; i++) + { + effects[i].DoBlockedProjectile(projectile, forward, hitPos); + } + } + } + + public void DoBlockRecharge() + { + blockRechargeEvent.Invoke(); + } +} diff --git a/ROUNDS/BlurPost.cs b/ROUNDS/BlurPost.cs new file mode 100644 index 0000000..1e10746 --- /dev/null +++ b/ROUNDS/BlurPost.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +[ExecuteInEditMode] +public class BlurPost : MonoBehaviour +{ + [SerializeField] + private Material postprocessMaterial; + + private void OnRenderImage(RenderTexture source, RenderTexture destination) + { + RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height); + Graphics.Blit(source, temporary, postprocessMaterial, 0); + Graphics.Blit(temporary, destination, postprocessMaterial, 1); + RenderTexture.ReleaseTemporary(temporary); + } +} diff --git a/ROUNDS/BounceEffect.cs b/ROUNDS/BounceEffect.cs new file mode 100644 index 0000000..ff98414 --- /dev/null +++ b/ROUNDS/BounceEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class BounceEffect : MonoBehaviour +{ + public abstract void DoBounce(HitInfo hit); +} diff --git a/ROUNDS/BounceEffectRetarget.cs b/ROUNDS/BounceEffectRetarget.cs new file mode 100644 index 0000000..8e1ef79 --- /dev/null +++ b/ROUNDS/BounceEffectRetarget.cs @@ -0,0 +1,103 @@ +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class BounceEffectRetarget : BounceEffect +{ + [Header("Sound")] + public SoundEvent soundTargetBounceTargetPlayer; + + private MoveTransform move; + + private PhotonView view; + + private void Start() + { + view = GetComponentInParent<PhotonView>(); + move = GetComponentInParent<MoveTransform>(); + GetComponentInParent<ChildRPC>().childRPCsVector2.Add("TargetBounce", SetNewVel); + GetComponentInParent<ChildRPC>().childRPCsInt.Add("TargetBounceLine", DrawLineTo); + } + + public override void DoBounce(HitInfo hit) + { + StartCoroutine(DelayMove(hit)); + } + + private void ActuallyDoBounce(int playerId) + { + Player playerWithID = PlayerManager.instance.GetPlayerWithID(playerId); + if ((bool)playerWithID) + { + GetComponentInParent<ChildRPC>().CallFunction("TargetBounce", (playerWithID.data.playerVel.position + Vector2.up * move.GetUpwardsCompensation(base.transform.position, playerWithID.data.playerVel.position) - (Vector2)base.transform.position).normalized * move.velocity.magnitude); + SoundManager.Instance.PlayAtPosition(soundTargetBounceTargetPlayer, SoundManager.Instance.GetTransform(), base.transform); + } + else + { + GetComponentInParent<ChildRPC>().CallFunction("TargetBounce", move.velocity); + } + } + + private void SetNewVel(Vector2 newVel) + { + move.enabled = true; + move.velocity = newVel; + } + + private Player FindTarget(HitInfo hit) + { + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position + (Vector3)hit.normal * 0.1f); + if (PlayerManager.instance.CanSeePlayer(base.transform.position, closestPlayer).canSee) + { + return closestPlayer; + } + return null; + } + + private IEnumerator DelayMove(HitInfo hit) + { + Player p = FindTarget(hit); + if ((bool)p && view.IsMine) + { + GetComponentInParent<ChildRPC>().CallFunction("TargetBounceLine", p.playerID); + } + move.enabled = false; + if ((bool)hit.rigidbody) + { + move.GetComponent<RayCastTrail>().IgnoreRigFor(hit.rigidbody, 0.5f); + } + yield return new WaitForSeconds(0.1f); + if (view.IsMine) + { + if ((bool)p) + { + ActuallyDoBounce(p.playerID); + } + else + { + ActuallyDoBounce(-1); + } + } + } + + private void DrawLineTo(int playerID) + { + Player playerWithID = PlayerManager.instance.GetPlayerWithID(playerID); + if ((bool)playerWithID) + { + StartCoroutine(DrawLine(playerWithID.transform)); + } + } + + private IEnumerator DrawLine(Transform target) + { + LineEffect line = GetComponentInChildren<LineEffect>(includeInactive: true); + line.StartDraw(); + while ((bool)line) + { + line.DrawLine(base.transform.position, target.position); + yield return null; + } + } +} diff --git a/ROUNDS/BounceTrigger.cs b/ROUNDS/BounceTrigger.cs new file mode 100644 index 0000000..8d7a1b5 --- /dev/null +++ b/ROUNDS/BounceTrigger.cs @@ -0,0 +1,22 @@ +using System; +using UnityEngine; + +public class BounceTrigger : MonoBehaviour +{ + private BounceEffect[] bounceEffects; + + private void Start() + { + bounceEffects = GetComponents<BounceEffect>(); + RayHitReflect componentInParent = GetComponentInParent<RayHitReflect>(); + componentInParent.reflectAction = (Action<HitInfo>)Delegate.Combine(componentInParent.reflectAction, new Action<HitInfo>(Reflect)); + } + + public void Reflect(HitInfo hit) + { + for (int i = 0; i < bounceEffects.Length; i++) + { + bounceEffects[i].DoBounce(hit); + } + } +} diff --git a/ROUNDS/BrodalAIController.cs b/ROUNDS/BrodalAIController.cs new file mode 100644 index 0000000..1d0d60f --- /dev/null +++ b/ROUNDS/BrodalAIController.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class BrodalAIController : MonoBehaviour +{ + private PlayerAPI m_playerAPI; + + private int m_sampleCount = 250; + + private float m_sampleSize; + + private LayerMask m_layerMask; + + private Dictionary<Guid, Platform> m_platforms = new Dictionary<Guid, Platform>(); + + private Platform m_currentPlatform; + + private Vector2 m_pointOnLine; + + private bool inited; + + private void Start() + { + m_playerAPI = GetComponentInParent<PlayerAPI>(); + HealthHandler healthHandler = m_playerAPI.player.data.healthHandler; + healthHandler.delayedReviveAction = (Action)Delegate.Combine(healthHandler.delayedReviveAction, new Action(Init)); + } + + public void Init() + { + m_platforms.Clear(); + m_currentPlatform = null; + PlotPlatforms(); + RaycastMap(); + PostProcessPlatforms(); + inited = true; + Debug.Log("Revived"); + } + + private void PostProcessPlatforms() + { + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + platform.Value.PostProcessPlatformPoints(); + } + } + + private void PlotPlatforms() + { + BoxCollider2D[] array = UnityEngine.Object.FindObjectsOfType<BoxCollider2D>(); + foreach (BoxCollider2D boxCollider2D in array) + { + if (boxCollider2D.gameObject.layer == LayerMask.GetMask("Player")) + { + continue; + } + bool flag = false; + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + foreach (BoxCollider2D boxCollider in platform.Value.BoxColliders) + { + bool flag2 = false; + if (boxCollider2D.bounds.Intersects(boxCollider.bounds)) + { + flag2 = true; + } + if (flag2) + { + m_platforms[platform.Key].AddCollider(boxCollider2D); + flag = true; + break; + } + } + if (flag) + { + break; + } + } + if (!flag) + { + Guid key = Guid.NewGuid(); + m_platforms.Add(key, new Platform()); + m_platforms[key].AddCollider(boxCollider2D); + } + } + } + + private void MergePlatforms() + { + } + + private void RaycastMap() + { + m_layerMask = LayerMask.GetMask("Default"); + Camera component = MainCam.instance.transform.GetComponent<Camera>(); + Vector3 vector = component.ViewportToWorldPoint(new Vector2(0f, 1f)); + Vector3 vector2 = component.ViewportToWorldPoint(new Vector2(1f, 1f)); + m_sampleSize = (vector2.x - vector.x) / (float)m_sampleCount; + for (float num = vector.x; num < vector2.x; num += m_sampleSize) + { + RaycastHit2D[] array = Physics2D.RaycastAll(new Vector3(num, vector.y, 0f), Vector2.down, 9999f, m_layerMask); + for (int i = 0; i < array.Length; i++) + { + RaycastHit2D raycastHit2D = array[i]; + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + if (platform.Value.ContainsCollider((BoxCollider2D)raycastHit2D.collider)) + { + m_platforms[platform.Key].AddPlatformPoint(raycastHit2D.point); + break; + } + } + } + } + } + + private void Update() + { + if (inited) + { + FindClosestPlatform(base.transform.position); + Vector2 vector = m_playerAPI.OtherPlayerPosition() - base.transform.position; + float magnitude = vector.magnitude; + vector.Normalize(); + Vector2 normalized = (vector + new Vector2(0f, 0.15f)).normalized; + m_playerAPI.SetAimDirection(normalized); + Vector2 position = new Vector2(base.transform.position.x, base.transform.position.y) + vector * 1.5f; + bool num = m_currentPlatform.IsPositionOutsidePlatform(position); + m_playerAPI.Move(m_playerAPI.TowardsOtherPlayer()); + if (num) + { + m_playerAPI.Jump(); + } + vector.y = 0f; + vector.Normalize(); + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position, vector, 0.85f, m_layerMask); + RaycastHit2D raycastHit2D2 = Physics2D.Raycast(base.transform.position, vector, magnitude, m_layerMask); + if ((bool)raycastHit2D.collider) + { + m_playerAPI.Jump(); + } + if (raycastHit2D2.collider == null) + { + m_playerAPI.Attack(); + } + m_playerAPI.Block(); + } + } + + private void FindClosestPlatform(Vector2 position) + { + float num = float.MaxValue; + foreach (KeyValuePair<Guid, Platform> platform in m_platforms) + { + float closestDistance = platform.Value.GetClosestDistance(position); + if (closestDistance < num) + { + m_currentPlatform = platform.Value; + num = closestDistance; + } + } + } +} diff --git a/ROUNDS/BuildOnly.cs b/ROUNDS/BuildOnly.cs new file mode 100644 index 0000000..48988a5 --- /dev/null +++ b/ROUNDS/BuildOnly.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BuildOnly : MonoBehaviour +{ + private void Start() + { + if (Application.isEditor) + { + base.gameObject.SetActive(value: false); + } + } +} diff --git a/ROUNDS/BulletBase.cs b/ROUNDS/BulletBase.cs new file mode 100644 index 0000000..446970a --- /dev/null +++ b/ROUNDS/BulletBase.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BulletBase : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/BulletDamageEvents.cs b/ROUNDS/BulletDamageEvents.cs new file mode 100644 index 0000000..09dae56 --- /dev/null +++ b/ROUNDS/BulletDamageEvents.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class BulletDamageEvents : MonoBehaviour +{ + public DmgEvent[] damageEvents; + + public void Start() + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + for (int i = 0; i < damageEvents.Length; i++) + { + if (componentInParent.damage > damageEvents[i].dmg) + { + damageEvents[i].eventToCall.Invoke(); + } + } + } +} diff --git a/ROUNDS/BulletPoint.cs b/ROUNDS/BulletPoint.cs new file mode 100644 index 0000000..d7a9157 --- /dev/null +++ b/ROUNDS/BulletPoint.cs @@ -0,0 +1,56 @@ +using System; +using UnityEngine; + +public class BulletPoint : MonoBehaviour +{ + public LayerMask mask; + + private Gun gun; + + private MoveTransform move; + + private ProjectileHit hit; + + private float counter = 5f; + + private void Start() + { + gun = GetComponent<Gun>(); + Gun obj = gun; + obj.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(obj.ShootPojectileAction, new Action<GameObject>(Fire)); + } + + private void Attack() + { + gun.Attack(1f, forceAttack: true); + } + + private void Fire(GameObject projectile) + { + move = projectile.GetComponent<MoveTransform>(); + } + + private void Update() + { + if ((bool)move) + { + counter = 0f; + Vector3 vector = base.transform.position - base.transform.root.position; + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.root.position, vector, vector.magnitude, mask, -10000f); + Vector3 vector2 = base.transform.position; + if (raycastHit2D.transform != null) + { + vector2 = raycastHit2D.point - (Vector2)vector.normalized * 0.1f; + } + move.velocity = Vector2.Lerp(move.velocity, (vector2 - move.transform.position) * 50f, TimeHandler.deltaTime * 50f); + } + else + { + counter += TimeHandler.deltaTime; + if (counter > 2f) + { + Attack(); + } + } + } +} diff --git a/ROUNDS/BulletSurf.cs b/ROUNDS/BulletSurf.cs new file mode 100644 index 0000000..23579ee --- /dev/null +++ b/ROUNDS/BulletSurf.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BulletSurf : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/BulletWrapper.cs b/ROUNDS/BulletWrapper.cs new file mode 100644 index 0000000..1229787 --- /dev/null +++ b/ROUNDS/BulletWrapper.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class BulletWrapper +{ + public float damage; + + public Vector2 velocity; + + public ProjectileHit projectileHit; + + public MoveTransform projectileMovement; +} diff --git a/ROUNDS/CameraZoomHandler.cs b/ROUNDS/CameraZoomHandler.cs new file mode 100644 index 0000000..56c8b86 --- /dev/null +++ b/ROUNDS/CameraZoomHandler.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class CameraZoomHandler : MonoBehaviour +{ + private Camera[] cameras; + + private void Start() + { + cameras = GetComponentsInChildren<Camera>(); + } + + private void Update() + { + float b = 20f; + if (MapManager.instance.currentMap != null) + { + b = MapManager.instance.currentMap.Map.size; + } + for (int i = 0; i < cameras.Length; i++) + { + cameras[i].orthographicSize = Mathf.Lerp(cameras[i].orthographicSize, b, Time.unscaledDeltaTime * 5f); + } + } +} diff --git a/ROUNDS/CanSeeInfo.cs b/ROUNDS/CanSeeInfo.cs new file mode 100644 index 0000000..947131d --- /dev/null +++ b/ROUNDS/CanSeeInfo.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public class CanSeeInfo +{ + public bool canSee; + + public Vector2 hitPoint; + + public float distance; +} diff --git a/ROUNDS/CapScale.cs b/ROUNDS/CapScale.cs new file mode 100644 index 0000000..bcb62a0 --- /dev/null +++ b/ROUNDS/CapScale.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class CapScale : MonoBehaviour +{ + public float min = 2f; + + public float max = 10f; + + private void Start() + { + if (base.transform.localScale.x < min) + { + base.transform.localScale = Vector3.one * min; + } + if (base.transform.localScale.x > max) + { + base.transform.localScale = Vector3.one * max; + } + } +} diff --git a/ROUNDS/CappedDeltaTime.cs b/ROUNDS/CappedDeltaTime.cs new file mode 100644 index 0000000..8bb24c6 --- /dev/null +++ b/ROUNDS/CappedDeltaTime.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class CappedDeltaTime : MonoBehaviour +{ + public static float time; + + private void Update() + { + time = Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.02f); + } +} diff --git a/ROUNDS/CardAnimation.cs b/ROUNDS/CardAnimation.cs new file mode 100644 index 0000000..3578ec6 --- /dev/null +++ b/ROUNDS/CardAnimation.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class CardAnimation : MonoBehaviour +{ +} diff --git a/ROUNDS/CardAudioModifier.cs b/ROUNDS/CardAudioModifier.cs new file mode 100644 index 0000000..f6206c0 --- /dev/null +++ b/ROUNDS/CardAudioModifier.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class CardAudioModifier : MonoBehaviour +{ + public enum StackType + { + RTPCValue, + PostEvent + } + + public string stackName; + + public StackType stackType; +} diff --git a/ROUNDS/CardBar.cs b/ROUNDS/CardBar.cs new file mode 100644 index 0000000..e985288 --- /dev/null +++ b/ROUNDS/CardBar.cs @@ -0,0 +1,95 @@ +using Sonigon; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CardBar : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCardPick; + + [Header("Settings")] + public GameObject pointer; + + [Header("Settings")] + public GameObject cardPos; + + private GameObject source; + + private CardInfo ci; + + private GameObject currentCard; + + private void Start() + { + source = base.transform.GetChild(0).gameObject; + } + + public void ClearBar() + { + if ((bool)currentCard) + { + Object.Destroy(currentCard); + } + for (int num = base.transform.childCount - 1; num >= 0; num--) + { + if (base.transform.GetChild(num).gameObject.activeSelf) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + } + } + + public void AddCard(CardInfo card) + { + SoundManager.Instance.Play(soundCardPick, base.transform); + ci = card; + GameObject obj = Object.Instantiate(source, source.transform.position, source.transform.rotation, source.transform.parent); + obj.transform.localScale = Vector3.one; + string cardName = card.cardName; + cardName = cardName.Substring(0, 2); + string text = cardName[0].ToString().ToUpper(); + if (cardName.Length > 1) + { + string text2 = cardName[1].ToString().ToLower(); + cardName = text + text2; + } + else + { + cardName = text; + } + obj.GetComponentInChildren<TextMeshProUGUI>().text = cardName; + obj.GetComponent<CardBarButton>().card = card; + obj.gameObject.SetActive(value: true); + } + + public void OnHover(CardInfo card, Vector3 hoverPos) + { + if ((bool)currentCard) + { + Object.Destroy(currentCard); + } + currentCard = CardChoice.instance.AddCardVisual(card, cardPos.transform.position); + Collider2D[] componentsInChildren = currentCard.transform.root.GetComponentsInChildren<Collider2D>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].enabled = false; + } + currentCard.GetComponentInChildren<Canvas>().sortingLayerName = "MostFront"; + currentCard.GetComponentInChildren<GraphicRaycaster>().enabled = false; + currentCard.GetComponentInChildren<SetScaleToZero>().enabled = false; + currentCard.GetComponentInChildren<SetScaleToZero>().transform.localScale = Vector3.one * 1.15f; + } + + public void StopHover() + { + if ((bool)currentCard) + { + Object.Destroy(currentCard); + } + } + + private void Update() + { + } +} diff --git a/ROUNDS/CardBarButton.cs b/ROUNDS/CardBarButton.cs new file mode 100644 index 0000000..13d9c62 --- /dev/null +++ b/ROUNDS/CardBarButton.cs @@ -0,0 +1,19 @@ +using UnityEngine; +using UnityEngine.EventSystems; + +public class CardBarButton : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler +{ + internal CardInfo card; + + public void OnPointerEnter(PointerEventData eventData) + { + GetComponentInParent<CardBar>().OnHover(card, base.transform.position); + base.transform.localScale = Vector3.one * 1.1f; + } + + public void OnPointerExit(PointerEventData eventData) + { + GetComponentInParent<CardBar>().StopHover(); + base.transform.localScale = Vector3.one * 1f; + } +} diff --git a/ROUNDS/CardBarHandler.cs b/ROUNDS/CardBarHandler.cs new file mode 100644 index 0000000..f6ceea2 --- /dev/null +++ b/ROUNDS/CardBarHandler.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class CardBarHandler : MonoBehaviour +{ + private CardBar[] cardBars; + + public static CardBarHandler instance; + + private void Start() + { + instance = this; + cardBars = GetComponentsInChildren<CardBar>(); + } + + public void AddCard(int teamId, CardInfo card) + { + cardBars[teamId].AddCard(card); + } + + public void ResetCardBards() + { + for (int i = 0; i < cardBars.Length; i++) + { + cardBars[i].ClearBar(); + } + } +} diff --git a/ROUNDS/CardCategories.cs b/ROUNDS/CardCategories.cs new file mode 100644 index 0000000..055dc4c --- /dev/null +++ b/ROUNDS/CardCategories.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class CardCategories : MonoBehaviour +{ +} diff --git a/ROUNDS/CardCategory.cs b/ROUNDS/CardCategory.cs new file mode 100644 index 0000000..7961b24 --- /dev/null +++ b/ROUNDS/CardCategory.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "Card Category", menuName = "Square Brawl/Card Category", order = 1)] +public class CardCategory : ScriptableObject +{ +} diff --git a/ROUNDS/CardChoice.cs b/ROUNDS/CardChoice.cs new file mode 100644 index 0000000..ac3ebb8 --- /dev/null +++ b/ROUNDS/CardChoice.cs @@ -0,0 +1,460 @@ +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using SoundImplementation; +using UnityEngine; + +public class CardChoice : MonoBehaviour +{ + private enum StickDirection + { + Left, + Right, + None + } + + public int pickrID = -1; + + public ArtInstance cardPickArt; + + private Transform[] children; + + public CardInfo[] cards; + + public int picks = 6; + + public static CardChoice instance; + + public bool IsPicking; + + private List<GameObject> spawnedCards = new List<GameObject>(); + + public AnimationCurve curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + + private float speed = 4f; + + private bool isPlaying; + + private StickDirection lastStickDirection; + + private int currentlySelectedCard; + + private float counter = 1f; + + private PickerType pickerType; + + public CardThemeColor[] cardThemes; + + private void Awake() + { + instance = this; + } + + private void Start() + { + for (int i = 0; i < cards.Length; i++) + { + PhotonNetwork.PrefabPool.RegisterPrefab(cards[i].gameObject.name, cards[i].gameObject); + } + children = new Transform[base.transform.childCount]; + for (int j = 0; j < children.Length; j++) + { + children[j] = base.transform.GetChild(j); + } + } + + public CardInfo GetSourceCard(CardInfo info) + { + for (int i = 0; i < cards.Length; i++) + { + if (cards[i].cardName == info.cardName) + { + return cards[i]; + } + } + return null; + } + + public void Pick(GameObject pickedCard = null, bool clear = false) + { + if ((bool)pickedCard) + { + pickedCard.GetComponentInChildren<ApplyCardStats>().Pick(pickrID, forcePick: false, pickerType); + GetComponent<PhotonView>().RPC("RPCA_DoEndPick", RpcTarget.All, CardIDs(), pickedCard.GetComponent<PhotonView>().ViewID, pickedCard.GetComponent<PublicInt>().theInt, pickrID); + } + else if (PlayerManager.instance.GetPlayerWithID(pickrID).data.view.IsMine) + { + StartCoroutine(ReplaceCards(pickedCard, clear)); + } + } + + private int[] CardIDs() + { + int[] array = new int[spawnedCards.Count]; + for (int i = 0; i < spawnedCards.Count; i++) + { + array[i] = spawnedCards[i].GetComponent<PhotonView>().ViewID; + } + return array; + } + + private List<GameObject> CardFromIDs(int[] cardIDs) + { + List<GameObject> list = new List<GameObject>(); + for (int i = 0; i < cardIDs.Length; i++) + { + list.Add(PhotonNetwork.GetPhotonView(cardIDs[i]).gameObject); + } + return list; + } + + [PunRPC] + private void RPCA_DoEndPick(int[] cardIDs, int targetCardID, int theInt = 0, int pickId = -1) + { + GameObject pickedCard = PhotonNetwork.GetPhotonView(targetCardID).gameObject; + spawnedCards = CardFromIDs(cardIDs); + StartCoroutine(IDoEndPick(pickedCard, theInt, pickId)); + } + + public IEnumerator IDoEndPick(GameObject pickedCard = null, int theInt = 0, int pickId = -1) + { + Vector3 startPos = pickedCard.transform.position; + Vector3 endPos = CardChoiceVisuals.instance.transform.position; + float c2 = 0f; + while (c2 < 1f) + { + CardChoiceVisuals.instance.framesToSnap = 1; + Vector3 position = Vector3.LerpUnclamped(startPos, endPos, curve.Evaluate(c2)); + pickedCard.transform.position = position; + base.transform.GetChild(theInt).position = position; + c2 += Time.deltaTime * speed; + yield return null; + } + GamefeelManager.GameFeel((startPos - endPos).normalized * 2f); + for (int i = 0; i < spawnedCards.Count; i++) + { + if ((bool)spawnedCards[i]) + { + if (spawnedCards[i].gameObject != pickedCard) + { + spawnedCards[i].AddComponent<Rigidbody>().AddForce((spawnedCards[i].transform.position - endPos) * Random.Range(0f, 50f)); + spawnedCards[i].GetComponent<Rigidbody>().AddTorque(Random.onUnitSphere * Random.Range(0f, 200f)); + spawnedCards[i].AddComponent<RemoveAfterSeconds>().seconds = Random.Range(0.5f, 1f); + spawnedCards[i].GetComponent<RemoveAfterSeconds>().shrink = true; + } + else + { + spawnedCards[i].GetComponentInChildren<CardVisuals>().Leave(); + } + } + } + yield return new WaitForSeconds(0.25f); + AnimationCurve softCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + Vector3 startPos2 = base.transform.GetChild(theInt).transform.position; + Vector3 endPos2 = startPos; + c2 = 0f; + while (c2 < 1f) + { + Vector3 position2 = Vector3.LerpUnclamped(startPos2, endPos2, softCurve.Evaluate(c2)); + base.transform.GetChild(theInt).position = position2; + c2 += Time.deltaTime * speed * 1.5f; + yield return null; + } + SoundPlayerStatic.Instance.PlayPlayerBallDisappear(); + base.transform.GetChild(theInt).position = startPos; + spawnedCards.Clear(); + if (PlayerManager.instance.GetPlayerWithID(pickId).data.view.IsMine) + { + StartCoroutine(ReplaceCards(pickedCard)); + } + } + + private GameObject Spawn(GameObject objToSpawn, Vector3 pos, Quaternion rot) + { + return PhotonNetwork.Instantiate(GetCardPath(objToSpawn), pos, rot, 0); + } + + private string GetCardPath(GameObject targetObj) + { + return targetObj.name; + } + + public GameObject AddCard(CardInfo cardToSpawn) + { + GameObject gameObject = Spawn(cardToSpawn.gameObject, new Vector3(30f, -10f, 0f), Quaternion.identity); + spawnedCards.Add(gameObject); + return gameObject; + } + + public GameObject AddCardVisual(CardInfo cardToSpawn, Vector3 pos) + { + GameObject obj = Object.Instantiate(cardToSpawn.gameObject, pos, Quaternion.identity); + obj.GetComponentInChildren<CardVisuals>().firstValueToSet = true; + return obj; + } + + private IEnumerator ReplaceCards(GameObject pickedCard = null, bool clear = false) + { + if (picks > 0) + { + SoundPlayerStatic.Instance.PlayPlayerBallAppear(); + } + isPlaying = true; + if (clear && spawnedCards != null) + { + for (int j = 0; j < spawnedCards.Count; j++) + { + if (pickedCard != spawnedCards[j]) + { + spawnedCards[j].GetComponentInChildren<CardVisuals>().Leave(); + yield return new WaitForSecondsRealtime(0.1f); + } + } + yield return new WaitForSecondsRealtime(0.2f); + if ((bool)pickedCard) + { + pickedCard.GetComponentInChildren<CardVisuals>().Pick(); + } + spawnedCards.Clear(); + } + yield return new WaitForSecondsRealtime(0.2f); + if (picks > 0) + { + for (int j = 0; j < children.Length; j++) + { + spawnedCards.Add(SpawnUniqueCard(children[j].transform.position, children[j].transform.rotation)); + spawnedCards[j].AddComponent<PublicInt>().theInt = j; + yield return new WaitForSecondsRealtime(0.1f); + } + } + else + { + GetComponent<PhotonView>().RPC("RPCA_DonePicking", RpcTarget.All); + } + picks--; + isPlaying = false; + } + + [PunRPC] + private void RPCA_DonePicking() + { + IsPicking = false; + } + + private GameObject GetRanomCard() + { + GameObject result = null; + float num = 0f; + for (int i = 0; i < cards.Length; i++) + { + if (cards[i].rarity == CardInfo.Rarity.Common) + { + num += 10f; + } + if (cards[i].rarity == CardInfo.Rarity.Uncommon) + { + num += 4f; + } + if (cards[i].rarity == CardInfo.Rarity.Rare) + { + num += 1f; + } + } + float num2 = Random.Range(0f, num); + for (int j = 0; j < cards.Length; j++) + { + if (cards[j].rarity == CardInfo.Rarity.Common) + { + num2 -= 10f; + } + if (cards[j].rarity == CardInfo.Rarity.Uncommon) + { + num2 -= 4f; + } + if (cards[j].rarity == CardInfo.Rarity.Rare) + { + num2 -= 1f; + } + if (num2 <= 0f) + { + result = cards[j].gameObject; + break; + } + } + return result; + } + + private GameObject SpawnUniqueCard(Vector3 pos, Quaternion rot) + { + GameObject ranomCard = GetRanomCard(); + CardInfo component = ranomCard.GetComponent<CardInfo>(); + Player player = null; + player = ((pickerType != 0) ? PlayerManager.instance.players[pickrID] : PlayerManager.instance.GetPlayersInTeam(pickrID)[0]); + for (int i = 0; i < spawnedCards.Count; i++) + { + bool flag = spawnedCards[i].GetComponent<CardInfo>().cardName == ranomCard.GetComponent<CardInfo>().cardName; + if (pickrID != -1) + { + Holdable holdable = player.data.GetComponent<Holding>().holdable; + if ((bool)holdable) + { + Gun component2 = holdable.GetComponent<Gun>(); + Gun component3 = ranomCard.GetComponent<Gun>(); + if ((bool)component3 && (bool)component2 && component3.lockGunToDefault && component2.lockGunToDefault) + { + flag = true; + } + } + for (int j = 0; j < player.data.currentCards.Count; j++) + { + CardInfo component4 = player.data.currentCards[j].GetComponent<CardInfo>(); + for (int k = 0; k < component4.blacklistedCategories.Length; k++) + { + for (int l = 0; l < component.categories.Length; l++) + { + if (component.categories[l] == component4.blacklistedCategories[k]) + { + flag = true; + } + } + } + if (!component4.allowMultiple && component.cardName == component4.cardName) + { + flag = true; + } + } + } + if (flag) + { + return SpawnUniqueCard(pos, rot); + } + } + GameObject obj = Spawn(ranomCard.gameObject, pos, rot); + obj.GetComponent<CardInfo>().sourceCard = ranomCard.GetComponent<CardInfo>(); + obj.GetComponentInChildren<DamagableEvent>().GetComponent<Collider2D>().enabled = false; + return obj; + } + + private void Update() + { + counter += Time.deltaTime; + _ = isPlaying; + if (pickrID != -1 && IsPicking) + { + DoPlayerSelect(); + } + if (Application.isEditor && !DevConsole.isTyping && Input.GetKeyDown(KeyCode.N)) + { + picks++; + instance.Pick(null, clear: true); + } + } + + private void DoPlayerSelect() + { + SoundMusicManager.Instance.PlayIngame(isCard: true); + if (spawnedCards.Count == 0 || pickrID == -1) + { + return; + } + PlayerActions[] array = null; + array = ((pickerType != 0) ? PlayerManager.instance.GetActionsFromPlayer(pickrID) : PlayerManager.instance.GetActionsFromTeam(pickrID)); + if (array == null) + { + Pick(spawnedCards[0]); + return; + } + StickDirection stickDirection = StickDirection.None; + for (int i = 0; i < array.Length; i++) + { + if (array[i] == null) + { + continue; + } + if (array[i].Right.Value > 0.7f) + { + stickDirection = StickDirection.Right; + } + if (array[i].Left.Value > 0.7f) + { + stickDirection = StickDirection.Left; + } + currentlySelectedCard = Mathf.Clamp(currentlySelectedCard, 0, spawnedCards.Count - 1); + for (int j = 0; j < spawnedCards.Count; j++) + { + if ((bool)spawnedCards[j] && (spawnedCards[j].GetComponentInChildren<CardVisuals>().isSelected != (currentlySelectedCard == j) || counter > 0.2f)) + { + counter = 0f; + spawnedCards[j].GetComponent<PhotonView>().RPC("RPCA_ChangeSelected", RpcTarget.All, currentlySelectedCard == j); + } + } + if (array[i].Jump.WasPressed && !isPlaying && spawnedCards[currentlySelectedCard] != null) + { + Pick(spawnedCards[currentlySelectedCard]); + pickrID = -1; + break; + } + } + if (stickDirection != lastStickDirection) + { + if (stickDirection == StickDirection.Left) + { + currentlySelectedCard--; + } + if (stickDirection == StickDirection.Right) + { + currentlySelectedCard++; + } + lastStickDirection = stickDirection; + } + if (CardChoiceVisuals.instance.currentCardSelected != currentlySelectedCard) + { + CardChoiceVisuals.instance.SetCurrentSelected(currentlySelectedCard); + } + } + + public IEnumerator DoPick(int picksToSet, int picketIDToSet, PickerType pType = PickerType.Team) + { + pickerType = pType; + StartPick(picksToSet, picketIDToSet); + while (IsPicking) + { + yield return null; + } + UIHandler.instance.StopShowPicker(); + CardChoiceVisuals.instance.Hide(); + } + + public void StartPick(int picksToSet, int pickerIDToSet) + { + pickrID = pickerIDToSet; + IsPicking = true; + picks = picksToSet; + ArtHandler.instance.SetSpecificArt(cardPickArt); + Pick(); + } + + public Color GetCardColor(CardThemeColor.CardThemeColorType colorType) + { + for (int i = 0; i < cardThemes.Length; i++) + { + if (cardThemes[i].themeType == colorType) + { + return cardThemes[i].targetColor; + } + } + return Color.black; + } + + public Color GetCardColor2(CardThemeColor.CardThemeColorType colorType) + { + for (int i = 0; i < cardThemes.Length; i++) + { + if (cardThemes[i].themeType == colorType) + { + return cardThemes[i].bgColor; + } + } + return Color.black; + } +} diff --git a/ROUNDS/CardChoiceVisuals.cs b/ROUNDS/CardChoiceVisuals.cs new file mode 100644 index 0000000..bf09e08 --- /dev/null +++ b/ROUNDS/CardChoiceVisuals.cs @@ -0,0 +1,162 @@ +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class CardChoiceVisuals : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCardSwitch; + + public static CardChoiceVisuals instance; + + [Header("Settings")] + public int currentCardSelected; + + public GameObject cardParent; + + public Transform leftHandTarget; + + public Transform rightHandTarget; + + public Transform shieldGem; + + private Vector3 leftHandRestPos; + + private Vector3 rightHandRestPos; + + private Vector3 leftHandVel; + + private Vector3 rightHandVel; + + public float spring = 40f; + + public float drag = 10f; + + public float sway = 1f; + + public float swaySpeed = 1f; + + public int framesToSnap; + + private bool isShowinig; + + private GameObject currentSkin; + + private void Awake() + { + instance = this; + leftHandRestPos = leftHandTarget.position; + rightHandRestPos = rightHandTarget.position; + } + + private void Start() + { + } + + private void Update() + { + if (!isShowinig || Time.unscaledDeltaTime > 0.1f || currentCardSelected >= cardParent.transform.childCount || currentCardSelected < 0) + { + return; + } + if (rightHandTarget.position.x == float.NaN || rightHandTarget.position.y == float.NaN || rightHandTarget.position.z == float.NaN) + { + rightHandTarget.position = Vector3.zero; + rightHandVel = Vector3.zero; + } + if (leftHandTarget.position.x == float.NaN || leftHandTarget.position.y == float.NaN || leftHandTarget.position.z == float.NaN) + { + leftHandTarget.position = Vector3.zero; + leftHandVel = Vector3.zero; + } + GameObject obj = cardParent.transform.GetChild(currentCardSelected).gameObject; + Vector3 zero = Vector3.zero; + zero = obj.transform.GetChild(0).position; + if (currentCardSelected < 2) + { + leftHandVel += (zero - leftHandTarget.position) * spring * Time.unscaledDeltaTime; + leftHandVel -= leftHandVel * Time.unscaledDeltaTime * drag; + rightHandVel += (rightHandRestPos - rightHandTarget.position) * spring * Time.unscaledDeltaTime * 0.5f; + rightHandVel -= rightHandVel * Time.unscaledDeltaTime * drag * 0.5f; + rightHandVel += sway * new Vector3(-0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed, 0f), -0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed + 100f, 0f), 0f) * Time.unscaledDeltaTime; + shieldGem.transform.position = rightHandTarget.position; + if (framesToSnap > 0) + { + leftHandTarget.position = zero; + } + } + else + { + rightHandVel += (zero - rightHandTarget.position) * spring * Time.unscaledDeltaTime; + rightHandVel -= rightHandVel * Time.unscaledDeltaTime * drag; + leftHandVel += (leftHandRestPos - leftHandTarget.position) * spring * Time.unscaledDeltaTime * 0.5f; + leftHandVel -= leftHandVel * Time.unscaledDeltaTime * drag * 0.5f; + leftHandVel += sway * new Vector3(-0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed, Time.unscaledTime * swaySpeed), -0.5f + Mathf.PerlinNoise(Time.unscaledTime * swaySpeed + 100f, Time.unscaledTime * swaySpeed + 100f), 0f) * Time.unscaledDeltaTime; + shieldGem.transform.position = leftHandTarget.position; + if (framesToSnap > 0) + { + rightHandTarget.position = zero; + } + } + framesToSnap--; + leftHandTarget.position += leftHandVel * Time.unscaledDeltaTime; + rightHandTarget.position += rightHandVel * Time.unscaledDeltaTime; + } + + public void Show(int pickerID = 0, bool animateIn = false) + { + isShowinig = true; + base.transform.GetChild(0).gameObject.SetActive(value: true); + if (animateIn) + { + GetComponent<CurveAnimation>().PlayIn(); + } + else + { + base.transform.localScale = Vector3.one * 33f; + } + if ((bool)currentSkin) + { + Object.Destroy(currentSkin); + } + if (PlayerManager.instance.players[pickerID].data.view.IsMine) + { + PlayerFace playerFace = null; + playerFace = ((!PhotonNetwork.OfflineMode) ? CharacterCreatorHandler.instance.selectedPlayerFaces[0] : CharacterCreatorHandler.instance.selectedPlayerFaces[pickerID]); + GetComponent<PhotonView>().RPC("RPCA_SetFace", RpcTarget.All, playerFace.eyeID, playerFace.eyeOffset, playerFace.mouthID, playerFace.mouthOffset, playerFace.detailID, playerFace.detailOffset, playerFace.detail2ID, playerFace.detail2Offset); + } + currentSkin = Object.Instantiate(PlayerSkinBank.GetPlayerSkinColors(pickerID).gameObject, base.transform.GetChild(0).transform.position, Quaternion.identity, base.transform.GetChild(0).transform); + currentSkin.GetComponentInChildren<ParticleSystem>().Play(); + leftHandTarget.position = base.transform.GetChild(0).position; + rightHandTarget.position = base.transform.GetChild(0).position; + leftHandVel *= 0f; + rightHandVel *= 0f; + StopAllCoroutines(); + } + + public void Hide() + { + GetComponent<CurveAnimation>().PlayOut(); + StartCoroutine(DelayHide()); + } + + private IEnumerator DelayHide() + { + yield return new WaitForSecondsRealtime(0.3f); + base.transform.GetChild(0).gameObject.SetActive(value: false); + isShowinig = false; + } + + internal void SetCurrentSelected(int toSet) + { + GetComponent<PhotonView>().RPC("RPCA_SetCurrentSelected", RpcTarget.All, toSet); + } + + [PunRPC] + internal void RPCA_SetCurrentSelected(int toSet) + { + SoundManager.Instance.Play(soundCardSwitch, base.transform); + currentCardSelected = toSet; + } +} diff --git a/ROUNDS/CardInfo.cs b/ROUNDS/CardInfo.cs new file mode 100644 index 0000000..e0b39fc --- /dev/null +++ b/ROUNDS/CardInfo.cs @@ -0,0 +1,68 @@ +using Photon.Pun; +using Sirenix.OdinInspector; +using UnityEngine; + +public class CardInfo : MonoBehaviour +{ + public enum Rarity + { + Common, + Uncommon, + Rare + } + + [Header("Sound Settings")] + public bool soundDisableBlockBasic; + + [Header("Settings")] + public string cardName = ""; + + [TextArea] + public string cardDestription = ""; + + public CardInfoStat[] cardStats; + + public Rarity rarity; + + public GameObject cardArt; + + public Sprite sprite; + + [HideInInspector] + public CardInfo sourceCard; + + public Color cardColor = new Color(0.14509805f, 0.14509805f, 0.14509805f); + + public CardCategory[] categories; + + [FoldoutGroup("Restrictions", 0)] + public bool allowMultiple = true; + + [FoldoutGroup("Restrictions", 0)] + public CardCategory[] blacklistedCategories; + + public GameObject cardBase; + + public CardThemeColor.CardThemeColorType colorTheme; + + private void Awake() + { + sourceCard = CardChoice.instance.GetSourceCard(this); + cardBase = Object.Instantiate(cardBase, base.transform.position, base.transform.rotation); + cardBase.transform.SetParent(base.transform, worldPositionStays: true); + bool charge = false; + Gun component = GetComponent<Gun>(); + if ((bool)component && component.useCharge) + { + charge = true; + } + cardBase.GetComponent<CardInfoDisplayer>().DrawCard(cardStats, cardName, cardDestription, sprite, charge); + cardBase.GetComponentInChildren<GeneralParticleSystem>().particleSettings.randomColor = cardColor; + } + + [PunRPC] + public void RPCA_ChangeSelected(bool setSelected) + { + GetComponentInChildren<CardVisuals>().ChangeSelected(setSelected); + } +} diff --git a/ROUNDS/CardInfoDisplayer.cs b/ROUNDS/CardInfoDisplayer.cs new file mode 100644 index 0000000..7c19bfe --- /dev/null +++ b/ROUNDS/CardInfoDisplayer.cs @@ -0,0 +1,61 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CardInfoDisplayer : MonoBehaviour +{ + public Color negativeColor; + + public Color positiveColor; + + public GameObject statObject; + + public GameObject grid; + + public GameObject chargeObj; + + public TextMeshProUGUI effectText; + + public TextMeshProUGUI nameText; + + public Image icon; + + public void DrawCard(CardInfoStat[] stats, string cardName, string description = "", Sprite image = null, bool charge = false) + { + if (charge) + { + chargeObj.SetActive(value: true); + chargeObj.transform.SetParent(grid.transform, worldPositionStays: true); + } + if (description != "") + { + effectText.text = description; + effectText.gameObject.SetActive(value: true); + effectText.transform.SetParent(grid.transform, worldPositionStays: true); + } + nameText.text = cardName.ToUpper(); + for (int i = 0; i < stats.Length; i++) + { + GameObject obj = Object.Instantiate(statObject, grid.transform.position, grid.transform.rotation, grid.transform); + obj.SetActive(value: true); + obj.transform.localScale = Vector3.one; + TextMeshProUGUI component = obj.transform.GetChild(0).GetComponent<TextMeshProUGUI>(); + TextMeshProUGUI component2 = obj.transform.GetChild(1).GetComponent<TextMeshProUGUI>(); + component.text = stats[i].stat; + if (stats[i].simepleAmount != 0 && !Optionshandler.showCardStatNumbers) + { + component2.text = stats[i].GetSimpleAmount(); + } + else + { + component2.text = stats[i].amount; + } + component2.color = (stats[i].positive ? positiveColor : negativeColor); + } + if ((bool)image) + { + icon.sprite = image; + } + effectText.transform.position += Vector3.up * 0.3f; + } +} diff --git a/ROUNDS/CardInfoStat.cs b/ROUNDS/CardInfoStat.cs new file mode 100644 index 0000000..943936c --- /dev/null +++ b/ROUNDS/CardInfoStat.cs @@ -0,0 +1,69 @@ +using System; + +[Serializable] +public class CardInfoStat +{ + public enum SimpleAmount + { + notAssigned, + aLittleBitOf, + Some, + aLotOf, + aHugeAmountOf, + slightlyLower, + lower, + aLotLower, + slightlySmaller, + smaller + } + + public bool positive; + + public string amount; + + public SimpleAmount simepleAmount; + + public string stat; + + public string GetSimpleAmount() + { + string result = ""; + if (simepleAmount == SimpleAmount.aLittleBitOf) + { + result = "Slightly more "; + } + if (simepleAmount == SimpleAmount.Some) + { + result = "More "; + } + if (simepleAmount == SimpleAmount.aLotOf) + { + result = "A bunch more "; + } + if (simepleAmount == SimpleAmount.aHugeAmountOf) + { + result = "A huge amount of"; + } + if (simepleAmount == SimpleAmount.slightlyLower) + { + result = "Slightly lower "; + } + if (simepleAmount == SimpleAmount.lower) + { + result = "Lower "; + } + if (simepleAmount == SimpleAmount.aLotLower) + { + result = "A lot lower"; + } + if (simepleAmount == SimpleAmount.smaller) + { + result = "Smaller"; + } + if (simepleAmount == SimpleAmount.slightlySmaller) + { + result = "Slightly smaller"; + } + return result; + } +} diff --git a/ROUNDS/CardRarityColor.cs b/ROUNDS/CardRarityColor.cs new file mode 100644 index 0000000..3008ae7 --- /dev/null +++ b/ROUNDS/CardRarityColor.cs @@ -0,0 +1,33 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +public class CardRarityColor : MonoBehaviour +{ + public Color uncommonColor; + + public Color rareColor; + + public Color uncommonColorOff; + + public Color rareColorOff; + + private void Awake() + { + CardVisuals componentInParent = GetComponentInParent<CardVisuals>(); + componentInParent.toggleSelectionAction = (Action<bool>)Delegate.Combine(componentInParent.toggleSelectionAction, new Action<bool>(Toggle)); + } + + public void Toggle(bool isOn) + { + CardInfo componentInParent = GetComponentInParent<CardInfo>(); + if (componentInParent.rarity == CardInfo.Rarity.Uncommon) + { + GetComponent<Image>().color = (isOn ? uncommonColor : uncommonColorOff); + } + if (componentInParent.rarity == CardInfo.Rarity.Rare) + { + GetComponent<Image>().color = (isOn ? rareColor : rareColorOff); + } + } +} diff --git a/ROUNDS/CardThemeColor.cs b/ROUNDS/CardThemeColor.cs new file mode 100644 index 0000000..780dcd5 --- /dev/null +++ b/ROUNDS/CardThemeColor.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; + +[Serializable] +public class CardThemeColor +{ + public enum CardThemeColorType + { + DestructiveRed, + FirepowerYellow, + DefensiveBlue, + TechWhite, + EvilPurple, + PoisonGreen, + NatureBrown, + ColdBlue, + MagicPink + } + + public CardThemeColorType themeType; + + public Color targetColor; + + public Color bgColor; +} diff --git a/ROUNDS/CardVisuals.cs b/ROUNDS/CardVisuals.cs new file mode 100644 index 0000000..483d5d7 --- /dev/null +++ b/ROUNDS/CardVisuals.cs @@ -0,0 +1,138 @@ +using System; +using Photon.Pun; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CardVisuals : MonoBehaviour +{ + private ScaleShake shake; + + public bool isSelected; + + private GeneralParticleSystem part; + + private Color selectedColor; + + private Color unSelectedColor = new Color(0.1f, 0.1f, 0.1f); + + public Color defaultColor; + + public Color chillColor; + + public Image[] images; + + public TextMeshProUGUI nameText; + + public GameObject statsObj; + + public GameObject[] objectsToToggle; + + private CardAnimation[] cardAnims; + + private CanvasGroup group; + + public bool firstValueToSet; + + public Action<bool> toggleSelectionAction; + + private void Start() + { + group = base.transform.Find("Canvas/Front/Grid").GetComponent<CanvasGroup>(); + selectedColor = GetComponentInParent<CardInfo>().cardColor; + part = GetComponentInChildren<GeneralParticleSystem>(); + shake = GetComponent<ScaleShake>(); + Transform transform = base.transform.Find("Canvas/Front/Background/Art"); + CardInfo componentInParent = GetComponentInParent<CardInfo>(); + defaultColor = CardChoice.instance.GetCardColor(componentInParent.colorTheme); + selectedColor = CardChoice.instance.GetCardColor2(componentInParent.colorTheme); + if ((bool)componentInParent.cardArt) + { + GameObject obj = UnityEngine.Object.Instantiate(componentInParent.cardArt, transform.transform.position, transform.transform.rotation, transform); + obj.transform.localPosition = Vector3.zero; + obj.transform.SetAsFirstSibling(); + obj.transform.localScale = Vector3.one; + } + cardAnims = GetComponentsInChildren<CardAnimation>(); + isSelected = !firstValueToSet; + ChangeSelected(firstValueToSet); + } + + public void Leave() + { + UnityEngine.Object.Destroy(base.transform.root.gameObject); + } + + public void Pick() + { + PhotonNetwork.Destroy(base.transform.root.gameObject); + } + + public void ChangeSelected(bool setSelected) + { + if (!part || isSelected == setSelected) + { + return; + } + isSelected = setSelected; + toggleSelectionAction?.Invoke(isSelected); + if (isSelected) + { + part.simulationSpeedMultiplier = 1.25f; + part.particleSettings.randomColor = selectedColor; + shake.targetScale = 1.15f; + group.alpha = 1f; + for (int i = 0; i < images.Length; i++) + { + images[i].color = defaultColor; + } + for (int j = 0; j < objectsToToggle.Length; j++) + { + objectsToToggle[j].SetActive(value: false); + } + for (int k = 0; k < cardAnims.Length; k++) + { + cardAnims[k].enabled = true; + } + nameText.color = defaultColor; + CurveAnimation[] componentsInChildren = GetComponentsInChildren<CurveAnimation>(); + for (int l = 0; l < componentsInChildren.Length; l++) + { + if (componentsInChildren[l].transform.parent != base.transform) + { + componentsInChildren[l].PlayIn(); + } + else if (componentsInChildren[l].currentState != 0) + { + componentsInChildren[l].PlayIn(); + } + } + return; + } + part.simulationSpeedMultiplier = 0.5f; + part.particleSettings.randomColor = unSelectedColor; + shake.targetScale = 0.9f; + group.alpha = 0.15f; + for (int m = 0; m < images.Length; m++) + { + images[m].color = chillColor; + } + for (int n = 0; n < objectsToToggle.Length; n++) + { + objectsToToggle[n].SetActive(value: true); + } + for (int num = 0; num < cardAnims.Length; num++) + { + cardAnims[num].enabled = false; + } + nameText.color = chillColor; + CurveAnimation[] componentsInChildren2 = GetComponentsInChildren<CurveAnimation>(); + for (int num2 = 0; num2 < componentsInChildren2.Length; num2++) + { + if (componentsInChildren2[num2].transform.parent != base.transform) + { + componentsInChildren2[num2].PlayOut(); + } + } + } +} diff --git a/ROUNDS/ChangeColor.cs b/ROUNDS/ChangeColor.cs new file mode 100644 index 0000000..a0d61bf --- /dev/null +++ b/ROUNDS/ChangeColor.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class ChangeColor : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/ChangeDamageMultiplierAfterDistanceTravelled.cs b/ROUNDS/ChangeDamageMultiplierAfterDistanceTravelled.cs new file mode 100644 index 0000000..7bd1bf8 --- /dev/null +++ b/ROUNDS/ChangeDamageMultiplierAfterDistanceTravelled.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class ChangeDamageMultiplierAfterDistanceTravelled : MonoBehaviour +{ + public float muiltiplier = 2f; + + public float distance = 10f; + + private ProjectileHit hit; + + private MoveTransform move; + + private TrailRenderer trail; + + private void Awake() + { + trail = GetComponentInChildren<TrailRenderer>(); + } + + private void Start() + { + hit = GetComponent<ProjectileHit>(); + move = GetComponent<MoveTransform>(); + } + + private void Update() + { + if (move.distanceTravelled > distance) + { + hit.damage *= muiltiplier; + hit.shake *= muiltiplier; + if ((bool)trail) + { + trail.widthMultiplier *= 2f; + } + Object.Destroy(this); + } + } +} diff --git a/ROUNDS/ChannelMessage.cs b/ROUNDS/ChannelMessage.cs new file mode 100644 index 0000000..2349349 --- /dev/null +++ b/ROUNDS/ChannelMessage.cs @@ -0,0 +1,3 @@ +using Irc; + +public delegate void ChannelMessage(ChannelMessageEventArgs channelMessageArgs); diff --git a/ROUNDS/CharacterCreator.cs b/ROUNDS/CharacterCreator.cs new file mode 100644 index 0000000..55d31ed --- /dev/null +++ b/ROUNDS/CharacterCreator.cs @@ -0,0 +1,101 @@ +using System; +using UnityEngine; + +public class CharacterCreator : MonoBehaviour +{ + public PlayerFace currentPlayerFace; + + public GameObject objectToEnable; + + public int playerID; + + public int portraitID; + + public bool ready; + + public PlayerActions playerActions; + + public GeneralInput.InputType inputType; + + public MenuControllerHandler.MenuControl currentControl = MenuControllerHandler.MenuControl.Unassigned; + + public MenuControllerHandler.MenuControl lastControl = MenuControllerHandler.MenuControl.Unassigned; + + public Action<MenuControllerHandler.MenuControl> SwitchAction; + + public CharacterCreatorNavigation nav; + + private void Start() + { + nav = GetComponentInChildren<CharacterCreatorNavigation>(); + } + + private void Update() + { + if (currentControl != lastControl) + { + SwitchAction?.Invoke(currentControl); + } + lastControl = currentControl; + } + + public void Close() + { + CharacterCreatorHandler.instance.ReleasePortrait(portraitID); + if (playerActions == null) + { + base.gameObject.SetActive(value: false); + MainMenuHandler.instance.Open(); + } + else + { + objectToEnable.SetActive(value: true); + base.gameObject.SetActive(value: false); + } + } + + public void Finish() + { + CharacterCreatorHandler.instance.ReleasePortrait(portraitID); + CharacterCreatorHandler.instance.SetFacePreset(portraitID, currentPlayerFace); + CharacterCreatorHandler.instance.SelectFace(0, currentPlayerFace, portraitID); + if (playerActions == null) + { + base.gameObject.SetActive(value: false); + MainMenuHandler.instance.Open(); + } + else + { + objectToEnable.SetActive(value: true); + base.gameObject.SetActive(value: false); + } + } + + internal void SetOffset(Vector2 offset, CharacterItemType itemType, int slotID) + { + if (itemType == CharacterItemType.Eyes) + { + currentPlayerFace.eyeOffset = offset; + } + if (itemType == CharacterItemType.Mouth) + { + currentPlayerFace.mouthOffset = offset; + } + if (itemType == CharacterItemType.Detail) + { + if (slotID == 0) + { + currentPlayerFace.detailOffset = offset; + } + if (slotID == 1) + { + currentPlayerFace.detail2Offset = offset; + } + } + } + + internal void SpawnFace(PlayerFace currentFace) + { + GetComponentInChildren<CharacterCreatorItemEquipper>().SpawnPlayerFace(currentFace); + } +} diff --git a/ROUNDS/CharacterCreatorButtonSpawner.cs b/ROUNDS/CharacterCreatorButtonSpawner.cs new file mode 100644 index 0000000..9e0fffb --- /dev/null +++ b/ROUNDS/CharacterCreatorButtonSpawner.cs @@ -0,0 +1,146 @@ +using UnityEngine; + +public class CharacterCreatorButtonSpawner : MonoBehaviour +{ + public GameObject sourceButton; + + private CharacterCreatorItemLoader loader; + + private CharacterCreator creator; + + private void Start() + { + creator = GetComponent<CharacterCreator>(); + loader = CharacterCreatorItemLoader.instance; + OpenMenu(CharacterItemType.Eyes, 0); + } + + public void OpenMenu(int id) + { + if (id == 0) + { + OpenMenu(CharacterItemType.Eyes, 0); + } + if (id == 1) + { + OpenMenu(CharacterItemType.Mouth, 0); + } + if (id == 2) + { + OpenMenu(CharacterItemType.Detail, 0); + } + if (id == 3) + { + OpenMenu(CharacterItemType.Detail, 1); + } + } + + public void OpenMenu(CharacterItemType target, int slotNr) + { + CharacterItem[] array = null; + if (target == CharacterItemType.Eyes) + { + array = loader.eyes; + } + if (target == CharacterItemType.Mouth) + { + array = loader.mouths; + } + if (target == CharacterItemType.Detail) + { + array = loader.accessories; + } + for (int i = 0; i < sourceButton.transform.parent.childCount; i++) + { + if (sourceButton.transform.parent.GetChild(i).gameObject.activeSelf) + { + Object.Destroy(sourceButton.transform.parent.GetChild(i).gameObject); + } + } + for (int j = 0; j < array.Length; j++) + { + GameObject gameObject = Object.Instantiate(sourceButton, sourceButton.transform.parent); + gameObject.SetActive(value: true); + Transform parent = gameObject.transform.Find("ItemParent"); + GameObject gameObject2 = Object.Instantiate(array[j].gameObject, parent); + gameObject.GetComponent<CharacterItemButton>().itemType = target; + gameObject.GetComponent<CharacterItemButton>().slotNr = slotNr; + gameObject.GetComponentInChildren<CharacterItem>().sprite = array[j].gameObject.GetComponent<SpriteRenderer>().sprite; + gameObject2.GetComponentInChildren<CharacterItem>().GetComponent<SpriteRenderer>().sortingOrder = array[j].gameObject.GetComponent<SpriteRenderer>().sortingOrder; + gameObject2.GetComponentInChildren<CharacterItem>().scale = array[j].scale; + gameObject2.GetComponentInChildren<CharacterItem>().itemType = target; + gameObject2.GetComponentInChildren<CharacterItem>().offset = array[j].offset; + gameObject2.GetComponentInChildren<CharacterItem>().slotNr = slotNr; + gameObject2.GetComponentInChildren<SpriteRenderer>().transform.localPosition = array[j].offset; + gameObject2.GetComponentInChildren<SpriteRenderer>().transform.localScale = array[j].scale * Vector2.one; + if (target == CharacterItemType.Eyes && j == creator.currentPlayerFace.eyeID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + if (target == CharacterItemType.Mouth && j == creator.currentPlayerFace.mouthID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + if (target == CharacterItemType.Detail && j == creator.currentPlayerFace.detailID && slotNr == 0) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + if (target == CharacterItemType.Detail && slotNr == 1 && j == creator.currentPlayerFace.detail2ID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + } + } + + public void SelectButton(CharacterItemType itemType, int slotNr) + { + for (int i = 0; i < sourceButton.transform.parent.childCount; i++) + { + GameObject gameObject = sourceButton.transform.parent.GetChild(i).gameObject; + if (itemType == CharacterItemType.Eyes) + { + if (i - 1 == creator.currentPlayerFace.eyeID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + if (itemType == CharacterItemType.Mouth) + { + if (i - 1 == creator.currentPlayerFace.mouthID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + if (itemType == CharacterItemType.Detail) + { + if (i - 1 == creator.currentPlayerFace.detailID && slotNr == 0) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + if (itemType == CharacterItemType.Detail && slotNr == 1) + { + if (i - 1 == creator.currentPlayerFace.detail2ID) + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: true); + } + else + { + gameObject.transform.Find("SelectedDot").gameObject.SetActive(value: false); + } + } + } + } +} diff --git a/ROUNDS/CharacterCreatorDragging.cs b/ROUNDS/CharacterCreatorDragging.cs new file mode 100644 index 0000000..21ec9f1 --- /dev/null +++ b/ROUNDS/CharacterCreatorDragging.cs @@ -0,0 +1,116 @@ +using InControl; +using UnityEngine; + +public class CharacterCreatorDragging : MonoBehaviour +{ + public Vector2 rightStick; + + private CharacterCreator creator; + + private Transform draggedObject; + + private Vector2 lastMouse = Vector3.zero; + + private void Start() + { + creator = GetComponentInParent<CharacterCreator>(); + } + + private void Update() + { + if (creator.inputType == GeneralInput.InputType.Keyboard || creator.inputType == GeneralInput.InputType.Either) + { + DoMouse(); + } + if (creator.inputType == GeneralInput.InputType.Controller || creator.inputType == GeneralInput.InputType.Either) + { + DoController(); + } + } + + private void DoController() + { + int num = -1; + int barPos = creator.nav.barPos; + for (int i = 0; i < base.transform.childCount; i++) + { + CharacterItem component = base.transform.GetChild(i).GetComponent<CharacterItem>(); + if (barPos == 0 && component.itemType == CharacterItemType.Eyes) + { + num = i; + } + if (barPos == 1 && component.itemType == CharacterItemType.Mouth) + { + num = i; + } + if (barPos == 2 && component.itemType == CharacterItemType.Detail && component.slotNr == 0) + { + num = i; + } + if (barPos == 3 && component.itemType == CharacterItemType.Detail && component.slotNr == 1) + { + num = i; + } + } + if (num >= base.transform.childCount) + { + return; + } + Vector2 vector = Vector2.zero; + if (creator.playerActions != null) + { + vector = creator.playerActions.Aim.Value; + } + else + { + for (int j = 0; j < InputManager.ActiveDevices.Count; j++) + { + vector = InputManager.ActiveDevices[j].RightStick.Value; + } + } + base.transform.GetChild(num).transform.position += (Vector3)vector * Time.deltaTime * 3f; + if (vector != Vector2.zero) + { + CharacterItem component2 = base.transform.GetChild(num).GetComponent<CharacterItem>(); + Vector2 offset = (Vector2)base.transform.GetChild(num).localPosition - component2.offset; + creator.SetOffset(offset, component2.itemType, component2.slotNr); + } + } + + private void DoMouse() + { + Vector2 vector = MainCam.instance.cam.ScreenToWorldPoint(Input.mousePosition); + if (Input.GetKeyDown(KeyCode.Mouse0)) + { + float num = 2f; + int num2 = -1; + for (int i = 0; i < base.transform.childCount; i++) + { + float num3 = Vector2.Distance(vector, base.transform.GetChild(i).transform.position); + Debug.DrawLine(vector, base.transform.GetChild(i).GetComponent<SpriteRenderer>().bounds.center, Color.red, 2f); + if (num3 < num) + { + num = num3; + num2 = i; + } + } + if (num2 != -1) + { + draggedObject = base.transform.GetChild(num2); + } + } + if (Input.GetKeyUp(KeyCode.Mouse0) && (bool)draggedObject) + { + CharacterItem component = draggedObject.GetComponent<CharacterItem>(); + Vector2 offset = (Vector2)draggedObject.transform.localPosition - component.offset; + creator.SetOffset(offset, component.itemType, component.slotNr); + draggedObject = null; + } + if ((bool)draggedObject) + { + draggedObject.transform.position += (Vector3)(vector - lastMouse); + draggedObject.transform.localPosition = Vector2.ClampMagnitude(draggedObject.transform.localPosition, 4.5f); + } + lastMouse = vector; + } +} diff --git a/ROUNDS/CharacterCreatorHandler.cs b/ROUNDS/CharacterCreatorHandler.cs new file mode 100644 index 0000000..1dd23c7 --- /dev/null +++ b/ROUNDS/CharacterCreatorHandler.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class CharacterCreatorHandler : MonoBehaviour +{ + public static CharacterCreatorHandler instance; + + public PlayerFace[] playerFaces = new PlayerFace[10]; + + public PlayerFace[] selectedPlayerFaces = new PlayerFace[4]; + + public int[] selectedFaceID = new int[4]; + + public List<int> lockedPortraits; + + public Action lockedPortraitAction; + + public Action<int> faceWasUpdatedAction; + + public void LockPortrait(int portrait) + { + lockedPortraits.Add(portrait); + lockedPortraitAction?.Invoke(); + } + + public void ReleasePortrait(int porttrait) + { + for (int i = 0; i < lockedPortraits.Count; i++) + { + if (porttrait == lockedPortraits[i]) + { + lockedPortraits.RemoveAt(i); + break; + } + } + lockedPortraitAction?.Invoke(); + } + + private void ReleaseAllPortraits() + { + lockedPortraits.Clear(); + lockedPortraitAction?.Invoke(); + } + + private void Awake() + { + instance = this; + for (int i = 0; i < playerFaces.Length; i++) + { + playerFaces[i].LoadFace(i.ToString()); + } + for (int j = 0; j < selectedFaceID.Length; j++) + { + selectedFaceID[j] = PlayerPrefs.GetInt("SelectedFace" + j); + SelectFace(j, playerFaces[selectedFaceID[j]], selectedFaceID[j]); + } + } + + internal void SelectFace(int faceID, PlayerFace selectedFace, int faceSlot) + { + selectedFaceID[faceID] = faceSlot; + PlayerPrefs.SetInt("SelectedFace" + faceID, selectedFaceID[faceID]); + selectedPlayerFaces[faceID] = selectedFace; + } + + public PlayerFace GetFacePreset(int faceID) + { + return playerFaces[faceID]; + } + + public bool SomeoneIsEditing() + { + for (int i = 0; i < base.transform.childCount; i++) + { + if (base.transform.GetChild(i).gameObject.activeSelf) + { + return true; + } + } + return false; + } + + internal void SetFacePreset(int faceID, PlayerFace currentPlayerFace) + { + playerFaces[faceID] = PlayerFace.CopyFace(currentPlayerFace); + playerFaces[faceID].SaveFace(faceID.ToString()); + faceWasUpdatedAction?.Invoke(faceID); + } + + public void EditCharacterLocalMultiplayer(int playerId, int portraitID, GameObject objectToEnable, PlayerFace currentFace) + { + LockPortrait(portraitID); + CharacterCreator component = base.transform.GetChild(playerId + 1).GetComponent<CharacterCreator>(); + component.playerActions = PlayerManager.instance.players[playerId].data.playerActions; + component.inputType = PlayerManager.instance.players[playerId].data.input.inputType; + component.gameObject.SetActive(value: true); + component.playerID = playerId; + component.objectToEnable = objectToEnable; + component.currentPlayerFace = currentFace; + component.portraitID = portraitID; + component.SpawnFace(currentFace); + } + + public void EditCharacterPortrait(int portraitID, PlayerFace currentFace) + { + LockPortrait(portraitID); + MainMenuHandler.instance.Close(); + CharacterCreator component = base.transform.GetChild(0).GetComponent<CharacterCreator>(); + component.inputType = GeneralInput.InputType.Either; + component.currentPlayerFace = currentFace; + component.gameObject.SetActive(value: true); + component.playerID = 0; + component.portraitID = portraitID; + component.SpawnFace(currentFace); + } + + public void CloseMenus() + { + for (int i = 0; i < base.transform.childCount; i++) + { + base.transform.GetChild(i).GetComponent<CharacterCreator>().Close(); + } + ReleaseAllPortraits(); + } + + public void EndCustomization(int playerId = -1) + { + if (playerId == -1) + { + GetComponentInChildren<CharacterCreator>(includeInactive: true).Finish(); + base.transform.GetChild(0).gameObject.SetActive(value: false); + } + } +} diff --git a/ROUNDS/CharacterCreatorItemEquipper.cs b/ROUNDS/CharacterCreatorItemEquipper.cs new file mode 100644 index 0000000..ba03491 --- /dev/null +++ b/ROUNDS/CharacterCreatorItemEquipper.cs @@ -0,0 +1,130 @@ +using Photon.Pun; +using UnityEngine; + +public class CharacterCreatorItemEquipper : MonoBehaviour +{ + public GameObject itemParent; + + public GameObject defaultEyes; + + public GameObject defaultMouth; + + private CharacterCreatorItemLoader itemLoader; + + private CharacterCreator creator; + + public float scaleM = 1f; + + private bool spawnedSpecific; + + private bool inited; + + private void Start() + { + Init(); + if ((bool)creator && !spawnedSpecific) + { + Equip(defaultEyes.GetComponent<CharacterItem>(), CharacterItemType.Eyes); + Equip(defaultMouth.GetComponent<CharacterItem>(), CharacterItemType.Mouth); + } + } + + public void SpawnPlayerFace(PlayerFace newFace) + { + spawnedSpecific = true; + EquipFace(newFace); + } + + private void Init() + { + if (!inited) + { + inited = true; + creator = GetComponent<CharacterCreator>(); + itemLoader = CharacterCreatorItemLoader.instance; + } + } + + [PunRPC] + public void RPCA_SetFace(int eyeID, Vector2 eyeOffset, int mouthID, Vector2 mouthOffset, int detailID, Vector2 detailOffset, int detail2ID, Vector2 detail2Offset) + { + PlayerFace face = PlayerFace.CreateFace(eyeID, eyeOffset, mouthID, mouthOffset, detailID, detailOffset, detail2ID, detail2Offset); + EquipFace(face); + } + + public void EquipFace(PlayerFace face) + { + Init(); + Equip(itemLoader.GetItem(face.eyeID, CharacterItemType.Eyes), CharacterItemType.Eyes, face.eyeOffset); + Equip(itemLoader.GetItem(face.mouthID, CharacterItemType.Mouth), CharacterItemType.Mouth, face.mouthOffset); + Equip(itemLoader.GetItem(face.detailID, CharacterItemType.Detail), CharacterItemType.Detail, face.detailOffset); + Equip(itemLoader.GetItem(face.detail2ID, CharacterItemType.Detail), CharacterItemType.Detail, face.detail2Offset, 1); + } + + public void Equip(CharacterItem newSprite, CharacterItemType itemType, Vector2 offset = default(Vector2), int slotNr = 0) + { + if (newSprite == null) + { + return; + } + Init(); + if ((bool)creator) + { + if (itemType == CharacterItemType.Eyes) + { + creator.currentPlayerFace.eyeID = itemLoader.GetItemID(newSprite, itemType); + } + if (itemType == CharacterItemType.Mouth) + { + creator.currentPlayerFace.mouthID = itemLoader.GetItemID(newSprite, itemType); + } + if (itemType == CharacterItemType.Detail) + { + if (slotNr == 0) + { + creator.currentPlayerFace.detailID = itemLoader.GetItemID(newSprite, itemType); + } + if (slotNr == 1) + { + creator.currentPlayerFace.detail2ID = itemLoader.GetItemID(newSprite, itemType); + } + } + } + Clear(itemType, slotNr); + SpawnItem(newSprite, itemType, offset, slotNr); + CopyChildren[] componentsInChildren = GetComponentsInChildren<CopyChildren>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].DoUpdate(); + } + } + + private void SpawnItem(CharacterItem newSprite, CharacterItemType itemType, Vector2 offset = default(Vector2), int slotNr = 0) + { + GameObject obj = Object.Instantiate(newSprite.gameObject); + obj.gameObject.SetActive(value: true); + obj.transform.SetParent(itemParent.transform); + obj.GetComponent<SpriteRenderer>().sprite = newSprite.GetComponent<CharacterItem>().sprite; + obj.GetComponent<SpriteRenderer>().sortingOrder = newSprite.GetComponent<CharacterItem>().GetComponent<SpriteRenderer>().sortingOrder; + obj.GetComponent<CharacterItem>().itemType = itemType; + obj.GetComponent<SpriteRenderer>().color = newSprite.GetComponent<SpriteRenderer>().color; + obj.GetComponentInChildren<CharacterItem>().offset = newSprite.GetComponent<CharacterItem>().offset; + obj.GetComponentInChildren<CharacterItem>().sprite = newSprite.GetComponent<CharacterItem>().sprite; + obj.GetComponentInChildren<CharacterItem>().slotNr = slotNr; + obj.transform.localScale = newSprite.GetComponent<CharacterItem>().scale * Vector3.one * scaleM; + obj.transform.localPosition = (newSprite.GetComponent<CharacterItem>().offset + offset) * scaleM; + creator?.SetOffset(offset, itemType, slotNr); + } + + private void Clear(CharacterItemType itemType, int slotNr = 0) + { + for (int i = 0; i < itemParent.transform.childCount; i++) + { + CharacterItem component = itemParent.transform.GetChild(i).GetComponent<CharacterItem>(); + if (component.itemType == itemType && component.slotNr == slotNr) + { + Object.DestroyImmediate(itemParent.transform.GetChild(i).gameObject); + } + } + } +} diff --git a/ROUNDS/CharacterCreatorItemLoader.cs b/ROUNDS/CharacterCreatorItemLoader.cs new file mode 100644 index 0000000..2a79940 --- /dev/null +++ b/ROUNDS/CharacterCreatorItemLoader.cs @@ -0,0 +1,77 @@ +using UnityEngine; + +public class CharacterCreatorItemLoader : MonoBehaviour +{ + public CharacterItem[] eyes; + + public CharacterItem[] mouths; + + public CharacterItem[] accessories; + + public static CharacterCreatorItemLoader instance; + + private void Awake() + { + instance = this; + } + + private void Update() + { + } + + internal CharacterItem GetItem(int itemID, CharacterItemType itemType) + { + try + { + return itemType switch + { + CharacterItemType.Eyes => eyes[itemID], + CharacterItemType.Mouth => mouths[itemID], + _ => accessories[itemID], + }; + } + catch + { + return null; + } + } + + internal int GetItemID(CharacterItem newSprite, CharacterItemType itemType) + { + CharacterItem[] array = null; + array = itemType switch + { + CharacterItemType.Eyes => eyes, + CharacterItemType.Mouth => mouths, + _ => accessories, + }; + for (int i = 0; i < array.Length; i++) + { + if (array[i].sprite == newSprite.sprite) + { + return i; + } + } + return -1; + } + + public void UpdateItems(CharacterItemType target, CharacterItem[] items) + { + for (int i = 0; i < items.Length; i++) + { + items[i].sprite = items[i].GetComponent<SpriteRenderer>().sprite; + } + if (target == CharacterItemType.Eyes) + { + eyes = items; + } + if (target == CharacterItemType.Mouth) + { + mouths = items; + } + if (target == CharacterItemType.Detail) + { + accessories = items; + } + } +} diff --git a/ROUNDS/CharacterCreatorNavigation.cs b/ROUNDS/CharacterCreatorNavigation.cs new file mode 100644 index 0000000..46292e4 --- /dev/null +++ b/ROUNDS/CharacterCreatorNavigation.cs @@ -0,0 +1,162 @@ +using InControl; +using UnityEngine; +using UnityEngine.UI; + +public class CharacterCreatorNavigation : MonoBehaviour +{ + private int itemsInRow = 7; + + private CharacterCreator creator; + + private Transform grid; + + private Transform bar; + + private GameObject currentObject; + + private GameObject currentBarObject; + + private CharacterCreatorDragging dragging; + + public int x; + + public int y; + + public int barPos; + + private float cd; + + private void Awake() + { + creator = GetComponent<CharacterCreator>(); + dragging = GetComponentInChildren<CharacterCreatorDragging>(); + grid = base.transform.GetChild(0).GetChild(0); + bar = base.transform.GetChild(0).GetChild(1); + } + + private void Update() + { + if (creator.playerActions != null) + { + PlayerActionUpdate(creator.playerActions.Device); + } + else if (creator.playerActions == null) + { + creator.currentControl = MenuControllerHandler.menuControl; + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + InputDevice device = InputManager.ActiveDevices[i]; + PlayerActionUpdate(device); + } + } + } + + private void PlayerActionUpdate(InputDevice device) + { + cd += Time.unscaledDeltaTime; + if (device != null) + { + if (device.CommandWasPressed) + { + creator.Finish(); + } + dragging.rightStick = device.RightStick.Value; + GridMovement(device); + BarMovement(device); + } + } + + private void BarMovement(InputDevice device) + { + if (!currentBarObject) + { + MoveNav(0); + } + if (device.LeftTrigger.WasPressed) + { + MoveNav(-1); + } + if (device.RightTrigger.WasPressed) + { + MoveNav(1); + } + } + + private void MoveNav(int delta) + { + cd = 0f; + if (delta > 0) + { + barPos++; + } + if (delta < 0) + { + barPos--; + } + VerifyBarPos(); + } + + private void VerifyBarPos() + { + if ((bool)currentBarObject) + { + currentBarObject.GetComponent<HoverEvent>().exitEvent.Invoke(); + } + barPos = Mathf.Clamp(barPos, 0, 3); + currentBarObject = bar.GetChild(barPos).gameObject; + currentBarObject.GetComponent<HoverEvent>().enterEvent.Invoke(); + currentBarObject.GetComponent<Button>().onClick.Invoke(); + } + + private void GridMovement(InputDevice device) + { + if (!currentObject) + { + MoveNav(Vector2.zero); + } + if (device.LeftStick.Value.magnitude > 0.75f && cd > 0.1f) + { + MoveNav(device.LeftStick); + } + if (device.Action1.WasPressed) + { + currentObject.GetComponent<Button>().onClick.Invoke(); + } + } + + private void MoveNav(Vector2 delta) + { + cd = 0f; + if (delta.x > 0.5f) + { + x++; + } + if (delta.x < -0.5f) + { + x--; + } + if (delta.y > 0.5f) + { + y--; + } + if (delta.y < -0.5f) + { + y++; + } + VerifyPos(); + } + + private void VerifyPos() + { + if ((bool)currentObject) + { + currentObject.GetComponent<HoverEvent>().exitEvent.Invoke(); + } + x = Mathf.Clamp(x, 1, itemsInRow); + y = Mathf.Clamp(y, 0, Mathf.CeilToInt((grid.childCount - 2) / itemsInRow)); + x = Mathf.Clamp(x, 1, grid.childCount - y * itemsInRow - 1); + int index = x + y * itemsInRow; + currentObject = grid.GetChild(index).gameObject; + currentObject.GetComponent<HoverEvent>().enterEvent.Invoke(); + } +} diff --git a/ROUNDS/CharacterCreatorPortrait.cs b/ROUNDS/CharacterCreatorPortrait.cs new file mode 100644 index 0000000..1c14cc2 --- /dev/null +++ b/ROUNDS/CharacterCreatorPortrait.cs @@ -0,0 +1,121 @@ +using System; +using InControl; +using UnityEngine; +using UnityEngine.UI; + +public class CharacterCreatorPortrait : MonoBehaviour +{ + public int playerId = -1; + + public PlayerFace myFace; + + public GameObject selectedObj; + + public MenuControllerHandler.MenuControl controlType = MenuControllerHandler.MenuControl.Unassigned; + + private Color defColor; + + private HoverEvent hoverEvent; + + public GameObject lockedObj; + + private bool isLocked; + + private void Start() + { + defColor = base.transform.Find("BG").GetComponent<Image>().color; + CharacterCreatorHandler instance = CharacterCreatorHandler.instance; + instance.faceWasUpdatedAction = (Action<int>)Delegate.Combine(instance.faceWasUpdatedAction, new Action<int>(FaceUpdated)); + myFace = CharacterCreatorHandler.instance.GetFacePreset(base.transform.GetSiblingIndex()); + hoverEvent = GetComponent<HoverEvent>(); + GetComponentInChildren<CharacterCreatorItemEquipper>().EquipFace(myFace); + if (CharacterCreatorHandler.instance.selectedFaceID[0] == base.transform.GetSiblingIndex()) + { + ClickButton(); + } + CharacterCreatorHandler instance2 = CharacterCreatorHandler.instance; + instance2.lockedPortraitAction = (Action)Delegate.Combine(instance2.lockedPortraitAction, new Action(CheckLocked)); + CheckLocked(); + } + + private void CheckLocked() + { + isLocked = false; + for (int i = 0; i < CharacterCreatorHandler.instance.lockedPortraits.Count; i++) + { + if (base.transform.GetSiblingIndex() == CharacterCreatorHandler.instance.lockedPortraits[i]) + { + isLocked = true; + } + } + if (isLocked) + { + lockedObj.SetActive(value: true); + } + else + { + lockedObj.SetActive(value: false); + } + } + + private void FaceUpdated(int faceID) + { + if (faceID == base.transform.GetSiblingIndex()) + { + myFace = CharacterCreatorHandler.instance.GetFacePreset(faceID); + GetComponent<CharacterCreatorItemEquipper>().EquipFace(myFace); + } + } + + public void ClickButton() + { + CharacterCreatorHandler.instance.SelectFace(Mathf.Clamp(playerId, 0, 10), myFace, base.transform.GetSiblingIndex()); + ShownFace(); + } + + private void ShownFace() + { + for (int i = 0; i < base.transform.parent.childCount; i++) + { + if (base.transform.parent.GetChild(i) == base.transform) + { + base.transform.parent.GetChild(i).Find("Frame").gameObject.SetActive(value: true); + } + else + { + base.transform.parent.GetChild(i).Find("Frame").gameObject.SetActive(value: false); + } + } + } + + public void EditCharacter() + { + if (!isLocked) + { + ClickButton(); + if (playerId == -1) + { + CharacterCreatorHandler.instance.EditCharacterPortrait(base.transform.GetSiblingIndex(), myFace); + return; + } + GameObject gameObject = base.transform.parent.parent.parent.gameObject; + gameObject.SetActive(value: false); + CharacterCreatorHandler.instance.EditCharacterLocalMultiplayer(playerId, base.transform.GetSiblingIndex(), gameObject, myFace); + } + } + + private void Update() + { + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].Action4.WasPressed && hoverEvent.isSelected) + { + EditCharacter(); + } + } + if (Input.GetKeyDown(KeyCode.Mouse1) && controlType != 0 && hoverEvent.isHovered) + { + EditCharacter(); + } + } +} diff --git a/ROUNDS/CharacterItem.cs b/ROUNDS/CharacterItem.cs new file mode 100644 index 0000000..4588084 --- /dev/null +++ b/ROUNDS/CharacterItem.cs @@ -0,0 +1,42 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +public class CharacterItem : MonoBehaviour +{ + public Sprite sprite; + + public float scale = 1f; + + public Vector2 offset = Vector2.zero; + + public CharacterItemType itemType; + + internal int slotNr; + + [ShowIf("itemType", CharacterItemType.Detail, true)] + public float moveHealthBarUp; + + [Button] + public void SaveTransform() + { + offset = base.transform.localPosition; + scale = base.transform.localScale.x; + } + + private void Start() + { + if (!base.transform.root.GetComponent<Player>()) + { + return; + } + base.gameObject.AddComponent<CharacterItemMirror>(); + if (moveHealthBarUp != 0f) + { + HealthBar componentInChildren = base.transform.root.GetComponentInChildren<HealthBar>(); + if ((bool)componentInChildren) + { + componentInChildren.transform.localPosition += Vector3.up * moveHealthBarUp; + } + } + } +} diff --git a/ROUNDS/CharacterItemButton.cs b/ROUNDS/CharacterItemButton.cs new file mode 100644 index 0000000..576dce0 --- /dev/null +++ b/ROUNDS/CharacterItemButton.cs @@ -0,0 +1,16 @@ +using SoundImplementation; +using UnityEngine; + +public class CharacterItemButton : MonoBehaviour +{ + public CharacterItemType itemType; + + public int slotNr; + + public void Click() + { + SoundPlayerStatic.Instance.PlayButtonClick(); + GetComponentInParent<CharacterCreatorItemEquipper>().Equip(base.gameObject.GetComponentInChildren<CharacterItem>(), itemType, Vector2.zero, slotNr); + GetComponentInParent<CharacterCreatorButtonSpawner>().SelectButton(itemType, slotNr); + } +} diff --git a/ROUNDS/CharacterItemMirror.cs b/ROUNDS/CharacterItemMirror.cs new file mode 100644 index 0000000..d3ff572 --- /dev/null +++ b/ROUNDS/CharacterItemMirror.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class CharacterItemMirror : MonoBehaviour +{ + private float speedThreshol = 3f; + + private LeftRight leftRight; + + private Player player; + + private void Start() + { + player = GetComponentInParent<Player>(); + if (base.transform.localPosition.x > 0f) + { + leftRight = LeftRight.Right; + } + else + { + leftRight = LeftRight.Left; + } + } + + private void Update() + { + LeftRight leftRight = this.leftRight; + if (player.data.playerVel.velocity.x > speedThreshol) + { + leftRight = LeftRight.Right; + } + if (player.data.playerVel.velocity.x < 0f - speedThreshol) + { + leftRight = LeftRight.Left; + } + if (leftRight != this.leftRight) + { + base.transform.localPosition = new Vector3(base.transform.localPosition.x * -1f, base.transform.localPosition.y, base.transform.localPosition.z); + base.transform.localScale = new Vector3(base.transform.localScale.x * -1f, base.transform.localScale.y, base.transform.localScale.z); + this.leftRight = leftRight; + } + } +} diff --git a/ROUNDS/CharacterItemType.cs b/ROUNDS/CharacterItemType.cs new file mode 100644 index 0000000..395a8ab --- /dev/null +++ b/ROUNDS/CharacterItemType.cs @@ -0,0 +1,6 @@ +public enum CharacterItemType +{ + Eyes, + Mouth, + Detail +} diff --git a/ROUNDS/CharacterSelectionInstance.cs b/ROUNDS/CharacterSelectionInstance.cs new file mode 100644 index 0000000..dd11ab4 --- /dev/null +++ b/ROUNDS/CharacterSelectionInstance.cs @@ -0,0 +1,157 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class CharacterSelectionInstance : MonoBehaviour +{ + public int currentlySelectedFace; + + public Player currentPlayer; + + public GameObject getReadyObj; + + private HoverEvent currentButton; + + private CharacterSelectionInstance[] selectors; + + private HoverEvent[] buttons; + + public bool isReady; + + private float counter; + + private void Start() + { + selectors = base.transform.parent.GetComponentsInChildren<CharacterSelectionInstance>(); + } + + public void ResetMenu() + { + base.transform.GetChild(0).gameObject.SetActive(value: false); + currentPlayer = null; + getReadyObj.gameObject.SetActive(value: false); + PlayerManager.instance.RemovePlayers(); + } + + private void OnEnable() + { + if (!base.transform.GetChild(0).gameObject.activeSelf) + { + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).gameObject.SetActive(value: true); + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).Play(); + } + } + + public void StartPicking(Player pickingPlayer) + { + currentPlayer = pickingPlayer; + currentlySelectedFace = 0; + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).gameObject.SetActive(value: false); + GetComponentInChildren<GeneralParticleSystem>(includeInactive: true).Stop(); + base.transform.GetChild(0).gameObject.SetActive(value: true); + getReadyObj.gameObject.SetActive(value: true); + if (currentPlayer.data.input.inputType == GeneralInput.InputType.Keyboard) + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = "PRESS [SPACE] WHEN READY"; + } + else + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = "PRESS [START] WHEN READY"; + } + buttons = base.transform.GetComponentsInChildren<HoverEvent>(); + for (int i = 0; i < buttons.Length; i++) + { + if (pickingPlayer.data.input.inputType == GeneralInput.InputType.Controller) + { + buttons[i].enabled = false; + buttons[i].GetComponent<Button>().interactable = false; + buttons[i].GetComponent<CharacterCreatorPortrait>().controlType = MenuControllerHandler.MenuControl.Controller; + continue; + } + buttons[i].enabled = true; + buttons[i].GetComponent<Button>().interactable = true; + buttons[i].GetComponent<CharacterCreatorPortrait>().controlType = MenuControllerHandler.MenuControl.Mouse; + Navigation navigation = buttons[i].GetComponent<Button>().navigation; + navigation.mode = Navigation.Mode.None; + buttons[i].GetComponent<Button>().navigation = navigation; + } + } + + public void ReadyUp() + { + isReady = !isReady; + bool flag = true; + for (int i = 0; i < selectors.Length; i++) + { + if (!selectors[i].isReady) + { + flag = false; + } + } + if (flag) + { + MainMenuHandler.instance.Close(); + GM_ArmsRace.instance.StartGame(); + } + if (currentPlayer.data.input.inputType == GeneralInput.InputType.Keyboard) + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = (isReady ? "READY" : "PRESS [SPACE] WHEN READY"); + } + else + { + getReadyObj.GetComponent<TextMeshProUGUI>().text = (isReady ? "READY" : "PRESS [START] WHEN READY"); + } + } + + private void Update() + { + if (!currentPlayer) + { + return; + } + if (currentPlayer.data.input.inputType != 0) + { + if (Input.GetKeyDown(KeyCode.Space)) + { + ReadyUp(); + } + return; + } + if (currentPlayer.data.playerActions.Device.CommandWasPressed) + { + ReadyUp(); + } + HoverEvent component = buttons[currentlySelectedFace].GetComponent<HoverEvent>(); + if (currentButton != component) + { + if ((bool)currentButton) + { + currentButton.GetComponent<SimulatedSelection>().Deselect(); + } + currentButton = component; + currentButton.GetComponent<SimulatedSelection>().Select(); + } + counter += Time.deltaTime; + if (Mathf.Abs(currentPlayer.data.playerActions.Move.X) > 0.5f && counter > 0.2f) + { + if (currentPlayer.data.playerActions.Move.X > 0.5f) + { + currentlySelectedFace++; + } + else + { + currentlySelectedFace--; + } + counter = 0f; + } + if (currentPlayer.data.playerActions.Jump.WasPressed) + { + currentButton.GetComponent<Button>().onClick.Invoke(); + } + if (currentPlayer.data.playerActions.Device.Action4.WasPressed) + { + currentButton.GetComponent<CharacterCreatorPortrait>().EditCharacter(); + } + currentlySelectedFace = Mathf.Clamp(currentlySelectedFace, 0, buttons.Length - 1); + } +} diff --git a/ROUNDS/CharacterSelectionMenu.cs b/ROUNDS/CharacterSelectionMenu.cs new file mode 100644 index 0000000..ed6c36a --- /dev/null +++ b/ROUNDS/CharacterSelectionMenu.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +public class CharacterSelectionMenu : MonoBehaviour +{ + private void Start() + { + PlayerManager instance = PlayerManager.instance; + instance.PlayerJoinedAction = (Action<Player>)Delegate.Combine(instance.PlayerJoinedAction, new Action<Player>(PlayerJoined)); + } + + private void PlayerJoined(Player joinedPlayer) + { + base.transform.GetChild(0).GetChild(PlayerManager.instance.players.Count - 1).GetComponent<CharacterSelectionInstance>() + .StartPicking(joinedPlayer); + } + + private void Update() + { + } +} diff --git a/ROUNDS/CharacterStatModifiers.cs b/ROUNDS/CharacterStatModifiers.cs new file mode 100644 index 0000000..9122d66 --- /dev/null +++ b/ROUNDS/CharacterStatModifiers.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class CharacterStatModifiers : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterSlowFreeze; + + private float soundSlowTime; + + private float soundSlowSpeedSec = 0.3f; + + [Header("Settings")] + public GameObject AddObjectToPlayer; + + [HideInInspector] + public List<GameObject> objectsAddedToPlayer; + + [Header("Multiply")] + public float sizeMultiplier = 1f; + + public float health = 1f; + + public float movementSpeed = 1f; + + public float jump = 1f; + + public float gravity = 1f; + + public float slow; + + public float slowSlow; + + public float fastSlow; + + [Header("Add")] + public float secondsToTakeDamageOver; + + public int numberOfJumps; + + public float regen; + + public float lifeSteal; + + public bool refreshOnDamage; + + public bool automaticReload = true; + + public int respawns; + + [HideInInspector] + public int remainingRespawns; + + [HideInInspector] + public float tasteOfBloodSpeed = 1f; + + [HideInInspector] + public float rageSpeed = 1f; + + public float attackSpeedMultiplier = 1f; + + private WasDealtDamageEffect[] wasDealtDamageEffects; + + private DealtDamageEffect[] dealtDamageEffects; + + private CharacterData data; + + public ParticleSystem slowPart; + + private float soundBigThreshold = 1.5f; + + public Action<Vector2, bool> DealtDamageAction; + + public Action<Vector2, bool> WasDealtDamageAction; + + public Action<int> OnReloadDoneAction; + + public Action<int> OutOfAmmpAction; + + internal float sinceDealtDamage; + + public bool SoundTransformScaleThresholdReached() + { + if (base.transform.localScale.x > soundBigThreshold) + { + return true; + } + return false; + } + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + public float GetSlow() + { + return Mathf.Clamp(slow, 0f, 0.9f); + } + + private void Update() + { + attackSpeedMultiplier = tasteOfBloodSpeed * rageSpeed; + sinceDealtDamage += TimeHandler.deltaTime; + if ((bool)data && !data.isPlaying) + { + sinceDealtDamage = 100f; + } + slow = slowSlow; + if (fastSlow > slowSlow) + { + slow = fastSlow; + } + if (slowSlow > 0f) + { + slowSlow = Mathf.Clamp(slowSlow - TimeHandler.deltaTime * 0.3f, 0f, 10f); + } + if (fastSlow > 0f) + { + fastSlow = Mathf.Clamp(fastSlow - TimeHandler.deltaTime * 2f, 0f, 1f); + } + } + + public void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null) + { + if (lifeSteal != 0f && !selfDamage) + { + GetComponent<HealthHandler>().Heal(damage.magnitude * lifeSteal); + } + if (refreshOnDamage) + { + GetComponent<Holding>().holdable.GetComponent<Weapon>().sinceAttack = float.PositiveInfinity; + } + if (DealtDamageAction != null) + { + DealtDamageAction(damage, selfDamage); + } + if ((bool)damagedPlayer) + { + data.lastDamagedPlayer = damagedPlayer; + } + if (!selfDamage) + { + sinceDealtDamage = 0f; + } + if (dealtDamageEffects != null) + { + for (int i = 0; i < dealtDamageEffects.Length; i++) + { + dealtDamageEffects[i].DealtDamage(damage, selfDamage, damagedPlayer); + } + } + } + + internal void ResetStats() + { + for (int i = 0; i < objectsAddedToPlayer.Count; i++) + { + UnityEngine.Object.Destroy(objectsAddedToPlayer[i]); + } + objectsAddedToPlayer.Clear(); + data.health = 100f; + data.maxHealth = 100f; + sizeMultiplier = 1f; + health = 1f; + movementSpeed = 1f; + jump = 1f; + gravity = 1f; + slow = 0f; + slowSlow = 0f; + fastSlow = 0f; + secondsToTakeDamageOver = 0f; + numberOfJumps = 0; + regen = 0f; + lifeSteal = 0f; + respawns = 0; + refreshOnDamage = false; + automaticReload = true; + tasteOfBloodSpeed = 1f; + rageSpeed = 1f; + attackSpeedMultiplier = 1f; + WasUpdated(); + ConfigureMassAndSize(); + } + + public void WasDealtDamage(Vector2 damage, bool selfDamage) + { + if (WasDealtDamageAction != null) + { + WasDealtDamageAction(damage, selfDamage); + } + if (wasDealtDamageEffects != null) + { + for (int i = 0; i < wasDealtDamageEffects.Length; i++) + { + wasDealtDamageEffects[i].WasDealtDamage(damage, selfDamage); + } + } + } + + public void WasUpdated() + { + GetComponent<ForceMultiplier>().multiplier = 1f / base.transform.root.localScale.x; + wasDealtDamageEffects = GetComponentsInChildren<WasDealtDamageEffect>(); + dealtDamageEffects = GetComponentsInChildren<DealtDamageEffect>(); + } + + public void AddSlowAddative(float slowToAdd, float maxValue = 1f, bool isFastSlow = false) + { + if (data.block.IsBlocking()) + { + return; + } + DoSlowDown(slowToAdd); + if (isFastSlow) + { + if (fastSlow < maxValue) + { + fastSlow += slowToAdd; + fastSlow = Mathf.Clamp(slow, 0f, maxValue); + } + } + else if (slowSlow < maxValue) + { + slowSlow += slowToAdd; + slowSlow = Mathf.Clamp(slowSlow, 0f, maxValue); + } + } + + [PunRPC] + public void RPCA_AddSlow(float slowToAdd, bool isFastSlow = false) + { + DoSlowDown(slowToAdd); + if (isFastSlow) + { + fastSlow = Mathf.Clamp(fastSlow, slowToAdd, 1f); + } + else + { + slowSlow = Mathf.Clamp(slowSlow, slowToAdd, 10f); + } + } + + private void DoSlowDown(float newSlow) + { + if (soundSlowTime + soundSlowSpeedSec < Time.time) + { + soundSlowTime = Time.time; + SoundManager.Instance.Play(soundCharacterSlowFreeze, base.transform); + } + float num = Mathf.Clamp(newSlow - slow, 0f, 1f); + slowPart.Emit((int)Mathf.Clamp((newSlow * 0.1f + num * 0.7f) * 50f, 1f, 50f)); + data.playerVel.velocity *= 1f - num * 1f; + data.sinceGrounded *= 1f - num * 1f; + } + + internal void ConfigureMassAndSize() + { + base.transform.localScale = Vector3.one * 1.2f * Mathf.Pow(data.maxHealth / 100f * 1.2f, 0.2f) * sizeMultiplier; + data.playerVel.mass = 100f * Mathf.Pow(data.maxHealth / 100f * 1.2f, 0.8f) * sizeMultiplier; + } + + internal void OnReload(int bulletsReloaded) + { + if (OnReloadDoneAction != null) + { + OnReloadDoneAction(bulletsReloaded); + } + } + + internal void OnOutOfAmmp(int maxAmmo) + { + if (OutOfAmmpAction != null) + { + OutOfAmmpAction(maxAmmo); + } + } +} diff --git a/ROUNDS/ChargeFeedback.cs b/ROUNDS/ChargeFeedback.cs new file mode 100644 index 0000000..322fe89 --- /dev/null +++ b/ROUNDS/ChargeFeedback.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +public class ChargeFeedback : MonoBehaviour +{ + private Gun gun; + + public float drag = 1f; + + public float spring = 1f; + + public float angle = 45f; + + public float chargeAngle = 15f; + + private float currentAngle; + + private float velocity; + + public float charge; + + private void Start() + { + gun = GetComponentInParent<Gun>(); + gun.AddAttackAction(Shoot); + } + + private void Update() + { + charge = 0f; + if (!gun.IsReady(0.15f)) + { + charge = 1f; + } + velocity += (charge * chargeAngle - currentAngle) * CappedDeltaTime.time * spring; + velocity -= velocity * CappedDeltaTime.time * drag; + currentAngle += CappedDeltaTime.time * velocity; + base.transform.localEulerAngles = new Vector3(currentAngle, 0f, 0f); + } + + public void Shoot() + { + velocity += (0f - angle) * 1000f * (gun.damage / 55f); + } +} diff --git a/ROUNDS/Chase.cs b/ROUNDS/Chase.cs new file mode 100644 index 0000000..1101987 --- /dev/null +++ b/ROUNDS/Chase.cs @@ -0,0 +1,62 @@ +using UnityEngine; +using UnityEngine.Events; + +public class Chase : MonoBehaviour +{ + public UnityEvent turnOnEvent; + + public UnityEvent turnOffEvent; + + public UnityEvent switchTargetEvent; + + private Player player; + + private LineEffect lineEffect; + + private bool isOn; + + private Player currentTarget; + + private void Start() + { + lineEffect = GetComponentInChildren<LineEffect>(includeInactive: true); + player = GetComponentInParent<Player>(); + } + + private void Update() + { + Player player = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(this.player.teamID), needVision: true); + if ((bool)player && (Vector2.Angle(player.transform.position - base.transform.position, this.player.data.input.direction) > 70f || this.player.data.input.direction == Vector3.zero)) + { + player = null; + } + if ((bool)player) + { + if (currentTarget != this.player) + { + currentTarget = this.player; + switchTargetEvent.Invoke(); + lineEffect.Play(base.transform, player.transform); + } + if (!isOn) + { + isOn = true; + turnOnEvent.Invoke(); + } + } + else + { + if (isOn) + { + isOn = false; + turnOffEvent.Invoke(); + } + if (lineEffect.isPlaying) + { + lineEffect.Stop(); + lineEffect.gameObject.SetActive(value: false); + } + currentTarget = null; + } + } +} diff --git a/ROUNDS/ChatFilter.cs b/ROUNDS/ChatFilter.cs new file mode 100644 index 0000000..91b8c96 --- /dev/null +++ b/ROUNDS/ChatFilter.cs @@ -0,0 +1,75 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +public class ChatFilter : MonoBehaviour +{ + [TextArea] + public string enterData; + + public string category; + + public static ChatFilter instance; + + public ChatFilterInstance[] filters; + + private void Awake() + { + instance = this; + } + + [Button] + private void EnterData() + { + string[] array = enterData.Replace('"', ' ').Trim().Split(','); + ChatFilterInstance chatFilterInstance = null; + for (int i = 0; i < filters.Length; i++) + { + if (filters[i].category == category) + { + chatFilterInstance = filters[i]; + break; + } + } + if (chatFilterInstance == null) + { + UnityEngine.Debug.LogError("No valid category target!"); + return; + } + for (int j = 0; j < array.Length; j++) + { + array[j] = array[j].Trim(); + array[j] = array[j].ToUpper(); + if (array[j] == "") + { + continue; + } + bool flag = false; + for (int k = 0; k < chatFilterInstance.words.Count; k++) + { + if (chatFilterInstance.words[k] == array[j]) + { + flag = true; + } + } + if (!flag) + { + chatFilterInstance.words.Add(array[j]); + } + } + } + + public string FilterMessage(string message) + { + for (int i = 0; i < filters.Length; i++) + { + for (int j = 0; j < filters[i].words.Count; j++) + { + if (message.ToUpper().Contains(filters[i].words[j])) + { + return filters[i].replacement; + } + } + } + return message; + } +} diff --git a/ROUNDS/ChatFilterInstance.cs b/ROUNDS/ChatFilterInstance.cs new file mode 100644 index 0000000..ef6d153 --- /dev/null +++ b/ROUNDS/ChatFilterInstance.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +[Serializable] +public class ChatFilterInstance +{ + public List<string> words = new List<string>(); + + public string category; + + [TextArea] + public string replacement; +} diff --git a/ROUNDS/ChildRPC.cs b/ROUNDS/ChildRPC.cs new file mode 100644 index 0000000..1305ce1 --- /dev/null +++ b/ROUNDS/ChildRPC.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using Photon.Pun; +using UnityEngine; + +public class ChildRPC : MonoBehaviour +{ + public Dictionary<string, Action<Vector2, Vector2, int>> childRPCsVector2Vector2Int = new Dictionary<string, Action<Vector2, Vector2, int>>(); + + public Dictionary<string, Action<Vector2, Vector2, int, int>> childRPCsVector2Vector2IntInt = new Dictionary<string, Action<Vector2, Vector2, int, int>>(); + + public Dictionary<string, Action<Vector2>> childRPCsVector2 = new Dictionary<string, Action<Vector2>>(); + + public Dictionary<string, Action<Vector3, Quaternion>> childRPCsVector3Quaternion = new Dictionary<string, Action<Vector3, Quaternion>>(); + + public Dictionary<string, Action<int>> childRPCsInt = new Dictionary<string, Action<int>>(); + + public Dictionary<string, Action> childRPCs = new Dictionary<string, Action>(); + + private PhotonView view; + + private void Start() + { + view = GetComponent<PhotonView>(); + } + + public void CallFunction(string key) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key) + { + if (childRPCs.ContainsKey(key)) + { + childRPCs[key](); + } + } + + public void CallFunction(string key, int intData) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, intData); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, int intData) + { + if (childRPCsInt.ContainsKey(key)) + { + childRPCsInt[key](intData); + } + } + + public void CallFunction(string key, Vector2 vectorData) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector2 vectorData) + { + if (childRPCsVector2.ContainsKey(key)) + { + childRPCsVector2[key](vectorData); + } + } + + public void CallFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData, vectorData2, intData); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData) + { + if (childRPCsVector2Vector2Int.ContainsKey(key)) + { + childRPCsVector2Vector2Int[key](vectorData, vectorData2, intData); + } + } + + public void CallFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData, int intData2) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData, vectorData2, intData, intData2); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector2 vectorData, Vector2 vectorData2, int intData, int intData2) + { + if (childRPCsVector2Vector2IntInt.ContainsKey(key)) + { + childRPCsVector2Vector2IntInt[key](vectorData, vectorData2, intData, intData2); + } + } + + public void CallFunction(string key, Vector3 vectorData, Quaternion quaterion) + { + view.RPC("RPCA_RecieveFunction", RpcTarget.All, key, vectorData, quaterion); + } + + [PunRPC] + public void RPCA_RecieveFunction(string key, Vector3 vectorData, Quaternion quaterion) + { + if (childRPCsVector3Quaternion.ContainsKey(key)) + { + childRPCsVector3Quaternion[key](vectorData, quaterion); + } + } +} diff --git a/ROUNDS/ChillingTouch.cs b/ROUNDS/ChillingTouch.cs new file mode 100644 index 0000000..487ab51 --- /dev/null +++ b/ROUNDS/ChillingTouch.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class ChillingTouch : DamageEffect +{ + public float baseSlow = 0.2f; + + public float scalingSlow = 0.01f; + + private AttackLevel level; + + private void Start() + { + level = GetComponent<AttackLevel>(); + } + + public override void DoDamageEffect(Vector2 dmg, bool selfDmg, Player damagedPlayer = null) + { + damagedPlayer.data.stats.RPCA_AddSlow((baseSlow + dmg.magnitude * scalingSlow) * (1f + ((float)level.attackLevel - 1f) * 0.3f)); + } +} diff --git a/ROUNDS/ChomaticAberrationFeeler.cs b/ROUNDS/ChomaticAberrationFeeler.cs new file mode 100644 index 0000000..ebe7c16 --- /dev/null +++ b/ROUNDS/ChomaticAberrationFeeler.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class ChomaticAberrationFeeler : GameFeeler +{ + public float force = 10f; + + public float damper = 0.95f; + + public float damperSpring = 0.95f; + + public float threshold; + + private PostProcessVolume postProcessVolume; + + private ChromaticAberration chromaticAberration; + + private float intensity; + + private float velocity; + + private float targetIntensity; + + public override void OnAwake() + { + postProcessVolume = GetComponent<PostProcessVolume>(); + if (!postProcessVolume.profile.TryGetSettings<ChromaticAberration>(out chromaticAberration)) + { + Debug.LogError("No ChromaticAberration in post!"); + } + else + { + targetIntensity = chromaticAberration.intensity.value; + } + } + + public override void OnGameFeel(Vector2 feelDirection) + { + feelDirection = Vector2.ClampMagnitude(feelDirection, 50f); + if (feelDirection.magnitude < threshold) + { + feelDirection = feelDirection.normalized * threshold * 0.3f; + } + velocity += feelDirection.sqrMagnitude * 0.2f * force; + } + + private void Update() + { + velocity *= damper; + intensity *= damperSpring; + intensity += velocity * Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.02f); + chromaticAberration.intensity.value = intensity + targetIntensity; + } + + private void FixedUpdate() + { + intensity *= 0.9f; + } + + public override void OnUIGameFeel(Vector2 feelDirection) + { + } +} diff --git a/ROUNDS/Cluster.cs b/ROUNDS/Cluster.cs new file mode 100644 index 0000000..2e5c648 --- /dev/null +++ b/ROUNDS/Cluster.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +public class Cluster : MonoBehaviour +{ + public float distanceToTravel = 8f; + + public float spread; + + public float velocitySpread; + + public int clusters = 3; + + private MoveTransform move; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + } + + private void Update() + { + if (!(move.distanceTravelled > distanceToTravel)) + { + return; + } + for (int i = 0; i < clusters; i++) + { + GameObject obj = Object.Instantiate(base.transform.root.gameObject, base.transform.root.position, base.transform.root.rotation); + Cluster componentInChildren = obj.GetComponentInChildren<Cluster>(); + if ((bool)componentInChildren) + { + Object.Destroy(componentInChildren); + } + MoveTransform component = obj.GetComponent<MoveTransform>(); + if ((bool)component) + { + component.DontRunStart = true; + component.velocity = base.transform.root.GetComponent<MoveTransform>().velocity; + component.multiplier = base.transform.root.GetComponent<MoveTransform>().multiplier; + component.velocity += base.transform.right * Random.Range(0f - spread, spread); + component.velocity *= Random.Range(1f - velocitySpread * 0.01f, 1f + velocitySpread * 0.01f); + } + } + Object.Destroy(this); + } +} diff --git a/ROUNDS/CodeAnimation.cs b/ROUNDS/CodeAnimation.cs new file mode 100644 index 0000000..ae132b3 --- /dev/null +++ b/ROUNDS/CodeAnimation.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +public class CodeAnimation : MonoBehaviour +{ + [HideInInspector] + public bool isPlaying; + + public bool loonIn; + + public bool playInOnAwake; + + public bool playInOnEnable; + + public float enablePlayDelay; + + public bool interuptAnimations = true; + + public bool setFirstFrame; + + public bool useTimeScale = true; + + private Vector3 defaultScale; + + private Vector3 defaultLocalPosition; + + private Vector3 defaultRectPosition; + + private Vector3 defaultLocalRotation; + + public CodeAnimationInstance[] animations; + + private RectTransform rectTransform; + + [HideInInspector] + public CodeAnimationInstance.AnimationUse currentState; + + [HideInInspector] + public float animationValue; + + private Action AnimationChangeAction; + + public void Start() + { + currentState = CodeAnimationInstance.AnimationUse.None; + rectTransform = GetComponent<RectTransform>(); + for (int i = 0; i < animations.Length; i++) + { + animations[i].animationSpeed += UnityEngine.Random.Range((0f - animations[i].animationSpeed) * animations[i].randomSpeedAmount, animations[i].animationSpeed * animations[i].randomSpeedAmount); + if (animations[i].animationUse == CodeAnimationInstance.AnimationUse.In) + { + float num = animations[i].curve[animations[i].curve.length - 1].value - animations[i].curve[0].value; + if ((bool)rectTransform && animations[i].animationType == CodeAnimationInstance.AnimationType.rectPosition) + { + rectTransform.anchoredPosition += num * (Vector2)animations[i].direction * (0f - animations[i].multiplier); + } + } + } + SetDefaults(); + if (playInOnAwake) + { + PlayIn(); + } + if (setFirstFrame) + { + ApplyValues(animations[0], 0f); + } + } + + private void OnEnable() + { + if (playInOnEnable) + { + StartCoroutine(DelayEnablePlay()); + } + } + + private IEnumerator DelayEnablePlay() + { + yield return new WaitForSecondsRealtime(enablePlayDelay); + PlayIn(); + } + + private void SetDefaults() + { + defaultScale = base.transform.localScale; + defaultLocalPosition = base.transform.localPosition; + defaultLocalRotation = base.transform.localRotation.eulerAngles; + if ((bool)rectTransform) + { + defaultRectPosition = rectTransform.anchoredPosition; + } + } + + public void Animate(CodeAnimationInstance.AnimationUse use) + { + currentState = use; + if (interuptAnimations) + { + StopAllCoroutines(); + } + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].animationUse == use) + { + StartCoroutine(PlayAnimations(animations[i])); + } + } + } + + [Button] + public void PlayIn() + { + Animate(CodeAnimationInstance.AnimationUse.In); + } + + [Button] + public void PlayOut() + { + Animate(CodeAnimationInstance.AnimationUse.Out); + } + + [Button] + public void PlayBoop() + { + Animate(CodeAnimationInstance.AnimationUse.Boop); + } + + private IEnumerator PlayAnimations(CodeAnimationInstance animation) + { + isPlaying = true; + animation.startEvent.Invoke(); + StartCoroutine(DelayTimedEvent(animation.eventTiming / animation.animationSpeed, animation.timedEvent)); + float t = animation.curve.keys[animation.curve.keys.Length - 1].time; + float c = 0f; + while (c < t) + { + ApplyValues(animation, c); + c += (useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime) * animation.animationSpeed; + yield return null; + } + ApplyValues(animation, t); + isPlaying = false; + animation.endEvent.Invoke(); + if (loonIn) + { + PlayIn(); + } + } + + private void ApplyValues(CodeAnimationInstance animation, float time) + { + if (animation.animationType == CodeAnimationInstance.AnimationType.rectPosition && (bool)rectTransform) + { + rectTransform.anchoredPosition = defaultRectPosition + animation.direction * animation.curve.Evaluate(time) * animation.multiplier; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.position) + { + base.transform.localPosition = defaultLocalPosition + animation.direction * animation.curve.Evaluate(time) * animation.multiplier; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.scale) + { + Vector3 localScale = defaultScale * animation.curve.Evaluate(time) * animation.multiplier; + if (!animation.X) + { + localScale.x = base.transform.localScale.x; + } + if (!animation.Y) + { + localScale.y = base.transform.localScale.y; + } + if (!animation.Z) + { + localScale.z = base.transform.localScale.z; + } + base.transform.localScale = localScale; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.floatNumber) + { + animationValue = animation.curve.Evaluate(time) * animation.multiplier; + } + if (animation.animationType == CodeAnimationInstance.AnimationType.rotation) + { + base.transform.localRotation = Quaternion.Euler(animation.curve.Evaluate(time) * animation.direction + defaultLocalRotation); + } + if (AnimationChangeAction != null) + { + AnimationChangeAction(); + } + } + + public void AddAnimationChangeAction(Action action) + { + AnimationChangeAction = (Action)Delegate.Combine(AnimationChangeAction, action); + } + + private IEnumerator DelayTimedEvent(float time, UnityEvent eventToCall) + { + yield return new WaitForSeconds(time); + eventToCall.Invoke(); + } +} diff --git a/ROUNDS/CodeAnimationInstance.cs b/ROUNDS/CodeAnimationInstance.cs new file mode 100644 index 0000000..be847e3 --- /dev/null +++ b/ROUNDS/CodeAnimationInstance.cs @@ -0,0 +1,62 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +[Serializable] +public class CodeAnimationInstance +{ + public enum AnimationType + { + position, + scale, + rectPosition, + floatNumber, + rotation + } + + public enum AnimationUse + { + In, + Out, + None, + Boop + } + + public float animationSpeed = 1f; + + [FoldoutGroup("Random", 0)] + public float randomSpeedAmount; + + [FoldoutGroup("USE", 0)] + public bool X = true; + + [FoldoutGroup("USE", 0)] + public bool Y = true; + + [FoldoutGroup("USE", 0)] + public bool Z = true; + + [Space(15f)] + public AnimationType animationType; + + public AnimationUse animationUse; + + public AnimationCurve curve; + + public float multiplier = 1f; + + public Vector3 direction; + + [FoldoutGroup("Events", 0)] + public UnityEvent startEvent; + + [FoldoutGroup("Events", 0)] + public UnityEvent timedEvent; + + [FoldoutGroup("Events", 0)] + public float eventTiming; + + [FoldoutGroup("Events", 0)] + public UnityEvent endEvent; +} diff --git a/ROUNDS/CollisionChecker.cs b/ROUNDS/CollisionChecker.cs new file mode 100644 index 0000000..a344911 --- /dev/null +++ b/ROUNDS/CollisionChecker.cs @@ -0,0 +1,41 @@ +using System; +using UnityEngine; + +public class CollisionChecker : MonoBehaviour +{ + private CharacterData data; + + public Action<Collision2D> collisionAction; + + private void Awake() + { + data = GetComponent<CharacterData>(); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + Collide(collision); + } + + private void OnCollisionStay2D(Collision2D collision) + { + Collide(collision); + } + + private void Collide(Collision2D collision) + { + if (collisionAction != null) + { + collisionAction(collision); + } + if (Vector3.Angle(Vector3.up, collision.contacts[0].normal) > 70f) + { + Vector3.Angle(Vector3.up, collision.contacts[0].normal); + _ = 110f; + } + else + { + data.TouchGround(collision.contacts[0].point, collision.contacts[0].normal, collision.otherRigidbody, collision.transform); + } + } +} diff --git a/ROUNDS/ColorBlink.cs b/ROUNDS/ColorBlink.cs new file mode 100644 index 0000000..35ebf03 --- /dev/null +++ b/ROUNDS/ColorBlink.cs @@ -0,0 +1,42 @@ +using System.Collections; +using UnityEngine; + +public class ColorBlink : MonoBehaviour +{ + public Color blinkColor; + + public float timeAmount; + + private Color defaultColor; + + private SpriteRenderer sprite; + + private bool inited; + + private void Start() + { + if (!inited) + { + inited = true; + sprite = GetComponent<SpriteRenderer>(); + defaultColor = sprite.color; + } + } + + public void DoBlink() + { + StopAllCoroutines(); + StartCoroutine(IDoBlink()); + } + + private IEnumerator IDoBlink() + { + if (!sprite) + { + Start(); + } + sprite.color = blinkColor; + yield return new WaitForSeconds(timeAmount); + sprite.color = defaultColor; + } +} diff --git a/ROUNDS/ColorHandler.cs b/ROUNDS/ColorHandler.cs new file mode 100644 index 0000000..b185b72 --- /dev/null +++ b/ROUNDS/ColorHandler.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Sirenix.OdinInspector; +using UnityEngine; + +public class ColorHandler : SerializedMonoBehaviour +{ + public enum ColorType + { + PhysicsObject + } + + public Dictionary<ColorType, Color> colors = new Dictionary<ColorType, Color>(); + + public static ColorHandler instance; + + private void Awake() + { + instance = this; + } + + public Color GetColor(ColorType colorType) + { + return colors[colorType]; + } +} diff --git a/ROUNDS/Comment.cs b/ROUNDS/Comment.cs new file mode 100644 index 0000000..020c8e3 --- /dev/null +++ b/ROUNDS/Comment.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +public class Comment : MonoBehaviour +{ + [TextArea(20, 100)] + public string comment; +} diff --git a/ROUNDS/Connected.cs b/ROUNDS/Connected.cs new file mode 100644 index 0000000..4ccc116 --- /dev/null +++ b/ROUNDS/Connected.cs @@ -0,0 +1 @@ +public delegate void Connected(); diff --git a/ROUNDS/ControllerImageToggler.cs b/ROUNDS/ControllerImageToggler.cs new file mode 100644 index 0000000..22463f4 --- /dev/null +++ b/ROUNDS/ControllerImageToggler.cs @@ -0,0 +1,71 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +public class ControllerImageToggler : MonoBehaviour +{ + public Sprite MKSprite; + + public Sprite controllerSprite; + + private Image img; + + private CharacterCreatorPortrait portrait; + + private CharacterSelectionInstance selector; + + private void Awake() + { + selector = GetComponentInParent<CharacterSelectionInstance>(); + portrait = GetComponentInParent<CharacterCreatorPortrait>(); + if ((bool)portrait && portrait.controlType != MenuControllerHandler.MenuControl.Unassigned) + { + Switch(portrait.controlType); + } + } + + private void Start() + { + img = GetComponent<Image>(); + MenuControllerHandler instance = MenuControllerHandler.instance; + instance.switchControlAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(instance.switchControlAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + if (!selector && portrait.controlType == MenuControllerHandler.MenuControl.Unassigned) + { + Switch(MenuControllerHandler.menuControl); + } + } + + private void Update() + { + if ((bool)selector && (bool)selector.currentPlayer) + { + if (selector.currentPlayer.data.input.inputType == GeneralInput.InputType.Controller) + { + img.sprite = controllerSprite; + } + else + { + img.sprite = MKSprite; + } + } + } + + private void Switch(MenuControllerHandler.MenuControl control) + { + if (!img) + { + img = GetComponent<Image>(); + } + if (!selector) + { + if (control == MenuControllerHandler.MenuControl.Controller) + { + img.sprite = controllerSprite; + } + else + { + img.sprite = MKSprite; + } + } + } +} diff --git a/ROUNDS/CooldownCondition.cs b/ROUNDS/CooldownCondition.cs new file mode 100644 index 0000000..51bbbf6 --- /dev/null +++ b/ROUNDS/CooldownCondition.cs @@ -0,0 +1,20 @@ +using UnityEngine; +using UnityEngine.Events; + +public class CooldownCondition : MonoBehaviour +{ + public UnityEvent triggerEvent; + + public float cooldown = 0.25f; + + private float lastTime = -100f; + + public void TryEvent() + { + if (!(Time.time < lastTime + cooldown)) + { + lastTime = Time.time; + triggerEvent.Invoke(); + } + } +} diff --git a/ROUNDS/CooldownWindUp.cs b/ROUNDS/CooldownWindUp.cs new file mode 100644 index 0000000..3d443a0 --- /dev/null +++ b/ROUNDS/CooldownWindUp.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +public class CooldownWindUp : MonoBehaviour +{ + public AnimationCurve multiplierCurve; + + private float currentMultiplier = 1f; + + private float startValue; + + private float currentValue; + + public float increasePerShot = 1f; + + private CooldownCondition cooldown; + + private void Start() + { + cooldown = GetComponent<CooldownCondition>(); + startValue = cooldown.cooldown; + } + + private void Update() + { + currentMultiplier = multiplierCurve.Evaluate(currentValue); + currentValue = Mathf.Clamp(currentValue, 0f, 100f); + cooldown.cooldown = startValue / currentMultiplier; + } + + public void Reset() + { + currentValue = 0f; + } + + public void Add() + { + currentValue += increasePerShot / currentMultiplier; + } +} diff --git a/ROUNDS/CopyChildren.cs b/ROUNDS/CopyChildren.cs new file mode 100644 index 0000000..6c1757d --- /dev/null +++ b/ROUNDS/CopyChildren.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class CopyChildren : MonoBehaviour +{ + public GameObject target; + + public void DoUpdate() + { + for (int num = base.transform.childCount - 1; num >= 0; num--) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + for (int i = 0; i < target.transform.childCount; i++) + { + Transform child = target.transform.GetChild(i); + Object.Instantiate(child.gameObject, base.transform.TransformPoint(child.localPosition), Quaternion.identity, base.transform).transform.localScale = child.localScale; + } + } + + private void Update() + { + DoUpdate(); + } +} diff --git a/ROUNDS/CopyObject.cs b/ROUNDS/CopyObject.cs new file mode 100644 index 0000000..c8ca2ed --- /dev/null +++ b/ROUNDS/CopyObject.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class CopyObject : MonoBehaviour +{ + public void CopySelf() + { + Object.Instantiate(base.gameObject, base.transform.position, base.transform.rotation, base.transform.parent); + } +} diff --git a/ROUNDS/CopyOwnerGunStats.cs b/ROUNDS/CopyOwnerGunStats.cs new file mode 100644 index 0000000..d9497a1 --- /dev/null +++ b/ROUNDS/CopyOwnerGunStats.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class CopyOwnerGunStats : MonoBehaviour +{ + private void Start() + { + ApplyCardStats.CopyGunStats(base.transform.root.GetComponent<SpawnedAttack>().spawner.GetComponent<WeaponHandler>().gun, GetComponent<Gun>()); + } +} diff --git a/ROUNDS/CopyPlayerAim.cs b/ROUNDS/CopyPlayerAim.cs new file mode 100644 index 0000000..46f2300 --- /dev/null +++ b/ROUNDS/CopyPlayerAim.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +public class CopyPlayerAim : MonoBehaviour +{ + public float spreadPerLevel; + + public float spread; + + private AttackLevel level; + + private void Start() + { + level = GetComponentInParent<AttackLevel>(); + } + + public void Go() + { + float num = Random.Range(0f - spread, spread); + float num2 = 0f; + if ((bool)level) + { + num2 = (float)level.attackLevel * spreadPerLevel; + } + num += Random.Range(0f - num2, num2); + Holding component = base.transform.root.GetComponent<Holding>(); + if ((bool)component) + { + base.transform.rotation = component.holdable.GetComponentInChildren<ShootPos>().transform.rotation; + } + base.transform.Rotate(Vector3.Cross(Vector3.forward, base.transform.forward) * num); + } +} diff --git a/ROUNDS/Cos.cs b/ROUNDS/Cos.cs new file mode 100644 index 0000000..d547ade --- /dev/null +++ b/ROUNDS/Cos.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class Cos : MonoBehaviour +{ + public float multiplier = 1f; + + private void Update() + { + base.transform.root.position += base.transform.right * Mathf.Cos(Time.time * 20f * multiplier) * 10f * multiplier * Time.smoothDeltaTime; + } +} diff --git a/ROUNDS/CounterUI.cs b/ROUNDS/CounterUI.cs new file mode 100644 index 0000000..a23dd69 --- /dev/null +++ b/ROUNDS/CounterUI.cs @@ -0,0 +1,59 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI.ProceduralImage; + +public class CounterUI : MonoBehaviour +{ + [Range(0f, 1f)] + public float counter; + + public float timeToFill = 10f; + + public ProceduralImage outerRing; + + public ProceduralImage fill; + + public Transform rotator; + + public Transform still; + + private float remainingDuration; + + private bool isAbyssalForm; + + private bool done; + + public UnityEvent doneEvent; + + private void ResetStuff() + { + counter = 0f; + } + + private void Update() + { + if (!done) + { + outerRing.fillAmount = counter; + fill.fillAmount = counter; + rotator.transform.localEulerAngles = new Vector3(0f, 0f, 0f - Mathf.Lerp(0f, 360f, counter)); + counter += TimeHandler.deltaTime / timeToFill; + counter = Mathf.Clamp(counter, -0.1f / timeToFill, 1f); + if (counter >= 1f) + { + done = true; + doneEvent.Invoke(); + } + if (counter <= 0f) + { + rotator.gameObject.SetActive(value: false); + still.gameObject.SetActive(value: false); + } + else + { + rotator.gameObject.SetActive(value: true); + still.gameObject.SetActive(value: true); + } + } + } +} diff --git a/ROUNDS/CrownPos.cs b/ROUNDS/CrownPos.cs new file mode 100644 index 0000000..f8cd30a --- /dev/null +++ b/ROUNDS/CrownPos.cs @@ -0,0 +1,16 @@ +using TMPro; +using UnityEngine; + +public class CrownPos : MonoBehaviour +{ + public TextMeshProUGUI text; + + public float GetOffset() + { + if (!(text.text == "")) + { + return 0.45f; + } + return 0f; + } +} diff --git a/ROUNDS/CurveAnimation.cs b/ROUNDS/CurveAnimation.cs new file mode 100644 index 0000000..cf4611f --- /dev/null +++ b/ROUNDS/CurveAnimation.cs @@ -0,0 +1,249 @@ +using System.Collections; +using Sirenix.OdinInspector; +using Sonigon; +using SoundImplementation; +using UnityEngine; +using UnityEngine.Events; + +public class CurveAnimation : MonoBehaviour +{ + [Header("Sound")] + public SoundAnimationPlay[] soundPlay = new SoundAnimationPlay[0]; + + [Header("Settings")] + public CurveAnimationInstance[] animations; + + [HideInInspector] + public Vector3 startScale; + + [HideInInspector] + public Vector3 startLocalPos; + + [HideInInspector] + public Vector3 startAnchoredPos; + + [HideInInspector] + public Vector3 startRotation; + + public CurveAnimationUse currentState = CurveAnimationUse.Out; + + private RectTransform rectTransform; + + [FoldoutGroup("Global settings", 0)] + public bool useTimeScale = true; + + [FoldoutGroup("Global settings", 0)] + public bool X = true; + + [FoldoutGroup("Global settings", 0)] + public bool Y = true; + + [FoldoutGroup("Global settings", 0)] + public bool Z = true; + + [FoldoutGroup("Global settings", 0)] + public bool stopAllAnimations; + + private bool inited; + + private void Init() + { + if (!inited) + { + startScale = base.transform.localScale; + startLocalPos = base.transform.localScale; + rectTransform = GetComponent<RectTransform>(); + if ((bool)rectTransform) + { + startAnchoredPos = rectTransform.anchoredPosition; + } + startRotation = base.transform.localEulerAngles; + } + } + + private void Awake() + { + Init(); + } + + private void OnDisable() + { + StopAllCoroutines(); + ResetAnimationState(); + for (int i = 0; i < animations.Length; i++) + { + animations[i].isPlaying = false; + } + } + + private void OnEnable() + { + ResetAnimationState(); + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].playOnAwake) + { + PlayAnimation(animations[i]); + } + } + } + + [Button] + public void PlayIn() + { + PlayAnimationWithUse(CurveAnimationUse.In); + } + + [Button] + public void PlayOut() + { + PlayAnimationWithUse(CurveAnimationUse.Out); + } + + [Button] + public void PlayBoop() + { + PlayAnimationWithUse(CurveAnimationUse.Boop); + } + + [Button] + public void Stop() + { + StopAllCoroutines(); + } + + private void ResetAnimationState() + { + ApplyAnimationFrame(GetAnimationWithUse(CurveAnimationUse.In), 0f); + } + + private CurveAnimationInstance GetAnimationWithUse(CurveAnimationUse use) + { + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].animationUse == use) + { + return animations[i]; + } + } + return animations[0]; + } + + public void PlayAnimation(CurveAnimationInstance animation) + { + for (int i = 0; i < soundPlay.Length; i++) + { + if (soundPlay[i] != null) + { + soundPlay[i].soundHasPlayed = false; + } + } + if (stopAllAnimations) + { + StopAllCoroutines(); + } + if (animation.isPlaying && animation.animation != null) + { + StopCoroutine(animation.animation); + } + animation.animation = StartCoroutine(DoAnimation(animation)); + } + + public void PlayAnimationWithUse(CurveAnimationUse animationUse) + { + for (int i = 0; i < soundPlay.Length; i++) + { + if (soundPlay[i] != null) + { + soundPlay[i].soundHasPlayed = false; + } + } + if (stopAllAnimations) + { + StopAllCoroutines(); + } + currentState = animationUse; + for (int j = 0; j < animations.Length; j++) + { + if (animations[j].animationUse == animationUse) + { + if (animations[j].isPlaying && animations[j].animation != null) + { + StopCoroutine(animations[j].animation); + } + animations[j].animation = StartCoroutine(DoAnimation(animations[j])); + } + } + } + + private IEnumerator DoAnimation(CurveAnimationInstance animation) + { + StartCoroutine(DelayEvent(animation.delay / animation.speed, animation.delayedEvent)); + animation.statEvent.Invoke(); + animation.isPlaying = true; + float c = 0f; + float t = animation.Curve().keys[animation.Curve().keys.Length - 1].time; + while (c < t) + { + c += (useTimeScale ? (TimeHandler.deltaTime * animation.speed) : (Time.unscaledDeltaTime * animation.speed)); + for (int i = 0; i < soundPlay.Length; i++) + { + if (soundPlay[i] != null && soundPlay[i].soundEvent != null && c >= soundPlay[i].soundDelay && animation.animationUse == soundPlay[i].curveAnimationUse && !soundPlay[i].soundHasPlayed && (bool)SoundManager.Instance) + { + soundPlay[i].soundHasPlayed = true; + SoundManager.Instance.Play(soundPlay[i].soundEvent, base.transform); + } + } + ApplyAnimationFrame(animation, c); + yield return null; + } + ApplyAnimationFrame(animation, t); + animation.isPlaying = false; + animation.endEvent.Invoke(); + if (animation.loop) + { + PlayAnimationWithUse(animation.animationUse); + } + } + + private IEnumerator DelayEvent(float seconds, UnityEvent eventToCall) + { + yield return new WaitForSeconds(seconds); + eventToCall.Invoke(); + } + + private void ApplyAnimationFrame(CurveAnimationInstance anim, float time) + { + if (anim.animationType == CurveAnimationType.Scale) + { + Vector3 vector = startScale * anim.Curve().Evaluate(time) * anim.multiplier; + Vector3 localScale = new Vector3(X ? vector.x : base.transform.localScale.x, Y ? vector.y : base.transform.localScale.y, Z ? vector.z : base.transform.localScale.z); + base.transform.localScale = localScale; + } + else if (anim.animationType == CurveAnimationType.Position) + { + base.transform.localPosition = startLocalPos + anim.animDirection * anim.Curve().Evaluate(time) * anim.multiplier; + } + else if (anim.animationType == CurveAnimationType.RectPosition) + { + rectTransform.anchoredPosition = startAnchoredPos + anim.animDirection * anim.Curve().Evaluate(time) * anim.multiplier; + } + else if (anim.animationType == CurveAnimationType.Rotation) + { + base.transform.localEulerAngles = startRotation + anim.animDirection * anim.Curve().Evaluate(time) * anim.multiplier; + } + } + + public bool IsPlaying() + { + bool result = false; + for (int i = 0; i < animations.Length; i++) + { + if (animations[i].isPlaying) + { + result = true; + } + } + return result; + } +} diff --git a/ROUNDS/CurveAnimationInstance.cs b/ROUNDS/CurveAnimationInstance.cs new file mode 100644 index 0000000..6d5ed2f --- /dev/null +++ b/ROUNDS/CurveAnimationInstance.cs @@ -0,0 +1,73 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +[Serializable] +public class CurveAnimationInstance +{ + [FoldoutGroup("$animationUse", 0)] + public CurveAnimationType animationType; + + [FoldoutGroup("$animationUse", 0)] + public CurveAnimationUse animationUse; + + [ShowIf("animationUse", CurveAnimationUse.In, true)] + [FoldoutGroup("$animationUse", 0)] + public AnimationCurve inCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f); + + [ShowIf("animationUse", CurveAnimationUse.Out, true)] + [FoldoutGroup("$animationUse", 0)] + public AnimationCurve outCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f); + + [ShowIf("animationUse", CurveAnimationUse.Boop, true)] + [FoldoutGroup("$animationUse", 0)] + public AnimationCurve boopCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [HideIf("animationType", CurveAnimationType.Scale, true)] + [FoldoutGroup("$animationUse", 0)] + public Vector3 animDirection; + + [FoldoutGroup("$animationUse/Settings", 0)] + public bool loop; + + [FoldoutGroup("$animationUse/Settings", 0)] + public bool playOnAwake; + + [FoldoutGroup("$animationUse/Settings", 0)] + public float speed = 1f; + + [FoldoutGroup("$animationUse/Settings", 0)] + public float multiplier = 1f; + + [FoldoutGroup("$animationUse/Events", 0)] + public UnityEvent statEvent; + + [FoldoutGroup("$animationUse/Events", 0)] + public UnityEvent endEvent; + + [FoldoutGroup("$animationUse/Events", 0)] + public UnityEvent delayedEvent; + + [FoldoutGroup("$animationUse/Events", 0)] + public float delay; + + [FoldoutGroup("$animationUse/Debug", 0, Order = 0, Expanded = false)] + public bool isPlaying; + + [HideInInspector] + public Coroutine animation; + + public AnimationCurve Curve() + { + if (animationUse == CurveAnimationUse.Boop) + { + return boopCurve; + } + if (animationUse != 0) + { + return outCurve; + } + return inCurve; + } +} diff --git a/ROUNDS/CurveAnimationType.cs b/ROUNDS/CurveAnimationType.cs new file mode 100644 index 0000000..ad2e885 --- /dev/null +++ b/ROUNDS/CurveAnimationType.cs @@ -0,0 +1,7 @@ +public enum CurveAnimationType +{ + Scale, + Position, + RectPosition, + Rotation +} diff --git a/ROUNDS/CurveAnimationUse.cs b/ROUNDS/CurveAnimationUse.cs new file mode 100644 index 0000000..f56a698 --- /dev/null +++ b/ROUNDS/CurveAnimationUse.cs @@ -0,0 +1,6 @@ +public enum CurveAnimationUse +{ + In, + Out, + Boop +} diff --git a/ROUNDS/Damagable.cs b/ROUNDS/Damagable.cs new file mode 100644 index 0000000..69afa0a --- /dev/null +++ b/ROUNDS/Damagable.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public abstract class Damagable : MonoBehaviour +{ + public abstract void CallTakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true); + + public abstract void TakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false); + + public abstract void TakeDamage(Vector2 damage, Vector2 damagePosition, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false); +} diff --git a/ROUNDS/DamagableEvent.cs b/ROUNDS/DamagableEvent.cs new file mode 100644 index 0000000..3d70256 --- /dev/null +++ b/ROUNDS/DamagableEvent.cs @@ -0,0 +1,134 @@ +using System; +using Photon.Pun; +using UnityEngine; +using UnityEngine.Events; + +public class DamagableEvent : Damagable +{ + public bool networkedDamage; + + public bool disabled; + + [HideInInspector] + public bool dead; + + public float currentHP = 100f; + + public float regenDelay = 1f; + + public float regenPerSecond; + + [HideInInspector] + public float maxHP = 100f; + + public UnityEvent damageEvent; + + public UnityEvent deathEvent; + + private float sinceDamage = 1f; + + [HideInInspector] + public Player lastPlayer; + + [HideInInspector] + public GameObject lastWeapon; + + private PhotonView view; + + public Action<Vector2> DieAction; + + private void Start() + { + view = GetComponent<PhotonView>(); + maxHP = currentHP; + } + + public override void TakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (disabled || dead) + { + return; + } + if (networkedDamage) + { + if ((bool)damagingPlayer) + { + if (!damagingPlayer.data.view.IsMine) + { + return; + } + view.RPC("RPCA_TakeDamage", RpcTarget.Others, damage, damagePosition); + } + else + { + if (!view.IsMine) + { + return; + } + view.RPC("RPCA_TakeDamage", RpcTarget.Others, damage, damagePosition); + } + } + DoDamage(damage, damagePosition, damagingWeapon, damagingPlayer, lethal, ignoreBlock); + } + + [PunRPC] + public void RPCA_TakeDamage(Vector2 damage, Vector2 damagePosition) + { + DoDamage(damage, damagePosition); + } + + private void DoDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if ((bool)damagingPlayer) + { + lastPlayer = damagingPlayer; + } + if ((bool)damagingWeapon) + { + lastWeapon = damagingWeapon; + } + sinceDamage = 0f; + currentHP -= damage.magnitude; + if (currentHP <= 0f) + { + Die(damage); + } + else + { + damageEvent.Invoke(); + } + } + + private void Die(Vector2 damage = default(Vector2)) + { + if (!dead && !disabled) + { + DieAction?.Invoke(damage); + deathEvent.Invoke(); + dead = true; + } + } + + private void Update() + { + if (!dead && !disabled) + { + sinceDamage += TimeHandler.deltaTime; + if (sinceDamage > regenDelay && currentHP < maxHP) + { + currentHP += regenPerSecond * TimeHandler.deltaTime; + currentHP = Mathf.Clamp(currentHP, float.NegativeInfinity, maxHP); + } + } + } + + public override void TakeDamage(Vector2 damage, Vector2 damagePosition, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + TakeDamage(damage, damagePosition, damagingWeapon, damagingPlayer, lethal); + } + + public override void CallTakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + TakeDamage(damage, damagePosition, Color.red, damagingWeapon, damagingPlayer, lethal); + } +} diff --git a/ROUNDS/DamageBox.cs b/ROUNDS/DamageBox.cs new file mode 100644 index 0000000..e86d79f --- /dev/null +++ b/ROUNDS/DamageBox.cs @@ -0,0 +1,96 @@ +using Sonigon; +using UnityEngine; + +public class DamageBox : MonoBehaviour +{ + [Header("Sound")] + public bool soundPlaySawDamage; + + public SoundEvent soundSawDamage; + + [Header("Settings")] + public bool towardsCenterOfMap; + + public bool awayFromMe; + + public float damage = 25f; + + public float force; + + public float setFlyingFor; + + public float shake; + + public float cd = 0.3f; + + public bool ignoreBlock; + + public ParticleSystem dmgPart; + + private float time; + + private SpawnedAttack spawned; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + Collide(collision); + } + + private void OnCollisionStay2D(Collision2D collision) + { + Collide(collision); + } + + private void Collide(Collision2D collision) + { + if (Time.time < time + cd) + { + return; + } + Vector3 vector = base.transform.root.forward; + if (towardsCenterOfMap) + { + vector = -collision.contacts[0].point.normalized; + } + if (awayFromMe) + { + vector = (collision.transform.position - base.transform.position).normalized; + } + Damagable componentInParent = collision.transform.GetComponentInParent<Damagable>(); + if (!componentInParent) + { + return; + } + time = Time.time; + HealthHandler component = componentInParent.GetComponent<HealthHandler>(); + CharacterData component2 = component.GetComponent<CharacterData>(); + if (!component2 || component2.view.IsMine) + { + if ((bool)component) + { + component.CallTakeForce(vector * force, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock, setFlyingFor); + } + componentInParent.CallTakeDamage(damage * vector, base.transform.position, null, (spawned != null) ? spawned.spawner : null); + if (soundPlaySawDamage) + { + SoundManager.Instance.PlayAtPosition(soundSawDamage, SoundManager.Instance.GetTransform(), base.transform); + } + if ((bool)dmgPart) + { + Vector3 forward = vector; + vector.z = 0f; + dmgPart.transform.parent.rotation = Quaternion.LookRotation(forward); + dmgPart.Play(); + } + if (shake != 0f) + { + component2.player.Call_AllGameFeel(shake * (Vector2)vector); + } + } + } +} diff --git a/ROUNDS/DamageEffect.cs b/ROUNDS/DamageEffect.cs new file mode 100644 index 0000000..d8d4907 --- /dev/null +++ b/ROUNDS/DamageEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class DamageEffect : MonoBehaviour +{ + public abstract void DoDamageEffect(Vector2 dmg, bool selfDmg, Player damagedPlayer = null); +} diff --git a/ROUNDS/DamageOverTime.cs b/ROUNDS/DamageOverTime.cs new file mode 100644 index 0000000..c1c6a17 --- /dev/null +++ b/ROUNDS/DamageOverTime.cs @@ -0,0 +1,38 @@ +using System.Collections; +using Sonigon; +using UnityEngine; + +public class DamageOverTime : MonoBehaviour +{ + private HealthHandler health; + + private CharacterData data; + + private void Start() + { + health = GetComponent<HealthHandler>(); + data = GetComponent<CharacterData>(); + } + + public void TakeDamageOverTime(Vector2 damage, Vector2 position, float time, float interval, Color color, SoundEvent soundDamageOverTime, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + StartCoroutine(DoDamageOverTime(damage, position, time, interval, color, soundDamageOverTime, damagingWeapon, damagingPlayer, lethal)); + } + + private IEnumerator DoDamageOverTime(Vector2 damage, Vector2 position, float time, float interval, Color color, SoundEvent soundDamageOverTime, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + float damageDealt = 0f; + float damageToDeal = damage.magnitude; + float dpt = damageToDeal / time * interval; + while (damageDealt < damageToDeal) + { + if (soundDamageOverTime != null && data.isPlaying && !data.dead) + { + SoundManager.Instance.Play(soundDamageOverTime, base.transform); + } + damageDealt += dpt; + health.DoDamage(damage.normalized * dpt, position, color, damagingWeapon, damagingPlayer, healthRemoval: true, lethal); + yield return new WaitForSeconds(interval / TimeHandler.timeScale); + } + } +} diff --git a/ROUNDS/DealDamageToPlayer.cs b/ROUNDS/DealDamageToPlayer.cs new file mode 100644 index 0000000..bfad181 --- /dev/null +++ b/ROUNDS/DealDamageToPlayer.cs @@ -0,0 +1,47 @@ +using Sonigon; +using UnityEngine; + +public class DealDamageToPlayer : MonoBehaviour +{ + public enum TargetPlayer + { + Own, + Other + } + + [Header("Sounds")] + public SoundEvent soundDamage; + + [Header("Settings")] + public float damage = 25f; + + public bool lethal = true; + + public TargetPlayer targetPlayer; + + private CharacterData data; + + private Player target; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + public void Go() + { + if (!target) + { + target = data.player; + if (targetPlayer == TargetPlayer.Other) + { + target = PlayerManager.instance.GetOtherPlayer(target); + } + } + if (soundDamage != null && target != null && target.data != null && target.data.isPlaying && !target.data.dead && !target.data.block.IsBlocking()) + { + SoundManager.Instance.Play(soundDamage, target.transform); + } + target.data.healthHandler.TakeDamage(damage * Vector2.up, base.transform.position, null, data.player, lethal); + } +} diff --git a/ROUNDS/DealtDamageEffect.cs b/ROUNDS/DealtDamageEffect.cs new file mode 100644 index 0000000..ec5cddc --- /dev/null +++ b/ROUNDS/DealtDamageEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class DealtDamageEffect : MonoBehaviour +{ + public abstract void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null); +} diff --git a/ROUNDS/DealtDamageTrigger.cs b/ROUNDS/DealtDamageTrigger.cs new file mode 100644 index 0000000..d596b4d --- /dev/null +++ b/ROUNDS/DealtDamageTrigger.cs @@ -0,0 +1,19 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class DealtDamageTrigger : MonoBehaviour +{ + public UnityEvent triggerEvent; + + private void Start() + { + CharacterStatModifiers stats = GetComponentInParent<Player>().data.stats; + stats.DealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(stats.DealtDamageAction, new Action<Vector2, bool>(DealtDamage)); + } + + private void DealtDamage(Vector2 dmg, bool lethal) + { + triggerEvent.Invoke(); + } +} diff --git a/ROUNDS/DeathEffect.cs b/ROUNDS/DeathEffect.cs new file mode 100644 index 0000000..5819e64 --- /dev/null +++ b/ROUNDS/DeathEffect.cs @@ -0,0 +1,101 @@ +using System.Collections; +using Sonigon; +using UnityEngine; + +public class DeathEffect : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundPhoenixActivate; + + public SoundEvent soundPhoenixChargeLoop; + + public SoundEvent soundPhoenixRespawn; + + private SoundParameterIntensity soundParameterChargeLoopIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + [Header("Settings")] + public float forceMulti = 1f; + + public float minScale = 0.9f; + + public float maxScale = 1.1f; + + public float minDrag = 0.9f; + + public float maxDrag = 1.1f; + + public float minForce = 0.9f; + + public float maxForce = 1.1f; + + public float spread = 0.5f; + + private Rigidbody2D[] rigs; + + private Color baseColor; + + private ParticleSystem[] parts; + + public ParticleSystem partToColor; + + public ParticleSystem[] partsToColor; + + private float respawnTimeCurrent; + + private float respawnTime = 2.53f; + + private void Update() + { + } + + public void PlayDeath(Color color, PlayerVelocity playerRig, Vector2 vel, int playerIDToRevive = -1) + { + if (vel.magnitude < 30f) + { + vel = vel.normalized * 30f; + } + vel *= 1f; + parts = GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < parts.Length; i++) + { + _ = parts[i].main; + if (parts[i].name.Contains("ROT")) + { + parts[i].transform.rotation = Quaternion.LookRotation(vel); + } + } + ParticleSystem.MainModule main = partToColor.main; + main.startColor = PlayerSkinBank.GetPlayerSkinColors(playerRig.GetComponent<Player>().playerID).color; + for (int j = 0; j < partsToColor.Length; j++) + { + ParticleSystem.MainModule main2 = partsToColor[j].main; + main2.startColor = PlayerSkinBank.GetPlayerSkinColors(playerRig.GetComponent<Player>().playerID).color; + } + if (playerIDToRevive != -1) + { + SoundManager.Instance.Play(soundPhoenixActivate, base.transform); + SoundManager.Instance.Play(soundPhoenixChargeLoop, base.transform, soundParameterChargeLoopIntensity); + StartCoroutine(RespawnPlayer(playerIDToRevive)); + } + } + + private IEnumerator RespawnPlayer(int playerIDToRevive = -1) + { + while (respawnTimeCurrent < respawnTime) + { + soundParameterChargeLoopIntensity.intensity = respawnTimeCurrent / respawnTime; + respawnTimeCurrent += 0.1f; + yield return new WaitForSeconds(0.1f); + } + SoundManager.Instance.Play(soundPhoenixRespawn, base.transform); + SoundManager.Instance.Stop(soundPhoenixChargeLoop, base.transform); + PlayerManager.instance.players[playerIDToRevive].data.healthHandler.Revive(isFullRevive: false); + PlayerManager.instance.players[playerIDToRevive].data.block.RPCA_DoBlock(firstBlock: true); + } + + private IEnumerator DoEffect(Rigidbody2D rig) + { + yield return new WaitForSeconds(Random.Range(0.05f, 0.15f)); + rig.GetComponent<SpriteRenderer>().color = baseColor; + } +} diff --git a/ROUNDS/Debug.cs b/ROUNDS/Debug.cs new file mode 100644 index 0000000..b35bd1d --- /dev/null +++ b/ROUNDS/Debug.cs @@ -0,0 +1,53 @@ +using System; +using UnityEngine; + +public static class Debug +{ + public static void Log(object logMsg) + { + } + + public static void Log(string logMsg) + { + } + + public static void Log(Exception exeption) + { + } + + public static void LogError(string logMsg) + { + } + + public static void LogError(string logMsg, object ob) + { + } + + public static void LogError(string logMsg, GameObject go) + { + } + + public static void LogWarning(string logMsg) + { + } + + public static void LogWarning(string logMsg, object ob) + { + } + + public static void ClearDeveloperConsole() + { + } + + public static void Assert(Transform t, string m) + { + } + + public static void DrawLine(Vector3 v1, Vector3 v2, Color c, float t) + { + } + + public static void DrawLine(Vector3 v1, Vector3 v2, Color c) + { + } +} diff --git a/ROUNDS/DelayEvent.cs b/ROUNDS/DelayEvent.cs new file mode 100644 index 0000000..0ebea56 --- /dev/null +++ b/ROUNDS/DelayEvent.cs @@ -0,0 +1,61 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Events; + +public class DelayEvent : MonoBehaviour +{ + public UnityEvent delayedEvent; + + public float time = 1f; + + public bool auto; + + public bool repeating; + + public bool usedTimeScale = true; + + private void Start() + { + CodeAnimation componentInParent = GetComponentInParent<CodeAnimation>(); + if ((bool)componentInParent) + { + time /= componentInParent.animations[0].animationSpeed; + } + if (auto) + { + Go(); + } + } + + public void Go() + { + StartCoroutine(DelayEventCall()); + } + + private IEnumerator DelayEventCall() + { + yield return 1; + if (usedTimeScale) + { + yield return new WaitForSeconds(time); + } + else + { + yield return new WaitForSecondsRealtime(time); + } + if (base.enabled) + { + delayedEvent.Invoke(); + if (repeating) + { + Go(); + } + } + } + + public void DoEvent() + { + StopAllCoroutines(); + delayedEvent.Invoke(); + } +} diff --git a/ROUNDS/DelayedEvent.cs b/ROUNDS/DelayedEvent.cs new file mode 100644 index 0000000..cfde350 --- /dev/null +++ b/ROUNDS/DelayedEvent.cs @@ -0,0 +1,14 @@ +using System; +using UnityEngine.Events; + +[Serializable] +public class DelayedEvent +{ + public UnityEvent eventTrigger; + + public float delay; + + public int cycles = 1; + + public int cyclesPerLvl; +} diff --git a/ROUNDS/DestroyEvent.cs b/ROUNDS/DestroyEvent.cs new file mode 100644 index 0000000..2e4fe63 --- /dev/null +++ b/ROUNDS/DestroyEvent.cs @@ -0,0 +1,22 @@ +using UnityEngine; +using UnityEngine.Events; + +public class DestroyEvent : MonoBehaviour +{ + public UnityEvent deathEvent; + + private bool m_isQuitting; + + private void OnDestroy() + { + if (!m_isQuitting) + { + deathEvent.Invoke(); + } + } + + private void OnApplicationQuit() + { + m_isQuitting = true; + } +} diff --git a/ROUNDS/DestroyObjects.cs b/ROUNDS/DestroyObjects.cs new file mode 100644 index 0000000..8cb52e2 --- /dev/null +++ b/ROUNDS/DestroyObjects.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public class DestroyObjects : MonoBehaviour +{ + public GameObject[] objectsToDestroy; + + public void DestroySelf() + { + Object.Destroy(base.gameObject); + } + + public void DestroyAllObjects() + { + for (int i = 0; i < objectsToDestroy.Length; i++) + { + Object.Destroy(objectsToDestroy[i]); + } + } +} diff --git a/ROUNDS/DestroyOnAwake.cs b/ROUNDS/DestroyOnAwake.cs new file mode 100644 index 0000000..47d4227 --- /dev/null +++ b/ROUNDS/DestroyOnAwake.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class DestroyOnAwake : MonoBehaviour +{ + private void Awake() + { + Object.Destroy(base.gameObject); + } +} diff --git a/ROUNDS/Destructible.cs b/ROUNDS/Destructible.cs new file mode 100644 index 0000000..e2b71b0 --- /dev/null +++ b/ROUNDS/Destructible.cs @@ -0,0 +1,45 @@ +using System; +using UnityEngine; + +public class Destructible : Damagable +{ + public float threshold = 25f; + + public float force = 1f; + + public float rangeMulti = 1f; + + public override void CallTakeDamage(Vector2 damage, Vector2 damagePosition, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + throw new NotImplementedException(); + } + + public override void TakeDamage(Vector2 damage, Vector2 position, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (!(damage.magnitude < threshold)) + { + damage = damage.normalized * 100f; + Transform[] array = new Transform[base.transform.childCount]; + for (int i = 0; i < array.Length; i++) + { + array[i] = base.transform.GetChild(i); + } + foreach (Transform transform in array) + { + transform.gameObject.SetActive(value: true); + transform.SetParent(null, worldPositionStays: true); + float num = damage.magnitude * 0.02f * rangeMulti; + float num2 = Mathf.Clamp((num - Vector2.Distance(transform.position, position)) / num, 0f, 1f); + Rigidbody2D component = transform.GetComponent<Rigidbody2D>(); + component.AddForce(damage * num2 * force * 0.1f * component.mass, ForceMode2D.Impulse); + transform.gameObject.AddComponent<RemoveAfterSeconds>().seconds = UnityEngine.Random.Range(1f, 3f); + } + base.gameObject.SetActive(value: false); + } + } + + public override void TakeDamage(Vector2 damage, Vector2 damagePosition, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + TakeDamage(damage, damagePosition, dmgColor, damagingWeapon, damagingPlayer, lethal); + } +} diff --git a/ROUNDS/DestructibleBoxDestruction.cs b/ROUNDS/DestructibleBoxDestruction.cs new file mode 100644 index 0000000..d7f7fb8 --- /dev/null +++ b/ROUNDS/DestructibleBoxDestruction.cs @@ -0,0 +1,40 @@ +using System; +using Sonigon; +using UnityEngine; + +public class DestructibleBoxDestruction : MonoBehaviour +{ + public bool soundPlayDestruction; + + public SoundEvent soundBoxDestruction; + + private void Start() + { + DamagableEvent componentInParent = GetComponentInParent<DamagableEvent>(); + componentInParent.DieAction = (Action<Vector2>)Delegate.Combine(componentInParent.DieAction, new Action<Vector2>(Die)); + } + + private void Die(Vector2 dmg) + { + if (soundPlayDestruction) + { + SoundManager.Instance.PlayAtPosition(soundBoxDestruction, SoundManager.Instance.GetTransform(), base.transform); + } + Rigidbody2D[] componentsInChildren = GetComponentsInChildren<Rigidbody2D>(includeInactive: true); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (base.transform != componentsInChildren[i].transform) + { + componentsInChildren[i].transform.SetParent(base.transform.root); + componentsInChildren[i].transform.gameObject.SetActive(value: true); + componentsInChildren[i].AddForce(dmg * UnityEngine.Random.Range(0f, 1f) * 500f, ForceMode2D.Impulse); + componentsInChildren[i].AddTorque(UnityEngine.Random.Range(-1f, 1f) * 1000f, ForceMode2D.Impulse); + componentsInChildren[i].GetComponent<RemoveAfterSeconds>().seconds = UnityEngine.Random.Range(0f, 0.5f); + componentsInChildren[i].GetComponentInChildren<GetColor>().Start(); + componentsInChildren[i].GetComponentInChildren<ColorBlink>().timeAmount *= UnityEngine.Random.Range(0.5f, 2f); + componentsInChildren[i].GetComponentInChildren<ColorBlink>().DoBlink(); + componentsInChildren[i].gameObject.layer = 18; + } + } + } +} diff --git a/ROUNDS/DevConsole.cs b/ROUNDS/DevConsole.cs new file mode 100644 index 0000000..e972cba --- /dev/null +++ b/ROUNDS/DevConsole.cs @@ -0,0 +1,128 @@ +using Photon.Pun; +using TMPro; +using UnityEngine; + +public class DevConsole : MonoBehaviour +{ + public TMP_InputField inputField; + + public static bool isTyping; + + private void Start() + { + isTyping = false; + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.Return)) + { + inputField.gameObject.SetActive(!inputField.gameObject.activeSelf); + isTyping = inputField.gameObject.activeSelf; + GameManager.lockInput = isTyping; + if (inputField.gameObject.activeSelf) + { + inputField.ActivateInputField(); + } + else + { + Send(inputField.text); + } + } + } + + private void Send(string message) + { + if (Application.isEditor || ((bool)GM_Test.instance && GM_Test.instance.gameObject.activeSelf)) + { + SpawnCard(message); + } + if (Application.isEditor) + { + SpawnMap(message); + } + int viewID = PlayerManager.instance.GetPlayerWithActorID(PhotonNetwork.LocalPlayer.ActorNumber).data.view.ViewID; + GetComponent<PhotonView>().RPC("RPCA_SendChat", RpcTarget.All, message, viewID); + } + + private void SpawnMap(string message) + { + try + { + int iD = int.Parse(message); + MapManager.instance.LoadLevelFromID(iD, onlyMaster: false, callInImidetly: true); + } + catch + { + } + } + + [PunRPC] + private void RPCA_SendChat(string message, int playerViewID) + { + PhotonNetwork.GetPhotonView(playerViewID).GetComponentInChildren<PlayerChat>().Send(message); + } + + private void SpawnCard(string message) + { + CardInfo[] cards = CardChoice.instance.cards; + int num = -1; + float num2 = 0f; + for (int i = 0; i < cards.Length; i++) + { + string text = cards[i].GetComponent<CardInfo>().cardName.ToUpper(); + text = text.Replace(" ", ""); + string text2 = message.ToUpper(); + text2 = text2.Replace(" ", ""); + float num3 = 0f; + for (int j = 0; j < text2.Length; j++) + { + if (text.Length > j && text2[j] == text[j]) + { + num3 += 1f / (float)text2.Length; + } + } + num3 -= (float)Mathf.Abs(text2.Length - text.Length) * 0.001f; + if (num3 > 0.1f && num3 > num2) + { + num2 = num3; + num = i; + } + } + if (num != -1) + { + GameObject obj = CardChoice.instance.AddCard(cards[num]); + obj.GetComponentInChildren<CardVisuals>().firstValueToSet = true; + obj.transform.root.GetComponentInChildren<ApplyCardStats>().shootToPick = true; + } + } + + public static int GetClosestString(string inputText, string[] compareTo) + { + CardInfo[] cards = CardChoice.instance.cards; + int result = -1; + float num = 0f; + for (int i = 0; i < cards.Length; i++) + { + string text = compareTo[i]; + text = text.Replace(" ", ""); + string text2 = inputText.ToUpper(); + text2 = text2.Replace(" ", ""); + float num2 = 0f; + for (int j = 0; j < text2.Length; j++) + { + if (text.Length > j && text2[j] == text[j]) + { + num2 += 1f / (float)text2.Length; + } + } + num2 -= (float)Mathf.Abs(text2.Length - text.Length) * 0.001f; + if (num2 > 0.1f && num2 > num) + { + num = num2; + result = i; + } + } + return result; + } +} diff --git a/ROUNDS/DisableChildren.cs b/ROUNDS/DisableChildren.cs new file mode 100644 index 0000000..e51223c --- /dev/null +++ b/ROUNDS/DisableChildren.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class DisableChildren : MonoBehaviour +{ + private void Start() + { + ParticleSystem[] componentsInChildren = GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].gameObject.SetActive(value: false); + } + } +} diff --git a/ROUNDS/DisableEvent.cs b/ROUNDS/DisableEvent.cs new file mode 100644 index 0000000..698d2e2 --- /dev/null +++ b/ROUNDS/DisableEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class DisableEvent : MonoBehaviour +{ + public UnityEvent disableEvent; + + public void OnDisable() + { + disableEvent.Invoke(); + } +} diff --git a/ROUNDS/DisableIfSimple.cs b/ROUNDS/DisableIfSimple.cs new file mode 100644 index 0000000..514da3d --- /dev/null +++ b/ROUNDS/DisableIfSimple.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +public class DisableIfSimple : MonoBehaviour +{ + private void Start() + { + Unparent componentInParent = GetComponentInParent<Unparent>(); + if ((bool)componentInParent && (bool)componentInParent.parent) + { + base.gameObject.SetActive(!componentInParent.parent.root.GetComponentInChildren<PlayerSkinHandler>().simpleSkin); + } + else + { + base.gameObject.SetActive(!base.transform.root.GetComponentInChildren<PlayerSkinHandler>().simpleSkin); + } + } +} diff --git a/ROUNDS/DisableObjects.cs b/ROUNDS/DisableObjects.cs new file mode 100644 index 0000000..e6c7516 --- /dev/null +++ b/ROUNDS/DisableObjects.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class DisableObjects : MonoBehaviour +{ + public bool playOnAwake = true; + + public GameObject[] objects; + + private void Start() + { + if (playOnAwake) + { + DoIt(); + } + } + + private void DoIt() + { + for (int i = 0; i < objects.Length; i++) + { + objects[i].SetActive(value: false); + } + } +} diff --git a/ROUNDS/DisplayMatchPlayerNames.cs b/ROUNDS/DisplayMatchPlayerNames.cs new file mode 100644 index 0000000..10e3cf5 --- /dev/null +++ b/ROUNDS/DisplayMatchPlayerNames.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using Photon.Pun; +using Photon.Realtime; +using TMPro; +using UnityEngine; + +public class DisplayMatchPlayerNames : MonoBehaviour +{ + public TextMeshProUGUI local; + + public TextMeshProUGUI other; + + public void ShowNames() + { + List<Photon.Realtime.Player> list = PhotonNetwork.CurrentRoom.Players.Select((KeyValuePair<int, Photon.Realtime.Player> p) => p.Value).ToList(); + bool flag = false; + flag = PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey(NetworkConnectionHandler.TWITCH_ROOM_AUDIENCE_RATING_KEY); + for (int i = 0; i < list.Count; i++) + { + string text = (flag ? (" (" + list[i].CustomProperties[NetworkConnectionHandler.TWITCH_PLAYER_SCORE_KEY].ToString() + ")") : string.Empty); + if (i == 0) + { + local.text = list[i].NickName + text; + } + else + { + other.text = list[i].NickName + text; + } + } + } +} diff --git a/ROUNDS/DmgEvent.cs b/ROUNDS/DmgEvent.cs new file mode 100644 index 0000000..16d50b1 --- /dev/null +++ b/ROUNDS/DmgEvent.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine.Events; + +[Serializable] +public class DmgEvent +{ + public UnityEvent eventToCall; + + public float dmg; +} diff --git a/ROUNDS/DoPlayerReload.cs b/ROUNDS/DoPlayerReload.cs new file mode 100644 index 0000000..8faa4e6 --- /dev/null +++ b/ROUNDS/DoPlayerReload.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class DoPlayerReload : MonoBehaviour +{ + private WeaponHandler wh; + + private void Start() + { + wh = GetComponentInParent<WeaponHandler>(); + } + + public void DoReload() + { + wh.DoReload(); + } +} diff --git a/ROUNDS/DodgeGround.cs b/ROUNDS/DodgeGround.cs new file mode 100644 index 0000000..a7d3815 --- /dev/null +++ b/ROUNDS/DodgeGround.cs @@ -0,0 +1,141 @@ +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class DodgeGround : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundSneakyDodgeGroundLoop; + + private bool soundIsPlaying; + + private float soundTimeToStopPlaying = 0.5f; + + private float soundTimeCurrent; + + private Transform spawnedSpawnerTransform; + + [Header("Settings")] + public float rayLength = 3f; + + public float rayUp = 0.3f; + + public float force; + + public LayerMask mask; + + private MoveTransform move; + + private SpawnedAttack spawned; + + public ParticleSystem p1; + + public ParticleSystem p2; + + public ParticleSystem p3; + + public LineRenderer l1; + + public LineRenderer l2; + + private float c3; + + private void Start() + { + spawned = GetComponentInParent<SpawnedAttack>(); + move = GetComponentInParent<MoveTransform>(); + GetComponentInParent<SyncProjectile>().active = true; + if (spawned != null && spawned.spawner != null) + { + spawnedSpawnerTransform = spawned.spawner.transform; + } + } + + private void SoundStart() + { + if (!soundIsPlaying && spawnedSpawnerTransform != null) + { + soundIsPlaying = true; + SoundManager.Instance.PlayAtPosition(soundSneakyDodgeGroundLoop, spawnedSpawnerTransform, base.transform); + } + } + + private void SoundStop() + { + if (soundIsPlaying && spawnedSpawnerTransform != null) + { + soundIsPlaying = false; + SoundManager.Instance.StopAtPosition(soundSneakyDodgeGroundLoop, base.transform); + } + } + + private void OnDestroy() + { + SoundStop(); + } + + private void Update() + { + float magnitude = move.velocity.magnitude; + c3 += TimeHandler.deltaTime; + l1.enabled = false; + l2.enabled = false; + bool flag = false; + float num = 1f; + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position, base.transform.forward + base.transform.right * rayUp, rayLength, mask); + if ((bool)raycastHit2D && (bool)raycastHit2D.transform && !raycastHit2D.collider.GetComponent<Damagable>() && raycastHit2D.transform.gameObject.layer != 10) + { + flag = true; + } + bool flag2 = false; + RaycastHit2D raycastHit2D2 = Physics2D.Raycast(base.transform.position, base.transform.forward + base.transform.right * (0f - rayUp), rayLength, mask); + if ((bool)raycastHit2D2 && (bool)raycastHit2D2.transform && !raycastHit2D2.collider.GetComponent<Damagable>() && raycastHit2D2.transform.gameObject.layer != 10) + { + flag2 = true; + } + if (flag && flag2 && raycastHit2D.transform == raycastHit2D2.transform) + { + if (raycastHit2D.distance < raycastHit2D2.distance) + { + flag2 = false; + } + else + { + flag = false; + } + } + if (flag) + { + move.velocity += (Vector3)raycastHit2D.normal * force * move.velocity.magnitude * num * TimeHandler.deltaTime; + l1.enabled = true; + l1.SetPosition(0, base.transform.position); + l1.SetPosition(1, raycastHit2D.point); + } + if (flag2) + { + move.velocity += (Vector3)raycastHit2D2.normal * force * move.velocity.magnitude * num * TimeHandler.deltaTime; + l2.enabled = true; + l2.SetPosition(0, base.transform.position); + l2.SetPosition(1, raycastHit2D2.point); + } + if (flag || flag2) + { + soundTimeCurrent = soundTimeToStopPlaying; + SoundStart(); + } + else if (soundIsPlaying) + { + soundTimeCurrent -= TimeHandler.deltaTime; + if (soundTimeCurrent < 0f) + { + SoundStop(); + } + } + move.velocity = move.velocity.normalized * magnitude; + if (flag && c3 > 0.05f) + { + c3 = 0f; + p3.Emit(1); + } + } +} diff --git a/ROUNDS/DontChangeMe.cs b/ROUNDS/DontChangeMe.cs new file mode 100644 index 0000000..cbef7b6 --- /dev/null +++ b/ROUNDS/DontChangeMe.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class DontChangeMe : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/DuringReloadTrigger.cs b/ROUNDS/DuringReloadTrigger.cs new file mode 100644 index 0000000..6f3609f --- /dev/null +++ b/ROUNDS/DuringReloadTrigger.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using UnityEngine.Events; + +public class DuringReloadTrigger : MonoBehaviour +{ + public UnityEvent triggerEvent; + + public UnityEvent triggerStartEvent; + + public UnityEvent triggerEndEvent; + + private Gun gunAmmo; + + private bool triggering; + + private void Start() + { + gunAmmo = GetComponentInParent<WeaponHandler>().gun; + } + + private void Update() + { + if (gunAmmo.isReloading) + { + if (!triggering) + { + triggerStartEvent.Invoke(); + triggering = true; + } + triggerEvent.Invoke(); + } + else if (triggering) + { + triggerEndEvent.Invoke(); + triggering = false; + } + } +} diff --git a/ROUNDS/DynamicParticleSet.cs b/ROUNDS/DynamicParticleSet.cs new file mode 100644 index 0000000..44931b9 --- /dev/null +++ b/ROUNDS/DynamicParticleSet.cs @@ -0,0 +1,9 @@ +using System; + +[Serializable] +public class DynamicParticleSet +{ + public ObjectsToSpawn objectsToSpawn; + + public float dmg; +} diff --git a/ROUNDS/DynamicParticles.cs b/ROUNDS/DynamicParticles.cs new file mode 100644 index 0000000..26a0cad --- /dev/null +++ b/ROUNDS/DynamicParticles.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +public class DynamicParticles : MonoBehaviour +{ + public static DynamicParticles instance; + + public DynamicParticleSet[] bulletHit; + + private int spawnsThisFrame; + + private void Start() + { + instance = this; + } + + private void Update() + { + spawnsThisFrame = 0; + } + + public void PlayBulletHit(float damage, Transform spawnerTransform, HitInfo hit, Color projectielColor) + { + if ((float)spawnsThisFrame > 5f) + { + return; + } + spawnsThisFrame++; + int num = 0; + for (int i = 1; i < bulletHit.Length && !(bulletHit[i].dmg > damage); i++) + { + num = i; + } + GameObject[] array = ObjectsToSpawn.SpawnObject(base.transform, hit, bulletHit[num].objectsToSpawn, null, null); + if (!(projectielColor != Color.black)) + { + return; + } + for (int j = 0; j < array.Length; j++) + { + for (int k = 0; k < array[j].transform.childCount; k++) + { + ChangeColor componentInChildren = array[j].transform.GetChild(k).GetComponentInChildren<ChangeColor>(); + if ((bool)componentInChildren) + { + componentInChildren.GetComponent<ParticleSystemRenderer>().material.color = projectielColor; + } + } + } + } +} diff --git a/ROUNDS/Emoji.cs b/ROUNDS/Emoji.cs new file mode 100644 index 0000000..14f1e06 --- /dev/null +++ b/ROUNDS/Emoji.cs @@ -0,0 +1,7 @@ +using System; + +[Serializable] +public class Emoji +{ + public CharacterItem[] emojiPieces; +} diff --git a/ROUNDS/EmojiButton.cs b/ROUNDS/EmojiButton.cs new file mode 100644 index 0000000..08e434a --- /dev/null +++ b/ROUNDS/EmojiButton.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class EmojiButton : MonoBehaviour +{ + private void Update() + { + } +} diff --git a/ROUNDS/EmojiCombiner.cs b/ROUNDS/EmojiCombiner.cs new file mode 100644 index 0000000..08039c4 --- /dev/null +++ b/ROUNDS/EmojiCombiner.cs @@ -0,0 +1,49 @@ +using UnityEngine; + +public class EmojiCombiner : MonoBehaviour +{ + public GameObject currentEmoji; + + public void AddEmoji(GameObject newEmoji) + { + CharacterItem characterItem = FindEmojiPiece(currentEmoji, "M"); + CharacterItem characterItem2 = FindEmojiPiece(newEmoji, "M"); + float delta = GetDelta(characterItem, characterItem2); + CharacterItem characterItem3 = FindEmojiPiece(currentEmoji, "E"); + CharacterItem characterItem4 = FindEmojiPiece(newEmoji, "E"); + float delta2 = GetDelta(characterItem3, characterItem4); + if (delta > delta2) + { + Object.Destroy(characterItem.gameObject); + GameObject obj = Object.Instantiate(characterItem2.gameObject); + obj.transform.SetParent(currentEmoji.transform); + obj.transform.localPosition = characterItem2.transform.localPosition; + } + else + { + Object.Destroy(characterItem3.gameObject); + GameObject obj2 = Object.Instantiate(characterItem4.gameObject); + obj2.transform.SetParent(currentEmoji.transform); + obj2.transform.localPosition = characterItem4.transform.localPosition; + } + } + + private float GetDelta(CharacterItem from, CharacterItem to) + { + return 1f; + } + + private CharacterItem FindEmojiPiece(GameObject emoji, string target) + { + target = target.ToUpper(); + CharacterItem[] componentsInChildren = emoji.GetComponentsInChildren<CharacterItem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].name.ToUpper()[0] == target.ToCharArray()[0]) + { + return componentsInChildren[i]; + } + } + return null; + } +} diff --git a/ROUNDS/Empower.cs b/ROUNDS/Empower.cs new file mode 100644 index 0000000..742e29a --- /dev/null +++ b/ROUNDS/Empower.cs @@ -0,0 +1,110 @@ +using System; +using Sonigon; +using UnityEngine; + +public class Empower : MonoBehaviour +{ + public SoundEvent soundEmpowerSpawn; + + public GameObject addObjectToBullet; + + public float dmgMultiplier = 2f; + + public float speedMultiplier = 2f; + + public Color empowerColor; + + private CharacterData data; + + private ParticleSystem[] parts; + + private Transform particleTransform; + + private bool empowered; + + private bool isOn; + + private void Start() + { + particleTransform = base.transform.GetChild(0); + data = GetComponentInParent<CharacterData>(); + parts = GetComponentsInChildren<ParticleSystem>(); + HealthHandler healthHandler = GetComponentInParent<Player>().data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(ResetEmpower)); + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(gun.ShootPojectileAction, new Action<GameObject>(Attack)); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void OnDestroy() + { + HealthHandler healthHandler = GetComponentInParent<Player>().data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Remove(healthHandler.reviveAction, new Action(ResetEmpower)); + Gun gun = data.weaponHandler.gun; + gun.ShootPojectileAction = (Action<GameObject>)Delegate.Remove(gun.ShootPojectileAction, new Action<GameObject>(Attack)); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void ResetEmpower() + { + empowered = false; + } + + public void Block(BlockTrigger.BlockTriggerType trigger) + { + if (trigger != BlockTrigger.BlockTriggerType.Echo && trigger != BlockTrigger.BlockTriggerType.Empower && trigger != BlockTrigger.BlockTriggerType.ShieldCharge) + { + empowered = true; + } + } + + public void Attack(GameObject projectile) + { + SpawnedAttack component = projectile.GetComponent<SpawnedAttack>(); + if (!component) + { + return; + } + if (empowered) + { + ProjectileHit component2 = projectile.GetComponent<ProjectileHit>(); + MoveTransform component3 = projectile.GetComponent<MoveTransform>(); + component.SetColor(empowerColor); + component2.damage *= dmgMultiplier; + component3.localForce *= speedMultiplier; + if ((bool)addObjectToBullet) + { + UnityEngine.Object.Instantiate(addObjectToBullet, projectile.transform.position, projectile.transform.rotation, projectile.transform); + } + } + empowered = false; + } + + private void Update() + { + if (empowered) + { + particleTransform.transform.position = data.weaponHandler.gun.transform.position; + particleTransform.transform.rotation = data.weaponHandler.gun.transform.rotation; + if (!isOn) + { + SoundManager.Instance.PlayAtPosition(soundEmpowerSpawn, SoundManager.Instance.GetTransform(), base.transform); + for (int i = 0; i < parts.Length; i++) + { + parts[i].Play(); + } + isOn = true; + } + } + else if (isOn) + { + for (int j = 0; j < parts.Length; j++) + { + parts[j].Stop(); + } + isOn = false; + } + } +} diff --git a/ROUNDS/EmpowerStopBlockObjectFollow.cs b/ROUNDS/EmpowerStopBlockObjectFollow.cs new file mode 100644 index 0000000..dd64869 --- /dev/null +++ b/ROUNDS/EmpowerStopBlockObjectFollow.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; + +public class EmpowerStopBlockObjectFollow : MonoBehaviour +{ + private void Start() + { + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void OnDestroy() + { + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.BlockAction, new Action<BlockTrigger.BlockTriggerType>(Block)); + } + + private void Block(BlockTrigger.BlockTriggerType triggerTyp) + { + if (triggerTyp == BlockTrigger.BlockTriggerType.Empower && (bool)GetComponent<SpawnObjects>()) + { + GetComponent<SpawnObjects>().mostRecentlySpawnedObject.GetComponent<FollowPlayer>().enabled = false; + } + } +} diff --git a/ROUNDS/EmptySprite.cs b/ROUNDS/EmptySprite.cs new file mode 100644 index 0000000..4442b89 --- /dev/null +++ b/ROUNDS/EmptySprite.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public static class EmptySprite +{ + private static Sprite instance; + + public static Sprite Get() + { + if (instance == null) + { + instance = Resources.Load<Sprite>("procedural_ui_image_default_sprite"); + } + return instance; + } + + public static bool IsEmptySprite(Sprite s) + { + if (Get() == s) + { + return true; + } + return false; + } +} diff --git a/ROUNDS/EnableEvent.cs b/ROUNDS/EnableEvent.cs new file mode 100644 index 0000000..2a2cfa0 --- /dev/null +++ b/ROUNDS/EnableEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class EnableEvent : MonoBehaviour +{ + public UnityEvent enableEvent; + + public void OnEnable() + { + enableEvent.Invoke(); + } +} diff --git a/ROUNDS/EnableObjectPerLevel.cs b/ROUNDS/EnableObjectPerLevel.cs new file mode 100644 index 0000000..ce1606c --- /dev/null +++ b/ROUNDS/EnableObjectPerLevel.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class EnableObjectPerLevel : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/EnsnareEffect.cs b/ROUNDS/EnsnareEffect.cs new file mode 100644 index 0000000..834d154 --- /dev/null +++ b/ROUNDS/EnsnareEffect.cs @@ -0,0 +1,98 @@ +using Sirenix.OdinInspector; +using Sonigon; +using UnityEngine; + +public class EnsnareEffect : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundEnsnare; + + public SoundEvent soundEnsnareBreak; + + public bool soundEnsnareJumpChange; + + public float range = 1f; + + private float seconds = 1f; + + public float force = 2000f; + + public float breakDistance = 2f; + + public float drag = 0.98f; + + private CharacterData target; + + private Vector2 startPos; + + public bool startPosIsMyPos; + + private float scale = 1f; + + private LineEffect line; + + [FoldoutGroup("SNAP", 0)] + public float snapCapLineTime = 0.5f; + + [FoldoutGroup("SNAP", 0)] + public float snapCapTimeTime = 0.5f; + + private bool done; + + private bool doneDone; + + private void Start() + { + scale *= base.transform.localScale.x; + range *= (1f + base.transform.localScale.x) * 0.5f; + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true); + if ((bool)closestPlayer && Vector3.Distance(base.transform.position, closestPlayer.transform.position) < range) + { + target = closestPlayer.data; + startPos = target.transform.position; + if (startPosIsMyPos) + { + startPos = base.transform.position; + } + float bezierOffset = 1f; + if (startPosIsMyPos) + { + bezierOffset = 0f; + } + line = GetComponentInChildren<LineEffect>(includeInactive: true); + line.Play(base.transform, closestPlayer.transform, bezierOffset); + if (soundEnsnare != null) + { + SoundManager.Instance.Play(soundEnsnare, target.transform); + } + if (soundEnsnareJumpChange) + { + target.playerSounds.AddEnsnareEffect(this); + } + } + } + + private void FixedUpdate() + { + if (!target || !(line.currentWidth > 0f)) + { + return; + } + target.sinceGrounded = 0f; + target.playerVel.velocity *= Mathf.Pow(drag, scale); + target.playerVel.AddForce(Vector2.ClampMagnitude(startPos - (Vector2)target.transform.position, 60f) * scale * force, ForceMode2D.Force); + if (!done && Vector2.Distance(startPos, target.transform.position) > breakDistance) + { + done = true; + line.counter = Mathf.Clamp(line.counter, snapCapLineTime, float.PositiveInfinity); + if (soundEnsnareJumpChange) + { + target.playerSounds.RemoveEnsnareEffect(this); + } + if (soundEnsnareBreak != null) + { + SoundManager.Instance.Play(soundEnsnareBreak, target.transform); + } + } + } +} diff --git a/ROUNDS/ErrorHandler.cs b/ROUNDS/ErrorHandler.cs new file mode 100644 index 0000000..e9ffc17 --- /dev/null +++ b/ROUNDS/ErrorHandler.cs @@ -0,0 +1,30 @@ +using TMPro; +using UnityEngine; + +public class ErrorHandler : MonoBehaviour +{ + public static ErrorHandler instance; + + public TextMeshProUGUI contextText; + + public TextMeshProUGUI reasonText; + + public GameObject UI; + + private void Awake() + { + instance = this; + } + + public void ShowError(string context, string reason) + { + contextText.text = context; + reasonText.text = reason; + UI.SetActive(value: true); + } + + public void HideError() + { + UI.SetActive(value: false); + } +} diff --git a/ROUNDS/EscapeMenuHandler.cs b/ROUNDS/EscapeMenuHandler.cs new file mode 100644 index 0000000..0204501 --- /dev/null +++ b/ROUNDS/EscapeMenuHandler.cs @@ -0,0 +1,62 @@ +using InControl; +using UnityEngine; + +public class EscapeMenuHandler : MonoBehaviour +{ + public static bool isEscMenu; + + public GameObject[] togglers; + + public GameObject canvs; + + private void Start() + { + isEscMenu = false; + } + + private void Update() + { + if (CharacterCreatorHandler.instance.SomeoneIsEditing() || canvs.activeInHierarchy) + { + return; + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + ToggleEsc(); + } + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].CommandWasPressed) + { + ToggleEsc(); + } + } + } + + public void ToggleEsc() + { + isEscMenu = !isEscMenu; + if (isEscMenu) + { + ListMenu.instance.SelectButton(GetComponentInChildren<ListMenuPage>().firstSelected); + } + else + { + ListMenu.instance.SelectButton(GetComponentsInChildren<ListMenuButton>()[1]); + } + for (int i = 0; i < togglers.Length; i++) + { + togglers[i].SetActive(isEscMenu); + } + if (isEscMenu) + { + ListMenu.instance.SelectButton(GetComponentInChildren<ListMenuPage>().firstSelected); + return; + } + ListMenuButton[] componentsInChildren = GetComponentsInChildren<ListMenuButton>(includeInactive: true); + if (componentsInChildren.Length > 2) + { + ListMenu.instance.SelectButton(componentsInChildren[1]); + } + } +} diff --git a/ROUNDS/EventSequence.cs b/ROUNDS/EventSequence.cs new file mode 100644 index 0000000..f875669 --- /dev/null +++ b/ROUNDS/EventSequence.cs @@ -0,0 +1,52 @@ +using System.Collections; +using UnityEngine; + +public class EventSequence : MonoBehaviour +{ + public bool playOnAwake = true; + + public bool useTimeScale = true; + + public DelayedEvent[] events; + + private int level; + + private void Start() + { + level = GetComponentInParent<AttackLevel>().attackLevel; + if (playOnAwake) + { + Go(); + } + } + + public void Go() + { + StartCoroutine(DoSequence()); + } + + private IEnumerator DoSequence() + { + for (int i = 0; i < events.Length; i++) + { + float num = 0f; + for (int i2 = 0; i2 < events[i].cycles + events[i].cyclesPerLvl * level; i2++) + { + num += events[i].delay; + if (num > TimeHandler.deltaTime) + { + if (useTimeScale) + { + yield return new WaitForSeconds(num); + } + else + { + yield return new WaitForSecondsRealtime(num); + } + num = 0f; + } + events[i].eventTrigger.Invoke(); + } + } + } +} diff --git a/ROUNDS/ExceptionThrown.cs b/ROUNDS/ExceptionThrown.cs new file mode 100644 index 0000000..1ba81e0 --- /dev/null +++ b/ROUNDS/ExceptionThrown.cs @@ -0,0 +1,3 @@ +using System; + +public delegate void ExceptionThrown(Exception exeption); diff --git a/ROUNDS/Explosion.cs b/ROUNDS/Explosion.cs new file mode 100644 index 0000000..02af031 --- /dev/null +++ b/ROUNDS/Explosion.cs @@ -0,0 +1,216 @@ +using System; +using Photon.Pun; +using Sirenix.OdinInspector; +using Sonigon; +using UnityEngine; + +public class Explosion : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundDamage; + + [Header("Settings")] + public float slow; + + public float silence; + + public bool fastSlow; + + public float stun; + + public float force = 2000f; + + public float objectForceMultiplier = 1f; + + public bool forceIgnoreMass; + + public float damage = 25f; + + public Color dmgColor = Color.black; + + public float range = 2f; + + public float flyingFor; + + public bool auto = true; + + public bool ignoreTeam; + + public bool ignoreWalls; + + public bool staticRangeMultiplier; + + [FoldoutGroup("Scaling", 0)] + public bool scaleSlow = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleSilence = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleDmg = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleRadius = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleStun = true; + + [FoldoutGroup("Scaling", 0)] + public bool scaleForce = true; + + [FoldoutGroup("Immunity", 0)] + public float immunity; + + private SpawnedAttack spawned; + + public bool locallySimulated; + + public Action<Damagable> DealDamageAction; + + public Action<Damagable> DealHealAction; + + public Action<Damagable, float> HitTargetAction; + + private PhotonView view; + + public Action<CharacterData, float> hitPlayerAction; + + private void Start() + { + spawned = GetComponent<SpawnedAttack>(); + view = GetComponent<PhotonView>(); + if (auto) + { + Explode(); + } + } + + private void DoExplosionEffects(Collider2D hitCol, float rangeMultiplier, float distance) + { + float num = (scaleDmg ? base.transform.localScale.x : 1f); + float num2 = (scaleForce ? base.transform.localScale.x : 1f); + float num3 = (scaleSlow ? base.transform.localScale.x : 1f); + float num4 = (scaleSilence ? base.transform.localScale.x : 1f); + float num5 = (scaleStun ? ((1f + base.transform.localScale.x) * 0.5f) : 1f); + Damagable componentInParent = hitCol.gameObject.GetComponentInParent<Damagable>(); + CharacterData characterData = null; + if ((bool)componentInParent) + { + characterData = hitCol.gameObject.GetComponentInParent<CharacterData>(); + if ((immunity > 0f && (bool)characterData && characterData.GetComponent<PlayerImmunity>().IsImune(immunity, num * damage * rangeMultiplier, base.gameObject.name)) || (!ignoreWalls && (bool)characterData && !PlayerManager.instance.CanSeePlayer(base.transform.position, characterData.player).canSee)) + { + return; + } + if (slow != 0f && (bool)componentInParent.GetComponent<CharacterStatModifiers>()) + { + if (locallySimulated) + { + if (spawned.IsMine() && !characterData.block.IsBlocking()) + { + characterData.stats.RPCA_AddSlow(slow * rangeMultiplier * num3, fastSlow); + } + } + else if (spawned.IsMine() && !characterData.block.IsBlocking()) + { + characterData.view.RPC("RPCA_AddSlow", RpcTarget.All, slow * rangeMultiplier * num3, fastSlow); + } + } + if (silence != 0f && (bool)componentInParent.GetComponent<SilenceHandler>() && spawned.IsMine() && !characterData.block.IsBlocking()) + { + characterData.view.RPC("RPCA_AddSilence", RpcTarget.All, silence * rangeMultiplier * num4); + } + if ((bool)spawned) + { + _ = spawned.spawner; + } + hitPlayerAction?.Invoke(characterData, rangeMultiplier); + if (damage < 0f) + { + if ((bool)characterData) + { + characterData.healthHandler.Heal(0f - damage); + } + if (DealHealAction != null) + { + DealHealAction(componentInParent); + } + } + else if (damage > 0f) + { + if (soundDamage != null && characterData != null) + { + SoundManager.Instance.Play(soundDamage, characterData.transform); + } + Vector2 vector = ((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized; + if (vector == Vector2.zero) + { + vector = Vector2.up; + } + if (spawned.IsMine()) + { + componentInParent.CallTakeDamage(num * damage * rangeMultiplier * vector, base.transform.position, null, spawned.spawner); + } + if (DealDamageAction != null) + { + DealDamageAction(componentInParent); + } + } + } + if ((bool)characterData) + { + if (HitTargetAction != null) + { + HitTargetAction(componentInParent, distance); + } + if (force != 0f) + { + if (locallySimulated) + { + characterData.healthHandler.TakeForce(((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized * rangeMultiplier * force * num2, ForceMode2D.Impulse, forceIgnoreMass); + } + else if (spawned.IsMine()) + { + characterData.healthHandler.CallTakeForce(((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized * rangeMultiplier * force * num2, ForceMode2D.Impulse, forceIgnoreMass, ignoreBlock: false, flyingFor * rangeMultiplier); + } + } + if (stun > 0f) + { + characterData.stunHandler.AddStun(stun * num5); + } + } + else if ((bool)hitCol.attachedRigidbody) + { + hitCol.attachedRigidbody.AddForce(((Vector2)hitCol.bounds.ClosestPoint(base.transform.position) - (Vector2)base.transform.position).normalized * rangeMultiplier * force * num2, ForceMode2D.Impulse); + } + } + + public void Explode() + { + float num = (scaleRadius ? base.transform.localScale.x : 1f); + Collider2D[] array = Physics2D.OverlapCircleAll(base.transform.position, range * num); + for (int i = 0; i < array.Length; i++) + { + if (array[i].gameObject.layer != 19) + { + Damagable componentInParent = array[i].gameObject.GetComponentInParent<Damagable>(); + float num2 = Vector2.Distance(base.transform.position, array[i].bounds.ClosestPoint(base.transform.position)); + float value = 1f - num2 / (range * num); + if (staticRangeMultiplier) + { + value = 1f; + } + value = Mathf.Clamp(value, 0f, 1f); + NetworkPhysicsObject component = array[i].GetComponent<NetworkPhysicsObject>(); + if ((bool)component && component.photonView.IsMine) + { + float num3 = (scaleForce ? base.transform.localScale.x : 1f); + component.BulletPush((Vector2)(component.transform.position - base.transform.position).normalized * objectForceMultiplier * 1f * value * force * num3, Vector2.zero, null); + } + if (((bool)componentInParent || (bool)array[i].attachedRigidbody) && (!ignoreTeam || !spawned || !(spawned.spawner.gameObject == array[i].transform.gameObject))) + { + DoExplosionEffects(array[i], value, num2); + } + } + } + } +} diff --git a/ROUNDS/Explosion_Overpower.cs b/ROUNDS/Explosion_Overpower.cs new file mode 100644 index 0000000..13a98ac --- /dev/null +++ b/ROUNDS/Explosion_Overpower.cs @@ -0,0 +1,23 @@ +using System; +using UnityEngine; + +public class Explosion_Overpower : MonoBehaviour +{ + public float dmgPer100Hp; + + private void Awake() + { + Explosion component = GetComponent<Explosion>(); + component.hitPlayerAction = (Action<CharacterData, float>)Delegate.Combine(component.hitPlayerAction, new Action<CharacterData, float>(HitPlayer)); + } + + private void HitPlayer(CharacterData data, float rangeMultiplier) + { + SpawnedAttack component = GetComponent<SpawnedAttack>(); + if (component.IsMine()) + { + float num = component.spawner.data.maxHealth * dmgPer100Hp * 0.01f * base.transform.localScale.x; + data.healthHandler.CallTakeDamage(num * (data.transform.position - component.spawner.transform.position).normalized, base.transform.position, null, GetComponent<SpawnedAttack>().spawner); + } + } +} diff --git a/ROUNDS/Extensions.cs b/ROUNDS/Extensions.cs new file mode 100644 index 0000000..41040bc --- /dev/null +++ b/ROUNDS/Extensions.cs @@ -0,0 +1,19 @@ +using System; + +public static class Extensions +{ + public static double NextGaussianDouble(this Random r) + { + double num; + double num3; + do + { + num = 2.0 * r.NextDouble() - 1.0; + double num2 = 2.0 * r.NextDouble() - 1.0; + num3 = num * num + num2 * num2; + } + while (num3 >= 1.0); + double num4 = Math.Sqrt(-2.0 * Math.Log(num3) / num3); + return num * num4; + } +} diff --git a/ROUNDS/ExtraBlock.cs b/ROUNDS/ExtraBlock.cs new file mode 100644 index 0000000..a14cdab --- /dev/null +++ b/ROUNDS/ExtraBlock.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class ExtraBlock : MonoBehaviour +{ + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + public void Go() + { + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true); + } +} diff --git a/ROUNDS/FRILerp.cs b/ROUNDS/FRILerp.cs new file mode 100644 index 0000000..f27815b --- /dev/null +++ b/ROUNDS/FRILerp.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +public class FRILerp : MonoBehaviour +{ + private void Start() + { + } + + public static Vector3 Lerp(Vector3 from, Vector3 target, float speed) + { + return Vector3.Lerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Vector3 LerpUnclamped(Vector3 from, Vector3 target, float speed) + { + return Vector3.LerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static float Lerp(float from, float target, float speed) + { + return Mathf.Lerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static float LerpUnclamped(float from, float target, float speed) + { + return Mathf.LerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Vector3 Slerp(Vector3 from, Vector3 target, float speed) + { + return Vector3.Slerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Vector3 SlerpUnclamped(Vector3 from, Vector3 target, float speed) + { + return Vector3.SlerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Quaternion Lerp(Quaternion from, Quaternion target, float speed) + { + return Quaternion.Lerp(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } + + public static Quaternion LerpUnclamped(Quaternion from, Quaternion target, float speed) + { + return Quaternion.LerpUnclamped(from, target, 1f - Mathf.Exp((0f - speed) * TimeHandler.deltaTime)); + } +} diff --git a/ROUNDS/FakeParticleDB.cs b/ROUNDS/FakeParticleDB.cs new file mode 100644 index 0000000..0e82935 --- /dev/null +++ b/ROUNDS/FakeParticleDB.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "FakeParticleDB", menuName = "FakeParticleDB", order = 999999999)] +public class FakeParticleDB : ScriptableObject +{ + public Material m_DefaultMaterial; + + public Material m_ParticleMaterial; + + private static FakeParticleDB _inst; + + private static FakeParticleDB instance + { + get + { + if (_inst == null) + { + _inst = Resources.Load("FakeParticleDB") as FakeParticleDB; + } + return _inst; + } + } + + public static Material GetParticleMaterial() + { + return instance.m_ParticleMaterial; + } + + public static Material GetDefaultMaterial() + { + return instance.m_DefaultMaterial; + } +} diff --git a/ROUNDS/FlickerEvent.cs b/ROUNDS/FlickerEvent.cs new file mode 100644 index 0000000..dd4096e --- /dev/null +++ b/ROUNDS/FlickerEvent.cs @@ -0,0 +1,48 @@ +using UnityEngine; +using UnityEngine.Events; + +public class FlickerEvent : MonoBehaviour +{ + public UnityEvent onEvent; + + public UnityEvent offEvent; + + public float interval; + + private float c; + + public bool isOn; + + private bool flickedOn; + + private void Start() + { + } + + private void Update() + { + c += TimeHandler.deltaTime; + if (isOn) + { + if (c > interval) + { + flickedOn = !flickedOn; + if (flickedOn) + { + onEvent.Invoke(); + } + else + { + offEvent.Invoke(); + } + c = 0f; + } + } + else if (flickedOn && c > interval) + { + c = 0f; + offEvent.Invoke(); + flickedOn = false; + } + } +} diff --git a/ROUNDS/FollowInactiveHand.cs b/ROUNDS/FollowInactiveHand.cs new file mode 100644 index 0000000..a52b5e7 --- /dev/null +++ b/ROUNDS/FollowInactiveHand.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class FollowInactiveHand : MonoBehaviour +{ + private CharacterData data; + + public Vector3 offSet; + + public GameObject leftHand; + + public GameObject rightHand; + + private void Start() + { + data = base.transform.root.GetComponent<CharacterData>(); + } + + private void Update() + { + if (data.aimDirection.x < 0f) + { + base.transform.position = rightHand.transform.TransformPoint(offSet); + } + else + { + base.transform.position = leftHand.transform.TransformPoint(offSet); + } + } +} diff --git a/ROUNDS/FollowLocalPos.cs b/ROUNDS/FollowLocalPos.cs new file mode 100644 index 0000000..194f947 --- /dev/null +++ b/ROUNDS/FollowLocalPos.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +public class FollowLocalPos : MonoBehaviour +{ + private Vector3 relative; + + private Vector3 relativeForward; + + private Vector3 relativeUp; + + public Transform target; + + public Player targetPlayer; + + private void Start() + { + if ((bool)target && relative == Vector3.zero) + { + Follow(target); + } + } + + private void LateUpdate() + { + if ((bool)target && target.gameObject.activeInHierarchy) + { + base.transform.position = target.TransformPoint(relative); + base.transform.rotation = Quaternion.LookRotation(target.TransformDirection(relativeForward), target.TransformDirection(relativeUp)); + } + else + { + Object.Destroy(base.gameObject); + } + } + + public void Follow(Transform targetTransform) + { + if ((bool)targetTransform) + { + target = targetTransform; + Player component = target.transform.root.GetComponent<Player>(); + Vector3 position = base.transform.position; + if ((bool)component) + { + targetPlayer = component; + base.transform.position -= base.transform.forward * 2f; + Vector3 position2 = target.position; + Vector3 vector = (base.transform.position - target.position).normalized * 1.1f; + position = position2 + vector; + base.transform.position = new Vector3(base.transform.position.x, base.transform.position.y, component.transform.position.z); + } + relative = targetTransform.InverseTransformPoint(position); + relativeForward = targetTransform.InverseTransformDirection(base.transform.forward); + relativeUp = targetTransform.InverseTransformDirection(base.transform.up); + } + } +} diff --git a/ROUNDS/FollowPlayer.cs b/ROUNDS/FollowPlayer.cs new file mode 100644 index 0000000..cd3c826 --- /dev/null +++ b/ROUNDS/FollowPlayer.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +public class FollowPlayer : MonoBehaviour +{ + public enum Target + { + Self, + Other + } + + public Target target; + + public bool inheritScale = true; + + private Vector3 startScale; + + private Player ownPlayer; + + private void Start() + { + startScale = base.transform.localScale; + ownPlayer = GetComponentInParent<Player>(); + if (!ownPlayer) + { + ownPlayer = GetComponentInParent<SpawnedAttack>().spawner; + } + } + + private void LateUpdate() + { + Player player = null; + player = ((target != Target.Other) ? ownPlayer : PlayerManager.instance.GetOtherPlayer(ownPlayer)); + if (inheritScale) + { + base.transform.localScale = new Vector3(player.transform.localScale.x * startScale.x, player.transform.localScale.y * startScale.y, player.transform.localScale.z * startScale.z); + } + base.transform.position = player.transform.position; + base.transform.rotation = player.transform.rotation; + } +} diff --git a/ROUNDS/FollowRandomPlayer.cs b/ROUNDS/FollowRandomPlayer.cs new file mode 100644 index 0000000..c8d8516 --- /dev/null +++ b/ROUNDS/FollowRandomPlayer.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +public class FollowRandomPlayer : MonoBehaviour +{ + public bool X = true; + + public bool Y = true; + + private Transform targetPlayer; + + public bool snap; + + private void Start() + { + } + + private void Update() + { + if (!targetPlayer) + { + GetNewPlayer(); + } + else if (snap) + { + base.transform.position = new Vector3(X ? targetPlayer.position.x : base.transform.position.x, Y ? targetPlayer.position.y : base.transform.position.y, 0f); + } + else + { + base.transform.position = Vector3.Lerp(base.transform.position, new Vector3(X ? targetPlayer.position.x : base.transform.position.x, Y ? targetPlayer.position.y : base.transform.position.y, 0f), TimeHandler.deltaTime * 5f); + } + } + + private void GetNewPlayer() + { + if (PlayerManager.instance.players.Count > 0) + { + targetPlayer = PlayerManager.instance.players[Random.Range(0, PlayerManager.instance.players.Count)].transform; + } + } +} diff --git a/ROUNDS/FollowScale.cs b/ROUNDS/FollowScale.cs new file mode 100644 index 0000000..6666c05 --- /dev/null +++ b/ROUNDS/FollowScale.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class FollowScale : MonoBehaviour +{ + public Transform target; + + private void Update() + { + if ((bool)target) + { + base.transform.localScale = target.transform.localScale; + } + } +} diff --git a/ROUNDS/FollowTransform.cs b/ROUNDS/FollowTransform.cs new file mode 100644 index 0000000..32c0671 --- /dev/null +++ b/ROUNDS/FollowTransform.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class FollowTransform : MonoBehaviour +{ + public Transform target; + + private Vector3 spawnOffset; + + public Vector3 offset; + + private void Start() + { + spawnOffset = base.transform.position - target.position; + } + + private void LateUpdate() + { + if ((bool)target) + { + base.transform.position = target.position + spawnOffset + offset; + } + } +} diff --git a/ROUNDS/ForceMultiplier.cs b/ROUNDS/ForceMultiplier.cs new file mode 100644 index 0000000..064bbfc --- /dev/null +++ b/ROUNDS/ForceMultiplier.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class ForceMultiplier : MonoBehaviour +{ + public float multiplier = 1f; +} diff --git a/ROUNDS/FreeModifier.cs b/ROUNDS/FreeModifier.cs new file mode 100644 index 0000000..4f8badf --- /dev/null +++ b/ROUNDS/FreeModifier.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Free")] +public class FreeModifier : ProceduralImageModifier +{ + [SerializeField] + private Vector4 radius; + + public Vector4 Radius + { + get + { + return radius; + } + set + { + radius = value; + base._Graphic.SetVerticesDirty(); + } + } + + public override Vector4 CalculateRadius(Rect imageRect) + { + return radius; + } + + protected void OnValidate() + { + radius.x = Mathf.Max(0f, radius.x); + radius.y = Mathf.Max(0f, radius.y); + radius.z = Mathf.Max(0f, radius.z); + radius.w = Mathf.Max(0f, radius.w); + } +} diff --git a/ROUNDS/GM_ArmsRace.cs b/ROUNDS/GM_ArmsRace.cs new file mode 100644 index 0000000..3d309ae --- /dev/null +++ b/ROUNDS/GM_ArmsRace.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class GM_ArmsRace : MonoBehaviour +{ + private int playersNeededToStart = 2; + + private int pointsToWinRound = 2; + + public int roundsToWinGame = 5; + + public int p1Points; + + public int p2Points; + + public int p1Rounds; + + public int p2Rounds; + + private PhotonView view; + + public static GM_ArmsRace instance; + + private bool isWaiting; + + public Action StartGameAction; + + public bool pickPhase = true; + + [HideInInspector] + public bool isPicking; + + private bool waitingForOtherPlayer = true; + + private int currentWinningTeamID = -1; + + public Action pointOverAction; + + private bool isTransitioning; + + private void Awake() + { + instance = this; + } + + private void Start() + { + view = GetComponent<PhotonView>(); + PlayerManager.instance.SetPlayersSimulated(simulated: false); + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + PlayerAssigner.instance.SetPlayersCanJoin(canJoin: true); + PlayerManager.instance.AddPlayerDiedAction(PlayerDied); + PlayerManager playerManager = PlayerManager.instance; + playerManager.PlayerJoinedAction = (Action<Player>)Delegate.Combine(playerManager.PlayerJoinedAction, new Action<Player>(PlayerJoined)); + ArtHandler.instance.NextArt(); + playersNeededToStart = 2; + UIHandler.instance.SetNumberOfRounds(roundsToWinGame); + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + if (!PhotonNetwork.OfflineMode) + { + UIHandler.instance.ShowJoinGameText("PRESS JUMP\n TO JOIN", PlayerSkinBank.GetPlayerSkinColors(0).winText); + } + } + + private void Update() + { + if (Input.GetKey(KeyCode.Alpha4)) + { + playersNeededToStart = 4; + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + } + if (Input.GetKey(KeyCode.Alpha2)) + { + playersNeededToStart = 2; + PlayerAssigner.instance.maxPlayers = playersNeededToStart; + } + } + + public void PlayerJoined(Player player) + { + if (PhotonNetwork.OfflineMode) + { + return; + } + if (!PhotonNetwork.OfflineMode) + { + if (player.data.view.IsMine) + { + UIHandler.instance.ShowJoinGameText("WAITING", PlayerSkinBank.GetPlayerSkinColors(1).winText); + } + else + { + UIHandler.instance.ShowJoinGameText("PRESS JUMP\n TO JOIN", PlayerSkinBank.GetPlayerSkinColors(1).winText); + } + } + player.data.isPlaying = false; + int count = PlayerManager.instance.players.Count; + if (count >= playersNeededToStart) + { + StartGame(); + } + else if (PhotonNetwork.OfflineMode) + { + if (playersNeededToStart - count == 3) + { + UIHandler.instance.ShowJoinGameText("ADD THREE MORE PLAYER TO START", PlayerSkinBank.GetPlayerSkinColors(count).winText); + } + if (playersNeededToStart - count == 2) + { + UIHandler.instance.ShowJoinGameText("ADD TWO MORE PLAYER TO START", PlayerSkinBank.GetPlayerSkinColors(count).winText); + } + if (playersNeededToStart - count == 1) + { + UIHandler.instance.ShowJoinGameText("ADD ONE MORE PLAYER TO START", PlayerSkinBank.GetPlayerSkinColors(count).winText); + } + } + } + + [PunRPC] + private void RPCO_RequestSyncUp() + { + view.RPC("RPCM_ReturnSyncUp", RpcTarget.Others); + } + + [PunRPC] + private void RPCM_ReturnSyncUp() + { + isWaiting = false; + } + + private IEnumerator WaitForSyncUp() + { + if (!PhotonNetwork.OfflineMode) + { + isWaiting = true; + view.RPC("RPCO_RequestSyncUp", RpcTarget.Others); + while (isWaiting) + { + yield return null; + } + } + } + + public void StartGame() + { + if (!GameManager.instance.isPlaying) + { + StartGameAction?.Invoke(); + GameManager.instance.isPlaying = true; + StartCoroutine(DoStartGame()); + } + } + + private IEnumerator DoStartGame() + { + GameManager.instance.battleOngoing = false; + UIHandler.instance.ShowJoinGameText("LETS GOO!", PlayerSkinBank.GetPlayerSkinColors(1).winText); + yield return new WaitForSeconds(0.25f); + UIHandler.instance.HideJoinGameText(); + PlayerManager.instance.SetPlayersSimulated(simulated: false); + PlayerManager.instance.SetPlayersVisible(visible: false); + MapManager.instance.LoadNextLevel(); + TimeHandler.instance.DoSpeedUp(); + yield return new WaitForSecondsRealtime(1f); + if (pickPhase) + { + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + yield return StartCoroutine(WaitForSyncUp()); + CardChoiceVisuals.instance.Show(i, animateIn: true); + yield return CardChoice.instance.DoPick(1, PlayerManager.instance.players[i].playerID, PickerType.Player); + yield return new WaitForSecondsRealtime(0.1f); + } + yield return StartCoroutine(WaitForSyncUp()); + CardChoiceVisuals.instance.Hide(); + } + MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); + TimeHandler.instance.DoSpeedUp(); + TimeHandler.instance.StartGame(); + GameManager.instance.battleOngoing = true; + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + PlayerManager.instance.SetPlayersVisible(visible: true); + } + + private IEnumerator PointTransition(int winningTeamID, string winTextBefore, string winText) + { + StartCoroutine(PointVisualizer.instance.DoSequence(p1Points, p2Points, winningTeamID == 0)); + yield return new WaitForSecondsRealtime(1f); + MapManager.instance.LoadNextLevel(); + yield return new WaitForSecondsRealtime(0.5f); + yield return StartCoroutine(WaitForSyncUp()); + MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); + PlayerManager.instance.RevivePlayers(); + yield return new WaitForSecondsRealtime(0.3f); + TimeHandler.instance.DoSpeedUp(); + GameManager.instance.battleOngoing = true; + isTransitioning = false; + } + + private void PointOver(int winningTeamID) + { + int num = p1Points; + int num2 = p2Points; + if (winningTeamID == 0) + { + num--; + } + else + { + num2--; + } + string winTextBefore = num + " - " + num2; + string winText = p1Points + " - " + p2Points; + StartCoroutine(PointTransition(winningTeamID, winTextBefore, winText)); + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + } + + private IEnumerator RoundTransition(int winningTeamID, int killedTeamID) + { + StartCoroutine(PointVisualizer.instance.DoWinSequence(p1Points, p2Points, p1Rounds, p2Rounds, winningTeamID == 0)); + yield return new WaitForSecondsRealtime(1f); + MapManager.instance.LoadNextLevel(); + yield return new WaitForSecondsRealtime(0.3f); + yield return new WaitForSecondsRealtime(1f); + TimeHandler.instance.DoSpeedUp(); + if (pickPhase) + { + Debug.Log("PICK PHASE"); + PlayerManager.instance.SetPlayersVisible(visible: false); + Player[] players = PlayerManager.instance.GetPlayersInTeam(killedTeamID); + for (int i = 0; i < players.Length; i++) + { + yield return StartCoroutine(WaitForSyncUp()); + yield return CardChoice.instance.DoPick(1, players[i].playerID, PickerType.Player); + yield return new WaitForSecondsRealtime(0.1f); + } + PlayerManager.instance.SetPlayersVisible(visible: true); + } + yield return StartCoroutine(WaitForSyncUp()); + TimeHandler.instance.DoSlowDown(); + MapManager.instance.CallInNewMapAndMovePlayers(MapManager.instance.currentLevelID); + PlayerManager.instance.RevivePlayers(); + yield return new WaitForSecondsRealtime(0.3f); + TimeHandler.instance.DoSpeedUp(); + isTransitioning = false; + GameManager.instance.battleOngoing = true; + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + } + + private void RoundOver(int winningTeamID, int losingTeamID) + { + currentWinningTeamID = winningTeamID; + StartCoroutine(RoundTransition(winningTeamID, losingTeamID)); + p1Points = 0; + p2Points = 0; + } + + private IEnumerator GameOverTransition(int winningTeamID) + { + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + UIHandler.instance.DisplayScreenText(PlayerManager.instance.GetColorFromTeam(winningTeamID).winText, "VICTORY!", 1f); + yield return new WaitForSecondsRealtime(2f); + GameOverRematch(winningTeamID); + } + + private void GameOverRematch(int winningTeamID) + { + UIHandler.instance.DisplayScreenTextLoop(PlayerManager.instance.GetColorFromTeam(winningTeamID).winText, "REMATCH?"); + UIHandler.instance.DisplayYesNoLoop(PlayerManager.instance.GetFirstPlayerInTeam(winningTeamID), GetRematchYesNo); + MapManager.instance.LoadNextLevel(); + } + + private void GetRematchYesNo(PopUpHandler.YesNo yesNo) + { + if (yesNo == PopUpHandler.YesNo.Yes) + { + StartCoroutine(IDoRematch()); + } + else + { + DoRestart(); + } + } + + [PunRPC] + public void RPCA_PlayAgain() + { + waitingForOtherPlayer = false; + } + + private IEnumerator IDoRematch() + { + if (!PhotonNetwork.OfflineMode) + { + GetComponent<PhotonView>().RPC("RPCA_PlayAgain", RpcTarget.Others); + UIHandler.instance.DisplayScreenTextLoop("WAITING"); + float c = 0f; + while (waitingForOtherPlayer) + { + c += Time.unscaledDeltaTime; + if (c > 10f) + { + DoRestart(); + yield break; + } + yield return null; + } + } + yield return null; + UIHandler.instance.StopScreenTextLoop(); + PlayerManager.instance.ResetCharacters(); + ResetMatch(); + StartCoroutine(DoStartGame()); + waitingForOtherPlayer = true; + } + + private void ResetMatch() + { + p1Points = 0; + p1Rounds = 0; + p2Points = 0; + p2Rounds = 0; + isTransitioning = false; + waitingForOtherPlayer = false; + UIHandler.instance.ShowRoundCounterSmall(p1Rounds, p2Rounds, p1Points, p2Points); + CardBarHandler.instance.ResetCardBards(); + PointVisualizer.instance.ResetPoints(); + } + + private void GameOverContinue(int winningTeamID) + { + UIHandler.instance.DisplayScreenTextLoop(PlayerManager.instance.GetColorFromTeam(winningTeamID).winText, "CONTINUE?"); + UIHandler.instance.DisplayYesNoLoop(PlayerManager.instance.GetFirstPlayerInTeam(winningTeamID), GetContinueYesNo); + MapManager.instance.LoadNextLevel(); + } + + private void GetContinueYesNo(PopUpHandler.YesNo yesNo) + { + if (yesNo == PopUpHandler.YesNo.Yes) + { + DoContinue(); + } + else + { + DoRestart(); + } + } + + private void DoContinue() + { + UIHandler.instance.StopScreenTextLoop(); + roundsToWinGame += 2; + UIHandler.instance.SetNumberOfRounds(roundsToWinGame); + RoundOver(currentWinningTeamID, PlayerManager.instance.GetOtherTeam(currentWinningTeamID)); + } + + private void DoRestart() + { + GameManager.instance.battleOngoing = false; + if (PhotonNetwork.OfflineMode) + { + Application.LoadLevel(Application.loadedLevel); + } + else + { + NetworkConnectionHandler.instance.NetworkRestart(); + } + } + + private void GameOver(int winningTeamID) + { + currentWinningTeamID = winningTeamID; + StartCoroutine(GameOverTransition(winningTeamID)); + } + + public void PlayerDied(Player killedPlayer, int playersAlive) + { + if (!PhotonNetwork.OfflineMode) + { + Debug.Log("PlayerDied: " + killedPlayer.data.view.Owner.NickName); + } + if (PlayerManager.instance.TeamsAlive() < 2) + { + TimeHandler.instance.DoSlowDown(); + if (PhotonNetwork.IsMasterClient) + { + view.RPC("RPCA_NextRound", RpcTarget.All, PlayerManager.instance.GetOtherTeam(PlayerManager.instance.GetLastTeamAlive()), PlayerManager.instance.GetLastTeamAlive(), p1Points, p2Points, p1Rounds, p2Rounds); + } + } + } + + [PunRPC] + public void RPCA_NextRound(int losingTeamID, int winningTeamID, int p1PointsSet, int p2PointsSet, int p1RoundsSet, int p2RoundsSet) + { + if (isTransitioning) + { + return; + } + GameManager.instance.battleOngoing = false; + p1Points = p1PointsSet; + p2Points = p2PointsSet; + p1Rounds = p1RoundsSet; + p2Rounds = p2RoundsSet; + Debug.Log("Winning team: " + winningTeamID); + Debug.Log("Losing team: " + losingTeamID); + isTransitioning = true; + GameManager.instance.GameOver(winningTeamID, losingTeamID); + PlayerManager.instance.SetPlayersSimulated(simulated: false); + switch (winningTeamID) + { + case 0: + p1Points++; + if (p1Points >= pointsToWinRound) + { + p1Rounds++; + if (p1Rounds >= roundsToWinGame) + { + Debug.Log("Game over, winning team: " + winningTeamID); + GameOver(winningTeamID); + pointOverAction(); + } + else + { + Debug.Log("Round over, winning team: " + winningTeamID); + RoundOver(winningTeamID, losingTeamID); + pointOverAction(); + } + } + else + { + Debug.Log("Point over, winning team: " + winningTeamID); + PointOver(winningTeamID); + pointOverAction(); + } + break; + case 1: + p2Points++; + if (p2Points >= pointsToWinRound) + { + p2Rounds++; + if (p2Rounds >= roundsToWinGame) + { + Debug.Log("Game over, winning team: " + winningTeamID); + GameOver(winningTeamID); + pointOverAction(); + } + else + { + Debug.Log("Round over, winning team: " + winningTeamID); + RoundOver(winningTeamID, losingTeamID); + pointOverAction(); + } + } + else + { + Debug.Log("Point over, winning team: " + winningTeamID); + PointOver(winningTeamID); + pointOverAction(); + } + break; + } + } +} diff --git a/ROUNDS/GM_Test.cs b/ROUNDS/GM_Test.cs new file mode 100644 index 0000000..b5d7ef6 --- /dev/null +++ b/ROUNDS/GM_Test.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections; +using UnityEngine; + +public class GM_Test : MonoBehaviour +{ + public bool testMap; + + public static GM_Test instance; + + private void Awake() + { + instance = this; + if (base.gameObject.activeSelf && !Application.isEditor) + { + testMap = false; + } + } + + private void Start() + { + if (testMap) + { + base.transform.root.GetComponent<SetOfflineMode>().SetOffline(); + } + if (testMap) + { + MapManager.instance.isTestingMap = true; + } + if (base.gameObject.activeSelf) + { + if (!testMap) + { + MapManager.instance.LoadNextLevel(callInImidetly: true, forceLoad: true); + } + else + { + MapManager.instance.currentMap = new MapWrapper(UnityEngine.Object.FindObjectOfType<Map>(), UnityEngine.Object.FindObjectOfType<Map>().gameObject.scene); + ArtHandler.instance.NextArt(); + } + PlayerAssigner.instance.SetPlayersCanJoin(canJoin: true); + TimeHandler.instance.StartGame(); + PlayerManager playerManager = PlayerManager.instance; + playerManager.PlayerJoinedAction = (Action<Player>)Delegate.Combine(playerManager.PlayerJoinedAction, new Action<Player>(PlayerWasAdded)); + PlayerManager.instance.AddPlayerDiedAction(PlayerDied); + GameManager.instance.isPlaying = true; + GameManager.instance.battleOngoing = true; + } + } + + private void PlayerWasAdded(Player player) + { + PlayerManager.instance.SetPlayersSimulated(simulated: true); + player.data.GetComponent<PlayerCollision>().IgnoreWallForFrames(2); + player.transform.position = MapManager.instance.currentMap.Map.GetRandomSpawnPos(); + PlayerManager.instance.SetPlayersSimulated(simulated: true); + PlayerManager.instance.SetPlayersPlaying(playing: true); + } + + private void PlayerDied(Player player, int unused) + { + StartCoroutine(DelayRevive(player)); + } + + private IEnumerator DelayRevive(Player player) + { + yield return new WaitForSecondsRealtime(2.5f); + PlayerWasAdded(player); + player.data.healthHandler.Revive(); + } +} diff --git a/ROUNDS/GameAnalytics.cs b/ROUNDS/GameAnalytics.cs new file mode 100644 index 0000000..4451ccb --- /dev/null +++ b/ROUNDS/GameAnalytics.cs @@ -0,0 +1,17 @@ +using UnityEngine; +using UnityEngine.Analytics; + +public class GameAnalytics : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.P)) + { + Analytics.SendEvent("PlayerKills", 5); + } + } +} diff --git a/ROUNDS/GameCrownHandler.cs b/ROUNDS/GameCrownHandler.cs new file mode 100644 index 0000000..8e555d5 --- /dev/null +++ b/ROUNDS/GameCrownHandler.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections; +using UnityEngine; + +public class GameCrownHandler : MonoBehaviour +{ + private float crownPos; + + public AnimationCurve transitionCurve; + + private GM_ArmsRace gm; + + private int currentCrownHolder = -1; + + private void Start() + { + gm = GetComponentInParent<GM_ArmsRace>(); + GM_ArmsRace gM_ArmsRace = gm; + gM_ArmsRace.pointOverAction = (Action)Delegate.Combine(gM_ArmsRace.pointOverAction, new Action(PointOver)); + } + + public void PointOver() + { + int num = -1; + int num2 = -1; + if (gm.p1Rounds > gm.p2Rounds) + { + num2 = 0; + } + if (gm.p1Rounds < gm.p2Rounds) + { + num2 = 1; + } + if (num2 == -1) + { + int num3 = -1; + if (gm.p1Points > gm.p2Points) + { + num3 = 0; + } + if (gm.p1Points < gm.p2Points) + { + num3 = 1; + } + if (num3 != -1) + { + num = num3; + } + } + else + { + num = num2; + } + if (num != -1 && num != currentCrownHolder) + { + if (currentCrownHolder == -1) + { + currentCrownHolder = num; + crownPos = currentCrownHolder; + GetComponent<CurveAnimation>().PlayIn(); + } + else + { + GiveCrownToPlayer(num); + } + } + } + + private void LateUpdate() + { + if (currentCrownHolder == -1) + { + return; + } + if (PlayerManager.instance.players[currentCrownHolder].gameObject.activeInHierarchy) + { + if (!base.transform.GetChild(0).gameObject.activeSelf) + { + base.transform.GetChild(0).gameObject.SetActive(value: true); + } + } + else if (base.transform.GetChild(0).gameObject.activeSelf) + { + base.transform.GetChild(0).gameObject.SetActive(value: false); + } + Vector3 position = Vector3.LerpUnclamped(PlayerManager.instance.players[0].data.GetCrownPos(), PlayerManager.instance.players[1].data.GetCrownPos(), crownPos); + base.transform.position = position; + } + + private void GiveCrownToPlayer(int playerID) + { + currentCrownHolder = playerID; + StartCoroutine(IGiveCrownToPlayer(playerID)); + } + + private IEnumerator IGiveCrownToPlayer(int playerID) + { + int fromInt; + int toInt; + if (playerID == 0) + { + fromInt = 1; + toInt = 0; + } + else + { + fromInt = 0; + toInt = 1; + } + for (float i = 0f; i < transitionCurve.keys[transitionCurve.keys.Length - 1].time; i += Time.unscaledDeltaTime) + { + crownPos = Mathf.LerpUnclamped(fromInt, toInt, transitionCurve.Evaluate(i)); + yield return null; + } + } +} diff --git a/ROUNDS/GameFeeler.cs b/ROUNDS/GameFeeler.cs new file mode 100644 index 0000000..7021a3e --- /dev/null +++ b/ROUNDS/GameFeeler.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public abstract class GameFeeler : MonoBehaviour +{ + private void Awake() + { + GamefeelManager.RegisterGamefeeler(this); + OnAwake(); + } + + public abstract void OnGameFeel(Vector2 feelDirection); + + public abstract void OnUIGameFeel(Vector2 feelDirection); + + public virtual void OnAwake() + { + } +} diff --git a/ROUNDS/GameManager.cs b/ROUNDS/GameManager.cs new file mode 100644 index 0000000..45aaeee --- /dev/null +++ b/ROUNDS/GameManager.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +public class GameManager : MonoBehaviour +{ + [Header("Settings")] + public static bool lockInput; + + public static GameManager instance; + + public bool isPlaying; + + public bool battleOngoing; + + public Action<int, int> GameOverAction; + + public void Awake() + { + instance = this; + } + + private void Start() + { + lockInput = false; + } + + private void Update() + { + } + + public void GameOver(int winingTeamID, int killedTeamID) + { + if (GameOverAction != null) + { + GameOverAction(winingTeamID, killedTeamID); + } + } +} diff --git a/ROUNDS/GamefeelManager.cs b/ROUNDS/GamefeelManager.cs new file mode 100644 index 0000000..ac99a47 --- /dev/null +++ b/ROUNDS/GamefeelManager.cs @@ -0,0 +1,60 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class GamefeelManager : MonoBehaviour +{ + public static GamefeelManager instance; + + private List<GameFeeler> m_GameFeelers = new List<GameFeeler>(); + + private void Awake() + { + instance = this; + } + + public static void RegisterGamefeeler(GameFeeler gameFeeler) + { + instance.m_GameFeelers.Add(gameFeeler); + } + + public void AddUIGameFeel(Vector2 directionForce) + { + for (int i = 0; i < instance.m_GameFeelers.Count; i++) + { + instance.m_GameFeelers[i].OnUIGameFeel(directionForce); + } + } + + public void AddGameFeel(Vector2 directionForce) + { + for (int i = 0; i < instance.m_GameFeelers.Count; i++) + { + instance.m_GameFeelers[i].OnGameFeel(directionForce); + } + } + + public static void GameFeel(Vector2 directionForce) + { + for (int i = 0; i < instance.m_GameFeelers.Count; i++) + { + instance.m_GameFeelers[i].OnGameFeel(directionForce); + } + } + + public void AddUIGameFeelOverTime(float amount, float time) + { + StartCoroutine(DoUIGameFeelOverTime(amount, time)); + } + + private IEnumerator DoUIGameFeelOverTime(float amount, float time) + { + float startTime = time; + while (time > 0f) + { + instance.AddUIGameFeel(amount * (Vector2)Random.onUnitSphere * Time.unscaledDeltaTime * (time / startTime)); + time -= Time.unscaledDeltaTime; + yield return null; + } + } +} diff --git a/ROUNDS/GeneralInput.cs b/ROUNDS/GeneralInput.cs new file mode 100644 index 0000000..0487def --- /dev/null +++ b/ROUNDS/GeneralInput.cs @@ -0,0 +1,274 @@ +using System.Collections; +using UnityEngine; + +public class GeneralInput : MonoBehaviour +{ + public enum InputType + { + Controller, + Keyboard, + Either + } + + public enum StickDirection + { + Left, + Right, + None + } + + public bool controlledElseWhere; + + public bool stunnedInput; + + public bool silencedInput; + + public KeyCode left; + + public KeyCode right; + + public KeyCode up; + + public KeyCode down; + + public KeyCode jump; + + public KeyCode shoot; + + public KeyCode shield; + + public Vector3 direction; + + public Vector3 latestPressedDirection; + + public Vector3 aimDirection; + + public Vector3 lastAimDirection; + + public bool jumpWasPressed; + + public bool jumpIsPressed; + + public bool shootWasPressed; + + public bool shootIsPressed; + + public bool shootWasReleased; + + public bool shieldWasPressed; + + public bool acceptWasPressed; + + public InputType inputType; + + private StickDirection lastStickDirection; + + public StickDirection stickPressDir = StickDirection.None; + + private CharacterData data; + + private int snapNumber = 16; + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + public void ResetInput() + { + direction = Vector3.zero; + aimDirection = Vector3.zero; + jumpIsPressed = false; + jumpWasPressed = false; + shootIsPressed = false; + shootWasPressed = false; + shootWasReleased = false; + shieldWasPressed = false; + acceptWasPressed = false; + } + + private void Update() + { + if (controlledElseWhere) + { + return; + } + ResetInput(); + DoUIInput(); + if (GameManager.lockInput || stunnedInput || !data.isPlaying || data.playerActions == null) + { + return; + } + direction += (Vector3)data.playerActions.Move; + direction = MakeEightDirections(direction); + if (direction != Vector3.zero) + { + latestPressedDirection = direction; + } + if (data.playerActions.Device == null) + { + aimDirection = MainCam.instance.cam.ScreenToWorldPoint(Input.mousePosition) - base.transform.position; + aimDirection.z = 0f; + aimDirection.Normalize(); + if (Optionshandler.lockMouse) + { + aimDirection = MakeEightDirections(aimDirection); + } + } + else + { + aimDirection.x += data.playerActions.Aim.X; + aimDirection.y += data.playerActions.Aim.Y; + if (Optionshandler.lockStick) + { + aimDirection = MakeEightDirections(aimDirection); + } + } + if (aimDirection != Vector3.zero) + { + aimDirection += Vector3.up * 0.13f / Mathf.Clamp(data.weaponHandler.gun.projectileSpeed, 1f, 100f); + } + if (aimDirection != Vector3.zero) + { + lastAimDirection = aimDirection; + } + if (data.playerActions.Jump.IsPressed) + { + jumpIsPressed = true; + } + if (data.playerActions.Jump.WasPressed) + { + jumpWasPressed = true; + } + if (!silencedInput) + { + if (data.playerActions.Fire.IsPressed) + { + shootIsPressed = true; + } + if (data.playerActions.Fire.WasPressed) + { + shootWasPressed = true; + } + if (data.playerActions.Fire.WasReleased) + { + shootWasReleased = true; + } + if (data.playerActions.Block.WasPressed) + { + shieldWasPressed = true; + } + } + } + + private void DoUIInput() + { + StickDirection stickDirection = StickDirection.None; + if (data.playerActions.Move.X > 0.7f) + { + stickDirection = StickDirection.Right; + } + if (data.playerActions.Move.X < -0.7f) + { + stickDirection = StickDirection.Left; + } + if (stickDirection != lastStickDirection) + { + stickPressDir = stickDirection; + lastStickDirection = stickDirection; + } + else + { + stickPressDir = StickDirection.None; + } + if (data.playerActions.Jump.WasPressed) + { + acceptWasPressed = true; + } + } + + public void DoStun(float stun) + { + if (base.gameObject.activeSelf) + { + StartCoroutine(Stun(stun)); + } + } + + private IEnumerator Stun(float stun) + { + base.enabled = false; + ResetInput(); + yield return new WaitForSeconds(stun); + base.enabled = true; + } + + public void SetState(Vector3 pos, bool isGrounded) + { + base.transform.position = pos; + } + + public void Move(bool right, bool left, bool up, bool down, bool jump) + { + ResetInput(); + if (left) + { + direction += Vector3.left; + } + if (right) + { + direction += Vector3.right; + } + if (up) + { + direction += Vector3.up; + } + if (down) + { + direction += Vector3.down; + } + if (jump) + { + jumpWasPressed = true; + } + Debug.Log("Move: Right: " + right + " Left: " + left + " Jump: " + jump); + if (Input.GetKey(shoot)) + { + shootIsPressed = true; + } + if (Input.GetKeyDown(shoot)) + { + shootWasPressed = true; + } + if (Input.GetKeyUp(shoot)) + { + shootWasReleased = true; + } + } + + private Vector3 MakeEightDirections(Vector3 dir) + { + _ = Vector3.zero; + float num = 360f / (float)snapNumber; + Vector3 vector = Vector3.up; + Vector3 vector2 = vector; + float num2 = 999f; + Vector3 result = dir; + for (int i = 0; i < snapNumber; i++) + { + vector2 = Quaternion.Euler(Vector3.forward * num * i) * vector; + float num3 = Vector3.Angle(dir, vector2); + if (num3 < num2) + { + num2 = num3; + result = vector2; + } + } + if (dir == Vector3.zero) + { + return Vector3.zero; + } + dir = dir.normalized; + return result; + } +} diff --git a/ROUNDS/GeneralParticleSystem.cs b/ROUNDS/GeneralParticleSystem.cs new file mode 100644 index 0000000..8f3203a --- /dev/null +++ b/ROUNDS/GeneralParticleSystem.cs @@ -0,0 +1,304 @@ +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; + +public class GeneralParticleSystem : MonoBehaviour +{ + public GameObject particleObject; + + public bool useTimeScale; + + private ObjectPool particlePool; + + [FoldoutGroup("Spawn settings", 0)] + public float randomXPos; + + [FoldoutGroup("Spawn settings", 0)] + public float randomYPos; + + [FoldoutGroup("Spawn settings", 0)] + public float rate = 10f; + + [FoldoutGroup("Spawn settings", 0)] + public bool playOnAwake = true; + + [FoldoutGroup("Spawn settings", 0)] + public bool playOnEnablee; + + [FoldoutGroup("Spawn settings", 0)] + public bool loop; + + [FoldoutGroup("Spawn settings", 0)] + public float duration = 2f; + + [FoldoutGroup("Spawn settings", 0)] + public AnimationCurve sizeMultiplierOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + public AnimationCurve emissionMultiplierOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + public ObjectParticle particleSettings; + + [FoldoutGroup("Global settings", 0)] + public float simulationSpeed = 1f; + + [HideInInspector] + public float simulationSpeedMultiplier = 1f; + + [FoldoutGroup("Global settings", 0)] + public float saturationMultiplier = 1f; + + [FoldoutGroup("Events", 0)] + public UnityEvent startEvent; + + [FoldoutGroup("Events", 0)] + public float startEventDelay; + + [FoldoutGroup("Events", 0)] + public UnityEvent endEvent; + + [FoldoutGroup("Events", 0)] + public float endEventDelay; + + private float sizeOverTimeAnimationCurveLength; + + private float sizeMultiplierOverTimeAnimationCurveLength; + + private float alphaOverTimeAnimationCurveLength; + + private float emissionOverTimeAnimationCurveLength; + + private bool inited; + + private Coroutine emissionLoop; + + private float lastEmissionTime; + + private bool isPlaying; + + private void OnEnable() + { + isPlaying = false; + if (playOnEnablee) + { + Play(); + } + } + + private void Start() + { + if (playOnAwake) + { + Play(); + } + Mask component = base.transform.parent.GetComponent<Mask>(); + if ((bool)component) + { + component.showMaskGraphic = false; + } + } + + private void Init() + { + if (!inited) + { + inited = true; + if (particleSettings.sizeOverTime.keys.Length > 1) + { + sizeOverTimeAnimationCurveLength = particleSettings.sizeOverTime.keys[particleSettings.sizeOverTime.keys.Length - 1].time - particleSettings.sizeOverTime.keys[0].time; + } + if (particleSettings.alphaOverTime.keys.Length > 1) + { + alphaOverTimeAnimationCurveLength = particleSettings.alphaOverTime.keys[particleSettings.alphaOverTime.keys.Length - 1].time - particleSettings.alphaOverTime.keys[0].time; + } + if (sizeMultiplierOverTime.keys.Length > 1) + { + sizeMultiplierOverTimeAnimationCurveLength = sizeMultiplierOverTime.keys[sizeMultiplierOverTime.keys.Length - 1].time - sizeMultiplierOverTime.keys[0].time; + } + if (emissionMultiplierOverTime.keys.Length > 1) + { + emissionOverTimeAnimationCurveLength = emissionMultiplierOverTime.keys[emissionMultiplierOverTime.keys.Length - 1].time - emissionMultiplierOverTime.keys[0].time; + } + particleObject.SetActive(value: false); + particlePool = new ObjectPool(particleObject, 100, base.transform); + } + } + + public void StartLooping() + { + loop = true; + Play(); + } + + public void EndLooping() + { + loop = false; + if (emissionLoop != null) + { + StopCoroutine(emissionLoop); + } + } + + [Button] + public void Play() + { + Init(); + if (!isPlaying) + { + emissionLoop = StartCoroutine(DoPlay()); + } + } + + private void OnDisable() + { + Stop(); + } + + public void Stop() + { + isPlaying = false; + DisableAllParticles(); + if (emissionLoop != null) + { + StopCoroutine(emissionLoop); + } + } + + private void DisableAllParticles() + { + if (base.transform.childCount > 0) + { + for (int i = 0; i < base.transform.GetChild(0).childCount; i++) + { + base.transform.GetChild(0).GetChild(i).gameObject.SetActive(value: false); + } + } + } + + private IEnumerator DoPlay() + { + isPlaying = true; + if (startEvent != null) + { + if (startEventDelay != 0f) + { + StartCoroutine(DelayEvent(startEvent, startEventDelay)); + } + else + { + startEvent.Invoke(); + } + } + float counter = 0f; + while (counter < duration) + { + CheckIfShouldEmit(counter / duration); + counter += (useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime) * (simulationSpeed * simulationSpeedMultiplier); + yield return null; + } + isPlaying = false; + if (loop) + { + Play(); + } + else if (endEvent != null) + { + if (endEventDelay != 0f) + { + StartCoroutine(DelayEvent(endEvent, endEventDelay)); + } + else + { + endEvent.Invoke(); + } + } + } + + private void CheckIfShouldEmit(float currentAnimationTime) + { + if ((useTimeScale ? Time.time : Time.unscaledTime) > lastEmissionTime + 1f / rate / (simulationSpeed * simulationSpeedMultiplier) / emissionMultiplierOverTime.Evaluate(currentAnimationTime * emissionOverTimeAnimationCurveLength) * Time.timeScale) + { + StartCoroutine(DoPlarticleLife(currentAnimationTime)); + lastEmissionTime = Time.time; + } + } + + private IEnumerator DoPlarticleLife(float currentAnimationTime) + { + GameObject spawned = particlePool.GetObject(); + float counter = 0f; + float t = particleSettings.lifetime; + Vector3 startSize = spawned.transform.localScale; + Vector3 modifiedStartSize = spawned.transform.localScale * particleSettings.size * sizeMultiplierOverTime.Evaluate(currentAnimationTime * sizeMultiplierOverTimeAnimationCurveLength); + Image img = spawned.GetComponent<Image>(); + Color startColor = Color.magenta; + if ((bool)img) + { + startColor = img.color; + } + if ((bool)img) + { + float value = Random.value; + if (particleSettings.color != Color.magenta) + { + img.color = particleSettings.color; + } + if (particleSettings.randomColor != Color.magenta) + { + img.color = Color.Lerp(img.color, particleSettings.randomColor, value); + } + if (!particleSettings.singleRandomValueColor) + { + value = Random.value; + } + if (particleSettings.randomAddedColor != Color.black) + { + img.color += Color.Lerp(Color.black, particleSettings.randomAddedColor, value); + } + if (!particleSettings.singleRandomValueColor) + { + value = Random.value; + } + if (particleSettings.randomAddedSaturation != 0f || saturationMultiplier != 1f) + { + Color.RGBToHSV(img.color, out var H, out var S, out var V); + S += value * particleSettings.randomAddedSaturation; + S *= saturationMultiplier; + img.color = Color.HSVToRGB(H, S, V); + } + } + spawned.transform.Rotate(base.transform.forward * particleSettings.rotation); + spawned.transform.Rotate(base.transform.forward * Random.Range(0f - particleSettings.randomRotation, particleSettings.randomRotation)); + spawned.transform.localPosition = Vector3.zero; + spawned.transform.position += base.transform.up * Random.Range(0f - randomYPos, randomYPos); + spawned.transform.position += base.transform.right * Random.Range(0f - randomXPos, randomXPos); + spawned.transform.position += base.transform.forward * Random.Range(-0.1f, 0.1f); + while (counter < t) + { + if (particleSettings.sizeOverTime.keys.Length > 1) + { + spawned.transform.localScale = modifiedStartSize * particleSettings.sizeOverTime.Evaluate(counter / t * sizeOverTimeAnimationCurveLength); + } + float num = particleSettings.alphaOverTime.Evaluate(counter / t * alphaOverTimeAnimationCurveLength); + if ((bool)img && img.color.a != num) + { + img.color = new Color(img.color.r, img.color.g, img.color.b, num); + } + counter += (useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime) * (simulationSpeed * simulationSpeedMultiplier); + yield return null; + } + if ((bool)img) + { + img.color = startColor; + } + spawned.transform.localScale = startSize; + particlePool.ReleaseObject(spawned); + } + + private IEnumerator DelayEvent(UnityEvent e, float t) + { + yield return new WaitForSeconds(t); + e?.Invoke(); + } +} diff --git a/ROUNDS/GeneralShooter.cs b/ROUNDS/GeneralShooter.cs new file mode 100644 index 0000000..3d39423 --- /dev/null +++ b/ROUNDS/GeneralShooter.cs @@ -0,0 +1,43 @@ +using System.Collections; +using UnityEngine; + +public class GeneralShooter : MonoBehaviour +{ + private Gun gun; + + [HideInInspector] + public float charge; + + public Transform[] shooters; + + private void Start() + { + gun = GetComponent<Gun>(); + } + + public void Attack() + { + if (base.enabled) + { + StartCoroutine(DoAttack()); + } + } + + private IEnumerator DoAttack() + { + int shotsToMake = Mathf.Clamp(Mathf.RoundToInt(0.5f / gun.attackSpeed), 1, 5); + for (int i = 0; i < shotsToMake; i++) + { + for (int j = 0; j < shooters.Length; j++) + { + gun.transform.position = shooters[j].position; + gun.transform.rotation = shooters[j].rotation; + gun.Attack(gun.currentCharge, forceAttack: true); + } + if (shotsToMake > i) + { + yield return new WaitForSeconds(0.1f); + } + } + } +} diff --git a/ROUNDS/GetColor.cs b/ROUNDS/GetColor.cs new file mode 100644 index 0000000..89dad00 --- /dev/null +++ b/ROUNDS/GetColor.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class GetColor : MonoBehaviour +{ + public ColorHandler.ColorType colorType; + + private bool inited; + + public void Start() + { + if (!inited) + { + inited = true; + SpriteRenderer component = GetComponent<SpriteRenderer>(); + if ((bool)component) + { + component.color = ColorHandler.instance.GetColor(colorType); + } + } + } +} diff --git a/ROUNDS/GetControllerButton.cs b/ROUNDS/GetControllerButton.cs new file mode 100644 index 0000000..bcb331e --- /dev/null +++ b/ROUNDS/GetControllerButton.cs @@ -0,0 +1,3 @@ +public class GetControllerButton +{ +} diff --git a/ROUNDS/GifCam.cs b/ROUNDS/GifCam.cs new file mode 100644 index 0000000..d7152c4 --- /dev/null +++ b/ROUNDS/GifCam.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class GifCam : MonoBehaviour +{ + public static bool isGifCam; + + private Camera[] cameras; + + private Vector3 camStartPos; + + private float cameraStartSize; + + private bool follow = true; + + private void Start() + { + cameras = GetComponentsInChildren<Camera>(); + camStartPos = cameras[0].transform.position; + cameraStartSize = cameras[0].orthographicSize; + } + + private void Update() + { + } +} diff --git a/ROUNDS/GoBack.cs b/ROUNDS/GoBack.cs new file mode 100644 index 0000000..2853d6d --- /dev/null +++ b/ROUNDS/GoBack.cs @@ -0,0 +1,31 @@ +using InControl; +using UnityEngine; +using UnityEngine.Events; + +public class GoBack : MonoBehaviour +{ + public UnityEvent goBackEvent; + + public ListMenuPage target; + + private void Start() + { + } + + private void Update() + { + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].Action2.WasPressed) + { + goBackEvent.Invoke(); + target.Open(); + } + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + goBackEvent.Invoke(); + target.Open(); + } + } +} diff --git a/ROUNDS/Grass.cs b/ROUNDS/Grass.cs new file mode 100644 index 0000000..0557f48 --- /dev/null +++ b/ROUNDS/Grass.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +public class Grass : MonoBehaviour +{ + public float target; + + private float velocity; + + private float currentRot; + + public float minSpring; + + public float maxSpring; + + public float minDrag; + + public float maxDrag; + + private float spring; + + private float drag; + + public float minPlayerEffect; + + public float maxPlayerEffect; + + private float playerEffect; + + public Sprite[] sprites; + + private void Start() + { + if (Random.value > 0.5f) + { + Object.Destroy(base.gameObject); + return; + } + GetComponentInChildren<SpriteRenderer>().sprite = sprites[Random.Range(0, sprites.Length)]; + spring = Random.Range(minSpring, maxSpring); + drag = Random.Range(minDrag, maxDrag); + playerEffect = Random.Range(minPlayerEffect, maxPlayerEffect); + currentRot = base.transform.localEulerAngles.z; + } + + private void Update() + { + velocity = Mathf.Lerp(velocity, (target - currentRot) * spring, CappedDeltaTime.time * drag); + currentRot += velocity * CappedDeltaTime.time; + base.transform.localEulerAngles = new Vector3(0f, 0f, currentRot); + if (PlayerManager.instance.players != null && PlayerManager.instance.players.Count > 0 && Vector2.Distance(PlayerManager.instance.players[0].data.playerVel.position, base.transform.position) < 1.5f) + { + AddForce(PlayerManager.instance.players[0].data.playerVel.velocity.x * playerEffect * CappedDeltaTime.time * 60f); + } + float num = 0.5f; + float num2 = 0.05f; + AddForce((Mathf.PerlinNoise(base.transform.position.x * num2 + Time.time * num, base.transform.position.y * num2 + Time.time * num) - 0.5f) * 30f * playerEffect * CappedDeltaTime.time * 60f); + } + + public void AddForce(float f) + { + velocity += f; + } +} diff --git a/ROUNDS/Gravity.cs b/ROUNDS/Gravity.cs new file mode 100644 index 0000000..1d9cb83 --- /dev/null +++ b/ROUNDS/Gravity.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +public class Gravity : MonoBehaviour +{ + public float gravityForce; + + public float exponent = 1f; + + private PlayerVelocity rig; + + private CharacterData data; + + private void Start() + { + data = GetComponent<CharacterData>(); + rig = GetComponent<PlayerVelocity>(); + } + + private void FixedUpdate() + { + float num = data.sinceGrounded; + if (data.sinceWallGrab < num) + { + num = data.sinceWallGrab; + } + if (num > 0f) + { + rig.AddForce(Vector3.down * TimeHandler.timeScale * Mathf.Pow(num, exponent) * gravityForce * rig.mass, ForceMode2D.Force); + } + else + { + rig.AddForce(Vector3.down * TimeHandler.timeScale * num * gravityForce * rig.mass, ForceMode2D.Force); + } + } +} diff --git a/ROUNDS/GridBounceCircle.cs b/ROUNDS/GridBounceCircle.cs new file mode 100644 index 0000000..f0c6b53 --- /dev/null +++ b/ROUNDS/GridBounceCircle.cs @@ -0,0 +1,57 @@ +using System.Collections; +using UnityEngine; + +public class GridBounceCircle : GridObject +{ + private float m_startSize; + + private bool isBlooping; + + private float currentDistance; + + private void Start() + { + m_startSize = base.transform.localScale.x; + } + + public override void BopCall(float power) + { + if (!isBlooping || (isBlooping && power > currentDistance)) + { + StopAllCoroutines(); + StartCoroutine(Blop(power)); + } + } + + public override void OnSetSize(float size) + { + if (!isBlooping) + { + base.transform.localScale = Vector3.one * size * m_startSize; + } + } + + private IEnumerator Blop(float power) + { + isBlooping = true; + currentDistance = power; + float maxSize = Mathf.Lerp(1f * m_startSize, 3f * m_startSize, power); + float timer2 = 0f; + while (timer2 < 1f) + { + timer2 += TimeHandler.deltaTime * 10f; + base.transform.localScale = Vector3.one * Mathf.Lerp(m_startSize, maxSize, timer2); + yield return null; + } + yield return new WaitForSeconds(0.2f); + timer2 = 0f; + while (timer2 < 1f) + { + timer2 += TimeHandler.deltaTime * 6f; + base.transform.localScale = Vector3.one * Mathf.Lerp(maxSize, m_startSize, timer2); + yield return null; + } + base.transform.localScale = Vector3.one * m_startSize; + isBlooping = false; + } +} diff --git a/ROUNDS/GridLightBulb.cs b/ROUNDS/GridLightBulb.cs new file mode 100644 index 0000000..8fa2523 --- /dev/null +++ b/ROUNDS/GridLightBulb.cs @@ -0,0 +1,57 @@ +using System.Collections; +using UnityEngine; + +public class GridLightBulb : GridObject +{ + private SpriteRenderer rend; + + public Color maxLightColor; + + private Color baseColor; + + private bool isLitUp; + + private float currentDistance; + + private void Start() + { + rend = GetComponent<SpriteRenderer>(); + baseColor = rend.color; + } + + public override void BopCall(float distance) + { + distance = 1f - distance; + if (!isLitUp || (isLitUp && distance > currentDistance)) + { + StopAllCoroutines(); + StartCoroutine(LightUp(distance)); + } + } + + private IEnumerator LightUp(float distance) + { + isLitUp = true; + currentDistance = distance; + Color lightColor = Color.Lerp(maxLightColor, baseColor, distance); + rend.color = lightColor; + yield return new WaitForSeconds(Random.Range(0.5f, 2f)); + int blinks = Random.Range(0, 8); + bool isOn = true; + for (int i = 0; i < blinks; i++) + { + if (isOn) + { + rend.color = baseColor; + } + else + { + rend.color = lightColor; + } + isOn = !isOn; + yield return new WaitForSeconds(Random.Range(0.05f, 0.1f)); + } + rend.color = baseColor; + isLitUp = false; + } +} diff --git a/ROUNDS/GridObject.cs b/ROUNDS/GridObject.cs new file mode 100644 index 0000000..6b4fcdd --- /dev/null +++ b/ROUNDS/GridObject.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class GridObject : MonoBehaviour +{ + public virtual void BopCall(float power) + { + } + + public virtual void BulletCall(float distance) + { + distance = Mathf.Clamp(0f, 1f, distance); + BopCall(1f - distance); + } + + public virtual void OnPlayerKilled(float distance) + { + } + + public virtual void OnGameOverOver(float distance) + { + } + + public virtual void OnSetSize(float size) + { + } +} diff --git a/ROUNDS/GridVisualizer.cs b/ROUNDS/GridVisualizer.cs new file mode 100644 index 0000000..ed73bf2 --- /dev/null +++ b/ROUNDS/GridVisualizer.cs @@ -0,0 +1,56 @@ +using UnityEngine; + +public class GridVisualizer : MonoBehaviour +{ + public Vector2 min; + + public Vector2 max; + + public GameObject prefab; + + public Vector2Int numberOfObjects; + + internal GridObject[,] spawnedObjects; + + public static GridVisualizer instance; + + private void Start() + { + instance = this; + SpawnGrid(); + } + + public void BulletCall(Vector2 worldSpacePosition) + { + Vector2Int gridPos = WorldToGridSpace(worldSpacePosition); + float power = Vector2.Distance(worldSpacePosition, GridToWorldSpace(gridPos)); + spawnedObjects[gridPos.x, gridPos.y].BopCall(power); + } + + public Vector2 GridToWorldSpace(int x, int y) + { + return GridToWorldSpace(new Vector2Int(x, y)); + } + + public Vector2 GridToWorldSpace(Vector2Int gridPos) + { + return new Vector2(Mathf.Lerp(min.x, max.x, (float)gridPos.x / (float)numberOfObjects.x), Mathf.Lerp(min.y, max.y, (float)gridPos.y / (float)numberOfObjects.y)); + } + + public Vector2Int WorldToGridSpace(Vector2 pos) + { + return new Vector2Int((int)(Mathf.InverseLerp(min.x, max.x, pos.x) * (float)numberOfObjects.x), (int)(Mathf.InverseLerp(min.y, max.y, pos.y) * (float)numberOfObjects.y)); + } + + private void SpawnGrid() + { + spawnedObjects = new GridObject[numberOfObjects.x, numberOfObjects.y]; + for (int i = 0; i < numberOfObjects.x; i++) + { + for (int j = 0; j < numberOfObjects.y; j++) + { + spawnedObjects[i, j] = Object.Instantiate(prefab, GridToWorldSpace(i, j), Quaternion.identity).GetComponent<GridObject>(); + } + } + } +} diff --git a/ROUNDS/Gun.cs b/ROUNDS/Gun.cs new file mode 100644 index 0000000..36e8df2 --- /dev/null +++ b/ROUNDS/Gun.cs @@ -0,0 +1,698 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sirenix.OdinInspector; +using SoundImplementation; +using UnityEngine; + +public class Gun : Weapon +{ + [Header("Sound Player Settings")] + public SoundGun soundGun = new SoundGun(); + + [Header("Sound Card Settings")] + public SoundShotModifier soundShotModifier; + + public SoundImpactModifier soundImpactModifier; + + public bool soundDisableRayHitBulletSound; + + [Header("Settings")] + public float recoil; + + public float bodyRecoil; + + public float shake; + + public bool forceSpecificShake; + + public ProjectilesToSpawn[] projectiles; + + private Rigidbody2D rig; + + public Transform shootPosition; + + [HideInInspector] + public Player player; + + [HideInInspector] + public bool isReloading; + + [Header("Multiply")] + [FoldoutGroup("Stats", 0)] + public float damage = 1f; + + [FoldoutGroup("Stats", 0)] + public float reloadTime = 1f; + + [FoldoutGroup("Stats", 0)] + public float reloadTimeAdd; + + [FoldoutGroup("Stats", 0)] + public float recoilMuiltiplier = 1f; + + [FoldoutGroup("Stats", 0)] + public float knockback = 1f; + + [FoldoutGroup("Stats", 0)] + public float attackSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float projectileSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float projectielSimulatonSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float gravity = 1f; + + [FoldoutGroup("Stats", 0)] + public float damageAfterDistanceMultiplier = 1f; + + [FoldoutGroup("Stats", 0)] + public float bulletDamageMultiplier = 1f; + + [FoldoutGroup("Stats", 0)] + public float multiplySpread = 1f; + + [FoldoutGroup("Stats", 0)] + public float shakeM = 1f; + + [Header("Add")] + [FoldoutGroup("Stats", 0)] + public int ammo; + + [FoldoutGroup("Stats", 0)] + public float ammoReg; + + [FoldoutGroup("Stats", 0)] + public float size; + + [FoldoutGroup("Stats", 0)] + public float overheatMultiplier; + + [FoldoutGroup("Stats", 0)] + public float timeToReachFullMovementMultiplier; + + [FoldoutGroup("Stats", 0)] + public int numberOfProjectiles; + + [FoldoutGroup("Stats", 0)] + public int bursts; + + [FoldoutGroup("Stats", 0)] + public int reflects; + + [FoldoutGroup("Stats", 0)] + public int smartBounce; + + [FoldoutGroup("Stats", 0)] + public int bulletPortal; + + [FoldoutGroup("Stats", 0)] + public int randomBounces; + + [FoldoutGroup("Stats", 0)] + public float timeBetweenBullets; + + [FoldoutGroup("Stats", 0)] + public float projectileSize; + + [FoldoutGroup("Stats", 0)] + public float speedMOnBounce = 1f; + + [FoldoutGroup("Stats", 0)] + public float dmgMOnBounce = 1f; + + [FoldoutGroup("Stats", 0)] + public float drag; + + [FoldoutGroup("Stats", 0)] + public float dragMinSpeed = 1f; + + [FoldoutGroup("Stats", 0)] + public float spread; + + [FoldoutGroup("Stats", 0)] + public float evenSpread; + + [FoldoutGroup("Stats", 0)] + public float percentageDamage; + + [FoldoutGroup("Stats", 0)] + public float cos; + + [FoldoutGroup("Stats", 0)] + public float slow; + + [FoldoutGroup("Stats", 0)] + [Header("Charge Multiply")] + public float chargeDamageMultiplier = 1f; + + [FoldoutGroup("Stats", 0)] + [Header("(1 + Charge * x) Multiply")] + public float chargeSpreadTo; + + [FoldoutGroup("Stats", 0)] + public float chargeEvenSpreadTo; + + [FoldoutGroup("Stats", 0)] + public float chargeSpeedTo; + + [FoldoutGroup("Stats", 0)] + public float chargeRecoilTo; + + [FoldoutGroup("Stats", 0)] + [Header("(1 + Charge * x) Add")] + public float chargeNumberOfProjectilesTo; + + [FoldoutGroup("Stats", 0)] + [Header("Special")] + public float destroyBulletAfter; + + [FoldoutGroup("Stats", 0)] + public float forceSpecificAttackSpeed; + + [FoldoutGroup("Stats", 0)] + public bool lockGunToDefault; + + [FoldoutGroup("Stats", 0)] + public bool unblockable; + + [FoldoutGroup("Stats", 0)] + public bool ignoreWalls; + + [HideInInspector] + public float currentCharge; + + public bool useCharge; + + public bool dontAllowAutoFire; + + public ObjectsToSpawn[] objectsToSpawn; + + public Color projectileColor = Color.black; + + public bool waveMovement; + + public bool teleport; + + public bool spawnSkelletonSquare; + + public float explodeNearEnemyRange; + + public float explodeNearEnemyDamage; + + public float hitMovementMultiplier = 1f; + + private Action attackAction; + + [HideInInspector] + public bool isProjectileGun; + + [HideInInspector] + public float defaultCooldown = 1f; + + [HideInInspector] + public int attackID = -1; + + public float attackSpeedMultiplier = 1f; + + private int gunID = -1; + + private GunAmmo gunAmmo; + + private Vector3 spawnPos; + + public Action<GameObject> ShootPojectileAction; + + private float spreadOfLastBullet; + + private SpawnedAttack spawnedAttack; + + [HideInInspector] + internal Vector3 forceShootDir; + + private float usedCooldown + { + get + { + if (!lockGunToDefault) + { + return attackSpeed; + } + return defaultCooldown; + } + } + + internal float GetRangeCompensation(float distance) + { + return Mathf.Pow(distance, 2f) * 0.015f / projectileSpeed; + } + + internal void ResetStats() + { + isReloading = false; + damage = 1f; + reloadTime = 1f; + reloadTimeAdd = 0f; + recoilMuiltiplier = 1f; + gunAmmo.reloadTimeMultiplier = 1f; + gunAmmo.reloadTimeAdd = 0f; + knockback = 1f; + attackSpeed = 0.3f; + projectileSpeed = 1f; + projectielSimulatonSpeed = 1f; + gravity = 1f; + damageAfterDistanceMultiplier = 1f; + bulletDamageMultiplier = 1f; + multiplySpread = 1f; + shakeM = 1f; + ammo = 0; + ammoReg = 0f; + size = 0f; + overheatMultiplier = 0f; + timeToReachFullMovementMultiplier = 0f; + numberOfProjectiles = 1; + bursts = 0; + reflects = 0; + smartBounce = 0; + bulletPortal = 0; + randomBounces = 0; + timeBetweenBullets = 0f; + projectileSize = 0f; + speedMOnBounce = 1f; + dmgMOnBounce = 1f; + drag = 0f; + dragMinSpeed = 1f; + spread = 0f; + evenSpread = 0f; + percentageDamage = 0f; + cos = 0f; + slow = 0f; + chargeNumberOfProjectilesTo = 0f; + destroyBulletAfter = 0f; + forceSpecificAttackSpeed = 0f; + lockGunToDefault = false; + unblockable = false; + ignoreWalls = false; + currentCharge = 0f; + useCharge = false; + waveMovement = false; + teleport = false; + spawnSkelletonSquare = false; + explodeNearEnemyRange = 0f; + explodeNearEnemyDamage = 0f; + hitMovementMultiplier = 1f; + isProjectileGun = false; + defaultCooldown = 1f; + attackSpeedMultiplier = 1f; + objectsToSpawn = new ObjectsToSpawn[0]; + GetComponentInChildren<GunAmmo>().maxAmmo = 3; + GetComponentInChildren<GunAmmo>().ReDrawTotalBullets(); + projectileColor = Color.black; + } + + private void Start() + { + gunAmmo = GetComponentInChildren<GunAmmo>(); + Gun[] componentsInChildren = base.transform.root.GetComponentsInChildren<Gun>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i] == this) + { + gunID = i; + } + } + if (!player) + { + player = GetComponentInParent<Player>(); + } + if (!player) + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + if ((bool)componentInParent) + { + player = componentInParent.ownPlayer; + } + } + if (!player) + { + SpawnedAttack component = base.transform.root.GetComponent<SpawnedAttack>(); + if ((bool)component) + { + player = component.spawner; + } + } + holdable = GetComponent<Holdable>(); + defaultCooldown = usedCooldown; + ShootPos componentInChildren = GetComponentInChildren<ShootPos>(); + if ((bool)componentInChildren) + { + shootPosition = componentInChildren.transform; + } + else + { + shootPosition = base.transform; + } + rig = GetComponent<Rigidbody2D>(); + soundGun.SetGun(this); + soundGun.SetGunTransform(base.transform); + soundGun.RefreshSoundModifiers(); + } + + private void Update() + { + if ((bool)holdable && (bool)holdable.holder && (bool)holdable.holder.player) + { + player = holdable.holder.player; + } + sinceAttack += TimeHandler.deltaTime * attackSpeedMultiplier; + if (!GameManager.instance.battleOngoing || (player != null && (!player.data.isPlaying || player.data.dead))) + { + soundGun.StopAutoPlayTail(); + } + } + + private void OnDestroy() + { + soundGun.StopAutoPlayTail(); + } + + public bool IsReady(float readuIn = 0f) + { + return sinceAttack + readuIn * attackSpeedMultiplier > usedCooldown; + } + + public float ReadyAmount() + { + return sinceAttack / usedCooldown; + } + + public override bool Attack(float charge, bool forceAttack = false, float damageM = 1f, float recoilM = 1f, bool useAmmo = true) + { + if (sinceAttack < usedCooldown && !forceAttack) + { + return false; + } + if (isReloading && !forceAttack) + { + return false; + } + sinceAttack = 0f; + int attacks = Mathf.Clamp(Mathf.RoundToInt(0.5f * charge / attackSpeed), 1, 10); + if (lockGunToDefault) + { + attacks = 1; + } + StartCoroutine(DoAttacks(charge, forceAttack, damageM, attacks, recoilM, useAmmo)); + return true; + } + + private IEnumerator DoAttacks(float charge, bool forceAttack = false, float damageM = 1f, int attacks = 1, float recoilM = 1f, bool useAmmo = true) + { + for (int i = 0; i < attacks; i++) + { + DoAttack(charge, forceAttack, damageM, recoilM, useAmmo); + yield return new WaitForSeconds(0.3f / (float)attacks); + } + } + + private void DoAttack(float charge, bool forceAttack = false, float damageM = 1f, float recoilM = 1f, bool useAmmo = true) + { + float num = 1f * (1f + charge * chargeRecoilTo) * recoilM; + if ((bool)rig) + { + rig.AddForce(rig.mass * recoil * Mathf.Clamp(usedCooldown, 0f, 1f) * -base.transform.up, ForceMode2D.Impulse); + } + _ = (bool)holdable; + if (attackAction != null) + { + attackAction(); + } + StartCoroutine(FireBurst(charge, forceAttack, damageM, recoilM, useAmmo)); + } + + private bool CheckIsMine() + { + bool result = false; + if ((bool)holdable && (bool)holdable.holder) + { + result = holdable.holder.player.data.view.IsMine; + } + else + { + Player componentInParent = GetComponentInParent<Player>(); + if ((bool)componentInParent) + { + result = componentInParent.data.view.IsMine; + } + } + return result; + } + + private IEnumerator FireBurst(float charge, bool forceAttack = false, float damageM = 1f, float recoilM = 1f, bool useAmmo = true) + { + int currentNumberOfProjectiles = (lockGunToDefault ? 1 : (numberOfProjectiles + Mathf.RoundToInt(chargeNumberOfProjectilesTo * charge))); + if (!lockGunToDefault) + { + _ = currentNumberOfProjectiles; + } + if (timeBetweenBullets == 0f) + { + GamefeelManager.GameFeel(base.transform.up * shake); + soundGun.PlayShot(currentNumberOfProjectiles); + } + for (int ii = 0; ii < Mathf.Clamp(bursts, 1, 100); ii++) + { + for (int i = 0; i < projectiles.Length; i++) + { + for (int j = 0; j < currentNumberOfProjectiles; j++) + { + if (CheckIsMine()) + { + spawnPos = base.transform.position; + if ((bool)player) + { + player.GetComponent<PlayerAudioModifyers>().SetStacks(); + if ((bool)holdable) + { + spawnPos = player.transform.position; + } + } + GameObject gameObject = PhotonNetwork.Instantiate(projectiles[i].objectToSpawn.gameObject.name, spawnPos, getShootRotation(j, currentNumberOfProjectiles, charge), 0); + if ((bool)holdable) + { + if (useAmmo) + { + if (PhotonNetwork.OfflineMode) + { + gameObject.GetComponent<ProjectileInit>().OFFLINE_Init(holdable.holder.player.playerID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + else + { + gameObject.GetComponent<PhotonView>().RPC("RPCA_Init", RpcTarget.All, holdable.holder.view.OwnerActorNr, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + } + else if (PhotonNetwork.OfflineMode) + { + gameObject.GetComponent<ProjectileInit>().OFFLINE_Init_noAmmoUse(holdable.holder.player.playerID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + else + { + gameObject.GetComponent<PhotonView>().RPC("RPCA_Init_noAmmoUse", RpcTarget.All, holdable.holder.view.OwnerActorNr, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + } + else if (PhotonNetwork.OfflineMode) + { + gameObject.GetComponent<ProjectileInit>().OFFLINE_Init_SeparateGun(GetComponentInParent<Player>().playerID, gunID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + else + { + gameObject.GetComponent<PhotonView>().RPC("RPCA_Init_SeparateGun", RpcTarget.All, GetComponentInParent<CharacterData>().view.OwnerActorNr, gunID, currentNumberOfProjectiles, damageM, UnityEngine.Random.Range(0f, 1f)); + } + } + if (timeBetweenBullets != 0f) + { + GamefeelManager.GameFeel(base.transform.up * shake); + soundGun.PlayShot(currentNumberOfProjectiles); + } + } + } + if (bursts > 1 && ii + 1 == Mathf.Clamp(bursts, 1, 100)) + { + soundGun.StopAutoPlayTail(); + } + if (timeBetweenBullets > 0f) + { + yield return new WaitForSeconds(timeBetweenBullets); + } + } + } + + public void BulletInit(GameObject bullet, int usedNumberOfProjectiles, float damageM, float randomSeed, bool useAmmo = true) + { + spawnedAttack = bullet.GetComponent<SpawnedAttack>(); + if (!spawnedAttack) + { + spawnedAttack = bullet.AddComponent<SpawnedAttack>(); + } + if (!bullet.GetComponentInChildren<DontChangeMe>()) + { + ApplyProjectileStats(bullet, usedNumberOfProjectiles, damageM, randomSeed); + } + if (soundDisableRayHitBulletSound) + { + RayHitBulletSound component = bullet.GetComponent<RayHitBulletSound>(); + if (component != null) + { + component.disableImpact = true; + } + } + ApplyPlayerStuff(bullet); + if (ShootPojectileAction != null) + { + ShootPojectileAction(bullet); + } + if (useAmmo && (bool)gunAmmo) + { + gunAmmo.Shoot(bullet); + } + } + + private Quaternion getShootRotation(int bulletID, int numOfProj, float charge) + { + Vector3 forward = shootPosition.forward; + if (forceShootDir != Vector3.zero) + { + forward = forceShootDir; + } + float num = multiplySpread * Mathf.Clamp(1f + charge * chargeSpreadTo, 0f, float.PositiveInfinity); + float num2 = UnityEngine.Random.Range(0f - spread, spread); + num2 /= (1f + projectileSpeed * 0.5f) * 0.5f; + forward += Vector3.Cross(forward, Vector3.forward) * num2 * num; + return Quaternion.LookRotation(lockGunToDefault ? shootPosition.forward : forward); + } + + private void ApplyPlayerStuff(GameObject obj) + { + ProjectileHit component = obj.GetComponent<ProjectileHit>(); + component.ownWeapon = base.gameObject; + if ((bool)player) + { + component.ownPlayer = player; + } + spawnedAttack.spawner = player; + spawnedAttack.attackID = attackID; + } + + private void ApplyProjectileStats(GameObject obj, int numOfProj = 1, float damageM = 1f, float randomSeed = 0f) + { + ProjectileHit component = obj.GetComponent<ProjectileHit>(); + component.dealDamageMultiplierr *= bulletDamageMultiplier; + component.damage *= damage * damageM; + component.percentageDamage = percentageDamage; + component.stun = component.damage / 150f; + component.force *= knockback; + component.movementSlow = slow; + component.hasControl = CheckIsMine(); + component.projectileColor = projectileColor; + component.unblockable = unblockable; + RayCastTrail component2 = obj.GetComponent<RayCastTrail>(); + if (ignoreWalls) + { + component2.mask = component2.ignoreWallsMask; + } + if ((bool)component2) + { + component2.extraSize += size; + } + if ((bool)player) + { + PlayerSkin teamColor = (component.team = PlayerSkinBank.GetPlayerSkinColors(player.playerID)); + obj.GetComponent<RayCastTrail>().teamID = player.playerID; + SetTeamColor.TeamColorThis(obj, teamColor); + } + List<ObjectsToSpawn> list = new List<ObjectsToSpawn>(); + for (int i = 0; i < objectsToSpawn.Length; i++) + { + list.Add(objectsToSpawn[i]); + if (!objectsToSpawn[i].AddToProjectile || ((bool)objectsToSpawn[i].AddToProjectile.gameObject.GetComponent<StopRecursion>() && isProjectileGun)) + { + continue; + } + GameObject gameObject = UnityEngine.Object.Instantiate(objectsToSpawn[i].AddToProjectile, component.transform.position, component.transform.rotation, component.transform); + gameObject.transform.localScale *= 1f * (1f - objectsToSpawn[i].scaleFromDamage) + component.damage / 55f * objectsToSpawn[i].scaleFromDamage; + if (objectsToSpawn[i].scaleStacks) + { + gameObject.transform.localScale *= 1f + (float)objectsToSpawn[i].stacks * objectsToSpawn[i].scaleStackM; + } + if (!objectsToSpawn[i].removeScriptsFromProjectileObject) + { + continue; + } + MonoBehaviour[] componentsInChildren = gameObject.GetComponentsInChildren<MonoBehaviour>(); + for (int j = 0; j < componentsInChildren.Length; j++) + { + if (componentsInChildren[j].GetType().ToString() != "SoundImplementation.SoundUnityEventPlayer") + { + UnityEngine.Object.Destroy(componentsInChildren[j]); + } + Debug.Log(componentsInChildren[j].GetType().ToString()); + } + } + component.objectsToSpawn = list.ToArray(); + if (reflects > 0) + { + RayHitReflect rayHitReflect = obj.gameObject.AddComponent<RayHitReflect>(); + rayHitReflect.reflects = reflects; + rayHitReflect.speedM = speedMOnBounce; + rayHitReflect.dmgM = dmgMOnBounce; + } + if (!forceSpecificShake) + { + float num = component.damage / 100f * ((1f + usedCooldown) / 2f) / ((1f + (float)numOfProj) / 2f) * 2f; + float num2 = Mathf.Clamp((0.2f + component.damage * (((float)numberOfProjectiles + 2f) / 2f) / 100f * ((1f + usedCooldown) / 2f)) * 1f, 0f, 3f); + component.shake = num * shakeM; + shake = num2; + } + MoveTransform component3 = obj.GetComponent<MoveTransform>(); + component3.localForce *= projectileSpeed; + component3.simulationSpeed *= projectielSimulatonSpeed; + component3.gravity *= gravity; + component3.worldForce *= gravity; + component3.drag = drag; + component3.drag = Mathf.Clamp(component3.drag, 0f, 45f); + component3.velocitySpread = Mathf.Clamp(spread * 50f, 0f, 50f); + component3.dragMinSpeed = dragMinSpeed; + component3.localForce *= Mathf.Lerp(1f - component3.velocitySpread * 0.01f, 1f + component3.velocitySpread * 0.01f, randomSeed); + component3.selectedSpread = 0f; + if (damageAfterDistanceMultiplier != 1f) + { + obj.AddComponent<ChangeDamageMultiplierAfterDistanceTravelled>().muiltiplier = damageAfterDistanceMultiplier; + } + if (cos > 0f) + { + obj.gameObject.AddComponent<Cos>().multiplier = cos; + } + if (destroyBulletAfter != 0f) + { + obj.GetComponent<RemoveAfterSeconds>().seconds = destroyBulletAfter; + } + if ((bool)spawnedAttack && projectileColor != Color.black) + { + spawnedAttack.SetColor(projectileColor); + } + } + + public void AddAttackAction(Action action) + { + attackAction = (Action)Delegate.Combine(attackAction, action); + } + + internal void RemoveAttackAction(Action action) + { + attackAction = (Action)Delegate.Remove(attackAction, action); + } +} diff --git a/ROUNDS/GunAmmo.cs b/ROUNDS/GunAmmo.cs new file mode 100644 index 0000000..102b4d4 --- /dev/null +++ b/ROUNDS/GunAmmo.cs @@ -0,0 +1,212 @@ +using Sonigon; +using UnityEngine; +using UnityEngine.UI; + +public class GunAmmo : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundReloadInProgressLoop; + + public SoundEvent soundReloadComplete; + + private SoundParameterIntensity soundReloadInProgressIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + private bool soundReloadInProgressPlaying; + + private float soundReloadTime; + + [Header("Settings")] + public int maxAmmo = 3; + + private int lastMaxAmmo; + + private int currentAmmo; + + public float reloadTime = 1.5f; + + public float reloadTimeMultiplier = 1f; + + public float reloadTimeAdd; + + private Gun gun; + + public CurveAnimation reloadAnim; + + private Image reloadRing; + + public Image cooldownRing; + + private float reloadCounter; + + private float freeReloadCounter; + + public Populate populate; + + public float ammoReg; + + private float currentRegCounter; + + private void Start() + { + reloadRing = reloadAnim.GetComponent<Image>(); + lastMaxAmmo = maxAmmo; + currentAmmo = maxAmmo; + gun = GetComponentInParent<Gun>(); + ReDrawTotalBullets(); + } + + private void OnDisable() + { + SoundStopReloadInProgress(); + } + + private void OnDestroy() + { + SoundStopReloadInProgress(); + } + + private void SoundStopReloadInProgress() + { + if (soundReloadInProgressPlaying) + { + soundReloadInProgressPlaying = false; + SoundManager.Instance.Stop(soundReloadInProgressLoop, base.transform); + } + } + + private float ReloadTime() + { + return (reloadTime + reloadTimeAdd) * reloadTimeMultiplier; + } + + private void Update() + { + if (!gun.isReloading) + { + SoundStopReloadInProgress(); + } + if (gun.isReloading) + { + reloadCounter -= TimeHandler.deltaTime; + if (!soundReloadInProgressPlaying) + { + soundReloadInProgressPlaying = true; + soundReloadTime = ReloadTime(); + soundReloadInProgressIntensity.intensity = 0f; + SoundManager.Instance.Play(soundReloadInProgressLoop, base.transform, soundReloadInProgressIntensity); + } + if (soundReloadInProgressPlaying && soundReloadTime > 0f) + { + soundReloadInProgressIntensity.intensity = 1f - reloadCounter / soundReloadTime; + } + if (reloadCounter < 0f) + { + ReloadAmmo(); + } + } + else if (currentAmmo != maxAmmo) + { + freeReloadCounter += TimeHandler.deltaTime; + if (freeReloadCounter > ReloadTime() && gun.player.data.stats.automaticReload) + { + currentAmmo = maxAmmo; + SetActiveBullets(); + } + currentRegCounter += ammoReg * TimeHandler.deltaTime * (float)maxAmmo; + if (currentRegCounter > 1f) + { + currentAmmo++; + currentRegCounter = 0f; + SetActiveBullets(); + } + } + if (currentAmmo <= 0) + { + if (reloadAnim.currentState != 0) + { + reloadAnim.PlayIn(); + } + } + else if (reloadAnim.currentState != CurveAnimationUse.Out) + { + reloadAnim.PlayOut(); + } + reloadRing.fillAmount = (ReloadTime() - reloadCounter) / ReloadTime(); + if (gun.attackSpeed > 0.4f) + { + cooldownRing.fillAmount = gun.ReadyAmount(); + if (gun.ReadyAmount() >= 1f) + { + cooldownRing.fillAmount = 0f; + } + } + else + { + cooldownRing.fillAmount = 0f; + } + if (maxAmmo != lastMaxAmmo) + { + ReDrawTotalBullets(); + } + lastMaxAmmo = maxAmmo; + } + + public void ReloadAmmo(bool playSound = true) + { + gun.player.data.stats.OnReload(maxAmmo - currentAmmo); + gun.isReloading = false; + currentAmmo = maxAmmo; + SoundStopReloadInProgress(); + if (playSound) + { + SoundManager.Instance.Play(soundReloadComplete, base.transform); + } + SetActiveBullets(); + } + + public void Shoot(GameObject projectile) + { + currentAmmo--; + freeReloadCounter = 0f; + SetActiveBullets(); + if (currentAmmo <= 0) + { + reloadCounter = ReloadTime(); + gun.isReloading = true; + gun.player.data.stats.OnOutOfAmmp(maxAmmo); + } + } + + public void ReDrawTotalBullets() + { + currentAmmo = maxAmmo; + for (int num = populate.transform.childCount - 1; num >= 0; num--) + { + if (populate.transform.GetChild(num).gameObject.activeSelf) + { + Object.Destroy(populate.transform.GetChild(num).gameObject); + } + } + populate.times = maxAmmo; + populate.DoPopulate(); + SetActiveBullets(forceTurnOn: true); + } + + private void SetActiveBullets(bool forceTurnOn = false) + { + for (int i = 1; i < populate.transform.childCount; i++) + { + if (i <= currentAmmo || forceTurnOn) + { + if (populate.transform.GetChild(i).GetComponent<CurveAnimation>().currentState != CurveAnimationUse.In || forceTurnOn) + { + populate.transform.GetChild(i).GetComponent<CurveAnimation>().PlayIn(); + } + } + else if (populate.transform.GetChild(i).GetComponent<CurveAnimation>().currentState != CurveAnimationUse.Out) + { + populate.transform.GetChild(i).GetComponent<CurveAnimation>().PlayOut(); + } + } + } +} diff --git a/ROUNDS/GunLevel.cs b/ROUNDS/GunLevel.cs new file mode 100644 index 0000000..427e442 --- /dev/null +++ b/ROUNDS/GunLevel.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +public class GunLevel : MonoBehaviour +{ + public Gun copyTo; + + private Gun copyFrom; + + private void Start() + { + copyFrom = GetComponent<Gun>(); + AttackLevel componentInParent = GetComponentInParent<AttackLevel>(); + componentInParent.LevelUpAction = (Action<int>)Delegate.Combine(componentInParent.LevelUpAction, new Action<int>(BuffGun)); + } + + public void BuffGun(int level) + { + ApplyCardStats.CopyGunStats(copyFrom, copyTo); + } +} diff --git a/ROUNDS/HandPos.cs b/ROUNDS/HandPos.cs new file mode 100644 index 0000000..a0e6af6 --- /dev/null +++ b/ROUNDS/HandPos.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class HandPos : MonoBehaviour +{ +} diff --git a/ROUNDS/HasToReturn.cs b/ROUNDS/HasToReturn.cs new file mode 100644 index 0000000..4cf01d8 --- /dev/null +++ b/ROUNDS/HasToReturn.cs @@ -0,0 +1,6 @@ +public enum HasToReturn +{ + hasToReturn, + canContinue, + hasToReturnNow +} diff --git a/ROUNDS/HealthBar.cs b/ROUNDS/HealthBar.cs new file mode 100644 index 0000000..98e08ec --- /dev/null +++ b/ROUNDS/HealthBar.cs @@ -0,0 +1,58 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +public class HealthBar : MonoBehaviour +{ + public Image hp; + + public Image white; + + private float drag = 25f; + + private float spring = 25f; + + private float hpCur; + + private float hpVel; + + private float hpTarg; + + private float whiteCur; + + private float whiteVel; + + private float whiteTarg; + + private float sinceDamage; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + CharacterStatModifiers componentInParent = GetComponentInParent<CharacterStatModifiers>(); + componentInParent.WasDealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(componentInParent.WasDealtDamageAction, new Action<Vector2, bool>(TakeDamage)); + } + + private void Update() + { + hpTarg = data.health / data.maxHealth; + sinceDamage += TimeHandler.deltaTime; + hpVel = FRILerp.Lerp(hpVel, (hpTarg - hpCur) * spring, drag); + whiteVel = FRILerp.Lerp(whiteVel, (whiteTarg - whiteCur) * spring, drag); + hpCur += hpVel * TimeHandler.deltaTime; + whiteCur += whiteVel * TimeHandler.deltaTime; + hp.fillAmount = hpCur; + white.fillAmount = whiteCur; + if (sinceDamage > 0.5f) + { + whiteTarg = hpTarg; + } + } + + public void TakeDamage(Vector2 dmg, bool selfDmg) + { + sinceDamage = 0f; + } +} diff --git a/ROUNDS/HealthHandler.cs b/ROUNDS/HealthHandler.cs new file mode 100644 index 0000000..bbc739f --- /dev/null +++ b/ROUNDS/HealthHandler.cs @@ -0,0 +1,362 @@ +using System; +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class HealthHandler : Damagable +{ + [Header("Sounds")] + public SoundEvent soundDie; + + public SoundEvent soundHeal; + + public SoundEvent soundDamagePassive; + + public SoundEvent soundDamageLifeSteal; + + public SoundEvent soundBounce; + + [Header("Settings")] + public SpriteRenderer hpSprite; + + public GameObject deathEffect; + + public float regeneration; + + private CharacterData data; + + private CodeAnimation anim; + + private Player player; + + private CharacterStatModifiers stats; + + public ParticleSystem healPart; + + private DamageOverTime dot; + + private Vector3 startHealthSpriteScale; + + public float flyingFor; + + private float lastDamaged; + + public Action delayedReviveAction; + + public Action reviveAction; + + [HideInInspector] + public bool DestroyOnDeath; + + public bool isRespawning; + + public GameObject deathEffectPhoenix; + + private void Awake() + { + dot = GetComponent<DamageOverTime>(); + data = GetComponent<CharacterData>(); + anim = GetComponentInChildren<CodeAnimation>(); + player = GetComponent<Player>(); + stats = GetComponent<CharacterStatModifiers>(); + } + + private void Start() + { + startHealthSpriteScale = hpSprite.transform.localScale; + } + + private void Update() + { + flyingFor -= TimeHandler.deltaTime; + if (regeneration > 0f) + { + Heal(regeneration * TimeHandler.deltaTime); + } + } + + public void Heal(float healAmount) + { + if (healAmount != 0f && data.health != data.maxHealth) + { + SoundManager.Instance.Play(soundHeal, base.transform); + data.health += healAmount; + data.health = Mathf.Clamp(data.health, float.NegativeInfinity, data.maxHealth); + healPart.Emit((int)Mathf.Clamp(healAmount * 0.2f, 1f, 10f)); + } + } + + public void CallTakeForce(Vector2 force, ForceMode2D forceMode = ForceMode2D.Impulse, bool forceIgnoreMass = false, bool ignoreBlock = false, float setFlying = 0f) + { + if (data.isPlaying && (!data.block.IsBlocking() || ignoreBlock)) + { + data.view.RPC("RPCA_SendTakeForce", RpcTarget.All, force, (int)forceMode, forceIgnoreMass, true, setFlying); + } + } + + [PunRPC] + public void RPCA_SendTakeForce(Vector2 force, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false, float setFlying = 0f) + { + TakeForce(force, (ForceMode2D)forceMode, forceIgnoreMass, ignoreBlock, setFlying); + data.GetComponent<SyncPlayerMovement>().SetDontSyncFor((float)PhotonNetwork.GetPing() * 0.001f + 0.2f); + } + + [PunRPC] + public void RPCA_SendForceOverTime(Vector2 force, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + StartCoroutine(IForceOverTime(force, time, forceMode, forceIgnoreMass, ignoreBlock)); + } + + private IEnumerator IForceOverTime(Vector2 force, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + for (float i = 0f; i < time; i += TimeHandler.deltaTime) + { + TakeForce(force, (ForceMode2D)forceMode, forceIgnoreMass, ignoreBlock); + data.GetComponent<SyncPlayerMovement>().SetDontSyncFor((float)PhotonNetwork.GetPing() * 0.001f + 0.2f); + yield return new WaitForFixedUpdate(); + } + } + + [PunRPC] + public void RPCA_SendForceTowardsPointOverTime(float force, float drag, float clampDistancce, Vector2 point, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + StartCoroutine(IForceTowardsPointOverTime(force, drag, clampDistancce, point, time, forceMode, forceIgnoreMass, ignoreBlock)); + } + + private IEnumerator IForceTowardsPointOverTime(float force, float drag, float clampDistancce, Vector2 point, float time, int forceMode, bool forceIgnoreMass = false, bool ignoreBlock = false) + { + for (float i = 0f; i < time; i += TimeHandler.fixedDeltaTime) + { + Vector2 vector = point - (Vector2)base.transform.position; + vector = Vector2.ClampMagnitude(vector, clampDistancce); + Vector2 vector2 = data.playerVel.velocity * (0f - drag) * TimeHandler.fixedDeltaTime; + TakeForce(force * vector + vector2 * drag * TimeHandler.timeScale, (ForceMode2D)forceMode, forceIgnoreMass, ignoreBlock); + data.GetComponent<SyncPlayerMovement>().SetDontSyncFor((float)PhotonNetwork.GetPing() * 0.001f + 0.2f); + yield return new WaitForFixedUpdate(); + } + } + + public void TakeForce(Vector2 force, ForceMode2D forceMode = ForceMode2D.Impulse, bool forceIgnoreMass = false, bool ignoreBlock = false, float setFlying = 0f) + { + if (!data.isPlaying || !data.playerVel.simulated) + { + return; + } + bool flag = data.block.IsBlocking(); + if (flag && !ignoreBlock) + { + return; + } + if (!flag) + { + if (setFlying > flyingFor && setFlying > 0.25f) + { + flyingFor = setFlying; + SoundManager.Instance.Play(soundBounce, base.transform); + } + } + if (forceIgnoreMass) + { + force *= data.playerVel.mass / 100f; + } + data.playerVel.AddForce(force, forceMode); + if (force.y > 0f) + { + if (!forceIgnoreMass) + { + force.y /= data.playerVel.mass / 100f; + } + if (forceMode == ForceMode2D.Force) + { + force *= 0.003f; + } + data.sinceGrounded -= force.y * 0.003f; + } + data.sinceGrounded = Mathf.Clamp(data.sinceGrounded, -0.5f, 100f); + } + + public override void CallTakeDamage(Vector2 damage, Vector2 position, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + if (!(damage == Vector2.zero) && !data.block.IsBlocking()) + { + data.view.RPC("RPCA_SendTakeDamage", RpcTarget.All, damage, position, lethal, (damagingPlayer != null) ? damagingPlayer.playerID : (-1)); + } + } + + [PunRPC] + public void RPCA_SendTakeDamage(Vector2 damage, Vector2 position, bool lethal = true, int playerID = -1) + { + if (!(damage == Vector2.zero)) + { + Player playerWithID = PlayerManager.instance.GetPlayerWithID(playerID); + GameObject damagingWeapon = null; + if ((bool)playerWithID) + { + damagingWeapon = playerWithID.data.weaponHandler.gun.gameObject; + } + TakeDamage(damage, position, damagingWeapon, playerWithID, lethal, ignoreBlock: true); + } + } + + public override void TakeDamage(Vector2 damage, Vector2 position, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (!(damage == Vector2.zero)) + { + TakeDamage(damage, position, Color.white * 0.85f, damagingWeapon, damagingPlayer, lethal, ignoreBlock); + } + } + + public override void TakeDamage(Vector2 damage, Vector2 position, Color dmgColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true, bool ignoreBlock = false) + { + if (!(damage == Vector2.zero) && data.isPlaying && data.playerVel.simulated && !data.dead && (!data.block.IsBlocking() || ignoreBlock)) + { + if (dmgColor == Color.black) + { + dmgColor = Color.white * 0.85f; + } + if (stats.secondsToTakeDamageOver == 0f) + { + DoDamage(damage, position, dmgColor, damagingWeapon, damagingPlayer, healthRemoval: false, lethal, ignoreBlock); + } + else + { + TakeDamageOverTime(damage, position, stats.secondsToTakeDamageOver, 0.25f, dmgColor, damagingWeapon, damagingPlayer, lethal); + } + } + } + + public void DoDamage(Vector2 damage, Vector2 position, Color blinkColor, GameObject damagingWeapon = null, Player damagingPlayer = null, bool healthRemoval = false, bool lethal = true, bool ignoreBlock = false) + { + if (damage == Vector2.zero || !data.isPlaying || data.dead || (data.block.IsBlocking() && !ignoreBlock) || isRespawning) + { + return; + } + if ((bool)damagingPlayer) + { + damagingPlayer.GetComponent<CharacterStatModifiers>().DealtDamage(damage, damagingPlayer != null && damagingPlayer.transform.root == base.transform, data.player); + } + StopAllCoroutines(); + DisplayDamage(blinkColor); + data.lastSourceOfDamage = damagingPlayer; + data.health -= damage.magnitude; + stats.WasDealtDamage(damage, damagingPlayer != null && damagingPlayer.transform.root == base.transform); + if (!lethal) + { + data.health = Mathf.Clamp(data.health, 1f, data.maxHealth); + } + if (data.health < 0f && !data.dead) + { + if (data.stats.remainingRespawns > 0) + { + data.view.RPC("RPCA_Die_Phoenix", RpcTarget.All, damage); + } + else + { + data.view.RPC("RPCA_Die", RpcTarget.All, damage); + } + } + if (lastDamaged + 0.15f < Time.time && damagingPlayer != null && damagingPlayer.data.stats.lifeSteal != 0f) + { + SoundManager.Instance.Play(soundDamageLifeSteal, base.transform); + } + lastDamaged = Time.time; + } + + public void TakeDamageOverTime(Vector2 damage, Vector2 position, float time, float interval, Color color, GameObject damagingWeapon = null, Player damagingPlayer = null, bool lethal = true) + { + dot.TakeDamageOverTime(damage, position, time, interval, color, soundDamagePassive, damagingWeapon, damagingPlayer, lethal); + } + + private void DisplayDamage(Color blinkColor) + { + GetComponentInChildren<PlayerSkinHandler>().BlinkColor(blinkColor); + } + + private IEnumerator DelayReviveAction() + { + yield return new WaitForSecondsRealtime(2f); + delayedReviveAction?.Invoke(); + } + + public void Revive(bool isFullRevive = true) + { + reviveAction?.Invoke(); + if (base.gameObject.activeInHierarchy) + { + StartCoroutine(DelayReviveAction()); + } + flyingFor = 0f; + if (isFullRevive) + { + data.stats.remainingRespawns = data.stats.respawns; + } + data.healthHandler.isRespawning = false; + data.health = data.maxHealth; + data.playerVel.velocity = Vector2.zero; + data.playerVel.angularVelocity = 0f; + data.stunTime = 0f; + data.block.ResetCD(soundPlay: false); + data.weaponHandler.gun.GetComponentInChildren<GunAmmo>().ReloadAmmo(playSound: false); + data.GetComponent<PlayerCollision>().IgnoreWallForFrames(5); + base.gameObject.SetActive(value: true); + if ((bool)deathEffect && data.dead) + { + anim.PlayIn(); + } + data.dead = false; + hpSprite.color = PlayerSkinBank.GetPlayerSkinColors(player.playerID).color; + data.stunHandler.StopStun(); + data.silenceHandler.StopSilence(); + GetComponent<CharacterStatModifiers>().slow = 0f; + GetComponent<CharacterStatModifiers>().slowSlow = 0f; + GetComponent<CharacterStatModifiers>().fastSlow = 0f; + GetComponent<WeaponHandler>().isOverHeated = false; + GetComponent<Block>().sinceBlock = float.PositiveInfinity; + dot.StopAllCoroutines(); + } + + [PunRPC] + private void RPCA_Die(Vector2 deathDirection) + { + if (data.isPlaying && !data.dead) + { + SoundManager.Instance.Play(soundDie, base.transform); + data.dead = true; + if (!DestroyOnDeath) + { + base.gameObject.SetActive(value: false); + GamefeelManager.GameFeel(deathDirection.normalized * 3f); + UnityEngine.Object.Instantiate(deathEffect, base.transform.position, base.transform.rotation).GetComponent<DeathEffect>().PlayDeath(PlayerSkinBank.GetPlayerSkinColors(player.playerID).color, data.playerVel, deathDirection); + dot.StopAllCoroutines(); + data.stunHandler.StopStun(); + data.silenceHandler.StopSilence(); + PlayerManager.instance.PlayerDied(player); + } + else + { + UnityEngine.Object.Destroy(base.transform.root.gameObject); + } + } + } + + [PunRPC] + private void RPCA_Die_Phoenix(Vector2 deathDirection) + { + if (data.isPlaying && !data.dead) + { + data.stats.remainingRespawns--; + isRespawning = true; + SoundManager.Instance.Play(soundDie, base.transform); + if (!DestroyOnDeath) + { + base.gameObject.SetActive(value: false); + GamefeelManager.GameFeel(deathDirection.normalized * 3f); + UnityEngine.Object.Instantiate(deathEffectPhoenix, base.transform.position, base.transform.rotation).GetComponent<DeathEffect>().PlayDeath(PlayerSkinBank.GetPlayerSkinColors(player.playerID).color, data.playerVel, deathDirection, player.playerID); + dot.StopAllCoroutines(); + data.stunHandler.StopStun(); + data.silenceHandler.StopSilence(); + } + } + } +} diff --git a/ROUNDS/HitInfo.cs b/ROUNDS/HitInfo.cs new file mode 100644 index 0000000..782dce3 --- /dev/null +++ b/ROUNDS/HitInfo.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class HitInfo +{ + public Vector2 point; + + public Vector2 normal; + + public Collider2D collider; + + public Transform transform; + + public Rigidbody2D rigidbody; + + internal static HitInfo GetHitInfo(RaycastHit2D raycastHit2D) + { + return new HitInfo + { + point = raycastHit2D.point, + normal = raycastHit2D.normal, + transform = raycastHit2D.transform, + collider = raycastHit2D.collider, + rigidbody = raycastHit2D.rigidbody + }; + } +} diff --git a/ROUNDS/Holdable.cs b/ROUNDS/Holdable.cs new file mode 100644 index 0000000..c2329b5 --- /dev/null +++ b/ROUNDS/Holdable.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class Holdable : MonoBehaviour +{ + public Rigidbody2D rig; + + public CharacterData holder; + + private void Awake() + { + rig = GetComponent<Rigidbody2D>(); + } + + private void Start() + { + } + + public void SetTeamColors(PlayerSkin teamColor, Player player) + { + SetTeamColor.TeamColorThis(base.gameObject, teamColor); + } +} diff --git a/ROUNDS/Holding.cs b/ROUNDS/Holding.cs new file mode 100644 index 0000000..1f1839f --- /dev/null +++ b/ROUNDS/Holding.cs @@ -0,0 +1,75 @@ +using UnityEngine; + +public class Holding : MonoBehaviour +{ + public float force; + + public float drag; + + public Holdable holdable; + + private Transform handPos; + + private PlayerVelocity rig; + + private GeneralInput input; + + private CharacterData data; + + private Player player; + + private Gun gun; + + private bool hasSpawnedGun; + + public void Awake() + { + if (hasSpawnedGun) + { + Object.Destroy(holdable.gameObject); + } + hasSpawnedGun = true; + holdable = Object.Instantiate(holdable, base.transform.position, Quaternion.identity); + player = GetComponent<Player>(); + holdable.GetComponent<Holdable>().holder = player.data; + handPos = GetComponentInChildren<HandPos>().transform; + rig = GetComponent<PlayerVelocity>(); + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + if ((bool)holdable) + { + gun = holdable.GetComponent<Gun>(); + GetComponentInChildren<WeaponHandler>().gun = holdable.GetComponent<Gun>(); + } + } + + private void Start() + { + if ((bool)holdable) + { + holdable.SetTeamColors(PlayerSkinBank.GetPlayerSkinColors(player.playerID), player); + } + } + + private void FixedUpdate() + { + if ((bool)holdable && (bool)holdable.rig) + { + holdable.rig.AddForce((handPos.transform.position + (Vector3)rig.velocity * 0.04f - holdable.transform.position) * force * holdable.rig.mass, ForceMode2D.Force); + holdable.rig.AddForce(holdable.rig.velocity * (0f - drag) * holdable.rig.mass, ForceMode2D.Force); + holdable.rig.transform.rotation = Quaternion.LookRotation(Vector3.forward, handPos.transform.forward); + } + } + + private void Update() + { + } + + private void OnDestroy() + { + if ((bool)holdable) + { + Object.Destroy(holdable.gameObject); + } + } +} diff --git a/ROUNDS/HoldingObject.cs b/ROUNDS/HoldingObject.cs new file mode 100644 index 0000000..c06d79f --- /dev/null +++ b/ROUNDS/HoldingObject.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class HoldingObject : MonoBehaviour +{ + public Holding holder; + + private void Start() + { + } + + private void Update() + { + if (CardChoice.instance.IsPicking) + { + base.transform.position = Vector3.up * 10000f; + } + else if (Vector3.Distance(holder.transform.position, base.transform.position) > 100f) + { + base.transform.position = holder.transform.position; + } + } +} diff --git a/ROUNDS/Homing.cs b/ROUNDS/Homing.cs new file mode 100644 index 0000000..39a12c1 --- /dev/null +++ b/ROUNDS/Homing.cs @@ -0,0 +1,104 @@ +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class Homing : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundHomingFound; + + private bool soundHomingCanPlay = true; + + [Header("Settings")] + public float amount = 1f; + + public float scalingDrag = 1f; + + public float drag = 1f; + + public float spread = 1f; + + private MoveTransform move; + + private bool isOn; + + public RotSpring rot1; + + public RotSpring rot2; + + private FlickerEvent[] flicks; + + private PhotonView view; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + flicks = GetComponentsInChildren<FlickerEvent>(); + view = GetComponentInParent<PhotonView>(); + GetComponentInParent<SyncProjectile>().active = true; + } + + private void Update() + { + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true); + if ((bool)closestPlayer) + { + Vector3 vector = closestPlayer.transform.position + base.transform.right * move.selectedSpread * Vector3.Distance(base.transform.position, closestPlayer.transform.position) * spread; + float num = Vector3.Angle(base.transform.root.forward, vector - base.transform.position); + if (num < 70f) + { + move.velocity -= move.velocity * num * TimeHandler.deltaTime * scalingDrag; + move.velocity -= move.velocity * TimeHandler.deltaTime * drag; + move.velocity += Vector3.ClampMagnitude(vector - base.transform.position, 1f) * TimeHandler.deltaTime * move.localForce.magnitude * 0.025f * amount; + move.velocity.z = 0f; + move.velocity += Vector3.up * TimeHandler.deltaTime * move.gravity * move.multiplier; + if (!isOn) + { + move.simulateGravity++; + if (soundHomingCanPlay) + { + soundHomingCanPlay = false; + SoundManager.Instance.PlayAtPosition(soundHomingFound, SoundManager.Instance.GetTransform(), base.transform); + } + } + isOn = true; + for (int i = 0; i < flicks.Length; i++) + { + flicks[i].isOn = true; + } + rot1.target = 10f; + rot2.target = -10f; + } + else + { + if (isOn) + { + move.simulateGravity--; + soundHomingCanPlay = true; + } + isOn = false; + for (int j = 0; j < flicks.Length; j++) + { + flicks[j].isOn = false; + } + rot1.target = 50f; + rot2.target = -50f; + } + } + else + { + if (isOn) + { + move.simulateGravity--; + soundHomingCanPlay = true; + } + isOn = false; + for (int k = 0; k < flicks.Length; k++) + { + flicks[k].isOn = false; + } + rot1.target = 50f; + rot2.target = -50f; + } + } +} diff --git a/ROUNDS/HoverEvent.cs b/ROUNDS/HoverEvent.cs new file mode 100644 index 0000000..6e9f332 --- /dev/null +++ b/ROUNDS/HoverEvent.cs @@ -0,0 +1,38 @@ +using SoundImplementation; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.EventSystems; + +public class HoverEvent : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler +{ + public UnityEvent enterEvent; + + public UnityEvent exitEvent; + + public bool isHovered; + + public bool isSelected; + + public void OnPointerEnter(PointerEventData eventData) + { + SoundPlayerStatic.Instance.PlayButtonHover(); + enterEvent.Invoke(); + isHovered = true; + } + + public void OnPointerExit(PointerEventData eventData) + { + exitEvent.Invoke(); + isHovered = false; + } + + private void Update() + { + isSelected = EventSystem.current.currentSelectedGameObject == base.gameObject; + } + + private void OnDisable() + { + isHovered = false; + } +} diff --git a/ROUNDS/HoverEventColor.cs b/ROUNDS/HoverEventColor.cs new file mode 100644 index 0000000..d6fa9c3 --- /dev/null +++ b/ROUNDS/HoverEventColor.cs @@ -0,0 +1,32 @@ +using UnityEngine; +using UnityEngine.UI; + +public class HoverEventColor : MonoBehaviour +{ + public Color hoverColor; + + private Color defaultColor; + + private HoverEvent hover; + + private Image img; + + private void Start() + { + img = GetComponent<Image>(); + defaultColor = img.color; + hover = GetComponent<HoverEvent>(); + hover.enterEvent.AddListener(Enter); + hover.exitEvent.AddListener(Exit); + } + + private void Enter() + { + img.color = hoverColor; + } + + private void Exit() + { + img.color = defaultColor; + } +} diff --git a/ROUNDS/HoverEvent_WobbleButton.cs b/ROUNDS/HoverEvent_WobbleButton.cs new file mode 100644 index 0000000..83e6079 --- /dev/null +++ b/ROUNDS/HoverEvent_WobbleButton.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; + +public class HoverEvent_WobbleButton : MonoBehaviour +{ + public float min = 1f; + + public float max = 1.1f; + + public float spring = 1f; + + public float drag = 1f; + + public float force = -0.1f; + + private ScaleShake sh; + + private void Awake() + { + HoverEvent hoverEvent = base.gameObject.AddComponent<HoverEvent>(); + sh = base.gameObject.AddComponent<ScaleShake>(); + Button component = GetComponent<Button>(); + sh.spring = spring; + sh.drag = drag; + sh.multiplier = force; + sh.high = max; + sh.low = min; + sh.useTimeScale = false; + sh.SetTarget(min); + UnityEvent unityEvent = new UnityEvent(); + unityEvent.AddListener(sh.SetHigh); + hoverEvent.enterEvent = unityEvent; + UnityEvent unityEvent2 = new UnityEvent(); + unityEvent2.AddListener(sh.SetLow); + hoverEvent.exitEvent = unityEvent2; + component.onClick.AddListener(sh.AddForce); + } + + private void OnDisable() + { + base.transform.localScale = Vector3.one * min; + sh.SetTarget(min); + } +} diff --git a/ROUNDS/HoveredTooltip.cs b/ROUNDS/HoveredTooltip.cs new file mode 100644 index 0000000..4fa3cb7 --- /dev/null +++ b/ROUNDS/HoveredTooltip.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +public class HoveredTooltip : MonoBehaviour +{ + private CurveAnimation anim; + + private HoverEvent hoverEvent; + + private void Start() + { + anim = GetComponent<CurveAnimation>(); + hoverEvent = GetComponentInParent<HoverEvent>(); + } + + private void Update() + { + if (!anim.IsPlaying()) + { + if ((hoverEvent.isHovered || hoverEvent.isSelected) && anim.currentState != 0) + { + anim.PlayIn(); + } + if (!hoverEvent.isHovered && !hoverEvent.isSelected && anim.currentState != CurveAnimationUse.Out) + { + anim.PlayOut(); + } + } + } + + private void OnEnable() + { + if ((bool)anim) + { + anim.currentState = CurveAnimationUse.Out; + anim.transform.localScale = Vector3.zero; + } + } + + private void OnDisable() + { + if ((bool)anim) + { + anim.currentState = CurveAnimationUse.Out; + anim.transform.localScale = Vector3.zero; + } + } +} diff --git a/ROUNDS/IKArmMove.cs b/ROUNDS/IKArmMove.cs new file mode 100644 index 0000000..ee14990 --- /dev/null +++ b/ROUNDS/IKArmMove.cs @@ -0,0 +1,56 @@ +using UnityEngine; + +public class IKArmMove : MonoBehaviour +{ + private CharacterData data; + + private PlayerVelocity rig; + + public Transform target; + + private Vector3 startPos; + + private Holding holding; + + private bool isActive; + + private Vector3 velolcity; + + private float sinceRaise = 10f; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + rig = GetComponentInParent<PlayerVelocity>(); + startPos = target.localPosition; + holding = GetComponentInParent<Holding>(); + } + + private void Update() + { + isActive = false; + sinceRaise += TimeHandler.deltaTime; + if ((bool)holding.holdable && (bool)holding.holdable.rig && holding.holdable.rig.transform.position.x > rig.transform.position.x == base.transform.position.x > rig.transform.position.x) + { + target.position = holding.holdable.rig.transform.position; + velolcity = Vector3.zero; + isActive = true; + return; + } + Vector3 vector = base.transform.parent.TransformPoint(startPos) + ((sinceRaise < 0.3f) ? Vector3.up : Vector3.zero); + Vector3 vector2 = rig.velocity; + vector2.x *= 0.3f; + velolcity = FRILerp.Lerp(velolcity, (vector - target.position) * 15f, 15f); + target.position += velolcity * TimeHandler.deltaTime; + target.position += vector2 * -0.3f * TimeHandler.deltaTime; + } + + public void RaiseHands() + { + if (!isActive) + { + sinceRaise = 0f; + velolcity += Vector3.up * 20f; + } + } +} diff --git a/ROUNDS/IKLegMove.cs b/ROUNDS/IKLegMove.cs new file mode 100644 index 0000000..cc6d6e6 --- /dev/null +++ b/ROUNDS/IKLegMove.cs @@ -0,0 +1,142 @@ +using UnityEngine; + +public class IKLegMove : MonoBehaviour +{ + private Rigidbody2D rig; + + public bool touchesGround; + + public IKLegMove otherLeg; + + public Transform target; + + public Transform foot; + + private Vector3 transformGroundPos; + + private Vector3 currentTransformGroundPos; + + private Vector3 previousTransformGroundPos; + + private Transform hitTransform; + + private Transform currentHitTransform; + + [HideInInspector] + public float allowedFootDistance; + + private float defaultAllowedFootDistance; + + public AnimationCurve footCurveUp; + + private float distanceToFoot; + + public LayerMask mask; + + [HideInInspector] + public float animationTime = 1f; + + private Vector3 velocity; + + private CharacterData data; + + private float animationLength; + + private bool hasLanded; + + private void Start() + { + rig = GetComponentInParent<Rigidbody2D>(); + data = GetComponentInParent<CharacterData>(); + defaultAllowedFootDistance = Vector3.Distance(base.transform.position, foot.position); + } + + private void LateUpdate() + { + allowedFootDistance = (defaultAllowedFootDistance = base.transform.root.localScale.x); + animationLength = footCurveUp.keys[footCurveUp.keys.Length - 1].time; + if (!data.isGrounded) + { + animationTime = 1f; + hasLanded = false; + } + distanceToFoot = Vector3.Distance(base.transform.position + (Vector3)rig.velocity * 0.01f, target.position); + velocity = rig.velocity; + if (velocity.y > 0f) + { + velocity.y *= -1f; + } + animationTime += TimeHandler.deltaTime; + RayCastForFootPosition(); + touchesGround = footCurveUp.Evaluate(animationTime) < 0.1f; + DoSteps(); + MoveFoot(); + } + + private void DoSteps() + { + float num = 0f; + if (target.position.x > base.transform.position.x == rig.velocity.x > 0f) + { + num += Mathf.Abs(rig.velocity.x) * 0.25f; + } + float num2 = Mathf.Clamp(animationTime * 0.4f - 0.23f, 0f, 0.2f); + if ((distanceToFoot > allowedFootDistance + num - num2 && data.isGrounded && (otherLeg.animationTime > animationLength * 0.5f || animationLength > 2f) && animationTime > animationLength) || !hasLanded) + { + hasLanded = true; + currentHitTransform = hitTransform; + previousTransformGroundPos = currentTransformGroundPos; + currentTransformGroundPos = transformGroundPos; + animationTime = 0f; + } + else + { + Vector3 vector = transformGroundPos - currentTransformGroundPos; + vector *= Mathf.Clamp(footCurveUp.Evaluate(animationTime) * 1f, 0f, 1f); + previousTransformGroundPos += vector; + currentTransformGroundPos += vector; + } + } + + private void MoveFoot() + { + if (!data.isGrounded) + { + target.position = Vector3.Lerp(target.position, base.transform.position + Vector3.down * allowedFootDistance * 0.5f, TimeHandler.deltaTime * 1f); + target.position += (Vector3)rig.velocity * 0.1f * TimeHandler.deltaTime; + } + else if ((bool)currentHitTransform) + { + Vector3 vector = currentHitTransform.TransformPoint(currentTransformGroundPos); + Vector3 a = currentHitTransform.TransformPoint(previousTransformGroundPos); + Vector3 vector2 = vector; + float num = 0f; + if (animationTime < animationLength) + { + vector2 = Vector3.Lerp(a, vector, animationTime / animationLength); + num = footCurveUp.Evaluate(animationTime); + } + target.position = vector2 + Vector3.up * num; + } + } + + private void RayCastForFootPosition() + { + RaycastHit2D[] array = Physics2D.RaycastAll(base.transform.position, Vector3.down + velocity * 0.2f, 3f, mask); + RaycastHit2D raycastHit2D = default(RaycastHit2D); + float num = float.PositiveInfinity; + for (int i = 0; i < array.Length; i++) + { + if (array[i].transform.root != base.transform.root && array[i].distance < num) + { + raycastHit2D = array[i]; + num = array[i].distance; + } + } + if ((bool)raycastHit2D.transform) + { + hitTransform = raycastHit2D.transform; + transformGroundPos = hitTransform.InverseTransformPoint(raycastHit2D.point); + } + } +} diff --git a/ROUNDS/IkLeg.cs b/ROUNDS/IkLeg.cs new file mode 100644 index 0000000..d8dd137 --- /dev/null +++ b/ROUNDS/IkLeg.cs @@ -0,0 +1,290 @@ +using Sonigon; +using UnityEngine; + +public class IkLeg : MonoBehaviour +{ + [Header("Sounds")] + [SerializeField] + private SoundEvent soundCharacterStep; + + [SerializeField] + private SoundEvent soundCharacterStepBig; + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(); + + private CharacterData data; + + private float legLenth; + + public Transform legRoot; + + public Transform footTarget; + + public LayerMask mask; + + public AnimationCurve upCurve; + + public AnimationCurve forwardCurve; + + public Transform moveDeltaTransform; + + [HideInInspector] + public float stepTime; + + public float stepSpeed = 1f; + + private float footDownTime; + + [HideInInspector] + public bool footDown = true; + + public IkLeg otherLeg; + + private Vector2 restPosition; + + private Vector2 startOffset; + + private Vector2 legRootOffset; + + private float scale = 1f; + + public float prediction = 1f; + + private Vector2 raycastPosLocal; + + private Vector2 raycastPosWorld; + + private Vector2 previousRaycastPosLocal; + + private Vector2 previousRaycastPosWorld; + + private Transform raycastTransform; + + private Transform previousRaycastTransform; + + private Vector2 footPosition; + + private Vector2 deltaPos; + + private Vector2 lastPos; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + legLenth = Vector3.Distance(base.transform.position, footTarget.position); + startOffset = footTarget.position - data.transform.position; + legRootOffset = legRoot.position - data.transform.position; + } + + private void FixedUpdate() + { + if ((bool)data) + { + SetValuesFixed(); + } + } + + private void LateUpdate() + { + if ((bool)data) + { + DoRayCast(); + UpdateRayCastWorldPos(); + DoStep(); + UpdatePreviousRayCastWorldPos(); + UpdateMiscVariables(); + SetFootPos(); + Apply(); + } + } + + private void AirFootMovement() + { + footPosition = Vector3.Lerp(footPosition, restPosition + data.playerVel.velocity * 0.08f, TimeHandler.deltaTime * 15f); + raycastTransform = null; + } + + private bool stepWasLost() + { + if (Vector3.Distance(footPosition, legRoot.position) > legLenth * 0.5f) + { + return true; + } + return false; + } + + private void DoStep() + { + if (footDown) + { + footDownTime += TimeHandler.deltaTime * stepSpeed / scale; + if (!(footDownTime > 1f) || !otherLeg.footDown || (!(Mathf.Abs(data.playerVel.velocity.x) > 1f) && !stepWasLost())) + { + return; + } + StartStep(); + footDownTime = 0f; + footDown = false; + if (!data.dead && data.isPlaying && data.isGrounded && !data.isWallGrab) + { + soundParameterIntensity.intensity = Mathf.Abs(data.playerVel.velocity.x); + if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterStepBig, data.transform, soundParameterIntensity); + } + else + { + SoundManager.Instance.Play(soundCharacterStep, data.transform, soundParameterIntensity); + } + } + } + else + { + stepTime += TimeHandler.deltaTime * stepSpeed / scale; + if (stepTime > 1f) + { + EndStep(); + stepTime = 0f; + footDown = true; + } + } + } + + private void EndStep() + { + if ((bool)raycastTransform) + { + previousRaycastTransform = raycastTransform; + previousRaycastPosLocal = raycastPosLocal; + } + } + + private void StartStep() + { + } + + private void SetFootPos() + { + if (data.isGrounded) + { + if ((bool)raycastTransform) + { + if (footDown) + { + footPosition = previousRaycastPosWorld; + } + else + { + footPosition = Vector3.Lerp(previousRaycastPosWorld, raycastPosWorld, forwardCurve.Evaluate(stepTime)) + Vector3.up * upCurve.Evaluate(stepTime); + } + } + } + else + { + AirFootMovement(); + } + } + + private void Apply() + { + legRoot.position = (Vector2)data.transform.position + legRootOffset * scale; + footTarget.position = footPosition; + } + + private void DoRayCast() + { + Vector2 vector = deltaPos * prediction; + Vector2 origin = data.transform.position + base.transform.right * base.transform.localPosition.x; + Vector2 direction = Vector2.down + vector; + float distance = legLenth * 1.5f * scale + vector.magnitude; + RaycastHit2D[] array = Physics2D.RaycastAll(origin, direction, distance, mask); + RaycastHit2D hit = default(RaycastHit2D); + for (int i = 0; i < array.Length; i++) + { + if (!(array[i].transform.root == data.transform) && (bool)array[i].transform) + { + if (!hit.transform) + { + hit = array[i]; + } + else if (array[i].distance < hit.distance) + { + hit = array[i]; + } + } + } + if ((bool)hit.transform) + { + HitGround(hit); + } + else + { + HitNothing(); + } + } + + private void HitNothing() + { + } + + private void HitGround(RaycastHit2D hit) + { + bool flag = false; + if (!raycastTransform && (bool)hit.transform) + { + flag = true; + } + if ((bool)raycastTransform && raycastTransform != hit.transform) + { + MigrateGroundHit(raycastTransform, hit.transform, hit); + } + raycastTransform = hit.transform; + raycastPosLocal = raycastTransform.InverseTransformPoint(hit.point); + if (flag) + { + Land(hit); + } + } + + private void MigrateGroundHit(Transform from, Transform to, RaycastHit2D hit) + { + } + + private void Land(RaycastHit2D hit) + { + EndStep(); + UpdatePreviousRayCastWorldPos(); + } + + private void UpdateRayCastWorldPos() + { + if ((bool)raycastTransform) + { + raycastPosWorld = raycastTransform.TransformPoint(raycastPosLocal); + } + } + + private void UpdatePreviousRayCastWorldPos() + { + if ((bool)previousRaycastTransform) + { + previousRaycastPosWorld = previousRaycastTransform.TransformPoint(previousRaycastPosLocal); + } + } + + private void UpdateMiscVariables() + { + scale = data.transform.localScale.x; + restPosition = (Vector2)data.transform.position + startOffset * 0.7f * scale; + } + + private void SetValuesFixed() + { + if ((bool)moveDeltaTransform) + { + deltaPos = Vector3.Lerp(deltaPos, (Vector2)moveDeltaTransform.position - lastPos, TimeHandler.deltaTime * 15f); + lastPos = moveDeltaTransform.position; + deltaPos.y = 0f; + } + } +} diff --git a/ROUNDS/Immunities.cs b/ROUNDS/Immunities.cs new file mode 100644 index 0000000..e35e4dd --- /dev/null +++ b/ROUNDS/Immunities.cs @@ -0,0 +1,15 @@ +public class Immunities +{ + public float time; + + public float dmg; + + public string name; + + public Immunities(float time, float dmg, string name) + { + this.time = time; + this.dmg = dmg; + this.name = name; + } +} diff --git a/ROUNDS/Implosion.cs b/ROUNDS/Implosion.cs new file mode 100644 index 0000000..080936a --- /dev/null +++ b/ROUNDS/Implosion.cs @@ -0,0 +1,39 @@ +using System; +using Photon.Pun; +using UnityEngine; + +public class Implosion : MonoBehaviour +{ + public float force; + + public float drag; + + public float time; + + public float clampDist; + + private void Start() + { + Explosion component = GetComponent<Explosion>(); + component.HitTargetAction = (Action<Damagable, float>)Delegate.Combine(component.HitTargetAction, new Action<Damagable, float>(HitTarget)); + clampDist *= base.transform.localScale.x; + force *= base.transform.localScale.x; + } + + public void HitTarget(Damagable damageble, float distance) + { + DoPull(damageble, distance); + } + + private void DoPull(Damagable damageble, float distance) + { + bool num = GetComponent<SpawnedAttack>().IsMine(); + HealthHandler component = damageble.GetComponent<HealthHandler>(); + CharacterData component2 = damageble.GetComponent<CharacterData>(); + _ = (Vector2)((base.transform.position - component.transform.position) * 0.25f); + if (num) + { + component2.view.RPC("RPCA_SendForceTowardsPointOverTime", RpcTarget.All, force, drag, clampDist, (Vector2)base.transform.position, time, 0, false, false); + } + } +} diff --git a/ROUNDS/InitPackage.cs b/ROUNDS/InitPackage.cs new file mode 100644 index 0000000..8014287 --- /dev/null +++ b/ROUNDS/InitPackage.cs @@ -0,0 +1,4 @@ +public class InitPackage +{ + public int currentMapID; +} diff --git a/ROUNDS/Irc/ChannelMessageEventArgs.cs b/ROUNDS/Irc/ChannelMessageEventArgs.cs new file mode 100644 index 0000000..389f9a1 --- /dev/null +++ b/ROUNDS/Irc/ChannelMessageEventArgs.cs @@ -0,0 +1,19 @@ +using System; + +namespace Irc; + +public class ChannelMessageEventArgs : EventArgs +{ + public string Channel { get; internal set; } + + public string From { get; internal set; } + + public string Message { get; internal set; } + + public ChannelMessageEventArgs(string Channel, string From, string Message) + { + this.Channel = Channel; + this.From = From; + this.Message = Message; + } +} diff --git a/ROUNDS/Irc/ExceptionEventArgs.cs b/ROUNDS/Irc/ExceptionEventArgs.cs new file mode 100644 index 0000000..efde0bb --- /dev/null +++ b/ROUNDS/Irc/ExceptionEventArgs.cs @@ -0,0 +1,18 @@ +using System; + +namespace Irc; + +public class ExceptionEventArgs : EventArgs +{ + public Exception Exception { get; internal set; } + + public ExceptionEventArgs(Exception x) + { + Exception = x; + } + + public override string ToString() + { + return Exception.ToString(); + } +} diff --git a/ROUNDS/Irc/StringEventArgs.cs b/ROUNDS/Irc/StringEventArgs.cs new file mode 100644 index 0000000..5c3c70f --- /dev/null +++ b/ROUNDS/Irc/StringEventArgs.cs @@ -0,0 +1,18 @@ +using System; + +namespace Irc; + +public class StringEventArgs : EventArgs +{ + public string Result { get; internal set; } + + public StringEventArgs(string s) + { + Result = s; + } + + public override string ToString() + { + return Result; + } +} diff --git a/ROUNDS/Irc/UpdateUsersEventArgs.cs b/ROUNDS/Irc/UpdateUsersEventArgs.cs new file mode 100644 index 0000000..9acc0a2 --- /dev/null +++ b/ROUNDS/Irc/UpdateUsersEventArgs.cs @@ -0,0 +1,16 @@ +using System; + +namespace Irc; + +public class UpdateUsersEventArgs : EventArgs +{ + public string Channel { get; internal set; } + + public string[] UserList { get; internal set; } + + public UpdateUsersEventArgs(string Channel, string[] UserList) + { + this.Channel = Channel; + this.UserList = UserList; + } +} diff --git a/ROUNDS/Irc/UserJoinedEventArgs.cs b/ROUNDS/Irc/UserJoinedEventArgs.cs new file mode 100644 index 0000000..b265bd1 --- /dev/null +++ b/ROUNDS/Irc/UserJoinedEventArgs.cs @@ -0,0 +1,16 @@ +using System; + +namespace Irc; + +public class UserJoinedEventArgs : EventArgs +{ + public string Channel { get; internal set; } + + public string User { get; internal set; } + + public UserJoinedEventArgs(string Channel, string User) + { + this.Channel = Channel; + this.User = User; + } +} diff --git a/ROUNDS/Irc/UserLeftEventArgs.cs b/ROUNDS/Irc/UserLeftEventArgs.cs new file mode 100644 index 0000000..7e5597b --- /dev/null +++ b/ROUNDS/Irc/UserLeftEventArgs.cs @@ -0,0 +1,16 @@ +using System; + +namespace Irc; + +public class UserLeftEventArgs : EventArgs +{ + public string Channel { get; internal set; } + + public string User { get; internal set; } + + public UserLeftEventArgs(string Channel, string User) + { + this.Channel = Channel; + this.User = User; + } +} diff --git a/ROUNDS/IsMineEvent.cs b/ROUNDS/IsMineEvent.cs new file mode 100644 index 0000000..11e2ce3 --- /dev/null +++ b/ROUNDS/IsMineEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class IsMineEvent : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/JustEvent.cs b/ROUNDS/JustEvent.cs new file mode 100644 index 0000000..2ca4c81 --- /dev/null +++ b/ROUNDS/JustEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class JustEvent : MonoBehaviour +{ + public UnityEvent justEvent; + + public void Go() + { + justEvent.Invoke(); + } +} diff --git a/ROUNDS/KillBox.cs b/ROUNDS/KillBox.cs new file mode 100644 index 0000000..eb69a56 --- /dev/null +++ b/ROUNDS/KillBox.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +public class KillBox : MonoBehaviour +{ + public bool alwaysOn; + + public float toggleTime = 0.3f; + + private float timeActivated = -10f; + + public bool readyToKill; + + private BoxCollider2D box; + + private void Start() + { + box = GetComponent<BoxCollider2D>(); + } + + private void Update() + { + readyToKill = timeActivated + toggleTime > Time.time; + if (!readyToKill) + { + return; + } + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + if (box.OverlapPoint(PlayerManager.instance.players[i].transform.position)) + { + PlayerManager.instance.players[i].data.healthHandler.TakeDamage(Vector2.up * 1000f, base.transform.position); + } + } + } + + public void Activate() + { + timeActivated = Time.time; + } +} diff --git a/ROUNDS/Landfall.AI/Evolver.cs b/ROUNDS/Landfall.AI/Evolver.cs new file mode 100644 index 0000000..89468ef --- /dev/null +++ b/ROUNDS/Landfall.AI/Evolver.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Landfall.AI; + +public class Evolver +{ + private float m_mutationRate = 0.1f; + + private int m_selectionSize = 5; + + private bool m_elitism = true; + + public Population Evolve(Population population) + { + Population population2 = new Population(population.Size, init: false); + int num = 0; + if (m_elitism) + { + num = population2.Size / 2; + population.Sort(); + for (int i = 0; i < num; i++) + { + Genome genome = population.GetGenome(i); + population2.SetGenome(i, genome); + genome.Fitness = 0f; + } + for (int j = 0; j < population2.Size / 2; j++) + { + population2.SetGenome(j + num, new Genome(population.GetGenome(j))); + } + } + else + { + for (int k = num; k < population2.Size; k++) + { + Genome parentA = Selection(population); + Genome parentB = Selection(population); + Genome g = Crossover(parentA, parentB); + population2.SetGenome(k, g); + } + } + for (int l = num; l < population2.Size; l++) + { + population2.GetGenome(l).Mutate(m_mutationRate); + } + return population2; + } + + public Genome Crossover(Genome parentA, Genome parentB) + { + Genome genome = new Genome(); + int num = Random.Range(0, parentA.Size - 1); + int num2 = Random.Range(0, parentA.Size - 1); + for (int i = 0; i < genome.Size; i++) + { + if (num < num2 && i > num && i < num2) + { + genome.SetGene(i, parentA.GetGene(i)); + } + else if (num > num2 && (i >= num || i <= num2)) + { + genome.SetGene(i, parentA.GetGene(i)); + } + else + { + genome.SetGene(i, parentB.GetGene(i)); + } + } + return genome; + } + + public Genome Selection(Population population) + { + List<Genome> list = new List<Genome>(m_selectionSize); + for (int i = 0; i < m_selectionSize; i++) + { + list.Add(population.GetGenome(i)); + } + Genome genome = list[0]; + for (int j = 0; j < m_selectionSize; j++) + { + Genome genome2 = population.GetGenome(j); + if (genome2.Fitness > genome.Fitness) + { + genome = genome2; + } + } + return genome; + } +} diff --git a/ROUNDS/Landfall.AI/Genome.cs b/ROUNDS/Landfall.AI/Genome.cs new file mode 100644 index 0000000..82404c3 --- /dev/null +++ b/ROUNDS/Landfall.AI/Genome.cs @@ -0,0 +1,86 @@ +using System; +using UnityEngine; + +namespace Landfall.AI; + +public class Genome +{ + private double[] m_genes; + + private float m_fitness; + + public double[] Genes + { + get + { + return m_genes; + } + set + { + m_genes = value; + } + } + + public float Fitness + { + get + { + return m_fitness; + } + set + { + m_fitness = value; + } + } + + public int Size => m_genes.Length; + + public Genome() + { + } + + public Genome(double[] genes) + { + SetGenes(genes); + } + + public Genome(Genome other) + { + m_genes = other.m_genes; + m_fitness = 0f; + } + + public void GenerateIndividual() + { + NeuralNet neuralNet = new NeuralNet(PlayerAIDavid.topology); + m_genes = neuralNet.GetWeights().ToArray(); + } + + public void Mutate(float mutationRate) + { + for (int i = 0; i < m_genes.Length; i++) + { + if (UnityEngine.Random.value < mutationRate) + { + System.Random r = new System.Random(); + m_genes[i] += r.NextGaussianDouble(); + } + } + } + + public double GetGene(int index) + { + return m_genes[index]; + } + + public void SetGene(int index, double value) + { + m_genes[index] = value; + m_fitness = 0f; + } + + public void SetGenes(double[] genes) + { + m_genes = genes; + } +} diff --git a/ROUNDS/Landfall.AI/NeuralNet.cs b/ROUNDS/Landfall.AI/NeuralNet.cs new file mode 100644 index 0000000..8007852 --- /dev/null +++ b/ROUNDS/Landfall.AI/NeuralNet.cs @@ -0,0 +1,115 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Landfall.AI; + +public class NeuralNet +{ + private Neuron[][] m_layers; + + private double m_bonusWeight = Random.Range(0.2f, 1f); + + public NeuralNet(int[] topology) + { + int num = topology.Length; + m_layers = new Neuron[num][]; + for (int i = 0; i < num; i++) + { + bool num2 = i == num - 1; + int num3 = topology[i]; + if (num2) + { + m_layers[i] = new Neuron[num3]; + } + else + { + m_layers[i] = new Neuron[num3 + 1]; + } + int numOutputs = ((!num2) ? topology[i + 1] : 0); + if (i < num - 1) + { + m_layers[i][num3] = new Neuron(topology[i + 1], num3); + m_layers[i][num3].OutputValue = 1.0; + } + for (int j = 0; j < num3; j++) + { + if (i == 0) + { + m_layers[i][j] = new Neuron(numOutputs, j); + } + else + { + m_layers[i][j] = new Neuron(numOutputs, j, m_layers[i - 1]); + } + } + } + } + + public void FeedForward(double[] inputValues, double bonusInput) + { + for (int i = 0; i < inputValues.Length; i++) + { + m_layers[0][i].OutputValue = inputValues[i]; + } + for (int j = 1; j < m_layers.Length; j++) + { + int num = ((j == m_layers.Length - 1) ? m_layers[j].Length : (m_layers[j].Length - 1)); + for (int k = 0; k < num; k++) + { + if (j == m_layers.Length - 1) + { + m_layers[j][k].FeedForward(bonusInput * m_bonusWeight); + } + else + { + m_layers[j][k].FeedForward(); + } + } + } + } + + public double[] GetResults() + { + double[] array = new double[m_layers[m_layers.Length - 1].Length]; + for (int i = 0; i < array.Length; i++) + { + array[i] = m_layers[m_layers.Length - 1][i].OutputValue; + } + return array; + } + + public List<double> GetWeights() + { + List<double> list = new List<double>(); + for (int i = 0; i < m_layers.Length; i++) + { + bool flag = i == m_layers.Length - 1; + for (int j = 0; j < m_layers[i].Length - ((!flag) ? 1 : 0); j++) + { + list.AddRange(m_layers[i][j].GetWeights()); + } + } + list.Add(m_bonusWeight); + return list; + } + + public void SetWeights(double[] weights) + { + SetWeights(new List<double>(weights)); + } + + public void SetWeights(List<double> weights) + { + int num = 0; + for (int i = 0; i < m_layers.Length; i++) + { + bool flag = i == m_layers.Length - 1; + int num2 = m_layers[i].Length - ((!flag) ? 1 : 0); + for (int j = 0; j < num2; j++) + { + num += m_layers[i][j].SetWeights(weights, num); + } + } + m_bonusWeight = weights[num]; + } +} diff --git a/ROUNDS/Landfall.AI/Neuron.cs b/ROUNDS/Landfall.AI/Neuron.cs new file mode 100644 index 0000000..2f24b57 --- /dev/null +++ b/ROUNDS/Landfall.AI/Neuron.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Landfall.AI; + +public class Neuron +{ + private class Connection + { + public double m_weight; + + public double m_deltaWeight; + } + + private static double _ETA = 0.15; + + private static double _ALPHA = 0.5; + + private double m_outputValue; + + private double m_gradient; + + private int m_index; + + private Dictionary<int, Connection> m_outputWeights = new Dictionary<int, Connection>(); + + private Neuron[] m_prevLayer; + + public double OutputValue + { + get + { + return m_outputValue; + } + set + { + m_outputValue = value; + } + } + + public Neuron(int numOutputs, int index, Neuron[] prevLayer) + : this(numOutputs, index) + { + m_prevLayer = prevLayer; + } + + public Neuron(int numOutputs, int index) + { + m_index = index; + for (int i = 0; i < numOutputs; i++) + { + Connection value = new Connection + { + m_weight = UnityEngine.Random.Range(-0.5f, 0.5f) + }; + m_outputWeights.Add(i, value); + } + } + + public void FeedForward() + { + double prevLayerSum = GetPrevLayerSum(); + m_outputValue = TransferFunction(prevLayerSum); + } + + public void FeedForward(double bonusInput) + { + double prevLayerSum = GetPrevLayerSum(); + prevLayerSum += bonusInput; + m_outputValue = TransferFunction(prevLayerSum); + } + + private double GetPrevLayerSum() + { + double num = 0.0; + if (m_prevLayer != null) + { + for (int i = 0; i < m_prevLayer.Length; i++) + { + Neuron neuron = m_prevLayer[i]; + num += neuron.OutputValue * neuron.m_outputWeights[m_index].m_weight; + } + } + return num; + } + + public List<double> GetWeights() + { + List<double> list = new List<double>(); + List<int> list2 = new List<int>(m_outputWeights.Keys); + list2.Sort(); + for (int i = 0; i < list2.Count; i++) + { + list.Add(m_outputWeights[list2[i]].m_weight); + } + return list; + } + + public int SetWeights(List<double> weights, int offset) + { + List<int> list = new List<int>(m_outputWeights.Keys); + list.Sort(); + for (int i = 0; i < list.Count; i++) + { + m_outputWeights[list[i]].m_weight = weights[offset + i]; + } + return list.Count; + } + + private static double TransferFunction(double x) + { + return Math.Tanh(x); + } + + private static double TransferFunctionDerivative(double x) + { + return 1.0 - x * x; + } +} diff --git a/ROUNDS/Landfall.AI/Population.cs b/ROUNDS/Landfall.AI/Population.cs new file mode 100644 index 0000000..a6617de --- /dev/null +++ b/ROUNDS/Landfall.AI/Population.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace Landfall.AI; + +public class Population +{ + private List<Genome> m_genomes = new List<Genome>(); + + public int Size => m_genomes.Count; + + public Population(int size) + : this(size, init: true) + { + } + + public Population(int size, bool init) + { + for (int i = 0; i < size; i++) + { + m_genomes.Add(null); + } + if (init) + { + for (int j = 0; j < size; j++) + { + Genome genome = new Genome(); + genome.GenerateIndividual(); + m_genomes[j] = genome; + } + } + } + + public Genome GetGenome(int index) + { + return m_genomes[index]; + } + + public Genome GetRandomGenome() + { + return m_genomes[Random.Range(0, m_genomes.Count)]; + } + + public void SetGenome(int index, Genome g) + { + m_genomes[index] = g; + } + + public Genome GetFittest() + { + Genome genome = m_genomes[0]; + for (int i = 1; i < m_genomes.Count; i++) + { + Genome genome2 = m_genomes[i]; + if (genome2.Fitness > genome.Fitness) + { + genome = genome2; + } + } + return genome; + } + + public void Sort() + { + m_genomes.OrderBy((Genome g) => g.Fitness); + } +} diff --git a/ROUNDS/Landfall.AI/WeightDataAsset.cs b/ROUNDS/Landfall.AI/WeightDataAsset.cs new file mode 100644 index 0000000..2671688 --- /dev/null +++ b/ROUNDS/Landfall.AI/WeightDataAsset.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Landfall.AI; + +[CreateAssetMenu(fileName = "WeightDataAsset", menuName = "Landfall/AI/Weight Data")] +public class WeightDataAsset : ScriptableObject +{ + [Serializable] + public struct WeightData + { + public double[] m_weights; + } + + public List<WeightData> m_weightDatas; + + public void Save() + { + } +} diff --git a/ROUNDS/Landfall.Network/ClientSteamLobby.cs b/ROUNDS/Landfall.Network/ClientSteamLobby.cs new file mode 100644 index 0000000..41f034d --- /dev/null +++ b/ROUNDS/Landfall.Network/ClientSteamLobby.cs @@ -0,0 +1,461 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Photon.Pun; +using Steamworks; + +namespace Landfall.Network; + +public class ClientSteamLobby +{ + private const string REGION_KEY = "RegionKey"; + + private const string ROOM_KEY = "RoomKey"; + + private const string GEAR_KEY = "GearKey"; + + private CallResult<LobbyEnter_t> m_OnLobbyEnteredCallresult; + + private CallResult<LobbyCreated_t> m_OnLobbyCreatedCallresult; + + private Callback<GameLobbyJoinRequested_t> m_OnLobbyJoinRequest; + + private Callback<LobbyInvite_t> m_OnInviteCallBack; + + private Callback<LobbyChatUpdate_t> m_OnLobbyUpdated; + + private Callback<LobbyDataUpdate_t> m_OnLobbyMemberDataUpdated; + + private Callback<LobbyChatMsg_t> m_OnLobbyChatMessage; + + private Action<string> m_OnLobbyCreatedActionString; + + private Action m_OnLobbyCreatedAction; + + private bool m_IsActive; + + private AppId_t ROUNDS_APPID = new AppId_t(1557740u); + + public bool IsMaster => SteamMatchmaking.GetLobbyOwner(CurrentLobby) == SteamUser.GetSteamID(); + + public bool IsInsideLobby + { + get + { + if (CurrentLobby.IsValid()) + { + return CurrentLobby.IsLobby(); + } + return false; + } + } + + public int NumberOfMembers + { + get + { + if (!m_IsActive) + { + return 0; + } + return SteamMatchmaking.GetNumLobbyMembers(CurrentLobby); + } + } + + public CSteamID CurrentLobby { get; private set; } + + public bool IsActive + { + get + { + return m_IsActive; + } + set + { + if (!SteamManager.Initialized) + { + m_IsActive = false; + } + else + { + m_IsActive = value; + } + } + } + + public ClientSteamLobby() + { + m_IsActive = SteamManager.Initialized; + if (m_IsActive) + { + CreateCallbacks(); + } + CurrentLobby = CSteamID.Nil; + CheckForCommandLine(); + } + + private void CheckForCommandLine() + { + string pszCommandLine; + int launchCommandLine = SteamApps.GetLaunchCommandLine(out pszCommandLine, 260); + if (pszCommandLine == null) + { + pszCommandLine = ""; + } + Debug.LogError("Command Line: ret: " + launchCommandLine + " : " + pszCommandLine); + } + + private void CreateCallbacks() + { + m_OnLobbyCreatedCallresult = CallResult<LobbyCreated_t>.Create(OnLobbyCreated); + m_OnLobbyEnteredCallresult = CallResult<LobbyEnter_t>.Create(OnLobbyEnter); + m_OnLobbyJoinRequest = Callback<GameLobbyJoinRequested_t>.Create(OnLobbyJoinRequest); + m_OnLobbyUpdated = Callback<LobbyChatUpdate_t>.Create(OnLobbyMembersUpdated); + m_OnLobbyMemberDataUpdated = Callback<LobbyDataUpdate_t>.Create(OnLobbyMemberDataUpdated); + m_OnLobbyChatMessage = Callback<LobbyChatMsg_t>.Create(OnLobbyChatMessage); + m_OnInviteCallBack = Callback<LobbyInvite_t>.Create(OnInviteToLobby); + } + + public void JoinedRoom(string roomName) + { + if (!m_IsActive) + { + return; + } + if (IsMaster) + { + byte[] roomData = GetRoomData(roomName); + Debug.Log("Joined room: " + roomName + " And is master!"); + if (SendDataThroughLobby(roomData)) + { + Debug.Log("Sent message to others in lobby about room"); + } + } + m_IsActive = false; + } + + private byte[] GetRequestStartGameData() + { + if (!m_IsActive) + { + return new byte[0]; + } + byte value = 3; + byte[] array = new byte[2]; + using MemoryStream output = new MemoryStream(array); + using BinaryWriter binaryWriter = new BinaryWriter(output); + binaryWriter.Write(value); + return array; + } + + private byte[] GetRoomData(string roomName) + { + if (!m_IsActive) + { + return new byte[0]; + } + byte value = 1; + byte[] array = new byte[2 * roomName.Length + 1]; + using MemoryStream output = new MemoryStream(array); + using BinaryWriter binaryWriter = new BinaryWriter(output); + binaryWriter.Write(value); + binaryWriter.Write(roomName); + return array; + } + + public void InviteFriend(CSteamID id) + { + bool flag = SteamMatchmaking.InviteUserToLobby(CurrentLobby, id); + Debug.Log(string.Concat("Sent invite to friend: ", id, flag ? " SUCCESS!" : " FAIL")); + } + + private bool SendDataThroughLobby(byte[] data) + { + return SteamMatchmaking.SendLobbyChatMsg(CurrentLobby, data, data.Length); + } + + public void ShowInviteScreenWhenConnected() + { + AddOnLobbyCreatedAction(delegate + { + Debug.Log("Activating SteamOverlay for INVITE: With Lobby: " + CurrentLobby); + SteamFriends.ActivateGameOverlayInviteDialog(CurrentLobby); + }); + } + + public void GetFriendsPlayingROUNDS(Action<List<CSteamID>> a) + { + List<CSteamID> list = new List<CSteamID>(); + for (int i = 0; i < NumberOfMembers; i++) + { + list.Add(SteamMatchmaking.GetLobbyMemberByIndex(CurrentLobby, i)); + } + List<CSteamID> list2 = new List<CSteamID>(); + int friendCount = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate); + for (int j = 0; j < friendCount; j++) + { + CSteamID friendByIndex = SteamFriends.GetFriendByIndex(j, EFriendFlags.k_EFriendFlagImmediate); + if (SteamFriends.GetFriendGamePlayed(friendByIndex, out var pFriendGameInfo) && pFriendGameInfo.m_gameID.AppID() == ROUNDS_APPID && !list.Contains(friendByIndex)) + { + Debug.Log("Friend: " + j + " : " + SteamFriends.GetFriendPersonaName(friendByIndex) + " Is playing ROUNDS!"); + list2.Add(friendByIndex); + } + } + a(list2); + } + + public void CreateLobby(int maxPlayers, Action<string> OnSuccess) + { + if (m_IsActive) + { + m_OnLobbyCreatedActionString = OnSuccess; + SteamAPICall_t hAPICall = SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypePrivate, maxPlayers); + m_OnLobbyCreatedCallresult.Set(hAPICall); + } + } + + private void AddOnLobbyCreatedAction(Action a) + { + m_OnLobbyCreatedAction = (Action)Delegate.Combine(m_OnLobbyCreatedAction, a); + } + + public void HideLobby() + { + if (m_IsActive && IsMaster) + { + SteamMatchmaking.SetLobbyJoinable(CurrentLobby, bLobbyJoinable: false); + } + } + + public void OpenLobby() + { + if (m_IsActive && IsMaster) + { + SteamMatchmaking.SetLobbyJoinable(CurrentLobby, bLobbyJoinable: true); + } + } + + private void JoinLobby(CSteamID lobbyID) + { + if (m_IsActive) + { + SteamAPICall_t hAPICall = SteamMatchmaking.JoinLobby(lobbyID); + m_OnLobbyEnteredCallresult.Set(hAPICall); + } + } + + private bool CheckAppVersion(CSteamID lobbyID) + { + throw new NotImplementedException(); + } + + private void LeaveCurrentLobby() + { + if (m_IsActive && CurrentLobby.IsLobby()) + { + SteamMatchmaking.LeaveLobby(CurrentLobby); + } + } + + public void GoOffline() + { + LeaveCurrentLobby(); + m_IsActive = false; + } + + public void LeaveLobby() + { + LeaveCurrentLobby(); + } + + public string[] GetPhotonIDsOfMembers() + { + if (!m_IsActive) + { + return new string[0]; + } + int numberOfMembers = NumberOfMembers; + string[] result = new string[numberOfMembers]; + Debug.Log("Reserving spots for : " + numberOfMembers + " Players!"); + for (int i = 0; i < numberOfMembers; i++) + { + string friendPersonaName = SteamFriends.GetFriendPersonaName(SteamMatchmaking.GetLobbyMemberByIndex(CurrentLobby, i)); + Debug.Log("Member: " + i + " : " + friendPersonaName); + } + return result; + } + + private void UpdateLobbyMembers() + { + if (m_IsActive) + { + Refresh(); + } + } + + private void UpdateLobbyData() + { + } + + public void Refresh() + { + } + + private void UpdateCurrentLobby(CSteamID lobbyID) + { + CurrentLobby = lobbyID; + } + + private void UpdateCurrentLobbyCallback() + { + } + + public void UpdateGear(string gearString) + { + if (m_IsActive) + { + SteamMatchmaking.SetLobbyMemberData(CurrentLobby, "GearKey", gearString); + } + } + + public void RequestStartGame() + { + throw new NotImplementedException(); + } + + public void ReadyUp(bool ready) + { + throw new NotImplementedException(); + } + + public void UpdateRegion() + { + throw new NotImplementedException(); + } + + public void UpdateMatchMode() + { + throw new NotImplementedException(); + } + + private void OnInviteToLobby(LobbyInvite_t param) + { + if (param.m_ulGameID == ROUNDS_APPID.m_AppId) + { + Debug.Log("Invite recieved from: " + param.m_ulSteamIDUser); + SteamFriends.GetFriendPersonaName(new CSteamID(param.m_ulSteamIDUser)); + } + } + + private void OnLobbyChatMessage(LobbyChatMsg_t param) + { + if (new CSteamID(param.m_ulSteamIDUser) == SteamUser.GetSteamID()) + { + Debug.Log("Recieving callback for local message, returning..."); + return; + } + if (new CSteamID(param.m_ulSteamIDLobby) != CurrentLobby) + { + Debug.LogError("Recieved lobby message for another lobby, returning..."); + return; + } + EChatEntryType eChatEntryType = (EChatEntryType)param.m_eChatEntryType; + if (eChatEntryType == EChatEntryType.k_EChatEntryTypeChatMsg) + { + int num = 60; + byte[] pvData = new byte[num]; + CSteamID pSteamIDUser; + EChatEntryType peChatEntryType; + int lobbyChatEntry = SteamMatchmaking.GetLobbyChatEntry(CurrentLobby, (int)param.m_iChatID, out pSteamIDUser, pvData, num, out peChatEntryType); + Debug.Log("Lobby Chsat Msg: " + lobbyChatEntry); + } + else + { + Debug.LogError("Recived unexpected lobbychat message: " + eChatEntryType); + } + } + + private void OnLobbyMembersUpdated(LobbyChatUpdate_t param) + { + _ = param.m_rgfChatMemberStateChange; + if (new CSteamID(param.m_ulSteamIDLobby) == CurrentLobby) + { + UpdateLobbyMembers(); + } + else + { + Debug.LogError("Getting update for another lobby!?"); + } + } + + private void OnLobbyMemberDataUpdated(LobbyDataUpdate_t param) + { + if (new CSteamID(param.m_ulSteamIDLobby) == CurrentLobby) + { + UpdateLobbyMembers(); + UpdateLobbyData(); + } + else + { + Debug.LogError("Getting Lobbychat update for another lobby!?"); + } + } + + private void OnLobbyJoinRequest(GameLobbyJoinRequested_t param) + { + Debug.Log("Lobby Join Request! " + param.m_steamIDLobby); + LeaveCurrentLobby(); + JoinLobby(param.m_steamIDLobby); + } + + private void OnLobbyCreated(LobbyCreated_t param, bool bIOFailure) + { + InternalOnLobbyCreated(param, bIOFailure, m_OnLobbyCreatedActionString); + } + + private void InternalOnLobbyCreated(LobbyCreated_t param, bool bIOFailure, Action<string> OnSuccess = null, Action OnFail = null) + { + if (bIOFailure) + { + Debug.LogError("BioFail"); + } + else if (param.m_eResult == EResult.k_EResultOK) + { + Debug.Log("Successfully created A steam Lobby"); + UpdateCurrentLobby(new CSteamID(param.m_ulSteamIDLobby)); + SteamMatchmaking.SetLobbyData(CurrentLobby, "RegionKey", PhotonNetwork.CloudRegion); + OnSuccess?.Invoke(param.m_ulSteamIDLobby.ToString()); + m_OnLobbyCreatedAction?.Invoke(); + ClearActions(); + } + else + { + Debug.Log("Failure creating A steam Lobby " + param.m_eResult); + } + } + + private void ClearActions() + { + m_OnLobbyCreatedAction = null; + m_OnLobbyCreatedActionString = null; + } + + private void OnLobbyEnter(LobbyEnter_t param, bool bIOFailure) + { + if (bIOFailure) + { + Debug.LogError("BioFail"); + } + else if (param.m_EChatRoomEnterResponse == 1) + { + Debug.Log("Successfully Entered A steam Lobby"); + CSteamID cSteamID = new CSteamID(param.m_ulSteamIDLobby); + UpdateCurrentLobby(cSteamID); + if (SteamManager.Initialized) + { + string lobbyData = SteamMatchmaking.GetLobbyData(cSteamID, "RegionKey"); + NetworkConnectionHandler.instance.ForceRegionJoin(lobbyData, cSteamID.ToString()); + } + } + } +} diff --git a/ROUNDS/Landfall.Network/SteamLobbyMessageType.cs b/ROUNDS/Landfall.Network/SteamLobbyMessageType.cs new file mode 100644 index 0000000..160ebff --- /dev/null +++ b/ROUNDS/Landfall.Network/SteamLobbyMessageType.cs @@ -0,0 +1,9 @@ +namespace Landfall.Network; + +public enum SteamLobbyMessageType : byte +{ + None, + JoinedRoom, + LeftRoom, + RequestStart +} diff --git a/ROUNDS/LeftRight.cs b/ROUNDS/LeftRight.cs new file mode 100644 index 0000000..d4777ee --- /dev/null +++ b/ROUNDS/LeftRight.cs @@ -0,0 +1,5 @@ +public enum LeftRight +{ + Left, + Right +} diff --git a/ROUNDS/LegRaycasters.cs b/ROUNDS/LegRaycasters.cs new file mode 100644 index 0000000..db676b0 --- /dev/null +++ b/ROUNDS/LegRaycasters.cs @@ -0,0 +1,77 @@ +using UnityEngine; + +public class LegRaycasters : MonoBehaviour +{ + public LayerMask mask; + + public float force; + + public float drag; + + public Transform[] legCastPositions; + + public AnimationCurve animationCurve; + + private PlayerVelocity rig; + + private CharacterData data; + + public AnimationCurve wobbleCurve; + + public AnimationCurve forceCurve; + + private IkLeg[] legs; + + private float totalStepTime; + + private void Awake() + { + legs = base.transform.root.GetComponentsInChildren<IkLeg>(); + } + + private void Start() + { + rig = GetComponentInParent<PlayerVelocity>(); + data = GetComponentInParent<CharacterData>(); + } + + private void FixedUpdate() + { + totalStepTime = 0f; + for (int i = 0; i < legs.Length; i++) + { + if (!legs[i].footDown) + { + totalStepTime += legs[i].stepTime; + } + } + for (int j = 0; j < legCastPositions.Length; j++) + { + RaycastHit2D[] array = Physics2D.RaycastAll(legCastPositions[j].transform.position + Vector3.up * 0.5f, Vector2.down, 1f * base.transform.root.localScale.x, mask); + for (int k = 0; k < array.Length; k++) + { + if ((bool)array[k].transform && array[k].transform.root != base.transform.root) + { + HitGround(legCastPositions[j], array[k]); + break; + } + } + } + } + + private void HitGround(Transform leg, RaycastHit2D hit) + { + if (!(data.sinceJump < 0.2f) && !(Vector3.Angle(Vector3.up, hit.normal) > 70f)) + { + data.TouchGround(hit.point, hit.normal, hit.rigidbody); + Vector3 vector = ((Vector3)hit.point - leg.transform.position) / base.transform.root.localScale.x; + if (data.input.direction.x != 0f) + { + vector.y += wobbleCurve.Evaluate(totalStepTime) * base.transform.root.localScale.x; + rig.AddForce(Vector3.up * forceCurve.Evaluate(totalStepTime) * rig.mass); + } + rig.AddForce(animationCurve.Evaluate(Mathf.Abs(vector.y)) * Vector3.up * rig.mass * force); + rig.AddForce(animationCurve.Evaluate(Mathf.Abs(vector.y)) * (0f - rig.velocity.y) * Vector2.up * rig.mass * drag); + } + } +} diff --git a/ROUNDS/LegRenderer.cs b/ROUNDS/LegRenderer.cs new file mode 100644 index 0000000..094b0c9 --- /dev/null +++ b/ROUNDS/LegRenderer.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using UnityEngine; + +public class LegRenderer : MonoBehaviour +{ + public Transform start; + + public Transform mid; + + public Transform end; + + public int segmentCount = 10; + + public GameObject segment; + + public float segmentLength = 1f; + + private List<Transform> segments = new List<Transform>(); + + private void Awake() + { + for (int i = 0; i < segmentCount; i++) + { + GameObject gameObject = Object.Instantiate(segment, base.transform); + gameObject.SetActive(value: true); + segments.Add(gameObject.transform); + if (i == segmentCount - 1) + { + gameObject.transform.localScale *= 0f; + } + } + } + + private void LateUpdate() + { + for (int i = 0; i < segments.Count; i++) + { + float t = (float)i / ((float)segments.Count - 1f); + _ = Vector3.zero; + if (i == 0) + { + _ = segments[i + 1].position - segments[i].position; + } + else if (i == segments.Count - 1) + { + _ = segments[i].position - segments[i - 1].position; + } + else + { + Vector3 vector = segments[i].position - segments[i - 1].position; + Vector3 vector2 = segments[i + 1].position - segments[i].position; + _ = (vector + vector2) * 0.5f; + } + segments[i].position = BezierCurve.QuadraticBezier(start.position, mid.position, end.position, t); + } + for (int j = 0; j < segments.Count; j++) + { + _ = (float)j / ((float)segments.Count - 1f); + Vector3 zero = Vector3.zero; + if (j == 0) + { + zero = segments[j + 1].position - segments[j].position; + } + else if (j == segments.Count - 1) + { + zero = segments[j].position - segments[j - 1].position; + } + else + { + Vector3 vector3 = segments[j].position - segments[j - 1].position; + Vector3 vector4 = segments[j + 1].position - segments[j].position; + zero = (vector3 + vector4) * 0.5f; + } + segments[j].rotation = Quaternion.LookRotation(Vector3.forward, zero); + } + } +} diff --git a/ROUNDS/LegRotator.cs b/ROUNDS/LegRotator.cs new file mode 100644 index 0000000..35e95b7 --- /dev/null +++ b/ROUNDS/LegRotator.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class LegRotator : MonoBehaviour +{ + private PlayerVelocity rig; + + private void Start() + { + rig = GetComponentInParent<PlayerVelocity>(); + } + + private void Update() + { + if ((bool)rig) + { + if (rig.velocity.x < 0f) + { + base.transform.localEulerAngles = Vector3.Lerp(base.transform.localEulerAngles, new Vector3(0f, 0f, 0f), TimeHandler.deltaTime * 15f * Mathf.Clamp(Mathf.Abs(rig.velocity.x), 0f, 1f)); + } + else + { + base.transform.localEulerAngles = Vector3.Lerp(base.transform.localEulerAngles, new Vector3(0f, 180f, 0f), TimeHandler.deltaTime * 15f * Mathf.Clamp(Mathf.Abs(rig.velocity.x), 0f, 1f)); + } + } + } +} diff --git a/ROUNDS/LerpBackToStartPos.cs b/ROUNDS/LerpBackToStartPos.cs new file mode 100644 index 0000000..cf73c0b --- /dev/null +++ b/ROUNDS/LerpBackToStartPos.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class LerpBackToStartPos : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/LevelMapper.cs b/ROUNDS/LevelMapper.cs new file mode 100644 index 0000000..63e1e06 --- /dev/null +++ b/ROUNDS/LevelMapper.cs @@ -0,0 +1,132 @@ +using System; +using UnityEngine; + +public class LevelMapper : MonoBehaviour +{ + private CharacterData data; + + private PlayerJump jump; + + private PlayerMovement movement; + + private bool isJumping; + + private bool isRunning; + + public GameObject node; + + public GameObject line; + + public GameObject line2; + + private Vector3 jumpPos; + + private Vector3 landPos; + + private Vector3 startRunPos; + + private Vector3 leaveGroundPos; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + jump = data.jump; + movement = data.movement; + PlayerJump playerJump = jump; + playerJump.JumpAction = (Action)Delegate.Combine(playerJump.JumpAction, new Action(Jump)); + CharacterData characterData = data; + characterData.TouchGroundAction = (Action<float, Vector3, Vector3, Transform>)Delegate.Combine(characterData.TouchGroundAction, new Action<float, Vector3, Vector3, Transform>(Ground)); + CharacterData characterData2 = data; + characterData2.TouchWallAction = (Action<float, Vector3, Vector3>)Delegate.Combine(characterData2.TouchWallAction, new Action<float, Vector3, Vector3>(Wall)); + } + + private void Update() + { + if (!data.isGrounded) + { + LeaveGround(); + } + } + + private void Jump() + { + isJumping = true; + jumpPos = base.transform.position; + } + + private void Wall(float sinceWall, Vector3 pos, Vector3 normal) + { + if (!data.isWallGrab) + { + if (data.sinceJump < 0.1f) + { + isJumping = false; + } + else + { + Land(); + } + } + } + + private void Ground(float sinceGround, Vector3 pos, Vector3 groundNormal, Transform groundTransform = null) + { + if (!isRunning) + { + startRunPos = pos; + isRunning = true; + } + if (!data.isGrounded) + { + if (data.sinceJump < 0.1f) + { + isJumping = false; + } + else + { + Land(); + } + } + } + + private void Land() + { + landPos = base.transform.position; + if (Vector3.Distance(landPos, jumpPos) > 3f && isJumping) + { + SaveJump(); + } + isJumping = false; + } + + private void LeaveGround() + { + if (isRunning) + { + leaveGroundPos = data.groundPos; + SaveRun(); + isRunning = false; + } + } + + private void SaveJump() + { + UnityEngine.Object.Instantiate(node, jumpPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.green; + UnityEngine.Object.Instantiate(node, landPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.red; + LineRenderer component = UnityEngine.Object.Instantiate(line, Vector3.zero, Quaternion.identity).GetComponent<LineRenderer>(); + component.SetPosition(0, jumpPos); + component.SetPosition(1, landPos); + } + + private void SaveRun() + { + if (!(Vector3.Distance(startRunPos, jumpPos) < 2f)) + { + UnityEngine.Object.Instantiate(node, startRunPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.blue; + UnityEngine.Object.Instantiate(node, leaveGroundPos, Quaternion.identity).GetComponent<SpriteRenderer>().color = Color.blue; + LineRenderer component = UnityEngine.Object.Instantiate(line2, Vector3.zero, Quaternion.identity).GetComponent<LineRenderer>(); + component.SetPosition(0, startRunPos); + component.SetPosition(1, leaveGroundPos); + } + } +} diff --git a/ROUNDS/LevelScale.cs b/ROUNDS/LevelScale.cs new file mode 100644 index 0000000..39969ca --- /dev/null +++ b/ROUNDS/LevelScale.cs @@ -0,0 +1,45 @@ +using System; +using UnityEngine; + +public class LevelScale : MonoBehaviour +{ + public bool onLevelUp = true; + + public bool onStart; + + private AttackLevel level; + + private Vector3 startScale; + + private bool inited; + + private void Init() + { + if (!inited) + { + inited = true; + startScale = base.transform.localScale; + } + } + + private void Start() + { + Init(); + level = GetComponent<AttackLevel>(); + if (onStart) + { + base.transform.localScale *= level.LevelScale(); + } + if (onLevelUp) + { + AttackLevel attackLevel = level; + attackLevel.LevelUpAction = (Action<int>)Delegate.Combine(attackLevel.LevelUpAction, new Action<int>(LevelUp)); + } + } + + public void LevelUp(int lvl) + { + Init(); + base.transform.localScale = startScale * level.LevelScale(); + } +} diff --git a/ROUNDS/LifeSteal.cs b/ROUNDS/LifeSteal.cs new file mode 100644 index 0000000..6608cdb --- /dev/null +++ b/ROUNDS/LifeSteal.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class LifeSteal : DealtDamageEffect +{ + private HealthHandler health; + + public float multiplier; + + public override void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null) + { + if (!selfDamage) + { + if (!health) + { + health = GetComponentInParent<HealthHandler>(); + } + health.Heal(damage.magnitude * multiplier); + } + } +} diff --git a/ROUNDS/LineEffect.cs b/ROUNDS/LineEffect.cs new file mode 100644 index 0000000..ee2cd03 --- /dev/null +++ b/ROUNDS/LineEffect.cs @@ -0,0 +1,454 @@ +using System; +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; + +public class LineEffect : MonoBehaviour +{ + public enum LineType + { + Line, + Ring + } + + public enum AnimType + { + Width, + Offset + } + + public bool playOnAwake; + + public bool loop; + + public LineType lineType; + + public int segments = 20; + + public float globalTimeSpeed = 1f; + + public bool raycastCollision; + + [FoldoutGroup("Animation", 0)] + public AnimationCurve lineWidthOverTimeCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [Space(10f)] + [FoldoutGroup("Animation", 0)] + public bool useColorOverTime; + + [FoldoutGroup("Animation", 0)] + [ShowIf("useColorOverTime", true)] + public Gradient colorOverTime; + + [Space(10f)] + [FoldoutGroup("Animation", 0)] + [ShowIf("lineType", LineType.Ring, true)] + public float radius = 5f; + + [FoldoutGroup("Animation", 0)] + [ShowIf("lineType", LineType.Ring, true)] + public AnimationCurve radiusOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [Space(10f)] + [FoldoutGroup("Special", 0)] + public float inheritScaleFactor; + + [Space(10f)] + public LineEffectInstance[] effects; + + private LineRenderer line; + + [HideInInspector] + public float counter; + + private float startWidth; + + [HideInInspector] + public float currentWidth; + + [FoldoutGroup("Debug", 0)] + public bool debug; + + [FoldoutGroup("Debug", 0)] + public Transform fromPos; + + [FoldoutGroup("Debug", 0)] + public Transform toPos; + + [FoldoutGroup("Debug", 0)] + public Transform bezierPos; + + [HideInInspector] + public float offsetMultiplier = 1f; + + [HideInInspector] + public float widthMultiplier = 1f; + + private float scaleMultiplier = 1f; + + private bool inited; + + public bool isPlaying; + + private Coroutine widthAnim; + + private Coroutine offsetAnim; + + private void Start() + { + globalTimeSpeed *= UnityEngine.Random.Range(0.95f, 1.05f); + } + + private void OnEnable() + { + if (!inited) + { + Init(); + } + if (playOnAwake && lineType == LineType.Ring) + { + Play(base.transform); + } + } + + private void Init() + { + if (!inited) + { + line = GetComponent<LineRenderer>(); + line.positionCount = segments; + line.useWorldSpace = true; + startWidth = line.widthMultiplier; + inited = true; + scaleMultiplier = 1f - inheritScaleFactor + base.transform.lossyScale.x * inheritScaleFactor; + } + } + + private void Update() + { + if (!debug) + { + return; + } + if (lineType == LineType.Line && (bool)fromPos && (bool)toPos) + { + if ((bool)bezierPos) + { + DrawLine(fromPos.position, toPos.position, bezierPos.position); + } + else + { + DrawLine(fromPos.position, toPos.position); + } + } + if (lineType == LineType.Ring && (bool)fromPos) + { + DrawLine(fromPos.position, Vector3.zero); + } + } + + public void StartDraw() + { + if (!base.gameObject.activeSelf) + { + base.gameObject.SetActive(value: true); + } + counter = 0f; + } + + public void DrawLine(Vector3 start, Vector3 end) + { + DrawLine(start, end, Vector3.one * 100f); + } + + public void DrawLine(Vector3 start, Vector3 end, Vector3 bezier) + { + Init(); + Vector3 vector = Vector3.zero; + for (int i = 0; i < line.positionCount; i++) + { + float num = 0f; + for (int j = 0; j < effects.Length; j++) + { + if (!effects[j].active) + { + continue; + } + float num2 = 0f; + float num3 = (float)i / ((float)line.positionCount - 1f); + float time = num3; + float num4 = effects[j].mainCurveTiling; + if (effects[j].tilingPerMeter) + { + if (lineType == LineType.Line) + { + num4 *= (start - end).magnitude; + } + if (lineType == LineType.Ring) + { + num4 *= radius; + } + } + num3 *= num4; + if (effects[j].mainCurveScrollSpeed > 0f) + { + num3 += effects[j].mainCurveScrollSpeed * Time.unscaledTime; + } + if (effects[j].mainCurveScrollSpeed < 0f) + { + num3 += (0f - effects[j].mainCurveScrollSpeed) * (100000f - Time.unscaledTime); + } + num3 %= 1f; + num2 = effects[j].mainCurve.Evaluate(num3); + num2 *= effects[j].mainCurveMultiplier; + num2 *= effects[j].effectOverLineCurve.Evaluate(time); + num2 *= effects[j].effectOverTimeCurve.Evaluate(counter); + if (effects[j].curveType == LineEffectInstance.CurveType.Add) + { + num += num2; + } + else if (effects[j].curveType == LineEffectInstance.CurveType.Multiply) + { + num *= num2; + } + } + float t = (float)i / ((float)line.positionCount - 1f); + Vector3 vector2 = Vector3.zero; + Vector3 vector3 = Vector3.zero; + if (lineType == LineType.Ring) + { + float f = (float)Math.PI / 180f * ((float)i * 360f / (float)(segments - 1)); + vector2 = start + new Vector3(Mathf.Sin(f) * (radius * base.transform.root.localScale.x * radiusOverTime.Evaluate(counter)), Mathf.Cos(f) * (radius * base.transform.root.localScale.x * radiusOverTime.Evaluate(counter)), 0f); + vector3 = ((!(vector != Vector3.zero)) ? Vector3.up : Vector3.Cross(Vector3.forward, vector2 - vector).normalized); + } + if (lineType == LineType.Line) + { + vector2 = Vector3.Lerp(start, end, t); + vector3 = Vector3.Cross(start - end, Vector3.forward).normalized; + if (bezier != Vector3.one * 100f) + { + vector2 = BezierCurve.QuadraticBezier(start, bezier, end, t); + } + } + vector = vector2; + line.SetPosition(i, vector2 + vector3 * num * offsetMultiplier); + } + if (raycastCollision) + { + RaycastPositions(); + } + if (lineType == LineType.Ring) + { + SmoothSeam(); + } + line.widthMultiplier = lineWidthOverTimeCurve.Evaluate(counter) * startWidth * scaleMultiplier * widthMultiplier; + currentWidth = line.widthMultiplier; + if (useColorOverTime) + { + line.startColor = colorOverTime.Evaluate(counter); + line.endColor = colorOverTime.Evaluate(counter); + } + counter += Time.unscaledDeltaTime * globalTimeSpeed; + if (counter > 1f) + { + if (debug || loop) + { + StartDraw(); + } + else + { + base.gameObject.SetActive(value: false); + } + } + } + + private void RaycastPositions() + { + for (int i = 0; i < line.positionCount; i++) + { + line.SetPosition(i, PhysicsFunctions.ObstructionPoint(base.transform.position, line.GetPosition(i))); + } + } + + private void SmoothSeam() + { + float num = 0.1f; + Vector3 b = (line.GetPosition(0) + line.GetPosition(line.positionCount - 1)) * 0.5f; + for (int i = 0; i < line.positionCount; i++) + { + float num2 = (float)i / ((float)line.positionCount - 1f); + _ = Vector3.zero; + Vector3 zero = Vector3.zero; + Vector3 position = line.GetPosition(i); + float t; + if (num2 > 0.5f) + { + t = Mathf.Clamp((num2 - (1f - num)) / num, 0f, 1f); + } + else + { + t = Mathf.Clamp(num2 * (1f / num), 0f, 1f); + t = 1f - t; + } + zero = Vector3.Lerp(position, b, t) - position; + zero.x *= 0.5f; + line.SetPosition(i, position + zero); + } + line.SetPosition(1, new Vector3(line.GetPosition(1).x, b.y)); + line.SetPosition(line.positionCount - 2, new Vector3(line.GetPosition(line.positionCount - 2).x, b.y)); + } + + public void Stop() + { + StopAllCoroutines(); + if (!loop) + { + base.gameObject.SetActive(value: false); + } + } + + public void Play() + { + Play(base.transform); + } + + private void OnDisable() + { + Stop(); + } + + public void ResetMultipliers() + { + offsetMultiplier = 1f; + scaleMultiplier = 1f; + widthMultiplier = 1f; + } + + public void Play(Transform fromTransform, Transform toTransform, float bezierOffset = 0f) + { + StartDraw(); + StopAllCoroutines(); + StartCoroutine(DoPlay(fromTransform, toTransform, bezierOffset)); + } + + private IEnumerator DoPlay(Transform fromTransform, Transform toTransform, float bezierOffset = 0f) + { + isPlaying = true; + Vector3 currentBez = Vector3.zero; + while (base.gameObject.activeSelf && (bool)fromTransform && (bool)toTransform) + { + if (bezierOffset != 0f) + { + float num = 1f; + if (toTransform.position.x < fromTransform.position.x) + { + num = -1f; + } + Vector3 vector = Vector3.Cross(Vector3.forward, toTransform.position - fromTransform.position).normalized * bezierOffset * num; + currentBez = ((!(currentBez == Vector3.zero)) ? Vector3.Lerp(currentBez, vector, TimeHandler.deltaTime * 5f) : vector); + Vector3 bezier = currentBez + (fromTransform.position + toTransform.position) * 0.5f; + DrawLine(fromTransform.position, toTransform.position, bezier); + } + else + { + DrawLine(fromTransform.position, toTransform.position); + } + yield return null; + } + isPlaying = false; + } + + public void Play(Transform fromTransform, Vector3 toPosition, float bezierOffset = 0f) + { + StartDraw(); + StopAllCoroutines(); + StartCoroutine(DoPlay(fromTransform, toPosition, bezierOffset)); + } + + private IEnumerator DoPlay(Transform fromTransform, Vector3 toPosition, float bezierOffset = 0f) + { + Vector3 currentBezOffset = Vector3.zero; + while (base.gameObject.activeSelf && (bool)fromTransform) + { + if (bezierOffset != 0f) + { + float num = 1f; + if (toPosition.x < fromTransform.position.x) + { + num = -1f; + } + Vector3 vector = Vector3.Cross(Vector3.forward, toPosition - fromTransform.position).normalized * bezierOffset * num; + currentBezOffset = ((!(currentBezOffset == Vector3.zero)) ? Vector3.Lerp(currentBezOffset, vector, TimeHandler.deltaTime * 2f) : vector); + _ = currentBezOffset + (fromTransform.position + toPosition) * 0.5f; + Vector3 bezier = (fromTransform.position + toPosition) * 0.5f; + DrawLine(fromTransform.position, toPosition, bezier); + } + else + { + DrawLine(fromTransform.position, toPosition); + } + yield return null; + } + } + + public void Play(Transform fromTransform) + { + StartDraw(); + StopAllCoroutines(); + StartCoroutine(DoPlay(fromTransform)); + } + + private IEnumerator DoPlay(Transform fromTransform) + { + while (base.gameObject.activeSelf && (bool)fromTransform) + { + DrawLine(fromTransform.position, Vector3.zero); + yield return null; + } + } + + public void PlayAnim(AnimType animType, AnimationCurve curve, float speed = 1f) + { + if (animType == AnimType.Offset && offsetAnim != null) + { + StopCoroutine(offsetAnim); + } + if (animType == AnimType.Width && widthAnim != null) + { + StopCoroutine(widthAnim); + } + Coroutine coroutine = StartCoroutine(DoPlayAnim(animType, curve, speed)); + if (animType == AnimType.Offset) + { + offsetAnim = coroutine; + } + if (animType == AnimType.Width) + { + widthAnim = coroutine; + } + } + + private IEnumerator DoPlayAnim(AnimType animType, AnimationCurve curve, float speed = 1f) + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + if (animType == AnimType.Offset) + { + offsetMultiplier = curve.Evaluate(c); + } + if (animType == AnimType.Width) + { + widthMultiplier = curve.Evaluate(c); + } + c += TimeHandler.deltaTime * speed; + yield return null; + } + } + + internal float GetRadius() + { + return radius * base.transform.root.localScale.x * radiusOverTime.Evaluate(counter); + } +} diff --git a/ROUNDS/LineEffectExplosionModifier.cs b/ROUNDS/LineEffectExplosionModifier.cs new file mode 100644 index 0000000..3f1c66b --- /dev/null +++ b/ROUNDS/LineEffectExplosionModifier.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using UnityEngine; + +public class LineEffectExplosionModifier : MonoBehaviour +{ + public AnimationCurve curve; + + public float speed = 1f; + + private LineEffect effect; + + private Coroutine corutine; + + private void Start() + { + effect = GetComponent<LineEffect>(); + Explosion componentInParent = GetComponentInParent<Explosion>(); + componentInParent.DealDamageAction = (Action<Damagable>)Delegate.Combine(componentInParent.DealDamageAction, new Action<Damagable>(DealDamage)); + Explosion componentInParent2 = GetComponentInParent<Explosion>(); + componentInParent2.DealHealAction = (Action<Damagable>)Delegate.Combine(componentInParent2.DealHealAction, new Action<Damagable>(DealDamage)); + } + + public void DealDamage(Damagable damagable) + { + if (corutine != null) + { + StopCoroutine(corutine); + } + corutine = StartCoroutine(DoCurve()); + } + + private IEnumerator DoCurve() + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + effect.offsetMultiplier = curve.Evaluate(c); + c += TimeHandler.deltaTime * speed; + yield return null; + } + } +} diff --git a/ROUNDS/LineEffectInstance.cs b/ROUNDS/LineEffectInstance.cs new file mode 100644 index 0000000..a154130 --- /dev/null +++ b/ROUNDS/LineEffectInstance.cs @@ -0,0 +1,40 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; + +[Serializable] +public class LineEffectInstance +{ + public enum CurveType + { + Add, + Multiply + } + + [Space(20f)] + public bool active = true; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public CurveType curveType; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public AnimationCurve mainCurve = AnimationCurve.Linear(0f, 0f, 1f, 0f); + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public float mainCurveMultiplier = 1f; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public float mainCurveTiling = 1f; + + [FoldoutGroup("Main Curve", 0, Order = 0, Expanded = true)] + public bool tilingPerMeter = true; + + [FoldoutGroup("Modifiers", 0)] + public AnimationCurve effectOverLineCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + [FoldoutGroup("Animation", 0)] + public float mainCurveScrollSpeed; + + [FoldoutGroup("Animation", 0)] + public AnimationCurve effectOverTimeCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f); +} diff --git a/ROUNDS/LineOfSightTrigger.cs b/ROUNDS/LineOfSightTrigger.cs new file mode 100644 index 0000000..99fca28 --- /dev/null +++ b/ROUNDS/LineOfSightTrigger.cs @@ -0,0 +1,59 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class LineOfSightTrigger : MonoBehaviour +{ + public UnityEvent turnOnEvent; + + public UnityEvent turnOffEvent; + + public UnityEvent switchTargetEvent; + + public Action<Player> turnOnAction; + + public Action<Player> switchTargetAction; + + public Action turnOffAction; + + private Player player; + + private bool isOn; + + private Player currentTarget; + + private void Start() + { + player = GetComponentInParent<Player>(); + } + + private void Update() + { + Player closestPlayerInTeam = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(player.teamID)); + if ((bool)closestPlayerInTeam) + { + if (currentTarget != player) + { + switchTargetEvent.Invoke(); + switchTargetAction?.Invoke(player); + currentTarget = closestPlayerInTeam; + } + if (!isOn) + { + isOn = true; + turnOnAction?.Invoke(player); + turnOnEvent.Invoke(); + } + } + else + { + if (isOn) + { + isOn = false; + turnOffAction?.Invoke(); + turnOffEvent.Invoke(); + } + currentTarget = null; + } + } +} diff --git a/ROUNDS/LineRangeEffect.cs b/ROUNDS/LineRangeEffect.cs new file mode 100644 index 0000000..6671fcc --- /dev/null +++ b/ROUNDS/LineRangeEffect.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +public class LineRangeEffect : MonoBehaviour +{ + public float dmg; + + public float knockback; + + private LineEffect lineEffect; + + private Player owner; + + private SpawnedAttack spawned; + + private bool done; + + private void Start() + { + spawned = GetComponent<SpawnedAttack>(); + owner = GetComponent<SpawnedAttack>().spawner; + lineEffect = GetComponentInChildren<LineEffect>(); + } + + private void Update() + { + if (done || !spawned.IsMine()) + { + return; + } + Player closestPlayerInTeam = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(owner.teamID), needVision: true); + if ((bool)closestPlayerInTeam) + { + float num = 2f; + float radius = lineEffect.GetRadius(); + float num2 = Vector2.Distance(base.transform.position, closestPlayerInTeam.transform.position); + if (num2 < radius + num && num2 > radius - num) + { + done = true; + closestPlayerInTeam.data.healthHandler.CallTakeDamage(dmg * base.transform.localScale.x * (closestPlayerInTeam.transform.position - base.transform.position).normalized, closestPlayerInTeam.transform.position, null, owner); + closestPlayerInTeam.data.healthHandler.CallTakeForce(knockback * base.transform.localScale.x * (closestPlayerInTeam.transform.position - base.transform.position).normalized); + } + } + } +} diff --git a/ROUNDS/ListMenu.cs b/ROUNDS/ListMenu.cs new file mode 100644 index 0000000..1ed98f6 --- /dev/null +++ b/ROUNDS/ListMenu.cs @@ -0,0 +1,136 @@ +using System.Collections; +using SoundImplementation; +using UnityEngine; +using UnityEngine.EventSystems; + +public class ListMenu : MonoBehaviour +{ + [Header("Settings")] + public GameObject bar; + + [Header("Settings")] + public GameObject particle; + + public ListMenuButton selectedButton; + + public ListMenuPage selectedPage; + + public static ListMenu instance; + + public GameObject menuCanvas; + + private bool isActive = true; + + private Vector3 lastPos; + + private bool playButtonHoverFirst = true; + + private void Awake() + { + instance = this; + } + + private void Start() + { + GetComponentInChildren<ListMenuPage>(includeInactive: true).Open(); + } + + private void Update() + { + if ((lastPos - bar.transform.position).sqrMagnitude > 0.5f && (MainMenuHandler.instance.isOpen || EscapeMenuHandler.isEscMenu)) + { + if (!playButtonHoverFirst) + { + SoundPlayerStatic.Instance.PlayButtonHover(); + } + else + { + playButtonHoverFirst = false; + } + } + lastPos = bar.transform.position; + if ((bool)selectedButton && EventSystem.current.currentSelectedGameObject == null) + { + EventSystem.current.SetSelectedGameObject(selectedButton.gameObject); + } + if (EscapeMenuHandler.isEscMenu || menuCanvas.activeInHierarchy) + { + if (!bar.activeSelf) + { + bar.SetActive(value: true); + particle.SetActive(value: true); + } + } + else if (bar.activeSelf) + { + bar.SetActive(value: false); + particle.SetActive(value: false); + } + } + + internal void DeselectButton() + { + if ((bool)selectedButton) + { + selectedButton.Deselect(); + } + } + + public void OpenPage(ListMenuPage pageToOpen) + { + if ((bool)selectedPage) + { + selectedPage.Close(); + } + bar.transform.localScale = new Vector3(bar.transform.localScale.x, pageToOpen.barHeight, 1f); + selectedPage = pageToOpen; + if (MenuControllerHandler.menuControl == MenuControllerHandler.MenuControl.Controller) + { + SelectButton(selectedPage.firstSelected); + } + else + { + bar.transform.position = Vector3.up * 10000f; + } + } + + public void SelectButton(ListMenuButton buttonToSelect) + { + if (!buttonToSelect || buttonToSelect.hideBar) + { + bar.transform.position = Vector3.up * 10000f; + } + else + { + StartCoroutine(ISelectButton(buttonToSelect)); + } + } + + public IEnumerator ISelectButton(ListMenuButton buttonToSelect) + { + if ((bool)selectedButton) + { + selectedButton.Deselect(); + } + yield return new WaitForEndOfFrame(); + buttonToSelect.Select(); + selectedButton = buttonToSelect; + bar.transform.position = buttonToSelect.transform.position; + if (EventSystem.current.currentSelectedGameObject != selectedButton.gameObject) + { + EventSystem.current.SetSelectedGameObject(selectedButton.gameObject); + } + if (buttonToSelect.setBarHeight != 0f) + { + bar.transform.localScale = new Vector3(bar.transform.localScale.x, buttonToSelect.setBarHeight, 1f); + } + } + + public void ClearBar() + { + if (MenuControllerHandler.menuControl != 0) + { + bar.transform.position = Vector3.up * 10000f; + } + } +} diff --git a/ROUNDS/ListMenuButton.cs b/ROUNDS/ListMenuButton.cs new file mode 100644 index 0000000..b208a12 --- /dev/null +++ b/ROUNDS/ListMenuButton.cs @@ -0,0 +1,102 @@ +using SoundImplementation; +using TMPro; +using UnityEngine; +using UnityEngine.EventSystems; + +public class ListMenuButton : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler, IUpdateSelectedHandler, ISelectHandler +{ + private TextMeshProUGUI text; + + private Color defaultColor; + + private Vector3 defaultPos; + + public bool changeFontSize = true; + + public bool hideBar; + + public float setBarHeight; + + public bool toggleTextColor; + + public Color selectedTextColor; + + public Color defaultTextColor; + + private float smallFont = 40f; + + private bool inited; + + private void Awake() + { + } + + private void Start() + { + Init(); + smallFont = text.fontSize; + defaultPos = text.transform.localPosition; + defaultColor = text.color; + } + + public void Nope() + { + Init(); + MenuEffects.instance.BlinkInColor(text, MenuEffects.instance.nopeColor, defaultColor, 0.15f); + MenuEffects.instance.ShakeObject(text.gameObject, defaultPos, 15f, 0.2f); + } + + public void Deselect() + { + Init(); + text.fontStyle = FontStyles.Normal; + _ = changeFontSize; + if (toggleTextColor) + { + GetComponentInChildren<TextMeshProUGUI>().color = defaultTextColor; + } + } + + public void Select() + { + Init(); + text.fontStyle = FontStyles.Bold; + _ = changeFontSize; + if (toggleTextColor) + { + GetComponentInChildren<TextMeshProUGUI>().color = selectedTextColor; + } + } + + public void OnPointerClick(PointerEventData eventData) + { + SoundPlayerStatic.Instance.PlayButtonClick(); + } + + public void OnPointerEnter(PointerEventData eventData) + { + ListMenu.instance.SelectButton(this); + } + + public void OnPointerExit(PointerEventData eventData) + { + } + + public void OnUpdateSelected(BaseEventData eventData) + { + } + + public void OnSelect(BaseEventData eventData) + { + ListMenu.instance.SelectButton(this); + } + + private void Init() + { + if (!inited) + { + inited = true; + text = GetComponentInChildren<TextMeshProUGUI>(); + } + } +} diff --git a/ROUNDS/ListMenuPage.cs b/ROUNDS/ListMenuPage.cs new file mode 100644 index 0000000..e4735b4 --- /dev/null +++ b/ROUNDS/ListMenuPage.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +public class ListMenuPage : MonoBehaviour +{ + public ListMenuButton firstSelected; + + public float barHeight = 92f; + + private GameObject grid; + + private void Awake() + { + grid = base.transform.GetChild(0).gameObject; + } + + public void Open() + { + ListMenu.instance.OpenPage(this); + grid.SetActive(value: true); + } + + public void Close() + { + DeselectAll(); + grid.SetActive(value: false); + } + + private void DeselectAll() + { + ListMenuButton[] componentsInChildren = GetComponentsInChildren<ListMenuButton>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].Deselect(); + } + } +} diff --git a/ROUNDS/LoadingScreen.cs b/ROUNDS/LoadingScreen.cs new file mode 100644 index 0000000..72d65fd --- /dev/null +++ b/ROUNDS/LoadingScreen.cs @@ -0,0 +1,81 @@ +using System.Collections; +using SoundImplementation; +using TMPro; +using UnityEngine; + +public class LoadingScreen : MonoBehaviour +{ + private const string SEARCHING_TEXT = "SEARCHING"; + + private const string SEARCHING_PRIVATE_TEXT = "WAITING FOR FRIEND"; + + [SerializeField] + private TextMeshProUGUI m_SearchingText; + + public GameObject gameMode; + + public GeneralParticleSystem searchingSystem; + + public GeneralParticleSystem matchFoundSystem; + + public GeneralParticleSystem[] playerNamesSystem; + + public float matchFoundTime = 0.5f; + + public float playerNameTime = 2f; + + public static LoadingScreen instance; + + private void Awake() + { + instance = this; + } + + public void StartLoading(bool privateGame = false) + { + StopAllCoroutines(); + matchFoundSystem.Stop(); + for (int i = 0; i < playerNamesSystem.Length; i++) + { + playerNamesSystem[i].Stop(); + } + searchingSystem.Play(); + m_SearchingText.text = GetSearchingString(privateGame); + } + + private string GetSearchingString(bool privGame) + { + if (privGame) + { + return "WAITING FOR FRIEND"; + } + return "SEARCHING"; + } + + private IEnumerator IDoLoading() + { + SoundPlayerStatic.Instance.PlayMatchFound(); + matchFoundSystem.Play(); + yield return new WaitForSeconds(matchFoundTime); + matchFoundSystem.Stop(); + GetComponentInChildren<DisplayMatchPlayerNames>().ShowNames(); + for (int i = 0; i < playerNamesSystem.Length; i++) + { + playerNamesSystem[i].Play(); + } + yield return new WaitForSeconds(playerNameTime); + for (int j = 0; j < playerNamesSystem.Length; j++) + { + playerNamesSystem[j].Stop(); + playerNamesSystem[j].GetComponentInParent<TextMeshProUGUI>().text = ""; + } + gameMode.SetActive(value: true); + } + + public void StopLoading() + { + StopAllCoroutines(); + searchingSystem.Stop(); + StartCoroutine(IDoLoading()); + } +} diff --git a/ROUNDS/LobbyHandler.cs b/ROUNDS/LobbyHandler.cs new file mode 100644 index 0000000..acf5511 --- /dev/null +++ b/ROUNDS/LobbyHandler.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class LobbyHandler : MonoBehaviour +{ + private void Start() + { + } +} diff --git a/ROUNDS/Looper.cs b/ROUNDS/Looper.cs new file mode 100644 index 0000000..ec7f469 --- /dev/null +++ b/ROUNDS/Looper.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +public class Looper : MonoBehaviour +{ + private float sinceLoop = 1f; + + private Camera mainCam; + + private TrailRenderer trail; + + private RayCastTrail rayTrail; + + private int loops = 3; + + private void Awake() + { + mainCam = MainCam.instance.transform.GetComponent<Camera>(); + trail = base.transform.root.GetComponentInChildren<TrailRenderer>(); + rayTrail = GetComponentInParent<RayCastTrail>(); + } + + private void Update() + { + if (loops <= 0 && sinceLoop > 0.3f) + { + Object.Destroy(this); + } + Vector3 vector = mainCam.WorldToScreenPoint(base.transform.position); + vector.x /= Screen.width; + vector.y /= Screen.height; + vector = new Vector3(Mathf.Clamp(vector.x, 0f, 1f), Mathf.Clamp(vector.y, 0f, 1f), vector.z); + if ((vector.x == 0f || vector.x == 1f || vector.y == 1f || vector.y == 0f) && sinceLoop > 0.1f) + { + if (vector.x == 0f) + { + vector.x = 1f; + } + else if (vector.x == 1f) + { + vector.x = 0f; + } + if (vector.y == 0f) + { + vector.y = 1f; + } + else if (vector.y == 1f) + { + vector.y = 0f; + } + vector.x *= Screen.width; + vector.y *= Screen.height; + base.transform.root.position = mainCam.ScreenToWorldPoint(vector); + rayTrail.MoveRay(); + for (int i = 0; i < trail.positionCount; i++) + { + trail.SetPosition(i, base.transform.position); + } + sinceLoop = 0f; + loops--; + } + else + { + sinceLoop += TimeHandler.deltaTime; + } + } +} diff --git a/ROUNDS/LowFrameRate.cs b/ROUNDS/LowFrameRate.cs new file mode 100644 index 0000000..1c86586 --- /dev/null +++ b/ROUNDS/LowFrameRate.cs @@ -0,0 +1,30 @@ +using Photon.Pun; +using UnityEngine; + +public class LowFrameRate : MonoBehaviourPunCallbacks +{ + public enum SlowWhat + { + Both, + Server, + Client + } + + public SlowWhat slowWhat = SlowWhat.Server; + + public int targetFrameRate = 10; + + public override void OnJoinedRoom() + { + base.OnJoinedRoom(); + if (slowWhat == SlowWhat.Both || (PhotonNetwork.IsMasterClient && slowWhat == SlowWhat.Server) || (!PhotonNetwork.IsMasterClient && slowWhat == SlowWhat.Client)) + { + Application.targetFrameRate = targetFrameRate; + QualitySettings.vSyncCount = 0; + } + else + { + Application.targetFrameRate = 100; + } + } +} diff --git a/ROUNDS/LowerScreenshakePerPlayer.cs b/ROUNDS/LowerScreenshakePerPlayer.cs new file mode 100644 index 0000000..77d6814 --- /dev/null +++ b/ROUNDS/LowerScreenshakePerPlayer.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class LowerScreenshakePerPlayer : MonoBehaviour +{ + public Screenshaker shake; + + private void Update() + { + if (PlayerManager.instance.players.Count > 2) + { + shake.shakeforce *= 0.5f; + Object.Destroy(this); + } + } +} diff --git a/ROUNDS/MainCam.cs b/ROUNDS/MainCam.cs new file mode 100644 index 0000000..fc79454 --- /dev/null +++ b/ROUNDS/MainCam.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class MainCam : MonoBehaviour +{ + public static MainCam instance; + + public Camera cam; + + private void Awake() + { + cam = GetComponent<Camera>(); + instance = this; + } +} diff --git a/ROUNDS/MainMenuHandler.cs b/ROUNDS/MainMenuHandler.cs new file mode 100644 index 0000000..2be5e82 --- /dev/null +++ b/ROUNDS/MainMenuHandler.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class MainMenuHandler : MonoBehaviour +{ + public static MainMenuHandler instance; + + public bool isOpen = true; + + private void Awake() + { + instance = this; + } + + public void Close() + { + isOpen = false; + base.transform.GetChild(0).gameObject.SetActive(value: false); + } + + public void Open() + { + isOpen = true; + base.transform.GetChild(0).gameObject.SetActive(value: true); + } +} diff --git a/ROUNDS/Map.cs b/ROUNDS/Map.cs new file mode 100644 index 0000000..c5a6c94 --- /dev/null +++ b/ROUNDS/Map.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class Map : MonoBehaviour +{ + public bool wasSpawned; + + public float size = 15f; + + public bool hasEntered; + + internal int levelID; + + internal int missingObjects; + + private float counter; + + private int readyForFrames; + + private bool hasCalledReady; + + public Rigidbody2D[] allRigs; + + private SpawnPoint[] spawnPoints; + + public Action mapIsReadyAction; + + public Action mapIsReadyEarlyAction; + + public Action mapMovingOutAction; + + internal bool hasRope; + + internal bool LoadedForAll() + { + return MapManager.instance.otherPlayersMostRecentlyLoadedLevel == levelID; + } + + private void Awake() + { + if (!GameManager.instance || !GameManager.instance.isPlaying) + { + GM_Test componentInChildren = GameManager.instance.transform.root.GetComponentInChildren<GM_Test>(includeInactive: true); + componentInChildren.gameObject.SetActive(value: true); + componentInChildren.testMap = true; + MapManager.instance.isTestingMap = true; + componentInChildren.transform.root.Find("UI/UI_MainMenu").gameObject.SetActive(value: false); + hasEntered = true; + } + } + + private void Update() + { + counter += Time.deltaTime; + if (!hasCalledReady && ((PhotonNetwork.OfflineMode && counter > 1f && hasEntered) || (hasEntered && LoadedForAll()))) + { + if (missingObjects <= 0) + { + readyForFrames++; + } + if (readyForFrames > 2) + { + StartCoroutine(StartMatch()); + } + } + } + + public void MapMoveOut() + { + mapMovingOutAction?.Invoke(); + } + + internal Vector3 GetRandomSpawnPos() + { + if (spawnPoints == null) + { + spawnPoints = GetComponentsInChildren<SpawnPoint>(); + } + return spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)].transform.position; + } + + private IEnumerator StartMatch() + { + hasCalledReady = true; + mapIsReadyEarlyAction?.Invoke(); + yield return new WaitForSecondsRealtime(0f); + allRigs = GetComponentsInChildren<Rigidbody2D>(); + mapIsReadyAction?.Invoke(); + } + + private void Start() + { + if (!PhotonNetwork.OfflineMode) + { + MapManager.instance.ReportMapLoaded(levelID); + } + if (MapManager.instance.isTestingMap) + { + wasSpawned = true; + } + if (!wasSpawned) + { + MapManager.instance.UnloadScene(base.gameObject.scene); + } + SpriteRenderer[] componentsInChildren = GetComponentsInChildren<SpriteRenderer>(includeInactive: true); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if ((double)componentsInChildren[i].color.a < 0.5) + { + continue; + } + componentsInChildren[i].transform.position = new Vector3(componentsInChildren[i].transform.position.x, componentsInChildren[i].transform.position.y, -3f); + if (!(componentsInChildren[i].gameObject.tag == "NoMask")) + { + componentsInChildren[i].color = new Color(11f / 51f, 11f / 51f, 11f / 51f); + if (!componentsInChildren[i].GetComponent<SpriteMask>()) + { + componentsInChildren[i].gameObject.AddComponent<SpriteMask>().sprite = componentsInChildren[i].sprite; + } + } + } + SpriteMask[] componentsInChildren2 = GetComponentsInChildren<SpriteMask>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + if (!(componentsInChildren2[j].gameObject.tag == "NoMask")) + { + componentsInChildren2[j].isCustomRangeActive = true; + componentsInChildren2[j].frontSortingLayerID = SortingLayer.NameToID("MapParticle"); + componentsInChildren2[j].frontSortingOrder = 1; + componentsInChildren2[j].backSortingLayerID = SortingLayer.NameToID("MapParticle"); + componentsInChildren2[j].backSortingOrder = 0; + } + } + } +} diff --git a/ROUNDS/MapManager.cs b/ROUNDS/MapManager.cs new file mode 100644 index 0000000..ace02f0 --- /dev/null +++ b/ROUNDS/MapManager.cs @@ -0,0 +1,200 @@ +using System.Collections; +using Photon.Pun; +using UnityEngine; +using UnityEngine.SceneManagement; + +public class MapManager : MonoBehaviour +{ + [SerializeField] + public string[] levels; + + public int currentLevelID; + + public static MapManager instance; + + [HideInInspector] + public bool isTestingMap; + + public MapWrapper currentMap; + + private PhotonView view; + + internal int otherPlayersMostRecentlyLoadedLevel = -1; + + public string forceMap = ""; + + private bool callInNextMap; + + private void Awake() + { + instance = this; + view = GetComponent<PhotonView>(); + } + + internal void ReportMapLoaded(int levelID) + { + view.RPC("RPCA_ReportMapLoaded", RpcTarget.Others, levelID); + } + + [PunRPC] + internal void RPCA_ReportMapLoaded(int levelID) + { + otherPlayersMostRecentlyLoadedLevel = levelID; + } + + private string GetRandomMap() + { + if (forceMap != "") + { + return forceMap; + } + int num = Random.Range(0, levels.Length); + while (num == currentLevelID && levels.Length > 1) + { + num = Random.Range(0, levels.Length); + } + return levels[num]; + } + + public void LoadNextLevel(bool callInImidetly = false, bool forceLoad = false) + { + if (forceLoad || PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode) + { + view.RPC("RPCA_SetCallInNextMap", RpcTarget.All, callInImidetly); + view.RPC("RPCA_LoadLevel", RpcTarget.All, GetRandomMap()); + } + } + + [PunRPC] + private void RPCA_SetCallInNextMap(bool toSet) + { + callInNextMap = toSet; + } + + public void LoadLevelFromID(int ID, bool onlyMaster = false, bool callInImidetly = false) + { + if (!(!PhotonNetwork.IsMasterClient && onlyMaster)) + { + callInNextMap = callInImidetly; + RPCA_LoadLevel(levels[ID]); + } + } + + [PunRPC] + public void RPCA_CallInNewMapAndMovePlayers(int mapID) + { + StartCoroutine(WaitForMapToBeLoaded(mapID)); + } + + private IEnumerator WaitForMapToBeLoaded(int mapID) + { + while (currentLevelID != mapID) + { + yield return null; + } + Debug.Log("CALL IN NEW MAP AND MOVE PLAYERS"); + if (currentMap != null) + { + MapTransition.instance.Enter(currentMap.Map); + } + MapTransition.instance.ClearObjects(); + PlayerManager.instance.RPCA_MovePlayers(); + } + + public void CallInNewMapAndMovePlayers(int mapID) + { + if (PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode) + { + view.RPC("RPCA_CallInNewMapAndMovePlayers", RpcTarget.All, mapID); + } + } + + [PunRPC] + public void RPCA_CallInNewMap() + { + if (currentMap != null) + { + MapTransition.instance.Enter(currentMap.Map); + } + MapTransition.instance.ClearObjects(); + } + + public void CallInNewMap() + { + if (PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode) + { + view.RPC("RPCA_CallInNewMap", RpcTarget.All); + } + } + + public SpawnPoint[] GetSpawnPoints() + { + return currentMap.Map.GetComponentsInChildren<SpawnPoint>(); + } + + private void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode) + { + Map map = null; + for (int i = 0; i < scene.GetRootGameObjects().Length; i++) + { + map = scene.GetRootGameObjects()[i].GetComponent<Map>(); + if ((bool)map) + { + break; + } + } + if (!map) + { + Debug.LogError("NO MAP WAS FOUND WHEN LOADING NEW MAP"); + } + map.wasSpawned = true; + SceneManager.sceneLoaded -= OnLevelFinishedLoading; + if (currentMap != null) + { + StartCoroutine(UnloadAfterSeconds(currentMap.Scene)); + MapTransition.instance.Exit(currentMap.Map); + } + MapTransition.instance.SetStartPos(map); + map.levelID = currentLevelID; + currentMap = new MapWrapper(map, scene); + currentLevelID = GetIDFromScene(scene); + if (callInNextMap) + { + CallInNewMap(); + callInNextMap = false; + } + Debug.Log("FINISHED LOADING SCENE"); + } + + private int GetIDFromScene(Scene scene) + { + int result = -1; + for (int i = 0; i < levels.Length; i++) + { + if (levels[i] == scene.name) + { + result = i; + } + } + return result; + } + + [PunRPC] + public void RPCA_LoadLevel(string sceneName) + { + Debug.Log("LOADING SCENE"); + SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); + SceneManager.sceneLoaded += OnLevelFinishedLoading; + } + + private IEnumerator UnloadAfterSeconds(Scene scene) + { + yield return new WaitForSecondsRealtime(2f); + SceneManager.UnloadSceneAsync(scene); + } + + public void UnloadScene(Scene scene) + { + SceneManager.UnloadSceneAsync(scene); + } +} diff --git a/ROUNDS/MapObjet_Rope.cs b/ROUNDS/MapObjet_Rope.cs new file mode 100644 index 0000000..463a1ec --- /dev/null +++ b/ROUNDS/MapObjet_Rope.cs @@ -0,0 +1,274 @@ +using System; +using System.Collections; +using Sonigon; +using UnityEngine; + +public class MapObjet_Rope : MonoBehaviour +{ + public enum JointType + { + spring, + Distance + } + + [Header("Sound")] + public bool soundRopePlay; + + public SoundEvent soundRopeLoop; + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + private bool soundIsPlaying; + + private bool soundInitialized; + + private float soundRopeLengthCurrent; + + private float soundRopeLengthLast; + + private float soundRopeLengthVelocity; + + [Header("Settings")] + public JointType jointType; + + private Map map; + + private LineRenderer lineRenderer; + + private AnchoredJoint2D joint; + + private Vector3 lastPos; + + private Vector3 vel1; + + private Vector3 vel2; + + private Vector3 postSnapPos1; + + private Vector3 postSnapPos2; + + private float sinceBreak; + + private void Start() + { + map = GetComponentInParent<Map>(); + map.hasRope = true; + lineRenderer = GetComponent<LineRenderer>(); + Map obj = map; + obj.mapIsReadyAction = (Action)Delegate.Combine(obj.mapIsReadyAction, new Action(Go)); + Map obj2 = map; + obj2.mapMovingOutAction = (Action)Delegate.Combine(obj2.mapMovingOutAction, new Action(Leave)); + } + + private void Leave() + { + if ((bool)joint) + { + UnityEngine.Object.Destroy(joint); + } + } + + public void Go() + { + StartCoroutine(IGo()); + } + + private IEnumerator IGo() + { + yield return new WaitForSeconds(0f); + Rigidbody2D rigidbody2D = null; + Rigidbody2D rigidbody2D2 = null; + for (int i = 0; i < map.allRigs.Length; i++) + { + Collider2D component = map.allRigs[i].GetComponent<Collider2D>(); + if ((bool)component) + { + if (component.OverlapPoint(base.transform.position)) + { + rigidbody2D = map.allRigs[i]; + } + if (component.OverlapPoint(base.transform.GetChild(0).position)) + { + rigidbody2D2 = map.allRigs[i]; + } + } + } + if ((bool)rigidbody2D) + { + AddJoint(rigidbody2D); + if ((bool)rigidbody2D2) + { + joint.connectedBody = rigidbody2D2; + joint.anchor = rigidbody2D.transform.InverseTransformPoint(base.transform.position); + joint.connectedAnchor = rigidbody2D2.transform.InverseTransformPoint(base.transform.GetChild(0).position); + } + else + { + joint.anchor = rigidbody2D.transform.InverseTransformPoint(base.transform.position); + joint.connectedAnchor = base.transform.GetChild(0).position; + } + joint.enableCollision = true; + } + else if ((bool)rigidbody2D2) + { + AddJoint(rigidbody2D2); + joint.anchor = rigidbody2D2.transform.InverseTransformPoint(base.transform.GetChild(0).position); + joint.connectedAnchor = base.transform.position; + joint.enableCollision = true; + } + else + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + private void AddJoint(Rigidbody2D target) + { + switch (jointType) + { + case JointType.spring: + joint = target.gameObject.AddComponent<SpringJoint2D>(); + break; + case JointType.Distance: + joint = target.gameObject.AddComponent<DistanceJoint2D>(); + break; + } + } + + private void OnDrawGizmos() + { + if (!joint) + { + if (!lineRenderer) + { + lineRenderer = GetComponent<LineRenderer>(); + } + lineRenderer.SetPosition(0, base.transform.position); + lineRenderer.SetPosition(1, base.transform.GetChild(0).position); + if (Event.current.shift) + { + base.transform.GetChild(0).position = lastPos; + } + lastPos = base.transform.GetChild(0).position; + } + } + + private void OnDestroy() + { + soundIsPlaying = false; + soundInitialized = false; + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + + private void OnDisable() + { + soundIsPlaying = false; + soundInitialized = false; + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + + private void Update() + { + if ((bool)joint) + { + if ((bool)joint.attachedRigidbody && !joint.attachedRigidbody.gameObject.activeSelf) + { + postSnapPos1 = lineRenderer.GetPosition(0); + } + if ((bool)joint.connectedBody && !joint.connectedBody.gameObject.activeSelf) + { + postSnapPos2 = lineRenderer.GetPosition(1); + } + if (((bool)joint.attachedRigidbody && !joint.attachedRigidbody.gameObject.activeSelf) || ((bool)joint.connectedBody && !joint.connectedBody.gameObject.activeSelf)) + { + sinceBreak += Time.deltaTime; + if (Vector2.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)) < 0.2f) + { + if (soundIsPlaying) + { + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + lineRenderer.enabled = false; + return; + } + } + if ((bool)joint.attachedRigidbody && joint.attachedRigidbody.gameObject.activeSelf) + { + vel1 = joint.attachedRigidbody.velocity * 1.5f; + } + if ((bool)joint.attachedRigidbody && !joint.attachedRigidbody.gameObject.activeSelf) + { + vel1 = FRILerp.Lerp(vel1, (lineRenderer.GetPosition(1) - lineRenderer.GetPosition(0)) * 15f * Mathf.Clamp(sinceBreak * 2f, 0f, 1f), 10f); + postSnapPos1 += vel1 * Time.deltaTime; + } + if (postSnapPos1 == Vector3.zero) + { + lineRenderer.SetPosition(0, joint.attachedRigidbody.transform.TransformPoint(joint.anchor)); + } + else + { + lineRenderer.SetPosition(0, postSnapPos1); + } + if ((bool)joint.connectedBody) + { + if (!joint.connectedBody.gameObject.activeSelf) + { + vel2 = FRILerp.Lerp(vel2, (lineRenderer.GetPosition(0) - lineRenderer.GetPosition(1)) * 15f * Mathf.Clamp(sinceBreak * 2f, 0f, 1f), 10f); + postSnapPos2 += vel2 * Time.deltaTime; + } + else + { + vel2 = joint.connectedBody.velocity * 1.5f; + } + if (postSnapPos2 == Vector3.zero) + { + lineRenderer.SetPosition(1, joint.connectedBody.transform.TransformPoint(joint.connectedAnchor)); + } + else + { + lineRenderer.SetPosition(1, postSnapPos2); + } + } + else if (postSnapPos2 == Vector3.zero) + { + lineRenderer.SetPosition(1, joint.connectedAnchor); + } + else + { + lineRenderer.SetPosition(1, postSnapPos2); + } + } + else + { + lineRenderer.SetPosition(0, Vector3.up * 200f); + lineRenderer.SetPosition(1, Vector3.up * 200f); + } + if (!soundRopePlay || lineRenderer.positionCount < 1) + { + return; + } + if (!soundInitialized) + { + soundInitialized = true; + soundRopeLengthLast = Vector3.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)); + } + soundRopeLengthCurrent = Vector3.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)); + soundRopeLengthVelocity = Mathf.Abs(soundRopeLengthLast - soundRopeLengthCurrent); + soundParameterIntensity.intensity = soundRopeLengthVelocity; + if (soundRopeLengthVelocity > 0.03f) + { + if (!soundIsPlaying) + { + soundIsPlaying = true; + SoundManager.Instance.PlayAtPosition(soundRopeLoop, SoundManager.Instance.transform, base.transform, soundParameterIntensity); + } + } + else if (soundIsPlaying) + { + soundIsPlaying = false; + soundInitialized = false; + SoundManager.Instance.StopAtPosition(soundRopeLoop, base.transform); + } + soundRopeLengthLast = Vector3.Distance(lineRenderer.GetPosition(0), lineRenderer.GetPosition(1)); + } +} diff --git a/ROUNDS/MapTransition.cs b/ROUNDS/MapTransition.cs new file mode 100644 index 0000000..bb238da --- /dev/null +++ b/ROUNDS/MapTransition.cs @@ -0,0 +1,145 @@ +using System.Collections; +using SoundImplementation; +using UnityEngine; +using UnityEngine.Events; + +public class MapTransition : MonoBehaviour +{ + [Header("Settings")] + public UnityEvent switchMapEvent; + + public AnimationCurve curve; + + public AnimationCurve gravityCurve; + + public static MapTransition instance; + + private const float mapPadding = 90f; + + public static bool isTransitioning; + + private void Awake() + { + instance = this; + } + + private void Start() + { + } + + public void SetStartPos(Map map) + { + map.transform.position = Vector3.right * 90f; + } + + public void Enter(Map map) + { + MoveObject(map.gameObject, Vector3.zero); + StartCoroutine(DelayEvent(0.1f)); + SoundPlayerStatic.Instance.PlayLevelTransitionIn(); + SoundMusicManager.Instance.PlayIngame(isCard: false); + } + + public void Exit(Map map) + { + SoundPlayerStatic.Instance.PlayLevelTransitionOut(); + map.MapMoveOut(); + MoveObject(map.gameObject, Vector3.right * -90f); + StartCoroutine(ClearObjectsAfterSeconds(1f)); + } + + private void MoveObject(GameObject target, Vector3 targetPos) + { + for (int i = 0; i < target.transform.childCount; i++) + { + Toggle(target.transform.GetChild(i).gameObject, enabled: false); + StartCoroutine(Move(target.transform.GetChild(i).gameObject, targetPos - target.transform.position, (i == 0) ? target.GetComponent<Map>() : null)); + } + } + + private void Toggle(GameObject obj, bool enabled) + { + Rigidbody2D component = obj.GetComponent<Rigidbody2D>(); + if ((bool)component) + { + component.simulated = enabled; + if (enabled) + { + StartCoroutine(LerpDrag(component)); + } + } + Collider2D component2 = obj.GetComponent<Collider2D>(); + if ((bool)component2) + { + component2.enabled = enabled; + } + CodeAnimation component3 = obj.GetComponent<CodeAnimation>(); + if ((bool)component3) + { + component3.enabled = enabled; + } + } + + private IEnumerator DelayEvent(float delay) + { + yield return new WaitForSecondsRealtime(delay); + switchMapEvent.Invoke(); + } + + private IEnumerator Move(GameObject target, Vector3 distance, Map targetMap = null) + { + isTransitioning = true; + float maxRandomDelay = 0.25f; + float randomDelay = Random.Range(0f, maxRandomDelay); + yield return new WaitForSecondsRealtime(randomDelay); + Vector3 targetStartPos = target.transform.position; + float t = curve.keys[curve.keys.Length - 1].time; + float c = 0f; + while (c < t) + { + c += Time.unscaledDeltaTime; + target.transform.position = targetStartPos + distance * curve.Evaluate(c); + yield return null; + } + target.transform.position = targetStartPos + distance; + Toggle(target, enabled: true); + yield return new WaitForSecondsRealtime(maxRandomDelay - randomDelay); + isTransitioning = false; + if ((bool)targetMap) + { + targetMap.hasEntered = true; + } + } + + private IEnumerator LerpDrag(Rigidbody2D target) + { + target.gravityScale = 0f; + float t = gravityCurve.keys[gravityCurve.keys.Length - 1].time; + float c = 0f; + while (c < t && (bool)target) + { + target.gravityScale = gravityCurve.Evaluate(c); + c += Time.unscaledDeltaTime; + yield return null; + } + if ((bool)target) + { + target.gravityScale = 1f; + } + } + + private IEnumerator ClearObjectsAfterSeconds(float time) + { + yield return new WaitForSecondsRealtime(time); + ClearObjects(); + } + + public void ClearObjects() + { + RemoveAfterSeconds[] array = Object.FindObjectsOfType<RemoveAfterSeconds>(); + for (int i = 0; i < array.Length; i++) + { + Object.Destroy(array[i].gameObject); + } + } +} diff --git a/ROUNDS/MapWrapper.cs b/ROUNDS/MapWrapper.cs new file mode 100644 index 0000000..9a6fe7d --- /dev/null +++ b/ROUNDS/MapWrapper.cs @@ -0,0 +1,14 @@ +using UnityEngine.SceneManagement; + +public class MapWrapper +{ + public Map Map { get; private set; } + + public Scene Scene { get; private set; } + + public MapWrapper(Map map, Scene scene) + { + Map = map; + Scene = scene; + } +} diff --git a/ROUNDS/MenuControllerEvent.cs b/ROUNDS/MenuControllerEvent.cs new file mode 100644 index 0000000..edd60c6 --- /dev/null +++ b/ROUNDS/MenuControllerEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class MenuControllerEvent : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/MenuControllerHandler.cs b/ROUNDS/MenuControllerHandler.cs new file mode 100644 index 0000000..4f399bd --- /dev/null +++ b/ROUNDS/MenuControllerHandler.cs @@ -0,0 +1,75 @@ +using System; +using InControl; +using UnityEngine; +using UnityEngine.EventSystems; + +public class MenuControllerHandler : MonoBehaviour +{ + public enum MenuControl + { + Controller, + Mouse, + Unassigned + } + + public static MenuControl menuControl; + + public MenuControl lastMenuControl; + + public Action<MenuControl> switchControlAction; + + public static MenuControllerHandler instance; + + private void Awake() + { + instance = this; + } + + private void Start() + { + Switch(); + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.Mouse0)) + { + menuControl = MenuControl.Mouse; + } + if (Input.GetKeyDown(KeyCode.Mouse1)) + { + menuControl = MenuControl.Mouse; + } + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + InputDevice inputDevice = InputManager.ActiveDevices[i]; + if (!inputDevice.AnyButtonWasPressed && !(Mathf.Abs(inputDevice.LeftStick.Value.y) > 0.1f)) + { + continue; + } + menuControl = MenuControl.Controller; + if (EventSystem.current.currentSelectedGameObject.activeInHierarchy) + { + continue; + } + ListMenuButton[] array = UnityEngine.Object.FindObjectsOfType<ListMenuButton>(); + for (int j = 0; j < array.Length; j++) + { + if (array[j].enabled) + { + ListMenu.instance.SelectButton(array[j]); + } + } + } + if (menuControl != lastMenuControl) + { + Switch(); + } + lastMenuControl = menuControl; + } + + private void Switch() + { + switchControlAction?.Invoke(menuControl); + } +} diff --git a/ROUNDS/MenuControllerToggler.cs b/ROUNDS/MenuControllerToggler.cs new file mode 100644 index 0000000..465cf16 --- /dev/null +++ b/ROUNDS/MenuControllerToggler.cs @@ -0,0 +1,75 @@ +using System; +using UnityEngine; + +public class MenuControllerToggler : MonoBehaviour +{ + public bool creatorControl; + + public GameObject controllerObject; + + public GameObject keyboardObject; + + private CharacterCreator creator; + + private void Awake() + { + CharacterCreator componentInParent = GetComponentInParent<CharacterCreator>(); + if (componentInParent.playerActions == null) + { + if (creatorControl) + { + componentInParent.SwitchAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(componentInParent.SwitchAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + Switch(GetComponentInParent<CharacterCreator>().currentControl); + } + else + { + MenuControllerHandler instance = MenuControllerHandler.instance; + instance.switchControlAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(instance.switchControlAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + Switch(MenuControllerHandler.menuControl); + } + } + } + + private void OnEnable() + { + CharacterCreator componentInParent = GetComponentInParent<CharacterCreator>(); + if (componentInParent.playerActions != null) + { + componentInParent.SwitchAction = (Action<MenuControllerHandler.MenuControl>)Delegate.Combine(componentInParent.SwitchAction, new Action<MenuControllerHandler.MenuControl>(Switch)); + if (componentInParent.inputType == GeneralInput.InputType.Controller) + { + Switch(MenuControllerHandler.MenuControl.Controller); + } + if (componentInParent.inputType == GeneralInput.InputType.Keyboard) + { + Switch(MenuControllerHandler.MenuControl.Mouse); + } + } + } + + private void Switch(MenuControllerHandler.MenuControl control) + { + if (control == MenuControllerHandler.MenuControl.Controller) + { + if ((bool)controllerObject) + { + controllerObject.SetActive(value: true); + } + if ((bool)keyboardObject) + { + keyboardObject.SetActive(value: false); + } + } + else + { + if ((bool)controllerObject) + { + controllerObject.SetActive(value: false); + } + if ((bool)keyboardObject) + { + keyboardObject.SetActive(value: true); + } + } + } +} diff --git a/ROUNDS/MenuEffects.cs b/ROUNDS/MenuEffects.cs new file mode 100644 index 0000000..5345984 --- /dev/null +++ b/ROUNDS/MenuEffects.cs @@ -0,0 +1,51 @@ +using System.Collections; +using TMPro; +using UnityEngine; + +public class MenuEffects : MonoBehaviour +{ + public static MenuEffects instance; + + public Color nopeColor; + + private void Awake() + { + instance = this; + } + + public void ShakeObject(GameObject objectToShake, Vector3 defaultPos, float amount, float time) + { + StartCoroutine(DoShakeObject(objectToShake, defaultPos, amount, time)); + } + + private IEnumerator DoShakeObject(GameObject objectToShake, Vector3 defaultPos, float amount, float time) + { + float c = 0f; + while (c < time) + { + Vector3 localPosition = defaultPos + Random.onUnitSphere * amount * ((time - c) / time); + localPosition.z = defaultPos.z; + objectToShake.transform.localPosition = localPosition; + c += Time.unscaledDeltaTime; + yield return null; + } + objectToShake.transform.localPosition = defaultPos; + } + + public void BlinkInColor(TextMeshProUGUI textToBlink, Color blinkColor, Color defaultColor, float seconds) + { + StartCoroutine(DoTextColorBlink(textToBlink, blinkColor, defaultColor, seconds)); + } + + private IEnumerator DoTextColorBlink(TextMeshProUGUI textToBlink, Color blinkColor, Color defaultColor, float seconds) + { + float c = 0f; + while (c < seconds) + { + textToBlink.color = blinkColor; + c += Time.unscaledDeltaTime; + yield return null; + } + textToBlink.color = defaultColor; + } +} diff --git a/ROUNDS/MoveForward.cs b/ROUNDS/MoveForward.cs new file mode 100644 index 0000000..4171a26 --- /dev/null +++ b/ROUNDS/MoveForward.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class MoveForward : MonoBehaviour +{ + public float amount = 3f; + + private void Start() + { + base.transform.position += Vector3.forward * amount; + } +} diff --git a/ROUNDS/MoveSequence.cs b/ROUNDS/MoveSequence.cs new file mode 100644 index 0000000..1437614 --- /dev/null +++ b/ROUNDS/MoveSequence.cs @@ -0,0 +1,99 @@ +using Photon.Pun; +using UnityEngine; + +public class MoveSequence : MonoBehaviour +{ + private int targetID; + + public Vector2[] positions; + + public float drag = 1f; + + public float spring = 1f; + + public float cap = 1f; + + public float threshold = 1f; + + public float timeAtPos; + + private float counter; + + private Vector2 startPos; + + private Vector2 velocity; + + private Rigidbody2D rig; + + private Map map; + + private string myKey; + + private void Start() + { + base.gameObject.layer = 17; + startPos = base.transform.localPosition; + rig = GetComponent<Rigidbody2D>(); + map = GetComponentInParent<Map>(); + myKey = "MapObect " + GetComponentInParent<Map>().levelID + " " + base.transform.GetSiblingIndex(); + MapManager.instance.GetComponent<ChildRPC>().childRPCsInt.Add(myKey, RPCA_SetTargetID); + } + + private void OnDestroy() + { + if ((bool)MapManager.instance) + { + MapManager.instance.GetComponent<ChildRPC>().childRPCsInt.Remove(myKey); + } + } + + private void OnDrawGizmos() + { + for (int i = 0; i < positions.Length; i++) + { + Gizmos.DrawSphere((Vector2)base.transform.position + positions[i], 0.25f + (float)i * 0.15f); + } + } + + private void Update() + { + if (MapTransition.isTransitioning || !map.hasEntered) + { + return; + } + Vector2 vector = positions[targetID] + startPos; + Vector2 vector2 = vector - (Vector2)base.transform.position; + vector2 = Vector3.ClampMagnitude(vector2, cap); + if ((bool)rig) + { + rig.gravityScale = 0f; + rig.AddForce(vector2 * spring * CappedDeltaTime.time * rig.mass); + } + else + { + velocity += vector2 * spring * CappedDeltaTime.time; + velocity -= velocity * drag * CappedDeltaTime.time; + base.transform.position += (Vector3)velocity * TimeHandler.deltaTime; + } + if (!PhotonNetwork.IsMasterClient || !(Vector2.Distance(base.transform.position, vector) < threshold)) + { + return; + } + counter += TimeHandler.deltaTime; + if (counter > timeAtPos) + { + targetID++; + if (targetID >= positions.Length) + { + targetID = 0; + } + MapManager.instance.GetComponent<ChildRPC>().CallFunction(myKey, targetID); + counter = 0f; + } + } + + private void RPCA_SetTargetID(int setValue) + { + targetID = setValue; + } +} diff --git a/ROUNDS/MoveTransform.cs b/ROUNDS/MoveTransform.cs new file mode 100644 index 0000000..e6b8d0f --- /dev/null +++ b/ROUNDS/MoveTransform.cs @@ -0,0 +1,78 @@ +using UnityEngine; + +public class MoveTransform : MonoBehaviour +{ + public float gravity = 30f; + + public float drag; + + public float dragMinSpeed = 1f; + + public float velocitySpread; + + public float spread; + + public Vector3 localForce; + + public Vector3 worldForce; + + public float multiplier = 1f; + + public Vector3 velocity; + + [HideInInspector] + public float distanceTravelled; + + [HideInInspector] + public bool DontRunStart; + + public float selectedSpread; + + public bool allowStop; + + public int simulateGravity; + + private int randomSeed; + + [HideInInspector] + internal float simulationSpeed = 1f; + + private void Start() + { + if (!DontRunStart) + { + velocity += base.transform.TransformDirection(localForce) + worldForce; + base.transform.rotation = Quaternion.LookRotation(velocity, Vector3.forward); + if (spread != 0f) + { + velocity += base.transform.up * selectedSpread; + } + } + } + + private void Update() + { + float num = Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.02f); + float deltaTime = TimeHandler.deltaTime; + num *= simulationSpeed; + deltaTime *= simulationSpeed; + if (simulateGravity == 0) + { + velocity += gravity * Vector3.down * deltaTime * multiplier; + } + if ((velocity.magnitude > 2f || allowStop) && velocity.magnitude > dragMinSpeed) + { + velocity -= velocity * Mathf.Clamp(drag * num * Mathf.Clamp(multiplier, 0f, 1f), 0f, 1f); + } + base.transform.position += velocity * deltaTime * multiplier; + distanceTravelled += velocity.magnitude * deltaTime * multiplier; + base.transform.rotation = Quaternion.LookRotation(velocity, Vector3.forward); + } + + public float GetUpwardsCompensation(Vector2 start, Vector2 end) + { + start.y = 0.5f; + end.y = 0.5f; + return Mathf.Pow(Vector3.Distance(start, end), 2.06f) * gravity / velocity.magnitude * 0.012f; + } +} diff --git a/ROUNDS/MoveTransformGravity.cs b/ROUNDS/MoveTransformGravity.cs new file mode 100644 index 0000000..fd822fe --- /dev/null +++ b/ROUNDS/MoveTransformGravity.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class MoveTransformGravity : MonoBehaviour +{ + public float amount = 1f; + + public float pow = 1.5f; + + private MoveTransform move; + + private float counter; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + } + + private void Update() + { + counter += TimeHandler.deltaTime; + move.velocity += Vector3.down * Mathf.Pow(amount * counter, pow); + } +} diff --git a/ROUNDS/Movement.cs b/ROUNDS/Movement.cs new file mode 100644 index 0000000..17d7b11 --- /dev/null +++ b/ROUNDS/Movement.cs @@ -0,0 +1,137 @@ +using UnityEngine; + +public class Movement : MonoBehaviour +{ + public float jumpForce; + + public float force; + + public float torque; + + public float drag = 1f; + + public float Angulardrag = 1f; + + public ParticleSystem[] jumpPart; + + private GeneralInput input; + + private Rigidbody2D rig; + + private CharacterData data; + + private CharacterStatModifiers stats; + + public Vector2 knockBack; + + private HealthHandler health; + + private Vector3 moveDir; + + private Vector3 idleForce; + + private void Start() + { + rig = GetComponent<Rigidbody2D>(); + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + stats = GetComponent<CharacterStatModifiers>(); + health = GetComponent<HealthHandler>(); + } + + private void FixedUpdate() + { + if (input.direction != Vector3.zero) + { + moveDir = input.direction; + idleForce = Vector3.Lerp(idleForce, moveDir, Time.fixedDeltaTime * 6f); + } + else if (data.isGrounded || data.isWallGrab) + { + idleForce = Vector3.Lerp(idleForce, Vector3.zero, 15f * Time.fixedDeltaTime); + } + else + { + idleForce = Vector3.Lerp(idleForce, Vector3.zero, 3f * Time.fixedDeltaTime); + } + if (input.direction == Vector3.zero) + { + moveDir = idleForce; + } + if (data.isGrounded || data.isWallGrab) + { + knockBack = Vector3.Lerp(knockBack, Vector3.zero, 10f * Time.fixedDeltaTime); + } + else + { + knockBack = Vector3.Lerp(knockBack, Vector3.zero, 7f * Time.fixedDeltaTime); + } + rig.AddForce(knockBack * 0.1f * rig.mass, ForceMode2D.Force); + if (moveDir.y > 0f) + { + moveDir.y = 0f; + } + rig.AddForce(-rig.velocity * 0.01f * drag * rig.mass, ForceMode2D.Force); + rig.AddTorque((0f - rig.angularVelocity) * 0.01f * Angulardrag * rig.mass, ForceMode2D.Force); + if (input.jumpIsPressed) + { + rig.AddForce(Vector2.up * 20f * rig.mass, ForceMode2D.Force); + } + rig.AddForce(moveDir * force * (1f - stats.GetSlow()) * rig.mass, ForceMode2D.Force); + } + + private void Update() + { + if (input.jumpWasPressed) + { + Jump(); + } + if (data.isGrounded && data.sinceJump > 0.2f) + { + data.currentJumps = data.jumps; + } + } + + private void Jump() + { + if (data.sinceJump < 0.15f) + { + return; + } + Vector3 vector = Vector3.up; + Vector3 vector2 = data.groundPos; + if (data.sinceGrounded < 0.1f) + { + if (data.sinceGrounded > 0.05f) + { + vector2 = base.transform.position; + } + data.currentJumps = data.jumps; + } + else if (data.sinceWallGrab < 0.1f) + { + vector = Vector2.up + data.wallNormal; + vector2 = data.wallPos; + data.currentJumps = data.jumps; + } + else + { + if (data.currentJumps <= 0) + { + return; + } + vector2 = base.transform.position; + } + data.currentJumps--; + rig.velocity = new Vector3(rig.velocity.x, 0f); + health.TakeForce(Vector2.up * jumpForce * 1f * (1f - stats.GetSlow()) * rig.mass); + data.sinceJump = 0f; + data.sinceGrounded = 0f; + for (int i = 0; i < jumpPart.Length; i++) + { + jumpPart[i].transform.position = new Vector3(vector2.x, vector2.y, 5f) - vector * 0f; + jumpPart[i].transform.rotation = Quaternion.LookRotation(rig.velocity); + jumpPart[i].Play(); + } + } +} diff --git a/ROUNDS/MultiOptions.cs b/ROUNDS/MultiOptions.cs new file mode 100644 index 0000000..82bb9e0 --- /dev/null +++ b/ROUNDS/MultiOptions.cs @@ -0,0 +1,168 @@ +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; + +public class MultiOptions : MonoBehaviour +{ + private GameObject source; + + private OptionsButton targetButton; + + private void Start() + { + } + + private void Update() + { + if (Input.GetKeyUp(KeyCode.Mouse0) || Input.GetKeyDown(KeyCode.Escape)) + { + Close(); + } + } + + internal void ClickRessButton(MultiOptionsButton buttonPressed) + { + targetButton.SetResolutionAndFullscreen(buttonPressed.currentRess, buttonPressed.currentFull); + Close(); + } + + public void Open(OptionsButton.SettingsTarget settingsTarget, Vector3 pos, OptionsButton askingButton) + { + targetButton = askingButton; + base.transform.position = pos; + source = base.transform.GetChild(0).gameObject; + if (settingsTarget == OptionsButton.SettingsTarget.Resolution) + { + PopulateRess(Screen.resolutions); + } + else + { + PopulateFullScreens(new Optionshandler.FullScreenOption[3] + { + Optionshandler.FullScreenOption.FullScreen, + Optionshandler.FullScreenOption.WindowedFullScreen, + Optionshandler.FullScreenOption.Windowed + }); + } + base.gameObject.SetActive(value: true); + ListMenuButton[] componentsInChildren = base.transform.parent.GetComponentsInChildren<ListMenuButton>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].transform.parent != base.transform) + { + componentsInChildren[i].enabled = false; + } + } + CanvasGroup[] componentsInChildren2 = base.transform.parent.GetComponentsInChildren<CanvasGroup>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + componentsInChildren2[j].alpha = 0.05f; + componentsInChildren2[j].interactable = false; + } + if (MenuControllerHandler.menuControl == MenuControllerHandler.MenuControl.Controller) + { + StartCoroutine(WaitFrame()); + } + else + { + ListMenu.instance.ClearBar(); + } + } + + private IEnumerator WaitFrame() + { + yield return new WaitForSecondsRealtime(0f); + ListMenu.instance.SelectButton(GetComponentInChildren<ListMenuButton>()); + } + + public void Close() + { + base.gameObject.SetActive(value: false); + ListMenuButton[] componentsInChildren = base.transform.parent.GetComponentsInChildren<ListMenuButton>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].transform.parent != base.transform) + { + componentsInChildren[i].enabled = true; + } + } + CanvasGroup[] componentsInChildren2 = base.transform.parent.GetComponentsInChildren<CanvasGroup>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + componentsInChildren2[j].alpha = 1f; + componentsInChildren2[j].interactable = true; + } + if (MenuControllerHandler.menuControl == MenuControllerHandler.MenuControl.Controller) + { + ListMenu.instance.SelectButton(targetButton.transform.GetComponent<ListMenuButton>()); + } + else + { + ListMenu.instance.ClearBar(); + } + } + + private void PopulateRess(Resolution[] allRess) + { + for (int num = base.transform.childCount - 1; num > 0; num--) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + allRess = GetBestResolutions(); + for (int i = 0; i < allRess.Length; i++) + { + GameObject obj = Object.Instantiate(source, source.transform.position, source.transform.rotation, source.transform.parent); + obj.GetComponentInChildren<TextMeshProUGUI>().text = allRess[i].width + " x " + allRess[i].height; + obj.GetComponent<MultiOptionsButton>().currentRess = allRess[i]; + obj.gameObject.SetActive(value: true); + } + } + + private Resolution[] GetBestResolutions() + { + List<Resolution> list = new List<Resolution>(); + for (int i = 0; i < Screen.resolutions.Length; i++) + { + if (IsBestRess(Screen.resolutions[i])) + { + list.Add(Screen.resolutions[i]); + } + } + return list.ToArray(); + } + + private bool IsBestRess(Resolution newRess) + { + for (int i = 0; i < Screen.resolutions.Length; i++) + { + if (Screen.resolutions[i].width == newRess.width && Screen.resolutions[i].height == newRess.height && newRess.refreshRate < Screen.resolutions[i].refreshRate) + { + return false; + } + } + return true; + } + + private void PopulateFullScreens(Optionshandler.FullScreenOption[] allScreens) + { + for (int num = base.transform.childCount - 1; num > 0; num--) + { + Object.Destroy(base.transform.GetChild(num).gameObject); + } + for (int i = 0; i < allScreens.Length; i++) + { + GameObject gameObject = Object.Instantiate(source, source.transform.position, source.transform.rotation, source.transform.parent); + if (allScreens[i] == Optionshandler.FullScreenOption.WindowedFullScreen) + { + gameObject.GetComponentInChildren<TextMeshProUGUI>().text = "WINDOWED FULLSCREEN"; + } + else + { + gameObject.GetComponentInChildren<TextMeshProUGUI>().text = allScreens[i].ToString().ToUpper(); + } + gameObject.GetComponent<MultiOptionsButton>().currentFull = allScreens[i]; + gameObject.gameObject.SetActive(value: true); + } + } +} diff --git a/ROUNDS/MultiOptionsButton.cs b/ROUNDS/MultiOptionsButton.cs new file mode 100644 index 0000000..7b8bf79 --- /dev/null +++ b/ROUNDS/MultiOptionsButton.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class MultiOptionsButton : MonoBehaviour +{ + public Resolution currentRess; + + public Optionshandler.FullScreenOption currentFull; + + public void Click() + { + GetComponentInParent<MultiOptions>().ClickRessButton(this); + } +} diff --git a/ROUNDS/MusicGridVisualizer.cs b/ROUNDS/MusicGridVisualizer.cs new file mode 100644 index 0000000..c7fc064 --- /dev/null +++ b/ROUNDS/MusicGridVisualizer.cs @@ -0,0 +1,13 @@ +public class MusicGridVisualizer : GridVisualizer +{ + private void Update() + { + for (int i = 0; i < numberOfObjects.x; i++) + { + for (int j = 0; j < numberOfObjects.y; j++) + { + spawnedObjects[i, j].OnSetSize(MusicVisualizerData.Samples[i + j] * 200f); + } + } + } +} diff --git a/ROUNDS/MusicVisualizerData.cs b/ROUNDS/MusicVisualizerData.cs new file mode 100644 index 0000000..078940e --- /dev/null +++ b/ROUNDS/MusicVisualizerData.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class MusicVisualizerData : MonoBehaviour +{ + public static float[] Samples = new float[512]; + + private AudioSource m_audioSource; + + private void Awake() + { + m_audioSource = GetComponent<AudioSource>(); + } + + private void Update() + { + m_audioSource.GetSpectrumData(Samples, 0, FFTWindow.Blackman); + } +} diff --git a/ROUNDS/NetworkConnectionHandler.cs b/ROUNDS/NetworkConnectionHandler.cs new file mode 100644 index 0000000..b55d8bc --- /dev/null +++ b/ROUNDS/NetworkConnectionHandler.cs @@ -0,0 +1,450 @@ +using System; +using System.Collections; +using ExitGames.Client.Photon; +using Landfall.Network; +using Photon.Pun; +using Photon.Realtime; +using SoundImplementation; +using Steamworks; +using UnityEngine; + +public class NetworkConnectionHandler : MonoBehaviourPunCallbacks +{ + public static readonly string TWITCH_PLAYER_SCORE_KEY = "TwitchScore"; + + public static readonly string TWITCH_ROOM_AUDIENCE_RATING_KEY = "C0"; + + public static NetworkConnectionHandler instance; + + private static ClientSteamLobby m_SteamLobby; + + private bool m_SearchingQuickMatch; + + private bool m_SearchingTwitch; + + private int currentViewers = 100; + + private TypedLobby sqlLobby = new TypedLobby("customSqlLobby", LobbyType.SqlLobby); + + public bool hasRegionSelect; + + private bool m_ForceRegion; + + private bool isConnectedToMaster; + + private float untilTryOtherRegionCounter; + + private void Start() + { + instance = this; + PhotonNetwork.ServerPortOverrides = PhotonPortDefinition.AlternativeUdpPorts; + PhotonNetwork.CrcCheckEnabled = true; + PhotonNetwork.NetworkingClient.LoadBalancingPeer.DisconnectTimeout = 30000; + if (m_SteamLobby == null) + { + m_SteamLobby = new ClientSteamLobby(); + } + else + { + m_SteamLobby.LeaveLobby(); + } + } + + private void Update() + { + if (m_SearchingQuickMatch && PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode && !GM_ArmsRace.instance) + { + untilTryOtherRegionCounter -= Time.deltaTime; + if (untilTryOtherRegionCounter < 0f) + { + StartCoroutine(PlayOnBestActiveRegion()); + } + } + } + + public void QuickMatch() + { + m_SearchingQuickMatch = true; + m_SearchingTwitch = false; + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(); + StartCoroutine(DoActionWhenConnected(JoinRandomRoom)); + } + + public void TwitchJoin(int score) + { + currentViewers = Mathf.Clamp(score, 1, score); + m_SearchingQuickMatch = false; + m_SearchingTwitch = true; + ExitGames.Client.Photon.Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; + if (customProperties.ContainsKey(TWITCH_PLAYER_SCORE_KEY)) + { + customProperties[TWITCH_PLAYER_SCORE_KEY] = score; + } + else + { + customProperties.Add(TWITCH_PLAYER_SCORE_KEY, score); + } + PhotonNetwork.LocalPlayer.SetCustomProperties(customProperties); + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(); + StartCoroutine(DoActionWhenConnected(JoinSpecificTWITCHRoom)); + } + + public void HostPrivateAndInviteFriend() + { + m_SearchingQuickMatch = false; + m_SearchingTwitch = false; + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(privateGame: true); + RoomOptions options = new RoomOptions(); + options.MaxPlayers = 2; + options.IsOpen = true; + options.IsVisible = false; + m_SteamLobby.ShowInviteScreenWhenConnected(); + StartCoroutine(DoActionWhenConnected(delegate + { + CreateRoom(options); + })); + } + + private void JoinRandomRoom() + { + Debug.Log("Joining random room"); + PhotonNetwork.JoinRandomRoom(); + } + + private void CreateSpecificTWITCHRoom() + { + Debug.Log("Creating SPECIFIC TWITCH ROOM!"); + RoomOptions roomOptions = new RoomOptions(); + roomOptions.CustomRoomProperties = new ExitGames.Client.Photon.Hashtable { { TWITCH_ROOM_AUDIENCE_RATING_KEY, currentViewers } }; + roomOptions.CustomRoomPropertiesForLobby = new string[1] { TWITCH_ROOM_AUDIENCE_RATING_KEY }; + PhotonNetwork.CreateRoom(null, roomOptions, sqlLobby); + } + + private void JoinSpecificTWITCHRoom() + { + Debug.Log("JOINING SPECIFIC TWITCH ROOM!"); + int num = 5; + int num2 = currentViewers * num; + int num3 = currentViewers / num; + int num4 = 10; + int num5 = currentViewers * num4; + int num6 = currentViewers / num4; + int num7 = 10000000; + int num8 = currentViewers * num7; + int num9 = currentViewers / num7; + string text = ""; + text = text + "C0 BETWEEN " + num3 + " AND " + num2 + ";"; + text = text + "C0 BETWEEN " + num6 + " AND " + num5 + ";"; + text = text + "C0 BETWEEN " + num9 + " AND " + num8; + PhotonNetwork.JoinRandomRoom(null, 0, MatchmakingMode.FillRoom, sqlLobby, text); + } + + public override void OnJoinRoomFailed(short returnCode, string message) + { + Debug.Log("JOINED RANDOM ROOM FAILED!"); + if (!m_SearchingTwitch) + { + JoinRandomRoom(); + } + else + { + CreateSpecificTWITCHRoom(); + } + } + + private IEnumerator DoActionWhenConnected(Action action) + { + yield return WaitForConnect(); + action(); + } + + private IEnumerator PlayOnBestActiveRegion() + { + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + while (PhotonNetwork.InRoom) + { + yield return null; + } + } + string[] regionsToTry = new string[13] + { + "usw", "eu", "us", "au", "ru", "za", "asia", "cae", "in", "jp", + "rue", "sa", "kr" + }; + float bestRegionScore = 0f; + string bestRegion = ""; + for (int i = 0; i < regionsToTry.Length; i++) + { + isConnectedToMaster = false; + PhotonNetwork.Disconnect(); + while (PhotonNetwork.IsConnected) + { + yield return null; + } + PhotonNetwork.ConnectToRegion(regionsToTry[i]); + Debug.Log("connectToRegion " + regionsToTry[i]); + isConnectedToMaster = false; + while (!isConnectedToMaster) + { + yield return null; + } + int countOfPlayersInRooms = PhotonNetwork.CountOfPlayersInRooms; + int ping = PhotonNetwork.GetPing(); + float num = (float)Mathf.Clamp(countOfPlayersInRooms, 0, 50) / Mathf.Clamp(ping, 10f, 1E+11f); + Debug.Log("Ping: " + Mathf.Clamp(PhotonNetwork.GetPing(), 10f, 1E+11f)); + Debug.Log(regionsToTry[i] + ": " + PhotonNetwork.CountOfPlayersInRooms); + if (num > bestRegionScore) + { + bestRegion = regionsToTry[i]; + bestRegionScore = num; + if (ping < 50 && countOfPlayersInRooms > 50) + { + break; + } + } + } + isConnectedToMaster = false; + PhotonNetwork.Disconnect(); + PhotonNetwork.LocalPlayer.NickName = "PlayerName"; + if (bestRegion == "") + { + PhotonNetwork.ConnectToBestCloudServer(); + } + else + { + Debug.Log("Connecting to " + bestRegion); + PhotonNetwork.ConnectToRegion(bestRegion); + } + while (!isConnectedToMaster) + { + yield return null; + } + JoinRandomRoom(); + } + + private IEnumerator WaitForConnect() + { + if (!PhotonNetwork.IsConnectedAndReady) + { + PhotonNetwork.LocalPlayer.NickName = "PlayerName"; + PhotonNetwork.ConnectUsingSettings(); + if (hasRegionSelect || m_ForceRegion) + { + PhotonNetwork.ConnectToRegion(RegionSelector.region); + } + else + { + PhotonNetwork.ConnectToBestCloudServer(); + } + } + while (!isConnectedToMaster) + { + Debug.Log("Trying to connect to photon"); + yield return null; + } + Debug.Log("Is connected"); + } + + public void ForceRegionJoin(string region, string room) + { + Debug.Log("CREEASDSSD"); + if (PhotonNetwork.InRoom) + { + PhotonNetwork.Disconnect(); + } + CharacterCreatorHandler.instance.CloseMenus(); + MainMenuHandler.instance.Close(); + RegionSelector.region = region; + TimeHandler.instance.gameStartTime = 1f; + LoadingScreen.instance?.StartLoading(); + m_ForceRegion = true; + StartCoroutine(DoActionWhenConnected(delegate + { + JoinSpecificRoom(room); + })); + } + + private void JoinSpecificRoom(string room) + { + PhotonNetwork.JoinRoom(room); + m_ForceRegion = false; + } + + public override void OnEnable() + { + base.OnEnable(); + Debug.Log("Add me!"); + PhotonNetwork.AddCallbackTarget(this); + } + + public override void OnDisable() + { + base.OnDisable(); + Debug.Log("Remove me!"); + PhotonNetwork.RemoveCallbackTarget(this); + } + + public override void OnConnectedToMaster() + { + isConnectedToMaster = true; + } + + public override void OnJoinRandomFailed(short returnCode, string message) + { + Debug.Log("JOINED RANDOM ROOM FAILED!"); + if (m_SearchingTwitch) + { + CreateSpecificTWITCHRoom(); + return; + } + RoomOptions roomOptions = new RoomOptions(); + roomOptions.MaxPlayers = 2; + roomOptions.IsOpen = true; + roomOptions.IsVisible = true; + if (!SteamManager.Initialized) + { + Debug.LogError("SteamManager is not initialized!"); + } + else + { + CreateRoom(roomOptions); + } + } + + private void CreateRoom(RoomOptions roomOptions) + { + m_SteamLobby.CreateLobby(roomOptions.MaxPlayers, delegate(string RoomName) + { + PhotonNetwork.CreateRoom(RoomName, roomOptions); + }); + } + + public override void OnJoinedRoom() + { + if (!PhotonNetwork.OfflineMode) + { + isConnectedToMaster = false; + Debug.Log("Room joined successfully"); + Debug.Log(PhotonNetwork.CloudRegion); + untilTryOtherRegionCounter = 15f; + PhotonNetwork.LocalPlayer.NickName = (m_SearchingTwitch ? TwitchUIHandler.TWITCH_NAME_KEY : SteamFriends.GetPersonaName()); + } + } + + public override void OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer) + { + SoundPlayerStatic.Instance.PlayPlayerAdded(); + if (PhotonNetwork.PlayerList.Length == 2) + { + if (PhotonNetwork.IsMasterClient) + { + GetComponent<PhotonView>().RPC("RPCA_FoundGame", RpcTarget.All); + } + if (m_SteamLobby != null) + { + m_SteamLobby.HideLobby(); + } + } + Debug.Log("PlayerJoined"); + base.OnPlayerEnteredRoom(newPlayer); + } + + [PunRPC] + private void RPCA_FoundGame() + { + LoadingScreen.instance?.StopLoading(); + } + + public override void OnLeftRoom() + { + isConnectedToMaster = false; + } + + public override void OnPlayerLeftRoom(Photon.Realtime.Player otherPlayer) + { + _ = GM_ArmsRace.instance == null; + StartCoroutine(DoDisconnect("DISCONNECTED", "Other player left")); + base.OnPlayerLeftRoom(otherPlayer); + } + + public override void OnDisconnected(DisconnectCause cause) + { + if (cause != 0 && cause != DisconnectCause.DisconnectByClientLogic) + { + StartCoroutine(DoDisconnect("DISCONNECTED", cause.ToString())); + isConnectedToMaster = false; + } + } + + private IEnumerator DoRetry() + { + LoadingScreen.instance.StartLoading(); + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + while (PhotonNetwork.InRoom) + { + yield return null; + } + } + JoinRandomRoom(); + } + + private IEnumerator DoDisconnect(string context, string reason) + { + ErrorHandler.instance.ShowError(context, reason); + yield return new WaitForSecondsRealtime(2f); + ErrorHandler.instance.HideError(); + NetworkRestart(); + } + + public override void OnRegionListReceived(RegionHandler regionHandler) + { + Debug.Log(regionHandler); + } + + public void NetworkRestart() + { + isConnectedToMaster = false; + if (PhotonNetwork.OfflineMode) + { + Application.LoadLevel(Application.loadedLevel); + } + else + { + StartCoroutine(WaitForRestart()); + } + } + + private IEnumerator WaitForRestart() + { + if (m_SteamLobby != null) + { + m_SteamLobby.LeaveLobby(); + } + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + while (PhotonNetwork.InRoom) + { + yield return null; + } + } + if (PhotonNetwork.IsConnected) + { + PhotonNetwork.Disconnect(); + while (PhotonNetwork.IsConnected) + { + yield return null; + } + } + EscapeMenuHandler.isEscMenu = false; + DevConsole.isTyping = false; + Application.LoadLevel(Application.loadedLevel); + } +} diff --git a/ROUNDS/NetworkData.cs b/ROUNDS/NetworkData.cs new file mode 100644 index 0000000..293da46 --- /dev/null +++ b/ROUNDS/NetworkData.cs @@ -0,0 +1,58 @@ +using Photon.Pun; +using UnityEngine; + +public class NetworkData : MonoBehaviour +{ + private PhotonView photonView; + + private bool inited; + + private void Start() + { + photonView = GetComponent<PhotonView>(); + } + + private void Init() + { + if (!inited) + { + inited = true; + if (PhotonNetwork.IsMasterClient) + { + Debug.Log("Why am i the master?"); + } + } + } + + private void Update() + { + if (PhotonNetwork.InRoom) + { + Init(); + } + } + + private void RequestJoin() + { + photonView.RPC("RequestJoinMaster", RpcTarget.MasterClient); + Debug.Log("Request join"); + } + + [PunRPC] + public void RequestJoinMaster() + { + string text = JsonUtility.ToJson(new InitPackage + { + currentMapID = MapManager.instance.currentLevelID + }); + photonView.RPC("RequestJoinResponse", RpcTarget.Others, text); + } + + [PunRPC] + public void RequestJoinResponse(string jsonResponse) + { + InitPackage initPackage = (InitPackage)JsonUtility.FromJson(jsonResponse, typeof(InitPackage)); + MapManager.instance.LoadLevelFromID(initPackage.currentMapID, onlyMaster: false, callInImidetly: true); + Debug.Log("Got response"); + } +} diff --git a/ROUNDS/NetworkPhysicsObject.cs b/ROUNDS/NetworkPhysicsObject.cs new file mode 100644 index 0000000..9ffb4d6 --- /dev/null +++ b/ROUNDS/NetworkPhysicsObject.cs @@ -0,0 +1,248 @@ +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class NetworkPhysicsObject : MonoBehaviour, IPunObservable +{ + [Header("Sounds")] + public SoundEvent soundBoxImpact; + + public float soundPitchSemitone; + + private SoundParameterPitchSemitone soundParameterPitchSemitone = new SoundParameterPitchSemitone(); + + private SoundParameterIntensity soundParameterIntensity = new SoundParameterIntensity(); + + [Header("Settings")] + public PhotonView photonView; + + private Rigidbody2D rig2D; + + private Collider2D col; + + public int sendFreq = 5; + + private int currentFrame; + + private float lastTime; + + private List<ObjectSyncPackage> syncPackages = new List<ObjectSyncPackage>(); + + private float sinceCol; + + public float collisionThreshold; + + public float shakeAmount; + + public float maxShake; + + public float playerColThreshold = 1f; + + public float dmgAmount = 1f; + + public float forceAmount = 1f; + + private float sinceDealDMG; + + private List<Player> hitPlayers = new List<Player>(); + + public float speed = 100f; + + private float sinceRequest; + + private float sincePushed; + + public float bulletPushMultiplier = 1f; + + private Vector2 currentForceToSend; + + private Vector2 currentForcePos; + + private float sendForceRate = 0.1f; + + private float sendForceCounter; + + public float sleepThreshold = 1f; + + public void Awake() + { + soundParameterPitchSemitone.pitchSemitone = soundPitchSemitone; + currentFrame = Random.Range(0, sendFreq); + photonView = GetComponent<PhotonView>(); + col = GetComponent<Collider2D>(); + rig2D = GetComponent<Rigidbody2D>(); + } + + private void Update() + { + if (!photonView) + { + return; + } + sinceRequest += Time.deltaTime; + sinceDealDMG += Time.deltaTime; + sendForceCounter += Time.deltaTime; + if (sendForceCounter > sendForceRate) + { + _ = photonView.IsMine; + if (currentForceToSend != Vector2.zero) + { + photonView.RPC("RPCA_SendForce", photonView.Owner, currentForceToSend, currentForcePos); + sendForceCounter = 0f; + currentForceToSend = Vector2.zero; + } + } + if (syncPackages.Count > 0) + { + if (syncPackages[0].timeDelta > 0f) + { + syncPackages[0].timeDelta -= Time.deltaTime * 1.5f * (1f + (float)syncPackages.Count * 0.5f); + } + else + { + if (syncPackages.Count > 2) + { + syncPackages.RemoveAt(0); + } + rig2D.isKinematic = false; + base.transform.position = syncPackages[0].pos; + base.transform.rotation = Quaternion.LookRotation(Vector3.forward, syncPackages[0].rot); + rig2D.velocity = syncPackages[0].vel; + rig2D.angularVelocity = syncPackages[0].angularVel; + syncPackages.RemoveAt(0); + } + } + sinceCol += Time.deltaTime; + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + currentFrame++; + if (stream.IsWriting) + { + if (currentFrame >= sendFreq) + { + currentFrame = 0; + stream.SendNext((Vector2)base.transform.position); + stream.SendNext((Vector2)base.transform.up); + stream.SendNext(rig2D.velocity); + stream.SendNext(rig2D.angularVelocity); + if (lastTime == 0f) + { + lastTime = Time.time; + } + stream.SendNext(Time.time - lastTime); + lastTime = Time.time; + } + } + else + { + ObjectSyncPackage objectSyncPackage = new ObjectSyncPackage(); + objectSyncPackage.pos = (Vector2)stream.ReceiveNext(); + objectSyncPackage.rot = (Vector2)stream.ReceiveNext(); + objectSyncPackage.vel = (Vector2)stream.ReceiveNext(); + objectSyncPackage.angularVel = (float)stream.ReceiveNext(); + objectSyncPackage.timeDelta = (float)stream.ReceiveNext(); + syncPackages.Add(objectSyncPackage); + } + } + + [PunRPC] + public void RPCA_Collide(Vector2 colForce) + { + soundParameterIntensity.intensity = colForce.magnitude; + SoundManager.Instance.PlayAtPosition(soundBoxImpact, SoundManager.Instance.GetTransform(), base.transform, soundParameterIntensity, soundParameterPitchSemitone); + GamefeelManager.instance.AddGameFeel(colForce); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + if (photonView.IsMine && !(collision.contacts[0].normalImpulse < collisionThreshold) && !(sinceCol < 0.1f)) + { + sinceCol = 0f; + photonView.RPC("RPCA_Collide", RpcTarget.All, Mathf.Clamp(collision.contacts[0].normalImpulse, 0f, maxShake) * collision.contacts[0].normal * shakeAmount); + } + } + + private void OnPlayerCollision(Vector2 collision, CharacterData player) + { + if (!player.view.IsMine || sinceDealDMG < 1f) + { + return; + } + Vector3 vector = collision * dmgAmount; + if (!(vector.magnitude < playerColThreshold)) + { + float num = Mathf.Pow(rig2D.mass / 20000f, 2f); + float num2 = Mathf.Pow(rig2D.mass / 20000f, 0.5f); + player.healthHandler.CallTakeDamage(vector * 0.3f * num, player.transform.position); + player.healthHandler.CallTakeForce(collision * forceAmount * num2, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: false, vector.magnitude * 0.05f); + if (player.block.IsBlocking()) + { + rig2D.velocity *= -1.1f; + rig2D.angularVelocity *= -1.1f; + } + else if (rig2D.mass < 80000f) + { + rig2D.velocity *= -0.5f * (20000f / rig2D.mass); + rig2D.angularVelocity *= -0.5f * (20000f / rig2D.mass); + } + sinceDealDMG = 0f; + photonView.RPC("RPCA_PlayerCollision", RpcTarget.AllViaServer, collision, rig2D.velocity, base.transform.position, player.view.ViewID); + } + } + + [PunRPC] + public void RPCM_RequestCollide(Vector2 collision, Vector2 afterVel, Vector3 position, int playerId) + { + photonView.RPC("RPCA_PlayerCollision", RpcTarget.AllViaServer, collision, afterVel, position, playerId); + } + + [PunRPC] + private void RPCA_PlayerCollision(Vector2 collision, Vector2 velAfter, Vector3 position, int playerID) + { + CharacterData component = PhotonNetwork.GetPhotonView(playerID).GetComponent<CharacterData>(); + base.transform.position = position; + rig2D.velocity = velAfter; + sinceDealDMG = 0f; + StartCoroutine(component.GetComponent<PlayerCollision>().IDoBounce(component.playerVel.velocity)); + } + + public void BulletPush(Vector2 force, Vector2 localPoint, CharacterData asker) + { + if (photonView.IsMine) + { + rig2D.AddForceAtPosition(force * bulletPushMultiplier, base.transform.TransformPoint(localPoint), ForceMode2D.Impulse); + } + } + + [PunRPC] + public void RPCA_SendForce(Vector2 forceSent, Vector2 sentForcePos) + { + rig2D.AddForceAtPosition(forceSent, base.transform.TransformPoint(currentForcePos)); + } + + public Vector3 Push(CharacterData data) + { + if (!data.view.IsMine) + { + return Vector3.zero; + } + sincePushed = 0f; + Vector2 vector = data.input.direction * 8f; + Vector2 vector2 = col.bounds.ClosestPoint(data.transform.position); + float num = Vector2.Angle(vector, vector2 - (Vector2)data.transform.position); + float num2 = (90f - num) / 90f; + Vector2 vector3 = TimeHandler.fixedDeltaTime * vector * num2 * speed * 1000f; + currentForceToSend += vector3; + currentForcePos = base.transform.InverseTransformPoint(vector2); + float num3 = Mathf.Clamp((Vector2.Angle(rig2D.velocity, (Vector2)base.transform.position - (Vector2)data.transform.position) - 90f) / 90f, 0f, 1f); + OnPlayerCollision(rig2D.velocity * num3, data); + return -vector; + } + + public void RequestOwnership(CharacterData player) + { + } +} diff --git a/ROUNDS/NetworkPlayer.cs b/ROUNDS/NetworkPlayer.cs new file mode 100644 index 0000000..47619c9 --- /dev/null +++ b/ROUNDS/NetworkPlayer.cs @@ -0,0 +1,4 @@ +public class NetworkPlayer +{ + private int playerID; +} diff --git a/ROUNDS/NetworkSettings.cs b/ROUNDS/NetworkSettings.cs new file mode 100644 index 0000000..1375488 --- /dev/null +++ b/ROUNDS/NetworkSettings.cs @@ -0,0 +1,11 @@ +using Photon.Pun; +using UnityEngine; + +public class NetworkSettings : MonoBehaviour +{ + private void Start() + { + PhotonNetwork.SendRate = 30; + PhotonNetwork.SerializationRate = 30; + } +} diff --git a/ROUNDS/NewScript.cs b/ROUNDS/NewScript.cs new file mode 100644 index 0000000..8bde104 --- /dev/null +++ b/ROUNDS/NewScript.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class NewScript : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/NextArt.cs b/ROUNDS/NextArt.cs new file mode 100644 index 0000000..9300887 --- /dev/null +++ b/ROUNDS/NextArt.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class NextArt : MonoBehaviour +{ + private void Start() + { + ArtHandler.instance.NextArt(); + } +} diff --git a/ROUNDS/ObjectParticle.cs b/ROUNDS/ObjectParticle.cs new file mode 100644 index 0000000..5e3927b --- /dev/null +++ b/ROUNDS/ObjectParticle.cs @@ -0,0 +1,34 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; + +[Serializable] +public class ObjectParticle +{ + public float size = 1f; + + public AnimationCurve sizeOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); + + public float lifetime = 1f; + + public float rotation; + + public float randomRotation; + + [FoldoutGroup("Color", 0)] + public Color color = Color.magenta; + + [FoldoutGroup("Color", 0)] + public Color randomColor = Color.magenta; + + [FoldoutGroup("Color", 0)] + public Color randomAddedColor = Color.black; + + [FoldoutGroup("Color", 0)] + public float randomAddedSaturation; + + [FoldoutGroup("Color", 0)] + public bool singleRandomValueColor = true; + + public AnimationCurve alphaOverTime = AnimationCurve.Linear(0f, 1f, 1f, 1f); +} diff --git a/ROUNDS/ObjectPool.cs b/ROUNDS/ObjectPool.cs new file mode 100644 index 0000000..b17adae --- /dev/null +++ b/ROUNDS/ObjectPool.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using UnityEngine; + +public class ObjectPool +{ + private Stack<GameObject> m_availableObjects = new Stack<GameObject>(); + + private List<GameObject> m_usedObjects = new List<GameObject>(); + + private GameObject m_objectPrefab; + + private Transform m_objectRoot; + + private int testCounter = 1; + + public ObjectPool(GameObject prefab, int initSpawn = 0, Transform parent = null) + { + m_objectPrefab = prefab; + m_objectRoot = new GameObject(prefab.name + "_root").transform; + m_objectRoot.transform.position = parent.position; + m_objectRoot.transform.rotation = parent.rotation; + m_objectRoot.transform.SetParent(parent, worldPositionStays: true); + m_objectRoot.transform.localScale = Vector3.one; + for (int i = 0; i < initSpawn; i++) + { + GameObject gameObject = Object.Instantiate(m_objectPrefab, m_objectRoot); + gameObject.SetActive(value: false); + m_availableObjects.Push(gameObject); + } + } + + public GameObject GetObject() + { + if (m_availableObjects.Count > 0) + { + GameObject gameObject = m_availableObjects.Pop(); + m_usedObjects.Add(gameObject); + gameObject.SetActive(value: true); + return gameObject; + } + GameObject gameObject2 = Object.Instantiate(m_objectPrefab, m_objectRoot); + m_usedObjects.Add(gameObject2); + gameObject2.SetActive(value: true); + return gameObject2; + } + + public bool ReleaseObject(GameObject obj) + { + bool num = m_usedObjects.Remove(obj); + if (num) + { + m_availableObjects.Push(obj); + obj.SetActive(value: false); + } + return num; + } + + public void ClearPool() + { + while (m_availableObjects.Count > 0) + { + Object.Destroy(m_availableObjects.Pop()); + } + for (int i = 0; i < m_usedObjects.Count; i++) + { + Object.Destroy(m_usedObjects[i]); + } + m_usedObjects.Clear(); + } +} diff --git a/ROUNDS/ObjectScaleToBulletStats.cs b/ROUNDS/ObjectScaleToBulletStats.cs new file mode 100644 index 0000000..da5e7d6 --- /dev/null +++ b/ROUNDS/ObjectScaleToBulletStats.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class ObjectScaleToBulletStats : MonoBehaviour +{ + public GameObject target; + + public float dmgAmount = 1f; + + public float speedAmount = 1f; + + private void Start() + { + ProjectileHit component = GetComponent<ProjectileHit>(); + MoveTransform component2 = GetComponent<MoveTransform>(); + if ((bool)component) + { + component.damage = Mathf.Lerp(component.damage, component.damage * target.transform.localScale.x, dmgAmount); + } + if ((bool)component2) + { + component2.localForce.z = Mathf.Lerp(component2.localForce.z, component2.localForce.z * target.transform.localScale.x, speedAmount); + } + } +} diff --git a/ROUNDS/ObjectShake.cs b/ROUNDS/ObjectShake.cs new file mode 100644 index 0000000..f4e8059 --- /dev/null +++ b/ROUNDS/ObjectShake.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class ObjectShake : MonoBehaviour +{ + public float globalMultiplier = 1f; + + public float interval = 0.1f; + + public float movementMultiplier = 1f; + + public float rotationMultiplier = 1f; + + private float counter; + + private void Start() + { + } + + private void Update() + { + counter += TimeHandler.deltaTime; + if (counter > interval) + { + base.transform.localPosition = Random.insideUnitCircle * movementMultiplier * globalMultiplier * 0.1f; + base.transform.localEulerAngles = new Vector3(base.transform.localEulerAngles.x, base.transform.localEulerAngles.y, (float)Random.Range(-10, 10) * globalMultiplier * rotationMultiplier); + counter = 0f; + } + } +} diff --git a/ROUNDS/ObjectSyncPackage.cs b/ROUNDS/ObjectSyncPackage.cs new file mode 100644 index 0000000..7affc5f --- /dev/null +++ b/ROUNDS/ObjectSyncPackage.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class ObjectSyncPackage +{ + public Vector2 pos; + + public Vector2 rot; + + public Vector2 vel; + + public float angularVel; + + public float timeDelta; +} diff --git a/ROUNDS/ObjectsToSpawn.cs b/ROUNDS/ObjectsToSpawn.cs new file mode 100644 index 0000000..cf688ce --- /dev/null +++ b/ROUNDS/ObjectsToSpawn.cs @@ -0,0 +1,123 @@ +using System; +using Sirenix.OdinInspector; +using UnityEngine; + +[Serializable] +public class ObjectsToSpawn +{ + public enum Direction + { + forward, + normal, + identity + } + + public enum SpawnOn + { + all, + player, + notPlayer + } + + [FoldoutGroup("OnHit", 0)] + public GameObject effect; + + [FoldoutGroup("OnHit", 0)] + public Direction direction; + + [FoldoutGroup("OnHit", 0)] + public SpawnOn spawnOn; + + [FoldoutGroup("OnHit", 0)] + public bool spawnAsChild; + + [FoldoutGroup("OnHit", 0)] + public int numberOfSpawns = 1; + + [FoldoutGroup("OnHit", 0)] + public float normalOffset; + + [FoldoutGroup("OnHit", 0)] + public bool stickToBigTargets; + + [FoldoutGroup("OnHit", 0)] + public bool stickToAllTargets; + + [FoldoutGroup("OnHit", 0)] + public bool zeroZ; + + [FoldoutGroup("OnProjectile", 0)] + public GameObject AddToProjectile; + + [FoldoutGroup("OnProjectile", 0)] + public bool removeScriptsFromProjectileObject; + + [FoldoutGroup("Stacking", 0)] + public bool scaleStacks; + + [FoldoutGroup("Stacking", 0)] + public float scaleStackM = 0.5f; + + [FoldoutGroup("Scaling", 0)] + public float scaleFromDamage; + + [HideInInspector] + public int stacks; + + public static GameObject[] SpawnObject(Transform spawnerTransform, HitInfo hit, ObjectsToSpawn objectToSpawn, HealthHandler playerHealth, PlayerSkin playerSkins, float damage = 55f, SpawnedAttack spawnedAttack = null, bool wasBlocked = false) + { + GameObject[] array = new GameObject[objectToSpawn.numberOfSpawns]; + for (int i = 0; i < objectToSpawn.numberOfSpawns; i++) + { + if (wasBlocked && objectToSpawn.stickToAllTargets) + { + continue; + } + Vector3 position = (Vector3)hit.point + (Vector3)hit.normal * objectToSpawn.normalOffset + (objectToSpawn.zeroZ ? Vector3.zero : (Vector3.forward * 5f)); + Quaternion rotation = Quaternion.LookRotation(spawnerTransform.forward); + if (objectToSpawn.direction == Direction.normal) + { + rotation = Quaternion.LookRotation(hit.normal + Vector2.right * 0.005f); + } + if (objectToSpawn.direction == Direction.identity) + { + rotation = Quaternion.identity; + } + if ((objectToSpawn.spawnOn != SpawnOn.notPlayer || !playerHealth) && (objectToSpawn.spawnOn != SpawnOn.player || (bool)playerHealth) && (bool)objectToSpawn.effect) + { + GameObject gameObject = UnityEngine.Object.Instantiate(objectToSpawn.effect, position, rotation); + if (objectToSpawn.spawnAsChild && (bool)hit.transform) + { + gameObject.transform.SetParent(hit.transform, worldPositionStays: true); + } + if ((bool)spawnedAttack) + { + spawnedAttack.CopySpawnedAttackTo(gameObject); + } + array[i] = gameObject; + SetTeamColor.TeamColorThis(gameObject, playerSkins); + if ((objectToSpawn.stickToBigTargets && !playerHealth && (!hit.rigidbody || hit.rigidbody.mass > 500f)) || objectToSpawn.stickToAllTargets) + { + gameObject.AddComponent<FollowLocalPos>().Follow(hit.transform); + } + if (objectToSpawn.scaleFromDamage != 0f) + { + gameObject.transform.localScale *= 1f * (1f - objectToSpawn.scaleFromDamage) + damage / 55f * objectToSpawn.scaleFromDamage; + } + if (objectToSpawn.scaleStacks) + { + gameObject.transform.localScale *= 1f + (float)objectToSpawn.stacks * objectToSpawn.scaleStackM; + } + } + } + return array; + } + + public static void SpawnObject(ObjectsToSpawn objectToSpawn, Vector3 position, Quaternion rotation) + { + for (int i = 0; i < objectToSpawn.numberOfSpawns; i++) + { + UnityEngine.Object.Instantiate(objectToSpawn.effect, position, rotation); + } + } +} diff --git a/ROUNDS/OnlineNameSelect.cs b/ROUNDS/OnlineNameSelect.cs new file mode 100644 index 0000000..c9fd43a --- /dev/null +++ b/ROUNDS/OnlineNameSelect.cs @@ -0,0 +1,21 @@ +using Photon.Pun; +using TMPro; +using UnityEngine; + +public class OnlineNameSelect : MonoBehaviour +{ + private TMP_InputField nameField; + + private void Start() + { + nameField = GetComponentInChildren<TMP_InputField>(); + nameField.text = PlayerPrefs.GetString("PlayerName", ""); + PhotonNetwork.LocalPlayer.NickName = nameField.text; + } + + public void OnChangedVal(string newVal) + { + PlayerPrefs.SetString("PlayerName", nameField.text); + PhotonNetwork.LocalPlayer.NickName = nameField.text; + } +} diff --git a/ROUNDS/OnlyOneEdgeModifier.cs b/ROUNDS/OnlyOneEdgeModifier.cs new file mode 100644 index 0000000..080423c --- /dev/null +++ b/ROUNDS/OnlyOneEdgeModifier.cs @@ -0,0 +1,57 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Only One Edge")] +public class OnlyOneEdgeModifier : ProceduralImageModifier +{ + public enum ProceduralImageEdge + { + Top, + Bottom, + Left, + Right + } + + [SerializeField] + private float radius; + + [SerializeField] + private ProceduralImageEdge side; + + public float Radius + { + get + { + return radius; + } + set + { + radius = value; + base._Graphic.SetVerticesDirty(); + } + } + + public ProceduralImageEdge Side + { + get + { + return side; + } + set + { + side = value; + } + } + + public override Vector4 CalculateRadius(Rect imageRect) + { + return side switch + { + ProceduralImageEdge.Top => new Vector4(radius, radius, 0f, 0f), + ProceduralImageEdge.Right => new Vector4(0f, radius, radius, 0f), + ProceduralImageEdge.Bottom => new Vector4(0f, 0f, radius, radius), + ProceduralImageEdge.Left => new Vector4(radius, 0f, 0f, radius), + _ => new Vector4(0f, 0f, 0f, 0f), + }; + } +} diff --git a/ROUNDS/OptionsButton.cs b/ROUNDS/OptionsButton.cs new file mode 100644 index 0000000..f33bfc6 --- /dev/null +++ b/ROUNDS/OptionsButton.cs @@ -0,0 +1,204 @@ +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class OptionsButton : MonoBehaviour +{ + public enum SettingsTarget + { + Resolution, + Vol_Master, + Vol_SFX, + Vol_Music, + CharacterPattern, + MapPattern, + leftStickAim, + lockAimDirections, + ShowCardStarts, + FullScreen, + FreeStickAim, + Vsync + } + + public enum SettingsType + { + Binary, + Slider, + MultiOption + } + + public SettingsTarget settingsTarget; + + public SettingsType settingsType; + + public bool currentBoolValue; + + public Resolution currentResolutionValue; + + public Optionshandler.FullScreenOption currentFullscreenValue; + + public float currentFloatValue; + + private TextMeshProUGUI text; + + public Slider slider; + + private void Awake() + { + text = GetComponentsInChildren<TextMeshProUGUI>(includeInactive: true)[1]; + if (settingsType == SettingsType.Slider) + { + slider = GetComponentInChildren<Slider>(includeInactive: true); + slider.onValueChanged.AddListener(SliderSlide); + } + else + { + GetComponent<Button>().onClick.AddListener(ClickButton); + } + } + + private void OnEnable() + { + switch (settingsTarget) + { + case SettingsTarget.Resolution: + currentResolutionValue = Optionshandler.resolution; + break; + case SettingsTarget.Vol_Master: + currentFloatValue = Optionshandler.vol_Master; + break; + case SettingsTarget.Vol_SFX: + currentFloatValue = Optionshandler.vol_Sfx; + break; + case SettingsTarget.Vol_Music: + currentFloatValue = Optionshandler.vol_Music; + break; + case SettingsTarget.CharacterPattern: + currentBoolValue = Optionshandler.characterPattrens; + break; + case SettingsTarget.MapPattern: + currentBoolValue = Optionshandler.mapPatterns; + break; + case SettingsTarget.leftStickAim: + currentBoolValue = Optionshandler.leftStickAim; + break; + case SettingsTarget.lockAimDirections: + currentBoolValue = Optionshandler.lockMouse; + break; + case SettingsTarget.FreeStickAim: + currentBoolValue = Optionshandler.lockStick; + break; + case SettingsTarget.ShowCardStarts: + currentBoolValue = Optionshandler.showCardStatNumbers; + break; + case SettingsTarget.FullScreen: + currentFullscreenValue = Optionshandler.fullScreen; + break; + case SettingsTarget.Vsync: + currentBoolValue = Optionshandler.vSync; + break; + } + if (settingsType == SettingsType.Slider) + { + slider.value = currentFloatValue; + } + ReDraw(); + } + + public void SetResolutionAndFullscreen(Resolution newRess, Optionshandler.FullScreenOption fullScreen) + { + currentResolutionValue = newRess; + currentFullscreenValue = fullScreen; + ClickButton(); + if (settingsTarget == SettingsTarget.Resolution) + { + Optionshandler.instance.SetResolution(newRess); + } + if (settingsTarget == SettingsTarget.FullScreen) + { + Optionshandler.instance.SetFullScreen(fullScreen); + } + } + + public void SliderChanged() + { + currentFloatValue = slider.value; + } + + private void SliderSlide(float newVal) + { + currentFloatValue = newVal; + ClickButton(); + } + + public void ClickButton() + { + if (settingsType == SettingsType.Binary) + { + currentBoolValue = !currentBoolValue; + } + switch (settingsTarget) + { + case SettingsTarget.Resolution: + base.transform.parent.parent.GetComponentInChildren<MultiOptions>(includeInactive: true).Open(settingsTarget, base.transform.GetChild(1).position, this); + break; + case SettingsTarget.Vol_Master: + Optionshandler.instance.SetVolMaster(currentFloatValue); + break; + case SettingsTarget.Vol_SFX: + Optionshandler.instance.SetVolSFX(currentFloatValue); + break; + case SettingsTarget.Vol_Music: + Optionshandler.instance.SetVolMusic(currentFloatValue); + break; + case SettingsTarget.CharacterPattern: + Optionshandler.instance.SetCharacterPatterns(currentBoolValue); + break; + case SettingsTarget.MapPattern: + Optionshandler.instance.SetMapPatterns(currentBoolValue); + break; + case SettingsTarget.leftStickAim: + Optionshandler.instance.SetLeftStickAim(currentBoolValue); + break; + case SettingsTarget.lockAimDirections: + Optionshandler.instance.lockMouseAim(currentBoolValue); + break; + case SettingsTarget.FreeStickAim: + Optionshandler.instance.lockStickAim(currentBoolValue); + break; + case SettingsTarget.ShowCardStarts: + Optionshandler.instance.SetShowCardStatNumbers(currentBoolValue); + break; + case SettingsTarget.FullScreen: + base.transform.parent.parent.GetComponentInChildren<MultiOptions>(includeInactive: true).Open(settingsTarget, base.transform.GetChild(1).position, this); + break; + case SettingsTarget.Vsync: + Optionshandler.instance.SetVSync(currentBoolValue); + break; + } + ReDraw(); + } + + private void ReDraw() + { + if (settingsType == SettingsType.Binary) + { + text.text = (currentBoolValue ? "YES" : "NO"); + } + if (settingsType == SettingsType.MultiOption) + { + if (settingsTarget == SettingsTarget.Resolution) + { + text.text = currentResolutionValue.width + " X " + currentResolutionValue.height; + } + else if (currentFullscreenValue == Optionshandler.FullScreenOption.WindowedFullScreen) + { + text.text = "WINDOWED FULLSCREEN"; + } + else + { + text.text = currentFullscreenValue.ToString().ToUpper(); + } + } + } +} diff --git a/ROUNDS/Optionshandler.cs b/ROUNDS/Optionshandler.cs new file mode 100644 index 0000000..21130c1 --- /dev/null +++ b/ROUNDS/Optionshandler.cs @@ -0,0 +1,187 @@ +using SoundImplementation; +using UnityEngine; + +public class Optionshandler : MonoBehaviour +{ + public enum FullScreenOption + { + FullScreen, + WindowedFullScreen, + MaximizedWindow, + Windowed + } + + public static Resolution resolution; + + public static float vol_Master; + + public static float vol_Sfx; + + public static float vol_Music; + + public static FullScreenOption fullScreen; + + public static bool characterPattrens; + + public static bool mapPatterns; + + public static bool vSync; + + public static bool leftStickAim; + + public static bool lockMouse; + + public static bool showCardStatNumbers; + + public static bool lockStick; + + public static Optionshandler instance; + + private void Start() + { + instance = this; + LoadOptions(); + ApplyOptions(); + } + + private void LoadOptions() + { + vol_Master = PlayerPrefs.GetFloat("Vol_Master", 1f); + vol_Sfx = PlayerPrefs.GetFloat("vol_Sfx", 1f); + vol_Music = PlayerPrefs.GetFloat("vol_Music", 1f); + resolution.width = PlayerPrefs.GetInt("res_X", 0); + resolution.height = PlayerPrefs.GetInt("res_Y", 0); + fullScreen = (FullScreenOption)PlayerPrefs.GetInt("fullScreen", 1); + characterPattrens = GetBool(PlayerPrefs.GetInt("characterPattrens", 1)); + mapPatterns = GetBool(PlayerPrefs.GetInt("mapPatterns", 1)); + leftStickAim = GetBool(PlayerPrefs.GetInt("leftStickAim", 1)); + vSync = GetBool(PlayerPrefs.GetInt("vSync", 0)); + lockStick = GetBool(PlayerPrefs.GetInt("lockStick", 0)); + lockMouse = GetBool(PlayerPrefs.GetInt("lockMouse", 0)); + showCardStatNumbers = GetBool(PlayerPrefs.GetInt("showCardStatNumbers", 0)); + if (resolution.height == 0 || resolution.width == 0) + { + resolution = Screen.currentResolution; + SaveOptions(); + } + else + { + ApplyOptions(); + } + } + + private void SaveOptions() + { + PlayerPrefs.SetFloat("Vol_Master", vol_Master); + PlayerPrefs.SetFloat("vol_Sfx", vol_Sfx); + PlayerPrefs.SetFloat("vol_Music", vol_Music); + PlayerPrefs.SetInt("res_X", resolution.width); + PlayerPrefs.SetInt("res_Y", resolution.height); + PlayerPrefs.SetInt("fullScreen", (int)fullScreen); + PlayerPrefs.SetInt("characterPattrens", GetInt(characterPattrens)); + PlayerPrefs.SetInt("mapPatterns", GetInt(mapPatterns)); + PlayerPrefs.SetInt("leftStickAim", GetInt(leftStickAim)); + PlayerPrefs.SetInt("vSync", GetInt(vSync)); + PlayerPrefs.SetInt("lockMouse", GetInt(lockMouse)); + PlayerPrefs.SetInt("lockStick", GetInt(lockStick)); + PlayerPrefs.SetInt("showCardStatNumbers", GetInt(showCardStatNumbers)); + ApplyOptions(); + } + + private void ApplyOptions() + { + Screen.SetResolution(resolution.width, resolution.height, (FullScreenMode)fullScreen); + QualitySettings.vSyncCount = (vSync ? 1 : 0); + SoundVolumeManager.Instance.SetAudioMixerVolumes(vol_Master, vol_Music, vol_Sfx); + } + + private bool GetBool(int value) + { + if (value != 1) + { + return false; + } + return true; + } + + private int GetInt(bool value) + { + if (!value) + { + return 0; + } + return 1; + } + + public void SetResolution(Resolution resolutionToSet) + { + resolution = resolutionToSet; + SaveOptions(); + } + + public void SetVSync(bool vSyncToSet) + { + vSync = vSyncToSet; + SaveOptions(); + } + + public void SetVolMaster(float vol_Master_ToSet) + { + vol_Master = vol_Master_ToSet; + SaveOptions(); + } + + public void SetVolSFX(float vol_SFX_ToSet) + { + vol_Sfx = vol_SFX_ToSet; + SaveOptions(); + } + + public void SetVolMusic(float vol_Music_ToSet) + { + vol_Music = vol_Music_ToSet; + SaveOptions(); + } + + public void SetCharacterPatterns(bool characterPatternsToSet) + { + characterPattrens = characterPatternsToSet; + SaveOptions(); + } + + public void SetMapPatterns(bool mapPatternsToSet) + { + mapPatterns = mapPatternsToSet; + SaveOptions(); + } + + public void SetLeftStickAim(bool leftStickAimToSet) + { + leftStickAim = leftStickAimToSet; + SaveOptions(); + } + + public void lockMouseAim(bool setLockMouse) + { + lockMouse = setLockMouse; + SaveOptions(); + } + + public void lockStickAim(bool setLockStick) + { + lockStick = setLockStick; + SaveOptions(); + } + + public void SetShowCardStatNumbers(bool showCardStatNumbersToSet) + { + showCardStatNumbers = showCardStatNumbersToSet; + SaveOptions(); + } + + public void SetFullScreen(FullScreenOption fullscreenToSet) + { + fullScreen = fullscreenToSet; + SaveOptions(); + } +} diff --git a/ROUNDS/Orbit.cs b/ROUNDS/Orbit.cs new file mode 100644 index 0000000..0e63f89 --- /dev/null +++ b/ROUNDS/Orbit.cs @@ -0,0 +1,24 @@ +using System; +using UnityEngine; + +public class Orbit : MonoBehaviour +{ + public GameObject[] objectsPerLevel; + + private void Start() + { + AttackLevel component = GetComponent<AttackLevel>(); + component.LevelUpAction = (Action<int>)Delegate.Combine(component.LevelUpAction, new Action<int>(UpdateLevel)); + } + + private void UpdateLevel(int newLevel) + { + for (int i = 0; i < objectsPerLevel.Length; i++) + { + if (i <= newLevel - 1) + { + objectsPerLevel[i].SetActive(value: true); + } + } + } +} diff --git a/ROUNDS/OutOfBoundsHandler.cs b/ROUNDS/OutOfBoundsHandler.cs new file mode 100644 index 0000000..a7ed350 --- /dev/null +++ b/ROUNDS/OutOfBoundsHandler.cs @@ -0,0 +1,149 @@ +using Sonigon; +using UnityEngine; + +public class OutOfBoundsHandler : MonoBehaviour +{ + private bool outOfBounds; + + private bool almostOutOfBounds; + + private Camera mainCam; + + private CharacterData data; + + public ParticleSystem wall; + + public ParticleSystem burst; + + public ParticleSystem burstBig; + + public ParticleSystem warning; + + public ParticleSystem shieldWall; + + public ParticleSystem shieldBurst; + + public ParticleSystem shieldBurstBig; + + private ChildRPC rpc; + + private float counter; + + private float warningPercentage = 0.1f; + + private void Start() + { + base.transform.position = Vector3.up * 200f; + data = base.transform.root.GetComponent<CharacterData>(); + rpc = data.GetComponent<ChildRPC>(); + rpc.childRPCs.Add("OutOfBounds", RPCA_DisplayOutOfBounds); + rpc.childRPCs.Add("ShieldOutOfBounds", RPCA_DisplayOutOfBoundsShield); + mainCam = MainCam.instance.transform.GetComponent<Camera>(); + base.transform.SetParent(null); + } + + private void LateUpdate() + { + if (!data) + { + Object.Destroy(base.gameObject); + } + else + { + if (!data.playerVel.simulated || !data.isPlaying) + { + return; + } + float x = Mathf.InverseLerp(-35.56f, 35.56f, data.transform.position.x); + float y = Mathf.InverseLerp(-20f, 20f, data.transform.position.y); + Vector3 vector = new Vector3(x, y, 0f); + vector = new Vector3(Mathf.Clamp(vector.x, 0f, 1f), Mathf.Clamp(vector.y, 0f, 1f), vector.z); + almostOutOfBounds = false; + outOfBounds = false; + if (vector.x <= 0f || vector.x >= 1f || vector.y >= 1f || vector.y <= 0f) + { + outOfBounds = true; + } + else if (vector.x < warningPercentage || vector.x > 1f - warningPercentage || vector.y > 1f - warningPercentage || vector.y < warningPercentage) + { + almostOutOfBounds = true; + if (vector.x < warningPercentage) + { + vector.x = 0f; + } + if (vector.x > 1f - warningPercentage) + { + vector.x = 1f; + } + if (vector.y < warningPercentage) + { + vector.y = 0f; + } + if (vector.y > 1f - warningPercentage) + { + vector.y = 1f; + } + } + counter += TimeHandler.deltaTime; + if (almostOutOfBounds && !data.dead) + { + base.transform.position = GetPoint(vector); + base.transform.rotation = Quaternion.LookRotation(Vector3.forward, -(data.transform.position - base.transform.position)); + if (counter > 0.1f) + { + counter = 0f; + warning.Play(); + } + } + if (!outOfBounds || data.dead) + { + return; + } + data.sinceGrounded = 0f; + base.transform.position = GetPoint(vector); + base.transform.rotation = Quaternion.LookRotation(Vector3.forward, -(data.transform.position - base.transform.position)); + if (counter > 0.1f && data.view.IsMine) + { + counter = 0f; + if (data.block.IsBlocking()) + { + rpc.CallFunction("ShieldOutOfBounds"); + data.playerVel.velocity *= 0f; + data.healthHandler.CallTakeForce(base.transform.up * 400f * data.playerVel.mass, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: true); + data.transform.position = base.transform.position; + } + else + { + rpc.CallFunction("OutOfBounds"); + data.healthHandler.CallTakeForce(base.transform.up * 200f * data.playerVel.mass, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: true); + data.healthHandler.CallTakeDamage(51f * base.transform.up, data.transform.position); + } + } + } + } + + private Vector3 GetPoint(Vector3 p) + { + float x = Mathf.Lerp(-35.56f, 35.56f, p.x); + float y = Mathf.Lerp(-20f, 20f, p.y); + return new Vector3(x, y, 0f); + } + + private void RPCA_DisplayOutOfBounds() + { + SoundManager.Instance.Play(data.playerSounds.soundCharacterDamageScreenEdge, data.transform); + burst.Play(); + wall.Play(); + burstBig.Play(); + data.sinceGrounded = 0f; + } + + private void RPCA_DisplayOutOfBoundsShield() + { + SoundManager.Instance.Play(data.playerSounds.soundCharacterDamageScreenEdge, data.transform); + shieldBurst.Play(); + shieldWall.Play(); + shieldBurstBig.Play(); + data.sinceGrounded = 0f; + } +} diff --git a/ROUNDS/ParticleExplosionModifier.cs b/ROUNDS/ParticleExplosionModifier.cs new file mode 100644 index 0000000..ca3a6f6 --- /dev/null +++ b/ROUNDS/ParticleExplosionModifier.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections; +using UnityEngine; + +public class ParticleExplosionModifier : MonoBehaviour +{ + public AnimationCurve curve; + + public float speed = 1f; + + private ParticleSystem effect; + + private ParticleSystem.MainModule main; + + private Coroutine corutine; + + private void Start() + { + effect = GetComponent<ParticleSystem>(); + main = effect.main; + Explosion componentInParent = GetComponentInParent<Explosion>(); + componentInParent.DealDamageAction = (Action<Damagable>)Delegate.Combine(componentInParent.DealDamageAction, new Action<Damagable>(DealDamage)); + Explosion componentInParent2 = GetComponentInParent<Explosion>(); + componentInParent2.DealHealAction = (Action<Damagable>)Delegate.Combine(componentInParent2.DealHealAction, new Action<Damagable>(DealDamage)); + } + + public void DealDamage(Damagable damagable) + { + if (corutine != null) + { + StopCoroutine(corutine); + } + corutine = StartCoroutine(DoCurve()); + } + + private IEnumerator DoCurve() + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + ParticleSystem.MinMaxCurve startSize = main.startSize; + startSize.constantMin = curve.Evaluate(c) * 0.5f; + startSize.constantMax = curve.Evaluate(c); + main.startSize = startSize; + c += TimeHandler.deltaTime * speed; + yield return null; + } + } +} diff --git a/ROUNDS/ParticlePlayer.cs b/ROUNDS/ParticlePlayer.cs new file mode 100644 index 0000000..c834a68 --- /dev/null +++ b/ROUNDS/ParticlePlayer.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +public class ParticlePlayer : MonoBehaviour +{ + public static ParticlePlayer instance; + + private int spawnsThisFrame; + + private void Awake() + { + instance = this; + } + + private void Update() + { + spawnsThisFrame = 0; + } + + public void PlayEffect(string effectName, Vector3 position, Quaternion rotation, float scale = 1f, Transform followTransform = null) + { + if ((float)spawnsThisFrame > 5f) + { + return; + } + spawnsThisFrame++; + Transform transform = base.transform.Find(effectName); + if (!transform) + { + return; + } + if ((bool)followTransform) + { + transform = Object.Instantiate(transform.gameObject, null).transform; + } + transform.transform.position = position; + transform.transform.localScale = scale * Vector3.one; + transform.transform.rotation = rotation; + if ((bool)followTransform) + { + transform.gameObject.AddComponent<FollowLocalPos>().Follow(followTransform); + } + ParticleSystem[] componentsInChildren = transform.GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if ((bool)followTransform) + { + ParticleSystem.MainModule main = componentsInChildren[i].main; + main.simulationSpace = ParticleSystemSimulationSpace.Local; + } + componentsInChildren[i].Play(); + } + } +} diff --git a/ROUNDS/ParticleTime.cs b/ROUNDS/ParticleTime.cs new file mode 100644 index 0000000..a3daa16 --- /dev/null +++ b/ROUNDS/ParticleTime.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +public class ParticleTime : MonoBehaviour +{ + private float startTime = 1f; + + private ParticleSystem.MainModule main; + + private void Start() + { + main = GetComponentInParent<ParticleSystem>().main; + startTime = main.simulationSpeed; + } + + private void Update() + { + main.simulationSpeed = startTime * TimeHandler.timeScale; + } +} diff --git a/ROUNDS/PerlinWordScale.cs b/ROUNDS/PerlinWordScale.cs new file mode 100644 index 0000000..f59f4c2 --- /dev/null +++ b/ROUNDS/PerlinWordScale.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class PerlinWordScale : MonoBehaviour +{ + public float scale = 1f; + + public float min = 0.5f; + + public float max = 2f; + + private void Start() + { + float t = Mathf.PerlinNoise(base.transform.position.x * scale, base.transform.position.y * scale); + base.transform.localScale *= Mathf.Lerp(min, max, t); + } +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackBoolean.cs b/ROUNDS/Photon.Compression.Internal/IPackBoolean.cs new file mode 100644 index 0000000..07aa10f --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackBoolean.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(bool))] +public interface IPackBoolean +{ + SerializationFlags Pack(ref bool value, bool prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref bool value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackByte.cs b/ROUNDS/Photon.Compression.Internal/IPackByte.cs new file mode 100644 index 0000000..e0001c2 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackByte.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(byte))] +public interface IPackByte +{ + SerializationFlags Pack(ref byte value, byte prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref byte value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackChar.cs b/ROUNDS/Photon.Compression.Internal/IPackChar.cs new file mode 100644 index 0000000..e1b514a --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackChar.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(char))] +public interface IPackChar +{ + SerializationFlags Pack(ref char value, char prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref char value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackDouble.cs b/ROUNDS/Photon.Compression.Internal/IPackDouble.cs new file mode 100644 index 0000000..e0a0bbf --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackDouble.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(double))] +public interface IPackDouble +{ + SerializationFlags Pack(ref double value, double preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref double value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackInt16.cs b/ROUNDS/Photon.Compression.Internal/IPackInt16.cs new file mode 100644 index 0000000..7b12053 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackInt16.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(short))] +public interface IPackInt16 +{ + SerializationFlags Pack(ref short value, short preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref short value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackInt32.cs b/ROUNDS/Photon.Compression.Internal/IPackInt32.cs new file mode 100644 index 0000000..a9e8642 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackInt32.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(int))] +public interface IPackInt32 +{ + SerializationFlags Pack(ref int value, int preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackInt64.cs b/ROUNDS/Photon.Compression.Internal/IPackInt64.cs new file mode 100644 index 0000000..8cb3d86 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackInt64.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(long))] +public interface IPackInt64 +{ + SerializationFlags Pack(ref long value, long preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref long value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackList.cs b/ROUNDS/Photon.Compression.Internal/IPackList.cs new file mode 100644 index 0000000..5588205 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackList.cs @@ -0,0 +1,12 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(List<>))] +public interface IPackList<T> where T : struct +{ + SerializationFlags Pack(ref List<T> value, List<T> prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref List<T> value, BitArray mask, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackSByte.cs b/ROUNDS/Photon.Compression.Internal/IPackSByte.cs new file mode 100644 index 0000000..2f7a2e2 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackSByte.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(sbyte))] +public interface IPackSByte +{ + SerializationFlags Pack(ref sbyte value, sbyte prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref sbyte value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackSingle.cs b/ROUNDS/Photon.Compression.Internal/IPackSingle.cs new file mode 100644 index 0000000..d742448 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackSingle.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(float))] +public interface IPackSingle +{ + SerializationFlags Pack(ref float value, float preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref float value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackString.cs b/ROUNDS/Photon.Compression.Internal/IPackString.cs new file mode 100644 index 0000000..45e8eab --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackString.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(string))] +public interface IPackString +{ + SerializationFlags Pack(ref string value, string preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref string value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackStringBuilder.cs b/ROUNDS/Photon.Compression.Internal/IPackStringBuilder.cs new file mode 100644 index 0000000..c06f27f --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackStringBuilder.cs @@ -0,0 +1,11 @@ +using System.Text; + +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(StringBuilder))] +public interface IPackStringBuilder +{ + SerializationFlags Pack(ref StringBuilder value, StringBuilder preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref StringBuilder value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackUInt16.cs b/ROUNDS/Photon.Compression.Internal/IPackUInt16.cs new file mode 100644 index 0000000..c20fbbe --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackUInt16.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(ushort))] +public interface IPackUInt16 +{ + SerializationFlags Pack(ref ushort value, ushort preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref ushort value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackUInt32.cs b/ROUNDS/Photon.Compression.Internal/IPackUInt32.cs new file mode 100644 index 0000000..b93c40a --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackUInt32.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(uint))] +public interface IPackUInt32 +{ + SerializationFlags Pack(ref uint value, uint preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref uint value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackUInt64.cs b/ROUNDS/Photon.Compression.Internal/IPackUInt64.cs new file mode 100644 index 0000000..05a7430 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackUInt64.cs @@ -0,0 +1,9 @@ +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(ulong))] +public interface IPackUInt64 +{ + SerializationFlags Pack(ref ulong value, ulong preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref ulong value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackVector2.cs b/ROUNDS/Photon.Compression.Internal/IPackVector2.cs new file mode 100644 index 0000000..0899313 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackVector2.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(Vector2))] +public interface IPackVector2 +{ + SerializationFlags Pack(ref Vector2 value, Vector2 preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref Vector2 value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackVector2Int.cs b/ROUNDS/Photon.Compression.Internal/IPackVector2Int.cs new file mode 100644 index 0000000..fb1af5c --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackVector2Int.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(Vector2Int))] +public interface IPackVector2Int +{ + SerializationFlags Pack(ref Vector2Int value, Vector2Int preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref Vector2Int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackVector3.cs b/ROUNDS/Photon.Compression.Internal/IPackVector3.cs new file mode 100644 index 0000000..fb9140c --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackVector3.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(Vector3))] +public interface IPackVector3 +{ + SerializationFlags Pack(ref Vector3 value, Vector3 preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref Vector3 value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/IPackVector3Int.cs b/ROUNDS/Photon.Compression.Internal/IPackVector3Int.cs new file mode 100644 index 0000000..21356ad --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/IPackVector3Int.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Photon.Compression.Internal; + +[PackSupportedTypes(typeof(Vector3Int))] +public interface IPackVector3Int +{ + SerializationFlags Pack(ref Vector3Int value, Vector3Int preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); + + SerializationFlags Unpack(ref Vector3Int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); +} diff --git a/ROUNDS/Photon.Compression.Internal/PackDelegate.cs b/ROUNDS/Photon.Compression.Internal/PackDelegate.cs new file mode 100644 index 0000000..7b4291b --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackDelegate.cs @@ -0,0 +1,3 @@ +namespace Photon.Compression.Internal; + +public delegate SerializationFlags PackDelegate<T>(ref T value, T prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); diff --git a/ROUNDS/Photon.Compression.Internal/PackFrame.cs b/ROUNDS/Photon.Compression.Internal/PackFrame.cs new file mode 100644 index 0000000..171e831 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackFrame.cs @@ -0,0 +1,10 @@ +using Photon.Utilities; + +namespace Photon.Compression.Internal; + +public abstract class PackFrame +{ + public FastBitMask128 mask; + + public FastBitMask128 isCompleteMask; +} diff --git a/ROUNDS/Photon.Compression.Internal/PackFrame_TestPackObject.cs b/ROUNDS/Photon.Compression.Internal/PackFrame_TestPackObject.cs new file mode 100644 index 0000000..db9cd60 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackFrame_TestPackObject.cs @@ -0,0 +1,118 @@ +using emotitron; +using Photon.Utilities; + +namespace Photon.Compression.Internal; + +public class PackFrame_TestPackObject : PackFrame +{ + public float rotation; + + public int intoroboto; + + public static void Interpolate(PackFrame start, PackFrame end, PackFrame trg, float time, ref FastBitMask128 readyMask, ref int maskOffset) + { + PackFrame_TestPackObject packFrame_TestPackObject = start as PackFrame_TestPackObject; + PackFrame_TestPackObject packFrame_TestPackObject2 = end as PackFrame_TestPackObject; + PackFrame_TestPackObject packFrame_TestPackObject3 = trg as PackFrame_TestPackObject; + FastBitMask128 fastBitMask = end.mask; + if (fastBitMask[maskOffset]) + { + packFrame_TestPackObject3.rotation = (packFrame_TestPackObject2.rotation - packFrame_TestPackObject.rotation) * time + packFrame_TestPackObject.rotation; + } + maskOffset++; + if (fastBitMask[maskOffset]) + { + packFrame_TestPackObject3.intoroboto = (int)((float)(packFrame_TestPackObject2.intoroboto - packFrame_TestPackObject.intoroboto) * time) + packFrame_TestPackObject.intoroboto; + } + maskOffset++; + } + + public static void Interpolate(PackFrame start, PackFrame end, object trg, float time, ref FastBitMask128 readyMask, ref int maskOffset) + { + PackFrame_TestPackObject packFrame_TestPackObject = start as PackFrame_TestPackObject; + PackFrame_TestPackObject packFrame_TestPackObject2 = end as PackFrame_TestPackObject; + TestPackObject testPackObject = trg as TestPackObject; + FastBitMask128 fastBitMask = end.mask; + if (readyMask[maskOffset] && fastBitMask[maskOffset]) + { + testPackObject.rotation = (packFrame_TestPackObject2.rotation - packFrame_TestPackObject.rotation) * time + packFrame_TestPackObject.rotation; + } + maskOffset++; + maskOffset++; + } + + public static void SnapshotCallback(PackFrame snapframe, PackFrame targframe, object trg, ref FastBitMask128 readyMask, ref int maskOffset) + { + PackFrame_TestPackObject packFrame_TestPackObject = snapframe as PackFrame_TestPackObject; + PackFrame_TestPackObject packFrame_TestPackObject2 = targframe as PackFrame_TestPackObject; + TestPackObject testPackObject = trg as TestPackObject; + FastBitMask128 fastBitMask = snapframe.mask; + FastBitMask128 fastBitMask2 = targframe.mask; + if (readyMask[maskOffset]) + { + float num = (fastBitMask[maskOffset] ? packFrame_TestPackObject.rotation : testPackObject.rotation); + float targ = (fastBitMask2[maskOffset] ? packFrame_TestPackObject2.rotation : num); + testPackObject.SnapshotHook(num, targ); + } + maskOffset++; + maskOffset++; + } + + public static void Capture(object src, PackFrame trg) + { + TestPackObject testPackObject = src as TestPackObject; + PackFrame_TestPackObject obj = trg as PackFrame_TestPackObject; + obj.rotation = testPackObject.rotation; + obj.intoroboto = testPackObject.intoroboto; + } + + public static void Apply(PackFrame src, object trg, ref FastBitMask128 mask, ref int maskOffset) + { + PackFrame_TestPackObject packFrame_TestPackObject = src as PackFrame_TestPackObject; + TestPackObject testPackObject = trg as TestPackObject; + if (mask[maskOffset]) + { + float oldrot = testPackObject.rotation; + testPackObject.rotation = packFrame_TestPackObject.rotation; + testPackObject.RotationHook(packFrame_TestPackObject.rotation, oldrot); + } + maskOffset++; + if (mask[maskOffset]) + { + testPackObject.intoroboto = packFrame_TestPackObject.intoroboto; + } + maskOffset++; + } + + public static void Copy(PackFrame src, PackFrame trg) + { + PackFrame_TestPackObject packFrame_TestPackObject = src as PackFrame_TestPackObject; + PackFrame_TestPackObject obj = trg as PackFrame_TestPackObject; + obj.rotation = packFrame_TestPackObject.rotation; + obj.intoroboto = packFrame_TestPackObject.intoroboto; + } + + public static PackFrame Factory() + { + return new PackFrame_TestPackObject + { + mask = new FastBitMask128(2), + isCompleteMask = new FastBitMask128(2) + }; + } + + public static PackFrame[] Factory(object trg, int count) + { + PackFrame_TestPackObject[] array = new PackFrame_TestPackObject[count]; + for (int i = 0; i < count; i++) + { + PackFrame_TestPackObject packFrame_TestPackObject = new PackFrame_TestPackObject + { + mask = new FastBitMask128(2), + isCompleteMask = new FastBitMask128(2) + }; + array[i] = packFrame_TestPackObject; + } + return array; + } +} diff --git a/ROUNDS/Photon.Compression.Internal/PackListDelegate.cs b/ROUNDS/Photon.Compression.Internal/PackListDelegate.cs new file mode 100644 index 0000000..9c80c05 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackListDelegate.cs @@ -0,0 +1,5 @@ +using System.Collections.Generic; + +namespace Photon.Compression.Internal; + +public delegate SerializationFlags PackListDelegate<T>(ref List<T> value, List<T> prevvalue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) where T : struct; diff --git a/ROUNDS/Photon.Compression.Internal/PackObjectDatabase.cs b/ROUNDS/Photon.Compression.Internal/PackObjectDatabase.cs new file mode 100644 index 0000000..520e01c --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackObjectDatabase.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using Photon.Utilities; + +namespace Photon.Compression.Internal; + +public static class PackObjectDatabase +{ + public delegate SerializationFlags PackStructDelegate(IntPtr obj, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags forceKeyframe); + + public delegate SerializationFlags PackObjDelegate(ref object obj, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags forceKeyframe); + + public delegate SerializationFlags PackFrameDelegate(PackFrame obj, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags forceKeyframe); + + public delegate SerializationFlags UnpackFrameDelegate(PackFrame obj, ref FastBitMask128 hasContentMask, ref FastBitMask128 isCompleteMask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags forceKeyframe); + + public delegate void PackCopyFrameToObjectDelegate(PackFrame src, object trg, ref FastBitMask128 mask, ref int maskOffset); + + public delegate void PackCopyFrameToStructDelegate(PackFrame src, IntPtr trg, ref FastBitMask128 mask, ref int maskOffset); + + public delegate void PackSnapshotObjectDelegate(PackFrame snap, PackFrame targ, object trg, ref FastBitMask128 readyMask, ref int maskOffset); + + public delegate void PackSnapshotStructDelegate(PackFrame snap, PackFrame targ, IntPtr trg, ref FastBitMask128 readyMask, ref int maskOffset); + + public delegate void PackInterpFrameToFrameDelegate(PackFrame start, PackFrame end, PackFrame trg, float ntime, ref FastBitMask128 readyMask, ref int maskOffset); + + public delegate void PackInterpFrameToObjectDelegate(PackFrame start, PackFrame end, object trg, float ntime, ref FastBitMask128 readyMask, ref int maskOffset); + + public delegate void PackInterpFrameToStructDelegate(PackFrame start, PackFrame end, IntPtr trg, float ntime, ref FastBitMask128 readyMask, ref int maskOffset); + + public class PackObjectInfo + { + public readonly Type packFrameType; + + public readonly int maxBits; + + public readonly int maxBytes; + + public readonly FastBitMask128 defaultReadyMask; + + public readonly PackObjDelegate PackObjToBuffer; + + public readonly PackStructDelegate PackStructToBuffer; + + public readonly PackFrameDelegate PackFrameToBuffer; + + public readonly UnpackFrameDelegate UnpackFrameFromBuffer; + + public Func<PackFrame> FactoryFrame; + + public Func<object, int, PackFrame[]> FactoryFramesObj; + + public Func<IntPtr, int, PackFrame[]> FactoryFramesStruct; + + public PackCopyFrameToObjectDelegate CopyFrameToObj; + + public PackCopyFrameToStructDelegate CopyFrameToStruct; + + public PackSnapshotObjectDelegate SnapObject; + + public PackSnapshotStructDelegate SnapStruct; + + public PackInterpFrameToFrameDelegate InterpFrameToFrame; + + public PackInterpFrameToObjectDelegate InterpFrameToObj; + + public PackInterpFrameToStructDelegate InterpFrameToStruct; + + public Action<object, PackFrame> CaptureObj; + + public Action<IntPtr, PackFrame> CaptureStruct; + + public Action<PackFrame, PackFrame> CopyFrameToFrame; + + public readonly int fieldCount; + + public PackObjectInfo(FastBitMask128 defaultReadyMask, PackObjDelegate packObjToBuffer, PackFrameDelegate packFrameToBuffer, UnpackFrameDelegate unpackFrameFromBuffer, int maxBits, Func<PackFrame> factoryFrame, Func<object, int, PackFrame[]> factoryFramesObj, PackCopyFrameToObjectDelegate copyFrameToObj, Action<object, PackFrame> captureObj, Action<PackFrame, PackFrame> copyFrameToFrame, PackSnapshotObjectDelegate snapObject, PackInterpFrameToFrameDelegate interpFrameToFrame, PackInterpFrameToObjectDelegate interpFrameToObj, int fieldCount) + { + PackObjToBuffer = packObjToBuffer; + this.defaultReadyMask = defaultReadyMask; + PackFrameToBuffer = packFrameToBuffer; + UnpackFrameFromBuffer = unpackFrameFromBuffer; + this.maxBits = maxBits; + maxBytes = maxBits + 7 >> 3; + FactoryFrame = factoryFrame; + FactoryFramesObj = factoryFramesObj; + CopyFrameToObj = copyFrameToObj; + CaptureObj = captureObj; + CopyFrameToFrame = copyFrameToFrame; + SnapObject = snapObject; + InterpFrameToFrame = interpFrameToFrame; + InterpFrameToObj = interpFrameToObj; + this.fieldCount = fieldCount; + } + + public PackObjectInfo(FastBitMask128 defaultReadyMask, PackStructDelegate packStructToBuffer, PackFrameDelegate packFrameToBuffer, UnpackFrameDelegate unpackFrameFromBuffer, int maxBits, Func<PackFrame> factoryFrame, Func<IntPtr, int, PackFrame[]> factoryFramesStruct, PackCopyFrameToStructDelegate copyFrameToStruct, Action<IntPtr, PackFrame> captureStruct, Action<PackFrame, PackFrame> copyFrameToFrame, PackSnapshotStructDelegate snapStruct, PackInterpFrameToFrameDelegate interpFrameToFrame, PackInterpFrameToStructDelegate interpFrameToStruct, int fieldCount) + { + this.defaultReadyMask = defaultReadyMask; + PackStructToBuffer = packStructToBuffer; + PackFrameToBuffer = packFrameToBuffer; + UnpackFrameFromBuffer = unpackFrameFromBuffer; + this.maxBits = maxBits; + maxBytes = maxBits + 7 >> 3; + FactoryFrame = factoryFrame; + FactoryFramesStruct = factoryFramesStruct; + CopyFrameToStruct = copyFrameToStruct; + CaptureStruct = captureStruct; + CopyFrameToFrame = copyFrameToFrame; + SnapStruct = snapStruct; + InterpFrameToFrame = interpFrameToFrame; + InterpFrameToStruct = interpFrameToStruct; + this.fieldCount = fieldCount; + } + } + + public static Dictionary<Type, PackObjectInfo> packObjInfoLookup = new Dictionary<Type, PackObjectInfo>(); + + public static PackObjectInfo GetPackObjectInfo(Type type) + { + if (packObjInfoLookup.TryGetValue(type, out var value)) + { + return value; + } + Type type2 = Type.GetType("Pack_" + type.Name); + if (type2 != null) + { + Debug.LogError("BRUTE FORCE Pack_" + type.Name + ". This shouldn't happen."); + type2.GetMethod("Initialize").Invoke(null, null); + } + if (packObjInfoLookup.TryGetValue(type, out value)) + { + return value; + } + return null; + } +} diff --git a/ROUNDS/Photon.Compression.Internal/PackSingleDelegate.cs b/ROUNDS/Photon.Compression.Internal/PackSingleDelegate.cs new file mode 100644 index 0000000..727226c --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackSingleDelegate.cs @@ -0,0 +1,3 @@ +namespace Photon.Compression.Internal; + +public delegate SerializationFlags PackSingleDelegate(ref float value, float preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); diff --git a/ROUNDS/Photon.Compression.Internal/PackSupportedTypesAttribute.cs b/ROUNDS/Photon.Compression.Internal/PackSupportedTypesAttribute.cs new file mode 100644 index 0000000..a5afede --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/PackSupportedTypesAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace Photon.Compression.Internal; + +[AttributeUsage(AttributeTargets.Interface)] +public class PackSupportedTypesAttribute : Attribute +{ + public Type supportedType; + + public PackSupportedTypesAttribute(Type supportedType) + { + this.supportedType = supportedType; + } +} diff --git a/ROUNDS/Photon.Compression.Internal/Pack_TestPackObject.cs b/ROUNDS/Photon.Compression.Internal/Pack_TestPackObject.cs new file mode 100644 index 0000000..e4fbddb --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/Pack_TestPackObject.cs @@ -0,0 +1,191 @@ +using emotitron; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Compression.Internal; + +public static class Pack_TestPackObject +{ + public const int LOCAL_FIELDS = 2; + + public const int TOTAL_FIELDS = 2; + + public static PackObjectDatabase.PackObjectInfo packObjInfo; + + private static PackDelegate<float> rotationPacker; + + private static UnpackDelegate<float> rotationUnpacker; + + private static PackDelegate<int> intorobotoPacker; + + private static UnpackDelegate<int> intorobotoUnpacker; + + public static bool initialized; + + public static bool isInitializing; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void Initialize() + { + if (!initialized) + { + isInitializing = true; + int num = 0; + PackObjectAttribute packObjectAttribute = typeof(TestPackObject).GetCustomAttributes(typeof(PackObjectAttribute), inherit: false)[0] as PackObjectAttribute; + DefaultKeyRate defaultKeyRate = packObjectAttribute.defaultKeyRate; + FastBitMask128 defaultReadyMask = new FastBitMask128(2); + int num2 = 0; + SyncHalfFloatAttribute syncHalfFloatAttribute = typeof(TestPackObject).GetField("rotation").GetCustomAttributes(typeof(SyncVarBaseAttribute), inherit: false)[0] as SyncHalfFloatAttribute; + rotationPacker = ((IPackSingle)syncHalfFloatAttribute).Pack; + rotationUnpacker = ((IPackSingle)syncHalfFloatAttribute).Unpack; + syncHalfFloatAttribute.Initialize(typeof(float)); + if (syncHalfFloatAttribute.keyRate == KeyRate.UseDefault) + { + syncHalfFloatAttribute.keyRate = (KeyRate)defaultKeyRate; + } + if (syncHalfFloatAttribute.syncAs == SyncAs.Auto) + { + syncHalfFloatAttribute.syncAs = packObjectAttribute.syncAs; + } + if (syncHalfFloatAttribute.syncAs == SyncAs.Auto) + { + syncHalfFloatAttribute.syncAs = SyncAs.State; + } + if (syncHalfFloatAttribute.syncAs == SyncAs.Trigger) + { + defaultReadyMask[num2] = true; + } + num += 16; + num2++; + SyncRangedIntAttribute syncRangedIntAttribute = typeof(TestPackObject).GetField("intoroboto").GetCustomAttributes(typeof(SyncVarBaseAttribute), inherit: false)[0] as SyncRangedIntAttribute; + intorobotoPacker = ((IPackInt32)syncRangedIntAttribute).Pack; + intorobotoUnpacker = ((IPackInt32)syncRangedIntAttribute).Unpack; + syncRangedIntAttribute.Initialize(typeof(int)); + if (syncRangedIntAttribute.keyRate == KeyRate.UseDefault) + { + syncRangedIntAttribute.keyRate = (KeyRate)defaultKeyRate; + } + if (syncRangedIntAttribute.syncAs == SyncAs.Auto) + { + syncRangedIntAttribute.syncAs = packObjectAttribute.syncAs; + } + if (syncRangedIntAttribute.syncAs == SyncAs.Auto) + { + syncRangedIntAttribute.syncAs = SyncAs.State; + } + if (syncRangedIntAttribute.syncAs == SyncAs.Trigger) + { + defaultReadyMask[num2] = true; + } + num += 2; + num2++; + packObjInfo = new PackObjectDatabase.PackObjectInfo(defaultReadyMask, Pack, Pack, Unpack, num, PackFrame_TestPackObject.Factory, PackFrame_TestPackObject.Factory, PackFrame_TestPackObject.Apply, PackFrame_TestPackObject.Capture, PackFrame_TestPackObject.Copy, PackFrame_TestPackObject.SnapshotCallback, PackFrame_TestPackObject.Interpolate, PackFrame_TestPackObject.Interpolate, 2); + PackObjectDatabase.packObjInfoLookup.Add(typeof(TestPackObject), packObjInfo); + isInitializing = false; + initialized = true; + } + } + + public static SerializationFlags Pack(ref object obj, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + TestPackObject testPackObject = obj as TestPackObject; + PackFrame_TestPackObject packFrame_TestPackObject = prevFrame as PackFrame_TestPackObject; + SerializationFlags serializationFlags = rotationPacker(ref testPackObject.rotation, packFrame_TestPackObject.rotation, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags != SerializationFlags.None; + SerializationFlags num = SerializationFlags.None | serializationFlags; + maskOffset++; + SerializationFlags serializationFlags2 = intorobotoPacker(ref testPackObject.intoroboto, packFrame_TestPackObject.intoroboto, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags2 != SerializationFlags.None; + SerializationFlags result = num | serializationFlags2; + maskOffset++; + return result; + } + + public static SerializationFlags Pack(ref TestPackObject packable, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + PackFrame_TestPackObject packFrame_TestPackObject = prevFrame as PackFrame_TestPackObject; + SerializationFlags serializationFlags = rotationPacker(ref packable.rotation, packFrame_TestPackObject.rotation, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags != SerializationFlags.None; + SerializationFlags num = SerializationFlags.None | serializationFlags; + maskOffset++; + SerializationFlags serializationFlags2 = intorobotoPacker(ref packable.intoroboto, packFrame_TestPackObject.intoroboto, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags2 != SerializationFlags.None; + SerializationFlags result = num | serializationFlags2; + maskOffset++; + return result; + } + + public static SerializationFlags Pack(PackFrame obj, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + PackFrame_TestPackObject packFrame_TestPackObject = obj as PackFrame_TestPackObject; + PackFrame_TestPackObject packFrame_TestPackObject2 = prevFrame as PackFrame_TestPackObject; + SerializationFlags serializationFlags = rotationPacker(ref packFrame_TestPackObject.rotation, packFrame_TestPackObject2.rotation, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags != SerializationFlags.None; + SerializationFlags num = SerializationFlags.None | serializationFlags; + maskOffset++; + SerializationFlags serializationFlags2 = intorobotoPacker(ref packFrame_TestPackObject.intoroboto, packFrame_TestPackObject2.intoroboto, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags2 != SerializationFlags.None; + SerializationFlags result = num | serializationFlags2; + maskOffset++; + return result; + } + + public static SerializationFlags Unpack(PackFrame obj, ref FastBitMask128 mask, ref FastBitMask128 isCompleteMask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + PackFrame_TestPackObject packFrame_TestPackObject = obj as PackFrame_TestPackObject; + SerializationFlags serializationFlags = SerializationFlags.None; + if (mask[maskOffset]) + { + SerializationFlags serializationFlags2 = rotationUnpacker(ref packFrame_TestPackObject.rotation, buffer, ref bitposition, frameId, writeFlags); + isCompleteMask[maskOffset] = (serializationFlags2 & SerializationFlags.IsComplete) != 0; + mask[maskOffset] = serializationFlags2 != SerializationFlags.None; + serializationFlags |= serializationFlags2; + } + maskOffset++; + if (mask[maskOffset]) + { + SerializationFlags serializationFlags3 = intorobotoUnpacker(ref packFrame_TestPackObject.intoroboto, buffer, ref bitposition, frameId, writeFlags); + isCompleteMask[maskOffset] = (serializationFlags3 & SerializationFlags.IsComplete) != 0; + mask[maskOffset] = serializationFlags3 != SerializationFlags.None; + serializationFlags |= serializationFlags3; + } + maskOffset++; + return serializationFlags; + } + + public static SerializationFlags Pack(ref PackFrame_TestPackObject packable, PackFrame prevFrame, ref FastBitMask128 mask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + PackFrame_TestPackObject packFrame_TestPackObject = prevFrame as PackFrame_TestPackObject; + SerializationFlags serializationFlags = rotationPacker(ref packable.rotation, packFrame_TestPackObject.rotation, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags != SerializationFlags.None; + SerializationFlags num = SerializationFlags.None | serializationFlags; + maskOffset++; + SerializationFlags serializationFlags2 = intorobotoPacker(ref packable.intoroboto, packFrame_TestPackObject.intoroboto, buffer, ref bitposition, frameId, writeFlags); + mask[maskOffset] = serializationFlags2 != SerializationFlags.None; + SerializationFlags result = num | serializationFlags2; + maskOffset++; + return result; + } + + public static SerializationFlags Unpack(ref PackFrame_TestPackObject packable, ref FastBitMask128 mask, ref FastBitMask128 isCompleteMask, ref int maskOffset, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + SerializationFlags serializationFlags = SerializationFlags.None; + if (mask[maskOffset]) + { + SerializationFlags serializationFlags2 = rotationUnpacker(ref packable.rotation, buffer, ref bitposition, frameId, writeFlags); + isCompleteMask[maskOffset] = (serializationFlags2 & SerializationFlags.IsComplete) != 0; + mask[maskOffset] = serializationFlags2 != SerializationFlags.None; + serializationFlags |= serializationFlags2; + } + maskOffset++; + if (mask[maskOffset]) + { + SerializationFlags serializationFlags3 = intorobotoUnpacker(ref packable.intoroboto, buffer, ref bitposition, frameId, writeFlags); + isCompleteMask[maskOffset] = (serializationFlags3 & SerializationFlags.IsComplete) != 0; + mask[maskOffset] = serializationFlags3 != SerializationFlags.None; + serializationFlags |= serializationFlags3; + } + maskOffset++; + return serializationFlags; + } +} diff --git a/ROUNDS/Photon.Compression.Internal/SyncRangedAttribute.cs b/ROUNDS/Photon.Compression.Internal/SyncRangedAttribute.cs new file mode 100644 index 0000000..95b1ec9 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/SyncRangedAttribute.cs @@ -0,0 +1,28 @@ +namespace Photon.Compression.Internal; + +public class SyncRangedAttribute : SyncVarBaseAttribute, IPackSingle +{ + private LiteFloatCrusher crusher = new LiteFloatCrusher(); + + public SyncRangedAttribute(LiteFloatCompressType compression, float min, float max, bool accurateCenter) + { + LiteFloatCrusher.Recalculate(compression, min, max, accurateCenter, crusher); + } + + public SerializationFlags Pack(ref float value, float preValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + uint num = (uint)crusher.Encode(value); + if (!IsForced(frameId, writeFlags) && num == (uint)crusher.Encode(preValue)) + { + return SerializationFlags.None; + } + crusher.WriteCValue(num, buffer, ref bitposition); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref float value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = crusher.ReadValue(buffer, ref bitposition); + return SerializationFlags.IsComplete; + } +} diff --git a/ROUNDS/Photon.Compression.Internal/SyncVarBaseAttribute.cs b/ROUNDS/Photon.Compression.Internal/SyncVarBaseAttribute.cs new file mode 100644 index 0000000..f7b3531 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/SyncVarBaseAttribute.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Compression.Internal; + +[Serializable] +[AttributeUsage(AttributeTargets.Field)] +public abstract class SyncVarBaseAttribute : Attribute +{ + public SyncAs syncAs; + + public KeyRate keyRate; + + public string applyCallback; + + public string snapshotCallback; + + public SetValueTiming setValueTiming = SetValueTiming.AfterCallback; + + public bool interpolate; + + public int bitCount = -1; + + public virtual void Initialize(Type primitiveType) + { + if (bitCount <= -1) + { + bitCount = GetDefaultBitCount(primitiveType); + } + } + + public virtual int GetDefaultBitCount(Type fieldType) + { + if (fieldType == typeof(byte) || fieldType == typeof(sbyte)) + { + return 8; + } + if (fieldType == typeof(ushort) || fieldType == typeof(short) || fieldType == typeof(char)) + { + return 16; + } + if (fieldType == typeof(uint) || fieldType == typeof(int) || fieldType == typeof(float)) + { + return 32; + } + if (fieldType == typeof(ulong) || fieldType == typeof(long) || fieldType == typeof(double)) + { + return 64; + } + if (fieldType == typeof(bool)) + { + return 1; + } + if (fieldType == typeof(Vector3)) + { + return 32; + } + if (fieldType == typeof(Vector2)) + { + return 32; + } + return 0; + } + + public virtual int GetMaxBits(Type fieldType) + { + if (fieldType == typeof(byte) || fieldType == typeof(sbyte)) + { + return 8; + } + if (fieldType == typeof(ushort) || fieldType == typeof(short) || fieldType == typeof(char)) + { + return 16; + } + if (fieldType == typeof(uint) || fieldType == typeof(int) || fieldType == typeof(float)) + { + return 32; + } + if (fieldType == typeof(ulong) || fieldType == typeof(long) || fieldType == typeof(double)) + { + return 64; + } + if (fieldType == typeof(bool)) + { + return 1; + } + if (fieldType == typeof(Vector3)) + { + return 96; + } + if (fieldType == typeof(Vector2)) + { + return 64; + } + if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>))) + { + Debug.LogWarning("Can't get max bits needed for List<> types, as they are variable. " + fieldType.Name); + return 2048; + } + Debug.LogWarning("Can't get bits needed for unsupported types. " + fieldType.Name); + return 2048; + } + + public bool IsKeyframe(int frameId) + { + if (keyRate == KeyRate.Every) + { + return true; + } + if (keyRate == KeyRate.Never) + { + return false; + } + if (frameId % (int)keyRate == 0) + { + return true; + } + return false; + } + + public bool IsForced(int frameId, SerializationFlags writeFlags) + { + if (syncAs == SyncAs.Trigger) + { + return false; + } + if (keyRate == KeyRate.Every) + { + return true; + } + if ((writeFlags & SerializationFlags.Force) != 0) + { + return true; + } + if (keyRate == KeyRate.Never && (writeFlags & SerializationFlags.NewConnection) != 0) + { + return true; + } + if (keyRate != 0 && frameId % (int)keyRate == 0) + { + return true; + } + return false; + } + + public bool IsForcedClass<T>(int frameId, T value, T prevValue, SerializationFlags writeFlags) where T : class + { + if (syncAs == SyncAs.Trigger) + { + Debug.LogError("Reference type " + typeof(T).Name + " cannot be set to SyncAs.Trigger. This PackAttribute setting only applies to structs."); + return true; + } + if (keyRate == KeyRate.Every) + { + return true; + } + if ((writeFlags & SerializationFlags.Force) != 0) + { + return true; + } + if (keyRate == KeyRate.Never && (writeFlags & SerializationFlags.NewConnection) != 0) + { + return true; + } + if (keyRate != 0 && frameId % (int)keyRate == 0) + { + return true; + } + if (!value.Equals(prevValue)) + { + return true; + } + return false; + } + + public bool IsForced<T>(int frameId, T value, T prevValue, SerializationFlags writeFlags) where T : struct + { + if (syncAs == SyncAs.Trigger) + { + return !value.Equals(new T()); + } + if (keyRate == KeyRate.Every) + { + return true; + } + if ((writeFlags & SerializationFlags.Force) != 0) + { + return true; + } + if (keyRate == KeyRate.Never && (writeFlags & SerializationFlags.NewConnection) != 0) + { + return true; + } + if (keyRate != 0 && frameId % (int)keyRate == 0) + { + return true; + } + if (!value.Equals(prevValue)) + { + return true; + } + return false; + } +} diff --git a/ROUNDS/Photon.Compression.Internal/UnpackDelegate.cs b/ROUNDS/Photon.Compression.Internal/UnpackDelegate.cs new file mode 100644 index 0000000..5186b32 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/UnpackDelegate.cs @@ -0,0 +1,3 @@ +namespace Photon.Compression.Internal; + +public delegate SerializationFlags UnpackDelegate<T>(ref T value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags); diff --git a/ROUNDS/Photon.Compression.Internal/UnpackListDelegate.cs b/ROUNDS/Photon.Compression.Internal/UnpackListDelegate.cs new file mode 100644 index 0000000..8676247 --- /dev/null +++ b/ROUNDS/Photon.Compression.Internal/UnpackListDelegate.cs @@ -0,0 +1,6 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Photon.Compression.Internal; + +public delegate SerializationFlags UnpackListDelegate<T>(ref List<T> value, BitArray mask, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) where T : struct; diff --git a/ROUNDS/Photon.Compression/CompressLevel.cs b/ROUNDS/Photon.Compression/CompressLevel.cs new file mode 100644 index 0000000..6157010 --- /dev/null +++ b/ROUNDS/Photon.Compression/CompressLevel.cs @@ -0,0 +1,10 @@ +namespace Photon.Compression; + +public enum CompressLevel +{ + SetBits = -1, + Disabled = 0, + uint16Low = 16, + uint32Med = 32, + uint64Hi = 64 +} diff --git a/ROUNDS/Photon.Compression/CompressedElement.cs b/ROUNDS/Photon.Compression/CompressedElement.cs new file mode 100644 index 0000000..a3e03f3 --- /dev/null +++ b/ROUNDS/Photon.Compression/CompressedElement.cs @@ -0,0 +1,547 @@ +using System; +using System.Runtime.InteropServices; +using emotitron.Compression; +using UnityEngine; + +namespace Photon.Compression; + +[StructLayout(LayoutKind.Explicit)] +public class CompressedElement : IEquatable<CompressedElement> +{ + public static CompressedElement reusable = new CompressedElement(); + + [FieldOffset(0)] + public CompressedFloat cx; + + [FieldOffset(16)] + public CompressedFloat cy; + + [FieldOffset(32)] + public CompressedFloat cz; + + [FieldOffset(0)] + public CompressedFloat cUniform; + + [FieldOffset(0)] + public CompressedQuat cQuat; + + [FieldOffset(48)] + public ElementCrusher crusher; + + private static readonly ulong[] reusableArray64 = new ulong[2]; + + private static readonly uint[] reusableArray32 = new uint[4]; + + private static readonly byte[] reusableArray8 = new byte[16]; + + [Obsolete("Compressed Element is now a class and no longer a struct. Where this used to be used, now compressedElement.Clear() should be used instead.")] + public static readonly CompressedElement Empty = new CompressedElement(); + + private static CompressedElement uppers = new CompressedElement(); + + private static CompressedElement lowers = new CompressedElement(); + + public uint this[int axis] => axis switch + { + 1 => cy, + 0 => cx, + _ => cz, + }; + + public void Clear() + { + crusher = null; + cx = new CompressedFloat(null, 0); + cy = new CompressedFloat(null, 0); + cz = new CompressedFloat(null, 0); + } + + public ulong[] AsArray64(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + reusableArray64.Append(cx.cvalue, ref bitposition, cx.crusher._bits[(int)bcl]); + reusableArray64.Append(cy.cvalue, ref bitposition, cy.crusher._bits[(int)bcl]); + reusableArray64.Append(cz.cvalue, ref bitposition, cz.crusher._bits[(int)bcl]); + reusableArray64.Zero(bitposition + 63 >> 6); + return reusableArray64; + } + + public void AsArray64(ulong[] nonalloc, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + nonalloc.Append(cx.cvalue, ref bitposition, cx.crusher._bits[(int)bcl]); + nonalloc.Append(cy.cvalue, ref bitposition, cy.crusher._bits[(int)bcl]); + nonalloc.Append(cz.cvalue, ref bitposition, cz.crusher._bits[(int)bcl]); + nonalloc.Zero(bitposition + 63 >> 6); + } + + public uint[] AsArray32(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + reusableArray64.Append(cx.cvalue, ref bitposition, cx.crusher._bits[(int)bcl]); + reusableArray64.Append(cy.cvalue, ref bitposition, cy.crusher._bits[(int)bcl]); + reusableArray64.Append(cz.cvalue, ref bitposition, cz.crusher._bits[(int)bcl]); + reusableArray64.Zero(bitposition + 31 >> 5); + return reusableArray32; + } + + public void AsArray32(uint[] nonalloc, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + nonalloc.Append(cx.cvalue, ref bitposition, cx.crusher._bits[(int)bcl]); + nonalloc.Append(cy.cvalue, ref bitposition, cy.crusher._bits[(int)bcl]); + nonalloc.Append(cz.cvalue, ref bitposition, cz.crusher._bits[(int)bcl]); + nonalloc.Zero(bitposition + 31 >> 5); + } + + public byte[] AsArray8(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + reusableArray8.Append(cx.cvalue, ref bitposition, cx.crusher._bits[(int)bcl]); + reusableArray8.Append(cy.cvalue, ref bitposition, cy.crusher._bits[(int)bcl]); + reusableArray8.Append(cz.cvalue, ref bitposition, cz.crusher._bits[(int)bcl]); + reusableArray64.Zero(bitposition + 7 >> 3); + return reusableArray8; + } + + public void AsArray8(byte[] nonalloc, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + nonalloc.Append(cx.cvalue, ref bitposition, cx.crusher._bits[(int)bcl]); + nonalloc.Append(cy.cvalue, ref bitposition, cy.crusher._bits[(int)bcl]); + nonalloc.Append(cz.cvalue, ref bitposition, cz.crusher._bits[(int)bcl]); + nonalloc.Zero(bitposition + 7 >> 3); + } + + public static explicit operator ulong(CompressedElement ce) + { + ulong buffer = 0uL; + ce.crusher.Write(ce, ref buffer); + return buffer; + } + + public static explicit operator uint(CompressedElement ce) + { + ulong buffer = 0uL; + ce.crusher.Write(ce, ref buffer); + return (uint)buffer; + } + + public static explicit operator ushort(CompressedElement ce) + { + ulong buffer = 0uL; + ce.crusher.Write(ce, ref buffer); + return (ushort)buffer; + } + + public static explicit operator byte(CompressedElement ce) + { + ulong buffer = 0uL; + ce.crusher.Write(ce, ref buffer); + return (byte)buffer; + } + + public static explicit operator ulong[](CompressedElement ce) + { + ce.AsArray64(reusableArray64); + return reusableArray64; + } + + public static explicit operator uint[](CompressedElement ce) + { + ce.AsArray32(reusableArray32); + return reusableArray32; + } + + public static explicit operator byte[](CompressedElement ce) + { + ce.AsArray8(reusableArray8); + return reusableArray8; + } + + public static explicit operator Element(CompressedElement ce) + { + return ce.Decompress(); + } + + public static explicit operator Vector3(CompressedElement ce) + { + Element element = ce.Decompress(); + if (ce.crusher.TRSType == TRSType.Quaternion) + { + Debug.LogWarning("Casting CompressedElement of type Quaternion to a Vector3 using quaternion.eulerAngles. Is this intentional? Cast to Quaternion and convert to eulerAnges yourself to silence this warning."); + return element.quat.eulerAngles; + } + return element.v; + } + + public static explicit operator Quaternion(CompressedElement ce) + { + Element element = ce.Decompress(); + TRSType tRSType = ce.crusher.TRSType; + switch (tRSType) + { + case TRSType.Quaternion: + return element.quat; + case TRSType.Euler: + Debug.LogWarning("Casting a CompressedElement of TRSType.Euler to a Quaternion using Quaternion.Euler(). Is this intentional? Cast to Vector3 and convert to Quaternion yourself to silence this warning."); + return Quaternion.Euler(element.v); + default: + Debug.LogError(string.Concat("Trying to cast a CompresedElement of ", tRSType, " to a quaternion, even though it is not a rotation type. Are you using the correct ElementCrusher to compressed this value?")); + return element.quat; + } + } + + public CompressedElement() + { + } + + public CompressedElement(ElementCrusher crusher, CompressedFloat cx, CompressedFloat cy, CompressedFloat cz) + { + this.crusher = crusher; + this.cx = cx; + this.cy = cy; + this.cz = cz; + } + + public CompressedElement(ElementCrusher crusher, uint cx, uint cy, uint cz) + { + UnityEngine.Debug.LogWarning("CE Construct"); + this.crusher = crusher; + this.cx = new CompressedFloat(crusher.XCrusher, cx); + this.cy = new CompressedFloat(crusher.YCrusher, cy); + this.cz = new CompressedFloat(crusher.ZCrusher, cz); + } + + public CompressedElement(ElementCrusher crusher, uint cUniform) + { + UnityEngine.Debug.LogWarning("CE Construct"); + this.crusher = crusher; + this.cUniform = new CompressedFloat(crusher.UCrusher, cUniform); + } + + public CompressedElement(ElementCrusher crusher, ulong cQuat) + { + UnityEngine.Debug.LogWarning("CE Construct"); + this.crusher = crusher; + this.cQuat = new CompressedQuat(crusher.QCrusher, cQuat); + } + + public void Set(ElementCrusher crusher, CompressedFloat cx, CompressedFloat cy, CompressedFloat cz) + { + this.crusher = crusher; + this.cx = cx; + this.cy = cy; + this.cz = cz; + } + + public void Set(ElementCrusher crusher, uint cx, uint cy, uint cz) + { + this.crusher = crusher; + this.cx = new CompressedFloat(crusher.XCrusher, cx); + this.cy = new CompressedFloat(crusher.YCrusher, cy); + this.cz = new CompressedFloat(crusher.ZCrusher, cz); + } + + public void Set(ElementCrusher crusher, uint cUniform) + { + this.crusher = crusher; + this.cUniform = new CompressedFloat(crusher.UCrusher, cUniform); + } + + public void Set(ElementCrusher crusher, ulong cQuat) + { + this.crusher = crusher; + this.cQuat = new CompressedQuat(crusher.QCrusher, cQuat); + } + + public void CopyTo(CompressedElement copyTarget) + { + copyTarget.crusher = crusher; + copyTarget.cx = cx; + copyTarget.cy = cy; + copyTarget.cz = cz; + } + + public void CopyFrom(CompressedElement copySource) + { + crusher = copySource.crusher; + cx = copySource.cx; + cy = copySource.cy; + cz = copySource.cz; + } + + public uint GetUInt(int axis) + { + return axis switch + { + 1 => cy, + 0 => cx, + _ => cz, + }; + } + + public Element Decompress() + { + return crusher.Decompress(this); + } + + public void Serialize(byte[] buffer, ref int bitposition, IncludedAxes ia, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + crusher.Write(this, buffer, ref bitposition, ia, bcl); + } + + [Obsolete("Use a.Compare(b) now instead.")] + public static bool Compare(CompressedElement a, CompressedElement b) + { + return a.Equals(b); + } + + public static int HighestDifferentBit(uint a, uint b) + { + int result = 0; + for (int i = 0; i < 32; i++) + { + uint num = (uint)(1 << i); + if ((a & num) == (b & num)) + { + result = i; + } + } + return result; + } + + public static void Extrapolate(ElementCrusher crusher, CompressedElement target, CompressedElement curr, CompressedElement prev, int divisor = 2) + { + target.Set(crusher, (uint)((uint)curr.cx + ((long)(uint)curr.cx - (long)(uint)prev.cx) / divisor), (uint)((uint)curr.cy + ((long)(uint)curr.cy - (long)(uint)prev.cy) / divisor), (uint)((uint)curr.cz + ((long)(uint)curr.cz - (long)(uint)prev.cz) / divisor)); + } + + [Obsolete] + public static CompressedElement Extrapolate(ElementCrusher crusher, CompressedElement curr, CompressedElement prev, int divisor = 2) + { + return new CompressedElement(crusher, (uint)((uint)curr.cx + ((long)(uint)curr.cx - (long)(uint)prev.cx) / divisor), (uint)((uint)curr.cy + ((long)(uint)curr.cy - (long)(uint)prev.cy) / divisor), (uint)((uint)curr.cz + ((long)(uint)curr.cz - (long)(uint)prev.cz) / divisor)); + } + + public static void Extrapolate(CompressedElement target, CompressedElement curr, CompressedElement prev, int divisor = 2) + { + target.Set(curr.crusher, (uint)((uint)curr.cx + ((long)(uint)curr.cx - (long)(uint)prev.cx) / divisor), (uint)((uint)curr.cy + ((long)(uint)curr.cy - (long)(uint)prev.cy) / divisor), (uint)((uint)curr.cz + ((long)(uint)curr.cz - (long)(uint)prev.cz) / divisor)); + } + + [Obsolete] + public static CompressedElement Extrapolate(CompressedElement curr, CompressedElement prev, int divisor = 2) + { + return new CompressedElement(curr.crusher, (uint)((uint)curr.cx + ((long)(uint)curr.cx - (long)(uint)prev.cx) / divisor), (uint)((uint)curr.cy + ((long)(uint)curr.cy - (long)(uint)prev.cy) / divisor), (uint)((uint)curr.cz + ((long)(uint)curr.cz - (long)(uint)prev.cz) / divisor)); + } + + [Obsolete] + public static void Extrapolate(ElementCrusher crusher, CompressedElement target, CompressedElement curr, CompressedElement prev, float amount = 0.5f) + { + target.Set(crusher, (uint)((float)(ulong)curr.cx + (float)((long)(uint)curr.cx - (long)(uint)prev.cx) * amount), (uint)((float)(ulong)curr.cy + (float)((long)(uint)curr.cy - (long)(uint)prev.cy) * amount), (uint)((float)(ulong)curr.cz + (float)((long)(uint)curr.cz - (long)(uint)prev.cz) * amount)); + } + + [Obsolete] + public static CompressedElement Extrapolate(ElementCrusher crusher, CompressedElement curr, CompressedElement prev, float amount = 0.5f) + { + return new CompressedElement(crusher, (uint)((float)(ulong)curr.cx + (float)((long)(uint)curr.cx - (long)(uint)prev.cx) * amount), (uint)((float)(ulong)curr.cy + (float)((long)(uint)curr.cy - (long)(uint)prev.cy) * amount), (uint)((float)(ulong)curr.cz + (float)((long)(uint)curr.cz - (long)(uint)prev.cz) * amount)); + } + + public static void Extrapolate(CompressedElement target, CompressedElement curr, CompressedElement prev, float amount = 0.5f) + { + target.Set(curr.crusher, (uint)((float)(ulong)curr.cx + (float)((long)(uint)curr.cx - (long)(uint)prev.cx) * amount), (uint)((float)(ulong)curr.cy + (float)((long)(uint)curr.cy - (long)(uint)prev.cy) * amount), (uint)((float)(ulong)curr.cz + (float)((long)(uint)curr.cz - (long)(uint)prev.cz) * amount)); + } + + [Obsolete] + public static CompressedElement Extrapolate(CompressedElement curr, CompressedElement prev, float amount = 0.5f) + { + return new CompressedElement(curr.crusher, (uint)((float)(ulong)curr.cx + (float)((long)(uint)curr.cx - (long)(uint)prev.cx) * amount), (uint)((float)(ulong)curr.cy + (float)((long)(uint)curr.cy - (long)(uint)prev.cy) * amount), (uint)((float)(ulong)curr.cz + (float)((long)(uint)curr.cz - (long)(uint)prev.cz) * amount)); + } + + public static BitCullingLevel GetGuessableBitCullLevel(CompressedElement a, CompressedElement b, BitCullingLevel maxCullLvl) + { + for (BitCullingLevel bitCullingLevel = maxCullLvl; bitCullingLevel > BitCullingLevel.NoCulling; bitCullingLevel--) + { + a.ZeroLowerBits(uppers, bitCullingLevel); + b.ZeroUpperBits(lowers, bitCullingLevel); + if (((ushort)uppers.cx | (ushort)lowers.cx) == (ushort)b.cx && ((ushort)uppers.cy | (ushort)lowers.cy) == (ushort)b.cy && ((ushort)uppers.cz | (ushort)lowers.cz) == (ushort)b.cz) + { + return bitCullingLevel; + } + } + return BitCullingLevel.NoCulling; + } + + [Obsolete] + public static BitCullingLevel GetGuessableBitCullLevel(CompressedElement oldComp, CompressedElement newComp, ElementCrusher ec, BitCullingLevel maxCullLvl) + { + for (BitCullingLevel bitCullingLevel = maxCullLvl; bitCullingLevel > BitCullingLevel.NoCulling; bitCullingLevel--) + { + oldComp.ZeroLowerBits(uppers, bitCullingLevel); + newComp.ZeroUpperBits(lowers, bitCullingLevel); + if (((ushort)uppers.cx | (ushort)lowers.cx) == (ushort)newComp.cx && ((ushort)uppers.cy | (ushort)lowers.cy) == (ushort)newComp.cy && ((ushort)uppers.cz | (ushort)lowers.cz) == (ushort)newComp.cz) + { + return bitCullingLevel; + } + } + return BitCullingLevel.NoCulling; + } + + public static BitCullingLevel FindBestBitCullLevel(CompressedElement a, CompressedElement b, BitCullingLevel maxCulling) + { + ElementCrusher elementCrusher = a.crusher; + if (elementCrusher == null) + { + UnityEngine.Debug.Log("NUL CE CRUSHER FindBestBitCullLevel"); + return BitCullingLevel.NoCulling; + } + if (elementCrusher.TRSType == TRSType.Quaternion) + { + if ((ulong)a.cQuat == (ulong)b.cQuat) + { + return BitCullingLevel.DropAll; + } + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.NoCulling || !TestMatchingUpper(a, b, BitCullingLevel.DropThird)) + { + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.DropThird || !TestMatchingUpper(a, b, BitCullingLevel.DropHalf)) + { + return BitCullingLevel.DropThird; + } + if (maxCulling == BitCullingLevel.DropHalf || !TestMatchingUpper(a, b, BitCullingLevel.DropAll)) + { + return BitCullingLevel.DropHalf; + } + return BitCullingLevel.DropAll; + } + + [Obsolete] + public static BitCullingLevel FindBestBitCullLevel(CompressedElement a, CompressedElement b, ElementCrusher ec, BitCullingLevel maxCulling) + { + if (ec.TRSType == TRSType.Quaternion) + { + if ((ulong)a.cQuat == (ulong)b.cQuat) + { + return BitCullingLevel.DropAll; + } + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.NoCulling || !TestMatchingUpper(a, b, ec, BitCullingLevel.DropThird)) + { + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.DropThird || !TestMatchingUpper(a, b, ec, BitCullingLevel.DropHalf)) + { + return BitCullingLevel.DropThird; + } + if (maxCulling == BitCullingLevel.DropHalf || !TestMatchingUpper(a, b, ec, BitCullingLevel.DropAll)) + { + return BitCullingLevel.DropHalf; + } + return BitCullingLevel.DropAll; + } + + [Obsolete] + public static BitCullingLevel FindBestBitCullLevel(CompressedElement a, CompressedElement b, FloatCrusher[] ec, BitCullingLevel maxCulling) + { + if (maxCulling == BitCullingLevel.NoCulling || !TestMatchingUpper(a, b, ec, BitCullingLevel.DropThird)) + { + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.DropThird || !TestMatchingUpper(a, b, ec, BitCullingLevel.DropHalf)) + { + return BitCullingLevel.DropThird; + } + if (maxCulling == BitCullingLevel.DropHalf || !TestMatchingUpper(a, b, ec, BitCullingLevel.DropAll)) + { + return BitCullingLevel.DropHalf; + } + return BitCullingLevel.DropAll; + } + + private static bool TestMatchingUpper(uint a, uint b, int lowerbits) + { + return a >> lowerbits << lowerbits == b >> lowerbits << lowerbits; + } + + public static bool TestMatchingUpper(CompressedElement a, CompressedElement b, BitCullingLevel bcl) + { + ElementCrusher elementCrusher = a.crusher; + if (TestMatchingUpper(a.cx, b.cx, elementCrusher.XCrusher.GetBits(bcl)) && TestMatchingUpper(a.cy, b.cy, elementCrusher.YCrusher.GetBits(bcl))) + { + return TestMatchingUpper(a.cz, b.cz, elementCrusher.ZCrusher.GetBits(bcl)); + } + return false; + } + + [Obsolete] + public static bool TestMatchingUpper(CompressedElement a, CompressedElement b, ElementCrusher ec, BitCullingLevel bcl) + { + if (TestMatchingUpper(a.cx, b.cx, ec[0].GetBits(bcl)) && TestMatchingUpper(a.cy, b.cy, ec[1].GetBits(bcl))) + { + return TestMatchingUpper(a.cz, b.cz, ec[2].GetBits(bcl)); + } + return false; + } + + [Obsolete] + public static bool TestMatchingUpper(CompressedElement a, CompressedElement b, FloatCrusher[] ec, BitCullingLevel bcl) + { + if (TestMatchingUpper(a.cx, b.cx, ec[0].GetBitsAtCullLevel(bcl)) && TestMatchingUpper(a.cy, b.cy, ec[1].GetBitsAtCullLevel(bcl))) + { + return TestMatchingUpper(a.cz, b.cz, ec[2].GetBitsAtCullLevel(bcl)); + } + return false; + } + + public override string ToString() + { + if (crusher == null) + { + return "[Empty CompElement]"; + } + if (crusher.TRSType == TRSType.Quaternion) + { + return string.Concat(crusher.TRSType, " [", cQuat.cvalue, "]"); + } + if (crusher.TRSType == TRSType.Scale && crusher.uniformAxes != 0) + { + return string.Concat(crusher.TRSType, " [", crusher.uniformAxes, " : ", cUniform.cvalue, "]"); + } + return string.Concat(crusher.TRSType, " [x:", cx.cvalue, " y:", cy.cvalue, " z:", cz.cvalue, "]"); + } + + public static bool operator ==(CompressedElement a, CompressedElement b) + { + return a?.Equals(b) ?? false; + } + + public static bool operator !=(CompressedElement a, CompressedElement b) + { + if ((object)a == null) + { + return true; + } + return !a.Equals(b); + } + + public override bool Equals(object obj) + { + return Equals(obj as CompressedElement); + } + + public bool Equals(CompressedElement other) + { + if ((object)other != null && cx.cvalue == other.cx.cvalue && cy.cvalue == other.cy.cvalue && cz.cvalue == other.cz.cvalue && cUniform.cvalue == other.cUniform.cvalue) + { + return cQuat.cvalue == other.cQuat.cvalue; + } + return false; + } + + public override int GetHashCode() + { + return ((((/*-1337834834 * -1521134295 */+ cx.GetHashCode()) * -1521134295 + cy.GetHashCode()) * -1521134295 + cz.GetHashCode()) * -1521134295 + cUniform.GetHashCode()) * -1521134295 + cQuat.GetHashCode(); + } +} diff --git a/ROUNDS/Photon.Compression/CompressedElementExt.cs b/ROUNDS/Photon.Compression/CompressedElementExt.cs new file mode 100644 index 0000000..53642ae --- /dev/null +++ b/ROUNDS/Photon.Compression/CompressedElementExt.cs @@ -0,0 +1,113 @@ +using System; +using System.Text; +using emotitron.Compression; + +namespace Photon.Compression; + +public static class CompressedElementExt +{ + public static uint[] reusableInts = new uint[3]; + + public static StringBuilder AppendSB(this StringBuilder strb, CompressedElement ce) + { + if ((object)ce == null) + { + strb.Append("[Null CompElement]"); + } + else + { + ElementCrusher crusher = ce.crusher; + if (crusher == null) + { + strb.Append("[CE Null Crusher]"); + } + else if (crusher.TRSType == TRSType.Quaternion) + { + strb.Append(crusher.TRSType).Append(" cQuat: [").Append(ce.cQuat.cvalue) + .Append("]"); + } + else if (crusher.TRSType == TRSType.Scale && crusher.uniformAxes != 0) + { + strb.Append(crusher.TRSType).Append(" cUni: [").Append(crusher.uniformAxes) + .Append(" : ") + .Append(ce.cUniform.cvalue) + .Append("]"); + } + else + { + strb.Append(crusher.TRSType).Append(" cXYZ: [x:").Append(ce.cx.cvalue) + .Append(" y:") + .Append(ce.cy.cvalue) + .Append(" z:") + .Append(ce.cz.cvalue) + .Append("]"); + } + } + return strb; + } + + public static void GetChangeAmount(uint[] results, CompressedElement a, CompressedElement b) + { + for (int i = 0; i < 3; i++) + { + results[i] = (uint)Math.Abs(a[i] - b[0]); + } + } + + [Obsolete] + public static uint[] GetChangeAmount(CompressedElement a, CompressedElement b) + { + for (int i = 0; i < 3; i++) + { + reusableInts[i] = (uint)Math.Abs(a[i] - b[0]); + } + return reusableInts; + } + + public static void GuessUpperBits(this CompressedElement newcpos, ElementCrusher ec, CompressedElement oldcpos, BitCullingLevel bcl) + { + newcpos.Set(ec, ec.XCrusher.GuessUpperBits(newcpos[0], oldcpos[0], bcl), ec.YCrusher.GuessUpperBits(newcpos[1], oldcpos[1], bcl), ec.ZCrusher.GuessUpperBits(newcpos[2], oldcpos[2], bcl)); + } + + [Obsolete] + public static CompressedElement GuessUpperBits(this CompressedElement newcpos, CompressedElement oldcpos, ElementCrusher ec, BitCullingLevel bcl) + { + return new CompressedElement(ec, ec.XCrusher.GuessUpperBits(newcpos[0], oldcpos[0], bcl), ec.YCrusher.GuessUpperBits(newcpos[1], oldcpos[1], bcl), ec.ZCrusher.GuessUpperBits(newcpos[2], oldcpos[2], bcl)); + } + + public static void OverwriteUpperBits(this CompressedElement low, CompressedElement uppers, BitCullingLevel bcl) + { + ElementCrusher crusher = low.crusher; + low.Set(crusher, crusher.XCrusher.OverwriteUpperBits(low.cx, uppers.cx, bcl), crusher.YCrusher.OverwriteUpperBits(low.cy, uppers.cy, bcl), crusher.ZCrusher.OverwriteUpperBits(low.cz, uppers.cz, bcl)); + } + + [Obsolete] + public static CompressedElement OverwriteUpperBits(this CompressedElement low, CompressedElement up, ElementCrusher ec, BitCullingLevel bcl) + { + return new CompressedElement(ec, ec[0].OverwriteUpperBits(low.cx, up.cx, bcl), ec[1].OverwriteUpperBits(low.cy, up.cy, bcl), ec[2].OverwriteUpperBits(low.cz, up.cz, bcl)); + } + + public static void ZeroLowerBits(this CompressedElement fullpos, CompressedElement target, BitCullingLevel bcl) + { + ElementCrusher crusher = fullpos.crusher; + target.Set(crusher, crusher.XCrusher.ZeroLowerBits(fullpos.cx, bcl), crusher.YCrusher.ZeroLowerBits(fullpos.cy, bcl), crusher.ZCrusher.ZeroLowerBits(fullpos.cz, bcl)); + } + + [Obsolete] + public static CompressedElement ZeroLowerBits(this CompressedElement fullpos, ElementCrusher ec, BitCullingLevel bcl) + { + return new CompressedElement(ec, ec[0].ZeroLowerBits(fullpos.cx, bcl), ec[1].ZeroLowerBits(fullpos.cy, bcl), ec[2].ZeroLowerBits(fullpos.cz, bcl)); + } + + public static void ZeroUpperBits(this CompressedElement fullpos, CompressedElement target, BitCullingLevel bcl) + { + ElementCrusher crusher = fullpos.crusher; + target.Set(crusher, crusher.XCrusher.ZeroUpperBits(fullpos.cx, bcl), crusher.YCrusher.ZeroUpperBits(fullpos.cy, bcl), crusher.ZCrusher.ZeroUpperBits(fullpos.cz, bcl)); + } + + [Obsolete] + public static CompressedElement ZeroUpperBits(this CompressedElement fullpos, ElementCrusher ec, BitCullingLevel bcl) + { + return new CompressedElement(ec, ec[0].ZeroUpperBits(fullpos.cx, bcl), ec[1].ZeroUpperBits(fullpos.cy, bcl), ec[2].ZeroUpperBits(fullpos.cz, bcl)); + } +} diff --git a/ROUNDS/Photon.Compression/CompressedMatrix.cs b/ROUNDS/Photon.Compression/CompressedMatrix.cs new file mode 100644 index 0000000..43efcc6 --- /dev/null +++ b/ROUNDS/Photon.Compression/CompressedMatrix.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using emotitron.Compression; +using UnityEngine; + +namespace Photon.Compression; + +public class CompressedMatrix : IEquatable<CompressedMatrix> +{ + public CompressedElement cPos = new CompressedElement(); + + public CompressedElement cRot = new CompressedElement(); + + public CompressedElement cScl = new CompressedElement(); + + public TransformCrusher crusher; + + public static CompressedMatrix reusable = new CompressedMatrix(); + + protected static readonly ulong[] reusableArray64 = new ulong[6]; + + protected static readonly uint[] reusableArray32 = new uint[12]; + + protected static readonly byte[] reusableArray8 = new byte[24]; + + public CompressedMatrix() + { + } + + public CompressedMatrix(TransformCrusher crusher) + { + this.crusher = crusher; + } + + public CompressedMatrix(TransformCrusher crusher, CompressedElement cPos, CompressedElement cRot, CompressedElement cScl) + { + this.crusher = crusher; + this.cPos = cPos; + this.cRot = cRot; + this.cScl = cScl; + } + + public CompressedMatrix(TransformCrusher crusher, ref CompressedElement cPos, ref CompressedElement cRot, ref CompressedElement cScl, int pBits, int rBits, int sBits) + { + this.crusher = crusher; + this.cPos = cPos; + this.cRot = cRot; + this.cScl = cScl; + } + + public void CopyTo(CompressedMatrix copyTarget) + { + cPos.CopyTo(copyTarget.cPos); + cRot.CopyTo(copyTarget.cRot); + cScl.CopyTo(copyTarget.cScl); + } + + public void CopyFrom(CompressedMatrix copySource) + { + cPos.CopyFrom(copySource.cPos); + cRot.CopyFrom(copySource.cRot); + cScl.CopyFrom(copySource.cScl); + } + + public void Clear() + { + crusher = null; + cPos.Clear(); + cRot.Clear(); + cScl.Clear(); + } + + public ulong[] AsArray64(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + crusher.Write(this, reusableArray64, ref bitposition, bcl); + reusableArray64.Zero(bitposition + 63 >> 6); + return reusableArray64; + } + + public void AsArray64(ulong[] nonalloc, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + crusher.Write(this, nonalloc, ref bitposition, bcl); + nonalloc.Zero(bitposition + 63 >> 6); + } + + public uint[] AsArray32(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + crusher.Write(this, reusableArray32, ref bitposition, bcl); + reusableArray32.Zero(bitposition + 31 >> 5); + return reusableArray32; + } + + public void AsArray32(uint[] nonalloc, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + crusher.Write(this, nonalloc, ref bitposition, bcl); + nonalloc.Zero(bitposition + 31 >> 5); + } + + public byte[] AsArray8(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + crusher.Write(this, reusableArray64, ref bitposition, bcl); + reusableArray8.Zero(bitposition + 7 >> 3); + return reusableArray8; + } + + public void AsArray8(byte[] nonalloc, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + crusher.Write(this, nonalloc, ref bitposition, bcl); + nonalloc.Zero(bitposition + 7 >> 3); + } + + public static explicit operator ulong(CompressedMatrix cm) + { + ulong buffer = 0uL; + int bitposition = 0; + cm.crusher.Write(cm, ref buffer, ref bitposition); + return buffer; + } + + public static explicit operator uint(CompressedMatrix cm) + { + ulong buffer = 0uL; + int bitposition = 0; + cm.crusher.Write(cm, ref buffer, ref bitposition); + return (uint)buffer; + } + + public static explicit operator ushort(CompressedMatrix cm) + { + ulong buffer = 0uL; + int bitposition = 0; + cm.crusher.Write(cm, ref buffer, ref bitposition); + return (ushort)buffer; + } + + public static explicit operator byte(CompressedMatrix cm) + { + ulong buffer = 0uL; + int bitposition = 0; + cm.crusher.Write(cm, ref buffer, ref bitposition); + return (byte)buffer; + } + + public static explicit operator ulong[](CompressedMatrix cm) + { + return cm.AsArray64(); + } + + public static explicit operator uint[](CompressedMatrix cm) + { + return cm.AsArray32(); + } + + public static explicit operator byte[](CompressedMatrix cm) + { + return cm.AsArray8(); + } + + public void Decompress(Matrix nonalloc) + { + if (crusher != null) + { + crusher.Decompress(nonalloc, this); + } + else + { + nonalloc.Clear(); + } + } + + public Matrix Decompress() + { + crusher.Decompress(Matrix.reusable, this); + return Matrix.reusable; + } + + [Obsolete("Supply the transform to Compress. Default Transform has been deprecated to allow shared TransformCrushers.")] + public void Apply() + { + if (crusher != null) + { + crusher.Apply(this); + } + } + + public void Apply(Transform t) + { + if (crusher != null) + { + crusher.Apply(t, this); + } + } + + [Obsolete("Apply for Rigidbody has been replaced with Move and Set, to indicate usage of MovePosition/Rotation vs rb.position/rotation.")] + public void Apply(Rigidbody rb) + { + if (crusher != null) + { + crusher.Apply(rb, this); + } + } + + public void Set(Rigidbody rb) + { + if (crusher != null) + { + crusher.Set(rb, this); + } + } + + public void Move(Rigidbody rb) + { + if (crusher != null) + { + crusher.Move(rb, this); + } + } + + public static bool operator ==(CompressedMatrix a, CompressedMatrix b) + { + return a?.Equals(b) ?? false; + } + + public static bool operator !=(CompressedMatrix a, CompressedMatrix b) + { + if ((object)a == null) + { + return true; + } + return !a.Equals(b); + } + + public override bool Equals(object obj) + { + return Equals(obj as CompressedMatrix); + } + + public bool Equals(CompressedMatrix other) + { + if ((object)other != null && cPos.Equals(other.cPos) && cRot.Equals(other.cRot)) + { + return cScl.Equals(other.cScl); + } + return false; + } + + public override int GetHashCode() + { + //return (((94804922 * -1521134295 + cPos.GetHashCode()) * -1521134295 + cRot.GetHashCode()) * -1521134295 + cScl.GetHashCode()) * -1521134295 + EqualityComparer<TransformCrusher>.Default.GetHashCode(crusher); + return (((/*94804922 * -1521134295 + */cPos.GetHashCode()) * -1521134295 + cRot.GetHashCode()) * -1521134295 + cScl.GetHashCode()) * -1521134295 + EqualityComparer<TransformCrusher>.Default.GetHashCode(crusher); + } +} diff --git a/ROUNDS/Photon.Compression/CompressedQuat.cs b/ROUNDS/Photon.Compression/CompressedQuat.cs new file mode 100644 index 0000000..10f90a3 --- /dev/null +++ b/ROUNDS/Photon.Compression/CompressedQuat.cs @@ -0,0 +1,68 @@ +using UnityEngine; + +namespace Photon.Compression; + +public struct CompressedQuat +{ + public readonly QuatCrusher crusher; + + public readonly ulong cvalue; + + public CompressedQuat(QuatCrusher crusher, ulong cvalue) + { + this = default(CompressedQuat); + this.crusher = crusher; + this.cvalue = cvalue; + } + + public CompressedQuat(QuatCrusher crusher, uint cvalue) + { + this = default(CompressedQuat); + this.crusher = crusher; + this.cvalue = cvalue; + } + + public CompressedQuat(QuatCrusher crusher, ushort cvalue) + { + this = default(CompressedQuat); + this.crusher = crusher; + this.cvalue = cvalue; + } + + public CompressedQuat(QuatCrusher crusher, byte cvalue) + { + this = default(CompressedQuat); + this.crusher = crusher; + this.cvalue = cvalue; + } + + public static implicit operator ulong(CompressedQuat cv) + { + return cv.cvalue; + } + + public static explicit operator uint(CompressedQuat cv) + { + return (uint)cv.cvalue; + } + + public static explicit operator ushort(CompressedQuat cv) + { + return (ushort)cv.cvalue; + } + + public static explicit operator byte(CompressedQuat cv) + { + return (byte)cv.cvalue; + } + + public Quaternion Decompress() + { + return crusher.Decompress(cvalue); + } + + public override string ToString() + { + return string.Concat("[CompressedQuat: ", cvalue, " bits: ", crusher, "] "); + } +} diff --git a/ROUNDS/Photon.Compression/DefaultKeyRate.cs b/ROUNDS/Photon.Compression/DefaultKeyRate.cs new file mode 100644 index 0000000..62eacd2 --- /dev/null +++ b/ROUNDS/Photon.Compression/DefaultKeyRate.cs @@ -0,0 +1,12 @@ +namespace Photon.Compression; + +public enum DefaultKeyRate +{ + Never = 0, + Every = 1, + Every2nd = 2, + Every3rd = 3, + Every4th = 4, + Every5th = 5, + Every10th = 10 +} diff --git a/ROUNDS/Photon.Compression/DefaultPackInclusion.cs b/ROUNDS/Photon.Compression/DefaultPackInclusion.cs new file mode 100644 index 0000000..4cbff53 --- /dev/null +++ b/ROUNDS/Photon.Compression/DefaultPackInclusion.cs @@ -0,0 +1,7 @@ +namespace Photon.Compression; + +public enum DefaultPackInclusion +{ + Explicit, + AllPublic +} diff --git a/ROUNDS/Photon.Compression/Element.cs b/ROUNDS/Photon.Compression/Element.cs new file mode 100644 index 0000000..02dc28c --- /dev/null +++ b/ROUNDS/Photon.Compression/Element.cs @@ -0,0 +1,160 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace Photon.Compression; + +[StructLayout(LayoutKind.Explicit)] +public struct Element : IEquatable<Element> +{ + public enum VectorType + { + Vector3 = 1, + Quaternion + } + + [FieldOffset(0)] + public VectorType vectorType; + + [FieldOffset(4)] + public Vector3 v; + + [FieldOffset(4)] + public Quaternion quat; + + public Element(Vector3 v) + { + this = default(Element); + vectorType = VectorType.Vector3; + this.v = v; + } + + public Element(Quaternion quat) + { + this = default(Element); + vectorType = VectorType.Quaternion; + this.quat = quat; + } + + public static explicit operator Quaternion(Element e) + { + if (e.vectorType == VectorType.Quaternion) + { + return e.quat; + } + return Quaternion.Euler(e.v); + } + + public static explicit operator Vector3(Element e) + { + if (e.vectorType == VectorType.Vector3) + { + return e.v; + } + return e.quat.eulerAngles; + } + + public static Element Slerp(Element a, Element b, float t) + { + if (a.vectorType == VectorType.Quaternion) + { + return Quaternion.Slerp((Quaternion)a, (Quaternion)b, t); + } + return Vector3.Slerp((Vector3)a, (Vector3)b, t); + } + + public static Element SlerpUnclamped(Element a, Element b, float t) + { + if (a.vectorType == VectorType.Quaternion) + { + return Quaternion.SlerpUnclamped((Quaternion)a, (Quaternion)b, t); + } + return Vector3.SlerpUnclamped((Vector3)a, (Vector3)b, t); + } + + public static bool operator ==(Element a, Element b) + { + if (a.vectorType != b.vectorType || a.vectorType != VectorType.Vector3) + { + if (a.quat.x == b.quat.x && a.quat.y == b.quat.y && a.quat.z == b.quat.z) + { + return a.quat.w == b.quat.w; + } + return false; + } + if (a.v.x == b.v.x && a.v.y == b.v.y) + { + return a.v.z == b.v.z; + } + return false; + } + + public static bool operator !=(Element a, Element b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj is Element) + { + return Equals((Element)obj); + } + return false; + } + + public bool Equals(Element other) + { + if (vectorType != other.vectorType || vectorType != VectorType.Vector3) + { + if (quat.x == other.quat.x && quat.y == other.quat.y && quat.z == other.quat.z) + { + return quat.w == other.quat.w; + } + return false; + } + if (v.x == other.v.x && v.y == other.v.y) + { + return v.z == other.v.z; + } + return false; + } + + public static bool Equals(Vector3 a, Vector3 b) + { + if (a.x == b.x && a.y == b.y) + { + return a.z == b.z; + } + return false; + } + + public static bool Equals(Quaternion a, Quaternion b) + { + if (a.x == b.x && a.y == b.y && a.z == b.z) + { + return a.w == b.w; + } + return false; + } + + public static implicit operator Element(Quaternion q) + { + return new Element(q); + } + + public static implicit operator Element(Vector3 v) + { + return new Element(v); + } + + public override string ToString() + { + return string.Concat(vectorType, " ", (vectorType == VectorType.Quaternion) ? quat.ToString() : v.ToString()); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } +} diff --git a/ROUNDS/Photon.Compression/ElementCrusher.cs b/ROUNDS/Photon.Compression/ElementCrusher.cs new file mode 100644 index 0000000..f71867a --- /dev/null +++ b/ROUNDS/Photon.Compression/ElementCrusher.cs @@ -0,0 +1,2188 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using emotitron.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public class ElementCrusher : Crusher<ElementCrusher>, IEquatable<ElementCrusher>, ICrusherCopy<ElementCrusher> +{ + public enum UniformAxes + { + NonUniform = 0, + XY = 3, + XZ = 5, + YZ = 6, + XYZ = 7 + } + + public enum StaticTRSType + { + Position, + Euler, + Quaternion, + Scale, + Generic + } + + public static Dictionary<int, ElementCrusher> staticElementCrushers = new Dictionary<int, ElementCrusher>(); + + private static readonly CompressedElement reusableCE = new CompressedElement(); + + public static ElementCrusher defaultUncompressedElementCrusher = CheckAgainstStatics(new ElementCrusher(StaticTRSType.Generic) + { + XCrusher = FloatCrusher.defaultUncompressedCrusher, + YCrusher = FloatCrusher.defaultUncompressedCrusher, + ZCrusher = FloatCrusher.defaultUncompressedCrusher, + UCrusher = FloatCrusher.defaultUncompressedCrusher + }); + + public static ElementCrusher defaultUncompressedPosCrusher = CheckAgainstStatics(new ElementCrusher(StaticTRSType.Position) + { + XCrusher = FloatCrusher.defaultUncompressedCrusher, + YCrusher = FloatCrusher.defaultUncompressedCrusher, + ZCrusher = FloatCrusher.defaultUncompressedCrusher, + UCrusher = FloatCrusher.defaultUncompressedCrusher + }); + + public static ElementCrusher defaultUncompressedSclCrusher = CheckAgainstStatics(new ElementCrusher(StaticTRSType.Position) + { + XCrusher = FloatCrusher.defaultUncompressedCrusher, + YCrusher = FloatCrusher.defaultUncompressedCrusher, + ZCrusher = FloatCrusher.defaultUncompressedCrusher, + UCrusher = FloatCrusher.defaultUncompressedCrusher + }); + + public static ElementCrusher defaultHalfFloatElementCrusher = CheckAgainstStatics(new ElementCrusher(StaticTRSType.Generic) + { + XCrusher = FloatCrusher.defaultUncompressedCrusher, + YCrusher = FloatCrusher.defaultUncompressedCrusher, + ZCrusher = FloatCrusher.defaultUncompressedCrusher, + UCrusher = FloatCrusher.defaultUncompressedCrusher + }); + + public static ElementCrusher defaultHalfFloatPosCrusher = CheckAgainstStatics(new ElementCrusher(StaticTRSType.Position) + { + XCrusher = FloatCrusher.defaulHalfFloatCrusher, + YCrusher = FloatCrusher.defaulHalfFloatCrusher, + ZCrusher = FloatCrusher.defaulHalfFloatCrusher, + UCrusher = FloatCrusher.defaulHalfFloatCrusher + }); + + public static ElementCrusher defaultHalfFloatSclCrusher = CheckAgainstStatics(new ElementCrusher(StaticTRSType.Scale) + { + XCrusher = FloatCrusher.defaulHalfFloatCrusher, + YCrusher = FloatCrusher.defaulHalfFloatCrusher, + ZCrusher = FloatCrusher.defaulHalfFloatCrusher, + UCrusher = FloatCrusher.defaulHalfFloatCrusher + }); + + public bool hideFieldName; + + [SerializeField] + private TRSType _trsType; + + [SerializeField] + public Transform defaultTransform; + + [SerializeField] + public UniformAxes uniformAxes; + + [SerializeField] + private FloatCrusher _xcrusher; + + [SerializeField] + private FloatCrusher _ycrusher; + + [SerializeField] + private FloatCrusher _zcrusher; + + [SerializeField] + private FloatCrusher _ucrusher; + + [SerializeField] + private QuatCrusher _qcrusher; + + [SerializeField] + public bool local; + + [SerializeField] + private bool useWorldBounds; + + [WorldBoundsSelectAttribute] + [HideInInspector] + [SerializeField] + private int boundsGroupId; + + [SerializeField] + public bool enableTRSTypeSelector; + + [SerializeField] + public bool enableLocalSelector = true; + + [NonSerialized] + private bool cached; + + [NonSerialized] + private bool cache_xEnabled; + + [NonSerialized] + private bool cache_yEnabled; + + [NonSerialized] + private bool cache_zEnabled; + + [NonSerialized] + private bool cache_uEnabled; + + [NonSerialized] + private bool cache_qEnabled; + + [NonSerialized] + private bool cache_isUniformScale; + + [NonSerialized] + private readonly int[] cache_xBits = new int[4]; + + [NonSerialized] + private readonly int[] cache_yBits = new int[4]; + + [NonSerialized] + private readonly int[] cache_zBits = new int[4]; + + [NonSerialized] + private readonly int[] cache_uBits = new int[4]; + + [NonSerialized] + private readonly int[] cache_TotalBits = new int[4]; + + public ReadOnlyCollection<int> Cached_TotalBits; + + [NonSerialized] + private int cache_qBits; + + [NonSerialized] + private bool cache_mustCorrectRotationX; + + public Bounds bounds; + + public static ulong[] reusableArray64 = new ulong[2]; + + public TRSType TRSType + { + get + { + return _trsType; + } + set + { + _trsType = value; + _xcrusher.TRSType = value; + _ycrusher.TRSType = value; + _zcrusher.TRSType = value; + } + } + + [Obsolete("Use the XCrusher property instead.")] + public FloatCrusher xcrusher + { + get + { + return XCrusher; + } + set + { + XCrusher = value; + } + } + + [Obsolete("Use the YCrusher property instead.")] + public FloatCrusher ycrusher + { + get + { + return YCrusher; + } + set + { + YCrusher = value; + } + } + + [Obsolete("Use the ZCrusher property instead.")] + public FloatCrusher zcrusher + { + get + { + return ZCrusher; + } + set + { + ZCrusher = value; + } + } + + [Obsolete("Use the UCrusher property instead.")] + public FloatCrusher ucrusher + { + get + { + return UCrusher; + } + set + { + UCrusher = value; + } + } + + [Obsolete("Use the QCrusher property instead.")] + public QuatCrusher qcrusher + { + get + { + return QCrusher; + } + set + { + QCrusher = value; + } + } + + public FloatCrusher XCrusher + { + get + { + return _xcrusher; + } + set + { + if (_xcrusher != value) + { + if (_xcrusher != null) + { + FloatCrusher floatCrusher = _xcrusher; + floatCrusher.OnRecalculated = (Action<FloatCrusher>)Delegate.Remove(floatCrusher.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + _xcrusher = value; + if (_xcrusher != null) + { + FloatCrusher floatCrusher2 = _xcrusher; + floatCrusher2.OnRecalculated = (Action<FloatCrusher>)Delegate.Combine(floatCrusher2.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public FloatCrusher YCrusher + { + get + { + return _ycrusher; + } + set + { + if (_ycrusher != value) + { + if (_ycrusher != null) + { + FloatCrusher floatCrusher = _ycrusher; + floatCrusher.OnRecalculated = (Action<FloatCrusher>)Delegate.Remove(floatCrusher.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + _ycrusher = value; + if (_ycrusher != null) + { + FloatCrusher floatCrusher2 = _ycrusher; + floatCrusher2.OnRecalculated = (Action<FloatCrusher>)Delegate.Combine(floatCrusher2.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public FloatCrusher ZCrusher + { + get + { + return _zcrusher; + } + set + { + if (_zcrusher != value) + { + if (_zcrusher != null) + { + FloatCrusher floatCrusher = _zcrusher; + floatCrusher.OnRecalculated = (Action<FloatCrusher>)Delegate.Remove(floatCrusher.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + _zcrusher = value; + if (_zcrusher != null) + { + FloatCrusher floatCrusher2 = _zcrusher; + floatCrusher2.OnRecalculated = (Action<FloatCrusher>)Delegate.Combine(floatCrusher2.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public FloatCrusher UCrusher + { + get + { + return _ucrusher; + } + set + { + if (_ucrusher != value) + { + if (_ucrusher != null) + { + FloatCrusher floatCrusher = _ucrusher; + floatCrusher.OnRecalculated = (Action<FloatCrusher>)Delegate.Remove(floatCrusher.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + _ucrusher = value; + if (_ucrusher != null) + { + FloatCrusher floatCrusher2 = _ucrusher; + floatCrusher2.OnRecalculated = (Action<FloatCrusher>)Delegate.Combine(floatCrusher2.OnRecalculated, new Action<FloatCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public QuatCrusher QCrusher + { + get + { + return _qcrusher; + } + set + { + if ((object)_qcrusher != value) + { + if (_qcrusher != null) + { + QuatCrusher quatCrusher = _qcrusher; + quatCrusher.OnRecalculated = (Action<QuatCrusher>)Delegate.Remove(quatCrusher.OnRecalculated, new Action<QuatCrusher>(OnCrusherChange)); + } + _qcrusher = value; + if (_qcrusher != null) + { + QuatCrusher quatCrusher2 = _qcrusher; + quatCrusher2.OnRecalculated = (Action<QuatCrusher>)Delegate.Combine(quatCrusher2.OnRecalculated, new Action<QuatCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + [SerializeField] + public bool UseWorldBounds + { + get + { + return useWorldBounds; + } + set + { + ApplyWorldCrusherSettings(value, boundsGroupId); + } + } + + public int BoundsGroupId + { + get + { + return boundsGroupId; + } + set + { + ApplyWorldCrusherSettings(useWorldBounds, value); + } + } + + public Bounds Bounds + { + get + { + bounds.SetMinMax(new Vector3((_xcrusher != null) ? _xcrusher.Min : 0f, (_ycrusher != null) ? _ycrusher.Min : 0f, (_zcrusher != null) ? _zcrusher.Min : 0f), new Vector3((_xcrusher != null) ? _xcrusher.Max : 0f, (_ycrusher != null) ? _ycrusher.Max : 0f, (_zcrusher != null) ? _zcrusher.Max : 0f)); + return bounds; + } + set + { + if (_xcrusher != null) + { + _xcrusher.SetRange(value.min.x, value.max.x); + } + if (_ycrusher != null) + { + _ycrusher.SetRange(value.min.y, value.max.y); + } + if (_zcrusher != null) + { + _zcrusher.SetRange(value.min.z, value.max.z); + } + CacheValues(); + } + } + + public bool Enabled + { + get + { + if (TRSType == TRSType.Quaternion) + { + if (_qcrusher.Enabled) + { + return _qcrusher.Bits > 0; + } + return false; + } + if (TRSType == TRSType.Scale && uniformAxes != 0) + { + return _ucrusher.Enabled; + } + return _xcrusher.Enabled | _ycrusher.Enabled | _zcrusher.Enabled; + } + set + { + if (TRSType == TRSType.Quaternion) + { + _qcrusher.Enabled = value; + } + else if (TRSType == TRSType.Scale && uniformAxes != 0) + { + _ucrusher.Enabled = value; + } + _xcrusher.Enabled = value; + _ycrusher.Enabled = value; + _zcrusher.Enabled = value; + } + } + + public FloatCrusher this[int axis] + { + get + { + switch (axis) + { + case 0: + return _xcrusher; + case 1: + return _ycrusher; + case 2: + return _zcrusher; + default: + Debug.Log("AXIS " + axis + " should not be calling happening"); + return null; + } + } + } + + public static ElementCrusher GetStaticPositionCrusher(Bounds bounds, int resolution) + { + return CheckAgainstStatics(new ElementCrusher(StaticTRSType.Position) + { + XCrusher = FloatCrusher.GetStaticFloatCrusher(resolution, bounds.min.x, bounds.max.x, Axis.Generic, TRSType.Position), + YCrusher = FloatCrusher.GetStaticFloatCrusher(resolution, bounds.min.y, bounds.max.y, Axis.Generic, TRSType.Position), + ZCrusher = FloatCrusher.GetStaticFloatCrusher(resolution, bounds.min.z, bounds.max.z, Axis.Generic, TRSType.Position) + }); + } + + public static ElementCrusher GetStaticQuatCrusher(int minBits) + { + return CheckAgainstStatics(new ElementCrusher(StaticTRSType.Quaternion) + { + QCrusher = new QuatCrusher(showEnableToggle: false, isStandalone: false) + { + Bits = minBits + } + }); + } + + public static ElementCrusher CheckAgainstStatics(ElementCrusher ec, bool CheckAgainstFloatCrushersAsWell = true) + { + if ((object)ec == null) + { + return null; + } + if (CheckAgainstFloatCrushersAsWell) + { + if (ec.cache_xEnabled) + { + ec.XCrusher = FloatCrusher.CheckAgainstStatics(ec._xcrusher); + } + if (ec.cache_yEnabled) + { + ec.YCrusher = FloatCrusher.CheckAgainstStatics(ec._ycrusher); + } + if (ec.cache_zEnabled) + { + ec.ZCrusher = FloatCrusher.CheckAgainstStatics(ec._zcrusher); + } + if (ec.cache_uEnabled) + { + ec.UCrusher = FloatCrusher.CheckAgainstStatics(ec._ucrusher); + } + } + int hashCode = ec.GetHashCode(); + if (staticElementCrushers.ContainsKey(hashCode)) + { + return staticElementCrushers[hashCode]; + } + staticElementCrushers.Add(hashCode, ec); + return ec; + } + + public void OnCrusherChange(QuatCrusher crusher) + { + CacheValues(); + } + + public void OnCrusherChange(FloatCrusher crusher) + { + CacheValues(); + } + + private void OnWorldBoundsReady() + { + ApplyWorldCrusherSettings(); + CacheValues(); + } + + public void ApplyWorldCrusherSettings() + { + if (!useWorldBounds) + { + return; + } + if (SettingsScriptableObject<WorldBoundsSettings>.single == null) + { + SettingsScriptableObject<WorldBoundsSettings>.OnSingletonReady = (Action)Delegate.Remove(SettingsScriptableObject<WorldBoundsSettings>.OnSingletonReady, new Action(OnWorldBoundsReady)); + SettingsScriptableObject<WorldBoundsSettings>.OnSingletonReady = (Action)Delegate.Combine(SettingsScriptableObject<WorldBoundsSettings>.OnSingletonReady, new Action(OnWorldBoundsReady)); + return; + } + SettingsScriptableObject<WorldBoundsSettings>.OnSingletonReady = (Action)Delegate.Remove(SettingsScriptableObject<WorldBoundsSettings>.OnSingletonReady, new Action(OnWorldBoundsReady)); + List<WorldBoundsGroup> worldBoundsGroups = SettingsScriptableObject<WorldBoundsSettings>.single.worldBoundsGroups; + if (boundsGroupId >= worldBoundsGroups.Count) + { + Debug.LogError("WorldBoundsGroup " + boundsGroupId + " no longer exists. Using Default(0)."); + boundsGroupId = 0; + } + WorldBoundsGroup worldBoundsGroup = worldBoundsGroups[boundsGroupId]; + worldBoundsGroup.OnWorldBoundChanged = (Action)Delegate.Remove(worldBoundsGroup.OnWorldBoundChanged, new Action(CacheValues)); + worldBoundsGroup.OnWorldBoundChanged = (Action)Delegate.Combine(worldBoundsGroup.OnWorldBoundChanged, new Action(CacheValues)); + ElementCrusher crusher = worldBoundsGroup.crusher; + if (_xcrusher != crusher._xcrusher) + { + XCrusher = crusher.XCrusher; + } + if (_ycrusher != crusher._ycrusher) + { + YCrusher = crusher.YCrusher; + } + if (_zcrusher != crusher._zcrusher) + { + ZCrusher = crusher.ZCrusher; + } + local = crusher.local; + } + + public void ApplyWorldCrusherSettings(bool newUseBounds, int newBndsGrpId) + { + if (newUseBounds != useWorldBounds) + { + useWorldBounds = newUseBounds; + if (!useWorldBounds) + { + Defaults(TRSType.Position); + } + } + if (SettingsScriptableObject<WorldBoundsSettings>.single == null) + { + Debug.LogWarning("Not Ready to Change the World"); + return; + } + List<WorldBoundsGroup> worldBoundsGroups = SettingsScriptableObject<WorldBoundsSettings>.single.worldBoundsGroups; + if (newBndsGrpId == boundsGroupId) + { + return; + } + if (boundsGroupId < worldBoundsGroups.Count) + { + WorldBoundsGroup worldBoundsGroup = worldBoundsGroups[boundsGroupId]; + if (worldBoundsGroup != null) + { + worldBoundsGroup.OnWorldBoundChanged = (Action)Delegate.Remove(worldBoundsGroup.OnWorldBoundChanged, new Action(CacheValues)); + } + } + if (newBndsGrpId >= worldBoundsGroups.Count) + { + boundsGroupId = 0; + } + else + { + boundsGroupId = newBndsGrpId; + } + WorldBoundsGroup worldBoundsGroup2 = worldBoundsGroups[boundsGroupId]; + if (worldBoundsGroup2 != null && useWorldBounds) + { + worldBoundsGroup2.OnWorldBoundChanged = (Action)Delegate.Combine(worldBoundsGroup2.OnWorldBoundChanged, new Action(CacheValues)); + ElementCrusher crusher = worldBoundsGroup2.crusher; + if (_xcrusher != crusher._xcrusher) + { + XCrusher = crusher.XCrusher; + } + if (_ycrusher != crusher._ycrusher) + { + YCrusher = crusher.YCrusher; + } + if (_zcrusher != crusher._zcrusher) + { + ZCrusher = crusher.ZCrusher; + } + local = crusher.local; + } + } + + private WorldBoundsGroup GetUsedWorldBounds() + { + if (_trsType == TRSType.Position && useWorldBounds) + { + if (boundsGroupId >= SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups.Count) + { + boundsGroupId = 0; + } + return SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups[boundsGroupId]; + } + return null; + } + + public override void OnBeforeSerialize() + { + } + + public override void OnAfterDeserialize() + { + } + + public void CacheValues() + { + ApplyWorldCrusherSettings(); + NullUnusedCrushers(); + if (_trsType == TRSType.Quaternion) + { + cache_qEnabled = _qcrusher != null && _qcrusher.Enabled && _qcrusher.Bits > 0; + cache_qBits = (cache_qEnabled ? _qcrusher.Bits : 0); + cache_TotalBits[0] = cache_qBits; + cache_TotalBits[1] = cache_qBits; + cache_TotalBits[2] = cache_qBits; + cache_TotalBits[3] = cache_qBits; + cache_isUniformScale = false; + } + else if (_trsType == TRSType.Scale && uniformAxes != 0) + { + cache_uEnabled = _ucrusher != null && _ucrusher.Enabled; + for (int i = 0; i < 4; i++) + { + int num = (cache_uEnabled ? _ucrusher.GetBits((BitCullingLevel)i) : 0); + cache_uBits[i] = num; + cache_TotalBits[i] = num; + } + cache_isUniformScale = true; + } + else + { + cache_mustCorrectRotationX = _trsType == TRSType.Euler && _xcrusher.UseHalfRangeX; + for (int j = 0; j < 4; j++) + { + cache_xEnabled = _xcrusher != null && _xcrusher.Enabled; + cache_yEnabled = _ycrusher != null && _ycrusher.Enabled; + cache_zEnabled = _zcrusher != null && _zcrusher.Enabled; + cache_xBits[j] = (cache_xEnabled ? _xcrusher.GetBits((BitCullingLevel)j) : 0); + cache_yBits[j] = (cache_yEnabled ? _ycrusher.GetBits((BitCullingLevel)j) : 0); + cache_zBits[j] = (cache_zEnabled ? _zcrusher.GetBits((BitCullingLevel)j) : 0); + cache_TotalBits[j] = cache_xBits[j] + cache_yBits[j] + cache_zBits[j]; + cache_isUniformScale = false; + } + } + Cached_TotalBits = Array.AsReadOnly(cache_TotalBits); + cached = true; + if (OnRecalculated != null) + { + OnRecalculated(this); + } + } + + private void NullUnusedCrushers() + { + if (_trsType == TRSType.Quaternion) + { + XCrusher = null; + YCrusher = null; + ZCrusher = null; + UCrusher = null; + } + else if (_trsType == TRSType.Scale && uniformAxes != 0) + { + XCrusher = null; + YCrusher = null; + ZCrusher = null; + QCrusher = null; + } + else + { + QCrusher = null; + UCrusher = null; + } + } + + public ElementCrusher() + { + Defaults(TRSType.Generic); + } + + internal ElementCrusher(StaticTRSType staticTrsType) + { + _trsType = (TRSType)staticTrsType; + } + + public ElementCrusher(bool enableTRSTypeSelector = true) + { + _trsType = TRSType.Generic; + Defaults(TRSType.Generic); + this.enableTRSTypeSelector = enableTRSTypeSelector; + } + + public ElementCrusher(TRSType trsType, bool enableTRSTypeSelector = true) + { + _trsType = trsType; + Defaults(trsType); + this.enableTRSTypeSelector = enableTRSTypeSelector; + } + + public void Defaults(TRSType trs) + { + switch (trs) + { + case TRSType.Euler: + case TRSType.Quaternion: + XCrusher = new FloatCrusher(BitPresets.Bits10, -90f, 90f, Axis.X, TRSType.Euler, showEnableToggle: true); + YCrusher = new FloatCrusher(BitPresets.Bits12, -180f, 180f, Axis.Y, TRSType.Euler, showEnableToggle: true); + ZCrusher = new FloatCrusher(BitPresets.Bits10, -180f, 180f, Axis.Z, TRSType.Euler, showEnableToggle: true); + QCrusher = new QuatCrusher(showEnableToggle: true, isStandalone: false); + break; + case TRSType.Scale: + XCrusher = new FloatCrusher(BitPresets.Bits12, 0f, 2f, Axis.X, TRSType.Scale, showEnableToggle: true); + YCrusher = new FloatCrusher(BitPresets.Bits10, 0f, 2f, Axis.Y, TRSType.Scale, showEnableToggle: true); + ZCrusher = new FloatCrusher(BitPresets.Bits10, 0f, 2f, Axis.Z, TRSType.Scale, showEnableToggle: true); + UCrusher = new FloatCrusher(BitPresets.Bits10, 0f, 2f, Axis.Uniform, TRSType.Scale, showEnableToggle: true); + break; + default: + XCrusher = new FloatCrusher(BitPresets.Bits12, -20f, 20f, Axis.X, trs, showEnableToggle: true); + YCrusher = new FloatCrusher(BitPresets.Bits10, -5f, 5f, Axis.Y, trs, showEnableToggle: true); + ZCrusher = new FloatCrusher(BitPresets.Bits10, -5f, 5f, Axis.Z, trs, showEnableToggle: true); + break; + } + } + + public void Write(CompressedElement nonalloc, Transform trans, byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + switch (TRSType) + { + case TRSType.Position: + Write(nonalloc, local ? trans.localPosition : trans.position, bytes, ref bitposition, bcl); + break; + case TRSType.Euler: + Write(nonalloc, local ? trans.localEulerAngles : trans.eulerAngles, bytes, ref bitposition, bcl); + break; + case TRSType.Quaternion: + Write(nonalloc, local ? trans.localRotation : trans.rotation, bytes, ref bitposition, bcl); + break; + case TRSType.Scale: + Write(nonalloc, trans.localScale, bytes, ref bitposition, bcl); + break; + default: + Write(nonalloc, local ? trans.localPosition : trans.position, bytes, ref bitposition, bcl); + break; + } + } + + [Obsolete] + public CompressedElement Write(Transform trans, byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + return TRSType switch + { + TRSType.Position => Write(local ? trans.localPosition : trans.position, bytes, ref bitposition, bcl), + TRSType.Euler => Write(local ? trans.localEulerAngles : trans.eulerAngles, bytes, ref bitposition, bcl), + TRSType.Quaternion => Write(local ? trans.localRotation : trans.rotation, bytes, ref bitposition, bcl), + TRSType.Scale => Write(trans.localScale, bytes, ref bitposition, bcl), + _ => Write(local ? trans.localPosition : trans.position, bytes, ref bitposition, bcl), + }; + } + + public void Write(CompressedElement ce, byte[] buffer, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + _qcrusher.Write(ce.cQuat, buffer, ref bitposition); + return; + } + if (cache_isUniformScale) + { + _ucrusher.Write(ce.cUniform, buffer, ref bitposition, bcl); + return; + } + if (cache_xEnabled && (ia & IncludedAxes.X) != 0) + { + _xcrusher.Write(ce.cx, buffer, ref bitposition, bcl); + } + if (cache_yEnabled && (ia & IncludedAxes.Y) != 0) + { + _ycrusher.Write(ce.cy, buffer, ref bitposition, bcl); + } + if (cache_zEnabled && (ia & IncludedAxes.Z) != 0) + { + _zcrusher.Write(ce.cz, buffer, ref bitposition, bcl); + } + } + + public void Write(CompressedElement ce, uint[] buffer, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + _qcrusher.Write(ce.cQuat, buffer, ref bitposition); + return; + } + if (cache_isUniformScale) + { + _ucrusher.Write(ce.cUniform, buffer, ref bitposition, bcl); + return; + } + if (cache_xEnabled && (ia & IncludedAxes.X) != 0) + { + _xcrusher.Write(ce.cx, buffer, ref bitposition, bcl); + } + if (cache_yEnabled && (ia & IncludedAxes.Y) != 0) + { + _ycrusher.Write(ce.cy, buffer, ref bitposition, bcl); + } + if (cache_zEnabled && (ia & IncludedAxes.Z) != 0) + { + _zcrusher.Write(ce.cz, buffer, ref bitposition, bcl); + } + } + + public void Write(CompressedElement ce, ulong[] buffer, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + _qcrusher.Write(ce.cQuat, buffer, ref bitposition); + return; + } + if (cache_isUniformScale) + { + _ucrusher.Write(ce.cUniform, buffer, ref bitposition, bcl); + return; + } + if (cache_xEnabled && (ia & IncludedAxes.X) != 0) + { + _xcrusher.Write(ce.cx, buffer, ref bitposition, bcl); + } + if (cache_yEnabled && (ia & IncludedAxes.Y) != 0) + { + _ycrusher.Write(ce.cy, buffer, ref bitposition, bcl); + } + if (cache_zEnabled && (ia & IncludedAxes.Z) != 0) + { + _zcrusher.Write(ce.cz, buffer, ref bitposition, bcl); + } + } + + public void Write(CompressedElement nonalloc, Vector3 v3, byte[] bytes, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Write(nonalloc, v3, bytes, ref bitposition); + } + + [Obsolete] + public CompressedElement Write(Vector3 v3, byte[] bytes, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + return Write(v3, bytes, ref bitposition); + } + + public void Write(CompressedElement nonalloc, Vector3 v3, byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cache_isUniformScale) + { + nonalloc.Set(this, _ucrusher.Write((uniformAxes == UniformAxes.YZ) ? v3.y : v3.x, bytes, ref bitposition, bcl).cvalue); + return; + } + if (TRSType == TRSType.Quaternion) + { + ulong cQuat = _qcrusher.Write(Quaternion.Euler(v3), bytes, ref bitposition); + nonalloc.Set(this, cQuat); + return; + } + if (cache_mustCorrectRotationX) + { + v3 = v3.GetXCorrectedEuler(); + } + nonalloc.Set(this, cache_xEnabled ? _xcrusher.Write(v3.x, bytes, ref bitposition, bcl) : default(CompressedFloat), cache_yEnabled ? _ycrusher.Write(v3.y, bytes, ref bitposition, bcl) : default(CompressedFloat), cache_zEnabled ? _zcrusher.Write(v3.z, bytes, ref bitposition, bcl) : default(CompressedFloat)); + } + + [Obsolete] + public CompressedElement Write(Vector3 v3, byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cache_isUniformScale) + { + return new CompressedElement(this, (uint)((CompressedValue)_ucrusher.Write((uniformAxes == UniformAxes.YZ) ? v3.y : v3.x, bytes, ref bitposition, bcl)).cvalue); + } + if (TRSType == TRSType.Quaternion) + { + ulong cQuat = _qcrusher.Write(Quaternion.Euler(v3), bytes, ref bitposition); + return new CompressedElement(this, cQuat); + } + if (cache_mustCorrectRotationX) + { + v3 = v3.GetXCorrectedEuler(); + } + return new CompressedElement(this, cache_xEnabled ? ((uint)_xcrusher.Write(v3.x, bytes, ref bitposition, bcl)) : 0u, cache_yEnabled ? ((uint)_ycrusher.Write(v3.y, bytes, ref bitposition, bcl)) : 0u, cache_zEnabled ? ((uint)_zcrusher.Write(v3.z, bytes, ref bitposition, bcl)) : 0u); + } + + public void Write(CompressedElement nonalloc, Quaternion quat, byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.Set(this, _qcrusher.Write(quat, bytes, ref bitposition)); + } + + [Obsolete] + public CompressedElement Write(Quaternion quat, byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + return new CompressedElement(this, _qcrusher.Write(quat, bytes, ref bitposition)); + } + + public void Write(CompressedElement nonalloc, Transform trans, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + switch (TRSType) + { + case TRSType.Position: + Write(nonalloc, local ? trans.localPosition : trans.position, buffer, ref bitposition, bcl); + break; + case TRSType.Euler: + Write(nonalloc, local ? trans.localEulerAngles : trans.eulerAngles, buffer, ref bitposition, bcl); + break; + case TRSType.Quaternion: + Write(nonalloc, local ? trans.localRotation : trans.rotation, buffer, ref bitposition, bcl); + break; + case TRSType.Scale: + Write(nonalloc, trans.localScale, buffer, ref bitposition, bcl); + break; + default: + Write(nonalloc, local ? trans.localPosition : trans.position, buffer, ref bitposition, bcl); + break; + } + } + + public void Write(CompressedElement nonalloc, Vector3 v3, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cache_isUniformScale) + { + nonalloc.Set(this, _ucrusher.Write((uniformAxes == UniformAxes.YZ) ? v3.y : v3.x, buffer, ref bitposition, bcl).cvalue); + return; + } + if (TRSType == TRSType.Quaternion) + { + ulong cQuat = _qcrusher.Write(Quaternion.Euler(v3), buffer, ref bitposition); + nonalloc.Set(this, cQuat); + return; + } + if (cache_mustCorrectRotationX) + { + v3 = v3.GetXCorrectedEuler(); + } + nonalloc.Set(this, cache_xEnabled ? _xcrusher.Write(v3.x, buffer, ref bitposition, bcl) : default(CompressedFloat), cache_yEnabled ? _ycrusher.Write(v3.y, buffer, ref bitposition, bcl) : default(CompressedFloat), cache_zEnabled ? _zcrusher.Write(v3.z, buffer, ref bitposition, bcl) : default(CompressedFloat)); + } + + public void Write(CompressedElement nonalloc, Quaternion quat, ulong[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.Set(this, _qcrusher.Write(quat, bytes, ref bitposition)); + } + + public void Read(CompressedElement nonalloc, byte[] bytes, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(nonalloc, bytes, ref bitposition, ia, bcl); + } + + public CompressedElement Read(byte[] buffer, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedElement.reusable, buffer, ref bitposition, ia, bcl); + return CompressedElement.reusable; + } + + public void Read(CompressedElement nonalloc, byte[] bytes, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + nonalloc.Set(this, bytes.Read(ref bitposition, cache_qBits)); + return; + } + if (cache_isUniformScale) + { + nonalloc.Set(this, (uint)bytes.Read(ref bitposition, cache_uBits[(int)bcl])); + return; + } + CompressedFloat cx; + if ((ia & IncludedAxes.X) != 0) + { + int bits = cache_xBits[(int)bcl]; + cx = (cache_xEnabled ? new CompressedFloat(_xcrusher, (uint)bytes.Read(ref bitposition, bits)) : default(CompressedFloat)); + } + else + { + cx = default(CompressedFloat); + } + CompressedFloat cy; + if ((ia & IncludedAxes.Y) != 0) + { + int bits2 = cache_yBits[(int)bcl]; + cy = (cache_yEnabled ? new CompressedFloat(_ycrusher, (uint)bytes.Read(ref bitposition, bits2)) : default(CompressedFloat)); + } + else + { + cy = default(CompressedFloat); + } + CompressedFloat cz; + if ((ia & IncludedAxes.Z) != 0) + { + int bits3 = cache_zBits[(int)bcl]; + cz = (cache_zEnabled ? new CompressedFloat(_zcrusher, (uint)bytes.Read(ref bitposition, bits3)) : default(CompressedFloat)); + } + else + { + cz = default(CompressedFloat); + } + nonalloc.Set(this, cx, cy, cz); + } + + public CompressedElement Read(byte[] bytes, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedElement.reusable, bytes, ref bitposition); + return CompressedElement.reusable; + } + + public void Read(CompressedElement nonalloc, ulong[] buffer, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + nonalloc.Set(this, buffer.Read(ref bitposition, cache_qBits)); + return; + } + if (cache_isUniformScale) + { + nonalloc.Set(this, (uint)buffer.Read(ref bitposition, cache_uBits[(int)bcl])); + return; + } + CompressedFloat cx; + if ((ia & IncludedAxes.X) != 0) + { + int bits = cache_xBits[(int)bcl]; + cx = (cache_xEnabled ? new CompressedFloat(_xcrusher, (uint)buffer.Read(ref bitposition, bits)) : default(CompressedFloat)); + } + else + { + cx = default(CompressedFloat); + } + CompressedFloat cy; + if ((ia & IncludedAxes.Y) != 0) + { + int bits2 = cache_yBits[(int)bcl]; + cy = (cache_yEnabled ? new CompressedFloat(_ycrusher, (uint)buffer.Read(ref bitposition, bits2)) : default(CompressedFloat)); + } + else + { + cy = default(CompressedFloat); + } + CompressedFloat cz; + if ((ia & IncludedAxes.Z) != 0) + { + int bits3 = cache_zBits[(int)bcl]; + cz = (cache_zEnabled ? new CompressedFloat(_zcrusher, (uint)buffer.Read(ref bitposition, bits3)) : default(CompressedFloat)); + } + else + { + cz = default(CompressedFloat); + } + nonalloc.Set(this, cx, cy, cz); + } + + public void Read(CompressedElement nonalloc, uint[] buffer, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + nonalloc.Set(this, buffer.Read(ref bitposition, cache_qBits)); + return; + } + if (cache_isUniformScale) + { + nonalloc.Set(this, (uint)buffer.Read(ref bitposition, cache_uBits[(int)bcl])); + return; + } + CompressedFloat cx; + if ((ia & IncludedAxes.X) != 0) + { + int bits = cache_xBits[(int)bcl]; + cx = (cache_xEnabled ? new CompressedFloat(_xcrusher, (uint)buffer.Read(ref bitposition, bits)) : default(CompressedFloat)); + } + else + { + cx = default(CompressedFloat); + } + CompressedFloat cy; + if ((ia & IncludedAxes.Y) != 0) + { + int bits2 = cache_yBits[(int)bcl]; + cy = (cache_yEnabled ? new CompressedFloat(_ycrusher, (uint)buffer.Read(ref bitposition, bits2)) : default(CompressedFloat)); + } + else + { + cy = default(CompressedFloat); + } + CompressedFloat cz; + if ((ia & IncludedAxes.Z) != 0) + { + int bits3 = cache_zBits[(int)bcl]; + cz = (cache_zEnabled ? new CompressedFloat(_zcrusher, (uint)buffer.Read(ref bitposition, bits3)) : default(CompressedFloat)); + } + else + { + cz = default(CompressedFloat); + } + nonalloc.Set(this, cx, cy, cz); + } + + public Element ReadAndDecompress(byte[] bytes, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(reusableCE, bytes, ref bitposition, ia, bcl); + return Decompress(reusableCE); + } + + public void Write(CompressedElement nonalloc, Transform trans, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + switch (TRSType) + { + case TRSType.Position: + Write(nonalloc, local ? trans.localPosition : trans.position, ref buffer, ref bitposition, bcl); + break; + case TRSType.Euler: + Write(nonalloc, local ? trans.localEulerAngles : trans.eulerAngles, ref buffer, ref bitposition, bcl); + break; + case TRSType.Quaternion: + Write(nonalloc, local ? trans.localRotation : trans.rotation, ref buffer, ref bitposition); + break; + case TRSType.Scale: + Write(nonalloc, trans.localScale, ref buffer, ref bitposition, bcl); + break; + default: + Write(nonalloc, local ? trans.localPosition : trans.position, ref buffer, ref bitposition, bcl); + break; + } + } + + public void Write(Transform trans, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + switch (TRSType) + { + case TRSType.Position: + Write(local ? trans.localPosition : trans.position, ref buffer, ref bitposition, bcl); + break; + case TRSType.Euler: + Write(local ? trans.localEulerAngles : trans.eulerAngles, ref buffer, ref bitposition, bcl); + break; + case TRSType.Quaternion: + Write(local ? trans.localRotation : trans.rotation, ref buffer, ref bitposition); + break; + case TRSType.Scale: + Write(trans.localScale, ref buffer, ref bitposition, bcl); + break; + default: + Write(local ? trans.localPosition : trans.position, ref buffer, ref bitposition, bcl); + break; + } + } + + public void Write(CompressedElement nonalloc, Vector3 v3, ref ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Write(nonalloc, v3, ref buffer, ref bitposition, bcl); + } + + public void Write(Vector3 v3, ref ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Write(v3, ref buffer, ref bitposition, bcl); + } + + public void Write(CompressedElement nonalloc, Vector3 v3, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + CompressedFloat cx = (cache_xEnabled ? _xcrusher.Write(v3.x, ref buffer, ref bitposition, bcl) : default(CompressedFloat)); + CompressedFloat cy = (cache_yEnabled ? _ycrusher.Write(v3.y, ref buffer, ref bitposition, bcl) : default(CompressedFloat)); + CompressedFloat cz = (cache_zEnabled ? _zcrusher.Write(v3.z, ref buffer, ref bitposition, bcl) : default(CompressedFloat)); + nonalloc.Set(this, cx, cy, cz); + } + + public void Write(Vector3 v3, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cache_xEnabled) + { + _xcrusher.Write(v3.x, ref buffer, ref bitposition, bcl); + } + if (cache_yEnabled) + { + _ycrusher.Write(v3.y, ref buffer, ref bitposition, bcl); + } + if (cache_zEnabled) + { + _zcrusher.Write(v3.z, ref buffer, ref bitposition, bcl); + } + } + + public void Write(CompressedElement nonalloc, Quaternion quat, ref ulong buffer) + { + int bitposition = 0; + Write(nonalloc, quat, ref buffer, ref bitposition); + } + + public void Write(Quaternion quat, ref ulong buffer) + { + int bitposition = 0; + Write(quat, ref buffer, ref bitposition); + } + + public void Write(CompressedElement nonalloc, Quaternion quat, ref ulong buffer, ref int bitposition) + { + if (!cached) + { + CacheValues(); + } + ulong cQuat = (cache_qEnabled ? _qcrusher.Write(quat, ref buffer, ref bitposition) : 0); + nonalloc.Set(this, cQuat); + } + + public void Write(Quaternion quat, ref ulong buffer, ref int bitposition) + { + if (!cached) + { + CacheValues(); + } + if (cache_qEnabled) + { + _qcrusher.Write(quat, ref buffer, ref bitposition); + } + } + + public CompressedElement Write(CompressedElement ce, ref ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + return Write(ce, ref buffer, ref bitposition, bcl); + } + + public CompressedElement Write(CompressedElement ce, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cache_qEnabled) + { + ce.cQuat.cvalue.Inject(ref buffer, ref bitposition, cache_qBits); + } + else if (cache_uEnabled) + { + ce.cUniform.cvalue.Inject(ref buffer, ref bitposition, cache_uBits[(int)bcl]); + } + else + { + if (cache_xEnabled) + { + ce.cx.cvalue.Inject(ref buffer, ref bitposition, cache_xBits[(int)bcl]); + } + if (cache_yEnabled) + { + ce.cy.cvalue.Inject(ref buffer, ref bitposition, cache_yBits[(int)bcl]); + } + if (cache_zEnabled) + { + ce.cz.cvalue.Inject(ref buffer, ref bitposition, cache_zBits[(int)bcl]); + } + } + return ce; + } + + public Element Read(ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + int bitposition = 0; + if (TRSType == TRSType.Quaternion) + { + ulong compressed = buffer.Read(ref bitposition, cache_qBits); + return _qcrusher.Decompress(compressed); + } + if (cache_isUniformScale) + { + float num = _ucrusher.ReadAndDecompress(buffer, ref bitposition, bcl); + return new Vector3(num, num, num); + } + return new Vector3(cache_xEnabled ? _xcrusher.ReadAndDecompress(buffer, ref bitposition, bcl) : 0f, cache_yEnabled ? _ycrusher.ReadAndDecompress(buffer, ref bitposition, bcl) : 0f, cache_zEnabled ? _zcrusher.ReadAndDecompress(buffer, ref bitposition, bcl) : 0f); + } + + public Element Read(ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + ulong compressed = buffer.Read(ref bitposition, cache_qBits); + return _qcrusher.Decompress(compressed); + } + if (cache_isUniformScale) + { + float num = _ucrusher.ReadAndDecompress(buffer, ref bitposition, bcl); + return new Vector3(num, num, num); + } + return new Vector3(cache_xEnabled ? _xcrusher.ReadAndDecompress(buffer, ref bitposition, bcl) : 0f, cache_yEnabled ? _ycrusher.ReadAndDecompress(buffer, ref bitposition, bcl) : 0f, cache_zEnabled ? _zcrusher.ReadAndDecompress(buffer, ref bitposition, bcl) : 0f); + } + + public void Read(CompressedElement nonalloc, ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(nonalloc, buffer, ref bitposition, bcl); + } + + public void Read(CompressedElement nonalloc, ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + nonalloc.Set(this, buffer.Read(ref bitposition, cache_qBits)); + return; + } + if (cache_isUniformScale) + { + nonalloc.Set(this, (uint)buffer.Read(ref bitposition, cache_uBits[(int)bcl])); + return; + } + CompressedFloat cx = (cache_xEnabled ? new CompressedFloat(_xcrusher, buffer.Read(ref bitposition, cache_xBits[(int)bcl])) : default(CompressedFloat)); + CompressedFloat cy = (cache_yEnabled ? new CompressedFloat(_ycrusher, buffer.Read(ref bitposition, cache_yBits[(int)bcl])) : default(CompressedFloat)); + CompressedFloat cz = (cache_zEnabled ? new CompressedFloat(_zcrusher, buffer.Read(ref bitposition, cache_zBits[(int)bcl])) : default(CompressedFloat)); + nonalloc.Set(this, cx, cy, cz); + } + + public void Read(CompressedElement nonalloc, ulong frag0, ulong frag1 = 0uL, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + int bitposition = 0; + reusableArray64.Write(frag0, ref bitposition, 64); + reusableArray64.Write(frag1, ref bitposition, 64); + bitposition = 0; + Read(nonalloc, reusableArray64, ref bitposition, IncludedAxes.XYZ, bcl); + } + + public CompressedElement Read(ulong frag0, ulong frag1 = 0uL, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedElement.reusable, frag0, frag1, bcl); + return CompressedElement.reusable; + } + + public void Compress(CompressedElement nonalloc, Transform trans) + { + switch (TRSType) + { + case TRSType.Position: + Compress(nonalloc, local ? trans.localPosition : trans.position); + break; + case TRSType.Euler: + Compress(nonalloc, local ? trans.localEulerAngles : trans.eulerAngles); + break; + case TRSType.Quaternion: + Compress(nonalloc, local ? trans.localRotation : trans.rotation); + break; + case TRSType.Scale: + Compress(nonalloc, local ? trans.localScale : trans.lossyScale); + break; + default: + Compress(nonalloc, local ? trans.localPosition : trans.position); + break; + } + } + + public CompressedElement Compress(Transform trans) + { + Compress(CompressedElement.reusable, trans); + return CompressedElement.reusable; + } + + public void CompressAndWrite(Transform trans, byte[] buffer, ref int bitposition) + { + switch (TRSType) + { + case TRSType.Position: + CompressAndWrite(local ? trans.localPosition : trans.position, buffer, ref bitposition); + break; + case TRSType.Euler: + CompressAndWrite(local ? trans.localEulerAngles : trans.eulerAngles, buffer, ref bitposition); + break; + case TRSType.Quaternion: + CompressAndWrite(local ? trans.localRotation : trans.rotation, buffer, ref bitposition); + break; + case TRSType.Scale: + CompressAndWrite(local ? trans.localScale : trans.lossyScale, buffer, ref bitposition); + break; + default: + CompressAndWrite(local ? trans.localPosition : trans.position, buffer, ref bitposition); + break; + } + } + + public void Compress(CompressedElement nonalloc, Element e) + { + if (TRSType == TRSType.Quaternion) + { + Compress(nonalloc, e.quat); + } + else + { + Compress(nonalloc, e.v); + } + } + + public CompressedElement Compress(Element e) + { + if (TRSType == TRSType.Quaternion) + { + Compress(CompressedElement.reusable, e.quat); + } + else + { + Compress(CompressedElement.reusable, e.v); + } + return CompressedElement.reusable; + } + + public void CompressAndWrite(Element e, byte[] buffer, ref int bitposition) + { + if (TRSType == TRSType.Quaternion) + { + CompressAndWrite(e.quat, buffer, ref bitposition); + } + else + { + CompressAndWrite(e.v, buffer, ref bitposition); + } + } + + public void Compress(CompressedElement nonalloc, Rigidbody rb, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + switch (_trsType) + { + case TRSType.Scale: + Compress(nonalloc, local ? rb.transform.localScale : rb.transform.lossyScale, ia); + break; + case TRSType.Quaternion: + if (cache_qEnabled) + { + Quaternion quat; + if (local) + { + Transform parent3 = rb.transform.parent; + quat = (parent3 ? (Quaternion.Inverse(parent3.rotation) * rb.rotation) : rb.rotation); + } + else + { + quat = rb.rotation; + } + nonalloc.Set(this, _qcrusher.Compress(quat)); + } + break; + case TRSType.Euler: + { + Vector3 vector2; + if (local) + { + Transform parent2 = rb.transform.parent; + vector2 = (parent2 ? (Quaternion.Inverse(parent2.rotation) * rb.rotation).eulerAngles : rb.rotation.eulerAngles); + } + else + { + vector2 = rb.rotation.eulerAngles; + } + CompressedFloat cx2 = ((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? _xcrusher.Compress(vector2.x) : default(CompressedFloat)); + CompressedFloat cy2 = ((cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? _ycrusher.Compress(vector2.y) : default(CompressedFloat)); + CompressedFloat cz2 = ((cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? _zcrusher.Compress(vector2.z) : default(CompressedFloat)); + nonalloc.Set(this, cx2, cy2, cz2); + break; + } + case TRSType.Position: + { + Vector3 vector; + if (local) + { + Transform parent = rb.transform.parent; + vector = (parent ? parent.InverseTransformPoint(rb.position) : rb.position); + } + else + { + vector = rb.position; + } + CompressedFloat cx = ((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? _xcrusher.Compress(vector.x) : default(CompressedFloat)); + CompressedFloat cy = ((cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? _ycrusher.Compress(vector.y) : default(CompressedFloat)); + CompressedFloat cz = ((cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? _zcrusher.Compress(vector.z) : default(CompressedFloat)); + nonalloc.Set(this, cx, cy, cz); + break; + } + default: + nonalloc.Clear(); + break; + } + } + + public void Compress(CompressedElement nonalloc, Vector3 v, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + if (_trsType == TRSType.Quaternion) + { + Debug.LogError("We shouldn't be seeing this. Quats should not be getting compressed from Eulers!"); + if (cache_qEnabled) + { + nonalloc.Set(this, _qcrusher.Compress(Quaternion.Euler(v))); + } + } + else if (_trsType == TRSType.Scale && uniformAxes != 0) + { + if (cache_uEnabled) + { + nonalloc.Set(this, _ucrusher.Compress((uniformAxes == UniformAxes.YZ) ? v.y : v.x)); + } + } + else + { + CompressedFloat cx = ((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? _xcrusher.Compress(v.x) : default(CompressedFloat)); + CompressedFloat cy = ((cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? _ycrusher.Compress(v.y) : default(CompressedFloat)); + CompressedFloat cz = ((cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? _zcrusher.Compress(v.z) : default(CompressedFloat)); + nonalloc.Set(this, cx, cy, cz); + } + } + + public CompressedElement Compress(Vector3 v) + { + Compress(CompressedElement.reusable, v); + return CompressedElement.reusable; + } + + public void CompressAndWrite(Vector3 v, byte[] buffer, ref int bitposition, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + if (_trsType == TRSType.Scale && uniformAxes != 0) + { + ulong value = (cache_uEnabled ? ((ulong)_ucrusher.Compress((uniformAxes == UniformAxes.YZ) ? v.y : v.x)) : 0); + buffer.Write(value, ref bitposition, cache_uBits[0]); + return; + } + if (_trsType == TRSType.Quaternion) + { + Debug.Log("We shouldn't be seeing this. Quats should not be getting compressed from Eulers!"); + if (cache_qEnabled) + { + buffer.Write(_qcrusher.Compress(Quaternion.Euler(v)), ref bitposition, cache_qBits); + } + return; + } + if (cache_xEnabled) + { + buffer.Write(_xcrusher.Compress(v.x).cvalue, ref bitposition, cache_xBits[0]); + } + if (cache_yEnabled) + { + buffer.Write(_ycrusher.Compress(v.y).cvalue, ref bitposition, cache_yBits[0]); + } + if (cache_zEnabled) + { + buffer.Write(_zcrusher.Compress(v.z).cvalue, ref bitposition, cache_zBits[0]); + } + } + + public void Compress(CompressedElement nonalloc, Quaternion quat) + { + if (!cached) + { + CacheValues(); + } + if (cache_qEnabled) + { + nonalloc.Set(this, _qcrusher.Compress(quat)); + } + } + + public CompressedElement Compress(Quaternion quat) + { + Compress(CompressedElement.reusable, quat); + return CompressedElement.reusable; + } + + public void CompressAndWrite(Quaternion quat, byte[] buffer, ref int bitposition) + { + if (!cached) + { + CacheValues(); + } + if (cache_qEnabled) + { + buffer.Write(_qcrusher.Compress(quat), ref bitposition, cache_qBits); + } + } + + public Element Decompress(CompressedElement compressed) + { + if (!cached) + { + CacheValues(); + } + if (_trsType == TRSType.Scale && uniformAxes != 0) + { + float num = _ucrusher.Decompress(compressed.cUniform); + return new Vector3(num, num, num); + } + if (_trsType == TRSType.Quaternion) + { + return _qcrusher.Decompress(compressed.cQuat); + } + return new Vector3(cache_xEnabled ? _xcrusher.Decompress(compressed.cx) : 0f, cache_yEnabled ? _ycrusher.Decompress(compressed.cy) : 0f, cache_zEnabled ? _zcrusher.Decompress(compressed.cz) : 0f); + } + + public Element Decompress(ulong cval, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + if (_trsType == TRSType.Scale && uniformAxes != 0) + { + float num = _ucrusher.Decompress((uint)cval); + return new Vector3(num, num, num); + } + if (_trsType == TRSType.Quaternion) + { + return _qcrusher.Decompress(cval); + } + int bitposition = 0; + return new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? _xcrusher.ReadAndDecompress(cval, ref bitposition) : 0f, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? _ycrusher.ReadAndDecompress(cval, ref bitposition) : 0f, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? _zcrusher.ReadAndDecompress(cval, ref bitposition) : 0f); + } + + [Obsolete("Apply for Rigidbody has been replaced with Move and Set, to indicate usage of MovePosition/Rotation vs rb.position/rotation.")] + public void Apply(Rigidbody rb, CompressedElement ce, IncludedAxes ia = IncludedAxes.XYZ) + { + Apply(rb, Decompress(ce), ia); + } + + [Obsolete("Apply for Rigidbody has been replaced with Move and Set, to indicate usage of MovePosition/Rotation vs rb.position/rotation.")] + public void Apply(Rigidbody rb, Element e, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + switch (_trsType) + { + case TRSType.Quaternion: + if (cache_qEnabled) + { + if (local && (bool)rb.transform.parent) + { + rb.transform.localRotation = e.quat; + } + else + { + rb.MoveRotation(e.quat); + } + } + break; + case TRSType.Position: + { + Vector3 vector = ((local & (bool)rb.transform.parent) ? rb.transform.TransformPoint(e.v) : e.v); + Vector3 position = rb.position; + rb.MovePosition(new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? vector.x : position.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? vector.y : position.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? vector.z : position.z)); + break; + } + case TRSType.Euler: + { + Vector3 eulerAngles = rb.rotation.eulerAngles; + if (local && (bool)rb.transform.parent) + { + rb.transform.eulerAngles = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : eulerAngles.z); + } + else + { + rb.MoveRotation(Quaternion.Euler((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : eulerAngles.z)); + } + break; + } + default: + Debug.LogError("Are you trying to Apply scale to a Rigidbody?"); + break; + } + } + + public void Move(Rigidbody rb, CompressedElement ce, IncludedAxes ia = IncludedAxes.XYZ) + { + Move(rb, Decompress(ce), ia); + } + + public void Move(Rigidbody rb, Element e, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + switch (_trsType) + { + case TRSType.Quaternion: + if (cache_qEnabled) + { + if (local && (bool)rb.transform.parent) + { + rb.MoveRotation(rb.transform.parent.rotation * e.quat); + } + else + { + rb.MoveRotation(e.quat); + } + } + break; + case TRSType.Position: + { + Vector3 vector = ((local & (bool)rb.transform.parent) ? rb.transform.TransformPoint(e.v) : e.v); + rb.MovePosition(new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? vector.x : rb.position.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? vector.y : rb.position.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? vector.z : rb.position.z)); + break; + } + case TRSType.Euler: + { + Vector3 eulerAngles = rb.rotation.eulerAngles; + if (local && (bool)rb.transform.parent) + { + rb.transform.eulerAngles = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : eulerAngles.z); + } + else + { + rb.MoveRotation(Quaternion.Euler((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : eulerAngles.z)); + } + break; + } + default: + Debug.LogError("Are you trying to Apply scale to a Rigidbody?"); + break; + } + } + + public void Set(Rigidbody rb, CompressedElement ce, IncludedAxes ia = IncludedAxes.XYZ) + { + Set(rb, Decompress(ce), ia); + } + + public void Set(Rigidbody2D rb, CompressedElement ce, IncludedAxes ia = IncludedAxes.XYZ) + { + Set(rb, Decompress(ce), ia); + } + + public void Set(Rigidbody rb, Element e, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + switch (_trsType) + { + case TRSType.Quaternion: + if (cache_qEnabled) + { + if (local && (bool)rb.transform.parent) + { + rb.rotation = rb.transform.parent.rotation * e.quat; + } + else + { + rb.rotation = e.quat; + } + } + break; + case TRSType.Position: + { + Vector3 vector = ((local & (bool)rb.transform.parent) ? rb.transform.TransformPoint(e.v) : e.v); + Vector3 position = rb.position; + rb.position = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? vector.x : position.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? vector.y : position.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? vector.z : position.z); + break; + } + case TRSType.Euler: + { + Vector3 eulerAngles = rb.rotation.eulerAngles; + if (local && (bool)rb.transform.parent) + { + rb.transform.eulerAngles = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : eulerAngles.z); + } + else + { + rb.rotation = Quaternion.Euler((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : eulerAngles.z); + } + break; + } + default: + Debug.LogError("Are you trying to Apply scale to a Rigidbody?"); + break; + } + } + + public void Set(Rigidbody2D rb2d, Element e, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + switch (_trsType) + { + case TRSType.Quaternion: + if (cache_qEnabled) + { + if (local && (bool)rb2d.transform.parent) + { + rb2d.transform.localRotation = e.quat; + } + else + { + rb2d.rotation = e.quat.z; + } + } + break; + case TRSType.Position: + { + Vector3 vector = ((local & (bool)rb2d.transform.parent) ? rb2d.transform.TransformPoint(e.v) : e.v); + rb2d.position = new Vector2((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? vector.x : rb2d.position.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? vector.y : rb2d.position.y); + break; + } + case TRSType.Euler: + if (local && (bool)rb2d.transform.parent) + { + rb2d.transform.localEulerAngles = new Vector3(0f, 0f, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : rb2d.rotation); + } + else + { + rb2d.rotation = ((cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : rb2d.rotation); + } + break; + default: + Debug.LogError("Are you trying to Apply scale to a Rigidbody?"); + break; + } + } + + public void Apply(Transform trans, CompressedElement ce, IncludedAxes ia = IncludedAxes.XYZ) + { + Apply(trans, Decompress(ce), ia); + } + + public void Apply(Transform trans, Element e, IncludedAxes ia = IncludedAxes.XYZ) + { + if (!cached) + { + CacheValues(); + } + switch (_trsType) + { + case TRSType.Quaternion: + if (cache_qEnabled) + { + if (local) + { + trans.localRotation = e.quat; + } + else + { + trans.rotation = e.quat; + } + } + return; + case TRSType.Position: + if (local) + { + trans.localPosition = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : trans.localPosition.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : trans.localPosition.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : trans.localPosition.z); + } + else + { + trans.position = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : trans.position.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : trans.position.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : trans.position.z); + } + return; + case TRSType.Euler: + if (local) + { + trans.localEulerAngles = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : trans.localEulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : trans.localEulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : trans.localEulerAngles.z); + } + else + { + trans.eulerAngles = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : trans.eulerAngles.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : trans.eulerAngles.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : trans.eulerAngles.z); + } + return; + } + if (local) + { + if (uniformAxes == UniformAxes.NonUniform) + { + trans.localScale = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : trans.localScale.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : trans.localScale.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : trans.localScale.z); + return; + } + float num = (((uniformAxes & (UniformAxes)1) != 0) ? e.v.x : e.v.y); + trans.localScale = new Vector3(((uniformAxes & (UniformAxes)1) != 0) ? num : trans.localScale.x, ((uniformAxes & (UniformAxes)2) != 0) ? num : trans.localScale.y, ((uniformAxes & (UniformAxes)4) != 0) ? num : trans.localScale.z); + } + else if (uniformAxes == UniformAxes.NonUniform) + { + trans.localScale = new Vector3((cache_xEnabled && (ia & IncludedAxes.X) != 0) ? e.v.x : trans.lossyScale.x, (cache_yEnabled && (ia & IncludedAxes.Y) != 0) ? e.v.y : trans.lossyScale.y, (cache_zEnabled && (ia & IncludedAxes.Z) != 0) ? e.v.z : trans.lossyScale.z); + } + else + { + float num2 = (((uniformAxes & (UniformAxes)1) != 0) ? e.v.x : e.v.y); + trans.localScale = new Vector3(((uniformAxes & (UniformAxes)1) != 0) ? num2 : trans.lossyScale.x, ((uniformAxes & (UniformAxes)2) != 0) ? num2 : trans.lossyScale.y, ((uniformAxes & (UniformAxes)4) != 0) ? num2 : trans.lossyScale.z); + } + } + + public Vector3 Clamp(Vector3 v3) + { + if (!cached) + { + CacheValues(); + } + if (TRSType == TRSType.Quaternion) + { + return v3; + } + if (TRSType == TRSType.Scale) + { + if (uniformAxes == UniformAxes.NonUniform) + { + return new Vector3(cache_xEnabled ? _xcrusher.Clamp(v3.x) : 0f, cache_yEnabled ? _ycrusher.Clamp(v3.y) : 0f, cache_zEnabled ? _zcrusher.Clamp(v3.z) : 0f); + } + return new Vector3(((uniformAxes & (UniformAxes)1) != 0) ? _ucrusher.Clamp(v3.x) : 0f, ((uniformAxes & (UniformAxes)2) != 0) ? _ucrusher.Clamp(v3.x) : 0f, ((uniformAxes & (UniformAxes)4) != 0) ? _ucrusher.Clamp(v3.x) : 0f); + } + if (TRSType == TRSType.Euler) + { + return new Vector3(cache_xEnabled ? _xcrusher.ClampRotation(v3.x) : 0f, cache_yEnabled ? _ycrusher.ClampRotation(v3.y) : 0f, cache_zEnabled ? _zcrusher.ClampRotation(v3.z) : 0f); + } + return new Vector3(cache_xEnabled ? _xcrusher.Clamp(v3.x) : 0f, cache_yEnabled ? _ycrusher.Clamp(v3.y) : 0f, cache_zEnabled ? _zcrusher.Clamp(v3.z) : 0f); + } + + public BitCullingLevel FindBestBitCullLevel(CompressedElement a, CompressedElement b, BitCullingLevel maxCulling) + { + if (TRSType == TRSType.Quaternion) + { + if ((ulong)a.cQuat == (ulong)b.cQuat) + { + return BitCullingLevel.DropAll; + } + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.NoCulling || !TestMatchingUpper(a, b, BitCullingLevel.DropThird)) + { + return BitCullingLevel.NoCulling; + } + if (maxCulling == BitCullingLevel.DropThird || !TestMatchingUpper(a, b, BitCullingLevel.DropHalf)) + { + return BitCullingLevel.DropThird; + } + if (maxCulling == BitCullingLevel.DropHalf || !TestMatchingUpper(a, b, BitCullingLevel.DropAll)) + { + return BitCullingLevel.DropHalf; + } + return BitCullingLevel.DropAll; + } + + private bool TestMatchingUpper(uint a, uint b, int lowerbits) + { + return a >> lowerbits << lowerbits == b >> lowerbits << lowerbits; + } + + public bool TestMatchingUpper(CompressedElement a, CompressedElement b, BitCullingLevel bcl) + { + if (TestMatchingUpper(a.cx, b.cx, _xcrusher.GetBits(bcl)) && TestMatchingUpper(a.cy, b.cy, _ycrusher.GetBits(bcl))) + { + return TestMatchingUpper(a.cz, b.cz, _zcrusher.GetBits(bcl)); + } + return false; + } + + public int TallyBits(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (_trsType == TRSType.Scale && uniformAxes != 0) + { + if (_ucrusher == null || !_ucrusher.Enabled) + { + return 0; + } + return _ucrusher.GetBits(bcl); + } + if (_trsType == TRSType.Quaternion) + { + if (!(_qcrusher != null) || !_qcrusher.Enabled) + { + return 0; + } + return _qcrusher.Bits; + } + if (_trsType == TRSType.Position && useWorldBounds) + { + return WorldBoundsSettings.TallyBits(ref boundsGroupId); + } + return ((_xcrusher != null && _xcrusher.Enabled) ? _xcrusher.GetBits(bcl) : 0) + ((_ycrusher != null && _ycrusher.Enabled) ? _ycrusher.GetBits(bcl) : 0) + ((_zcrusher != null && _zcrusher.Enabled) ? _zcrusher.GetBits(bcl) : 0); + } + + public void CopyFrom(ElementCrusher src) + { + _trsType = src._trsType; + uniformAxes = src.uniformAxes; + if (_xcrusher != null && src._xcrusher != null) + { + _xcrusher.CopyFrom(src._xcrusher); + } + if (_ycrusher != null && src._ycrusher != null) + { + _ycrusher.CopyFrom(src._ycrusher); + } + if (_zcrusher != null && src._zcrusher != null) + { + _zcrusher.CopyFrom(src._zcrusher); + } + if (_ucrusher != null && src._ucrusher != null) + { + _ucrusher.CopyFrom(src._ucrusher); + } + if (_qcrusher != null && src._qcrusher != null) + { + _qcrusher.CopyFrom(src._qcrusher); + } + local = src.local; + } + + public override string ToString() + { + return string.Concat("ElementCrusher [", _trsType, "] "); + } + + public override bool Equals(object obj) + { + return Equals(obj as ElementCrusher); + } + + public bool Equals(ElementCrusher other) + { + if (other != null && _trsType == other._trsType && EqualityComparer<Transform>.Default.Equals(defaultTransform, other.defaultTransform) && uniformAxes == other.uniformAxes && ((_xcrusher == null) ? (other._xcrusher == null) : _xcrusher.Equals(other._xcrusher)) && ((_ycrusher == null) ? (other._ycrusher == null) : _ycrusher.Equals(other._ycrusher)) && ((_zcrusher == null) ? (other._zcrusher == null) : _zcrusher.Equals(other._zcrusher)) && ((_ucrusher == null) ? (other._ucrusher == null) : _ucrusher.Equals(other._ucrusher)) && ((_qcrusher == null) ? (other._qcrusher == null) : _qcrusher.Equals(other._qcrusher))) + { + return local == other.local; + } + return false; + } + + public override int GetHashCode() + { + //return (((((((-1042106911 * -1521134295 + _trsType.GetHashCode()) * -1521134295 + uniformAxes.GetHashCode()) * -1521134295 + ((_xcrusher != null) ? _xcrusher.GetHashCode() : 0)) * -1521134295 + ((_ycrusher != null) ? _ycrusher.GetHashCode() : 0)) * -1521134295 + ((_zcrusher != null) ? _zcrusher.GetHashCode() : 0)) * -1521134295 + ((_ucrusher != null) ? _ucrusher.GetHashCode() : 0)) * -1521134295 + ((!(_qcrusher == null)) ? _qcrusher.GetHashCode() : 0)) * -1521134295 + local.GetHashCode(); + return (((((((/*-1042106911 * -1521134295 + */_trsType.GetHashCode()) * -1521134295 + uniformAxes.GetHashCode()) * -1521134295 + ((_xcrusher != null) ? _xcrusher.GetHashCode() : 0)) * -1521134295 + ((_ycrusher != null) ? _ycrusher.GetHashCode() : 0)) * -1521134295 + ((_zcrusher != null) ? _zcrusher.GetHashCode() : 0)) * -1521134295 + ((_ucrusher != null) ? _ucrusher.GetHashCode() : 0)) * -1521134295 + ((!(_qcrusher == null)) ? _qcrusher.GetHashCode() : 0)) * -1521134295 + local.GetHashCode(); + } + + public static bool operator ==(ElementCrusher crusher1, ElementCrusher crusher2) + { + return EqualityComparer<ElementCrusher>.Default.Equals(crusher1, crusher2); + } + + public static bool operator !=(ElementCrusher crusher1, ElementCrusher crusher2) + { + return !(crusher1 == crusher2); + } +} diff --git a/ROUNDS/Photon.Compression/FactorBoundsOn.cs b/ROUNDS/Photon.Compression/FactorBoundsOn.cs new file mode 100644 index 0000000..dd87d84 --- /dev/null +++ b/ROUNDS/Photon.Compression/FactorBoundsOn.cs @@ -0,0 +1,7 @@ +namespace Photon.Compression; + +public enum FactorBoundsOn +{ + EnableDisable, + AwakeDestroy +} diff --git a/ROUNDS/Photon.Compression/FloatCrusherExtensions.cs b/ROUNDS/Photon.Compression/FloatCrusherExtensions.cs new file mode 100644 index 0000000..f4b6908 --- /dev/null +++ b/ROUNDS/Photon.Compression/FloatCrusherExtensions.cs @@ -0,0 +1,171 @@ +using System; +using emotitron.Compression; + +namespace Photon.Compression; + +public static class FloatCrusherExtensions +{ + public static CompressedFloat Write(this FloatCrusher fc, float f, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + CompressedFloat result = fc.Compress(f); + result.cvalue.Inject(ref buffer, ref bitposition, bits); + return result; + } + + public static CompressedFloat Write(this FloatCrusher fc, float f, ref uint buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + CompressedFloat result = fc.Compress(f); + result.cvalue.Inject(ref buffer, ref bitposition, bits); + return result; + } + + public static CompressedFloat Write(this FloatCrusher fc, float f, ref ushort buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + CompressedFloat result = fc.Compress(f); + result.cvalue.Inject(ref buffer, ref bitposition, bits); + return result; + } + + public static CompressedFloat Write(this FloatCrusher fc, float f, ref byte buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + CompressedFloat result = fc.Compress(f); + result.cvalue.Inject(ref buffer, ref bitposition, bits); + return result; + } + + public static CompressedFloat Write(this FloatCrusher fc, CompressedFloat c, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + c.cvalue.Inject(ref buffer, ref bitposition, fc._bits[(int)bcl]); + return c; + } + + public static float ReadAndDecompress(this FloatCrusher fc, ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + uint c = (uint)buffer.Read(ref bitposition, bits); + return fc.Decompress(c); + } + + public static CompressedFloat Read(this FloatCrusher fc, ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + uint cvalue = (uint)buffer.Read(ref bitposition, bits); + return new CompressedFloat(fc, cvalue); + } + + [Obsolete("No reason for buffer to be a ref")] + public static CompressedFloat Read(this FloatCrusher fc, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int num = fc._bits[(int)bcl]; + uint num2 = fc.masks[(int)bcl]; + uint cvalue = (uint)((buffer >> bitposition) & num2); + bitposition += num; + return new CompressedFloat(fc, cvalue); + } + + public static CompressedFloat Write(this FloatCrusher fc, CompressedFloat c, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + buffer.Write(c.cvalue, ref bitposition, bits); + return c; + } + + public static CompressedFloat Write(this FloatCrusher fc, CompressedFloat c, uint[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + buffer.Write(c.cvalue, ref bitposition, bits); + return c; + } + + public static CompressedFloat Write(this FloatCrusher fc, CompressedFloat c, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + buffer.Write(c.cvalue, ref bitposition, bits); + return c; + } + + public static CompressedFloat Write(this FloatCrusher fc, uint c, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + buffer.Write(c, ref bitposition, bits); + return new CompressedFloat(fc, c); + } + + public static CompressedFloat Write(this FloatCrusher fc, uint c, uint[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + buffer.Write(c, ref bitposition, bits); + return new CompressedFloat(fc, c); + } + + public static CompressedFloat Write(this FloatCrusher fc, uint c, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + buffer.Write(c, ref bitposition, bits); + return new CompressedFloat(fc, c); + } + + public static CompressedFloat Write(this FloatCrusher fc, float f, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + uint num = fc.Compress(f); + int bits = fc._bits[(int)bcl]; + buffer.Write(num, ref bitposition, bits); + return new CompressedFloat(fc, num); + } + + public static CompressedFloat Write(this FloatCrusher fc, float f, uint[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + uint num = fc.Compress(f); + buffer.Write(num, ref bitposition, bits); + return new CompressedFloat(fc, num); + } + + public static CompressedFloat Write(this FloatCrusher fc, float f, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + uint num = fc.Compress(f); + buffer.Write(num, ref bitposition, bits); + return new CompressedFloat(fc, num); + } + + public static CompressedFloat Read(this FloatCrusher fc, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + return new CompressedFloat(fc, buffer.ReadUInt32(ref bitposition, bits)); + } + + public static CompressedFloat Read(this FloatCrusher fc, uint[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + return new CompressedFloat(fc, buffer.ReadUInt32(ref bitposition, bits)); + } + + public static CompressedFloat Read(this FloatCrusher fc, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bits = fc._bits[(int)bcl]; + return new CompressedFloat(fc, buffer.ReadUInt32(ref bitposition, bits)); + } + + public static float ReadAndDecompress(this FloatCrusher fc, byte[] buffer, ref int bitposition) + { + uint c = buffer.ReadUInt32(ref bitposition, fc._bits[0]); + return fc.Decompress(c); + } + + public static float ReadAndDecompress(this FloatCrusher fc, uint[] buffer, ref int bitposition) + { + uint c = buffer.ReadUInt32(ref bitposition, fc._bits[0]); + return fc.Decompress(c); + } + + public static float ReadAndDecompress(this FloatCrusher fc, ulong[] buffer, ref int bitposition) + { + uint c = buffer.ReadUInt32(ref bitposition, fc._bits[0]); + return fc.Decompress(c); + } +} diff --git a/ROUNDS/Photon.Compression/IHasTransformCrusher.cs b/ROUNDS/Photon.Compression/IHasTransformCrusher.cs new file mode 100644 index 0000000..02834fb --- /dev/null +++ b/ROUNDS/Photon.Compression/IHasTransformCrusher.cs @@ -0,0 +1,6 @@ +namespace Photon.Compression; + +public interface IHasTransformCrusher +{ + TransformCrusher TC { get; } +} diff --git a/ROUNDS/Photon.Compression/IOnElementCrusherChange.cs b/ROUNDS/Photon.Compression/IOnElementCrusherChange.cs new file mode 100644 index 0000000..3290e71 --- /dev/null +++ b/ROUNDS/Photon.Compression/IOnElementCrusherChange.cs @@ -0,0 +1,6 @@ +namespace Photon.Compression; + +public interface IOnElementCrusherChange +{ + void OnCrusherChange(ElementCrusher ec); +} diff --git a/ROUNDS/Photon.Compression/IPackObj.cs b/ROUNDS/Photon.Compression/IPackObj.cs new file mode 100644 index 0000000..845f2f6 --- /dev/null +++ b/ROUNDS/Photon.Compression/IPackObj.cs @@ -0,0 +1,5 @@ +namespace Photon.Compression; + +public interface IPackObj +{ +} diff --git a/ROUNDS/Photon.Compression/IPackObjOnReadyChange.cs b/ROUNDS/Photon.Compression/IPackObjOnReadyChange.cs new file mode 100644 index 0000000..268e56b --- /dev/null +++ b/ROUNDS/Photon.Compression/IPackObjOnReadyChange.cs @@ -0,0 +1,8 @@ +using Photon.Utilities; + +namespace Photon.Compression; + +public interface IPackObjOnReadyChange +{ + void OnPackObjReadyChange(FastBitMask128 readyMask, bool AllAreReady); +} diff --git a/ROUNDS/Photon.Compression/IncludeAxisExtensions.cs b/ROUNDS/Photon.Compression/IncludeAxisExtensions.cs new file mode 100644 index 0000000..9648a98 --- /dev/null +++ b/ROUNDS/Photon.Compression/IncludeAxisExtensions.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace Photon.Compression; + +public static class IncludeAxisExtensions +{ + public static float SqrMagnitude(this Vector3 v, IncludedAxes ia) + { + return (((ia & IncludedAxes.X) != 0) ? (v.x * v.x) : 0f) + (((ia & IncludedAxes.Y) != 0) ? (v.y * v.y) : 0f) + (((ia & IncludedAxes.Z) != 0) ? (v.z * v.z) : 0f); + } + + public static float Magnitude(this Vector3 v, IncludedAxes ia) + { + return Mathf.Sqrt((((ia & IncludedAxes.X) != 0) ? (v.x * v.x) : 0f) + (((ia & IncludedAxes.Y) != 0) ? (v.y * v.y) : 0f) + (((ia & IncludedAxes.Z) != 0) ? (v.z * v.z) : 0f)); + } + + public static Vector3 Lerp(this GameObject go, Vector3 start, Vector3 end, IncludedAxes ia, float t, bool localPosition = false) + { + Vector3 vector = Vector3.Lerp(start, end, t); + return new Vector3(((ia & IncludedAxes.X) != 0) ? vector[0] : (localPosition ? go.transform.localPosition[0] : go.transform.position[0]), ((ia & IncludedAxes.Y) != 0) ? vector[1] : (localPosition ? go.transform.localPosition[1] : go.transform.position[1]), ((ia & IncludedAxes.Z) != 0) ? vector[2] : (localPosition ? go.transform.localPosition[2] : go.transform.position[2])); + } + + public static void SetPosition(this GameObject go, Vector3 pos, IncludedAxes ia, bool localPosition = false) + { + Vector3 vector = new Vector3(((ia & IncludedAxes.X) != 0) ? pos[0] : (localPosition ? go.transform.localPosition[0] : go.transform.position[0]), ((ia & IncludedAxes.Y) != 0) ? pos[1] : (localPosition ? go.transform.localPosition[1] : go.transform.position[1]), ((ia & IncludedAxes.Z) != 0) ? pos[2] : (localPosition ? go.transform.localPosition[2] : go.transform.position[2])); + if (!localPosition) + { + go.transform.position = vector; + } + else + { + go.transform.localPosition = vector; + } + } +} diff --git a/ROUNDS/Photon.Compression/IncludedAxes.cs b/ROUNDS/Photon.Compression/IncludedAxes.cs new file mode 100644 index 0000000..543928b --- /dev/null +++ b/ROUNDS/Photon.Compression/IncludedAxes.cs @@ -0,0 +1,14 @@ +namespace Photon.Compression; + +public enum IncludedAxes +{ + None = 0, + X = 1, + Y = 2, + XY = 3, + Z = 4, + XZ = 5, + YZ = 6, + XYZ = 7, + Uniform = 15 +} diff --git a/ROUNDS/Photon.Compression/IndicatorBit.cs b/ROUNDS/Photon.Compression/IndicatorBit.cs new file mode 100644 index 0000000..325faaf --- /dev/null +++ b/ROUNDS/Photon.Compression/IndicatorBit.cs @@ -0,0 +1,7 @@ +namespace Photon.Compression; + +public enum IndicatorBit +{ + None, + IsZero +} diff --git a/ROUNDS/Photon.Compression/IndicatorBits.cs b/ROUNDS/Photon.Compression/IndicatorBits.cs new file mode 100644 index 0000000..7e6ffb0 --- /dev/null +++ b/ROUNDS/Photon.Compression/IndicatorBits.cs @@ -0,0 +1,8 @@ +namespace Photon.Compression; + +public enum IndicatorBits +{ + None, + IsZero, + IsZeroMidMinMax +} diff --git a/ROUNDS/Photon.Compression/KeyRate.cs b/ROUNDS/Photon.Compression/KeyRate.cs new file mode 100644 index 0000000..99b0891 --- /dev/null +++ b/ROUNDS/Photon.Compression/KeyRate.cs @@ -0,0 +1,13 @@ +namespace Photon.Compression; + +public enum KeyRate +{ + UseDefault = -1, + Never = 0, + Every = 1, + Every2nd = 2, + Every3rd = 3, + Every4th = 4, + Every5th = 5, + Every10th = 10 +} diff --git a/ROUNDS/Photon.Compression/LiteCrusher.cs b/ROUNDS/Photon.Compression/LiteCrusher.cs new file mode 100644 index 0000000..06871b9 --- /dev/null +++ b/ROUNDS/Photon.Compression/LiteCrusher.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public abstract class LiteCrusher +{ + [SerializeField] + protected int bits; + + public static int GetBitsForMaxValue(uint maxvalue) + { + for (int i = 0; i < 32; i++) + { + if (maxvalue >> i == 0) + { + return i; + } + } + return 32; + } +} +[Serializable] +public abstract class LiteCrusher<TComp, T> : LiteCrusher where TComp : struct where T : struct +{ + public abstract TComp Encode(T val); + + public abstract T Decode(uint val); + + public abstract TComp WriteValue(T val, byte[] buffer, ref int bitposition); + + public abstract void WriteCValue(uint val, byte[] buffer, ref int bitposition); + + public abstract T ReadValue(byte[] buffer, ref int bitposition); + + public abstract TComp ReadCValue(byte[] buffer, ref int bitposition); +} diff --git a/ROUNDS/Photon.Compression/LiteFloatCompressType.cs b/ROUNDS/Photon.Compression/LiteFloatCompressType.cs new file mode 100644 index 0000000..e7139c7 --- /dev/null +++ b/ROUNDS/Photon.Compression/LiteFloatCompressType.cs @@ -0,0 +1,18 @@ +namespace Photon.Compression; + +public enum LiteFloatCompressType +{ + Bits2 = 2, + Bits3 = 3, + Bits4 = 4, + Bits5 = 5, + Bits6 = 6, + Bits7 = 7, + Bits8 = 8, + Bits9 = 9, + Bits10 = 10, + Bits12 = 12, + Bits14 = 14, + Half16 = 16, + Full32 = 32 +} diff --git a/ROUNDS/Photon.Compression/LiteFloatCrusher.cs b/ROUNDS/Photon.Compression/LiteFloatCrusher.cs new file mode 100644 index 0000000..cdf20cf --- /dev/null +++ b/ROUNDS/Photon.Compression/LiteFloatCrusher.cs @@ -0,0 +1,249 @@ +using System; +using Photon.Compression.HalfFloat; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public class LiteFloatCrusher : LiteCrusher<ulong, float> +{ + public enum Normalization + { + None, + Positive, + Negative + } + + [SerializeField] + public Normalization normalization; + + [SerializeField] + protected float min; + + [SerializeField] + protected float max; + + [SerializeField] + public LiteFloatCompressType compressType = LiteFloatCompressType.Half16; + + [SerializeField] + public LiteOutOfBoundsHandling outOfBoundsHandling; + + [SerializeField] + private bool accurateCenter = true; + + [SerializeField] + private float encoder; + + [SerializeField] + private float decoder; + + [SerializeField] + private ulong maxCVal; + + public LiteFloatCrusher() + { + compressType = LiteFloatCompressType.Half16; + normalization = Normalization.Positive; + min = 0f; + max = 1f; + accurateCenter = true; + Recalculate(compressType, min, max, accurateCenter, this); + } + + public LiteFloatCrusher(LiteFloatCompressType compressType, float min, float max, bool accurateCenter, LiteOutOfBoundsHandling outOfBoundsHandling = LiteOutOfBoundsHandling.Clamp) + { + this.compressType = compressType; + normalization = Normalization.None; + if (min == max) + { + max += 1f; + Debug.LogWarning("Float crusher is being given min and max values that are the same. This likely is not intentional. Check your range values. Value is <i>" + min + "</i>, changing the max to " + max + " to avoid division by zero errors."); + } + if (min < max) + { + this.min = min; + this.max = max; + } + else + { + this.min = max; + this.max = min; + } + this.accurateCenter = accurateCenter; + this.outOfBoundsHandling = outOfBoundsHandling; + Recalculate(compressType, min, max, accurateCenter, this); + } + + public LiteFloatCrusher(LiteFloatCompressType compressType, Normalization normalization = Normalization.None, LiteOutOfBoundsHandling outOfBoundsHandling = LiteOutOfBoundsHandling.Clamp) + { + this.compressType = compressType; + this.normalization = normalization; + switch (normalization) + { + case Normalization.None: + min = 0f; + max = 1f; + accurateCenter = false; + break; + case Normalization.Positive: + min = 0f; + max = 1f; + accurateCenter = false; + break; + case Normalization.Negative: + min = -1f; + max = 1f; + accurateCenter = true; + break; + } + this.outOfBoundsHandling = outOfBoundsHandling; + Recalculate(compressType, min, max, accurateCenter, this); + } + + public static void Recalculate(LiteFloatCompressType compressType, float min, float max, bool accurateCenter, LiteFloatCrusher crusher) + { + int num = (crusher.bits = (int)compressType); + float num2 = max - min; + ulong num3 = (ulong)((num == 64) ? (-1) : ((1L << num) - 1)); + if (accurateCenter && num3 != 0L) + { + num3--; + } + crusher.encoder = ((num2 == 0f) ? 0f : ((float)num3 / num2)); + crusher.decoder = ((num3 == 0L) ? 0f : (num2 / (float)num3)); + crusher.maxCVal = num3; + } + + public static void Recalculate(LiteFloatCompressType compressType, float min, float max, bool accurateCenter, ref int bits, ref float encoder, ref float decoder, ref ulong maxCVal) + { + bits = (int)compressType; + float num = max - min; + ulong num2 = (ulong)((bits == 64) ? (-1) : ((1L << bits) - 1)); + if (accurateCenter && num2 != 0L) + { + num2--; + } + encoder = ((num == 0f) ? 0f : ((float)num2 / num)); + decoder = ((num2 == 0L) ? 0f : (num / (float)num2)); + maxCVal = num2; + } + + public override ulong Encode(float val) + { + if (compressType == LiteFloatCompressType.Half16) + { + return HalfUtilities.Pack(val); + } + if (compressType == LiteFloatCompressType.Full32) + { + return ((ByteConverter)val).uint32; + } + float num = (val - min) * encoder + 0.5f; + if (num < 0f) + { + if (outOfBoundsHandling == LiteOutOfBoundsHandling.Clamp) + { + return 0uL; + } + return maxCVal + (ulong)((long)num % 10); + } + if (num > (float)maxCVal) + { + if (outOfBoundsHandling == LiteOutOfBoundsHandling.Clamp) + { + return maxCVal; + } + return (ulong)(num % (float)maxCVal); + } + ulong num2 = (ulong)num; + if (num2 <= maxCVal) + { + return num2; + } + return maxCVal; + } + + public override float Decode(uint cval) + { + if (compressType == LiteFloatCompressType.Half16) + { + return HalfUtilities.Unpack((ushort)cval); + } + if (compressType == LiteFloatCompressType.Full32) + { + return ((ByteConverter)cval).float32; + } + if (cval == 0) + { + return min; + } + if (cval == maxCVal) + { + return max; + } + return (float)cval * decoder + min; + } + + public override ulong WriteValue(float val, byte[] buffer, ref int bitposition) + { + if (compressType == LiteFloatCompressType.Half16) + { + ulong num = HalfUtilities.Pack(val); + buffer.Write(num, ref bitposition, 16); + return num; + } + if (compressType == LiteFloatCompressType.Full32) + { + ulong num2 = ((ByteConverter)val).uint32; + buffer.Write(num2, ref bitposition, 32); + return num2; + } + ulong num3 = Encode(val); + buffer.Write(num3, ref bitposition, (int)compressType); + return num3; + } + + public override void WriteCValue(uint cval, byte[] buffer, ref int bitposition) + { + if (compressType == LiteFloatCompressType.Half16) + { + buffer.Write(cval, ref bitposition, 16); + } + else if (compressType == LiteFloatCompressType.Full32) + { + buffer.Write(cval, ref bitposition, 32); + } + else + { + buffer.Write(cval, ref bitposition, (int)compressType); + } + } + + public override float ReadValue(byte[] buffer, ref int bitposition) + { + if (compressType == LiteFloatCompressType.Half16) + { + return HalfUtilities.Unpack((ushort)buffer.Read(ref bitposition, 16)); + } + if (compressType == LiteFloatCompressType.Full32) + { + return ((ByteConverter)(uint)buffer.Read(ref bitposition, 32)).float32; + } + uint val = (uint)buffer.Read(ref bitposition, (int)compressType); + return Decode(val); + } + + public override ulong ReadCValue(byte[] buffer, ref int bitposition) + { + if (compressType == LiteFloatCompressType.Half16) + { + return (ushort)buffer.Read(ref bitposition, 16); + } + if (compressType == LiteFloatCompressType.Full32) + { + return (uint)buffer.Read(ref bitposition, 32); + } + return (uint)buffer.Read(ref bitposition, (int)compressType); + } +} diff --git a/ROUNDS/Photon.Compression/LiteIntCompressType.cs b/ROUNDS/Photon.Compression/LiteIntCompressType.cs new file mode 100644 index 0000000..80013c5 --- /dev/null +++ b/ROUNDS/Photon.Compression/LiteIntCompressType.cs @@ -0,0 +1,8 @@ +namespace Photon.Compression; + +public enum LiteIntCompressType +{ + PackSigned, + PackUnsigned, + Range +} diff --git a/ROUNDS/Photon.Compression/LiteIntCrusher.cs b/ROUNDS/Photon.Compression/LiteIntCrusher.cs new file mode 100644 index 0000000..6b9ad68 --- /dev/null +++ b/ROUNDS/Photon.Compression/LiteIntCrusher.cs @@ -0,0 +1,170 @@ +using System; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public class LiteIntCrusher : LiteCrusher<uint, int> +{ + [SerializeField] + public LiteIntCompressType compressType; + + [SerializeField] + protected int min; + + [SerializeField] + protected int max; + + [SerializeField] + private int smallest; + + [SerializeField] + private int biggest; + + public LiteIntCrusher() + { + compressType = LiteIntCompressType.PackSigned; + min = -128; + max = 127; + if (compressType == LiteIntCompressType.Range) + { + Recalculate(min, max, ref smallest, ref biggest, ref bits); + } + } + + public LiteIntCrusher(LiteIntCompressType compType = LiteIntCompressType.PackSigned, int min = -128, int max = 127) + { + compressType = compType; + this.min = min; + this.max = max; + if (compressType == LiteIntCompressType.Range) + { + Recalculate(min, max, ref smallest, ref biggest, ref bits); + } + } + + public override uint WriteValue(int val, byte[] buffer, ref int bitposition) + { + switch (compressType) + { + case LiteIntCompressType.PackUnsigned: + buffer.WritePackedBytes((uint)val, ref bitposition, 32); + return (uint)val; + case LiteIntCompressType.PackSigned: + { + uint num2 = (uint)((val << 1) ^ (val >> 31)); + buffer.WritePackedBytes(num2, ref bitposition, 32); + return num2; + } + case LiteIntCompressType.Range: + { + uint num = Encode(val); + buffer.Write(num, ref bitposition, bits); + return num; + } + default: + return 0u; + } + } + + public override void WriteCValue(uint cval, byte[] buffer, ref int bitposition) + { + switch (compressType) + { + case LiteIntCompressType.PackUnsigned: + buffer.WritePackedBytes(cval, ref bitposition, 32); + break; + case LiteIntCompressType.PackSigned: + buffer.WritePackedBytes(cval, ref bitposition, 32); + break; + case LiteIntCompressType.Range: + buffer.Write(cval, ref bitposition, bits); + break; + } + } + + public override int ReadValue(byte[] buffer, ref int bitposition) + { + switch (compressType) + { + case LiteIntCompressType.PackUnsigned: + return (int)buffer.ReadPackedBytes(ref bitposition, 32); + case LiteIntCompressType.PackSigned: + return buffer.ReadSignedPackedBytes(ref bitposition, 32); + case LiteIntCompressType.Range: + { + uint val = (uint)buffer.Read(ref bitposition, bits); + return Decode(val); + } + default: + return 0; + } + } + + public override uint ReadCValue(byte[] buffer, ref int bitposition) + { + return compressType switch + { + LiteIntCompressType.PackUnsigned => (uint)buffer.ReadPackedBytes(ref bitposition, 32), + LiteIntCompressType.PackSigned => (uint)buffer.ReadPackedBytes(ref bitposition, 32), + LiteIntCompressType.Range => (uint)buffer.Read(ref bitposition, bits), + _ => 0u, + }; + } + + public override uint Encode(int value) + { + switch (compressType) + { + case LiteIntCompressType.PackSigned: + return value.ZigZag(); + case LiteIntCompressType.PackUnsigned: + return (uint)value; + default: + value = ((value > biggest) ? biggest : ((value < smallest) ? smallest : value)); + return (uint)(value - smallest); + } + } + + public override int Decode(uint cvalue) + { + return compressType switch + { + LiteIntCompressType.PackSigned => cvalue.UnZigZag(), + LiteIntCompressType.PackUnsigned => (int)cvalue, + _ => (int)(cvalue + smallest), + }; + } + + public static void Recalculate(int min, int max, LiteIntCrusher crusher) + { + if (min < max) + { + crusher.smallest = min; + crusher.biggest = max; + } + else + { + crusher.smallest = max; + crusher.biggest = min; + } + int maxvalue = crusher.biggest - crusher.smallest; + crusher.bits = LiteCrusher.GetBitsForMaxValue((uint)maxvalue); + } + + public static void Recalculate(int min, int max, ref int smallest, ref int biggest, ref int bits) + { + if (min < max) + { + smallest = min; + biggest = max; + } + else + { + smallest = max; + biggest = min; + } + int maxvalue = biggest - smallest; + bits = LiteCrusher.GetBitsForMaxValue((uint)maxvalue); + } +} diff --git a/ROUNDS/Photon.Compression/LiteOutOfBoundsHandling.cs b/ROUNDS/Photon.Compression/LiteOutOfBoundsHandling.cs new file mode 100644 index 0000000..a9262e4 --- /dev/null +++ b/ROUNDS/Photon.Compression/LiteOutOfBoundsHandling.cs @@ -0,0 +1,7 @@ +namespace Photon.Compression; + +public enum LiteOutOfBoundsHandling +{ + Clamp, + Loop +} diff --git a/ROUNDS/Photon.Compression/Matrix.cs b/ROUNDS/Photon.Compression/Matrix.cs new file mode 100644 index 0000000..d31c191 --- /dev/null +++ b/ROUNDS/Photon.Compression/Matrix.cs @@ -0,0 +1,300 @@ +using System; +using emotitron.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Compression; + +public class Matrix +{ + public TransformCrusher crusher; + + public Vector3 position; + + public Element rotation; + + public Vector3 scale; + + public static Matrix reusable = new Matrix(); + + public Matrix() + { + } + + public Matrix(TransformCrusher crusher) + { + this.crusher = crusher; + } + + public Matrix(TransformCrusher crusher, Vector3 position, Element rotation, Vector3 scale) + { + this.crusher = crusher; + this.position = position; + this.scale = scale; + this.rotation = rotation; + } + + public Matrix(TransformCrusher crusher, Transform transform) + { + this.crusher = crusher; + position = ((crusher == null || crusher.PosCrusher == null || crusher.PosCrusher.local) ? transform.localPosition : transform.position); + scale = ((crusher == null || crusher.SclCrusher == null || crusher.SclCrusher.local) ? transform.localScale : transform.lossyScale); + bool flag = crusher == null || crusher.RotCrusher == null || crusher.RotCrusher.local; + if (crusher != null && crusher.RotCrusher != null && crusher.RotCrusher.TRSType == TRSType.Quaternion) + { + rotation = (flag ? transform.localRotation : transform.rotation); + } + else + { + rotation = (flag ? transform.localEulerAngles : transform.eulerAngles); + } + } + + public void Set(TransformCrusher crusher, Vector3 position, Element rotation, Vector3 scale) + { + this.crusher = crusher; + this.position = position; + this.scale = scale; + this.rotation = rotation; + } + + [Obsolete("Use Capture() instead. Set was confusing with other usage.")] + public void Set(TransformCrusher crusher, Transform transform) + { + Capture(crusher, transform); + } + + public void Capture(TransformCrusher crusher, Transform transform) + { + this.crusher = crusher; + position = transform.position; + scale = transform.localScale; + if (crusher != null && crusher.RotCrusher != null && crusher.RotCrusher.TRSType == TRSType.Quaternion) + { + rotation = transform.rotation; + } + else + { + rotation = transform.eulerAngles; + } + } + + [Obsolete("Use Capture() instead. Set was confusing with other usage.")] + public void Set(Transform transform) + { + Capture(transform); + } + + public void Capture(Transform transform) + { + position = transform.position; + scale = transform.localScale; + if (crusher != null && crusher.RotCrusher != null && crusher.RotCrusher.TRSType == TRSType.Quaternion) + { + rotation = transform.rotation; + } + else + { + rotation = transform.eulerAngles; + } + } + + [Obsolete("Use Capture() instead. Set was confusing with other usage.")] + public void Set(TransformCrusher crusher, Rigidbody rb) + { + Capture(crusher, rb); + } + + public void Capture(TransformCrusher crusher, Rigidbody rb) + { + this.crusher = crusher; + position = rb.position; + scale = rb.transform.localScale; + if (crusher != null && crusher.RotCrusher != null && crusher.RotCrusher.TRSType == TRSType.Quaternion) + { + rotation = rb.rotation; + } + else + { + rotation = rb.rotation.eulerAngles; + } + } + + [Obsolete("Use Capture() instead. Set was confusing with other usage.")] + public void Set(Rigidbody rb) + { + Capture(rb); + } + + public void Capture(Rigidbody rb) + { + position = rb.position; + if (crusher != null && crusher.RotCrusher != null && crusher.RotCrusher.TRSType == TRSType.Quaternion) + { + rotation = rb.rotation; + } + else + { + rotation = rb.rotation.eulerAngles; + } + scale = rb.transform.localScale; + } + + public void Clear() + { + crusher = null; + } + + public void Compress(CompressedMatrix nonalloc) + { + crusher.Compress(nonalloc, this); + } + + [Obsolete("Supply the transform to Apply to. Default Transform has been deprecated to allow shared TransformCrushers.")] + public void Apply() + { + crusher.Apply(this); + } + + public void Apply(Transform t) + { + if (crusher == null) + { + Debug.LogError("No crusher defined for this matrix. This matrix has not yet had a value assigned to it most likely, but you are trying to apply it to a transform."); + } + else + { + crusher.Apply(t, this); + } + } + + [Obsolete("Apply for Rigidbody has been replaced with Move and Set, to indicate usage of MovePosition/Rotation vs rb.position/rotation.")] + public void Apply(Rigidbody rb) + { + if (crusher == null) + { + Debug.LogError("No crusher defined for this matrix. This matrix has not yet had a value assigned to it most likely, but you are trying to apply it to a transform."); + } + else + { + crusher.Apply(rb, this); + } + } + + public static Matrix Lerp(Matrix target, Matrix start, Matrix end, float t) + { + TransformCrusher transformCrusher = (target.crusher = end.crusher); + target.position = Vector3.Lerp(start.position, end.position, t); + if (transformCrusher != null && transformCrusher.RotCrusher != null) + { + if (transformCrusher.RotCrusher.TRSType == TRSType.Quaternion) + { + target.rotation = Quaternion.Slerp((Quaternion)start.rotation, (Quaternion)end.rotation, t); + } + else + { + Vector3 a = (Vector3)start.rotation; + Vector3 vector = (Vector3)end.rotation; + float num = a.y - vector.y; + float num2 = a.z - vector.z; + Vector3 b = new Vector3(vector.x, (num > 180f) ? (vector.y + 360f) : ((num < -180f) ? (vector.y - 360f) : vector.y), (num2 > 180f) ? (vector.z + 360f) : ((num2 < -180f) ? (vector.z - 360f) : vector.z)); + target.rotation = Vector3.Lerp(a, b, t); + } + } + else + { + target.rotation = end.rotation; + } + target.scale = Vector3.Lerp(start.scale, end.scale, t); + return target; + } + + public static Matrix LerpUnclamped(Matrix target, Matrix start, Matrix end, float t) + { + TransformCrusher transformCrusher = (target.crusher = end.crusher); + target.position = Vector3.LerpUnclamped(start.position, end.position, t); + if (transformCrusher != null && transformCrusher.RotCrusher != null) + { + if (transformCrusher.RotCrusher.TRSType == TRSType.Quaternion) + { + target.rotation = Quaternion.SlerpUnclamped((Quaternion)start.rotation, (Quaternion)end.rotation, t); + } + else + { + Vector3 a = (Vector3)start.rotation; + Vector3 vector = (Vector3)end.rotation; + float num = a.y - vector.y; + float num2 = a.z - vector.z; + Vector3 b = new Vector3(vector.x, (num > 180f) ? (vector.y + 360f) : ((num < -180f) ? (vector.y - 360f) : vector.y), (num2 > 180f) ? (vector.z + 360f) : ((num2 < -180f) ? (vector.z - 360f) : vector.z)); + target.rotation = Vector3.LerpUnclamped(a, b, t); + } + } + else + { + target.rotation = end.rotation; + } + target.scale = Vector3.LerpUnclamped(start.scale, end.scale, t); + return target; + } + + public static Matrix CatmullRomLerpUnclamped(Matrix target, Matrix pre, Matrix start, Matrix end, Matrix post, float t) + { + TransformCrusher transformCrusher = (target.crusher = end.crusher); + target.position = CatmulRom.CatmullRomLerp(pre.position, start.position, end.position, post.position, t); + if (transformCrusher != null && transformCrusher.RotCrusher != null) + { + if (transformCrusher.RotCrusher.TRSType == TRSType.Quaternion) + { + target.rotation = Quaternion.SlerpUnclamped((Quaternion)start.rotation, (Quaternion)end.rotation, t); + } + else + { + Vector3 a = (Vector3)start.rotation; + Vector3 vector = (Vector3)end.rotation; + float num = a.y - vector.y; + float num2 = a.z - vector.z; + Vector3 b = new Vector3(vector.x, (num > 180f) ? (vector.y + 360f) : ((num < -180f) ? (vector.y - 360f) : vector.y), (num2 > 180f) ? (vector.z + 360f) : ((num2 < -180f) ? (vector.z - 360f) : vector.z)); + target.rotation = Vector3.LerpUnclamped(a, b, t); + } + } + else + { + target.rotation = end.rotation; + } + target.scale = CatmulRom.CatmullRomLerp(pre.scale, start.scale, end.scale, post.scale, t); + return target; + } + + public static Matrix CatmullRomLerpUnclamped(Matrix target, Matrix pre, Matrix start, Matrix end, float t) + { + TransformCrusher transformCrusher = (target.crusher = end.crusher); + target.position = CatmulRom.CatmullRomLerp(pre.position, start.position, end.position, t); + if (transformCrusher != null && transformCrusher.RotCrusher != null) + { + if (transformCrusher.RotCrusher.TRSType == TRSType.Quaternion) + { + target.rotation = Quaternion.SlerpUnclamped((Quaternion)start.rotation, (Quaternion)end.rotation, t); + } + else + { + Vector3 a = (Vector3)start.rotation; + Vector3 vector = (Vector3)end.rotation; + float num = a.y - vector.y; + float num2 = a.z - vector.z; + Vector3 b = new Vector3(vector.x, (num > 180f) ? (vector.y + 360f) : ((num < -180f) ? (vector.y - 360f) : vector.y), (num2 > 180f) ? (vector.z + 360f) : ((num2 < -180f) ? (vector.z - 360f) : vector.z)); + target.rotation = Vector3.LerpUnclamped(a, b, t); + } + } + else + { + target.rotation = end.rotation; + } + target.scale = CatmulRom.CatmullRomLerp(pre.scale, start.scale, end.scale, t); + return target; + } + + public override string ToString() + { + return string.Concat("MATRIX pos: ", position, " rot: ", rotation, " scale: ", scale, " rottype: ", rotation.vectorType); + } +} diff --git a/ROUNDS/Photon.Compression/MatrixExtensions.cs b/ROUNDS/Photon.Compression/MatrixExtensions.cs new file mode 100644 index 0000000..e7e4f72 --- /dev/null +++ b/ROUNDS/Photon.Compression/MatrixExtensions.cs @@ -0,0 +1,12 @@ +namespace Photon.Compression; + +public static class MatrixExtensions +{ + public static void CopyFrom(this Matrix target, Matrix src) + { + target.crusher = src.crusher; + target.position = src.position; + target.rotation = src.rotation; + target.scale = src.scale; + } +} diff --git a/ROUNDS/Photon.Compression/NormCompress.cs b/ROUNDS/Photon.Compression/NormCompress.cs new file mode 100644 index 0000000..2a9c276 --- /dev/null +++ b/ROUNDS/Photon.Compression/NormCompress.cs @@ -0,0 +1,182 @@ +using Photon.Compression.HalfFloat; + +namespace Photon.Compression; + +public static class NormCompress +{ + public struct NormCompressCodec + { + public readonly int bits; + + public readonly float encoder; + + public readonly float decoder; + + public NormCompressCodec(int bits, float encoder, float decoder) + { + this.bits = bits; + this.encoder = encoder; + this.decoder = decoder; + } + } + + public static NormCompressCodec[] codecForBit; + + private const float NORM_COMP_ENCODE15 = 32767f; + + private const float NORM_COMP_DECODE15 = 3.051851E-05f; + + private const float NORM_COMP_ENCODE14 = 16383f; + + private const float NORM_COMP_DECODE14 = 6.103888E-05f; + + private const float NORM_COMP_ENCODE13 = 8191f; + + private const float NORM_COMP_DECODE13 = 0.00012208521f; + + private const float NORM_COMP_ENCODE12 = 4095f; + + private const float NORM_COMP_DECODE12 = 0.00024420026f; + + private const float NORM_COMP_ENCODE11 = 2047f; + + private const float NORM_COMP_DECODE11 = 0.0004885198f; + + private const float NORM_COMP_ENCODE10 = 1023f; + + private const float NORM_COMP_DECODE10 = 0.0009775171f; + + private const float NORM_COMP_ENCODE9 = 511f; + + private const float NORM_COMP_DECODE9 = 0.0019569471f; + + private const float NORM_COMP_ENCODE8 = 255f; + + private const float NORM_COMP_DECODE8 = 0.003921569f; + + private const float NORM_COMP_ENCODE7 = 127f; + + private const float NORM_COMP_DECODE7 = 0.003921569f; + + private const float NORM_COMP_ENCODE6 = 63f; + + private const float NORM_COMP_DECODE6 = 1f / 63f; + + private const float NORM_COMP_ENCODE5 = 31f; + + private const float NORM_COMP_DECODE5 = 1f / 31f; + + private const float NORM_COMP_ENCODE4 = 15f; + + private const float NORM_COMP_DECODE4 = 1f / 15f; + + private const float NORM_COMP_ENCODE3 = 7f; + + private const float NORM_COMP_DECODE3 = 1f / 7f; + + private const float NORM_COMP_ENCODE2 = 3f; + + private const float NORM_COMP_DECODE2 = 1f / 3f; + + private const float NORM_COMP_ENCODE1 = 1f; + + private const float NORM_COMP_DECODE1 = 1f; + + private const float NORM_COMP_ENCODE0 = 0f; + + private const float NORM_COMP_DECODE0 = 0f; + + static NormCompress() + { + codecForBit = new NormCompressCodec[33]; + for (int i = 0; i <= 32; i++) + { + uint maxValueForBits = GetMaxValueForBits(i); + codecForBit[i] = new NormCompressCodec(i, maxValueForBits, 1f / (float)maxValueForBits); + } + } + + public static uint CompressNorm(this float value, int bits) + { + value = ((value > 1f) ? 1f : ((value < 0f) ? 0f : value)); + return bits switch + { + 0 => 0u, + 1 => (uint)value, + 2 => (uint)(value * 3f), + 3 => (uint)(value * 7f), + 4 => (uint)(value * 15f), + 5 => (uint)(value * 31f), + 6 => (uint)(value * 63f), + 7 => (uint)(value * 127f), + 8 => (uint)(value * 255f), + 9 => (uint)(value * 511f), + 10 => (uint)(value * 1023f), + 11 => (uint)(value * 2047f), + 12 => (uint)(value * 4095f), + 13 => (uint)(value * 8191f), + 14 => (uint)(value * 16383f), + 15 => (uint)(value * 32767f), + 16 => HalfUtilities.Pack(value), + _ => (ByteConverter)value, + }; + } + + public static uint WriteNorm(this byte[] buffer, float value, ref int bitposition, int bits) + { + value = ((value > 1f) ? 1f : ((value < 0f) ? 0f : value)); + uint num = bits switch + { + 0 => 0u, + 1 => (uint)value, + 2 => (uint)(value * 3f), + 3 => (uint)(value * 7f), + 4 => (uint)(value * 15f), + 5 => (uint)(value * 31f), + 6 => (uint)(value * 63f), + 7 => (uint)(value * 127f), + 8 => (uint)(value * 255f), + 9 => (uint)(value * 511f), + 10 => (uint)(value * 1023f), + 11 => (uint)(value * 2047f), + 12 => (uint)(value * 4095f), + 13 => (uint)(value * 8191f), + 14 => (uint)(value * 16383f), + 15 => (uint)(value * 32767f), + 16 => HalfUtilities.Pack(value), + _ => (ByteConverter)value, + }; + buffer.Write(num, ref bitposition, bits); + return num; + } + + public static float ReadNorm(this byte[] buffer, ref int bitposition, int bits) + { + return bits switch + { + 0 => 0f, + 1 => (float)buffer.Read(ref bitposition, 1) * 1f, + 2 => (float)buffer.Read(ref bitposition, 2) * (1f / 3f), + 3 => (float)buffer.Read(ref bitposition, 3) * (1f / 7f), + 4 => (float)buffer.Read(ref bitposition, 4) * (1f / 15f), + 5 => (float)buffer.Read(ref bitposition, 5) * (1f / 31f), + 6 => (float)buffer.Read(ref bitposition, 6) * (1f / 63f), + 7 => (float)buffer.Read(ref bitposition, 7) * 0.003921569f, + 8 => (float)buffer.Read(ref bitposition, 8) * 0.003921569f, + 9 => (float)buffer.Read(ref bitposition, 9) * 0.0019569471f, + 10 => (float)buffer.Read(ref bitposition, 10) * 0.0009775171f, + 11 => (float)buffer.Read(ref bitposition, 11) * 0.0004885198f, + 12 => (float)buffer.Read(ref bitposition, 12) * 0.00024420026f, + 13 => (float)buffer.Read(ref bitposition, 13) * 0.00012208521f, + 14 => (float)buffer.Read(ref bitposition, 14) * 6.103888E-05f, + 15 => (float)buffer.Read(ref bitposition, 15) * 3.051851E-05f, + 16 => buffer.ReadHalf(ref bitposition), + _ => buffer.ReadFloat(ref bitposition), + }; + } + + public static uint GetMaxValueForBits(int bitcount) + { + return (uint)((1L << bitcount) - 1); + } +} diff --git a/ROUNDS/Photon.Compression/NormalizedFloatCompression.cs b/ROUNDS/Photon.Compression/NormalizedFloatCompression.cs new file mode 100644 index 0000000..32f1023 --- /dev/null +++ b/ROUNDS/Photon.Compression/NormalizedFloatCompression.cs @@ -0,0 +1,18 @@ +namespace Photon.Compression; + +public enum NormalizedFloatCompression +{ + Bits2 = 2, + Bits3 = 3, + Bits4 = 4, + Bits5 = 5, + Bits6 = 6, + Bits7 = 7, + Bits8 = 8, + Bits9 = 9, + Bits10 = 10, + Bits12 = 12, + Bits14 = 14, + Half16 = 16, + Full32 = 32 +} diff --git a/ROUNDS/Photon.Compression/PackObjectAttribute.cs b/ROUNDS/Photon.Compression/PackObjectAttribute.cs new file mode 100644 index 0000000..4880ce9 --- /dev/null +++ b/ROUNDS/Photon.Compression/PackObjectAttribute.cs @@ -0,0 +1,22 @@ +using System; + +namespace Photon.Compression; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +public class PackObjectAttribute : Attribute +{ + public DefaultKeyRate defaultKeyRate; + + public DefaultPackInclusion defaultInclusion; + + public SyncAs syncAs = SyncAs.State; + + public string postSnapCallback; + + public string postApplyCallback; + + public PackObjectAttribute(DefaultKeyRate defaultKeyRate = DefaultKeyRate.Every) + { + this.defaultKeyRate = defaultKeyRate; + } +} diff --git a/ROUNDS/Photon.Compression/PackObjectSettings.cs b/ROUNDS/Photon.Compression/PackObjectSettings.cs new file mode 100644 index 0000000..be7a955 --- /dev/null +++ b/ROUNDS/Photon.Compression/PackObjectSettings.cs @@ -0,0 +1,20 @@ +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Compression; + +public class PackObjectSettings : SettingsScriptableObject<PackObjectSettings> +{ + [Header("Code Generation")] + [Tooltip("Enables the auto generation of codegen for PackObjects / PackAttributes. Disable this if you would like to suspend codegen. Existing codegen will remain, unless it produces errors.")] + public bool autoGenerate = true; + + [Tooltip("Automatically deletes codegen if it produces any compile errors. Typically you will want to leave this enabled. Disable to see the actual errors being generated.")] + public bool deleteBadCode = true; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void Bootstrap() + { + _ = SettingsScriptableObject<PackObjectSettings>.Single; + } +} diff --git a/ROUNDS/Photon.Compression/QuatCrusher.cs b/ROUNDS/Photon.Compression/QuatCrusher.cs new file mode 100644 index 0000000..1ba9a68 --- /dev/null +++ b/ROUNDS/Photon.Compression/QuatCrusher.cs @@ -0,0 +1,321 @@ +using System; +using System.Collections.Generic; +using emotitron.Compression; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public class QuatCrusher : Crusher<QuatCrusher>, IEquatable<QuatCrusher>, ICrusherCopy<QuatCrusher> +{ + public static bool QC_ISPRO = true; + + [Range(16f, 64f)] + [SerializeField] + private int bits; + + [SerializeField] + public CompressLevel _compressLevel; + + [SerializeField] + public Transform transform; + + [SerializeField] + public bool local; + + [HideInInspector] + public bool isStandalone; + + [SerializeField] + public bool showEnableToggle; + + [SerializeField] + private bool enabled = true; + + private QuatCompress.Cache cache; + + [NonSerialized] + private bool initialized; + + public int Bits + { + get + { + if (!enabled) + { + return 0; + } + if (!QC_ISPRO) + { + return RoundBitsToBestPreset(bits); + } + return bits; + } + set + { + if (QC_ISPRO) + { + bits = value; + CompressLevel = CompressLevel.SetBits; + } + else + { + bits = RoundBitsToBestPreset(value); + CompressLevel = (CompressLevel)bits; + } + if (OnRecalculated != null) + { + OnRecalculated(this); + } + } + } + + public CompressLevel CompressLevel + { + get + { + return _compressLevel; + } + set + { + if (QC_ISPRO) + { + _compressLevel = value; + bits = ((_compressLevel == CompressLevel.SetBits) ? bits : ((int)_compressLevel)); + } + else + { + if (_compressLevel == CompressLevel.SetBits) + { + _compressLevel = (CompressLevel)bits; + } + _compressLevel = (CompressLevel)RoundBitsToBestPreset((int)value); + bits = (int)_compressLevel; + } + if (OnRecalculated != null) + { + OnRecalculated(this); + } + } + } + + [SerializeField] + public bool Enabled + { + get + { + return enabled; + } + set + { + enabled = value; + if (OnRecalculated != null) + { + OnRecalculated(this); + } + } + } + + public QuatCrusher() + { + _compressLevel = CompressLevel.uint64Hi; + showEnableToggle = false; + isStandalone = true; + } + + public QuatCrusher(int bits, bool showEnableToggle = false, bool isStandalone = true) + { + this.bits = (QC_ISPRO ? bits : RoundBitsToBestPreset(bits)); + _compressLevel = CompressLevel.SetBits; + this.showEnableToggle = showEnableToggle; + this.isStandalone = isStandalone; + } + + public QuatCrusher(bool showEnableToggle = false, bool isStandalone = true) + { + bits = 32; + _compressLevel = (QC_ISPRO ? CompressLevel.SetBits : CompressLevel.uint32Med); + this.showEnableToggle = showEnableToggle; + this.isStandalone = isStandalone; + } + + public QuatCrusher(CompressLevel compressLevel, bool showEnableToggle = false, bool isStandalone = true) + { + _compressLevel = compressLevel; + bits = (int)compressLevel; + this.showEnableToggle = showEnableToggle; + this.isStandalone = isStandalone; + } + + public void Initialize() + { + cache = QuatCompress.caches[Bits]; + initialized = true; + } + + public override void OnBeforeSerialize() + { + } + + public override void OnAfterDeserialize() + { + if (OnRecalculated != null) + { + OnRecalculated(this); + } + } + + public static int RoundBitsToBestPreset(int bits) + { + if (bits > 32) + { + return 64; + } + if (bits > 16) + { + return 32; + } + if (bits > 8) + { + return 16; + } + return 0; + } + + public ulong Compress() + { + if (!initialized) + { + Initialize(); + } + if (local) + { + return transform.localRotation.Compress(cache); + } + return transform.rotation.Compress(cache); + } + + public ulong Compress(Quaternion quat) + { + if (!initialized) + { + Initialize(); + } + return quat.Compress(cache); + } + + public Quaternion Decompress(ulong compressed) + { + if (!initialized) + { + Initialize(); + } + return compressed.Decompress(cache); + } + + public ulong Write(Quaternion quat, byte[] buffer, ref int bitposition) + { + ulong num = Compress(quat); + buffer.Write(num, ref bitposition, bits); + return num; + } + + public ulong Write(Quaternion quat, uint[] buffer, ref int bitposition) + { + ulong num = Compress(quat); + buffer.Write(num, ref bitposition, bits); + return num; + } + + public ulong Write(Quaternion quat, ulong[] buffer, ref int bitposition) + { + ulong num = Compress(quat); + buffer.Write(num, ref bitposition, bits); + return num; + } + + public ulong Write(ulong c, byte[] buffer, ref int bitposition) + { + buffer.Write(c, ref bitposition, bits); + return c; + } + + public ulong Write(ulong c, uint[] buffer, ref int bitposition) + { + buffer.Write(c, ref bitposition, bits); + return c; + } + + public ulong Write(ulong c, ulong[] buffer, ref int bitposition) + { + buffer.Write(c, ref bitposition, bits); + return c; + } + + public Quaternion Read(byte[] buffer, ref int bitposition) + { + ulong compressed = buffer.Read(ref bitposition, bits); + return Decompress(compressed); + } + + public Quaternion Read(uint[] buffer, ref int bitposition) + { + ulong compressed = buffer.Read(ref bitposition, bits); + return Decompress(compressed); + } + + public Quaternion Read(ulong[] buffer, ref int bitposition) + { + ulong compressed = buffer.Read(ref bitposition, bits); + return Decompress(compressed); + } + + public ulong Write(Quaternion quat, ref ulong buffer, ref int bitposition) + { + ulong num = Compress(quat); + num.Inject(ref buffer, ref bitposition, bits); + return num; + } + + public Quaternion Read(ref ulong buffer, ref int bitposition) + { + ulong compressed = buffer.Read(ref bitposition, bits); + return Decompress(compressed); + } + + public void CopyFrom(QuatCrusher source) + { + bits = source.bits; + _compressLevel = source._compressLevel; + local = source.local; + } + + public override bool Equals(object obj) + { + return Equals(obj as QuatCrusher); + } + + public bool Equals(QuatCrusher other) + { + if (other != null && bits == other.bits && _compressLevel == other._compressLevel) + { + return local == other.local; + } + return false; + } + + public override int GetHashCode() + { + return ((/*-282774512 * -1521134295 + */bits.GetHashCode()) * -1521134295 + _compressLevel.GetHashCode()) * -1521134295 + local.GetHashCode(); + } + + public static bool operator ==(QuatCrusher crusher1, QuatCrusher crusher2) + { + return EqualityComparer<QuatCrusher>.Default.Equals(crusher1, crusher2); + } + + public static bool operator !=(QuatCrusher crusher1, QuatCrusher crusher2) + { + return !(crusher1 == crusher2); + } +} diff --git a/ROUNDS/Photon.Compression/SerializationFlags.cs b/ROUNDS/Photon.Compression/SerializationFlags.cs new file mode 100644 index 0000000..3f3664f --- /dev/null +++ b/ROUNDS/Photon.Compression/SerializationFlags.cs @@ -0,0 +1,12 @@ +namespace Photon.Compression; + +public enum SerializationFlags +{ + None = 0, + HasContent = 1, + Force = 2, + ForceReliable = 4, + SendToSelf = 8, + NewConnection = 0x10, + IsComplete = 0x20 +} diff --git a/ROUNDS/Photon.Compression/SetValueTiming.cs b/ROUNDS/Photon.Compression/SetValueTiming.cs new file mode 100644 index 0000000..291d8b6 --- /dev/null +++ b/ROUNDS/Photon.Compression/SetValueTiming.cs @@ -0,0 +1,8 @@ +namespace Photon.Compression; + +public enum SetValueTiming +{ + Never, + AfterCallback, + BeforeCallback +} diff --git a/ROUNDS/Photon.Compression/SyncAs.cs b/ROUNDS/Photon.Compression/SyncAs.cs new file mode 100644 index 0000000..ea6de39 --- /dev/null +++ b/ROUNDS/Photon.Compression/SyncAs.cs @@ -0,0 +1,8 @@ +namespace Photon.Compression; + +public enum SyncAs +{ + Auto, + State, + Trigger +} diff --git a/ROUNDS/Photon.Compression/SyncHalfFloatAttribute.cs b/ROUNDS/Photon.Compression/SyncHalfFloatAttribute.cs new file mode 100644 index 0000000..6b60ef0 --- /dev/null +++ b/ROUNDS/Photon.Compression/SyncHalfFloatAttribute.cs @@ -0,0 +1,67 @@ +using System; +using Photon.Compression.HalfFloat; +using Photon.Compression.Internal; + +namespace Photon.Compression; + +public class SyncHalfFloatAttribute : SyncVarBaseAttribute, IPackSingle, IPackDouble +{ + private readonly IndicatorBit indicatorBit; + + public SyncHalfFloatAttribute(IndicatorBit indicatorBit = IndicatorBit.None, KeyRate keyRate = KeyRate.UseDefault) + { + this.indicatorBit = indicatorBit; + base.keyRate = keyRate; + } + + public override int GetMaxBits(Type fieldType) + { + return 16 + ((indicatorBit != 0) ? 1 : 0); + } + + public SerializationFlags Pack(ref float value, float prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + ushort num = HalfUtilities.Pack(value); + if (!IsForced(frameId, value, prevValue, writeFlags) && num == HalfUtilities.Pack(prevValue)) + { + return SerializationFlags.None; + } + if (indicatorBit == IndicatorBit.IsZero) + { + if (value == 0f) + { + buffer.Write(1uL, ref bitposition, 1); + return SerializationFlags.IsComplete; + } + buffer.Write(0uL, ref bitposition, 1); + } + buffer.Write(num, ref bitposition, 16); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref float value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (indicatorBit == IndicatorBit.IsZero && buffer.Read(ref bitposition, 1) == 0L) + { + value = 0f; + return SerializationFlags.None; + } + ushort value2 = (ushort)buffer.Read(ref bitposition, 16); + value = HalfUtilities.Unpack(value2); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref double value, double prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + float value2 = (float)value; + return Pack(ref value2, (float)prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref double value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + float value2 = 0f; + SerializationFlags result = Unpack(ref value2, buffer, ref bitposition, frameId, writeFlags); + value = value2; + return result; + } +} diff --git a/ROUNDS/Photon.Compression/SyncListAttribute.cs b/ROUNDS/Photon.Compression/SyncListAttribute.cs new file mode 100644 index 0000000..9777f60 --- /dev/null +++ b/ROUNDS/Photon.Compression/SyncListAttribute.cs @@ -0,0 +1,133 @@ +using System.Collections; +using System.Collections.Generic; +using Photon.Compression.Internal; + +namespace Photon.Compression; + +public class SyncListAttribute : SyncVarBaseAttribute, IPackList<int> +{ + public SerializationFlags Pack(ref List<int> value, List<int> prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + bool flag = IsKeyframe(frameId); + bool flag2 = (writeFlags & (SerializationFlags)22) != 0; + SerializationFlags serializationFlags = SerializationFlags.None; + int num = bitposition; + int i = 0; + for (int count = value.Count; i < count; i++) + { + int num2 = value[i]; + if (!flag) + { + if (!flag2 && num2 == prevValue[i]) + { + buffer.WriteBool(b: false, ref bitposition); + continue; + } + buffer.WriteBool(b: true, ref bitposition); + } + buffer.WriteSignedPackedBytes(num2, ref bitposition, bitCount); + serializationFlags |= SerializationFlags.HasContent; + } + if (serializationFlags == SerializationFlags.None) + { + bitposition = num; + } + return serializationFlags; + } + + public SerializationFlags Unpack(ref List<int> value, BitArray isCompleteMask, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + bool flag = IsKeyframe(frameId); + SerializationFlags serializationFlags = SerializationFlags.None; + SerializationFlags serializationFlags2 = SerializationFlags.IsComplete; + int i = 0; + for (int count = value.Count; i < count; i++) + { + if (!flag && !buffer.ReadBool(ref bitposition)) + { + serializationFlags2 = SerializationFlags.None; + isCompleteMask[i] = false; + } + else + { + isCompleteMask[i] = true; + value[i] = buffer.ReadSignedPackedBytes(ref bitposition, bitCount); + serializationFlags |= SerializationFlags.HasContent; + } + } + return serializationFlags | serializationFlags2; + } + + public SerializationFlags Pack(ref List<uint> value, List<uint> prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + bool flag = IsKeyframe(frameId); + bool flag2 = (writeFlags & (SerializationFlags)22) != 0; + SerializationFlags serializationFlags = SerializationFlags.None; + int num = bitposition; + int i = 0; + for (int count = value.Count; i < count; i++) + { + uint num2 = value[i]; + if (!flag) + { + if (!flag2 && num2 == prevValue[i]) + { + buffer.WriteBool(b: false, ref bitposition); + continue; + } + buffer.WriteBool(b: true, ref bitposition); + } + buffer.WritePackedBytes(num2, ref bitposition, bitCount); + serializationFlags |= SerializationFlags.HasContent; + } + if (serializationFlags == SerializationFlags.None) + { + bitposition = num; + } + return serializationFlags; + } + + public SerializationFlags Unpack(ref List<uint> value, BitArray isCompleteMask, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + bool flag = IsKeyframe(frameId); + SerializationFlags serializationFlags = SerializationFlags.None; + SerializationFlags serializationFlags2 = SerializationFlags.IsComplete; + int i = 0; + for (int count = value.Count; i < count; i++) + { + if (!flag && !buffer.ReadBool(ref bitposition)) + { + serializationFlags2 = SerializationFlags.None; + isCompleteMask[i] = false; + } + else + { + isCompleteMask[i] = true; + value[i] = (uint)buffer.ReadPackedBytes(ref bitposition, bitCount); + serializationFlags |= SerializationFlags.HasContent; + } + } + return serializationFlags | serializationFlags2; + } + + public static void Copy<T>(List<T> src, List<T> trg, BitArray mask) where T : struct + { + int i = 0; + for (int count = src.Count; i < count; i++) + { + if (mask.Get(i)) + { + trg[i] = src[i]; + } + } + } + + public static void Capture<T>(List<T> src, List<T> trg) where T : struct + { + int i = 0; + for (int count = src.Count; i < count; i++) + { + trg[i] = src[i]; + } + } +} diff --git a/ROUNDS/Photon.Compression/SyncRangedIntAttribute.cs b/ROUNDS/Photon.Compression/SyncRangedIntAttribute.cs new file mode 100644 index 0000000..5b51a2b --- /dev/null +++ b/ROUNDS/Photon.Compression/SyncRangedIntAttribute.cs @@ -0,0 +1,280 @@ +using System; +using Photon.Compression.Internal; +using Photon.Utilities; + +namespace Photon.Compression; + +public class SyncRangedIntAttribute : SyncVarBaseAttribute, IPackByte, IPackSByte, IPackUInt16, IPackInt16, IPackUInt32, IPackInt32, IPackUInt64, IPackInt64, IPackSingle, IPackDouble +{ + private int min; + + private int max; + + private readonly int smallest; + + private readonly int biggest; + + private readonly IndicatorBits indicatorBits; + + public SyncRangedIntAttribute(int min, int max, IndicatorBits indicatorBits = IndicatorBits.None, KeyRate keyRate = KeyRate.UseDefault) + { + this.min = min; + this.max = max; + this.indicatorBits = indicatorBits; + base.keyRate = keyRate; + if (min < max) + { + smallest = min; + biggest = max; + } + else + { + smallest = max; + biggest = min; + } + uint maxvalue = (uint)(biggest - smallest); + bitCount = maxvalue.GetBitsForMaxValue(); + } + + public override int GetMaxBits(Type fieldType) + { + return indicatorBits switch + { + IndicatorBits.IsZero => bitCount + 1, + IndicatorBits.IsZeroMidMinMax => bitCount + 2, + _ => bitCount, + }; + } + + private SerializationFlags Write(int value, int prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + int num = ((value > biggest) ? biggest : ((value < smallest) ? smallest : value)); + if (!IsForced(frameId, num, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + if (indicatorBits == IndicatorBits.IsZero) + { + if (num == 0) + { + buffer.Write(0uL, ref bitposition, 1); + return SerializationFlags.IsComplete; + } + buffer.Write(1uL, ref bitposition, 1); + } + else if (indicatorBits == IndicatorBits.IsZeroMidMinMax) + { + if (num == 0) + { + buffer.Write(0uL, ref bitposition, 1); + return SerializationFlags.IsComplete; + } + if (num == min) + { + buffer.Write(1uL, ref bitposition, 1); + return SerializationFlags.IsComplete; + } + if (num == max) + { + buffer.Write(3uL, ref bitposition, 1); + return SerializationFlags.IsComplete; + } + buffer.Write(3uL, ref bitposition, 1); + } + if (bitCount < 16) + { + buffer.Write((ulong)(num - smallest), ref bitposition, bitCount); + } + else + { + buffer.WritePackedBytes((ulong)(num - smallest), ref bitposition, bitCount); + } + return SerializationFlags.IsComplete; + } + + private int Read(byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (indicatorBits == IndicatorBits.IsZero) + { + if (buffer.Read(ref bitposition, 1) == 0L) + { + return 0; + } + } + else if (indicatorBits == IndicatorBits.IsZeroMidMinMax) + { + ulong num = buffer.Read(ref bitposition, 2); + if (num <= 2) + { + switch (num) + { + case 0uL: + return 0; + case 1uL: + return min; + case 2uL: + return max; + } + } + } + if (bitCount < 16) + { + return (int)buffer.Read(ref bitposition, bitCount) + smallest; + } + return (int)((long)buffer.ReadPackedBytes(ref bitposition, bitCount) + (long)smallest); + } + + public SerializationFlags Pack(ref byte value, byte prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write(value, prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref byte value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (byte)Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref sbyte value, sbyte prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write(value, prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref sbyte value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (sbyte)Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref ushort value, ushort prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write(value, prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref ushort value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (ushort)Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref short value, short prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write(value, prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref short value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (short)Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref uint value, uint prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write((int)value, (int)prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref uint value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (uint)Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref int value, int prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write(value, prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref ulong value, ulong prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write((int)value, (int)prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref ulong value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (ulong)Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref long value, long prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + return Write((int)value, (int)prevValue, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref long value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref float value, float prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + int num = (int)Math.Round(value); + int num2 = (int)Math.Round(prevValue); + if (!IsForced(frameId, writeFlags) && num == num2) + { + return SerializationFlags.None; + } + return Write(num, num2, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref float value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref double value, double prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + int num = (int)Math.Round(value); + int num2 = (int)Math.Round(prevValue); + if (!IsForced(frameId, writeFlags) && num == num2) + { + return SerializationFlags.None; + } + return Write(num, num2, buffer, ref bitposition, frameId, writeFlags); + } + + public SerializationFlags Unpack(ref double value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = Read(buffer, ref bitposition, frameId, writeFlags); + return SerializationFlags.IsComplete; + } +} diff --git a/ROUNDS/Photon.Compression/SyncVarAttribute.cs b/ROUNDS/Photon.Compression/SyncVarAttribute.cs new file mode 100644 index 0000000..ee81de7 --- /dev/null +++ b/ROUNDS/Photon.Compression/SyncVarAttribute.cs @@ -0,0 +1,463 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Photon.Compression.Internal; +using UnityEngine; + +namespace Photon.Compression; + +public class SyncVarAttribute : SyncVarBaseAttribute, IPackByte, IPackSByte, IPackUInt16, IPackInt16, IPackUInt32, IPackInt32, IPackUInt64, IPackInt64, IPackSingle, IPackDouble, IPackString, IPackStringBuilder, IPackVector2, IPackVector3, IPackVector2Int, IPackVector3Int, IPackBoolean, IPackChar +{ + public const int MAX_STR_LEN = 63; + + public const int STR_LEN_BITS = 6; + + public bool WholeNumbers; + + private static StringBuilder sb = new StringBuilder(0); + + public SyncVarAttribute(KeyRate keyRate = KeyRate.UseDefault) + { + base.keyRate = keyRate; + } + + public override int GetMaxBits(Type fieldType) + { + if (fieldType == typeof(string) || fieldType == typeof(StringBuilder)) + { + return 1030; + } + if (fieldType == typeof(Vector2)) + { + return 64; + } + if (fieldType == typeof(Vector2)) + { + return 96; + } + return base.GetMaxBits(fieldType); + } + + public bool Compare<T>(List<T> a, List<T> b) where T : struct + { + int count = a.Count; + if (count != b.Count) + { + return false; + } + for (int i = 0; i < count; i++) + { + if (!a[i].Equals(b[i])) + { + return false; + } + } + return false; + } + + public SerializationFlags Pack(ref bool value, bool prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write((ulong)(value ? 1 : 0), ref bitposition, 1); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref bool value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = buffer.Read(ref bitposition, 1) != 0L; + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref byte value, byte prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref byte value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (byte)buffer.Read(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref sbyte value, sbyte prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSigned(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref sbyte value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (sbyte)buffer.ReadSigned(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref ushort value, ushort prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref ushort value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (ushort)buffer.Read(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref short value, short prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + Debug.Log("Pack " + bitCount); + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSigned(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref short value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (short)buffer.ReadSigned(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref char value, char prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref char value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (char)buffer.Read(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref uint value, uint prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WritePackedBytes(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref uint value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = (uint)buffer.ReadPackedBytes(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref int value, int prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = buffer.ReadSignedPackedBytes(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref ulong value, ulong prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WritePackedBytes(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref ulong value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = buffer.ReadPackedBytes(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref long value, long prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes64(value, ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref long value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = buffer.ReadSignedPackedBytes64(ref bitposition, bitCount); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref float value, float prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + int value2 = (int)Math.Round(value); + int prevValue2 = (int)Math.Round(prevValue); + if (!IsForced(frameId, value2, prevValue2, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes(value2, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write((uint)(ByteConverter)value, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref float value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + value = buffer.ReadSignedPackedBytes(ref bitposition, 32); + return SerializationFlags.IsComplete; + } + value = (ByteConverter)buffer.Read(ref bitposition, 32); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref double value, double prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + long value2 = (int)Math.Round(value); + long prevValue2 = (int)Math.Round(prevValue); + if (!IsForced(frameId, value2, prevValue2, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes64(value2, ref bitposition, 64); + return SerializationFlags.IsComplete; + } + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write((ByteConverter)value, ref bitposition, 64); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref double value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + value = buffer.ReadSignedPackedBytes64(ref bitposition, 64); + return SerializationFlags.IsComplete; + } + value = (ByteConverter)buffer.Read(ref bitposition, 64); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref string value, string prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForcedClass(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + if (value == null) + { + buffer.Write(0uL, ref bitposition, 6); + return SerializationFlags.IsComplete; + } + int num = value.Length; + if (num > 63) + { + num = 63; + } + buffer.Write((uint)num, ref bitposition, 6); + for (int i = 0; i < num; i++) + { + buffer.Write(value[i], ref bitposition, bitCount); + } + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref string value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + sb.Length = 0; + int num = (int)buffer.Read(ref bitposition, 6); + for (int i = 0; i < num; i++) + { + sb.Append((char)buffer.Read(ref bitposition, bitCount)); + } + value = sb.ToString(); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref StringBuilder value, StringBuilder prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForcedClass(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + if (value == null) + { + buffer.Write(0uL, ref bitposition, 6); + return SerializationFlags.IsComplete; + } + int num = value.Length; + if (num > 63) + { + num = 63; + } + buffer.Write((uint)num, ref bitposition, 6); + for (int i = 0; i < num; i++) + { + buffer.Write(value[i], ref bitposition, bitCount); + } + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref StringBuilder value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (value == null) + { + value = new StringBuilder(64); + } + else + { + value.Length = 0; + } + int num = (int)buffer.Read(ref bitposition, 6); + for (int i = 0; i < num; i++) + { + value.Append((char)buffer.Read(ref bitposition, bitCount)); + } + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref Vector2 value, Vector2 prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + Vector2Int value2 = new Vector2Int((int)value.x, (int)value.y); + if (!IsForced<Vector2Int>(prevValue: new Vector2Int((int)prevValue.x, (int)prevValue.y), frameId: frameId, value: value2, writeFlags: writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes(value2.x, ref bitposition, 32); + buffer.WriteSignedPackedBytes(value2.y, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write((uint)(ByteConverter)value.x, ref bitposition, 32); + buffer.Write((uint)(ByteConverter)value.y, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref Vector2 value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + value = new Vector2(buffer.ReadSignedPackedBytes(ref bitposition, 32), buffer.ReadSignedPackedBytes(ref bitposition, 32)); + return SerializationFlags.IsComplete; + } + value = new Vector2((ByteConverter)buffer.Read(ref bitposition, 32), (ByteConverter)buffer.Read(ref bitposition, 32)); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref Vector3 value, Vector3 prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + Vector3Int value2 = new Vector3Int((int)value.x, (int)value.y, (int)value.z); + if (!IsForced<Vector3Int>(prevValue: new Vector3Int((int)prevValue.x, (int)prevValue.y, (int)prevValue.z), frameId: frameId, value: value2, writeFlags: writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes(value2.x, ref bitposition, 32); + buffer.WriteSignedPackedBytes(value2.y, ref bitposition, 32); + buffer.WriteSignedPackedBytes(value2.z, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.Write((uint)(ByteConverter)value.x, ref bitposition, 32); + buffer.Write((uint)(ByteConverter)value.y, ref bitposition, 32); + buffer.Write((uint)(ByteConverter)value.z, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref Vector3 value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (WholeNumbers) + { + value = new Vector3(buffer.ReadSignedPackedBytes(ref bitposition, 32), buffer.ReadSignedPackedBytes(ref bitposition, 32), buffer.ReadSignedPackedBytes(ref bitposition, 32)); + return SerializationFlags.IsComplete; + } + value = new Vector3((ByteConverter)buffer.Read(ref bitposition, 32), (ByteConverter)buffer.Read(ref bitposition, 32), (ByteConverter)buffer.Read(ref bitposition, 32)); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref Vector2Int value, Vector2Int prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes(value.x, ref bitposition, 32); + buffer.WriteSignedPackedBytes(value.y, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref Vector2Int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = new Vector2Int(buffer.ReadSignedPackedBytes(ref bitposition, 32), buffer.ReadSignedPackedBytes(ref bitposition, 32)); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Pack(ref Vector3Int value, Vector3Int prevValue, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + if (!IsForced(frameId, value, prevValue, writeFlags)) + { + return SerializationFlags.None; + } + buffer.WriteSignedPackedBytes(value.x, ref bitposition, 32); + buffer.WriteSignedPackedBytes(value.y, ref bitposition, 32); + buffer.WriteSignedPackedBytes(value.z, ref bitposition, 32); + return SerializationFlags.IsComplete; + } + + public SerializationFlags Unpack(ref Vector3Int value, byte[] buffer, ref int bitposition, int frameId, SerializationFlags writeFlags) + { + value = new Vector3Int(buffer.ReadSignedPackedBytes(ref bitposition, 32), buffer.ReadSignedPackedBytes(ref bitposition, 32), buffer.ReadSignedPackedBytes(ref bitposition, 32)); + return SerializationFlags.IsComplete; + } +} diff --git a/ROUNDS/Photon.Compression/TransformCrusher.cs b/ROUNDS/Photon.Compression/TransformCrusher.cs new file mode 100644 index 0000000..c9775dd --- /dev/null +++ b/ROUNDS/Photon.Compression/TransformCrusher.cs @@ -0,0 +1,1193 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using emotitron.Compression; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public class TransformCrusher : Crusher<TransformCrusher>, ICrusherCopy<TransformCrusher> +{ + public const int VersionMajor = 3; + + public const int VersionMinor = 5; + + public const int VersionRevision = 3; + + public const int Build = 3503; + + public static Dictionary<int, TransformCrusher> staticTransformCrushers = new Dictionary<int, TransformCrusher>(); + + [HideInInspector] + [Obsolete("Default Transform breaks crusher sharing across multiple instances and is now deprecated.")] + [Tooltip("This is the default assumed transform when no transform or gameobject is given to methods.")] + public Transform defaultTransform; + + [SerializeField] + protected ElementCrusher posCrusher; + + [SerializeField] + protected ElementCrusher rotCrusher; + + [SerializeField] + protected ElementCrusher sclCrusher; + + [NonSerialized] + protected readonly int[] cached_pBits = new int[4]; + + [NonSerialized] + protected readonly int[] cached_rBits = new int[4]; + + [NonSerialized] + protected readonly int[] cached_sBits = new int[4]; + + [NonSerialized] + protected readonly int[] _cached_total = new int[4]; + + public ReadOnlyCollection<int> cached_total; + + protected bool cached; + + public static ulong[] reusableArray64 = new ulong[5]; + + private const string transformMissingError = "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."; + + public ElementCrusher PosCrusher + { + get + { + return posCrusher; + } + set + { + if ((object)posCrusher != value) + { + if (posCrusher != null) + { + ElementCrusher elementCrusher = posCrusher; + elementCrusher.OnRecalculated = (Action<ElementCrusher>)Delegate.Remove(elementCrusher.OnRecalculated, new Action<ElementCrusher>(OnCrusherChange)); + } + posCrusher = value; + if (posCrusher != null) + { + ElementCrusher elementCrusher2 = posCrusher; + elementCrusher2.OnRecalculated = (Action<ElementCrusher>)Delegate.Combine(elementCrusher2.OnRecalculated, new Action<ElementCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public ElementCrusher RotCrusher + { + get + { + return rotCrusher; + } + set + { + if ((object)rotCrusher != value) + { + if (rotCrusher != null) + { + ElementCrusher elementCrusher = rotCrusher; + elementCrusher.OnRecalculated = (Action<ElementCrusher>)Delegate.Remove(elementCrusher.OnRecalculated, new Action<ElementCrusher>(OnCrusherChange)); + } + rotCrusher = value; + if (rotCrusher != null) + { + ElementCrusher elementCrusher2 = rotCrusher; + elementCrusher2.OnRecalculated = (Action<ElementCrusher>)Delegate.Combine(elementCrusher2.OnRecalculated, new Action<ElementCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public ElementCrusher SclCrusher + { + get + { + return sclCrusher; + } + set + { + if ((object)sclCrusher != value) + { + if (sclCrusher != null) + { + ElementCrusher elementCrusher = sclCrusher; + elementCrusher.OnRecalculated = (Action<ElementCrusher>)Delegate.Remove(elementCrusher.OnRecalculated, new Action<ElementCrusher>(OnCrusherChange)); + } + sclCrusher = value; + if (sclCrusher != null) + { + ElementCrusher elementCrusher2 = sclCrusher; + elementCrusher2.OnRecalculated = (Action<ElementCrusher>)Delegate.Combine(elementCrusher2.OnRecalculated, new Action<ElementCrusher>(OnCrusherChange)); + } + CacheValues(); + } + } + } + + public static TransformCrusher CheckAgainstStatics(TransformCrusher tc, bool CheckElementCrusherAsWell = true) + { + if ((object)tc == null) + { + return null; + } + if (CheckElementCrusherAsWell) + { + tc.posCrusher = ElementCrusher.CheckAgainstStatics(tc.posCrusher); + tc.rotCrusher = ElementCrusher.CheckAgainstStatics(tc.rotCrusher); + tc.sclCrusher = ElementCrusher.CheckAgainstStatics(tc.sclCrusher); + } + int hashCode = tc.GetHashCode(); + if (staticTransformCrushers.ContainsKey(hashCode)) + { + return staticTransformCrushers[hashCode]; + } + staticTransformCrushers.Add(hashCode, tc); + return tc; + } + + public void OnCrusherChange(ElementCrusher crusher) + { + CacheValues(); + } + + public TransformCrusher() + { + ConstructDefault(); + } + + public TransformCrusher(bool isStatic = false) + { + ConstructDefault(isStatic); + } + + protected virtual void ConstructDefault(bool isStatic = false) + { + if (!isStatic) + { + PosCrusher = new ElementCrusher(TRSType.Position, enableTRSTypeSelector: false); + RotCrusher = new ElementCrusher(TRSType.Euler, enableTRSTypeSelector: false) + { + XCrusher = new FloatCrusher(BitPresets.Bits12, -90f, 90f, Axis.X, TRSType.Euler, showEnableToggle: true), + YCrusher = new FloatCrusher(BitPresets.Bits12, -180f, 180f, Axis.Y, TRSType.Euler, showEnableToggle: true), + ZCrusher = new FloatCrusher(BitPresets.Disabled, -180f, 180f, Axis.Z, TRSType.Euler, showEnableToggle: true) + }; + SclCrusher = new ElementCrusher(TRSType.Scale, enableTRSTypeSelector: false) + { + uniformAxes = ElementCrusher.UniformAxes.XYZ, + UCrusher = new FloatCrusher(8, 0f, 2f, Axis.Uniform, TRSType.Scale, showEnableToggle: true) + }; + } + } + + public override void OnBeforeSerialize() + { + } + + public override void OnAfterDeserialize() + { + CacheValues(); + } + + public virtual void CacheValues() + { + for (int i = 0; i < 4; i++) + { + cached_pBits[i] = ((!(posCrusher == null)) ? posCrusher.Cached_TotalBits[i] : 0); + cached_rBits[i] = ((!(rotCrusher == null)) ? rotCrusher.Cached_TotalBits[i] : 0); + cached_sBits[i] = ((!(sclCrusher == null)) ? sclCrusher.Cached_TotalBits[i] : 0); + _cached_total[i] = cached_pBits[i] + cached_rBits[i] + cached_sBits[i]; + cached_total = Array.AsReadOnly(_cached_total); + } + cached = true; + } + + public void Write(CompressedMatrix cm, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(cm.cPos, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(cm.cRot, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(cm.cScl, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + } + + public void Write(CompressedMatrix cm, uint[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(cm.cPos, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(cm.cRot, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(cm.cScl, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + } + + public void Write(CompressedMatrix cm, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(cm.cPos, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(cm.cRot, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(cm.cScl, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + } + + public void Write(CompressedMatrix nonalloc, Transform transform, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(nonalloc.cPos, transform, buffer, ref bitposition, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(nonalloc.cRot, transform, buffer, ref bitposition, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(nonalloc.cScl, transform, buffer, ref bitposition, bcl); + } + } + + public void Write(Transform transform, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Write(CompressedMatrix.reusable, transform, buffer, ref bitposition, bcl); + } + + public Matrix ReadAndDecompress(ulong[] array, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + return ReadAndDecompress(array, ref bitposition, bcl); + } + + public Matrix ReadAndDecompress(uint[] array, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + return ReadAndDecompress(array, ref bitposition, bcl); + } + + public Matrix ReadAndDecompress(byte[] array, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + return ReadAndDecompress(array, ref bitposition, bcl); + } + + public void ReadAndDecompress(Matrix nonalloc, ulong[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public void ReadAndDecompress(Matrix nonalloc, uint[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public void ReadAndDecompress(Matrix nonalloc, byte[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public Matrix ReadAndDecompress(ulong[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + ReadAndDecompress(Matrix.reusable, array, ref bitposition, bcl); + return Matrix.reusable; + } + + public Matrix ReadAndDecompress(uint[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + ReadAndDecompress(Matrix.reusable, array, ref bitposition, bcl); + return Matrix.reusable; + } + + public Matrix ReadAndDecompress(byte[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + ReadAndDecompress(Matrix.reusable, array, ref bitposition, bcl); + return Matrix.reusable; + } + + public void Read(CompressedMatrix nonalloc, byte[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Read(nonalloc.cPos, array, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Read(nonalloc.cRot, array, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Read(nonalloc.cScl, array, ref bitposition, IncludedAxes.XYZ, bcl); + } + } + + public CompressedMatrix Read(ulong[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + public CompressedMatrix Read(uint[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + public CompressedMatrix Read(byte[] array, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + public CompressedMatrix Read(ulong[] array, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + public CompressedMatrix Read(uint[] array, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + public CompressedMatrix Read(byte[] array, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, array, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + public void Read(CompressedMatrix nonalloc, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Read(nonalloc.cPos, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Read(nonalloc.cRot, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Read(nonalloc.cScl, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + } + + public void Read(CompressedMatrix nonalloc, uint[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Read(nonalloc.cPos, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Read(nonalloc.cRot, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Read(nonalloc.cScl, buffer, ref bitposition, IncludedAxes.XYZ, bcl); + } + } + + public void Write(CompressedMatrix nonalloc, Transform transform, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(nonalloc.cPos, transform, ref buffer, ref bitposition, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(nonalloc.cRot, transform, ref buffer, ref bitposition, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(nonalloc.cScl, transform, ref buffer, ref bitposition, bcl); + } + } + + public void Write(Transform transform, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(transform, ref buffer, ref bitposition, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(transform, ref buffer, ref bitposition, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(transform, ref buffer, ref bitposition, bcl); + } + } + + public void Write(CompressedMatrix cm, ref ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(cm.cPos, ref buffer, ref bitposition, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(cm.cRot, ref buffer, ref bitposition, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(cm.cScl, ref buffer, ref bitposition, bcl); + } + } + + public void Write(CompressedMatrix nonalloc, Transform transform, ref ulong bitstream, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + Compress(nonalloc, transform); + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Write(nonalloc.cPos, ref bitstream, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Write(nonalloc.cRot, ref bitstream, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Write(nonalloc.cScl, ref bitstream, bcl); + } + } + + public void ReadAndDecompress(Matrix nonalloc, ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + ReadAndDecompress(nonalloc, buffer, ref bitposition, bcl); + } + + [Obsolete("Use the nonalloc overload instead and supply a target Matrix. Matrix is now a class rather than a struct")] + public Matrix ReadAndDecompress(ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + return ReadAndDecompress(buffer, ref bitposition, bcl); + } + + public void ReadAndDecompress(Matrix nonalloc, ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + [Obsolete("Use the nonalloc overload instead and supply a target Matrix. Matrix is now a class rather than a struct")] + public Matrix ReadAndDecompress(ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + return Decompress(CompressedMatrix.reusable); + } + + public void ReadAndApply(Transform target, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Apply(target, CompressedMatrix.reusable); + } + + public void Read(CompressedMatrix nonalloc, ulong frag0, ulong frag1 = 0uL, ulong frag2 = 0uL, ulong frag3 = 0uL, ulong frag4 = 0uL, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + int bitposition = 0; + reusableArray64.Write(frag0, ref bitposition, 64); + reusableArray64.Write(frag1, ref bitposition, 64); + reusableArray64.Write(frag2, ref bitposition, 64); + reusableArray64.Write(frag3, ref bitposition, 64); + reusableArray64.Write(frag4, ref bitposition, 64); + bitposition = 0; + Read(nonalloc, reusableArray64, ref bitposition, bcl); + } + + public void ReadAndDecompress(Matrix nonalloc, ulong frag0, ulong frag1 = 0uL, ulong frag2 = 0uL, ulong frag3 = 0uL, ulong frag4 = 0uL, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, frag0, frag1, frag2, frag3, frag4, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public CompressedMatrix Read(ulong frag0, ulong frag1 = 0uL, ulong frag2 = 0uL, ulong frag3 = 0uL, uint frag4 = 0u, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, frag0, frag1, frag2, frag3, frag4, bcl); + return CompressedMatrix.reusable; + } + + public void Read(CompressedMatrix nonalloc, ulong buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(nonalloc, buffer, ref bitposition, bcl); + } + + public void Read(CompressedMatrix nonalloc, ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[(int)bcl] > 0) + { + posCrusher.Read(nonalloc.cPos, buffer, ref bitposition, bcl); + } + if (cached_rBits[(int)bcl] > 0) + { + rotCrusher.Read(nonalloc.cRot, buffer, ref bitposition, bcl); + } + if (cached_sBits[(int)bcl] > 0) + { + sclCrusher.Read(nonalloc.cScl, buffer, ref bitposition, bcl); + } + } + + public CompressedMatrix Read(ulong buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + return CompressedMatrix.reusable; + } + + [Obsolete("Supply the transform to compress. Default Transform has be deprecated.")] + public void Compress(CompressedMatrix nonalloc) + { + Debug.Assert(defaultTransform, "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."); + Compress(nonalloc, defaultTransform); + } + + [Obsolete("Supply the transform to compress. Default Transform has be deprecated.")] + public CompressedMatrix Compress() + { + Debug.Assert(defaultTransform, "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."); + return Compress(defaultTransform); + } + + public void Compress(CompressedMatrix nonalloc, Matrix matrix) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[0] > 0) + { + posCrusher.Compress(nonalloc.cPos, matrix.position); + } + else + { + nonalloc.cPos.Clear(); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Compress(nonalloc.cRot, matrix.rotation); + } + else + { + nonalloc.cRot.Clear(); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Compress(nonalloc.cScl, matrix.scale); + } + else + { + nonalloc.cScl.Clear(); + } + } + + public void Compress(CompressedMatrix nonalloc, Transform transform) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + if (cached_pBits[0] > 0) + { + posCrusher.Compress(nonalloc.cPos, transform); + } + else + { + nonalloc.cPos.Clear(); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Compress(nonalloc.cRot, transform); + } + else + { + nonalloc.cRot.Clear(); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Compress(nonalloc.cScl, transform); + } + else + { + nonalloc.cScl.Clear(); + } + } + + public CompressedMatrix Compress(Transform transform) + { + Compress(CompressedMatrix.reusable, transform); + return CompressedMatrix.reusable; + } + + public CompressedMatrix Compress(Rigidbody rb) + { + Compress(CompressedMatrix.reusable, rb); + return CompressedMatrix.reusable; + } + + public void Compress(CompressedMatrix nonalloc, Rigidbody rb) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + posCrusher.Compress(nonalloc.cPos, rb); + rotCrusher.Compress(nonalloc.cRot, rb); + sclCrusher.Compress(nonalloc.cScl, rb); + } + + public CompressedMatrix Compress(Rigidbody2D rb2d) + { + Compress(CompressedMatrix.reusable, rb2d); + return CompressedMatrix.reusable; + } + + public void Compress(CompressedMatrix nonalloc, Rigidbody2D rb2d) + { + if (!cached) + { + CacheValues(); + } + nonalloc.crusher = this; + posCrusher.Compress(nonalloc.cPos, rb2d.transform); + rotCrusher.Compress(nonalloc.cRot, rb2d.transform); + sclCrusher.Compress(nonalloc.cScl, rb2d.transform); + } + + public void CompressAndWrite(Matrix matrix, byte[] buffer, ref int bitposition) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[0] > 0) + { + posCrusher.CompressAndWrite(matrix.position, buffer, ref bitposition); + } + if (cached_rBits[0] > 0) + { + rotCrusher.CompressAndWrite(matrix.rotation, buffer, ref bitposition); + } + if (cached_sBits[0] > 0) + { + sclCrusher.CompressAndWrite(matrix.scale, buffer, ref bitposition); + } + } + + public void CompressAndWrite(Transform transform, byte[] buffer, ref int bitposition) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[0] > 0) + { + posCrusher.CompressAndWrite(transform, buffer, ref bitposition); + } + if (cached_rBits[0] > 0) + { + rotCrusher.CompressAndWrite(transform, buffer, ref bitposition); + } + if (cached_sBits[0] > 0) + { + sclCrusher.CompressAndWrite(transform, buffer, ref bitposition); + } + } + + public void CompressAndWrite(Rigidbody rb, byte[] buffer, ref int bitposition) + { + if (!cached) + { + CacheValues(); + } + if (cached_pBits[0] > 0) + { + Vector3 v = ((posCrusher.local && (bool)rb.transform.parent) ? rb.transform.InverseTransformPoint(rb.position) : rb.position); + posCrusher.CompressAndWrite(v, buffer, ref bitposition); + } + if (cached_rBits[0] > 0) + { + if (rotCrusher.TRSType == TRSType.Quaternion) + { + rotCrusher.CompressAndWrite(rb.rotation, buffer, ref bitposition); + } + else + { + rotCrusher.CompressAndWrite(rb.rotation.eulerAngles, buffer, ref bitposition); + } + } + if (cached_sBits[0] > 0) + { + sclCrusher.CompressAndWrite(rb.transform, buffer, ref bitposition); + } + } + + public void Decompress(Matrix nonalloc, ulong[] buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public void Decompress(Matrix nonalloc, uint[] buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public void Decompress(Matrix nonalloc, ulong compressed, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, compressed, bcl); + Decompress(nonalloc, CompressedMatrix.reusable); + } + + public Matrix Decompress(ulong[] buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Decompress(Matrix.reusable, CompressedMatrix.reusable); + return Matrix.reusable; + } + + public Matrix Decompress(uint[] buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Decompress(Matrix.reusable, CompressedMatrix.reusable); + return Matrix.reusable; + } + + public Matrix Decompress(byte[] buffer, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int bitposition = 0; + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Decompress(Matrix.reusable, CompressedMatrix.reusable); + return Matrix.reusable; + } + + public Matrix Decompress(ulong compressed, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, compressed, bcl); + Decompress(Matrix.reusable, CompressedMatrix.reusable); + return Matrix.reusable; + } + + public void Decompress(Matrix nonalloc, CompressedMatrix compMatrix) + { + if (!cached) + { + CacheValues(); + } + nonalloc.Set(this, (cached_pBits[0] > 0) ? ((Vector3)posCrusher.Decompress(compMatrix.cPos)) : default(Vector3), (cached_rBits[0] > 0) ? rotCrusher.Decompress(compMatrix.cRot) : ((rotCrusher.TRSType == TRSType.Quaternion) ? new Element(new Quaternion(0f, 0f, 0f, 1f)) : new Element(new Vector3(0f, 0f, 0f))), (cached_sBits[0] > 0) ? ((Vector3)sclCrusher.Decompress(compMatrix.cScl)) : default(Vector3)); + } + + [Obsolete("Use the nonalloc overload instead and supply a target Matrix. Matrix is now a class rather than a struct")] + public Matrix Decompress(CompressedMatrix compMatrix) + { + if (!cached) + { + CacheValues(); + } + return new Matrix(this, (cached_pBits[0] > 0) ? ((Vector3)posCrusher.Decompress(compMatrix.cPos)) : default(Vector3), (cached_rBits[0] > 0) ? rotCrusher.Decompress(compMatrix.cRot) : ((rotCrusher.TRSType == TRSType.Quaternion) ? new Element(new Quaternion(0f, 0f, 0f, 1f)) : new Element(new Vector3(0f, 0f, 0f))), (cached_sBits[0] > 0) ? ((Vector3)sclCrusher.Decompress(compMatrix.cScl)) : default(Vector3)); + } + + public void Set(Rigidbody rb, CompressedMatrix cmatrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Set(rb, cmatrix.cPos); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Set(rb, cmatrix.cRot); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb.transform, cmatrix.cScl); + } + } + + public void Set(Rigidbody rb, Matrix matrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Set(rb, matrix.position); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Set(rb, matrix.rotation); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb.transform, matrix.scale); + } + } + + public void Set(Rigidbody rb, ulong frag0, ulong frag1 = 0uL, ulong frag2 = 0uL, ulong frag3 = 0uL, ulong frag4 = 0uL) + { + Read(CompressedMatrix.reusable, frag0, frag1, frag2, frag3, frag4); + Set(rb, CompressedMatrix.reusable); + } + + public void Set(Rigidbody rb, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Set(rb, CompressedMatrix.reusable); + } + + public void Set(Rigidbody rb, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Set(rb, CompressedMatrix.reusable); + } + + public void Set(Rigidbody2D rb2d, Matrix matrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Set(rb2d, matrix.position); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Set(rb2d, matrix.rotation); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb2d.transform, matrix.scale); + } + } + + public void Set(Rigidbody2D rb2d, CompressedMatrix cmatrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Set(rb2d, cmatrix.cPos); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Set(rb2d, cmatrix.cRot); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb2d.transform, cmatrix.cScl); + } + } + + public void Move(Rigidbody rb, CompressedMatrix cmatrix) + { + Move(rb, cmatrix.Decompress()); + if (cached_pBits[0] > 0) + { + posCrusher.Move(rb, cmatrix.cPos); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Move(rb, cmatrix.cRot); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb.transform, cmatrix.cScl); + } + } + + public void Move(Rigidbody rb, Matrix matrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Move(rb, matrix.position); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Move(rb, matrix.rotation); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb.transform, matrix.scale); + } + } + + public void Move(Rigidbody rb, ulong frag0, ulong frag1 = 0uL, ulong frag2 = 0uL, ulong frag3 = 0uL, ulong frag4 = 0uL) + { + Read(CompressedMatrix.reusable, frag0, frag1, frag2, frag3, frag4); + Move(rb, CompressedMatrix.reusable); + } + + public void Move(Rigidbody rb, ulong[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Move(rb, CompressedMatrix.reusable); + } + + public void Move(Rigidbody rb, byte[] buffer, ref int bitposition, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + Read(CompressedMatrix.reusable, buffer, ref bitposition, bcl); + Move(rb, CompressedMatrix.reusable); + } + + [Obsolete("Apply for Rigidbody has been replaced with Move and Set, to indicate usage of MovePosition/Rotation vs rb.position/rotation.")] + public void Apply(Rigidbody rb, CompressedMatrix cmatrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Apply(rb, cmatrix.cPos); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Apply(rb, cmatrix.cRot); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb.transform, cmatrix.cScl); + } + } + + [Obsolete("Apply for Rigidbody has been replaced with Move and Set, to indicate usage of MovePosition/Rotation vs rb.position/rotation.")] + public void Apply(Rigidbody rb, Matrix matrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Apply(rb, matrix.position); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Apply(rb, matrix.rotation); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(rb.transform, matrix.scale); + } + } + + [Obsolete("Supply the transform to compress. Default Transform has be deprecated.")] + public void Apply(ulong cvalue) + { + Debug.Assert(defaultTransform, "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."); + Apply(defaultTransform, cvalue); + } + + public void Apply(Transform t, ulong cvalue) + { + Decompress(Matrix.reusable, cvalue); + Apply(t, Matrix.reusable); + } + + [Obsolete("Supply the transform to compress. Default Transform has be deprecated.")] + public void Apply(ulong u0, ulong u1, ulong u2, ulong u3, uint u4) + { + Debug.Assert(defaultTransform, "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."); + Apply(defaultTransform, u0, u1, u2, u3, u4); + } + + public void Apply(Transform t, ulong frag0, ulong frag1 = 0uL, ulong frag2 = 0uL, ulong frag3 = 0uL, ulong frag4 = 0uL) + { + Read(CompressedMatrix.reusable, frag0, frag1, frag2, frag3, frag4); + Apply(t, CompressedMatrix.reusable); + } + + [Obsolete("Supply the transform to Apply to. Default Transform has be deprecated.")] + public void Apply(CompressedMatrix cmatrix) + { + Debug.Assert(defaultTransform, "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."); + Apply(defaultTransform, cmatrix); + } + + public void Apply(Transform t, CompressedMatrix cmatrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Apply(t, cmatrix.cPos); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Apply(t, cmatrix.cRot); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(t, cmatrix.cScl); + } + } + + [Obsolete("Supply the transform to Apply to. Default Transform has be deprecated.")] + public void Apply(Matrix matrix) + { + Debug.Assert(defaultTransform, "The 'defaultTransform' is null and has not be set in the inspector. For non-editor usages of TransformCrusher you need to pass the target transform to this method."); + Apply(defaultTransform, matrix); + } + + public void Apply(Transform transform, Matrix matrix) + { + if (cached_pBits[0] > 0) + { + posCrusher.Apply(transform, matrix.position); + } + if (cached_rBits[0] > 0) + { + rotCrusher.Apply(transform, matrix.rotation); + } + if (cached_sBits[0] > 0) + { + sclCrusher.Apply(transform, matrix.scale); + } + } + + public void Capture(Rigidbody rb, CompressedMatrix cm, Matrix m) + { + Compress(cm, rb); + Decompress(m, cm); + } + + public void Capture(Rigidbody2D rb2d, CompressedMatrix cm, Matrix m) + { + Compress(cm, rb2d); + Decompress(m, cm); + } + + public void Capture(Transform tr, CompressedMatrix cm, Matrix m) + { + posCrusher.Compress(cm.cPos, tr); + m.position = (Vector3)posCrusher.Decompress(cm.cPos); + rotCrusher.Compress(cm.cRot, tr); + m.rotation = rotCrusher.Decompress(cm.cRot); + sclCrusher.Compress(cm.cScl, tr); + m.scale = (Vector3)sclCrusher.Decompress(cm.cScl); + } + + public int TallyBits(BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + int num = ((posCrusher != null) ? posCrusher.TallyBits(bcl) : 0); + int num2 = ((posCrusher != null) ? rotCrusher.TallyBits(bcl) : 0); + int num3 = ((posCrusher != null) ? sclCrusher.TallyBits(bcl) : 0); + return num + num2 + num3; + } + + public void CopyFrom(TransformCrusher source) + { + posCrusher.CopyFrom(source.posCrusher); + rotCrusher.CopyFrom(source.rotCrusher); + sclCrusher.CopyFrom(source.sclCrusher); + CacheValues(); + } + + public override bool Equals(object obj) + { + return Equals(obj as TransformCrusher); + } + + public bool Equals(TransformCrusher other) + { + if (other != null && ((posCrusher == null) ? (other.posCrusher == null) : posCrusher.Equals(other.posCrusher)) && ((rotCrusher == null) ? (other.rotCrusher == null) : rotCrusher.Equals(other.rotCrusher))) + { + if (!(sclCrusher == null)) + { + return sclCrusher.Equals(other.sclCrusher); + } + return other.sclCrusher == null; + } + return false; + } + + public override int GetHashCode() + { + return ((/*-453726296 * -1521134295 +*/ ((!(posCrusher == null)) ? posCrusher.GetHashCode() : 0)) * -1521134295 + ((!(rotCrusher == null)) ? rotCrusher.GetHashCode() : 0)) * -1521134295 + ((!(sclCrusher == null)) ? sclCrusher.GetHashCode() : 0); + } + + public static bool operator ==(TransformCrusher crusher1, TransformCrusher crusher2) + { + return EqualityComparer<TransformCrusher>.Default.Equals(crusher1, crusher2); + } + + public static bool operator !=(TransformCrusher crusher1, TransformCrusher crusher2) + { + return !(crusher1 == crusher2); + } +} diff --git a/ROUNDS/Photon.Compression/WorldBounds.cs b/ROUNDS/Photon.Compression/WorldBounds.cs new file mode 100644 index 0000000..71f44be --- /dev/null +++ b/ROUNDS/Photon.Compression/WorldBounds.cs @@ -0,0 +1,148 @@ +using System; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Compression; + +[ExecuteInEditMode] +public class WorldBounds : MonoBehaviour +{ + [SerializeField] + [HideInInspector] + private Bounds manualBounds = new Bounds(new Vector3(0f, 0f, 0f), new Vector3(600f, 40f, 600f)); + + [Tooltip("Selects which WorldBounds group this object should be factored into.")] + [WorldBoundsSelectAttribute] + [SerializeField] + [HideInInspector] + public int worldBoundsGrp; + + [SerializeField] + [HideInInspector] + private bool includeChildren = true; + + [Tooltip("Awake/Destroy will consider element into the world size as long as it exists in the scene (You may need to wake it though). Enable/Disable only factors it in if it is active.")] + [SerializeField] + [HideInInspector] + private BoundsTools.BoundsType factorIn; + + [HideInInspector] + public Bounds myBounds; + + [HideInInspector] + public int myBoundsCount; + + public Action OnWorldBoundsChange; + + public Bounds ManualBounds + { + get + { + return manualBounds; + } + set + { + manualBounds = value; + CollectMyBounds(); + } + } + + public BoundsTools.BoundsType FactorIn + { + get + { + return factorIn; + } + set + { + factorIn = value; + CollectMyBounds(); + } + } + + private void Awake() + { + CollectMyBounds(); + } + + public void CollectMyBounds() + { + WorldBoundsSettings single = SettingsScriptableObject<WorldBoundsSettings>.Single; + if ((bool)single) + { + if (SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups.Count == 0) + { + SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups.Add(new WorldBoundsGroup()); + } + if (worldBoundsGrp >= SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups.Count) + { + worldBoundsGrp = 0; + } + WorldBoundsGroup worldBoundsGroup = single.worldBoundsGroups[worldBoundsGrp]; + if (factorIn == BoundsTools.BoundsType.Manual) + { + myBounds = manualBounds; + myBoundsCount = 1; + } + else + { + myBounds = base.gameObject.CollectMyBounds(factorIn, out myBoundsCount, includeChildren); + } + WorldBoundsSettings.RemoveWorldBoundsFromAll(this); + if (myBoundsCount > 0 && base.enabled && !worldBoundsGroup.activeWorldBounds.Contains(this)) + { + worldBoundsGroup.activeWorldBounds.Add(this); + worldBoundsGroup.RecalculateWorldCombinedBounds(); + } + if (OnWorldBoundsChange != null) + { + OnWorldBoundsChange(); + } + } + } + + private void Start() + { + } + + private void OnEnable() + { + FactorInBounds(b: true); + } + + private void OnDisable() + { + FactorInBounds(b: false); + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.magenta; + Gizmos.DrawWireCube(SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups[worldBoundsGrp]._combinedWorldBounds.center, SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups[worldBoundsGrp]._combinedWorldBounds.size); + } + + public void FactorInBounds(bool b) + { + if (this == null) + { + return; + } + if (worldBoundsGrp >= SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups.Count) + { + worldBoundsGrp = 0; + } + WorldBoundsGroup worldBoundsGroup = SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups[worldBoundsGrp]; + if (b) + { + if (!worldBoundsGroup.activeWorldBounds.Contains(this)) + { + worldBoundsGroup.activeWorldBounds.Add(this); + } + } + else + { + worldBoundsGroup.activeWorldBounds.Remove(this); + } + worldBoundsGroup.RecalculateWorldCombinedBounds(); + } +} diff --git a/ROUNDS/Photon.Compression/WorldBoundsGroup.cs b/ROUNDS/Photon.Compression/WorldBoundsGroup.cs new file mode 100644 index 0000000..3960fed --- /dev/null +++ b/ROUNDS/Photon.Compression/WorldBoundsGroup.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using emotitron.Compression; +using UnityEngine; + +namespace Photon.Compression; + +[Serializable] +public class WorldBoundsGroup +{ + public const string defaultName = "Default"; + + public const string newAddName = "Unnamed"; + + public string name = "Default"; + + [NonSerialized] + public Action OnWorldBoundChanged; + + public ElementCrusher crusher = GetUncompressedCrusher(); + + [NonSerialized] + public readonly List<WorldBounds> activeWorldBounds = new List<WorldBounds>(); + + [NonSerialized] + public Bounds _combinedWorldBounds; + + public int ActiveBoundsObjCount => activeWorldBounds.Count; + + public static ElementCrusher GetUncompressedCrusher() + { + return new ElementCrusher(TRSType.Position, enableTRSTypeSelector: false) + { + enableLocalSelector = false, + hideFieldName = true, + XCrusher = new FloatCrusher + { + axis = Axis.X, + outOfBoundsHandling = OutOfBoundsHandling.Clamp, + Resolution = 100uL, + BitsDeterminedBy = BitsDeterminedBy.Uncompressed + }, + YCrusher = new FloatCrusher + { + axis = Axis.Y, + outOfBoundsHandling = OutOfBoundsHandling.Clamp, + Resolution = 100uL, + BitsDeterminedBy = BitsDeterminedBy.Uncompressed + }, + ZCrusher = new FloatCrusher + { + axis = Axis.Z, + outOfBoundsHandling = OutOfBoundsHandling.Clamp, + Resolution = 100uL, + BitsDeterminedBy = BitsDeterminedBy.Uncompressed + } + }; + } + + public void ResetActiveBounds() + { + activeWorldBounds.Clear(); + } + + public void RecalculateWorldCombinedBounds() + { + FloatCrusher xCrusher = crusher.XCrusher; + FloatCrusher yCrusher = crusher.YCrusher; + FloatCrusher zCrusher = crusher.ZCrusher; + if (activeWorldBounds.Count == 0) + { + _combinedWorldBounds = default(Bounds); + } + else + { + if (xCrusher.BitsDeterminedBy > BitsDeterminedBy.Disabled || xCrusher.BitsDeterminedBy == BitsDeterminedBy.SetBits || xCrusher.BitsDeterminedBy == BitsDeterminedBy.Uncompressed || xCrusher.BitsDeterminedBy == BitsDeterminedBy.HalfFloat) + { + xCrusher.Resolution = 100uL; + xCrusher.BitsDeterminedBy = BitsDeterminedBy.Resolution; + } + if (yCrusher.BitsDeterminedBy > BitsDeterminedBy.Disabled || yCrusher.BitsDeterminedBy == BitsDeterminedBy.SetBits || yCrusher.BitsDeterminedBy == BitsDeterminedBy.Uncompressed || yCrusher.BitsDeterminedBy == BitsDeterminedBy.HalfFloat) + { + yCrusher.Resolution = 100uL; + yCrusher.BitsDeterminedBy = BitsDeterminedBy.Resolution; + } + if (zCrusher.BitsDeterminedBy > BitsDeterminedBy.Disabled || zCrusher.BitsDeterminedBy == BitsDeterminedBy.SetBits || zCrusher.BitsDeterminedBy == BitsDeterminedBy.Uncompressed || zCrusher.BitsDeterminedBy == BitsDeterminedBy.HalfFloat) + { + zCrusher.Resolution = 100uL; + zCrusher.BitsDeterminedBy = BitsDeterminedBy.Resolution; + } + _combinedWorldBounds = activeWorldBounds[0].myBounds; + for (int i = 1; i < activeWorldBounds.Count; i++) + { + _combinedWorldBounds.Encapsulate(activeWorldBounds[i].myBounds); + } + crusher.Bounds = _combinedWorldBounds; + } + if (OnWorldBoundChanged != null) + { + OnWorldBoundChanged(); + } + } +} diff --git a/ROUNDS/Photon.Compression/WorldBoundsSelectAttributeAttribute.cs b/ROUNDS/Photon.Compression/WorldBoundsSelectAttributeAttribute.cs new file mode 100644 index 0000000..8a71ee1 --- /dev/null +++ b/ROUNDS/Photon.Compression/WorldBoundsSelectAttributeAttribute.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +namespace Photon.Compression; + +public class WorldBoundsSelectAttributeAttribute : PropertyAttribute +{ +} diff --git a/ROUNDS/Photon.Compression/WorldBoundsSettings.cs b/ROUNDS/Photon.Compression/WorldBoundsSettings.cs new file mode 100644 index 0000000..ce165d5 --- /dev/null +++ b/ROUNDS/Photon.Compression/WorldBoundsSettings.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using emotitron.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Compression; + +[CreateAssetMenu] +public class WorldBoundsSettings : SettingsScriptableObject<WorldBoundsSettings> +{ + [HideInInspector] + public List<WorldBoundsGroup> worldBoundsGroups = new List<WorldBoundsGroup>(); + + public static ElementCrusher defaultWorldBoundsCrusher; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void Bootstrap() + { + WorldBoundsSettings worldBoundsSettings = SettingsScriptableObject<WorldBoundsSettings>.Single; + List<WorldBoundsGroup> list = worldBoundsSettings.worldBoundsGroups; + if (worldBoundsSettings != null && list.Count > 0) + { + defaultWorldBoundsCrusher = worldBoundsSettings.worldBoundsGroups[0].crusher; + } + } + + protected override void Awake() + { + base.Awake(); + if (worldBoundsGroups.Count == 0) + { + worldBoundsGroups.Add(new WorldBoundsGroup()); + } + } + + public override void Initialize() + { + base.Initialize(); + if (worldBoundsGroups.Count == 0) + { + worldBoundsGroups.Add(new WorldBoundsGroup()); + } + defaultWorldBoundsCrusher = worldBoundsGroups[0].crusher; + foreach (WorldBoundsGroup worldBoundsGroup in worldBoundsGroups) + { + worldBoundsGroup.RecalculateWorldCombinedBounds(); + } + } + + public static void RemoveWorldBoundsFromAll(WorldBounds wb) + { + List<WorldBoundsGroup> list = SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups; + for (int i = 0; i < list.Count; i++) + { + List<WorldBounds> activeWorldBounds = list[i].activeWorldBounds; + if (activeWorldBounds.Contains(wb)) + { + activeWorldBounds.Remove(wb); + list[i].RecalculateWorldCombinedBounds(); + } + } + } + + public static int TallyBits(ref int index, BitCullingLevel bcl = BitCullingLevel.NoCulling) + { + List<WorldBoundsGroup> list = SettingsScriptableObject<WorldBoundsSettings>.Single.worldBoundsGroups; + if (index >= list.Count) + { + index = 0; + } + ElementCrusher crusher = SettingsScriptableObject<WorldBoundsSettings>.single.worldBoundsGroups[index].crusher; + return crusher.XCrusher.GetBits(bcl) + crusher.YCrusher.GetBits(bcl) + crusher.ZCrusher.GetBits(bcl); + } +} diff --git a/ROUNDS/Photon.Compression/XYZSwitchMaskAttribute.cs b/ROUNDS/Photon.Compression/XYZSwitchMaskAttribute.cs new file mode 100644 index 0000000..2998d75 --- /dev/null +++ b/ROUNDS/Photon.Compression/XYZSwitchMaskAttribute.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +namespace Photon.Compression; + +public class XYZSwitchMaskAttribute : PropertyAttribute +{ +} diff --git a/ROUNDS/Photon.Pun.Demo/OwnerGUI.cs b/ROUNDS/Photon.Pun.Demo/OwnerGUI.cs new file mode 100644 index 0000000..445f343 --- /dev/null +++ b/ROUNDS/Photon.Pun.Demo/OwnerGUI.cs @@ -0,0 +1,24 @@ +using Photon.Pun.Simple; +using UnityEngine.UI; + +namespace Photon.Pun.Demo; + +public class OwnerGUI : NetComponent +{ + private Text text; + + public override void OnAwake() + { + base.OnAwake(); + text = GetComponentInChildren<Text>(); + } + + private void Update() + { + if ((bool)text) + { + PhotonView photonView = base.photonView; + text.text = photonView.OwnerActorNr + " : " + photonView.ControllerActorNr; + } + } +} diff --git a/ROUNDS/Photon.Pun.Example/TakeOwnership.cs b/ROUNDS/Photon.Pun.Example/TakeOwnership.cs new file mode 100644 index 0000000..2408d0f --- /dev/null +++ b/ROUNDS/Photon.Pun.Example/TakeOwnership.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +namespace Photon.Pun.Example; + +public class TakeOwnership : MonoBehaviour +{ + public KeyCode keycode = KeyCode.C; + + private void Start() + { + } + + private void Update() + { + if (Input.GetKeyDown(keycode)) + { + TransferOwner(); + } + } + + public void TransferOwner() + { + GetComponent<PhotonView>().TransferOwnership(PhotonNetwork.LocalPlayer.ActorNumber); + } +} diff --git a/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupAssign.cs b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupAssign.cs new file mode 100644 index 0000000..235f91f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupAssign.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace Photon.Pun.Simple.ContactGroups; + +public class ContactGroupAssign : MonoBehaviour, IContactGroupsAssign, IContactGroupMask +{ + public ContactGroupMaskSelector contactGroups; + + [Tooltip("Will add a ContactGroupAssign to any children that have colliders and no ContactGroupAssign of their own. ")] + [SerializeField] + protected bool applyToChildren = true; + + public bool ApplyToChildren => applyToChildren; + + public int Mask => contactGroups.Mask; +} diff --git a/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupMaskSelector.cs b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupMaskSelector.cs new file mode 100644 index 0000000..afdd64a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupMaskSelector.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple.ContactGroups; + +[Serializable] +public struct ContactGroupMaskSelector : IContactGroupMask +{ + [SerializeField] + private int mask; + + public int Mask + { + get + { + return mask; + } + set + { + mask = value; + } + } + + public ContactGroupMaskSelector(int mask) + { + this.mask = mask; + } + + public static implicit operator int(ContactGroupMaskSelector selector) + { + return selector.mask; + } + + public static implicit operator ContactGroupMaskSelector(int mask) + { + return new ContactGroupMaskSelector(mask); + } +} diff --git a/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupSelector.cs b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupSelector.cs new file mode 100644 index 0000000..8f10152 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupSelector.cs @@ -0,0 +1,21 @@ +using System; + +namespace Photon.Pun.Simple.ContactGroups; + +[Serializable] +public struct ContactGroupSelector : IContactGroupMask +{ + public int index; + + public int Mask + { + get + { + if (index != 0) + { + return 1 << index - 1; + } + return 0; + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupSettings.cs b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupSettings.cs new file mode 100644 index 0000000..6e58a95 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupSettings.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple.ContactGroups; + +public class ContactGroupSettings : SettingsScriptableObject<ContactGroupSettings> +{ + public static bool initialized; + + public const string DEF_NAME = "Default"; + + [HideInInspector] + public List<string> contactGroupTags = new List<string>(2) { "Default", "Critical" }; + + public Dictionary<string, int> rewindLayerTagToId = new Dictionary<string, int>(); + + [NonSerialized] + public static int bitsForMask; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void Bootstrap() + { + _ = SettingsScriptableObject<ContactGroupSettings>.Single; + } + + public override void Initialize() + { + SettingsScriptableObject<ContactGroupSettings>.single = this; + base.Initialize(); + if (initialized) + { + return; + } + initialized = true; + bitsForMask = contactGroupTags.Count - 1; + for (int i = 0; i < contactGroupTags.Count; i++) + { + if (rewindLayerTagToId.ContainsKey(contactGroupTags[i])) + { + Debug.LogError("The tag '" + contactGroupTags[i] + "' is used more than once in '" + GetType().Name + "'. Repeats will be discarded, which will likely break some parts of rewind until they are removed."); + } + else + { + rewindLayerTagToId.Add(contactGroupTags[i], i); + } + } + } + + [Obsolete("Left over from NST, likely not useful any more.")] + public static int FindClosestMatch(string n, int id) + { + ContactGroupSettings contactGroupSettings = SettingsScriptableObject<ContactGroupSettings>.Single; + if (contactGroupSettings.contactGroupTags.Contains(n)) + { + return contactGroupSettings.contactGroupTags.IndexOf(n); + } + if (id < contactGroupSettings.contactGroupTags.Count) + { + return id; + } + return 0; + } +} diff --git a/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupValues.cs b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupValues.cs new file mode 100644 index 0000000..7e13a5c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.ContactGroups/ContactGroupValues.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple.ContactGroups; + +[Serializable] +public class ContactGroupValues +{ + [SerializeField] + public List<float> values = new List<float> { 1f }; +} diff --git a/ROUNDS/Photon.Pun.Simple.ContactGroups/IContactGroupMask.cs b/ROUNDS/Photon.Pun.Simple.ContactGroups/IContactGroupMask.cs new file mode 100644 index 0000000..fbe4f11 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.ContactGroups/IContactGroupMask.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple.ContactGroups; + +public interface IContactGroupMask +{ + int Mask { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple.Debugging/UIConsole.cs b/ROUNDS/Photon.Pun.Simple.Debugging/UIConsole.cs new file mode 100644 index 0000000..b355eb0 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Debugging/UIConsole.cs @@ -0,0 +1,175 @@ +using System.Text; +using UnityEngine; +using UnityEngine.UI; + +namespace Photon.Pun.Simple.Debugging; + +public class UIConsole : MonoBehaviour +{ + public int maxSize = 3000; + + public bool logToDebug = true; + + public static readonly StringBuilder strb = new StringBuilder(); + + private static UIConsole single; + + private static Text uitext; + + public static UIConsole Single + { + get + { + if (single == null) + { + CreateGUI(); + } + return single; + } + } + + public UIConsole __ + { + get + { + strb.Append(" "); + return single; + } + } + + private void Awake() + { + single = this; + uitext = GetComponent<Text>(); + uitext.text = strb.ToString(); + } + + public static void Log(string str) + { + if ((bool)single) + { + if (strb.Length > single.maxSize) + { + strb.Length = 0; + } + if (uitext != null) + { + strb.Append(str).Append("\n"); + uitext.text = strb.ToString(); + } + if (single.logToDebug) + { + Debug.Log(str); + } + } + } + + public UIConsole _(object str) + { + strb.Append(str.ToString()); + return single; + } + + public UIConsole _(string str) + { + strb.Append(str); + return single; + } + + public UIConsole _(int str) + { + strb.Append(str); + return single; + } + + public UIConsole _(uint str) + { + strb.Append(str); + return single; + } + + public UIConsole _(byte str) + { + strb.Append(str); + return single; + } + + public UIConsole _(sbyte str) + { + strb.Append(str); + return single; + } + + public UIConsole _(short str) + { + strb.Append(str); + return single; + } + + public UIConsole _(ushort str) + { + strb.Append(str); + return single; + } + + public UIConsole _(long str) + { + strb.Append(str); + return single; + } + + public UIConsole _(ulong str) + { + strb.Append(str); + return single; + } + + public UIConsole _(float str) + { + strb.Append(str); + return single; + } + + public UIConsole _(double str) + { + strb.Append(str); + return single; + } + + public static void Refresh() + { + if ((bool)single && uitext != null) + { + uitext.text = strb.ToString(); + } + } + + public static void Clear() + { + strb.Length = 0; + if ((bool)uitext) + { + uitext.text = strb.ToString(); + } + } + + public static UIConsole CreateGUI() + { + GameObject gameObject = new GameObject("UI CONSOLE"); + Canvas canvas = gameObject.AddComponent<Canvas>(); + GameObject gameObject2 = new GameObject("CONSOLE TEXT"); + gameObject2.transform.parent = gameObject.transform; + uitext = gameObject2.AddComponent<Text>(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; + uitext.font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font; + uitext.verticalOverflow = VerticalWrapMode.Overflow; + uitext.horizontalOverflow = HorizontalWrapMode.Overflow; + uitext.alignment = TextAnchor.UpperCenter; + uitext.rectTransform.pivot = new Vector2(0f, 0f); + uitext.rectTransform.anchorMin = new Vector2(0f, 0f); + uitext.rectTransform.anchorMax = new Vector2(1f, 1f); + uitext.rectTransform.offsetMax = new Vector2(0f, 0f); + single = gameObject2.AddComponent<UIConsole>(); + return single; + } +} diff --git a/ROUNDS/Photon.Pun.Simple.GhostWorlds/IHasNetworkID.cs b/ROUNDS/Photon.Pun.Simple.GhostWorlds/IHasNetworkID.cs new file mode 100644 index 0000000..3ffae64 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.GhostWorlds/IHasNetworkID.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple.GhostWorlds; + +public interface IHasNetworkID +{ + uint ViewID { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/CallbackUtilities.cs b/ROUNDS/Photon.Pun.Simple.Internal/CallbackUtilities.cs new file mode 100644 index 0000000..ad3588b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/CallbackUtilities.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace Photon.Pun.Simple.Internal; + +public static class CallbackUtilities +{ + public static int RegisterInterface<T>(List<T> callbackList, object c, bool register) where T : class + { + if (callbackList == null) + { + callbackList = new List<T>(); + } + if (!(c is T item)) + { + return callbackList.Count; + } + if (register) + { + if (!callbackList.Contains(item)) + { + callbackList.Add(item); + } + } + else if (callbackList.Contains(item)) + { + callbackList.Remove(item); + } + return callbackList.Count; + } +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/NetMsgCallbacks.cs b/ROUNDS/Photon.Pun.Simple.Internal/NetMsgCallbacks.cs new file mode 100644 index 0000000..eca574d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/NetMsgCallbacks.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine; + +namespace Photon.Pun.Simple.Internal; + +public static class NetMsgCallbacks +{ + public delegate void ByteBufferCallback(object conn, int connId, byte[] buffer); + + private class CallbackLists + { + public List<ByteBufferCallback> bufferCallbacks; + } + + private static Dictionary<int, CallbackLists> callbacks = new Dictionary<int, CallbackLists>(); + + public const byte DEF_MSG_ID = 215; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void RegisterOnEventListener() + { + PhotonNetwork.NetworkingClient.EventReceived += OnEvent; + } + + public static void OnEvent(EventData photonEvent) + { + byte code = photonEvent.Code; + if (!callbacks.ContainsKey(code)) + { + return; + } + bool useByteArraySlicePoolForEvents = PhotonNetwork.NetworkingClient.LoadBalancingPeer.UseByteArraySlicePoolForEvents; + ByteArraySlice byteArraySlice; + byte[] buffer; + if (useByteArraySlicePoolForEvents) + { + byteArraySlice = photonEvent.CustomData as ByteArraySlice; + buffer = byteArraySlice.Buffer; + } + else + { + byteArraySlice = null; + buffer = photonEvent.CustomData as byte[]; + } + CallbackLists callbackLists = callbacks[code]; + if (callbackLists.bufferCallbacks != null && callbackLists.bufferCallbacks.Count > 0) + { + foreach (ByteBufferCallback bufferCallback in callbackLists.bufferCallbacks) + { + bufferCallback(null, photonEvent.Sender, buffer); + } + } + if (useByteArraySlicePoolForEvents) + { + byteArraySlice.Release(); + } + } + + [Obsolete("Removed the asServer from UNET side, killing it here as well.")] + public static void RegisterCallback(byte msgid, ByteBufferCallback callback, bool asServer) + { + if (!callbacks.ContainsKey(msgid)) + { + callbacks.Add(msgid, new CallbackLists()); + } + if (callbacks[msgid].bufferCallbacks == null) + { + callbacks[msgid].bufferCallbacks = new List<ByteBufferCallback>(); + } + List<ByteBufferCallback> bufferCallbacks = callbacks[msgid].bufferCallbacks; + if (!bufferCallbacks.Contains(callback)) + { + bufferCallbacks.Add(callback); + } + } + + public static void RegisterCallback(ByteBufferCallback callback) + { + RegisterCallback(215, callback); + } + + public static void RegisterCallback(byte msgid, ByteBufferCallback callback) + { + if (!callbacks.ContainsKey(msgid)) + { + callbacks.Add(msgid, new CallbackLists()); + } + if (callbacks[msgid].bufferCallbacks == null) + { + callbacks[msgid].bufferCallbacks = new List<ByteBufferCallback>(); + } + List<ByteBufferCallback> bufferCallbacks = callbacks[msgid].bufferCallbacks; + if (!bufferCallbacks.Contains(callback)) + { + bufferCallbacks.Add(callback); + } + } + + [Obsolete("Removed the asServer from UNET side, killing it here as well.")] + public static void UnregisterCallback(byte msgid, ByteBufferCallback callback, bool asServer) + { + if (callbacks.ContainsKey(msgid)) + { + CallbackLists callbackLists = callbacks[msgid]; + callbackLists.bufferCallbacks.Remove(callback); + if (callbackLists.bufferCallbacks.Count == 0) + { + callbacks.Remove(msgid); + } + } + } + + public static void UnregisterCallback(ByteBufferCallback callback) + { + UnregisterCallback(215, callback); + } + + public static void UnregisterCallback(byte msgid, ByteBufferCallback callback) + { + if (callbacks.ContainsKey(msgid)) + { + CallbackLists callbackLists = callbacks[msgid]; + callbackLists.bufferCallbacks.Remove(callback); + if (callbackLists.bufferCallbacks.Count == 0) + { + callbacks.Remove(msgid); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/NetMsgSends.cs b/ROUNDS/Photon.Pun.Simple.Internal/NetMsgSends.cs new file mode 100644 index 0000000..983f798 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/NetMsgSends.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using ExitGames.Client.Photon; +using Photon.Compression; +using Photon.Realtime; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple.Internal; + +public static class NetMsgSends +{ + private static bool unreliableCapable; + + public static byte[] reusableBuffer = new byte[16384]; + + public static byte[] reusableNetObjBuffer = new byte[4096]; + + public static HashSet<int> newPlayers = new HashSet<int>(); + + private static RaiseEventOptions[] opts = new RaiseEventOptions[3] + { + new RaiseEventOptions + { + Receivers = ReceiverGroup.Others + }, + new RaiseEventOptions + { + Receivers = ReceiverGroup.All + }, + new RaiseEventOptions + { + Receivers = ReceiverGroup.MasterClient + } + }; + + public static bool ReadyToSend => PhotonNetwork.NetworkClientState == ClientState.Joined; + + public static bool AmActiveServer => false; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void CacheSettings() + { + unreliableCapable = PhotonNetwork.NetworkingClient.LoadBalancingPeer.UsedProtocol == ConnectionProtocol.Udp; + } + + public static void Send(this byte[] buffer, int bitposition, Object refObj, SerializationFlags flags, bool flush = false) + { + Room currentRoom = PhotonNetwork.CurrentRoom; + if (PhotonNetwork.OfflineMode || currentRoom == null || currentRoom.Players == null) + { + return; + } + bool flag = (flags & SerializationFlags.SendToSelf) != 0; + if (flag || SettingsScriptableObject<TickEngineSettings>.single.sendWhenSolo || currentRoom.Players.Count > 1) + { + ReceiveGroup receiveGroup = (flag ? ReceiveGroup.All : ReceiveGroup.Others); + int count = bitposition + 7 >> 3; + LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient; + DeliveryMode deliveryMode; + if (newPlayers.Count > 0) + { + deliveryMode = DeliveryMode.Reliable; + newPlayers.Clear(); + } + else + { + bool flag2 = (flags & SerializationFlags.ForceReliable) != 0; + deliveryMode = ((!unreliableCapable) ? DeliveryMode.Reliable : (flag2 ? DeliveryMode.ReliableUnsequenced : DeliveryMode.Unreliable)); + } + SendOptions sendOptions = default(SendOptions); + sendOptions.DeliveryMode = deliveryMode; + SendOptions sendOptions2 = sendOptions; + ByteArraySlice customEventContent = PhotonNetwork.NetworkingClient.LoadBalancingPeer.ByteArraySlicePool.Acquire(buffer, 0, count); + networkingClient.OpRaiseEvent(215, customEventContent, opts[(int)receiveGroup], sendOptions2); + if (flush) + { + networkingClient.Service(); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/NetObjColliderExt.cs b/ROUNDS/Photon.Pun.Simple.Internal/NetObjColliderExt.cs new file mode 100644 index 0000000..06e8e5f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/NetObjColliderExt.cs @@ -0,0 +1,152 @@ +using System.Collections.Generic; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple.Internal; + +public static class NetObjColliderExt +{ + public static readonly List<Component> reusableComponents = new List<Component>(); + + public static readonly List<Collider> reusableColliders = new List<Collider>(); + + public static readonly List<Collider2D> reusableColliders2D = new List<Collider2D>(); + + public static void IndexColliders(this NetObject netObj) + { + List<Component> indexedColliders = netObj.indexedColliders; + Dictionary<Component, int> colliderLookup = netObj.colliderLookup; + colliderLookup.Clear(); + indexedColliders.Clear(); + netObj.transform.GetNestedComponentsInChildren<Component, NetObject>(reusableComponents); + int count = reusableComponents.Count; + for (int i = 0; i < count; i++) + { + Component component = reusableComponents[i]; + if ((bool)(component as Collider)) + { + indexedColliders.Add(component); + } + else if ((bool)(component as Collider2D)) + { + indexedColliders.Add(component); + } + } + int j = 0; + for (int count2 = indexedColliders.Count; j < count2; j++) + { + colliderLookup.Add(indexedColliders[j], j); + } + netObj.bitsForColliderIndex = (indexedColliders.Count - 1).GetBitsForMaxValue(); + } + + public static int GetFirstChildCollider(this Transform transform, ref Component firstFoundCollider, bool countTriggers, bool countNonTriggers) + { + if (!countTriggers && !countNonTriggers) + { + Debug.LogError("Counting Colliders, but args indicate to ignore everything. Set one to true."); + firstFoundCollider = null; + return 0; + } + transform.GetComponentsInChildren(includeInactive: true, reusableColliders); + int count = reusableColliders.Count; + if (count > 0) + { + if (countTriggers && countNonTriggers) + { + firstFoundCollider = reusableColliders[0]; + return count; + } + int num = 0; + firstFoundCollider = null; + for (int i = 0; i < count; i++) + { + Collider collider = reusableColliders[i]; + if (countTriggers ? collider.isTrigger : (!collider.isTrigger)) + { + if (firstFoundCollider == null) + { + firstFoundCollider = collider; + } + num++; + } + } + return num; + } + transform.GetComponentsInChildren(includeInactive: true, reusableColliders2D); + int count2 = reusableColliders2D.Count; + if (count2 > 0) + { + if (countTriggers && countNonTriggers) + { + firstFoundCollider = reusableColliders[0]; + return count; + } + int num2 = 0; + firstFoundCollider = null; + for (int j = 0; j < count2; j++) + { + Collider2D collider2D = reusableColliders2D[j]; + if (countTriggers ? collider2D.isTrigger : (!collider2D.isTrigger)) + { + if (firstFoundCollider == null) + { + firstFoundCollider = collider2D; + } + num2++; + } + } + return num2; + } + firstFoundCollider = null; + return 0; + } + + public static int CountChildCollider(this Transform transform, bool countTriggers, bool countNonTriggers) + { + if (!countTriggers && !countNonTriggers) + { + Debug.LogError("Counting Colliders, but args indicate to ignore everything. Set one to true."); + return 0; + } + transform.GetComponentsInChildren(includeInactive: true, reusableColliders); + int count = reusableColliders.Count; + if (count > 0) + { + if (countTriggers && countNonTriggers) + { + return count; + } + int num = 0; + for (int i = 0; i < count; i++) + { + Collider collider = reusableColliders[i]; + if (countTriggers ? collider.isTrigger : (!collider.isTrigger)) + { + num++; + } + } + return num; + } + transform.GetComponentsInChildren(includeInactive: true, reusableColliders2D); + int count2 = reusableColliders2D.Count; + if (count2 > 0) + { + if (countTriggers && countNonTriggers) + { + return count; + } + int num2 = 0; + for (int j = 0; j < count2; j++) + { + Collider2D collider2D = reusableColliders2D[j]; + if (countTriggers ? collider2D.isTrigger : (!collider2D.isTrigger)) + { + num2++; + } + } + return num2; + } + return 0; + } +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/ParameterDefaults.cs b/ROUNDS/Photon.Pun.Simple.Internal/ParameterDefaults.cs new file mode 100644 index 0000000..f41e27f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/ParameterDefaults.cs @@ -0,0 +1,36 @@ +using System; +using Photon.Utilities; + +namespace Photon.Pun.Simple.Internal; + +[Serializable] +public class ParameterDefaults +{ + public ParameterInterpolation interpolateFloats = ParameterInterpolation.Hold; + + public ParameterInterpolation interpolateInts = ParameterInterpolation.Hold; + + public ParameterExtrapolation extrapolateFloats = ParameterExtrapolation.Hold; + + public ParameterExtrapolation extrapolateInts = ParameterExtrapolation.Hold; + + public ParameterExtrapolation extrapolateBools = ParameterExtrapolation.Hold; + + public ParameterExtrapolation extrapolateTriggers; + + public bool includeFloats = true; + + public bool includeInts = true; + + public bool includeBools = true; + + public bool includeTriggers; + + public SmartVar defaultFloat = 0f; + + public SmartVar defaultInt = 0; + + public SmartVar defaultBool = false; + + public SmartVar defaultTrigger = false; +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/ParameterExtrapolation.cs b/ROUNDS/Photon.Pun.Simple.Internal/ParameterExtrapolation.cs new file mode 100644 index 0000000..db9bad0 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/ParameterExtrapolation.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple.Internal; + +public enum ParameterExtrapolation +{ + Default, + Hold, + Lerp +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/ParameterInterpolation.cs b/ROUNDS/Photon.Pun.Simple.Internal/ParameterInterpolation.cs new file mode 100644 index 0000000..ad5c36e --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/ParameterInterpolation.cs @@ -0,0 +1,9 @@ +namespace Photon.Pun.Simple.Internal; + +public enum ParameterInterpolation +{ + Default, + Hold, + Lerp, + Advance +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/ParameterMissingHold.cs b/ROUNDS/Photon.Pun.Simple.Internal/ParameterMissingHold.cs new file mode 100644 index 0000000..944bc6e --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/ParameterMissingHold.cs @@ -0,0 +1,7 @@ +namespace Photon.Pun.Simple.Internal; + +public enum ParameterMissingHold +{ + Default, + Hold +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/ParameterSettings.cs b/ROUNDS/Photon.Pun.Simple.Internal/ParameterSettings.cs new file mode 100644 index 0000000..fada75a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/ParameterSettings.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using Photon.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple.Internal; + +[Serializable] +public class ParameterSettings +{ + public int hash; + + public AnimatorControllerParameterType paramType; + + public bool include; + + public ParameterInterpolation interpolate; + + public ParameterExtrapolation extrapolate; + + public SmartVar defaultValue; + + public LiteFloatCrusher fcrusher; + + public LiteIntCrusher icrusher; + + private static readonly List<int> rebuiltHashes = new List<int>(); + + private static readonly List<ParameterSettings> rebuiltSettings = new List<ParameterSettings>(); + + public ParameterSettings(int hash, ParameterDefaults defs, ref int paramCount, AnimatorControllerParameterType paramType) + { + this.hash = hash; + this.paramType = paramType; + switch (paramType) + { + case AnimatorControllerParameterType.Float: + include = defs.includeFloats; + interpolate = defs.interpolateFloats; + extrapolate = defs.extrapolateFloats; + defaultValue = (float)defs.defaultFloat; + fcrusher = new LiteFloatCrusher(LiteFloatCompressType.Half16, 0f, 1f, accurateCenter: true); + break; + case AnimatorControllerParameterType.Int: + include = defs.includeInts; + interpolate = defs.interpolateInts; + extrapolate = defs.extrapolateInts; + defaultValue = (int)defs.defaultInt; + icrusher = new LiteIntCrusher(); + break; + case AnimatorControllerParameterType.Bool: + include = defs.includeBools; + interpolate = ParameterInterpolation.Hold; + extrapolate = ParameterExtrapolation.Hold; + defaultValue = (bool)defs.defaultBool; + break; + case AnimatorControllerParameterType.Trigger: + include = defs.includeTriggers; + interpolate = ParameterInterpolation.Default; + extrapolate = ParameterExtrapolation.Default; + defaultValue = (bool)defs.defaultTrigger; + break; + } + } + + public static List<string> RebuildParamSettings(Animator a, ref ParameterSettings[] paraSettings, ref int paramCount, ParameterDefaults defs) + { + AnimatorControllerParameter[] parameters = a.parameters; + rebuiltHashes.Clear(); + rebuiltSettings.Clear(); + bool flag = false; + paramCount = parameters.Length; + for (int i = 0; i < paramCount; i++) + { + AnimatorControllerParameter animatorControllerParameter = parameters[i]; + int nameHash = animatorControllerParameter.nameHash; + int hashIndex = GetHashIndex(paraSettings, nameHash); + if (hashIndex != i) + { + flag = true; + } + rebuiltHashes.Add(nameHash); + rebuiltSettings.Add((hashIndex == -1) ? new ParameterSettings(nameHash, defs, ref paramCount, animatorControllerParameter.type) : paraSettings[hashIndex]); + } + if (flag) + { + paraSettings = rebuiltSettings.ToArray(); + } + return null; + } + + private static int GetHashIndex(ParameterSettings[] ps, int lookfor) + { + int i = 0; + for (int num = ps.Length; i < num; i++) + { + if (ps[i].hash == lookfor) + { + return i; + } + } + return -1; + } +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/ReceiveGroup.cs b/ROUNDS/Photon.Pun.Simple.Internal/ReceiveGroup.cs new file mode 100644 index 0000000..ffd067f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/ReceiveGroup.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple.Internal; + +public enum ReceiveGroup +{ + Others, + All, + Master +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/SimpleDocsURLS.cs b/ROUNDS/Photon.Pun.Simple.Internal/SimpleDocsURLS.cs new file mode 100644 index 0000000..a4bef33 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/SimpleDocsURLS.cs @@ -0,0 +1,22 @@ +namespace Photon.Pun.Simple.Internal; + +public static class SimpleDocsURLS +{ + public const string CORE_PATH = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/"; + + public const string OVERVIEW_PATH = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simpleoverview"; + + public const string SYNCCOMPS_PATH = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplecoresynccomponents"; + + public const string SUBSYS_PATH = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplesubsystems"; + + public const string CORE_OBJS_PATH = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplecoreobjects"; + + public const string PACK_OBJS_PATH = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplepackobjects"; + + public const string CONTACT_SYSTEM = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplesubsystems#contact_system"; + + public const string MOUNT_SYSTEM = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplesubsystems#mount_system"; + + public const string TICK_SETTINGS = "https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplecoreobjects#tick_engine_settings"; +} diff --git a/ROUNDS/Photon.Pun.Simple.Internal/TickManager.cs b/ROUNDS/Photon.Pun.Simple.Internal/TickManager.cs new file mode 100644 index 0000000..2026ae0 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Internal/TickManager.cs @@ -0,0 +1,167 @@ +using System.Collections.Generic; +using ExitGames.Client.Photon; +using Photon.Realtime; +using UnityEngine; + +namespace Photon.Pun.Simple.Internal; + +public class TickManager : IInRoomCallbacks +{ + public static readonly Dictionary<int, ConnectionTickOffsets> perConnOffsets = new Dictionary<int, ConnectionTickOffsets>(); + + public static readonly List<int> connections = new List<int>(); + + public static TickManager single; + + public static bool needToSendInitialForNewConn; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + public static void Bootstrap() + { + single = new TickManager(); + PhotonNetwork.NetworkingClient.AddCallbackTarget(single); + } + + public void OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer) + { + AddConnection(newPlayer.ActorNumber); + } + + public void OnPlayerLeftRoom(Photon.Realtime.Player otherPlayer) + { + RemoveConnection(otherPlayer.ActorNumber); + } + + public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) + { + } + + public void OnPlayerPropertiesUpdate(Photon.Realtime.Player targetPlayer, Hashtable changedProps) + { + } + + public void OnMasterClientSwitched(Photon.Realtime.Player newMasterClient) + { + } + + public static void PreSnapshot(int currentFrameId) + { + for (int i = 0; i < connections.Count; i++) + { + if (perConnOffsets[connections[i]] != null) + { + ConnectionTickOffsets connectionTickOffsets = perConnOffsets[connections[i]]; + int num = connectionTickOffsets.ConvertFrameLocalToOrigin(currentFrameId); + float num2 = (connectionTickOffsets.validFrameMask[num] ? (Time.time - connectionTickOffsets.frameArriveTime[num]) : (-1f)); + connectionTickOffsets.frameTimeBeforeConsumption[num] = num2; + connectionTickOffsets.SnapshotAdvance(); + } + } + } + + public static void PostSnapshot(int currentFrameId) + { + for (int i = 0; i < connections.Count; i++) + { + if (perConnOffsets[connections[i]] != null) + { + perConnOffsets[connections[i]].PostSnapshot(); + } + } + } + + public static ConnectionTickOffsets LogIncomingFrame(int connId, int originFrameId, out FrameArrival arrival) + { + int frameCount = TickEngineSettings.frameCount; + if (!perConnOffsets.TryGetValue(connId, out var value) || value == null) + { + LogNewConnection(connId, originFrameId, frameCount, out value); + } + int num = originFrameId + value.originToLocalFrame; + if (num >= frameCount) + { + num -= frameCount; + } + value.frameArriveTime[originFrameId] = Time.time; + int currentFrameId = NetMaster.CurrentFrameId; + int num2; + if (num == currentFrameId) + { + num2 = 0; + } + else + { + num2 = currentFrameId - num; + if (num2 < 0) + { + num2 += frameCount; + } + if (num2 >= TickEngineSettings.halfFrameCount) + { + num2 -= frameCount; + } + } + if (num2 >= 0) + { + if (num2 != 0 && num2 != 1 && num2 < TickEngineSettings.halfFrameCount) + { + } + } + else + { + _ = -TickEngineSettings.halfFrameCount; + } + arrival = (FrameArrival)num2; + bool flag = num2 <= 0; + value.frameArrivedTooLate |= !flag; + value.validFrameMask.Set(originFrameId, value: true); + return value; + } + + private static void LogNewConnection(int connId, int originFrameId, int frameCount, out ConnectionTickOffsets offsets) + { + int num; + for (num = NetMaster.CurrentFrameId + TickEngineSettings.targetBufferSize; num >= frameCount; num -= frameCount) + { + } + int num2 = num - originFrameId; + if (num2 < 0) + { + num2 += frameCount; + } + int num3 = frameCount - num2; + if (num3 < 0) + { + num3 += frameCount; + } + offsets = new ConnectionTickOffsets(connId, num2, num3); + AddConnection(connId, offsets); + } + + private static void AddConnection(int connId, ConnectionTickOffsets offsets = null) + { + if (PhotonNetwork.LocalPlayer.ActorNumber != connId) + { + if (!connections.Contains(connId)) + { + perConnOffsets.Add(connId, offsets); + connections.Add(connId); + NetMsgSends.newPlayers.Add(connId); + needToSendInitialForNewConn = true; + } + else + { + perConnOffsets[connId] = offsets; + } + } + } + + public static void RemoveConnection(int connId) + { + if (perConnOffsets.ContainsKey(connId)) + { + perConnOffsets.Remove(connId); + connections.Remove(connId); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple.Pooling/Pool.cs b/ROUNDS/Photon.Pun.Simple.Pooling/Pool.cs new file mode 100644 index 0000000..992b1f7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple.Pooling/Pool.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple.Pooling; + +public class Pool : MonoBehaviour +{ + private struct PoolItemDef + { + public GameObject prefab; + + public int growBy; + + public Type scriptToAdd; + + public PoolItemDef(GameObject prefab, int growBy, Type scriptToAdd) + { + this.prefab = prefab; + this.growBy = growBy; + this.scriptToAdd = scriptToAdd; + } + } + + private static Dictionary<GameObject, Stack<Pool>> pools = new Dictionary<GameObject, Stack<Pool>>(); + + private static Dictionary<GameObject, PoolItemDef> poolItemDefs = new Dictionary<GameObject, PoolItemDef>(); + + [HideInInspector] + public GameObject origPrefab; + + [HideInInspector] + public Rigidbody rb; + + [HideInInspector] + public Component extraScript; + + public float deathClock; + + public static void AddPrefabToPool(GameObject _prefab, int startingSize = 8, int _growBy = 8, Type _scriptToAdd = null, bool tidyUp = false) + { + if (!poolItemDefs.ContainsKey(_prefab)) + { + pools.Add(_prefab, new Stack<Pool>()); + PoolItemDef value = new PoolItemDef(_prefab, _growBy, _scriptToAdd); + poolItemDefs.Add(_prefab, value); + GrowPool(_prefab, startingSize); + if (tidyUp) + { + _prefab.gameObject.SetActive(value: false); + } + } + } + + public static Pool Spawn(GameObject origPrefab, Transform t, float duration = 5f) + { + return Spawn(origPrefab, t.position, t.rotation, duration); + } + + public static Pool Spawn(GameObject origPrefab, Vector3 pos, Quaternion rot, Vector3 scl, float duration = 5f) + { + Pool pool = Spawn(origPrefab, pos, rot, duration); + pool.gameObject.transform.localScale = scl; + return pool; + } + + public static Pool Spawn(GameObject origPrefab, Vector3 pos, Quaternion rot, float duration = 5f) + { + if (pools[origPrefab].Count == 0) + { + GrowPool(origPrefab); + } + if (!pools[origPrefab].Peek()) + { + pools[origPrefab].Clear(); + GrowPool(origPrefab); + } + Pool pool = pools[origPrefab].Pop(); + pool.transform.position = pos; + pool.transform.rotation = rot; + pool.deathClock = duration; + pool.enabled = duration > 0f; + pool.gameObject.SetActive(value: true); + return pool; + } + + private static void GrowPool(GameObject _prefab, int growAmt = -1) + { + PoolItemDef def = poolItemDefs[_prefab]; + int num = ((growAmt < 1) ? def.growBy : growAmt); + for (int i = 0; i < num; i++) + { + AddItemToPool(UnityEngine.Object.Instantiate(def.prefab), _prefab, def); + } + } + + private static void AddItemToPool(GameObject go, GameObject _prefab, PoolItemDef def) + { + go.SetActive(value: false); + Pool pool = go.AddComponent<Pool>(); + pool.CacheComponents(); + if (def.scriptToAdd != null && go.GetComponent(def.scriptToAdd) == null) + { + pool.extraScript = go.AddComponent(def.scriptToAdd); + } + pool.origPrefab = _prefab; + pools[_prefab].Push(pool); + } + + private static void ReturnToPool(Pool p, GameObject _prefab) + { + pools[_prefab].Push(p); + } + + public void CacheComponents() + { + rb = GetComponent<Rigidbody>(); + } + + private void Update() + { + deathClock -= TimeHandler.deltaTime; + if (deathClock < 0f) + { + base.gameObject.SetActive(value: false); + } + } + + private void OnDisable() + { + ReturnToPool(this, origPrefab); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AnimPassThru.cs b/ROUNDS/Photon.Pun.Simple/AnimPassThru.cs new file mode 100644 index 0000000..739da08 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AnimPassThru.cs @@ -0,0 +1,29 @@ +namespace Photon.Pun.Simple; + +public struct AnimPassThru +{ + public PassThruType passThruType; + + public int hash; + + public float normlTime; + + public float fixedTime; + + public float duration; + + public int layer; + + public LocalApplyTiming localApplyTiming; + + public AnimPassThru(PassThruType triggerType, int hash, int layer, float normTime, float otherTime, float duration, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + passThruType = triggerType; + this.hash = hash; + normlTime = normTime; + fixedTime = otherTime; + this.duration = duration; + this.layer = layer; + this.localApplyTiming = localApplyTiming; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ApplyOrderConstants.cs b/ROUNDS/Photon.Pun.Simple/ApplyOrderConstants.cs new file mode 100644 index 0000000..c55fff5 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ApplyOrderConstants.cs @@ -0,0 +1,26 @@ +namespace Photon.Pun.Simple; + +public static class ApplyOrderConstants +{ + public const int MAX_ORDER_VAL = 24; + + public const int COLLISIONS = 2; + + public const int STATE_TIMER = 3; + + public const int STATES = 5; + + public const int TRANSFORM = 9; + + public const int ANIMATOR = 11; + + public const int DEFAULT = 13; + + public const int VITALS = 15; + + public const int HITSCAN = 17; + + public const int WEAPONS = 19; + + public const int OWNERSHIP = 21; +} diff --git a/ROUNDS/Photon.Pun.Simple/AutoDestroyUnspawned.cs b/ROUNDS/Photon.Pun.Simple/AutoDestroyUnspawned.cs new file mode 100644 index 0000000..bab0506 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AutoDestroyUnspawned.cs @@ -0,0 +1,26 @@ +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace Photon.Pun.Simple; + +[DisallowMultipleComponent] +public class AutoDestroyUnspawned : MonoBehaviour +{ + public bool onlyIfPrefab = true; + + public bool hasPrefabParent; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + public static void DestroyUnspawned() + { + AutoDestroyUnspawned[] array = Object.FindObjectsOfType<AutoDestroyUnspawned>(); + for (int num = array.Length - 1; num >= 0; num--) + { + AutoDestroyUnspawned autoDestroyUnspawned = array[num]; + if ((!autoDestroyUnspawned.onlyIfPrefab || autoDestroyUnspawned.hasPrefabParent) && autoDestroyUnspawned.gameObject.scene == SceneManager.GetActiveScene()) + { + Object.Destroy(autoDestroyUnspawned.gameObject); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AutoLayerByAuthority.cs b/ROUNDS/Photon.Pun.Simple/AutoLayerByAuthority.cs new file mode 100644 index 0000000..89dd1f3 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AutoLayerByAuthority.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class AutoLayerByAuthority : MonoBehaviour +{ + public int authorityLayer = 8; + + public int nonAuthorityLayer = 9; + + public int projectileLayer = 10; + + public bool applyToChildren = true; + + private void Awake() + { + Physics.IgnoreLayerCollision(authorityLayer, projectileLayer); + if (applyToChildren) + { + SetChildrenLayer(base.transform, projectileLayer); + } + else + { + base.gameObject.layer = projectileLayer; + } + } + + public void OnChangeAuthority(bool IsMine, bool serverIsActive) + { + Debug.Log("Auth change " + base.name); + int layer = (IsMine ? authorityLayer : nonAuthorityLayer); + if (applyToChildren) + { + SetChildrenLayer(base.transform, layer); + } + else + { + base.gameObject.layer = layer; + } + } + + public void SetChildrenLayer(Transform t, int layer) + { + t.gameObject.layer = layer; + for (int i = 0; i < t.childCount; i++) + { + if (!t.GetChild(i).GetComponent<AutoLayerByAuthority>()) + { + SetChildrenLayer(t.GetChild(i), layer); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AutoMountHitscan.cs b/ROUNDS/Photon.Pun.Simple/AutoMountHitscan.cs new file mode 100644 index 0000000..7b0c451 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AutoMountHitscan.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class AutoMountHitscan : HitscanComponent +{ + protected SyncState syncState; + + private Queue<Mount> foundMounts = new Queue<Mount>(); + + public SyncState SyncState => syncState; + + public override void OnAwake() + { + base.OnAwake(); + if ((bool)netObj) + { + syncState = netObj.GetComponent<SyncState>(); + } + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + List<IOnPreSimulate> onPreSimulateCallbacks = netObj.onPreSimulateCallbacks; + bool flag = onPreSimulateCallbacks.Contains(this); + base.OnAuthorityChanged(isMine, controllerChanged); + if (isMine) + { + if (!flag) + { + onPreSimulateCallbacks.Add(this); + } + } + else if (flag) + { + onPreSimulateCallbacks.Remove(this); + } + } + + public override void OnPreSimulate(int frameId, int subFrameId) + { + if (subFrameId != TickEngineSettings.sendEveryXTick - 1) + { + return; + } + triggerQueued = true; + base.OnPreSimulate(frameId, subFrameId); + if (foundMounts.Count != 0) + { + do + { + Mount attachTo = foundMounts.Dequeue(); + syncState.SoftMount(attachTo); + } + while (foundMounts.Count != 0); + } + else + { + syncState.SoftMount(null); + } + } + + public override bool ProcessHit(Collider hit) + { + Mount nestedComponentInParents = hit.transform.GetNestedComponentInParents<Mount, NetObject>(); + if ((bool)nestedComponentInParents) + { + foundMounts.Enqueue(nestedComponentInParents); + } + return false; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AutoOwnerComponentEnable.cs b/ROUNDS/Photon.Pun.Simple/AutoOwnerComponentEnable.cs new file mode 100644 index 0000000..cae26c7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AutoOwnerComponentEnable.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class AutoOwnerComponentEnable : NetComponent, IOnAuthorityChanged +{ + public enum EnableIf + { + Ignore, + Owner, + Other + } + + [Serializable] + public class ComponentToggle + { + public Behaviour component; + + public EnableIf enableIfOwned = EnableIf.Owner; + } + + public bool includeChildren = true; + + public bool includeUnity = true; + + public bool includePhoton; + + public bool includeSimple; + + [HideInInspector] + [SerializeField] + private List<ComponentToggle> componentToggles = new List<ComponentToggle>(); + + [HideInInspector] + [SerializeField] + private List<Behaviour> componentLookup = new List<Behaviour>(); + + public override void OnStart() + { + base.OnStart(); + SwitchAuth(base.IsMine); + } + + public override void OnJoinedRoom() + { + base.OnJoinedRoom(); + SwitchAuth(base.IsMine); + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + SwitchAuth(isMine); + } + + private void SwitchAuth(bool isMine) + { + for (int i = 0; i < componentToggles.Count; i++) + { + ComponentToggle componentToggle = componentToggles[i]; + if (componentToggle != null && componentToggle.enableIfOwned != 0 && componentToggle.component != null) + { + componentToggle.component.enabled = ((componentToggle.enableIfOwned == EnableIf.Owner) ? isMine : (!isMine)); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AutoOwnerGameObjEnable.cs b/ROUNDS/Photon.Pun.Simple/AutoOwnerGameObjEnable.cs new file mode 100644 index 0000000..a1ccacd --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AutoOwnerGameObjEnable.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class AutoOwnerGameObjEnable : MonoBehaviour, IOnAuthorityChanged +{ + public enum EnableIf + { + Owner, + Other + } + + public EnableIf enableIf; + + public void Start() + { + PhotonView componentInParent = GetComponentInParent<PhotonView>(); + if ((bool)componentInParent) + { + SwitchAuth(componentInParent.IsMine); + } + } + + public void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + Debug.Log("AuthChanged"); + SwitchAuth(isMine); + } + + private void SwitchAuth(bool isMine) + { + base.gameObject.SetActive((enableIf == EnableIf.Owner) ? isMine : (!isMine)); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AutoZoom.cs b/ROUNDS/Photon.Pun.Simple/AutoZoom.cs new file mode 100644 index 0000000..72f9e26 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AutoZoom.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using emotitron.Utilities.GUIUtilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class AutoZoom : MonoBehaviour +{ + public static List<Transform> watched = new List<Transform>(); + + public const float MAX_FOV = 75f; + + public const float MIN_FOV = 15f; + + [Range(0.1f, 0.5f)] + [HideInInspector] + public float window = 0.25f; + + [ValueType("/sec", 48f)] + [HideInInspector] + public float panRate = 20f; + + [ValueType("/sec", 48f)] + [HideInInspector] + public float zoomRate = 200f; + + private Camera cam; + + private void Awake() + { + cam = GetComponent<Camera>(); + if (!cam) + { + watched.Add(base.transform); + } + } + + private void OnDestroy() + { + if (watched.Contains(base.transform)) + { + watched.Remove(base.transform); + } + } + + private void LateUpdate() + { + if ((bool)cam && cam.isActiveAndEnabled) + { + Bounds bounds = default(Bounds); + for (int i = 0; i < watched.Count; i++) + { + Vector2 vector = cam.WorldToViewportPoint(watched[i].position); + bounds.Encapsulate(vector + new Vector2(-0.5f, -0.5f)); + } + if (watched.Count > 0) + { + cam.transform.Rotate(new Vector3(0f, 1f, 0f), bounds.center.x * Time.deltaTime * panRate); + float num = bounds.extents.x - window; + float num2 = bounds.extents.y - window; + float num3 = ((num > num2) ? num : num2); + float value = cam.fieldOfView + num3 * Time.deltaTime * zoomRate; + cam.fieldOfView = Mathf.Clamp(value, 15f, 75f); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/AxisMask.cs b/ROUNDS/Photon.Pun.Simple/AxisMask.cs new file mode 100644 index 0000000..8ff25e7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/AxisMask.cs @@ -0,0 +1,13 @@ +namespace Photon.Pun.Simple; + +public enum AxisMask +{ + None, + X, + Y, + XY, + Z, + XZ, + YZ, + XYZ +} diff --git a/ROUNDS/Photon.Pun.Simple/BasicInventory.cs b/ROUNDS/Photon.Pun.Simple/BasicInventory.cs new file mode 100644 index 0000000..157be30 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/BasicInventory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class BasicInventory : Inventory<Vector3Int> +{ + [SerializeField] + public Vector3Int capacity = new Vector3Int(16, 1, 1); + + public int Volume => capacity.x * capacity.y * capacity.z; + + public int Used + { + get + { + int num = 0; + List<IMountable> mountedObjs = base.DefaultMount.mountedObjs; + int i = 0; + for (int count = mountedObjs.Count; i < count; i++) + { + if (mountedObjs[i] is IInventoryable<Vector3Int> inventoryable) + { + Vector3Int size = inventoryable.Size; + int num2 = size.x * size.y * size.z; + num += num2; + } + } + return num; + } + } + + public int Remaining => Volume - Used; + + public override bool TestCapacity(IInventoryable<Vector3Int> inventoryable) + { + Vector3Int size = inventoryable.Size; + return size.x * size.y * size.z <= Remaining; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ConnectionTickOffsets.cs b/ROUNDS/Photon.Pun.Simple/ConnectionTickOffsets.cs new file mode 100644 index 0000000..1d4e8a5 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ConnectionTickOffsets.cs @@ -0,0 +1,172 @@ +using Photon.Utilities; + +namespace Photon.Pun.Simple; + +public class ConnectionTickOffsets +{ + public int connId; + + public int originToLocalFrame; + + public int localToOriginFrame; + + public int numOfSequentialFramesWithTooSmallBuffer; + + public int numOfSequentialFramesWithTooLargeBuffer; + + public bool frameArrivedTooLate; + + public bool hadInitialSnapshot; + + public int advanceCount; + + public float[] frameArriveTime; + + public float[] frameTimeBeforeConsumption; + + public FastBitMask128 validFrameMask; + + public int ConvertFrameLocalToOrigin(int localFrameId) + { + int frameCount = TickEngineSettings.frameCount; + int num = localFrameId + localToOriginFrame; + if (num >= frameCount) + { + num -= frameCount; + } + return num; + } + + public int ConvertFrameOriginToLocal(int originFrameId) + { + int frameCount = TickEngineSettings.frameCount; + int num = originFrameId + originToLocalFrame; + if (num >= frameCount) + { + num -= frameCount; + } + return num; + } + + public ConnectionTickOffsets(int connId, int originToLocal, int localToOrigin) + { + this.connId = connId; + originToLocalFrame = originToLocal; + localToOriginFrame = localToOrigin; + int frameCount = TickEngineSettings.frameCount; + validFrameMask = new FastBitMask128(frameCount + 1); + frameArriveTime = new float[frameCount]; + frameTimeBeforeConsumption = new float[frameCount]; + for (int i = 0; i < frameCount; i++) + { + frameTimeBeforeConsumption[i] = float.PositiveInfinity; + } + } + + public void SnapshotAdvance() + { + int frameCount = TickEngineSettings.frameCount; + int num = NetMaster.CurrentFrameId + localToOriginFrame; + if (num >= frameCount) + { + num -= frameCount; + } + int num2 = validFrameMask.CountValidRange(num, TickEngineSettings.quaterFrameCount); + if (!hadInitialSnapshot) + { + if (num2 == 0) + { + advanceCount = 0; + return; + } + if (num2 > TickEngineSettings.targetBufferSize) + { + advanceCount = num2 - TickEngineSettings.targetBufferSize; + return; + } + } + if (num2 == 0) + { + if (frameArrivedTooLate) + { + numOfSequentialFramesWithTooLargeBuffer = 0; + numOfSequentialFramesWithTooSmallBuffer = 0; + frameArrivedTooLate = false; + advanceCount = 0; + return; + } + numOfSequentialFramesWithTooLargeBuffer = 0; + advanceCount = 1; + } + else if (num2 < TickEngineSettings.minBufferSize) + { + numOfSequentialFramesWithTooLargeBuffer = 0; + numOfSequentialFramesWithTooSmallBuffer += ((!frameArrivedTooLate) ? 1 : 2); + frameArrivedTooLate = false; + if (numOfSequentialFramesWithTooSmallBuffer >= TickEngineSettings.ticksBeforeGrow) + { + advanceCount = 0; + return; + } + advanceCount = 1; + } + else if (num2 > TickEngineSettings.maxBufferSize) + { + numOfSequentialFramesWithTooSmallBuffer = 0; + if (numOfSequentialFramesWithTooLargeBuffer > TickEngineSettings.ticksBeforeGrow) + { + advanceCount = num2 - TickEngineSettings.targetBufferSize + 1; + numOfSequentialFramesWithTooLargeBuffer = 0; + } + else + { + advanceCount = 1; + numOfSequentialFramesWithTooLargeBuffer++; + } + } + else + { + numOfSequentialFramesWithTooLargeBuffer = 0; + numOfSequentialFramesWithTooSmallBuffer = (frameArrivedTooLate ? 1 : 0); + advanceCount = 1; + } + frameArrivedTooLate = false; + } + + public void PostSnapshot() + { + int frameCount = TickEngineSettings.frameCount; + int num = NetMaster.CurrentFrameId + localToOriginFrame; + if (num >= frameCount) + { + num -= frameCount; + } + int num2 = num - TickEngineSettings.quaterFrameCount; + if (num2 < 0) + { + num2 += frameCount; + } + validFrameMask.ClearBitsBefore(num2, TickEngineSettings.quaterFrameCount); + if (advanceCount > 0) + { + hadInitialSnapshot = true; + } + if (advanceCount != 1) + { + localToOriginFrame += advanceCount - 1; + if (localToOriginFrame < 0) + { + localToOriginFrame += frameCount; + } + else if (localToOriginFrame >= frameCount) + { + localToOriginFrame -= frameCount; + } + originToLocalFrame = frameCount - localToOriginFrame; + if (originToLocalFrame < 0) + { + originToLocalFrame += frameCount; + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ConsumedDespawn.cs b/ROUNDS/Photon.Pun.Simple/ConsumedDespawn.cs new file mode 100644 index 0000000..0c0a79a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ConsumedDespawn.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum ConsumedDespawn +{ + Never, + OnPartial, + OnDepleted +} diff --git a/ROUNDS/Photon.Pun.Simple/Consumption.cs b/ROUNDS/Photon.Pun.Simple/Consumption.cs new file mode 100644 index 0000000..ee4090f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Consumption.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum Consumption +{ + None = 0, + Partial = 1, + All = 3 +} diff --git a/ROUNDS/Photon.Pun.Simple/ContactEvent.cs b/ROUNDS/Photon.Pun.Simple/ContactEvent.cs new file mode 100644 index 0000000..0704512 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ContactEvent.cs @@ -0,0 +1,24 @@ +namespace Photon.Pun.Simple; + +public struct ContactEvent +{ + public readonly IContactSystem contactSystem; + + public readonly IContactTrigger contactTrigger; + + public readonly ContactType contactType; + + public ContactEvent(IContactSystem contactSystem, IContactTrigger contacter, ContactType contactType) + { + this.contactSystem = contactSystem; + contactTrigger = contacter; + this.contactType = contactType; + } + + public ContactEvent(ContactEvent contactEvent) + { + contactSystem = contactEvent.contactSystem; + contactTrigger = contactEvent.contactTrigger; + contactType = contactEvent.contactType; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ContactManager.cs b/ROUNDS/Photon.Pun.Simple/ContactManager.cs new file mode 100644 index 0000000..d140894 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ContactManager.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class ContactManager : MonoBehaviour +{ + public List<IContactSystem> contactSystems = new List<IContactSystem>(0); + + public List<IContactTrigger> contactTriggers = new List<IContactTrigger>(0); + + public void Awake() + { + base.transform.GetNestedComponentsInChildren<IContactSystem, NetObject>(contactSystems); + base.transform.GetNestedComponentsInChildren<IContactTrigger, NetObject>(contactTriggers); + int count = contactSystems.Count; + if (count > 255) + { + throw new IndexOutOfRangeException("NetObjects may not have more than 255 IContactSystem components on them."); + } + for (byte b = 0; b < count; b = (byte)(b + 1)) + { + contactSystems[b].SystemIndex = b; + } + } + + public IContactSystem GetContacting(int index) + { + return contactSystems[index]; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ContactProjectile.cs b/ROUNDS/Photon.Pun.Simple/ContactProjectile.cs new file mode 100644 index 0000000..77eaafa --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ContactProjectile.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class ContactProjectile : MonoBehaviour, IProjectile, IOnPreSimulate, IOnPreUpdate +{ + protected IProjectileCannon owner; + + [NonSerialized] + public Vector3 velocity; + + [NonSerialized] + public int frameId; + + [NonSerialized] + public int subFrameId; + + [SerializeField] + [EnumMask(false, null)] + protected RespondTo terminateOn = (RespondTo)14; + + [SerializeField] + [EnumMask(false, null)] + protected RespondTo damageOn = (RespondTo)14; + + protected Rigidbody rb; + + protected Rigidbody2D rb2d; + + protected bool _hasRigidBody; + + protected bool needsSnapshot; + + protected IContactTrigger localContactTrigger; + + protected bool useRbForces; + + protected bool useRb2dForces; + + protected bool useRBGravity; + + public List<IOnNetworkHit> onHit = new List<IOnNetworkHit>(); + + public List<IOnTerminate> onTerminate = new List<IOnTerminate>(); + + private Vector3 snapPos; + + private Vector3 targPos; + + private Quaternion snapRot; + + private Quaternion targRot; + + protected static List<NetObject> reusableNetObjects = new List<NetObject>(); + + public IProjectileCannon Owner + { + get + { + return owner; + } + set + { + owner = value; + } + } + + public bool HasRigidbody => _hasRigidBody; + + public VitalNameType VitalNameType => new VitalNameType(VitalType.None); + + private void Reset() + { + localContactTrigger = GetComponent<IContactTrigger>(); + if (localContactTrigger == null) + { + localContactTrigger = base.gameObject.AddComponent<ContactTrigger>(); + } + } + + private void Awake() + { + rb = GetComponentInParent<Rigidbody>(); + rb2d = GetComponentInParent<Rigidbody2D>(); + _hasRigidBody = (bool)rb || (bool)rb2d; + useRbForces = (bool)rb && !rb.isKinematic; + useRb2dForces = (bool)rb2d && !rb2d.isKinematic; + useRBGravity = ((bool)rb && rb.useGravity) || ((bool)rb2d && rb.useGravity); + needsSnapshot = !_hasRigidBody || ((bool)rb && rb.isKinematic) || ((bool)rb2d && rb2d.isKinematic); + localContactTrigger = GetComponent<IContactTrigger>(); + if (needsSnapshot) + { + NetMasterCallbacks.RegisterCallbackInterfaces(this); + } + if (_hasRigidBody) + { + NetMasterCallbacks.onPreUpdates.Remove(this); + } + GetComponents(onHit); + GetComponents(onTerminate); + } + + private void OnDestroy() + { + NetMasterCallbacks.RegisterCallbackInterfaces(this, register: false, delay: true); + } + + public virtual void LagCompensate(float timeshift) + { + snapPos = base.transform.position + velocity * timeshift; + if ((bool)rb && rb.useGravity) + { + velocity += Physics.gravity * timeshift; + } + else if ((bool)rb2d) + { + velocity += Physics.gravity * timeshift; + } + } + + public void Initialize(IProjectileCannon owner, int frameId, int subFrameId, Vector3 localVelocity, RespondTo terminateOn, RespondTo damageOn, float timeshift = 0f) + { + this.owner = owner; + velocity = base.transform.TransformDirection(localVelocity); + this.terminateOn = terminateOn; + this.damageOn = damageOn; + this.frameId = frameId; + this.subFrameId = subFrameId; + if (timeshift != 0f) + { + LagCompensate(timeshift); + } + else + { + snapPos = base.transform.position; + } + if (useRbForces) + { + rb.MovePosition(snapPos); + rb.velocity = velocity; + } + else if ((bool)rb2d) + { + rb2d.MovePosition(snapPos); + rb2d.velocity = velocity; + } + else + { + base.transform.position = snapPos; + targPos = snapPos + velocity * Time.fixedDeltaTime; + base.transform.position = snapPos; + } + localContactTrigger.Proxy = owner.ContactTrigger; + } + + public void OnPreSimulate(int frameId, int subFrameId) + { + if (!useRbForces && !useRb2dForces) + { + SimulateTime(Time.fixedDeltaTime); + } + } + + public virtual void SimulateTime(float t) + { + Vector3 vector = targPos; + targPos = vector + velocity * t; + snapPos = vector; + if (useRb2dForces) + { + velocity += Physics.gravity * rb2d.gravityScale * t; + } + else + { + velocity += Physics.gravity * t; + } + Interpolate(0f); + } + + public virtual void OnPreUpdate() + { + if (!useRbForces && !useRb2dForces) + { + Interpolate(NetMaster.NormTimeSinceFixed); + } + } + + protected void Interpolate(float t) + { + base.transform.position = Vector3.Lerp(snapPos, targPos, t); + } + + protected virtual void Terminate() + { + Debug.Log("Terminate"); + int i = 0; + for (int count = onTerminate.Count; i < count; i++) + { + onTerminate[i].OnTerminate(); + } + base.gameObject.SetActive(value: false); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ContactReactorBase.cs b/ROUNDS/Photon.Pun.Simple/ContactReactorBase.cs new file mode 100644 index 0000000..95b2303 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ContactReactorBase.cs @@ -0,0 +1,51 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public abstract class ContactReactorBase : NetComponent, IContactReactor +{ + [HideInInspector] + public ContactType triggerOn = (ContactType)15; + + protected SyncState syncState; + + protected int syncStateMountMask; + + public ContactType TriggerOn => triggerOn; + + public abstract bool IsPickup { get; } + + public override void OnAwakeInitialize(bool isNetObject) + { + if (isNetObject) + { + syncState = base.transform.GetNestedComponentInParent<SyncState, NetObject>(); + syncStateMountMask = (syncState ? syncState.mountableTo.mask : 0); + } + base.OnAwakeInitialize(isNetObject); + } + + public virtual Consumption OnContactEvent(ContactEvent contactEvent) + { + ContactType contactType = contactEvent.contactType; + if (triggerOn != 0 && (contactType & triggerOn) == 0) + { + return Consumption.None; + } + if (IsPickup) + { + int validMountsMask = contactEvent.contactSystem.ValidMountsMask; + int num = syncState.mountableTo; + if (validMountsMask != 0 && (validMountsMask & num) == 0) + { + return Consumption.None; + } + } + return ProcessContactEvent(contactEvent); + } + + protected abstract Consumption ProcessContactEvent(ContactEvent contactEvent); +} +public abstract class ContactReactorBase<T> : ContactReactorBase, IOnContactEvent where T : class, IContactSystem +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/ContactTrigger.cs b/ROUNDS/Photon.Pun.Simple/ContactTrigger.cs new file mode 100644 index 0000000..e1f3c45 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ContactTrigger.cs @@ -0,0 +1,423 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Photon.Pun.Simple.ContactGroups; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class ContactTrigger : MonoBehaviour, IContactTrigger, IContactable, IOnPreSimulate, IOnStateChange +{ + [Tooltip("If ITriggeringComponent has multiple colliders, they will all be capable of triggering Enter/Stay/Exit events. Enabling this prevents that, and will suppress multiple calls on the same object.")] + [SerializeField] + public bool preventRepeats = true; + + [SerializeField] + [HideInInspector] + public int[] _ignoredSystems; + + protected List<Type> ignoredSystems = new List<Type>(); + + public List<IOnContactEvent> OnContactEventCallbacks = new List<IOnContactEvent>(1); + + private List<IContactSystem> _contactSystems = new List<IContactSystem>(0); + + [Tooltip("This ContactTrigger can act as a proxy of another. For example projectiles set the proxy as the shooters ContactTrigger, so projectile hits can be treated as hits by the players weapon. Default setting is 'this', indicating this isn't a proxy.")] + public IContactTrigger _proxy; + + protected NetObject netObj; + + protected ISyncContact syncContact; + + protected IContactGroupsAssign contactGroupsAssign; + + internal ContactType usedContactTypes; + + protected HashSet<IContactSystem> triggeringHitscans = new HashSet<IContactSystem>(); + + protected HashSet<IContactSystem> triggeringEnters = new HashSet<IContactSystem>(); + + protected HashSet<IContactSystem> triggeringStays = new HashSet<IContactSystem>(); + + public static List<IContactSystem> tempFindSystems; + + internal static List<Type> contactSystemTypes; + + public bool PreventRepeats + { + get + { + return preventRepeats; + } + set + { + preventRepeats = value; + } + } + + public List<IContactSystem> ContactSystems => _contactSystems; + + public IContactTrigger Proxy + { + get + { + return _proxy; + } + set + { + _proxy = value; + } + } + + public byte Index { get; set; } + + public NetObject NetObj => netObj; + + public ISyncContact SyncContact => syncContact; + + public IContactGroupsAssign ContactGroupsAssign => contactGroupsAssign; + + static ContactTrigger() + { + tempFindSystems = new List<IContactSystem>(2); + contactSystemTypes = new List<Type>(); + FindDerivedTypesFromAssembly(); + } + + public virtual void PollInterfaces() + { + _contactSystems.Clear(); + base.transform.GetNestedComponentsInParents<IContactSystem, NetObject>(tempFindSystems); + int i = 0; + for (int count = tempFindSystems.Count; i < count; i++) + { + Type type = tempFindSystems[i].GetType(); + bool flag = false; + foreach (Type ignoredSystem in ignoredSystems) + { + if (type.CheckIsAssignableFrom(ignoredSystem)) + { + flag = true; + break; + } + } + if (!flag) + { + _contactSystems.Add(tempFindSystems[i]); + } + } + base.transform.GetNestedComponentsInChildren(OnContactEventCallbacks, true, typeof(NetObject), typeof(IContactTrigger)); + } + + public virtual void Awake() + { + if (_proxy == null) + { + _proxy = this; + } + GetAllowedTypesFromHashes(); + PollInterfaces(); + netObj = base.transform.GetParentComponent<NetObject>(); + syncContact = GetComponent<ISyncContact>(); + contactGroupsAssign = GetComponent<ContactGroupAssign>(); + if (contactGroupsAssign == null) + { + IContactGroupsAssign nestedComponentInParent = base.transform.GetNestedComponentInParent<IContactGroupsAssign, NetObject>(); + if (nestedComponentInParent != null && nestedComponentInParent.ApplyToChildren) + { + contactGroupsAssign = nestedComponentInParent; + } + } + foreach (IOnContactEvent onContactEventCallback in OnContactEventCallbacks) + { + usedContactTypes |= onContactEventCallback.TriggerOn; + } + } + + protected virtual void OnEnable() + { + if (preventRepeats) + { + NetMasterCallbacks.RegisterCallbackInterfaces(this); + triggeringHitscans.Clear(); + triggeringEnters.Clear(); + triggeringStays.Clear(); + } + } + + protected virtual void OnDisable() + { + if (preventRepeats) + { + NetMasterCallbacks.RegisterCallbackInterfaces(this, register: false, delay: true); + } + } + + public void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true) + { + if (preventRepeats) + { + triggeringEnters.Clear(); + } + } + + private void OnTriggerEnter2D(Collider2D other) + { + Contact(other, ContactType.Enter); + } + + private void OnTriggerEnter(Collider other) + { + Contact(other, ContactType.Enter); + } + + private void OnCollisionEnter2D(Collision2D collision) + { + Contact(collision.collider, ContactType.Enter); + } + + private void OnCollisionEnter(Collision collision) + { + Contact(collision.collider, ContactType.Enter); + } + + private void OnTriggerStay2D(Collider2D other) + { + Contact(other, ContactType.Stay); + } + + private void OnTriggerStay(Collider other) + { + Contact(other, ContactType.Stay); + } + + private void OnCollisionStay2D(Collision2D collision) + { + Contact(collision.collider, ContactType.Stay); + } + + private void OnCollisionStay(Collision collision) + { + Contact(collision.collider, ContactType.Stay); + } + + private void OnTriggerExit2D(Collider2D other) + { + Contact(other, ContactType.Exit); + } + + private void OnTriggerExit(Collider other) + { + Contact(other, ContactType.Exit); + } + + private void OnCollisionExit2D(Collision2D collision) + { + Contact(collision.collider, ContactType.Exit); + } + + private void OnCollisionExit(Collision collision) + { + Contact(collision.collider, ContactType.Exit); + } + + protected virtual void Contact(Component otherCollider, ContactType contactType) + { + IContactTrigger nestedComponentInParents = otherCollider.transform.GetNestedComponentInParents<IContactTrigger, NetObject>(); + if (nestedComponentInParents != null && !CheckIsNested(this, nestedComponentInParents.Proxy) && (object)_proxy.NetObj != nestedComponentInParents.Proxy.NetObj) + { + nestedComponentInParents.Proxy.OnContact(this, contactType); + _proxy.OnContact(nestedComponentInParents, contactType); + } + } + + protected bool CheckIsNested(IContactTrigger first, IContactTrigger second) + { + NetObject netObject = first.NetObj; + NetObject netObject2 = second.NetObj; + NetObject netObject3 = netObject; + while ((object)netObject3 != null) + { + if ((object)netObject3 == netObject2) + { + return true; + } + Transform parent = netObject3.transform.parent; + if ((object)parent == null) + { + break; + } + netObject3 = parent.GetParentComponent<NetObject>(); + } + netObject3 = netObject2; + while ((object)netObject3 != null) + { + if ((object)netObject3 == netObject) + { + return true; + } + Transform parent2 = netObject3.transform.parent; + if ((object)parent2 == null) + { + break; + } + netObject3 = parent2.GetParentComponent<NetObject>(); + } + return false; + } + + public virtual void OnContact(IContactTrigger otherCT, ContactType contactType) + { + if ((bool)GetComponent<ContactProjectile>() && contactType == ContactType.Enter) + { + Debug.Log("Prj Contact"); + } + List<IContactSystem> contactSystems = otherCT.Proxy.ContactSystems; + int count = contactSystems.Count; + if (count == 0 || (netObj != null && !_proxy.NetObj.AllObjsAreReady)) + { + return; + } + NetObject netObject = otherCT.Proxy.NetObj; + if (netObject != null && !netObject.AllObjsAreReady) + { + Debug.Log(Time.time + base.name + " " + netObject.photonView.OwnerActorNr + " Other object not ready so ignoring contact"); + return; + } + for (int i = 0; i < count; i++) + { + IContactSystem contactSystem = contactSystems[i]; + if (!IsCompatibleSystem(contactSystem, otherCT)) + { + continue; + } + if (preventRepeats) + { + switch (contactType) + { + case ContactType.Enter: + if (triggeringEnters.Contains(contactSystem)) + { + continue; + } + triggeringEnters.Add(contactSystem); + break; + case ContactType.Stay: + if (triggeringStays.Contains(contactSystem)) + { + continue; + } + triggeringStays.Add(contactSystem); + break; + case ContactType.Exit: + if (!triggeringEnters.Contains(contactSystem)) + { + continue; + } + triggeringEnters.Remove(contactSystem); + break; + case ContactType.Hitscan: + if (triggeringHitscans.Contains(contactSystem)) + { + continue; + } + triggeringHitscans.Add(contactSystem); + break; + } + } + if ((usedContactTypes & contactType) == 0) + { + break; + } + ContactEvent contactEvent = new ContactEvent(contactSystem, otherCT, contactType); + if (Proxy.SyncContact == null) + { + ContactCallbacks(contactEvent); + } + else + { + syncContact.SyncContactEvent(contactEvent); + } + } + } + + public virtual Consumption ContactCallbacks(ContactEvent contactEvent) + { + Consumption consumption = Consumption.None; + int i = 0; + for (int count = OnContactEventCallbacks.Count; i < count; i++) + { + consumption |= OnContactEventCallbacks[i].OnContactEvent(contactEvent); + if (consumption == Consumption.All) + { + return Consumption.All; + } + } + return consumption; + } + + public void OnPreSimulate(int frameId, int subFrameId) + { + if (preventRepeats) + { + triggeringHitscans.Clear(); + triggeringStays.Clear(); + } + } + + internal void GetAllowedTypesFromHashes() + { + ignoredSystems.Clear(); + if (_ignoredSystems == null) + { + return; + } + foreach (Type contactSystemType in contactSystemTypes) + { + int hashCode = contactSystemType.Name.GetHashCode(); + bool flag = false; + int[] array = _ignoredSystems; + for (int i = 0; i < array.Length; i++) + { + if (array[i] == hashCode) + { + flag = true; + } + } + if (flag) + { + ignoredSystems.Add(contactSystemType); + } + } + } + + internal static void FindDerivedTypesFromAssembly() + { + contactSystemTypes.Clear(); + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + for (int i = 0; i < assemblies.Length; i++) + { + Type[] types = assemblies[i].GetTypes(); + foreach (Type type in types) + { + if (!type.IsAbstract && typeof(IContactSystem).CheckIsAssignableFrom(type)) + { + contactSystemTypes.Add(type); + } + } + } + } + + private bool IsCompatibleSystem(IContactSystem system, IContactTrigger ct) + { + Type type = system.GetType(); + foreach (Type ignoredSystem in ignoredSystems) + { + if (ignoredSystem.CheckIsAssignableFrom(type)) + { + return false; + } + } + return true; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ContactType.cs b/ROUNDS/Photon.Pun.Simple/ContactType.cs new file mode 100644 index 0000000..a443044 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ContactType.cs @@ -0,0 +1,10 @@ +namespace Photon.Pun.Simple; + +public enum ContactType +{ + Undefined = 0, + Enter = 1, + Stay = 2, + Exit = 4, + Hitscan = 8 +} diff --git a/ROUNDS/Photon.Pun.Simple/DisplayToggle.cs b/ROUNDS/Photon.Pun.Simple/DisplayToggle.cs new file mode 100644 index 0000000..4e64b2c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/DisplayToggle.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum DisplayToggle +{ + GameObject, + Component, + Renderer +} diff --git a/ROUNDS/Photon.Pun.Simple/DoubleTime.cs b/ROUNDS/Photon.Pun.Simple/DoubleTime.cs new file mode 100644 index 0000000..917128d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/DoubleTime.cs @@ -0,0 +1,71 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public static class DoubleTime +{ + public static double time; + + public static double prevUpdateTime; + + public static double prevFixedTime; + + public static double deltaTime; + + public static double timeSinceFixed; + + public static double fixedTime; + + public static double fixedDeltaTime; + + public static float normTimeSinceFixed; + + public static double updateTime; + + public static float mixedDeltaTime; + + public static bool isInFixed; + + private static bool isFirstUpdatePostFixed; + + public static void SnapFixed() + { + prevFixedTime = fixedTime; + fixedDeltaTime = Time.fixedDeltaTime; + if (fixedTime == 0.0) + { + fixedTime = Time.fixedTime; + time = Time.time; + } + else + { + fixedTime += fixedDeltaTime; + mixedDeltaTime = (float)(fixedTime - time); + time = fixedTime; + } + isInFixed = true; + isFirstUpdatePostFixed = true; + } + + public static void SnapUpdate() + { + prevUpdateTime = updateTime; + if (updateTime == 0.0) + { + updateTime = Time.time; + fixedTime = Time.fixedTime; + time = fixedTime; + } + else + { + updateTime += Time.deltaTime; + } + timeSinceFixed = updateTime - fixedTime; + deltaTime = updateTime - prevUpdateTime; + normTimeSinceFixed = (float)(timeSinceFixed / (double)Time.fixedDeltaTime); + mixedDeltaTime = (isFirstUpdatePostFixed ? ((float)(updateTime - time)) : Time.deltaTime); + time = updateTime; + isFirstUpdatePostFixed = false; + isInFixed = false; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/EnableOnNetObjReady.cs b/ROUNDS/Photon.Pun.Simple/EnableOnNetObjReady.cs new file mode 100644 index 0000000..c1d3e5d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/EnableOnNetObjReady.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class EnableOnNetObjReady : MonoBehaviour, IOnNetObjReady +{ + public GameObject visibilityObject; + + public void Reset() + { + visibilityObject = base.gameObject; + } + + public void Awake() + { + if (visibilityObject == null) + { + visibilityObject = base.gameObject; + } + } + + private void Start() + { + NetObject componentInParent = GetComponentInParent<NetObject>(); + if ((bool)componentInParent) + { + visibilityObject.SetActive(componentInParent.AllObjsAreReady); + } + } + + public void OnNetObjReadyChange(bool ready) + { + if (visibilityObject == null) + { + visibilityObject = base.gameObject; + } + visibilityObject.SetActive(ready); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/FrameArrival.cs b/ROUNDS/Photon.Pun.Simple/FrameArrival.cs new file mode 100644 index 0000000..756f1b0 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/FrameArrival.cs @@ -0,0 +1,9 @@ +namespace Photon.Pun.Simple; + +public enum FrameArrival +{ + IsFuture = -1, + IsTarget, + IsSnap, + IsLate +} diff --git a/ROUNDS/Photon.Pun.Simple/FrameBase.cs b/ROUNDS/Photon.Pun.Simple/FrameBase.cs new file mode 100644 index 0000000..edeb03a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/FrameBase.cs @@ -0,0 +1,47 @@ +using System; + +namespace Photon.Pun.Simple; + +public abstract class FrameBase +{ + public int frameId; + + public FrameContents content; + + public FrameBase() + { + } + + public FrameBase(int frameId) + { + this.frameId = frameId; + } + + public static TFrame Instantiate<TFrame>(int frameId) where TFrame : FrameBase + { + TFrame obj = (TFrame)Activator.CreateInstance(typeof(TFrame)); + obj.frameId = frameId; + return obj; + } + + public virtual void CopyFrom(FrameBase sourceFrame) + { + content = sourceFrame.content; + } + + public virtual void Clear() + { + content = FrameContents.Empty; + } + + public static void PopulateFrames<TFrame>(ref TFrame[] frames) where TFrame : FrameBase + { + int frameCount = TickEngineSettings.frameCount; + frames = new TFrame[frameCount + 1]; + for (int i = 0; i <= frameCount; i++) + { + TFrame val = Instantiate<TFrame>(i); + frames[i] = val; + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/FrameContents.cs b/ROUNDS/Photon.Pun.Simple/FrameContents.cs new file mode 100644 index 0000000..d3124e2 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/FrameContents.cs @@ -0,0 +1,10 @@ +namespace Photon.Pun.Simple; + +public enum FrameContents +{ + Empty, + Partial, + NoChange, + Extrapolated, + Complete +} diff --git a/ROUNDS/Photon.Pun.Simple/GenericHitscanExt.cs b/ROUNDS/Photon.Pun.Simple/GenericHitscanExt.cs new file mode 100644 index 0000000..258c7f4 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/GenericHitscanExt.cs @@ -0,0 +1,328 @@ +using System; +using System.Collections.Generic; +using Photon.Pun.Simple.Pooling; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public static class GenericHitscanExt +{ + public static Collider[] reusableColliderArray = new Collider[64]; + + public static RaycastHit[] reusableRayHitArray = new RaycastHit[64]; + + public static List<NetworkHit> reusableHitscanHitList = new List<NetworkHit>(); + + public static List<NetObject> reusableNetObjectsList = new List<NetObject>(); + + private static GameObject DebugSpherePrefab; + + private static GameObject DebugCylinderPrefab; + + private static GameObject DebugCubePrefab; + + private static readonly Dictionary<int, int> reusableGameObjIntDict = new Dictionary<int, int>(); + + private static GameObject SetUpDebugPrimitive(this GameObject go, string name, bool createCylinderChild = false) + { + go.name = name; + go.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; + UnityEngine.Object.DontDestroyOnLoad(go); + Collider component; + if (createCylinderChild) + { + GameObject gameObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder); + gameObject.GetComponent<Renderer>().material.color = Color.yellow; + gameObject.transform.parent = go.transform; + gameObject.transform.eulerAngles = new Vector3(90f, 0f, 0f); + component = gameObject.GetComponent<Collider>(); + } + else + { + component = go.GetComponent<Collider>(); + } + UnityEngine.Object.DestroyImmediate(component); + Renderer component2 = go.GetComponent<Renderer>(); + if ((bool)component2) + { + component2.material.color = Color.yellow; + } + return go; + } + + private static void CreateDebugPrimitives() + { + DebugSpherePrefab = GameObject.CreatePrimitive(PrimitiveType.Sphere).SetUpDebugPrimitive("DebugSpherePrefab"); + Pool.AddPrefabToPool(DebugSpherePrefab.gameObject, 2, 2, null, tidyUp: true); + DebugCubePrefab = GameObject.CreatePrimitive(PrimitiveType.Cube).SetUpDebugPrimitive("DebugCubePrefab"); + Pool.AddPrefabToPool(DebugCubePrefab.gameObject, 2, 2, null, tidyUp: true); + DebugCylinderPrefab = new GameObject().SetUpDebugPrimitive("DebugCylinderPrefab", createCylinderChild: true); + Pool.AddPrefabToPool(DebugCylinderPrefab.gameObject, 4, 4, null, tidyUp: true); + } + + public static void VisualizeHitscan(this HitscanDefinition hd, Transform origin, float duration = 0.5f) + { + if (DebugSpherePrefab == null) + { + CreateDebugPrimitives(); + } + switch (hd.hitscanType) + { + case HitscanType.Raycast: + { + Vector3 pos10 = (hd.useOffset ? (origin.position + origin.TransformDirection(hd.offset1) + origin.forward * hd.distance * 0.5f) : (origin.position + origin.forward * hd.distance * 0.5f)); + Pool.Spawn(DebugCylinderPrefab, pos10, origin.rotation, new Vector3(0.1f, 0.1f, hd.distance * 0.5f), duration); + break; + } + case HitscanType.BoxCast: + { + Vector3 vector10 = (hd.useOffset ? (origin.position + origin.TransformDirection(hd.offset1)) : origin.position); + Vector3 vector11 = (hd.useOffset ? (origin.position + origin.TransformDirection(hd.offset1) + origin.forward * hd.distance) : (origin.position + origin.forward * hd.distance)); + Vector3 pos12 = vector10 + (vector11 - vector10) * 0.5f; + Quaternion rot2 = Quaternion.Euler(origin.eulerAngles + hd.orientation); + Vector3 scl2 = hd.halfExtents * 2f; + Pool.Spawn(DebugCubePrefab, vector11, rot2, scl2, duration); + Pool.Spawn(DebugCylinderPrefab, pos12, Quaternion.LookRotation(vector11 - vector10, Vector3.up), new Vector3(0.1f, 0.1f, hd.distance * 0.5f), duration); + break; + } + case HitscanType.SphereCast: + { + Vector3 pos3 = (hd.useOffset ? (origin.position + origin.TransformDirection(hd.offset1)) : origin.position); + Vector3 pos4 = (hd.useOffset ? (origin.position + origin.TransformDirection(hd.offset1) + origin.forward * hd.distance * 0.5f) : (origin.position + origin.forward * hd.distance * 0.5f)); + Vector3 pos5 = (hd.useOffset ? (origin.position + origin.TransformDirection(hd.offset1) + origin.forward * hd.distance) : (origin.position + origin.forward * hd.distance)); + float num2 = hd.radius * 2f; + Pool.Spawn(DebugSpherePrefab, pos3, Quaternion.identity, new Vector3(num2, num2, num2), duration); + Pool.Spawn(DebugSpherePrefab, pos5, Quaternion.identity, new Vector3(num2, num2, num2), duration); + Pool.Spawn(DebugCylinderPrefab, pos4, origin.rotation, new Vector3(num2, num2, hd.distance * 0.5f), duration); + break; + } + case HitscanType.CapsuleCast: + { + Vector3 vector4 = origin.position + origin.TransformDirection(hd.offset1); + Vector3 vector5 = origin.position + origin.TransformDirection(hd.offset2); + Vector3 vector6 = origin.forward * hd.distance; + Vector3 vector7 = vector6 * 0.5f; + Vector3 pos6 = vector4 + vector7; + Vector3 pos7 = vector5 + vector7; + Vector3 vector8 = vector4 + vector6; + Vector3 vector9 = vector5 + vector6; + Vector3 pos8 = vector4 + (vector5 - vector4) * 0.5f; + Vector3 pos9 = vector8 + (vector9 - vector8) * 0.5f; + float num3 = hd.radius * 2f; + Pool.Spawn(DebugSpherePrefab, vector4, Quaternion.identity, new Vector3(num3, num3, num3), duration); + Pool.Spawn(DebugSpherePrefab, vector8, Quaternion.identity, new Vector3(num3, num3, num3), duration); + Pool.Spawn(DebugSpherePrefab, vector5, Quaternion.identity, new Vector3(num3, num3, num3), duration); + Pool.Spawn(DebugSpherePrefab, vector9, Quaternion.identity, new Vector3(num3, num3, num3), duration); + Pool.Spawn(DebugCylinderPrefab, pos6, origin.rotation, new Vector3(num3, num3, hd.distance * 0.5f), duration); + Pool.Spawn(DebugCylinderPrefab, pos7, origin.rotation, new Vector3(num3, num3, hd.distance * 0.5f), duration); + float z = Vector3.Magnitude(vector5 - vector4) * 0.5f; + Pool.Spawn(DebugCylinderPrefab, pos8, Quaternion.LookRotation(vector5 - vector4, Vector3.up), new Vector3(num3, num3, z), duration); + Pool.Spawn(DebugCylinderPrefab, pos9, Quaternion.LookRotation(vector9 - vector8, Vector3.up), new Vector3(num3, num3, z), duration); + break; + } + case HitscanType.OverlapSphere: + { + Vector3 pos11 = (hd.useOffset ? (origin.position + hd.offset1) : origin.position); + Quaternion rotation2 = origin.rotation; + float num4 = hd.radius * 2f; + Pool.Spawn(DebugSpherePrefab, pos11, rotation2, new Vector3(num4, num4, num4), duration); + break; + } + case HitscanType.OverlapBox: + { + Vector3 pos2 = (hd.useOffset ? (origin.position + hd.offset1) : origin.position); + Quaternion rot = Quaternion.Euler(origin.eulerAngles + hd.orientation); + Vector3 scl = hd.halfExtents * 2f; + Pool.Spawn(DebugCubePrefab, pos2, rot, scl, duration); + break; + } + case HitscanType.OverlapCapsule: + { + Quaternion rotation = origin.rotation; + float num = hd.radius * 2f; + Vector3 vector = origin.TransformPoint(hd.offset1); + Vector3 vector2 = origin.TransformPoint(hd.offset2); + Vector3 vector3 = vector2 - vector; + Vector3 pos = vector + vector3 * 0.5f; + Pool.Spawn(DebugSpherePrefab, vector, rotation, new Vector3(num, num, num), duration); + Pool.Spawn(DebugSpherePrefab, vector2, rotation, new Vector3(num, num, num), duration); + Pool.Spawn(DebugCylinderPrefab, pos, Quaternion.LookRotation(vector3, Vector3.up), new Vector3(num, num, vector3.magnitude * 0.5f), duration); + break; + } + } + } + + public static int GenericHitscanNonAlloc(this HitscanDefinition hd, Transform origin, out RaycastHit[] rayhits, out Collider[] hits, ref int nearestIndex, bool showDebugWidgets = false, bool useSecondaryRealm = false) + { + hits = reusableColliderArray; + rayhits = reusableRayHitArray; + return hd.GenericHitscanNonAlloc(origin, ref reusableColliderArray, ref reusableRayHitArray, ref nearestIndex, showDebugWidgets, useSecondaryRealm); + } + + public static int GenericHitscanNonAlloc(this HitscanDefinition hd, Transform origin, NetObject ownerNetObj, ref List<NetworkHit> hitscanHits, ref int nearestIndex, bool showDebugWidgets = false, bool useSecondaryRealm = false) + { + if (hitscanHits == null) + { + hitscanHits = reusableHitscanHitList; + } + int nearestIndex2 = -1; + nearestIndex = -1; + int num = hd.GenericHitscanNonAlloc(origin, ref reusableColliderArray, ref reusableRayHitArray, ref nearestIndex2, showDebugWidgets, useSecondaryRealm); + reusableGameObjIntDict.Clear(); + hitscanHits.Clear(); + if (num > 0) + { + for (int i = 0; i < num; i++) + { + Collider collider = reusableColliderArray[i]; + List<NetObject> list = reusableNetObjectsList; + collider.transform.GetNestedComponentsInParents(list); + int count = list.Count; + if (count == 0) + { + continue; + } + bool flag = false; + for (int j = 0; j < count; j++) + { + if ((object)list[j] == ownerNetObj) + { + flag = true; + break; + } + } + if (flag) + { + continue; + } + NetObject netObject = list[0]; + int viewID = netObject.ViewID; + int num2 = collider.GetComponent<IContactGroupsAssign>()?.Mask ?? 0; + int value; + bool num3 = reusableGameObjIntDict.TryGetValue(viewID, out value); + int colliderId = netObject.colliderLookup[collider]; + if (num3) + { + NetworkHit networkHit = hitscanHits[value]; + hitscanHits[value] = new NetworkHit(networkHit.netObjId, networkHit.hitMask | num2, colliderId); + if (i == nearestIndex2) + { + nearestIndex = value; + } + } + else + { + if (i == nearestIndex2) + { + nearestIndex = hitscanHits.Count; + } + hitscanHits.Add(new NetworkHit(viewID, num2, colliderId)); + reusableGameObjIntDict.Add(viewID, hitscanHits.Count - 1); + } + } + } + return reusableGameObjIntDict.Count; + } + + public static int GenericHitscanNonAlloc(this HitscanDefinition hd, Transform origin, ref Collider[] hits, ref RaycastHit[] rayhits, ref int nearestIndex, bool showDebugWidgets = false, bool useSecondaryRealm = false) + { + if (showDebugWidgets) + { + hd.VisualizeHitscan(origin); + } + if (hits == null) + { + hits = reusableColliderArray; + } + if (rayhits == null) + { + rayhits = reusableRayHitArray; + } + HitscanType hitscanType = hd.hitscanType; + Vector3 vector = (hd.useOffset ? origin.TransformPoint(hd.offset1) : origin.position); + LayerMask layerMask = hd.layerMask; + int num = hitscanType switch + { + HitscanType.Raycast => Physics.RaycastNonAlloc(origin.position, origin.forward, rayhits, hd.distance, layerMask), + HitscanType.SphereCast => Physics.SphereCastNonAlloc(new Ray(vector, origin.forward), hd.radius, rayhits, hd.distance, layerMask), + HitscanType.BoxCast => Physics.BoxCastNonAlloc(vector, hd.halfExtents, origin.forward, rayhits, Quaternion.Euler(origin.eulerAngles + hd.orientation), hd.distance, layerMask), + HitscanType.CapsuleCast => Physics.CapsuleCastNonAlloc(origin.TransformPoint(hd.offset1), origin.TransformPoint(hd.offset2), hd.radius, origin.forward, rayhits, hd.distance, layerMask), + HitscanType.OverlapSphere => Physics.OverlapSphereNonAlloc(vector, hd.radius, hits, layerMask), + HitscanType.OverlapBox => Physics.OverlapBoxNonAlloc(vector, hd.halfExtents, hits, Quaternion.Euler(origin.eulerAngles + hd.orientation), layerMask), + HitscanType.OverlapCapsule => Physics.OverlapCapsuleNonAlloc(origin.TransformPoint(hd.offset1), origin.TransformPoint(hd.offset2), hd.radius, hits, layerMask), + _ => 0, + }; + nearestIndex = -1; + if (num == 0) + { + return num; + } + bool nearestOnly = hd.nearestOnly; + float num2 = float.PositiveInfinity; + if (hitscanType.IsOverlap()) + { + nearestIndex = -1; + return num; + } + if (nearestOnly) + { + for (int i = 0; i < num; i++) + { + RaycastHit raycastHit = rayhits[i]; + float distance = raycastHit.distance; + if (distance < num2) + { + num2 = distance; + nearestIndex = i; + } + } + hits[0] = rayhits[nearestIndex].collider; + return 1; + } + for (int j = 0; j < num; j++) + { + RaycastHit raycastHit2 = rayhits[j]; + float distance2 = raycastHit2.distance; + if (distance2 < num2) + { + num2 = distance2; + nearestIndex = j; + } + if (!nearestOnly) + { + hits[j] = rayhits[j].collider; + } + } + if (nearestOnly) + { + hits[0] = rayhits[nearestIndex].collider; + return 1; + } + return num; + } + + [Obsolete("Haven't reworked this for new physx yet.")] + public static int GenericCastNonAlloc(this Transform srcT, Collider[] hits, RaycastHit[] rayhits, float distance, float radius, int mask, Quaternion orientation, bool useOffset, Vector3 offset1, Vector3 offset2, HitscanType hitscanType) + { + Vector3 vector = (useOffset ? (srcT.position + srcT.TransformDirection(offset1)) : srcT.position); + int num = hitscanType switch + { + HitscanType.Raycast => Physics.RaycastNonAlloc(new Ray(vector, srcT.forward), rayhits, distance, mask), + HitscanType.SphereCast => Physics.SphereCastNonAlloc(new Ray(vector, srcT.forward), radius, rayhits, distance, mask), + HitscanType.BoxCast => Physics.BoxCastNonAlloc(vector, offset2, srcT.forward, rayhits, orientation, distance, mask), + HitscanType.CapsuleCast => Physics.CapsuleCastNonAlloc(srcT.TransformPoint(offset1), srcT.TransformPoint(offset2), radius, srcT.forward, rayhits, distance, mask), + HitscanType.OverlapSphere => Physics.OverlapSphereNonAlloc(vector, radius, hits, mask), + HitscanType.OverlapBox => Physics.OverlapBoxNonAlloc(vector, offset2, hits, orientation, mask), + HitscanType.OverlapCapsule => Physics.OverlapCapsuleNonAlloc(srcT.TransformPoint(offset1), srcT.TransformPoint(offset2), radius, hits, mask), + _ => 0, + }; + if (hitscanType.IsCast()) + { + for (int i = 0; i < num; i++) + { + hits[i] = rayhits[i].collider; + } + } + return num; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/GenericSpawnPoint.cs b/ROUNDS/Photon.Pun.Simple/GenericSpawnPoint.cs new file mode 100644 index 0000000..167548a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/GenericSpawnPoint.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class GenericSpawnPoint : MonoBehaviour +{ + [Header("Spawn Point Blocked Check")] + [Tooltip("Select the physics layers for colliders to test against. If 'avoidCollision' is true and any colliders on these layers are blocking the spawn point, will attempt to find the next spawn point that isn't blocked.")] + public LayerMask layerMask; + + public float blockedCheckRadius = 2f; + + public static readonly List<GenericSpawnPoint> spawns = new List<GenericSpawnPoint>(); + + private static int lastPicked; + + private static readonly Collider[] reusable = new Collider[8]; + + public bool IsBlocked + { + get + { + if (Physics.OverlapSphereNonAlloc(base.transform.position, blockedCheckRadius, reusable, layerMask) != 0) + { + return true; + } + return false; + } + } + + private void OnEnable() + { + spawns.Add(this); + } + + private void OnDisable() + { + spawns.Remove(this); + } + + public static Transform GetRandomSpawnPoint(bool avoidCollision = true) + { + if (spawns.Count == 0) + { + return null; + } + int num = Random.Range(0, spawns.Count - 1); + if (avoidCollision) + { + for (int i = 0; i < spawns.Count; i++) + { + if (!spawns[(i + num) % spawns.Count].IsBlocked) + { + return spawns[(i + num) % spawns.Count].transform; + } + } + } + return spawns[num].transform; + } + + public static Transform GetNextSpawnPoint(bool avoidCollision = true) + { + if (spawns.Count == 0) + { + return null; + } + lastPicked = (lastPicked + 1) % spawns.Count; + if (avoidCollision) + { + for (int i = 0; i < spawns.Count; i++) + { + int index = (i + lastPicked) % spawns.Count; + if (!spawns[index].IsBlocked) + { + lastPicked = index; + break; + } + } + } + return spawns[lastPicked].transform; + } + + public static Transform GetSpawnPointFromValue(int value) + { + if (spawns.Count == 0) + { + return null; + } + int index = (value + 1) % spawns.Count; + return spawns[index].transform; + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.yellow; + Gizmos.DrawWireSphere(base.transform.position, blockedCheckRadius); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/HitscanComponent.cs b/ROUNDS/Photon.Pun.Simple/HitscanComponent.cs new file mode 100644 index 0000000..11dd894 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/HitscanComponent.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public abstract class HitscanComponent : NetComponent, IOnPreSimulate +{ + public GameObject origin; + + public HitscanDefinition hitscanDefinition = new HitscanDefinition(); + + [Tooltip("Ignore any collider hits that are nested children of the same NetObject this Hitscan is on.")] + public bool ignoreSelf = true; + + public bool visualize; + + protected bool triggerQueued; + + public override void OnAwake() + { + base.OnAwake(); + if (!origin) + { + origin = base.gameObject; + } + } + + public virtual void OnPreSimulate(int frameId, int subFrameId) + { + if (triggerQueued) + { + int nearestIndex = -1; + RaycastHit[] rayhits; + Collider[] hits; + int hitcount = hitscanDefinition.GenericHitscanNonAlloc(base.transform, out rayhits, out hits, ref nearestIndex); + if (visualize) + { + hitscanDefinition.VisualizeHitscan(base.transform); + } + triggerQueued = false; + ProcessHits(hits, hitcount); + } + } + + public virtual void ProcessHits(Collider[] hits, int hitcount) + { + for (int i = 0; i < hitcount; i++) + { + Collider collider = hits[i]; + if (ignoreSelf) + { + NetObject parentComponent = collider.transform.GetParentComponent<NetObject>(); + if (parentComponent == netObj) + { + Debug.Log("Ignoring self " + base.name + " hit: " + (collider ? collider.name : "null") + " hitnetobj: " + (parentComponent ? parentComponent.name : "null")); + continue; + } + } + if (ProcessHit(collider)) + { + break; + } + } + } + + public abstract bool ProcessHit(Collider hit); +} diff --git a/ROUNDS/Photon.Pun.Simple/HitscanDefinition.cs b/ROUNDS/Photon.Pun.Simple/HitscanDefinition.cs new file mode 100644 index 0000000..446806d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/HitscanDefinition.cs @@ -0,0 +1,33 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[Serializable] +public class HitscanDefinition +{ + public Replicate ownerToAuthority = Replicate.Hits; + + public Replicate authorityToAll = Replicate.Hits; + + [Tooltip("This cast/overlap test will be done on the initiating client against colliders on these layers. Exclude layers that won't include any objects that you don't want to test (such as walls).")] + public LayerMask layerMask = -1; + + public bool useOffset; + + public Vector3 offset1 = new Vector3(0f, 0f, 0f); + + public Vector3 offset2 = new Vector3(0f, 1f, 0f); + + public Vector3 halfExtents = new Vector3(1f, 1f, 1f); + + public Vector3 orientation = new Vector3(0f, 0f, 0f); + + public HitscanType hitscanType; + + public float distance = 100f; + + public float radius = 1f; + + public bool nearestOnly = true; +} diff --git a/ROUNDS/Photon.Pun.Simple/HitscanType.cs b/ROUNDS/Photon.Pun.Simple/HitscanType.cs new file mode 100644 index 0000000..8d482ed --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/HitscanType.cs @@ -0,0 +1,12 @@ +namespace Photon.Pun.Simple; + +public enum HitscanType +{ + Raycast, + SphereCast, + CapsuleCast, + BoxCast, + OverlapSphere, + OverlapCapsule, + OverlapBox +} diff --git a/ROUNDS/Photon.Pun.Simple/HitscanTypeExt.cs b/ROUNDS/Photon.Pun.Simple/HitscanTypeExt.cs new file mode 100644 index 0000000..e6e6dda --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/HitscanTypeExt.cs @@ -0,0 +1,41 @@ +namespace Photon.Pun.Simple; + +public static class HitscanTypeExt +{ + public static bool IsCast(this HitscanType hitscanType) + { + return hitscanType < HitscanType.OverlapSphere; + } + + public static bool IsOverlap(this HitscanType hitscanType) + { + return hitscanType > HitscanType.BoxCast; + } + + public static bool UsesRadius(this HitscanType hitscanType) + { + if (hitscanType != HitscanType.SphereCast && hitscanType != HitscanType.CapsuleCast && hitscanType != HitscanType.OverlapSphere) + { + return hitscanType == HitscanType.OverlapCapsule; + } + return true; + } + + public static bool IsBox(this HitscanType hitscanType) + { + if (hitscanType != HitscanType.BoxCast) + { + return hitscanType == HitscanType.OverlapBox; + } + return true; + } + + public static bool IsCapsule(this HitscanType hitscanType) + { + if (hitscanType != HitscanType.CapsuleCast) + { + return hitscanType == HitscanType.OverlapCapsule; + } + return true; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/IAdjustableApplyOrder.cs b/ROUNDS/Photon.Pun.Simple/IAdjustableApplyOrder.cs new file mode 100644 index 0000000..c9b7147 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IAdjustableApplyOrder.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface IAdjustableApplyOrder : IApplyOrder +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IApplyOrder.cs b/ROUNDS/Photon.Pun.Simple/IApplyOrder.cs new file mode 100644 index 0000000..311d14a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IApplyOrder.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IApplyOrder +{ + int ApplyOrder { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IAutoKinematic.cs b/ROUNDS/Photon.Pun.Simple/IAutoKinematic.cs new file mode 100644 index 0000000..4bdd3b8 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IAutoKinematic.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IAutoKinematic +{ + bool AutoKinematicEnabled { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IConsumable.cs b/ROUNDS/Photon.Pun.Simple/IConsumable.cs new file mode 100644 index 0000000..507fe8d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IConsumable.cs @@ -0,0 +1,10 @@ +namespace Photon.Pun.Simple; + +public interface IConsumable +{ + double Charges { get; set; } + + Consumption Consumption { get; } + + ConsumedDespawn ConsumedDespawn { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IContactGroupsAssign.cs b/ROUNDS/Photon.Pun.Simple/IContactGroupsAssign.cs new file mode 100644 index 0000000..d9014e4 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IContactGroupsAssign.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public interface IContactGroupsAssign +{ + int Mask { get; } + + bool ApplyToChildren { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IContactReactor.cs b/ROUNDS/Photon.Pun.Simple/IContactReactor.cs new file mode 100644 index 0000000..9f3ad9b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IContactReactor.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface IContactReactor +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IContactSystem.cs b/ROUNDS/Photon.Pun.Simple/IContactSystem.cs new file mode 100644 index 0000000..23659ba --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IContactSystem.cs @@ -0,0 +1,24 @@ +using Photon.Pun.Simple.ContactGroups; + +namespace Photon.Pun.Simple; + +public interface IContactSystem +{ + NetObject NetObj { get; } + + int ViewID { get; } + + bool IsMine { get; } + + byte SystemIndex { get; set; } + + Mount DefaultMount { get; } + + int ValidMountsMask { get; } + + IContactGroupMask ValidContactGroups { get; } + + Consumption TryTrigger(IContactReactor reactor, ContactEvent contactEvent, int compatibleMounts); + + Mount TryPickup(IContactReactor reactor, ContactEvent contactEvent); +} diff --git a/ROUNDS/Photon.Pun.Simple/IContactTrigger.cs b/ROUNDS/Photon.Pun.Simple/IContactTrigger.cs new file mode 100644 index 0000000..ca0c7e9 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IContactTrigger.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Photon.Pun.Simple; + +public interface IContactTrigger +{ + NetObject NetObj { get; } + + byte Index { get; set; } + + IContactTrigger Proxy { get; set; } + + bool PreventRepeats { get; set; } + + List<IContactSystem> ContactSystems { get; } + + ISyncContact SyncContact { get; } + + IContactGroupsAssign ContactGroupsAssign { get; } + + Consumption ContactCallbacks(ContactEvent contactEvent); + + void OnContact(IContactTrigger otherCT, ContactType contactType); +} diff --git a/ROUNDS/Photon.Pun.Simple/IContactable.cs b/ROUNDS/Photon.Pun.Simple/IContactable.cs new file mode 100644 index 0000000..576d247 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IContactable.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface IContactable +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IDeltaFrameChangeDetect.cs b/ROUNDS/Photon.Pun.Simple/IDeltaFrameChangeDetect.cs new file mode 100644 index 0000000..f337d3b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IDeltaFrameChangeDetect.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IDeltaFrameChangeDetect : IUseKeyframes +{ + bool UseDeltas { get; set; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IFlagTeleport.cs b/ROUNDS/Photon.Pun.Simple/IFlagTeleport.cs new file mode 100644 index 0000000..89022c5 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IFlagTeleport.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IFlagTeleport +{ + void FlagTeleport(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IInventorySystem.cs b/ROUNDS/Photon.Pun.Simple/IInventorySystem.cs new file mode 100644 index 0000000..e18b588 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IInventorySystem.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public interface IInventorySystem : IContactSystem +{ +} +public interface IInventorySystem<T> : IInventorySystem, IContactSystem +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IInventoryable.cs b/ROUNDS/Photon.Pun.Simple/IInventoryable.cs new file mode 100644 index 0000000..bdba2f6 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IInventoryable.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IInventoryable<T> : IContactable +{ + T Size { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IMountable.cs b/ROUNDS/Photon.Pun.Simple/IMountable.cs new file mode 100644 index 0000000..3d71215 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IMountable.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public interface IMountable +{ + Mount CurrentMount { get; } + + bool IsDroppable { get; } + + bool IsThrowable { get; } + + Rigidbody Rb { get; } + + Rigidbody2D Rb2d { get; } + + void ImmediateUnmount(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnAuthorityChanged.cs b/ROUNDS/Photon.Pun.Simple/IOnAuthorityChanged.cs new file mode 100644 index 0000000..0fbf5a3 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnAuthorityChanged.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnAuthorityChanged +{ + void OnAuthorityChanged(bool isMine, bool asServer); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnAwake.cs b/ROUNDS/Photon.Pun.Simple/IOnAwake.cs new file mode 100644 index 0000000..161809e --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnAwake.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnAwake +{ + void OnAwake(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnCaptureState.cs b/ROUNDS/Photon.Pun.Simple/IOnCaptureState.cs new file mode 100644 index 0000000..f7daa96 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnCaptureState.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnCaptureState +{ + void OnCaptureCurrentState(int frameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnChangeOwnedVitals.cs b/ROUNDS/Photon.Pun.Simple/IOnChangeOwnedVitals.cs new file mode 100644 index 0000000..49feef9 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnChangeOwnedVitals.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnChangeOwnedVitals +{ + void OnChangeOwnedVitals(IVitalsSystem added, IVitalsSystem removed); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnContactEvent.cs b/ROUNDS/Photon.Pun.Simple/IOnContactEvent.cs new file mode 100644 index 0000000..96e9fc7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnContactEvent.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public interface IOnContactEvent +{ + ContactType TriggerOn { get; } + + Consumption OnContactEvent(ContactEvent contactEvent); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnCriticallyLateFrame.cs b/ROUNDS/Photon.Pun.Simple/IOnCriticallyLateFrame.cs new file mode 100644 index 0000000..b612e80 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnCriticallyLateFrame.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnCriticallyLateFrame +{ + void HandleCriticallyLateFrame(int frameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnDisable.cs b/ROUNDS/Photon.Pun.Simple/IOnDisable.cs new file mode 100644 index 0000000..cf7b8de --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnDisable.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnDisable +{ + void OnPostDisable(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnEnable.cs b/ROUNDS/Photon.Pun.Simple/IOnEnable.cs new file mode 100644 index 0000000..71f9f51 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnEnable.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnEnable +{ + void OnPostEnable(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnIncrementFrame.cs b/ROUNDS/Photon.Pun.Simple/IOnIncrementFrame.cs new file mode 100644 index 0000000..9802f32 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnIncrementFrame.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnIncrementFrame +{ + void OnIncrementFrame(int newFrameId, int newSubFrameId, int previousFrameId, int prevSubFrameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnInterpolate.cs b/ROUNDS/Photon.Pun.Simple/IOnInterpolate.cs new file mode 100644 index 0000000..edad48b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnInterpolate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnInterpolate +{ + bool OnInterpolate(int snapFrameId, int targFrameId, float t); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnJoinedRoom.cs b/ROUNDS/Photon.Pun.Simple/IOnJoinedRoom.cs new file mode 100644 index 0000000..c960773 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnJoinedRoom.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnJoinedRoom +{ + void OnJoinedRoom(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnNetObjReady.cs b/ROUNDS/Photon.Pun.Simple/IOnNetObjReady.cs new file mode 100644 index 0000000..3c331ea --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnNetObjReady.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnNetObjReady +{ + void OnNetObjReadyChange(bool ready); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnNetSerialize.cs b/ROUNDS/Photon.Pun.Simple/IOnNetSerialize.cs new file mode 100644 index 0000000..301a5e0 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnNetSerialize.cs @@ -0,0 +1,12 @@ +using Photon.Compression; + +namespace Photon.Pun.Simple; + +public interface IOnNetSerialize +{ + bool SkipWhenEmpty { get; } + + SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags); + + SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival frameArrival); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnNetworkHit.cs b/ROUNDS/Photon.Pun.Simple/IOnNetworkHit.cs new file mode 100644 index 0000000..547801b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnNetworkHit.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnNetworkHit +{ + void OnNetworkHit(NetworkHits results); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPostCallbackLoop.cs b/ROUNDS/Photon.Pun.Simple/IOnPostCallbackLoop.cs new file mode 100644 index 0000000..f5c20bd --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPostCallbackLoop.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPostCallbackLoop +{ + void OnPostCallback(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPostLateUpdate.cs b/ROUNDS/Photon.Pun.Simple/IOnPostLateUpdate.cs new file mode 100644 index 0000000..98659a7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPostLateUpdate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPostLateUpdate +{ + void OnPostLateUpdate(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPostSimulate.cs b/ROUNDS/Photon.Pun.Simple/IOnPostSimulate.cs new file mode 100644 index 0000000..11e77ae --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPostSimulate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPostSimulate +{ + void OnPostSimulate(int frameId, int subFrameId, bool isNetTick); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPostUpdate.cs b/ROUNDS/Photon.Pun.Simple/IOnPostUpdate.cs new file mode 100644 index 0000000..5bd3f03 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPostUpdate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPostUpdate +{ + void OnPostUpdate(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPreLateUpdate.cs b/ROUNDS/Photon.Pun.Simple/IOnPreLateUpdate.cs new file mode 100644 index 0000000..e4f0b00 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPreLateUpdate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPreLateUpdate +{ + void OnPreLateUpdate(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPreNetDestroy.cs b/ROUNDS/Photon.Pun.Simple/IOnPreNetDestroy.cs new file mode 100644 index 0000000..34aac8a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPreNetDestroy.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPreNetDestroy +{ + void OnPreNetDestroy(NetObject roothNetObj); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPreQuit.cs b/ROUNDS/Photon.Pun.Simple/IOnPreQuit.cs new file mode 100644 index 0000000..7aaba5b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPreQuit.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPreQuit +{ + void OnPreQuit(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPreSimulate.cs b/ROUNDS/Photon.Pun.Simple/IOnPreSimulate.cs new file mode 100644 index 0000000..9111b72 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPreSimulate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPreSimulate +{ + void OnPreSimulate(int frameId, int subFrameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnPreUpdate.cs b/ROUNDS/Photon.Pun.Simple/IOnPreUpdate.cs new file mode 100644 index 0000000..c191c3b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnPreUpdate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnPreUpdate +{ + void OnPreUpdate(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnQuantize.cs b/ROUNDS/Photon.Pun.Simple/IOnQuantize.cs new file mode 100644 index 0000000..a8ffb97 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnQuantize.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnQuantize +{ + void OnQuantize(int frameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnRootVitalBecameZero.cs b/ROUNDS/Photon.Pun.Simple/IOnRootVitalBecameZero.cs new file mode 100644 index 0000000..2c1da34 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnRootVitalBecameZero.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnRootVitalBecameZero +{ + void OnRootVitalBecameZero(Vital vital, IVitalsContactReactor causeOfDeath); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnSnapshot.cs b/ROUNDS/Photon.Pun.Simple/IOnSnapshot.cs new file mode 100644 index 0000000..f88e586 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnSnapshot.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnSnapshot +{ + bool OnSnapshot(int pre1FrameId, int snapFrameId, int targFrameId, bool prevIsValid, bool snapIsValid, bool targIsValid); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnStart.cs b/ROUNDS/Photon.Pun.Simple/IOnStart.cs new file mode 100644 index 0000000..2845515 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnStart.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnStart +{ + void OnStart(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnStateChange.cs b/ROUNDS/Photon.Pun.Simple/IOnStateChange.cs new file mode 100644 index 0000000..0b4e15f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnStateChange.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public interface IOnStateChange +{ + void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnTerminate.cs b/ROUNDS/Photon.Pun.Simple/IOnTerminate.cs new file mode 100644 index 0000000..cbe881c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnTerminate.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnTerminate +{ + void OnTerminate(); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnTickPreSerialization.cs b/ROUNDS/Photon.Pun.Simple/IOnTickPreSerialization.cs new file mode 100644 index 0000000..0d56436 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnTickPreSerialization.cs @@ -0,0 +1,8 @@ +using Photon.Compression; + +namespace Photon.Pun.Simple; + +public interface IOnTickPreSerialization +{ + SerializationFlags OnPreSerializeTick(int frameId, byte[] buffer, ref int bitposition); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnTickSnapshot.cs b/ROUNDS/Photon.Pun.Simple/IOnTickSnapshot.cs new file mode 100644 index 0000000..9785d44 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnTickSnapshot.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnTickSnapshot +{ + bool OnSnapshot(int newTargetFrameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnVitalChange.cs b/ROUNDS/Photon.Pun.Simple/IOnVitalChange.cs new file mode 100644 index 0000000..5ab448f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnVitalChange.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface IOnVitalChange +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnVitalParamChange.cs b/ROUNDS/Photon.Pun.Simple/IOnVitalParamChange.cs new file mode 100644 index 0000000..f5f5ddd --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnVitalParamChange.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnVitalParamChange : IOnVitalChange +{ + void OnVitalParamChange(Vital vital); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnVitalValueChange.cs b/ROUNDS/Photon.Pun.Simple/IOnVitalValueChange.cs new file mode 100644 index 0000000..d52760b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnVitalValueChange.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnVitalValueChange : IOnVitalChange +{ + void OnVitalValueChange(Vital vital); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnVitalsChange.cs b/ROUNDS/Photon.Pun.Simple/IOnVitalsChange.cs new file mode 100644 index 0000000..033238a --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnVitalsChange.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface IOnVitalsChange +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnVitalsParamChange.cs b/ROUNDS/Photon.Pun.Simple/IOnVitalsParamChange.cs new file mode 100644 index 0000000..af6dab9 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnVitalsParamChange.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnVitalsParamChange : IOnVitalsChange +{ + void OnVitalParamChange(Vital vital); +} diff --git a/ROUNDS/Photon.Pun.Simple/IOnVitalsValueChange.cs b/ROUNDS/Photon.Pun.Simple/IOnVitalsValueChange.cs new file mode 100644 index 0000000..b7ae665 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IOnVitalsValueChange.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IOnVitalsValueChange : IOnVitalsChange +{ + void OnVitalValueChange(Vital vital); +} diff --git a/ROUNDS/Photon.Pun.Simple/IProjectile.cs b/ROUNDS/Photon.Pun.Simple/IProjectile.cs new file mode 100644 index 0000000..d6e8366 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IProjectile.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public interface IProjectile +{ + IProjectileCannon Owner { get; set; } + + void Initialize(IProjectileCannon owner, int frameId, int subFrameId, Vector3 velocity, RespondTo terminateOn, RespondTo damageOn, float timeshift); +} diff --git a/ROUNDS/Photon.Pun.Simple/IProjectileCannon.cs b/ROUNDS/Photon.Pun.Simple/IProjectileCannon.cs new file mode 100644 index 0000000..401fbb3 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IProjectileCannon.cs @@ -0,0 +1,12 @@ +namespace Photon.Pun.Simple; + +public interface IProjectileCannon +{ + PhotonView PhotonView { get; } + + NetObject NetObj { get; } + + IContactTrigger ContactTrigger { get; } + + int ViewID { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IReadyable.cs b/ROUNDS/Photon.Pun.Simple/IReadyable.cs new file mode 100644 index 0000000..e3c3fd9 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IReadyable.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IReadyable +{ + bool AlwaysReady { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/ISerializationOptional.cs b/ROUNDS/Photon.Pun.Simple/ISerializationOptional.cs new file mode 100644 index 0000000..664c504 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ISerializationOptional.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface ISerializationOptional : IOnNetSerialize +{ + bool IncludeInSerialization { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/ISpawnController.cs b/ROUNDS/Photon.Pun.Simple/ISpawnController.cs new file mode 100644 index 0000000..a2123ea --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ISpawnController.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface ISpawnController +{ + bool AllowNetObjectReadyCallback(bool ready); +} diff --git a/ROUNDS/Photon.Pun.Simple/ISyncAnimator.cs b/ROUNDS/Photon.Pun.Simple/ISyncAnimator.cs new file mode 100644 index 0000000..ddbf95d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ISyncAnimator.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface ISyncAnimator +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/ISyncContact.cs b/ROUNDS/Photon.Pun.Simple/ISyncContact.cs new file mode 100644 index 0000000..7c82369 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ISyncContact.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface ISyncContact +{ + void SyncContactEvent(ContactEvent contactEvent); +} diff --git a/ROUNDS/Photon.Pun.Simple/ISyncTransform.cs b/ROUNDS/Photon.Pun.Simple/ISyncTransform.cs new file mode 100644 index 0000000..09895f8 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ISyncTransform.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface ISyncTransform +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/ITransformController.cs b/ROUNDS/Photon.Pun.Simple/ITransformController.cs new file mode 100644 index 0000000..f41537b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ITransformController.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public interface ITransformController +{ + bool HandlesInterpolation { get; } + + bool HandlesExtrapolation { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/IUseKeyframes.cs b/ROUNDS/Photon.Pun.Simple/IUseKeyframes.cs new file mode 100644 index 0000000..029fee1 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IUseKeyframes.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IUseKeyframes +{ + bool IsKeyframe(int frameId); +} diff --git a/ROUNDS/Photon.Pun.Simple/IVitalsConsumable.cs b/ROUNDS/Photon.Pun.Simple/IVitalsConsumable.cs new file mode 100644 index 0000000..b4f49a6 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IVitalsConsumable.cs @@ -0,0 +1,5 @@ +namespace Photon.Pun.Simple; + +public interface IVitalsConsumable : IVitalsContactReactor, IContactReactor, IConsumable +{ +} diff --git a/ROUNDS/Photon.Pun.Simple/IVitalsContactReactor.cs b/ROUNDS/Photon.Pun.Simple/IVitalsContactReactor.cs new file mode 100644 index 0000000..202da33 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IVitalsContactReactor.cs @@ -0,0 +1,12 @@ +namespace Photon.Pun.Simple; + +public interface IVitalsContactReactor : IContactReactor +{ + VitalNameType VitalNameType { get; } + + bool AllowOverload { get; } + + bool Propagate { get; } + + double DischargeValue(ContactType contactType = ContactType.Undefined); +} diff --git a/ROUNDS/Photon.Pun.Simple/IVitalsSystem.cs b/ROUNDS/Photon.Pun.Simple/IVitalsSystem.cs new file mode 100644 index 0000000..eb193e2 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/IVitalsSystem.cs @@ -0,0 +1,6 @@ +namespace Photon.Pun.Simple; + +public interface IVitalsSystem : IContactSystem +{ + Vitals Vitals { get; } +} diff --git a/ROUNDS/Photon.Pun.Simple/Interpolation.cs b/ROUNDS/Photon.Pun.Simple/Interpolation.cs new file mode 100644 index 0000000..06bc6ac --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Interpolation.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum Interpolation +{ + None, + Linear, + CatmullRom +} diff --git a/ROUNDS/Photon.Pun.Simple/Inventory.cs b/ROUNDS/Photon.Pun.Simple/Inventory.cs new file mode 100644 index 0000000..c2d18f6 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Inventory.cs @@ -0,0 +1,77 @@ +using Photon.Pun.Simple.ContactGroups; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public abstract class Inventory<T> : NetComponent, IInventorySystem<T>, IInventorySystem, IContactSystem +{ + [SerializeField] + protected MountSelector defaultMounting = new MountSelector(0); + + [SerializeField] + protected ContactGroupMaskSelector contactGroups; + + protected MountsManager mountsLookup; + + protected int defaultMountingMask; + + public Mount DefaultMount { get; set; } + + public IContactGroupMask ValidContactGroups => contactGroups; + + public byte SystemIndex { get; set; } + + public int ValidMountsMask => defaultMountingMask; + + public override void OnAwakeInitialize(bool isNetObject) + { + base.OnAwakeInitialize(isNetObject); + base.transform.EnsureRootComponentExists<ContactManager, NetObject>(); + mountsLookup = netObj.transform.GetComponent<MountsManager>(); + defaultMountingMask = 1 << defaultMounting.id; + } + + public override void OnStart() + { + base.OnStart(); + if ((bool)mountsLookup) + { + DefaultMount = mountsLookup.GetMount(defaultMounting); + } + } + + public virtual Consumption TryTrigger(IContactReactor reactor, ContactEvent contactEvent, int compatibleMounts) + { + if (!(reactor is IInventoryable<T>)) + { + return Consumption.None; + } + if ((int)contactGroups != 0) + { + int num = contactEvent.contactTrigger.ContactGroupsAssign?.Mask ?? 0; + if ((contactGroups.Mask & num) == 0) + { + return Consumption.None; + } + } + if (!TestCapacity(reactor as IInventoryable<T>)) + { + return Consumption.None; + } + if (compatibleMounts == defaultMountingMask || (compatibleMounts & defaultMountingMask) != 0) + { + return Consumption.All; + } + return Consumption.None; + } + + public virtual Mount TryPickup(IContactReactor reactor, ContactEvent contactEvent) + { + return DefaultMount; + } + + public virtual bool TestCapacity(IInventoryable<T> inventoryable) + { + return true; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/InventoryContactReactors.cs b/ROUNDS/Photon.Pun.Simple/InventoryContactReactors.cs new file mode 100644 index 0000000..67a499f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/InventoryContactReactors.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class InventoryContactReactors : InventoryContactReactors<Vector3Int> +{ + [SerializeField] + protected Vector3Int size = new Vector3Int(1, 1, 1); + + public override Vector3Int Size => size; + + public override void OnAwakeInitialize(bool isNetObject) + { + base.OnAwakeInitialize(isNetObject); + volume = size.x * size.y * size.z; + } +} +public abstract class InventoryContactReactors<T> : ContactReactorBase<IInventorySystem<T>>, IInventoryable<T>, IContactable +{ + protected int volume; + + public abstract T Size { get; } + + public int Volume => volume; + + public override bool IsPickup => true; + + protected override Consumption ProcessContactEvent(ContactEvent contactEvent) + { + if (!(contactEvent.contactSystem is IInventorySystem<T> inventorySystem)) + { + return Consumption.None; + } + if (IsPickup) + { + Mount mount = inventorySystem.TryPickup(this, contactEvent); + if ((bool)mount) + { + syncState.HardMount(mount); + } + } + return Consumption.All; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/KinematicSetting.cs b/ROUNDS/Photon.Pun.Simple/KinematicSetting.cs new file mode 100644 index 0000000..3c1c146 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/KinematicSetting.cs @@ -0,0 +1,9 @@ +namespace Photon.Pun.Simple; + +public enum KinematicSetting +{ + Ignore, + Default, + NonKinematic, + Kinematic +} diff --git a/ROUNDS/Photon.Pun.Simple/LocalApplyTiming.cs b/ROUNDS/Photon.Pun.Simple/LocalApplyTiming.cs new file mode 100644 index 0000000..f31c126 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/LocalApplyTiming.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum LocalApplyTiming +{ + Never, + Immediately, + OnSend +} diff --git a/ROUNDS/Photon.Pun.Simple/MaskLogic.cs b/ROUNDS/Photon.Pun.Simple/MaskLogic.cs new file mode 100644 index 0000000..9143195 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MaskLogic.cs @@ -0,0 +1,73 @@ +using System; + +namespace Photon.Pun.Simple; + +[Serializable] +public abstract class MaskLogic +{ + public enum Operator + { + EQUALS, + AND, + OR + } + + public Operator operation = Operator.AND; + + public int stateMask; + + public int notMask; + + protected int trueMask; + + protected abstract string[] EnumNames { get; } + + protected abstract int[] EnumValues { get; } + + protected abstract bool DefinesZero { get; } + + protected abstract int DefaultValue { get; } + + public MaskLogic() + { + stateMask = DefaultValue; + } + + public void RecalculateMasks() + { + if (operation == Operator.EQUALS) + { + notMask = 0; + } + notMask &= stateMask; + trueMask = stateMask & ~notMask; + } + + public bool Evaluate(int state) + { + if (stateMask == 0) + { + return state == 0; + } + switch (operation) + { + case Operator.EQUALS: + return stateMask == state; + case Operator.OR: + if ((trueMask & state) == 0) + { + return (notMask & state) != notMask; + } + return true; + case Operator.AND: + if ((trueMask & state) == trueMask) + { + return (notMask & state) == 0; + } + return false; + default: + operation = Operator.EQUALS; + return stateMask == state; + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/Mount.cs b/ROUNDS/Photon.Pun.Simple/Mount.cs new file mode 100644 index 0000000..c2f645c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Mount.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class Mount : NetComponent, IOnPreQuit, IOnPreNetDestroy +{ + public const string ROOT_MOUNT_NAME = "Root"; + + [Tooltip("A Mount component can be associated with more than one mount name. The first root will always include 'Root'.")] + [SerializeField] + [HideInInspector] + public MountSelector mountType = new MountSelector(1); + + [SerializeField] + [HideInInspector] + public int componentIndex; + + [NonSerialized] + public List<IMountable> mountedObjs = new List<IMountable>(); + + [NonSerialized] + public MountsManager mountsLookup; + + public override void OnAwake() + { + base.OnAwake(); + mountsLookup = netObj.GetComponent<MountsManager>(); + } + + public void OnPreQuit() + { + DismountAll(); + } + + public void OnPreNetDestroy(NetObject rootNetObj) + { + if (rootNetObj == netObj) + { + DismountAll(); + } + } + + public void DismountAll() + { + for (int num = mountedObjs.Count - 1; num >= 0; num--) + { + if ((bool)(mountedObjs[num] as Component)) + { + mountedObjs[num].ImmediateUnmount(); + } + } + } + + public static void ChangeMounting(IMountable mountable, Mount prevMount, Mount newMount) + { + prevMount?.mountedObjs.Remove(mountable); + if ((object)newMount != null) + { + List<IMountable> list = newMount.mountedObjs; + if (!list.Contains(mountable)) + { + list.Add(mountable); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/MountMaskSelector.cs b/ROUNDS/Photon.Pun.Simple/MountMaskSelector.cs new file mode 100644 index 0000000..060ea6d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MountMaskSelector.cs @@ -0,0 +1,29 @@ +using System; + +namespace Photon.Pun.Simple; + +[Serializable] +public struct MountMaskSelector +{ + public int mask; + + public MountMaskSelector(int mountTypeMask) + { + mask = mountTypeMask; + } + + public MountMaskSelector(bool allTrue) + { + mask = (allTrue ? MountSettings.AllTrueMask : 0); + } + + public static implicit operator int(MountMaskSelector selector) + { + return selector.mask; + } + + public static implicit operator MountMaskSelector(int mask) + { + return new MountMaskSelector(mask); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/MountSelector.cs b/ROUNDS/Photon.Pun.Simple/MountSelector.cs new file mode 100644 index 0000000..fd8e4fe --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MountSelector.cs @@ -0,0 +1,24 @@ +using System; + +namespace Photon.Pun.Simple; + +[Serializable] +public struct MountSelector +{ + public int id; + + public MountSelector(int index) + { + id = index; + } + + public static implicit operator int(MountSelector selector) + { + return selector.id; + } + + public static implicit operator MountSelector(int id) + { + return new MountSelector(id); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/MountSettings.cs b/ROUNDS/Photon.Pun.Simple/MountSettings.cs new file mode 100644 index 0000000..bcf7ae7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MountSettings.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class MountSettings : SettingsScriptableObject<MountSettings> +{ + [HideInInspector] + [SerializeField] + private List<string> mountNames = new List<string> { "Root", "1", "2", "3", "4" }; + + public static int mountTypeCount; + + public static int bitsForMountId; + + public static int AllTrueMask + { + get + { + if (SettingsScriptableObject<MountSettings>.Single.mountNames.Count == 32) + { + return -1; + } + return (int)((1L << SettingsScriptableObject<MountSettings>.Single.mountNames.Count) - 1); + } + } + + public override void Initialize() + { + base.Initialize(); + mountTypeCount = SettingsScriptableObject<MountSettings>.Single.mountNames.Count; + bitsForMountId = (mountTypeCount - 1).GetBitsForMaxValue(); + } + + public static int GetIndex(string name) + { + return SettingsScriptableObject<MountSettings>.single.mountNames.IndexOf(name); + } + + public static string GetName(int index) + { + if (index >= mountTypeCount) + { + return null; + } + return SettingsScriptableObject<MountSettings>.single.mountNames[index]; + } + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void Bootstrap() + { + _ = SettingsScriptableObject<MountSettings>.Single; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/MountSwitcher.cs b/ROUNDS/Photon.Pun.Simple/MountSwitcher.cs new file mode 100644 index 0000000..6d2c38b --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MountSwitcher.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class MountSwitcher : NetComponent, IOnPreUpdate, IOnPreSimulate +{ + public KeyCode keycode = KeyCode.M; + + public MountSelector mount = new MountSelector(1); + + protected bool triggered; + + protected SyncState syncState; + + public override void OnAwake() + { + base.OnAwake(); + if ((bool)netObj) + { + syncState = netObj.GetComponent<SyncState>(); + } + if (!GetComponent<SyncState>()) + { + Debug.LogWarning(GetType().Name + " on '" + base.transform.parent.name + "/" + base.name + "' needs to be on the root of NetObject with component " + typeof(SyncState).Name + ". Disabling."); + netObj.RemoveInterfaces(this); + } + } + + public void OnPreUpdate() + { + if (Input.GetKeyDown(keycode)) + { + triggered = true; + } + } + + public void OnPreSimulate(int frameId, int subFrameId) + { + if (triggered) + { + triggered = false; + Mount currentMount = syncState.CurrentMount; + if ((object)currentMount != null && currentMount.IsMine) + { + Debug.Log(string.Concat("Try change to mount : ", currentMount, " : ", currentMount.IsMine.ToString(), " : ", mount.id)); + syncState.ChangeMount(mount.id); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/MountThrow.cs b/ROUNDS/Photon.Pun.Simple/MountThrow.cs new file mode 100644 index 0000000..532663f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MountThrow.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[RequireComponent(typeof(Mount))] +public class MountThrow : NetComponent, IOnPreUpdate, IOnPreSimulate +{ + public KeyCode throwKey; + + public Mount mount; + + public bool fromRoot = true; + + public bool inheritRBVelocity = true; + + public Vector3 offset = new Vector3(0f, 3f, 0f); + + public Vector3 velocity = new Vector3(0f, 1f, 5f); + + private bool throwQueued; + + public override void OnAwake() + { + base.OnAwake(); + if (mount == null) + { + mount = GetComponent<Mount>(); + } + } + + public void OnPreUpdate() + { + if (base.IsMine && Input.GetKeyDown(throwKey)) + { + throwQueued = true; + } + } + + public void OnPreSimulate(int frameId, int subFrameId) + { + if (!throwQueued) + { + return; + } + throwQueued = false; + List<IMountable> mountedObjs = mount.mountedObjs; + for (int i = 0; i < mountedObjs.Count; i++) + { + IMountable mountable = mountedObjs[i]; + Rigidbody rb = mountable.Rb; + if ((bool)rb && mountable.IsThrowable) + { + SyncState syncState = mountable as SyncState; + if ((bool)syncState) + { + Transform transform = (fromRoot ? mount.mountsLookup.transform : base.transform); + Vector3 position = transform.TransformPoint(offset); + Quaternion rotation = transform.rotation; + Vector3 vector = ((inheritRBVelocity && (bool)rb) ? (rb.velocity + transform.TransformVector(velocity)) : transform.TransformVector(velocity)); + syncState.Throw(position, rotation, vector); + } + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/MountsManager.cs b/ROUNDS/Photon.Pun.Simple/MountsManager.cs new file mode 100644 index 0000000..81bc6f1 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/MountsManager.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[AddComponentMenu("")] +[DisallowMultipleComponent] +public class MountsManager : MonoBehaviour, IOnAwake, IOnPreQuit +{ + [NonSerialized] + public Dictionary<int, Mount> mountIdLookup = new Dictionary<int, Mount>(); + + [NonSerialized] + public List<Mount> indexedMounts = new List<Mount>(); + + [NonSerialized] + public int bitsForMountId; + + public void OnAwake() + { + CollectMounts(); + bitsForMountId = ((indexedMounts.Count != 0) ? (indexedMounts.Count - 1).GetBitsForMaxValue() : 0); + } + + public void OnPreQuit() + { + UnmountAll(); + } + + public List<Mount> CollectMounts(bool force = false) + { + indexedMounts.Clear(); + mountIdLookup.Clear(); + base.transform.GetNestedComponentsInChildren<Mount, NetObject>(indexedMounts); + int i = 0; + for (int count = indexedMounts.Count; i < count; i++) + { + Mount mount = indexedMounts[i]; + mount.componentIndex = i; + int id = mount.mountType.id; + if (!mountIdLookup.ContainsKey(id)) + { + mountIdLookup.Add(id, mount); + } + } + return indexedMounts; + } + + public Mount GetMount(int mountId) + { + mountIdLookup.TryGetValue(mountId, out var value); + return value; + } + + public void UnmountAll() + { + int i = 0; + for (int count = indexedMounts.Count; i < count; i++) + { + indexedMounts[i].DismountAll(); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetComponent.cs b/ROUNDS/Photon.Pun.Simple/NetComponent.cs new file mode 100644 index 0000000..887cd89 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetComponent.cs @@ -0,0 +1,115 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +[HelpURL("https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simpleoverview")] +public abstract class NetComponent : MonoBehaviour, IOnJoinedRoom, IOnAwake, IOnStart, IOnEnable, IOnDisable, IOnAuthorityChanged +{ + [HideInInspector] + [SerializeField] + protected int prefabInstanceId; + + protected NetObject netObj; + + protected PhotonView photonView; + + protected bool hadFirstAuthorityAssgn; + + public NetObject NetObj => netObj; + + public RigidbodyType RigidbodyType { get; private set; } + + public int ViewID => photonView.ViewID; + + public PhotonView PhotonView => photonView; + + public bool IsMine => photonView.IsMine; + + public int ControllerActorNr => photonView.ControllerActorNr; + + protected virtual void Reset() + { + } + + protected virtual void OnValidate() + { + } + + public virtual void OnJoinedRoom() + { + } + + public void Awake() + { + if (!base.transform.GetParentComponent<NetObject>()) + { + OnAwakeInitialize(isNetObject: false); + } + } + + public virtual void OnAwake() + { + netObj = base.transform.GetParentComponent<NetObject>(); + EnsureComponentsDependenciesExist(); + OnAwakeInitialize(isNetObject: true); + } + + public virtual void OnAwakeInitialize(bool isNetObject) + { + } + + protected virtual NetObject EnsureComponentsDependenciesExist() + { + if (!netObj) + { + netObj = base.transform.GetParentComponent<NetObject>(); + } + if ((bool)netObj) + { + photonView = netObj.GetComponent<PhotonView>(); + RigidbodyType = (netObj.Rb ? RigidbodyType.RB : (netObj.Rb2D ? RigidbodyType.RB2D : RigidbodyType.None)); + return netObj; + } + Debug.LogError("NetComponent derived class cannot find a NetObject on '" + base.transform.root.name + "'."); + return null; + } + + public virtual void Start() + { + if (!netObj) + { + OnStartInitialize(isNetObject: false); + } + } + + public virtual void OnStart() + { + OnStartInitialize(isNetObject: true); + } + + public virtual void OnStartInitialize(bool isNetObject) + { + } + + public virtual void OnPostEnable() + { + } + + public virtual void OnPostDisable() + { + hadFirstAuthorityAssgn = false; + } + + public virtual void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + if (controllerChanged && !hadFirstAuthorityAssgn) + { + OnFirstAuthorityAssign(isMine, controllerChanged); + hadFirstAuthorityAssgn = true; + } + } + + public virtual void OnFirstAuthorityAssign(bool isMine, bool asServer) + { + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetMaster.cs b/ROUNDS/Photon.Pun.Simple/NetMaster.cs new file mode 100644 index 0000000..acc48ab --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetMaster.cs @@ -0,0 +1,334 @@ +using ExitGames.Client.Photon; +using Photon.Compression; +using Photon.Pun.Simple.Internal; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[HelpURL("https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simpleoverview")] +public class NetMaster : MonoBehaviour +{ + public static NetMaster single; + + public static bool isShuttingDown; + + protected static float lastSentTickTime; + + private static int _currFrameId; + + private static int _currSubFrameId; + + private static int _prevFrameId; + + private static int _prevSubFrameId; + + protected static float rtt; + + private bool simulationHasRun; + + public const int BITS_FOR_NETOBJ_SIZE = 16; + + public static int CurrentFrameId => _currFrameId; + + public static int CurrentSubFrameId => _currSubFrameId; + + public static int PreviousFrameId => _prevFrameId; + + public static int PreviousSubFrameId => _prevSubFrameId; + + public static float NormTimeSinceFixed { get; private set; } + + public static float RTT => rtt; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void EnsureExistsInScene() + { + if (!SettingsScriptableObject<TickEngineSettings>.Single.enableTickEngine) + { + return; + } + GameObject gameObject = null; + if ((bool)single) + { + gameObject = single.gameObject; + } + else + { + if ((bool)NetMasterLate.single) + { + gameObject = NetMasterLate.single.gameObject; + } + single = Object.FindObjectOfType<NetMaster>(); + if ((bool)single) + { + gameObject = single.gameObject; + } + else + { + if (!gameObject) + { + gameObject = new GameObject("Net Master"); + } + single = gameObject.AddComponent<NetMaster>(); + } + } + if (!NetMasterLate.single) + { + NetMasterLate.single = Object.FindObjectOfType<NetMasterLate>(); + if (!NetMasterLate.single) + { + NetMasterLate.single = gameObject.AddComponent<NetMasterLate>(); + } + } + NetMsgCallbacks.RegisterCallback(ReceiveMessage); + } + + private void Awake() + { + if ((bool)single && single != this) + { + Object.Destroy(single); + } + single = this; + Object.DontDestroyOnLoad(this); + _prevFrameId = TickEngineSettings.frameCount - 1; + _prevSubFrameId = TickEngineSettings.sendEveryXTick - 1; + } + + private void OnApplicationQuit() + { + isShuttingDown = true; + NetMasterCallbacks.OnPreQuitCallbacks(); + } + + private void FixedUpdate() + { + if ((NetObject.activeControlledNetObjs.Count == 0 && NetObject.activeUncontrolledNetObjs.Count == 0) || !SettingsScriptableObject<TickEngineSettings>.single.enableTickEngine) + { + return; + } + if (!NetMsgSends.ReadyToSend) + { + DoubleTime.SnapFixed(); + return; + } + if (simulationHasRun) + { + PostSimulate(); + } + DoubleTime.SnapFixed(); + bool flag = true; + while (PhotonNetwork.InRoom && PhotonNetwork.IsMessageQueueRunning && flag) + { + flag = PhotonNetwork.NetworkingClient.LoadBalancingPeer.DispatchIncomingCommands(); + } + rtt = (float)PhotonNetwork.GetPing() * 0.001f; + simulationHasRun = true; + } + + private void Update() + { + if ((NetObject.activeControlledNetObjs.Count != 0 || NetObject.activeUncontrolledNetObjs.Count != 0) && SettingsScriptableObject<TickEngineSettings>.single.enableTickEngine) + { + if (simulationHasRun) + { + PostSimulate(); + } + DoubleTime.SnapUpdate(); + NormTimeSinceFixed = (Time.time - Time.fixedTime) / Time.fixedDeltaTime; + NetMasterCallbacks.OnPreUpdateCallbacks(); + float t = (Time.time - lastSentTickTime) / TickEngineSettings.netTickInterval; + NetObject.NetObjDictsLocked = true; + NonAllocDictionary<int, NetObject>.ValueIterator enumerator = NetObject.activeUncontrolledNetObjs.Values.GetEnumerator(); + while (enumerator.MoveNext()) + { + enumerator.Current.OnInterpolate(_prevFrameId, _currFrameId, t); + } + NetObject.NetObjDictsLocked = false; + NetMasterCallbacks.OnInterpolateCallbacks(_prevFrameId, _currFrameId, t); + } + } + + private void LateUpdate() + { + NetMasterCallbacks.OnPreLateUpdateCallbacks(); + } + + private void PostSimulate() + { + bool flag = _currSubFrameId == TickEngineSettings.sendEveryXTick - 1; + NetMasterCallbacks.OnPostSimulateCallbacks(_currFrameId, _currSubFrameId, flag); + if (flag) + { + SerializeAllAndSend(); + } + IncrementFrameId(); + simulationHasRun = false; + } + + private static void IncrementFrameId() + { + _prevSubFrameId = _currSubFrameId; + _currSubFrameId++; + if (_currSubFrameId >= TickEngineSettings.sendEveryXTick) + { + _currSubFrameId = 0; + _prevFrameId = _currFrameId; + _currFrameId++; + if (_currFrameId >= TickEngineSettings.frameCount) + { + _currFrameId = 0; + } + } + NetMasterCallbacks.OnIncrementFrameCallbacks(_currFrameId, _currSubFrameId, _prevFrameId, _prevSubFrameId); + if (_currSubFrameId == 0) + { + TickManager.PreSnapshot(_currFrameId); + NetObject.NetObjDictsLocked = true; + NonAllocDictionary<int, NetObject>.ValueIterator enumerator = NetObject.activeUncontrolledNetObjs.Values.GetEnumerator(); + while (enumerator.MoveNext()) + { + enumerator.Current.OnSnapshot(_currFrameId); + } + NetObject.NetObjDictsLocked = false; + NetMasterCallbacks.OnSnapshotCallbacks(_currFrameId); + TickManager.PostSnapshot(_currFrameId); + lastSentTickTime = Time.fixedTime; + } + } + + private static void SerializeAllAndSend() + { + byte[] reusableBuffer = NetMsgSends.reusableBuffer; + int bitposition = 0; + SerializationFlags writeFlags; + SerializationFlags flags; + if (TickManager.needToSendInitialForNewConn) + { + writeFlags = (SerializationFlags)22; + flags = SerializationFlags.HasContent; + TickManager.needToSendInitialForNewConn = false; + } + else + { + writeFlags = SerializationFlags.None; + flags = SerializationFlags.None; + } + reusableBuffer.Write((uint)_currFrameId, ref bitposition, TickEngineSettings.frameCountBits); + NetMasterCallbacks.OnPreSerializeTickCallbacks(_currFrameId, reusableBuffer, ref bitposition); + NetObject.NetObjDictsLocked = true; + SerializeNetObjDict(NetObject.activeControlledNetObjs, reusableBuffer, ref bitposition, ref flags, writeFlags); + NetObject.NetObjDictsLocked = false; + while (NetMasterCallbacks.postSerializationActions.Count > 0) + { + NetMasterCallbacks.postSerializationActions.Dequeue()(); + } + if (flags != 0) + { + reusableBuffer.WritePackedBytes(0uL, ref bitposition, 32); + reusableBuffer.Send(bitposition, null, flags, flush: true); + } + } + + private static void SerializeNetObjDict(NonAllocDictionary<int, NetObject> dict, byte[] buffer, ref int bitposition, ref SerializationFlags flags, SerializationFlags writeFlags) + { + NonAllocDictionary<int, NetObject>.ValueIterator enumerator = dict.Values.GetEnumerator(); + while (enumerator.MoveNext()) + { + NetObject current = enumerator.Current; + int num = bitposition; + buffer.WritePackedBytes((uint)current.ViewID, ref bitposition, 32); + int num2 = bitposition; + buffer.WriteBool(b: true, ref bitposition); + int bitposition2 = bitposition; + bitposition += 16; + SerializationFlags serializationFlags = current.OnNetSerialize(_currFrameId, buffer, ref bitposition, writeFlags); + if (serializationFlags == SerializationFlags.None) + { + if (current.SkipWhenEmpty) + { + bitposition = num; + continue; + } + bitposition = num2; + buffer.WriteBool(b: false, ref bitposition); + } + else + { + flags |= serializationFlags; + int num3 = bitposition - bitposition2; + buffer.Write((uint)num3, ref bitposition2, 16); + } + } + } + + public static void ReceiveMessage(object conn, int connId, byte[] buffer) + { + _ = TickEngineSettings.frameCount; + int bitposition = 0; + int originFrameId = (int)buffer.Read(ref bitposition, TickEngineSettings.frameCountBits); + TickManager.LogIncomingFrame(connId, originFrameId, out var arrival); + while (true) + { + int num = (int)buffer.ReadPackedBytes(ref bitposition, 32); + if (num == 0) + { + break; + } + bool flag = buffer.ReadBool(ref bitposition); + if (!flag) + { + continue; + } + int num2 = bitposition; + int num3 = (int)buffer.Read(ref bitposition, 16); + int num4 = num2 + num3; + PhotonView photonView = PhotonNetwork.GetPhotonView(num); + NetObject netObject = (photonView ? photonView.GetComponent<NetObject>() : null); + if ((object)netObject == null) + { + bitposition = num4; + continue; + } + if (netObject.IgnoreNonControllerUpdates) + { + int controllerActorNr = photonView.ControllerActorNr; + int ownerActorNr = photonView.OwnerActorNr; + if (controllerActorNr == -1) + { + photonView.SetControllerInternal(connId); + } + else if (controllerActorNr != connId && ownerActorNr != connId) + { + bitposition = num4; + continue; + } + } + netObject.OnDeserialize(connId, originFrameId, buffer, ref bitposition, flag, arrival); + bitposition = num4; + } + } + + public static FrameArrival CheckFrameArrival(int incomingFrame) + { + int num = incomingFrame - _prevFrameId; + if (num == 0) + { + return FrameArrival.IsSnap; + } + if (num < 0) + { + num += TickEngineSettings.frameCount; + } + if (num == 1) + { + return FrameArrival.IsTarget; + } + if (num >= TickEngineSettings.halfFrameCount) + { + return FrameArrival.IsLate; + } + return FrameArrival.IsFuture; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetMasterCallbacks.cs b/ROUNDS/Photon.Pun.Simple/NetMasterCallbacks.cs new file mode 100644 index 0000000..a49fae5 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetMasterCallbacks.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using Photon.Pun.Simple.Internal; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public static class NetMasterCallbacks +{ + public struct DelayedRegistrationItem + { + public object comp; + + public bool register; + + public DelayedRegistrationItem(object comp, bool register) + { + this.comp = comp; + this.register = register; + } + } + + public static List<IOnTickPreSerialization> onTickPreSerializations = new List<IOnTickPreSerialization>(); + + public static List<IOnPreUpdate> onPreUpdates = new List<IOnPreUpdate>(); + + public static List<IOnPostUpdate> onPostUpdates = new List<IOnPostUpdate>(); + + public static List<IOnPreLateUpdate> onPreLateUpdates = new List<IOnPreLateUpdate>(); + + public static List<IOnPostLateUpdate> onPostLateUpdates = new List<IOnPostLateUpdate>(); + + public static List<IOnIncrementFrame> onIncrementFrames = new List<IOnIncrementFrame>(); + + public static List<IOnPreSimulate> onPreSimulates = new List<IOnPreSimulate>(); + + public static List<IOnPostSimulate> onPostSimulates = new List<IOnPostSimulate>(); + + public static List<IOnTickSnapshot> onSnapshots = new List<IOnTickSnapshot>(); + + public static List<IOnInterpolate> onInterpolates = new List<IOnInterpolate>(); + + public static List<IOnPreQuit> onPreQuits = new List<IOnPreQuit>(); + + public static Queue<Action> postCallbackActions = new Queue<Action>(); + + public static Queue<Action> postSimulateActions = new Queue<Action>(); + + public static Queue<Action> postSerializationActions = new Queue<Action>(); + + public static Queue<DelayedRegistrationItem> pendingRegistrations = new Queue<DelayedRegistrationItem>(); + + private static bool callbacksLocked; + + public static bool CallbacksLocked + { + set + { + callbacksLocked = value; + if (!value) + { + while (pendingRegistrations.Count > 0) + { + DelayedRegistrationItem delayedRegistrationItem = pendingRegistrations.Dequeue(); + RegisterCallbackInterfaces(delayedRegistrationItem.comp, delayedRegistrationItem.register); + } + while (postCallbackActions.Count > 0) + { + postCallbackActions.Dequeue()(); + } + } + } + } + + public static void RegisterCallbackInterfaces(object comp, bool register = true, bool delay = false) + { + if (delay || callbacksLocked) + { + pendingRegistrations.Enqueue(new DelayedRegistrationItem(comp, register)); + return; + } + CallbackUtilities.RegisterInterface(onPreUpdates, comp, register); + CallbackUtilities.RegisterInterface(onPostUpdates, comp, register); + CallbackUtilities.RegisterInterface(onPreLateUpdates, comp, register); + CallbackUtilities.RegisterInterface(onPostLateUpdates, comp, register); + CallbackUtilities.RegisterInterface(onIncrementFrames, comp, register); + CallbackUtilities.RegisterInterface(onPreSimulates, comp, register); + CallbackUtilities.RegisterInterface(onPostSimulates, comp, register); + CallbackUtilities.RegisterInterface(onSnapshots, comp, register); + CallbackUtilities.RegisterInterface(onInterpolates, comp, register); + CallbackUtilities.RegisterInterface(onPreQuits, comp, register); + } + + public static void OnPreQuitCallbacks() + { + CallbacksLocked = true; + int i = 0; + for (int count = onPreQuits.Count; i < count; i++) + { + onPreQuits[i].OnPreQuit(); + } + CallbacksLocked = false; + } + + public static void OnPreUpdateCallbacks() + { + CallbacksLocked = true; + int i = 0; + for (int count = onPreUpdates.Count; i < count; i++) + { + onPreUpdates[i].OnPreUpdate(); + } + CallbacksLocked = false; + } + + public static void OnInterpolateCallbacks(int _prevFrameId, int _currFrameId, float t) + { + CallbacksLocked = true; + int i = 0; + for (int count = onInterpolates.Count; i < count; i++) + { + onInterpolates[i].OnInterpolate(_prevFrameId, _currFrameId, t); + } + CallbacksLocked = false; + } + + public static void OnPreLateUpdateCallbacks() + { + CallbacksLocked = true; + int i = 0; + for (int count = onPreLateUpdates.Count; i < count; i++) + { + onPreLateUpdates[i].OnPreLateUpdate(); + } + CallbacksLocked = false; + } + + public static void OnPostSimulateCallbacks(int _currFrameId, int _currSubFrameId, bool isNetTick) + { + CallbacksLocked = true; + int i = 0; + for (int count = onPostSimulates.Count; i < count; i++) + { + onPostSimulates[i].OnPostSimulate(_currFrameId, _currSubFrameId, isNetTick); + } + CallbacksLocked = false; + } + + public static void OnIncrementFrameCallbacks(int _currFrameId, int _currSubFrameId, int _prevFrameId, int _prevSubFrameId) + { + CallbacksLocked = true; + int i = 0; + for (int count = onIncrementFrames.Count; i < count; i++) + { + onIncrementFrames[i].OnIncrementFrame(_currFrameId, _currSubFrameId, _prevFrameId, _prevSubFrameId); + } + CallbacksLocked = false; + } + + public static void OnSnapshotCallbacks(int _currFrameId) + { + CallbacksLocked = true; + int i = 0; + for (int count = onSnapshots.Count; i < count; i++) + { + onSnapshots[i].OnSnapshot(_currFrameId); + } + CallbacksLocked = false; + while (postSimulateActions.Count > 0) + { + postSimulateActions.Dequeue()(); + } + } + + public static void OnPreSerializeTickCallbacks(int _currFrameId, byte[] buffer, ref int bitposition) + { + CallbacksLocked = true; + int i = 0; + for (int count = onTickPreSerializations.Count; i < count; i++) + { + onTickPreSerializations[i].OnPreSerializeTick(_currFrameId, buffer, ref bitposition); + } + CallbacksLocked = false; + } + + public static void OnPreSimulateCallbacks(int currentFrameId, int currentSubFrameId) + { + CallbacksLocked = true; + int i = 0; + for (int count = onPreSimulates.Count; i < count; i++) + { + IOnPreSimulate onPreSimulate = onPreSimulates[i]; + Behaviour behaviour = onPreSimulate as Behaviour; + if (!behaviour || (behaviour.isActiveAndEnabled && behaviour.gameObject.activeInHierarchy)) + { + onPreSimulate.OnPreSimulate(currentFrameId, currentSubFrameId); + } + } + CallbacksLocked = false; + } + + public static void OnPostUpdateCallbacks() + { + CallbacksLocked = true; + int i = 0; + for (int count = onPostUpdates.Count; i < count; i++) + { + IOnPostUpdate onPostUpdate = onPostUpdates[i]; + Behaviour behaviour = onPostUpdate as Behaviour; + if (!behaviour || (behaviour.isActiveAndEnabled && behaviour.gameObject.activeInHierarchy)) + { + onPostUpdate.OnPostUpdate(); + } + } + CallbacksLocked = false; + } + + public static void OnPostLateUpdateCallbacks() + { + CallbacksLocked = true; + int i = 0; + for (int count = onPostLateUpdates.Count; i < count; i++) + { + IOnPostLateUpdate onPostLateUpdate = onPostLateUpdates[i]; + Behaviour behaviour = onPostLateUpdate as Behaviour; + if (!behaviour || (behaviour.isActiveAndEnabled && behaviour.gameObject.activeInHierarchy)) + { + onPostLateUpdate.OnPostLateUpdate(); + } + } + CallbacksLocked = false; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetMasterLate.cs b/ROUNDS/Photon.Pun.Simple/NetMasterLate.cs new file mode 100644 index 0000000..bd28b99 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetMasterLate.cs @@ -0,0 +1,44 @@ +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[HelpURL("https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simpleoverview")] +public class NetMasterLate : MonoBehaviour +{ + public static NetMasterLate single; + + private void Awake() + { + if ((bool)single && single != this) + { + Object.Destroy(single); + } + single = this; + Object.DontDestroyOnLoad(this); + } + + private void FixedUpdate() + { + if (SettingsScriptableObject<TickEngineSettings>.single.enableTickEngine && (NetObject.activeControlledNetObjs.Count != 0 || NetObject.activeUncontrolledNetObjs.Count != 0)) + { + NetMasterCallbacks.OnPreSimulateCallbacks(NetMaster.CurrentFrameId, NetMaster.CurrentSubFrameId); + } + } + + private void Update() + { + if (SettingsScriptableObject<TickEngineSettings>.single.enableTickEngine && (NetObject.activeControlledNetObjs.Count != 0 || NetObject.activeUncontrolledNetObjs.Count != 0)) + { + NetMasterCallbacks.OnPostUpdateCallbacks(); + } + } + + private void LateUpdate() + { + if (SettingsScriptableObject<TickEngineSettings>.single.enableTickEngine && (NetObject.activeControlledNetObjs.Count != 0 || NetObject.activeUncontrolledNetObjs.Count != 0)) + { + NetMasterCallbacks.OnPostLateUpdateCallbacks(); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetObject.cs b/ROUNDS/Photon.Pun.Simple/NetObject.cs new file mode 100644 index 0000000..ccf9958 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetObject.cs @@ -0,0 +1,917 @@ +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using Photon.Compression; +using Photon.Compression.Internal; +using Photon.Pun.Simple.Internal; +using Photon.Realtime; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[DisallowMultipleComponent] +[HelpURL("https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simpleoverview")] +[RequireComponent(typeof(PhotonView))] +public class NetObject : MonoBehaviour, IMatchmakingCallbacks, IOnPhotonViewPreNetDestroy, IPhotonViewCallback, IOnPhotonViewOwnerChange, IOnPhotonViewControllerChange, IOnPreUpdate, IOnPreSimulate, IOnPostSimulate, IOnQuantize, IOnIncrementFrame, IOnPreQuit +{ + private class PackObjRecord + { + public Component component; + + public PackObjectDatabase.PackObjectInfo info; + + public PackFrame[] packFrames; + + public FastBitMask128 prevReadyMask; + + public FastBitMask128 readyMask; + + public IPackObjOnReadyChange onReadyCallback; + } + + [SerializeField] + [HideInInspector] + [Tooltip("Enabling this will tell the serializer to completely exclude this net object from serialization if none of its content has changed. While this will remove heartbeat data, It may also produce undesirable extrapolation and buffer resizing behavior, as receiving clients will see this as a network failure.")] + protected bool skipWhenEmpty; + + [SerializeField] + [HideInInspector] + [Tooltip("Controls if incoming NetObject updates from a current non-owner/controller should be ignored. The exception to this is if the controller is currently null/-1, which indicates that the initial ownership messages from the Master has not yet arrived or been applied, in which case the first arriving updates originating Player will be treated as the current Controller, regardless of this setting.")] + protected bool ignoreNonControllerUpdates = true; + + [SerializeField] + [HideInInspector] + [Tooltip("When enabled, if a frame update for this Net Object arrives AFTER that frame number has already been applied (it will have been reconstructed/extrapolated with a best guess), the incoming update will be immediately applied, and all frames between that frame and the current snapshot will be reapplied.")] + protected bool resimulateLateArrivals = true; + + protected Rigidbody _rigidbody; + + protected Rigidbody2D _rigidbody2D; + + public static NonAllocDictionary<int, NetObject> activeControlledNetObjs = new NonAllocDictionary<int, NetObject>(); + + public static NonAllocDictionary<int, NetObject> activeUncontrolledNetObjs = new NonAllocDictionary<int, NetObject>(); + + private static Queue<NetObject> pendingActiveNetObjDictChanges = new Queue<NetObject>(); + + private static bool netObjDictsLocked; + + [NonSerialized] + public Dictionary<Component, int> colliderLookup = new Dictionary<Component, int>(); + + [NonSerialized] + public List<Component> indexedColliders = new List<Component>(); + + [NonSerialized] + public int bitsForColliderIndex; + + [NonSerialized] + public FastBitMask128 frameValidMask; + + [NonSerialized] + public int[] originHistory; + + [NonSerialized] + public FastBitMask128 syncObjReadyMask; + + [NonSerialized] + public FastBitMask128 packObjReadyMask; + + [NonSerialized] + private readonly Dictionary<Component, int> packObjIndexLookup = new Dictionary<Component, int>(); + + private bool _allObjsAreReady; + + protected int viewID; + + [NonSerialized] + public PhotonView photonView; + + private static List<Component> reusableComponents = new List<Component>(); + + private static readonly List<IOnJoinedRoom> onJoinedRoomCallbacks = new List<IOnJoinedRoom>(); + + private static readonly List<IOnAwake> onAwakeCallbacks = new List<IOnAwake>(); + + private static readonly List<IOnStart> onStartCallbacks = new List<IOnStart>(); + + private readonly List<IOnEnable> onEnableCallbacks = new List<IOnEnable>(); + + private readonly List<IOnDisable> onDisableCallbacks = new List<IOnDisable>(); + + public readonly List<IOnPreUpdate> onPreUpdateCallbacks = new List<IOnPreUpdate>(); + + public readonly List<IOnAuthorityChanged> onAuthorityChangedCallbacks = new List<IOnAuthorityChanged>(); + + public readonly List<IOnNetSerialize> onNetSerializeCallbacks = new List<IOnNetSerialize>(); + + public readonly List<IOnCriticallyLateFrame> onCriticallyLateFrameCallbacks = new List<IOnCriticallyLateFrame>(); + + public readonly List<IOnIncrementFrame> onIncrementFramesCallbacks = new List<IOnIncrementFrame>(); + + public readonly List<IOnSnapshot> onSnapshotCallbacks = new List<IOnSnapshot>(); + + public readonly List<IOnQuantize> onQuantizeCallbacks = new List<IOnQuantize>(); + + public readonly List<IOnInterpolate> onInterpolateCallbacks = new List<IOnInterpolate>(); + + public readonly List<IOnCaptureState> onCaptureCurrentStateCallbacks = new List<IOnCaptureState>(); + + public readonly List<IOnPreSimulate> onPreSimulateCallbacks = new List<IOnPreSimulate>(); + + public readonly List<IOnPostSimulate> onPostSimulateCallbacks = new List<IOnPostSimulate>(); + + public readonly List<IOnPreQuit> onPreQuitCallbacks = new List<IOnPreQuit>(); + + public readonly List<IOnPreNetDestroy> onPreNetDestroyCallbacks = new List<IOnPreNetDestroy>(); + + private readonly List<IOnNetObjReady> onNetObjReadyCallbacks = new List<IOnNetObjReady>(); + + private readonly List<SyncObject> syncObjects = new List<SyncObject>(); + + private readonly List<PackObjRecord> packObjects = new List<PackObjRecord>(); + + private bool processedInitialBacklog; + + private float firstDeserializeTime; + + public bool SkipWhenEmpty => skipWhenEmpty; + + public bool IgnoreNonControllerUpdates => ignoreNonControllerUpdates; + + public bool ResimulateLateArrivals => resimulateLateArrivals; + + public Rigidbody Rb => _rigidbody; + + public Rigidbody2D Rb2D => _rigidbody2D; + + public static bool NetObjDictsLocked + { + set + { + netObjDictsLocked = value; + if (!value) + { + int i = 0; + for (int count = pendingActiveNetObjDictChanges.Count; i < count; i++) + { + NetObject netObject = pendingActiveNetObjDictChanges.Dequeue(); + netObject.DetermineActiveAndControlled(netObject.photonView.IsMine); + } + } + } + } + + public bool AllObjsAreReady + { + get + { + if (!photonView.IsMine) + { + return _allObjsAreReady; + } + return true; + } + private set + { + if (_allObjsAreReady != value) + { + _allObjsAreReady = value; + for (int i = 0; i < onNetObjReadyCallbacks.Count; i++) + { + onNetObjReadyCallbacks[i].OnNetObjReadyChange(value); + } + packObjReadyMask.SetAllTrue(); + syncObjReadyMask.SetAllTrue(); + } + } + } + + public int ViewID => viewID; + + public void OnSyncObjReadyChange(SyncObject sobj, ReadyStateEnum readyState) + { + int syncObjIndex = sobj.SyncObjIndex; + if (readyState != 0) + { + syncObjReadyMask[syncObjIndex] = true; + } + else + { + syncObjReadyMask[syncObjIndex] = false; + } + AllObjsAreReady = syncObjReadyMask.AllAreTrue && packObjReadyMask.AllAreTrue; + } + + public void OnPackObjReadyChange(Component pobj, ReadyStateEnum readyState) + { + int bit = packObjIndexLookup[pobj]; + if (readyState != 0) + { + packObjReadyMask[bit] = true; + } + else + { + packObjReadyMask[bit] = false; + } + AllObjsAreReady = syncObjReadyMask.AllAreTrue && packObjReadyMask.AllAreTrue; + } + + protected void Awake() + { + frameValidMask = new FastBitMask128(TickEngineSettings.frameCount); + originHistory = new int[TickEngineSettings.frameCount]; + int i = 0; + for (int frameCount = TickEngineSettings.frameCount; i < frameCount; i++) + { + originHistory[i] = -1; + } + if (!_rigidbody) + { + _rigidbody = base.transform.GetNestedComponentInChildren<Rigidbody, NetObject>(includeInactive: true); + } + if (!_rigidbody) + { + _rigidbody2D = base.transform.GetNestedComponentInChildren<Rigidbody2D, NetObject>(includeInactive: true); + } + photonView = GetComponent<PhotonView>(); + if (photonView == null) + { + Debug.LogWarning("PhotonView missing from NetObject on GameObject '" + base.name + "'. One will be added to suppress errors, but this object will likely not be networked correctly."); + photonView = base.gameObject.AddComponent<PhotonView>(); + } + CollectAndReorderInterfaces(); + this.IndexColliders(); + base.transform.GetNestedComponentsInChildren<IOnAwake, NetObject>(onAwakeCallbacks); + int j = 0; + for (int count = onAwakeCallbacks.Count; j < count; j++) + { + onAwakeCallbacks[j].OnAwake(); + } + } + + private void Start() + { + base.transform.GetNestedComponentsInChildren<IOnStart, NetObject>(onStartCallbacks); + int i = 0; + for (int count = onStartCallbacks.Count; i < count; i++) + { + onStartCallbacks[i].OnStart(); + } + if (PhotonNetwork.IsConnectedAndReady) + { + OnChangeAuthority(photonView.IsMine, controllerHasChanged: true); + } + viewID = photonView.ViewID; + } + + private void OnEnable() + { + NetMasterCallbacks.RegisterCallbackInterfaces(this); + PhotonNetwork.AddCallbackTarget(this); + photonView.AddCallbackTarget(this); + DetermineActiveAndControlled(photonView.IsMine); + int i = 0; + for (int count = onEnableCallbacks.Count; i < count; i++) + { + onEnableCallbacks[i].OnPostEnable(); + } + } + + private void OnDisable() + { + PhotonNetwork.RemoveCallbackTarget(this); + photonView.RemoveCallbackTarget(this); + NetMasterCallbacks.RegisterCallbackInterfaces(this, register: false); + DetermineActiveAndControlled(photonView.IsMine); + int i = 0; + for (int count = onDisableCallbacks.Count; i < count; i++) + { + onDisableCallbacks[i].OnPostDisable(); + } + } + + public void OnPreQuit() + { + int i = 0; + _ = onPreQuitCallbacks.Count; + for (; i < onPreQuitCallbacks.Count; i++) + { + onPreQuitCallbacks[i].OnPreQuit(); + } + } + + public void OnPreNetDestroy(PhotonView rootView) + { + NetObject component = rootView.GetComponent<NetObject>(); + if (!(component == null)) + { + int i = 0; + for (int count = onPreNetDestroyCallbacks.Count; i < count; i++) + { + onPreNetDestroyCallbacks[i].OnPreNetDestroy(component); + } + } + } + + private void OnDestroy() + { + if (activeControlledNetObjs.ContainsKey(photonView.ViewID)) + { + activeControlledNetObjs.Remove(photonView.ViewID); + } + if (activeUncontrolledNetObjs.ContainsKey(photonView.ViewID)) + { + activeUncontrolledNetObjs.Remove(photonView.ViewID); + } + } + + public virtual void PrepareForDestroy() + { + MountsManager component = GetComponent<MountsManager>(); + if ((bool)component) + { + component.UnmountAll(); + } + } + + public void OnOwnerChange(Photon.Realtime.Player newOwner, Photon.Realtime.Player previousOwner) + { + OnChangeAuthority(photonView.IsMine, controllerHasChanged: true); + } + + public void OnControllerChange(Photon.Realtime.Player newController, Photon.Realtime.Player previousController) + { + OnChangeAuthority(photonView.IsMine, controllerHasChanged: true); + } + + public void OnFriendListUpdate(List<FriendInfo> friendList) + { + } + + public void OnCreatedRoom() + { + } + + public void OnCreateRoomFailed(short returnCode, string message) + { + } + + public void OnJoinedRoom() + { + base.transform.GetNestedComponentsInChildren<IOnJoinedRoom, NetObject>(onJoinedRoomCallbacks); + int i = 0; + for (int count = onJoinedRoomCallbacks.Count; i < count; i++) + { + onJoinedRoomCallbacks[i].OnJoinedRoom(); + } + OnChangeAuthority(photonView.IsMine, controllerHasChanged: true); + } + + public void OnJoinRoomFailed(short returnCode, string message) + { + } + + public void OnJoinRandomFailed(short returnCode, string message) + { + } + + public void OnLeftRoom() + { + } + + private void DetermineActiveAndControlled(bool amController) + { + int key = photonView.ViewID; + if (netObjDictsLocked) + { + pendingActiveNetObjDictChanges.Enqueue(this); + return; + } + bool flag = activeControlledNetObjs.ContainsKey(key); + bool flag2 = activeUncontrolledNetObjs.ContainsKey(key); + if (base.isActiveAndEnabled) + { + if (amController) + { + if (!flag) + { + activeControlledNetObjs.Add(key, this); + } + if (flag2) + { + activeUncontrolledNetObjs.Remove(key); + } + } + else + { + if (flag) + { + activeControlledNetObjs.Remove(key); + } + if (!flag2) + { + activeUncontrolledNetObjs.Add(key, this); + } + } + } + else + { + if (flag) + { + activeControlledNetObjs.Remove(key); + } + if (flag2) + { + activeUncontrolledNetObjs.Remove(key); + } + } + } + + public void OnChangeAuthority(bool isMine, bool controllerHasChanged) + { + DetermineActiveAndControlled(isMine); + int i = 0; + for (int count = onAuthorityChangedCallbacks.Count; i < count; i++) + { + onAuthorityChangedCallbacks[i].OnAuthorityChanged(isMine, controllerHasChanged); + } + if (isMine) + { + AllObjsAreReady = true; + } + } + + private void CollectAndReorderInterfaces() + { + base.transform.GetNestedComponentsInChildren<Component, NetObject>(reusableComponents); + int i = 0; + int count = reusableComponents.Count; + for (; i <= 24; i++) + { + for (int j = 0; j < count; j++) + { + Component component = reusableComponents[j]; + if (component == this) + { + continue; + } + if (!(component is IApplyOrder applyOrder)) + { + if (i == 13) + { + AddInterfaces(component); + AddPackObjects(component); + } + } + else if (applyOrder.ApplyOrder == i) + { + AddInterfaces(component); + } + } + } + syncObjReadyMask = new FastBitMask128(syncObjects.Count); + packObjReadyMask = new FastBitMask128(packObjects.Count); + for (int k = 0; k < syncObjects.Count; k++) + { + SyncObject syncObject = syncObjects[k]; + syncObject.SyncObjIndex = k; + OnSyncObjReadyChange(syncObject, syncObject.ReadyState); + } + } + + public void RemoveInterfaces(Component comp) + { + AddInterfaces(comp, remove: true); + } + + private void AddInterfaces(Component comp, bool remove = false) + { + AddInterfaceToList(comp, onEnableCallbacks, remove); + AddInterfaceToList(comp, onDisableCallbacks, remove); + AddInterfaceToList(comp, onPreUpdateCallbacks, remove); + AddInterfaceToList(comp, onAuthorityChangedCallbacks, remove); + AddInterfaceToList(comp, onCaptureCurrentStateCallbacks, remove); + AddInterfaceToList(comp, onNetSerializeCallbacks, remove, checkSerializationOptional: true); + AddInterfaceToList(comp, onQuantizeCallbacks, remove, checkSerializationOptional: true); + AddInterfaceToList(comp, onIncrementFramesCallbacks, remove, checkSerializationOptional: true); + AddInterfaceToList(comp, onSnapshotCallbacks, remove, checkSerializationOptional: true); + AddInterfaceToList(comp, onCriticallyLateFrameCallbacks, remove, checkSerializationOptional: true); + AddInterfaceToList(comp, onInterpolateCallbacks, remove, checkSerializationOptional: true); + AddInterfaceToList(comp, onPreSimulateCallbacks, remove); + AddInterfaceToList(comp, onPostSimulateCallbacks, remove); + AddInterfaceToList(comp, onPreQuitCallbacks, remove); + AddInterfaceToList(comp, onPreNetDestroyCallbacks, remove); + AddInterfaceToList(comp, onNetObjReadyCallbacks, remove); + AddInterfaceToList(comp, syncObjects, remove); + } + + private void AddInterfaceToList<T>(object comp, List<T> list, bool remove, bool checkSerializationOptional = false) where T : class + { + if (comp is T val && (!checkSerializationOptional || !(val is ISerializationOptional serializationOptional) || serializationOptional.IncludeInSerialization)) + { + T item = comp as T; + if (remove && list.Contains(item)) + { + list.Remove(item); + } + else + { + list.Add(item); + } + } + } + + private void AddPackObjects(Component comp) + { + if (comp == null) + { + return; + } + Type type = comp.GetType(); + if (comp.GetType().GetCustomAttributes(typeof(PackObjectAttribute), inherit: false).Length != 0) + { + PackObjectDatabase.PackObjectInfo packObjectInfo = PackObjectDatabase.GetPackObjectInfo(type); + if (packObjectInfo != null) + { + PackObjRecord item = new PackObjRecord + { + component = comp, + onReadyCallback = (comp as IPackObjOnReadyChange), + info = packObjectInfo, + packFrames = packObjectInfo.FactoryFramesObj(comp, TickEngineSettings.frameCount), + prevReadyMask = new FastBitMask128(packObjectInfo.fieldCount), + readyMask = new FastBitMask128(packObjectInfo.fieldCount) + }; + packObjIndexLookup.Add(comp, packObjects.Count); + packObjects.Add(item); + } + } + } + + public void OnPreUpdate() + { + int i = 0; + for (int count = onPreUpdateCallbacks.Count; i < count; i++) + { + onPreUpdateCallbacks[i].OnPreUpdate(); + } + } + + public SerializationFlags GenerateMessage(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + OnCaptureCurrentState(frameId); + OnQuantize(frameId); + return OnSerialize(frameId, buffer, ref bitposition, writeFlags); + } + + public SerializationFlags OnSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + SerializationFlags serializationFlags = writeFlags; + int num = ((frameId == 0) ? TickEngineSettings.frameCount : frameId) - 1; + int count = packObjects.Count; + for (int i = 0; i < count; i++) + { + PackObjRecord packObjRecord = packObjects[i]; + PackFrame packFrame = packObjRecord.packFrames[frameId]; + int fieldCount = packObjRecord.info.fieldCount; + int bitposition2 = bitposition; + bitposition += fieldCount; + int maskOffset = 0; + serializationFlags |= packObjRecord.info.PackFrameToBuffer(packFrame, packObjRecord.packFrames[num], ref packFrame.mask, ref maskOffset, buffer, ref bitposition, frameId, writeFlags); + for (int j = 0; j < fieldCount; j++) + { + buffer.WriteBool(packFrame.mask[j], ref bitposition2); + } + } + int k = 0; + for (int count2 = onNetSerializeCallbacks.Count; k < count2; k++) + { + serializationFlags |= onNetSerializeCallbacks[k].OnNetSerialize(frameId, buffer, ref bitposition, writeFlags); + } + return serializationFlags; + } + + public void OnDeserialize(int connId, int originFrameId, byte[] buffer, ref int bitposition, bool hasData, FrameArrival arrival) + { + if (!hasData) + { + return; + } + frameValidMask[originFrameId] = true; + originHistory[originFrameId] = connId; + int count = packObjects.Count; + for (int i = 0; i < count; i++) + { + PackObjRecord packObjRecord = packObjects[i]; + PackFrame packFrame = packObjRecord.packFrames[originFrameId]; + int fieldCount = packObjRecord.info.fieldCount; + for (int j = 0; j < fieldCount; j++) + { + packFrame.mask[j] = buffer.ReadBool(ref bitposition); + } + int maskOffset = 0; + SerializationFlags serializationFlags = packObjRecord.info.UnpackFrameFromBuffer(packFrame, ref packFrame.mask, ref packFrame.isCompleteMask, ref maskOffset, buffer, ref bitposition, originFrameId, SerializationFlags.None); + if (arrival >= FrameArrival.IsSnap && !packObjRecord.readyMask.AllAreTrue && (serializationFlags & SerializationFlags.IsComplete) != 0) + { + packObjRecord.readyMask.OR(packObjRecord.info.defaultReadyMask); + packObjRecord.readyMask.OR(packFrame.isCompleteMask); + FastBitMask128 mask = !packObjRecord.readyMask & packFrame.mask; + maskOffset = 0; + packObjRecord.info.CopyFrameToObj(packFrame, packObjRecord.component, ref mask, ref maskOffset); + BroadcastReadyMaskChange(packObjRecord); + } + } + int k = 0; + for (int count2 = onNetSerializeCallbacks.Count; k < count2; k++) + { + onNetSerializeCallbacks[k].OnNetDeserialize(originFrameId, buffer, ref bitposition, arrival); + } + if (!resimulateLateArrivals || arrival < FrameArrival.IsSnap) + { + return; + } + int frameCount = TickEngineSettings.frameCount; + int num = originFrameId + 1; + if (num >= frameCount) + { + num -= frameCount; + } + int num2 = originFrameId; + int num3 = originFrameId - 1; + if (num3 < 0) + { + num3 += frameCount; + } + for (int l = 0; l <= (int)arrival; l++) + { + int m = 0; + for (int count3 = onSnapshotCallbacks.Count; m < count3; m++) + { + bool prevIsValid = frameValidMask[num3]; + bool snapIsValid = frameValidMask[num2]; + bool targIsValid = frameValidMask[num]; + onSnapshotCallbacks[m].OnSnapshot(num3, num2, num, prevIsValid, snapIsValid, targIsValid); + } + if (l == (int)arrival) + { + break; + } + num3 = num2; + num2 = num; + num++; + if (num >= frameCount) + { + num -= frameCount; + } + } + int n = 0; + for (int count4 = onCriticallyLateFrameCallbacks.Count; n < count4; n++) + { + onCriticallyLateFrameCallbacks[n].HandleCriticallyLateFrame(originFrameId); + } + } + + public void OnPreSimulate(int frameId, int _currSubFrameId) + { + int i = 0; + for (int count = onPreSimulateCallbacks.Count; i < count; i++) + { + IOnPreSimulate onPreSimulate = onPreSimulateCallbacks[i]; + Behaviour behaviour = onPreSimulate as Behaviour; + if (behaviour.enabled && behaviour.gameObject.activeInHierarchy) + { + onPreSimulate.OnPreSimulate(frameId, _currSubFrameId); + } + } + } + + public void OnPostSimulate(int frameId, int subFrameId, bool isNetTick) + { + int i = 0; + for (int count = onPostSimulateCallbacks.Count; i < count; i++) + { + IOnPostSimulate onPostSimulate = onPostSimulateCallbacks[i]; + Behaviour behaviour = onPostSimulate as Behaviour; + if (behaviour.enabled && behaviour.gameObject.activeInHierarchy) + { + onPostSimulate.OnPostSimulate(frameId, subFrameId, isNetTick); + } + } + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + if (photonView.Group != 0) + { + buffer = NetMsgSends.reusableNetObjBuffer; + int bitposition2 = 0; + buffer.Write((uint)frameId, ref bitposition2, TickEngineSettings.frameCountBits); + buffer.WritePackedBytes((uint)viewID, ref bitposition2, 32); + int num = bitposition2; + buffer.WriteBool(b: true, ref bitposition2); + int bitposition3 = bitposition2; + bitposition2 += 16; + SerializationFlags serializationFlags = GenerateMessage(frameId, buffer, ref bitposition2, writeFlags); + if (serializationFlags == SerializationFlags.None) + { + if (skipWhenEmpty) + { + return SerializationFlags.None; + } + bitposition2 = num; + buffer.WriteBool(b: false, ref bitposition); + } + if (serializationFlags != 0 || !SkipWhenEmpty) + { + buffer.Write((uint)(bitposition2 - bitposition3), ref bitposition3, 16); + buffer.WritePackedBytes(0uL, ref bitposition2, 32); + buffer.Send(bitposition2, base.gameObject, serializationFlags); + } + return SerializationFlags.None; + } + return GenerateMessage(frameId, buffer, ref bitposition, writeFlags); + } + + public void OnCaptureCurrentState(int frameId) + { + int count = packObjects.Count; + for (int i = 0; i < count; i++) + { + PackObjRecord packObjRecord = packObjects[i]; + packObjRecord.info.CaptureObj(packObjRecord.component, packObjRecord.packFrames[frameId]); + } + int j = 0; + for (int count2 = onCaptureCurrentStateCallbacks.Count; j < count2; j++) + { + onCaptureCurrentStateCallbacks[j].OnCaptureCurrentState(frameId); + } + } + + public void OnQuantize(int frameId) + { + int i = 0; + for (int count = onQuantizeCallbacks.Count; i < count; i++) + { + IOnQuantize onQuantize = onQuantizeCallbacks[i]; + Behaviour behaviour = onQuantize as Behaviour; + if (behaviour.enabled && behaviour.gameObject.activeInHierarchy) + { + onQuantize.OnQuantize(frameId); + } + } + } + + public void OnIncrementFrame(int newFrameId, int newSubFrameId, int previousFrameId, int prevSubFrameId) + { + int i = 0; + for (int count = onIncrementFramesCallbacks.Count; i < count; i++) + { + onIncrementFramesCallbacks[i].OnIncrementFrame(newFrameId, newSubFrameId, previousFrameId, prevSubFrameId); + } + } + + public bool OnSnapshot(int localTargFrameId) + { + if (!photonView) + { + return false; + } + if (!photonView.enabled) + { + return false; + } + if (!TickManager.perConnOffsets.TryGetValue(photonView.ControllerActorNr, out var value)) + { + return false; + } + if (value == null) + { + return false; + } + if (!value.hadInitialSnapshot) + { + return false; + } + int advanceCount = value.advanceCount; + if (advanceCount == 0) + { + return false; + } + int frameCount = TickEngineSettings.frameCount; + int num = value.ConvertFrameLocalToOrigin(localTargFrameId); + int num2 = num - 1; + if (num2 < 0) + { + num2 += frameCount; + } + int num3 = num - 2; + if (num3 < 0) + { + num3 += frameCount; + } + int frameCount2 = TickEngineSettings.frameCount; + int i = 0; + int num4 = num; + for (; i < advanceCount; i++) + { + num4 = num + i; + if (num4 >= frameCount2) + { + num4 -= frameCount2; + } + int num5 = num4 - TickEngineSettings.halfFrameCount; + if (num5 < 0) + { + num5 += frameCount2; + } + bool flag = frameValidMask[num2]; + bool flag2 = frameValidMask[num4]; + int count = packObjects.Count; + for (int j = 0; j < count; j++) + { + PackObjRecord packObjRecord = packObjects[j]; + PackFrame packFrame = packObjRecord.packFrames[num2]; + PackFrame packFrame2 = packObjRecord.packFrames[num4]; + packObjRecord.readyMask.OR(packObjRecord.info.defaultReadyMask); + packObjRecord.readyMask.OR(packFrame.isCompleteMask); + if (!flag2) + { + packObjRecord.info.CopyFrameToFrame(packFrame, packFrame2); + } + int maskOffset = 0; + packObjRecord.info.SnapObject(packFrame, packFrame2, packObjRecord.component, ref packObjRecord.readyMask, ref maskOffset); + if (flag) + { + maskOffset = 0; + packObjRecord.info.CopyFrameToObj(packFrame, packObjRecord.component, ref packFrame.mask, ref maskOffset); + } + if (!packObjRecord.readyMask.Compare(packObjRecord.prevReadyMask)) + { + BroadcastReadyMaskChange(packObjRecord); + } + } + bool prevIsValid = frameValidMask[num3]; + bool snapIsValid = frameValidMask[num2]; + bool targIsValid = frameValidMask[num4]; + int k = 0; + for (int count2 = onSnapshotCallbacks.Count; k < count2; k++) + { + onSnapshotCallbacks[k].OnSnapshot(num3, num2, num4, prevIsValid, snapIsValid, targIsValid); + } + num3 = num2; + num2 = num4; + frameValidMask[num5] = false; + } + return true; + } + + private void BroadcastReadyMaskChange(PackObjRecord p) + { + OnPackObjReadyChange(p.component, p.readyMask.AllAreTrue ? ReadyStateEnum.Ready : ReadyStateEnum.Unready); + p.onReadyCallback?.OnPackObjReadyChange(p.readyMask, p.readyMask.AllAreTrue); + p.prevReadyMask.Copy(p.readyMask); + } + + public bool OnInterpolate(int localSnapFrameId, int localTargFrameId, float t) + { + if (!TickManager.perConnOffsets.TryGetValue(photonView.ControllerActorNr, out var value)) + { + return false; + } + if (value == null) + { + return false; + } + if (!value.hadInitialSnapshot) + { + return false; + } + int num = value.ConvertFrameLocalToOrigin(localSnapFrameId); + int num2 = value.ConvertFrameLocalToOrigin(localTargFrameId); + if (value.validFrameMask[num2]) + { + int count = packObjects.Count; + for (int i = 0; i < count; i++) + { + PackObjRecord packObjRecord = packObjects[i]; + PackFrame start = packObjRecord.packFrames[num]; + PackFrame end = packObjRecord.packFrames[num2]; + int maskOffset = 0; + packObjRecord.info.InterpFrameToObj(start, end, packObjRecord.component, t, ref packObjRecord.readyMask, ref maskOffset); + } + } + int j = 0; + for (int count2 = onInterpolateCallbacks.Count; j < count2; j++) + { + IOnInterpolate onInterpolate = onInterpolateCallbacks[j]; + Behaviour behaviour = onInterpolate as Behaviour; + if (behaviour.enabled && behaviour.gameObject.activeInHierarchy) + { + onInterpolate.OnInterpolate(num, num2, t); + } + } + return true; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetworkHit.cs b/ROUNDS/Photon.Pun.Simple/NetworkHit.cs new file mode 100644 index 0000000..79294f6 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetworkHit.cs @@ -0,0 +1,34 @@ +using Photon.Compression; + +namespace Photon.Pun.Simple; + +public struct NetworkHit +{ + public readonly int netObjId; + + public readonly int hitMask; + + public readonly int colliderId; + + public NetworkHit(int objectID, int hitMask, int colliderId) + { + netObjId = objectID; + this.hitMask = hitMask; + this.colliderId = colliderId; + } + + public void Serialize(byte[] buffer, ref int bitposition, int bitsForHitmask, int bitsForColliderId) + { + buffer.WritePackedBytes((ulong)netObjId, ref bitposition, 32); + buffer.Write((ulong)hitMask, ref bitposition, bitsForHitmask); + buffer.Write((ulong)colliderId, ref bitposition, bitsForColliderId); + } + + public static NetworkHit Deserialize(byte[] buffer, ref int bitposition, int bitsForHitmask, int bitsForColliderId) + { + int objectID = (int)buffer.ReadPackedBytes(ref bitposition, 32); + int num = (int)buffer.Read(ref bitposition, bitsForHitmask); + int num2 = (int)buffer.Read(ref bitposition, bitsForColliderId); + return new NetworkHit(objectID, num, num2); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/NetworkHits.cs b/ROUNDS/Photon.Pun.Simple/NetworkHits.cs new file mode 100644 index 0000000..9b03244 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/NetworkHits.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using Photon.Compression; + +namespace Photon.Pun.Simple; + +public class NetworkHits +{ + public readonly List<NetworkHit> hits = new List<NetworkHit>(); + + public bool nearestOnly; + + public int nearestIndex = -1; + + public int bitsForContactGroupMask; + + public NetworkHits(bool nearestOnly, int bitsForContactGroupMask) + { + this.nearestOnly = nearestOnly; + this.bitsForContactGroupMask = bitsForContactGroupMask; + } + + public void Reset(bool nearestOnly, int bitsForContactGroupMask) + { + this.nearestOnly = nearestOnly; + this.bitsForContactGroupMask = bitsForContactGroupMask; + hits.Clear(); + nearestIndex = -1; + } + + public void Clear() + { + hits.Clear(); + nearestIndex = -1; + } + + public SerializationFlags Serialize(byte[] buffer, ref int bitposition, int bitsForColliderId) + { + SerializationFlags result = SerializationFlags.None; + if (nearestOnly) + { + if (nearestIndex != -1) + { + buffer.WriteBool(b: true, ref bitposition); + hits[nearestIndex].Serialize(buffer, ref bitposition, bitsForContactGroupMask, bitsForColliderId); + result = SerializationFlags.HasContent; + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + } + else + { + int i = 0; + _ = hits.Count; + for (; i < hits.Count; i++) + { + buffer.WriteBool(b: true, ref bitposition); + hits[i].Serialize(buffer, ref bitposition, bitsForContactGroupMask, bitsForColliderId); + result = SerializationFlags.HasContent; + } + buffer.WriteBool(b: false, ref bitposition); + } + return result; + } + + public SerializationFlags Deserialize(byte[] buffer, ref int bitposition, int bitsForColliderId) + { + hits.Clear(); + SerializationFlags result = SerializationFlags.None; + if (nearestOnly) + { + if (buffer.ReadBool(ref bitposition)) + { + hits.Add(NetworkHit.Deserialize(buffer, ref bitposition, bitsForContactGroupMask, bitsForColliderId)); + result = SerializationFlags.HasContent; + nearestIndex = 0; + } + else + { + nearestIndex = -1; + } + } + else + { + while (buffer.ReadBool(ref bitposition)) + { + hits.Add(NetworkHit.Deserialize(buffer, ref bitposition, bitsForContactGroupMask, bitsForColliderId)); + result = SerializationFlags.HasContent; + } + } + return result; + } + + public override string ToString() + { + string text = GetType().Name; + for (int i = 0; i < hits.Count; i++) + { + text = text + "\nObj:" + hits[i].netObjId + " Mask:" + hits[i].hitMask; + } + return text; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ObjState.cs b/ROUNDS/Photon.Pun.Simple/ObjState.cs new file mode 100644 index 0000000..5deea0c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ObjState.cs @@ -0,0 +1,13 @@ +namespace Photon.Pun.Simple; + +public enum ObjState +{ + Despawned = 0, + Visible = 1, + Mounted = 2, + AnchoredPosition = 4, + AnchoredRotation = 8, + Anchored = 12, + Dropped = 16, + Transit = 32 +} diff --git a/ROUNDS/Photon.Pun.Simple/ObjStateEditor.cs b/ROUNDS/Photon.Pun.Simple/ObjStateEditor.cs new file mode 100644 index 0000000..7160234 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ObjStateEditor.cs @@ -0,0 +1,12 @@ +namespace Photon.Pun.Simple; + +public enum ObjStateEditor +{ + Despawned = 0, + Visible = 1, + Mounted = 2, + AnchoredPosition = 4, + AnchoredRotation = 8, + Dropped = 0x10, + Transit = 0x20 +} diff --git a/ROUNDS/Photon.Pun.Simple/ObjStateLogic.cs b/ROUNDS/Photon.Pun.Simple/ObjStateLogic.cs new file mode 100644 index 0000000..72d74a1 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ObjStateLogic.cs @@ -0,0 +1,19 @@ +using System; + +namespace Photon.Pun.Simple; + +[Serializable] +public class ObjStateLogic : MaskLogic +{ + protected static int[] stateValues = (int[])Enum.GetValues(typeof(ObjStateEditor)); + + protected static string[] stateNames = Enum.GetNames(typeof(ObjStateEditor)); + + protected override bool DefinesZero => true; + + protected override string[] EnumNames => stateNames; + + protected override int[] EnumValues => stateValues; + + protected override int DefaultValue => 1; +} diff --git a/ROUNDS/Photon.Pun.Simple/OnStateChangeKinematic.cs b/ROUNDS/Photon.Pun.Simple/OnStateChangeKinematic.cs new file mode 100644 index 0000000..62c08bf --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/OnStateChangeKinematic.cs @@ -0,0 +1,132 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +[DisallowMultipleComponent] +public class OnStateChangeKinematic : NetComponent, IOnStateChange, IApplyOrder, IAutoKinematic +{ + public KinematicSetting onDespawned = KinematicSetting.Kinematic; + + public KinematicSetting onAnchored = KinematicSetting.Kinematic; + + public KinematicSetting onMounted = KinematicSetting.NonKinematic; + + public KinematicSetting onTransit = KinematicSetting.NonKinematic; + + public KinematicSetting onDropped = KinematicSetting.NonKinematic; + + public KinematicSetting onVisible = KinematicSetting.Default; + + [Tooltip("Destroy this component if no Rigidbodies exist on this GameObject.")] + public bool autoDestroy = true; + + private ObjState currentState; + + private Rigidbody rb; + + private Rigidbody2D rb2d; + + private bool kinematicDefault; + + private int interpolateDefault; + + public int ApplyOrder => 11; + + public bool AutoKinematicEnabled => true; + + public override void OnAwake() + { + base.OnAwake(); + rb = netObj.Rb; + rb2d = netObj.Rb2D; + if ((bool)rb) + { + kinematicDefault = rb.isKinematic; + interpolateDefault = (int)rb.interpolation; + } + else if ((bool)rb2d) + { + kinematicDefault = rb2d.isKinematic; + interpolateDefault = (int)rb2d.interpolation; + } + if (autoDestroy && !rb && !rb2d) + { + Object.Destroy(this); + } + SetOwnedKinematics(currentState); + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + if (isMine) + { + SetOwnedKinematics(currentState); + } + else + { + SetUnownedKinematics(); + } + } + + public void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true) + { + if (base.IsMine) + { + SetOwnedKinematics(newState); + } + } + + protected virtual void SetUnownedKinematics() + { + if (base.RigidbodyType != 0) + { + if (base.RigidbodyType == RigidbodyType.RB) + { + rb.isKinematic = true; + rb.interpolation = RigidbodyInterpolation.None; + } + else + { + rb2d.isKinematic = true; + rb2d.interpolation = RigidbodyInterpolation2D.None; + } + } + } + + protected virtual void SetOwnedKinematics(ObjState state) + { + if (base.RigidbodyType == RigidbodyType.None) + { + return; + } + bool flag = ((state == ObjState.Despawned && onDespawned != 0) ? onDespawned : (((state & ObjState.Anchored) != 0 && onAnchored != 0) ? onAnchored : (((state & ObjState.Mounted) != 0 && onMounted != 0) ? onMounted : (((state & ObjState.Transit) != 0 && onTransit != 0) ? onTransit : (((state & ObjState.Dropped) != 0 && onDropped != 0) ? onDropped : (((state & ObjState.Visible) == 0 || onVisible == KinematicSetting.Ignore) ? KinematicSetting.Default : onVisible)))))) switch + { + KinematicSetting.Kinematic => true, + KinematicSetting.NonKinematic => false, + _ => kinematicDefault, + }; + if (base.RigidbodyType == RigidbodyType.RB) + { + rb.position = base.transform.position; + if (flag) + { + rb.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative; + rb.isKinematic = true; + } + else + { + rb.isKinematic = false; + } + rb.interpolation = ((state != 0 && (state & ObjState.Mounted) == 0) ? ((RigidbodyInterpolation)interpolateDefault) : RigidbodyInterpolation.None); + } + else + { + rb2d.position = base.transform.position; + rb2d.isKinematic = flag; + rb2d.simulated = !flag; + rb2d.interpolation = ((state != 0 && (state & ObjState.Mounted) == 0) ? ((RigidbodyInterpolation2D)interpolateDefault) : RigidbodyInterpolation2D.None); + } + currentState = state; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/OnStateChangeToggle.cs b/ROUNDS/Photon.Pun.Simple/OnStateChangeToggle.cs new file mode 100644 index 0000000..cf26399 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/OnStateChangeToggle.cs @@ -0,0 +1,94 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class OnStateChangeToggle : NetComponent, IOnStateChange +{ + [HideInInspector] + [Tooltip("How this object should be toggled. GameObject toggles gameObject.SetActive(), Renderer toggles renderer.enabled, and Component toggles component.enabled.")] + public DisplayToggle toggle; + + [Tooltip("User specified component to toggle enabled.")] + [HideInInspector] + public Component component; + + [HideInInspector] + public GameObject _gameObject; + + [HideInInspector] + public Renderer _renderer; + + [HideInInspector] + public ObjStateLogic stateLogic = new ObjStateLogic(); + + private bool reactToAttached; + + private MonoBehaviour monob; + + private bool show; + + public override void OnAwake() + { + base.OnAwake(); + if (toggle == DisplayToggle.Renderer) + { + if (_renderer == null) + { + _renderer = GetComponent<Renderer>(); + } + } + else if (toggle == DisplayToggle.Component) + { + monob = component as MonoBehaviour; + } + else if (_gameObject == null) + { + _gameObject = base.gameObject; + } + stateLogic.RecalculateMasks(); + reactToAttached = (stateLogic.notMask & 2) == 0 && (stateLogic.stateMask & 2) != 0; + } + + public void OnStateChange(ObjState newState, ObjState previousState, Transform pickup, Mount attachedTo = null, bool isReady = true) + { + if (!isReady) + { + show = false; + } + else if (stateLogic.Evaluate((int)newState)) + { + show = true; + if (reactToAttached && attachedTo == null && (newState & ObjState.Mounted) != 0) + { + show = false; + } + } + else + { + show = false; + } + DeferredEnable(); + } + + private void DeferredEnable() + { + switch (toggle) + { + case DisplayToggle.GameObject: + _gameObject.SetActive(show); + break; + case DisplayToggle.Component: + if ((bool)monob) + { + monob.enabled = show; + } + break; + case DisplayToggle.Renderer: + if ((bool)_renderer) + { + _renderer.enabled = show; + } + break; + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/OwnedIVitals.cs b/ROUNDS/Photon.Pun.Simple/OwnedIVitals.cs new file mode 100644 index 0000000..b6a316c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/OwnedIVitals.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; + +namespace Photon.Pun.Simple; + +public static class OwnedIVitals +{ + public static List<IVitalsSystem> ownedVitalComponents = new List<IVitalsSystem>(); + + public static List<IOnChangeOwnedVitals> iOnChangeOwnedVitals = new List<IOnChangeOwnedVitals>(); + + public static IVitalsSystem LastItem + { + get + { + int count = ownedVitalComponents.Count; + if (count <= 0) + { + return null; + } + return ownedVitalComponents[count - 1]; + } + } + + public static void OnChangeAuthority(IVitalsSystem ivc, bool isMine, bool asServer) + { + if (isMine) + { + if (!ownedVitalComponents.Contains(ivc)) + { + ownedVitalComponents.Add(ivc); + for (int i = 0; i < iOnChangeOwnedVitals.Count; i++) + { + iOnChangeOwnedVitals[i].OnChangeOwnedVitals(ivc, null); + } + } + } + else if (ownedVitalComponents.Contains(ivc)) + { + ownedVitalComponents.Remove(ivc); + for (int j = 0; j < iOnChangeOwnedVitals.Count; j++) + { + iOnChangeOwnedVitals[j].OnChangeOwnedVitals(null, ivc); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/PassThruType.cs b/ROUNDS/Photon.Pun.Simple/PassThruType.cs new file mode 100644 index 0000000..7bad959 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/PassThruType.cs @@ -0,0 +1,11 @@ +namespace Photon.Pun.Simple; + +public enum PassThruType +{ + SetTrigger, + ResetTrigger, + Play, + PlayFixed, + CrossFade, + CrossFadeFixed +} diff --git a/ROUNDS/Photon.Pun.Simple/ProjectileHelpers.cs b/ROUNDS/Photon.Pun.Simple/ProjectileHelpers.cs new file mode 100644 index 0000000..0ea9c38 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ProjectileHelpers.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public static class ProjectileHelpers +{ + public static GameObject prefab; + + public static GameObject GetPlaceholderProj() + { + if (prefab != null) + { + return prefab; + } + GameObject gameObject = new GameObject("Projectile Placeholder Prefab"); + gameObject.gameObject.SetActive(value: false); + Rigidbody rigidbody = gameObject.AddComponent<Rigidbody>(); + rigidbody.useGravity = false; + rigidbody.interpolation = RigidbodyInterpolation.Interpolate; + rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; + gameObject.AddComponent<ContactProjectile>(); + gameObject.AddComponent<ContactTrigger>(); + GameObject gameObject2 = GameObject.CreatePrimitive(PrimitiveType.Sphere); + gameObject2.transform.parent = gameObject.transform; + gameObject2.GetComponent<Collider>().isTrigger = true; + gameObject2.GetComponent<Renderer>().material.color = Color.yellow; + gameObject2.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); + prefab = gameObject; + return gameObject; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/ReadyStateEnum.cs b/ROUNDS/Photon.Pun.Simple/ReadyStateEnum.cs new file mode 100644 index 0000000..6405cf9 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/ReadyStateEnum.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum ReadyStateEnum +{ + Unready, + Ready, + Disabled +} diff --git a/ROUNDS/Photon.Pun.Simple/Replicate.cs b/ROUNDS/Photon.Pun.Simple/Replicate.cs new file mode 100644 index 0000000..06d55a4 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Replicate.cs @@ -0,0 +1,9 @@ +namespace Photon.Pun.Simple; + +public enum Replicate +{ + None, + CastOnly, + Hits, + HitsWithContactGroups +} diff --git a/ROUNDS/Photon.Pun.Simple/Replication.cs b/ROUNDS/Photon.Pun.Simple/Replication.cs new file mode 100644 index 0000000..941c700 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Replication.cs @@ -0,0 +1,7 @@ +namespace Photon.Pun.Simple; + +public enum Replication +{ + OwnerSend = 1, + MasterSend +} diff --git a/ROUNDS/Photon.Pun.Simple/RespondTo.cs b/ROUNDS/Photon.Pun.Simple/RespondTo.cs new file mode 100644 index 0000000..374117f --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/RespondTo.cs @@ -0,0 +1,9 @@ +namespace Photon.Pun.Simple; + +public enum RespondTo +{ + HitSelf = 1, + IContactTrigger = 2, + HitNetObj = 4, + HitNonNetObj = 8 +} diff --git a/ROUNDS/Photon.Pun.Simple/RigidbodyType.cs b/ROUNDS/Photon.Pun.Simple/RigidbodyType.cs new file mode 100644 index 0000000..77319af --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/RigidbodyType.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum RigidbodyType +{ + None, + RB, + RB2D +} diff --git a/ROUNDS/Photon.Pun.Simple/SimulateHealth.cs b/ROUNDS/Photon.Pun.Simple/SimulateHealth.cs new file mode 100644 index 0000000..fb143ff --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SimulateHealth.cs @@ -0,0 +1,47 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SimulateHealth : MonoBehaviour +{ + private Vitals vitals; + + public VitalNameType vitalType = new VitalNameType(VitalType.Health); + + public KeyCode AddHealthKey = KeyCode.Alpha6; + + public KeyCode RemHealthKey = KeyCode.Alpha7; + + public KeyCode DamagehKey = KeyCode.Alpha8; + + public float amount = 20f; + + private void Start() + { + IVitalsSystem componentInChildren = GetComponentInChildren<IVitalsSystem>(); + if (componentInChildren == null || !(componentInChildren as SyncObject).PhotonView.IsMine) + { + Object.Destroy(this); + } + else + { + vitals = componentInChildren.Vitals; + } + } + + private void Update() + { + if (Input.GetKeyDown(AddHealthKey)) + { + vitals.ApplyCharges(vitalType, amount, allowOverload: false, propagate: false); + } + if (Input.GetKeyDown(RemHealthKey)) + { + vitals.ApplyCharges(vitalType, 0f - amount, allowOverload: false, propagate: true); + } + if (Input.GetKeyDown(DamagehKey)) + { + vitals.ApplyCharges(amount, allowOverload: false, propagate: true); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/StateChangeInfo.cs b/ROUNDS/Photon.Pun.Simple/StateChangeInfo.cs new file mode 100644 index 0000000..049c0bf --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/StateChangeInfo.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public struct StateChangeInfo +{ + public ObjState objState; + + public Mount mount; + + public Vector3? offsetPos; + + public Quaternion? offsetRot; + + public Vector3? velocity; + + public bool force; + + public StateChangeInfo(StateChangeInfo src) + { + objState = src.objState; + mount = src.mount; + offsetPos = src.offsetPos; + offsetRot = src.offsetRot; + velocity = src.velocity; + force = src.force; + } + + public StateChangeInfo(ObjState itemState, Mount mount, Vector3? offsetPos, Quaternion? offsetRot, Vector3? velocity, bool force) + { + objState = itemState; + this.mount = mount; + this.offsetPos = offsetPos; + this.offsetRot = offsetRot; + this.velocity = velocity; + this.force = force; + } + + public StateChangeInfo(ObjState itemState, Mount mount, Vector3? offsetPos, Vector3? velocity, bool force) + { + objState = itemState; + this.mount = mount; + this.offsetPos = offsetPos; + offsetRot = null; + this.velocity = velocity; + this.force = force; + } + + public StateChangeInfo(ObjState itemState, Mount mount, bool force) + { + objState = itemState; + this.mount = mount; + offsetPos = null; + offsetRot = null; + velocity = null; + this.force = force; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncAdditiveMover.cs b/ROUNDS/Photon.Pun.Simple/SyncAdditiveMover.cs new file mode 100644 index 0000000..b0bc206 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncAdditiveMover.cs @@ -0,0 +1,57 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncAdditiveMover : NetComponent, ITransformController, IOnPreUpdate, IOnPreSimulate +{ + [Serializable] + public class TRSDefinition : TRSDefinitionBase + { + public Vector3 addVector = new Vector3(0f, 0f, 0f); + } + + [HideInInspector] + public TRSDefinition posDef = new TRSDefinition(); + + [HideInInspector] + public TRSDefinition rotDef = new TRSDefinition(); + + [HideInInspector] + public TRSDefinition sclDef = new TRSDefinition(); + + public bool HandlesInterpolation => true; + + public bool HandlesExtrapolation => true; + + public void OnPreSimulate(int frameId, int subFrameId) + { + if (base.isActiveAndEnabled && (!photonView || photonView.IsMine)) + { + AddVector(); + } + } + + public void OnPreUpdate() + { + if (base.isActiveAndEnabled) + { + AddVector(); + } + } + + private void AddVector() + { + float mixedDeltaTime = DoubleTime.mixedDeltaTime; + base.transform.localScale += sclDef.addVector * mixedDeltaTime; + if (rotDef.local) + { + base.transform.localEulerAngles += rotDef.addVector * mixedDeltaTime; + } + else + { + base.transform.eulerAngles += rotDef.addVector * mixedDeltaTime; + } + base.transform.Translate(posDef.addVector * mixedDeltaTime, posDef.local ? Space.Self : Space.World); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncAnimator.cs b/ROUNDS/Photon.Pun.Simple/SyncAnimator.cs new file mode 100644 index 0000000..9ec36d6 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncAnimator.cs @@ -0,0 +1,1403 @@ +using System; +using System.Collections.Generic; +using emotitron.Compression; +using Photon.Compression; +using Photon.Pun.Simple.Internal; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncAnimator : SyncObject<SyncAnimator.Frame>, IOnSnapshot, IOnNetSerialize, IOnAuthorityChanged, ISyncAnimator, IReadyable, IUseKeyframes, IOnInterpolate, IOnCaptureState +{ + public class Frame : FrameBase + { + public SyncAnimator syncAnimator; + + public SmartVar[] parameters; + + public int?[] stateHashes; + + public bool[] layerIsInTransition; + + public float[] normalizedTime; + + public float?[] layerWeights; + + public Queue<AnimPassThru> passThrus; + + public Frame() + { + } + + public Frame(SyncAnimator syncAnimator, int frameId) + : base(frameId) + { + this.syncAnimator = syncAnimator; + int layerCount = syncAnimator.layerCount; + stateHashes = new int?[layerCount]; + layerIsInTransition = new bool[layerCount]; + normalizedTime = new float[layerCount]; + layerWeights = new float?[layerCount]; + passThrus = new Queue<AnimPassThru>(2); + parameters = new SmartVar[syncAnimator.paramCount]; + int paramCount = syncAnimator.paramCount; + for (int i = 0; i < paramCount; i++) + { + parameters[i] = syncAnimator.sharedParamSettings[i].defaultValue; + } + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + Frame frame = sourceFrame as Frame; + if (syncAnimator.syncParams) + { + SmartVar[] array = frame.parameters; + int num = array.Length; + for (int i = 0; i < num; i++) + { + parameters[i] = array[i]; + } + } + if (syncAnimator.syncStates) + { + int num2 = frame.stateHashes.Length; + for (int j = 0; j < num2; j++) + { + stateHashes[j] = frame.stateHashes[j]; + layerIsInTransition[j] = frame.layerIsInTransition[j]; + normalizedTime[j] = frame.normalizedTime[j]; + layerWeights[j] = frame.layerWeights[j]; + } + } + } + + public override void Clear() + { + base.Clear(); + int i = 0; + for (int num = stateHashes.Length; i < num; i++) + { + stateHashes[i] = null; + } + passThrus.Clear(); + int j = 0; + for (int num2 = layerWeights.Length; j < num2; j++) + { + layerWeights[j] = null; + stateHashes[j] = null; + normalizedTime[j] = 0f; + layerWeights[j] = null; + } + } + } + + private static Dictionary<int, Dictionary<int, int>> masterSharedTriggHashes = new Dictionary<int, Dictionary<int, int>>(); + + private static Dictionary<int, List<int>> masterSharedTriggIndexes = new Dictionary<int, List<int>>(); + + [HideInInspector] + public List<int> sharedTriggIndexes = new List<int>(); + + private Dictionary<int, int> sharedTriggHashes; + + private static Dictionary<int, Dictionary<int, int>> masterSharedStateHashes = new Dictionary<int, Dictionary<int, int>>(); + + private static Dictionary<int, List<int>> masterSharedStateIndexes = new Dictionary<int, List<int>>(); + + [HideInInspector] + public List<int> sharedStateIndexes = new List<int>(); + + private Dictionary<int, int> sharedStateHashes; + + [Tooltip("The Animator to sync. If null the first animator on this game object will be found and used.")] + public Animator animator; + + [Tooltip("Disables applyRootMotion on any non-authority instances, to avoid a tug of war between the transform sync and root motion.")] + public bool autoRootMotion = true; + + [HideInInspector] + public bool syncPassThrus = true; + + [HideInInspector] + public NormalizedFloatCompression passthruNormTimeCompress = NormalizedFloatCompression.Bits10; + + [HideInInspector] + public bool syncStates = true; + + [HideInInspector] + public NormalizedFloatCompression normalizedTimeCompress = NormalizedFloatCompression.Bits10; + + [HideInInspector] + public bool syncLayers = true; + + [HideInInspector] + public bool syncLayerWeights = true; + + [HideInInspector] + public NormalizedFloatCompression layerWeightCompress = NormalizedFloatCompression.Bits10; + + [NonSerialized] + public int layerCount; + + [HideInInspector] + public bool syncParams = true; + + [HideInInspector] + public bool useGlobalParamSettings = true; + + private static Dictionary<int, ParameterDefaults> masterSharedParamDefaults = new Dictionary<int, ParameterDefaults>(); + + [HideInInspector] + public ParameterDefaults sharedParamDefaults = new ParameterDefaults(); + + private static Dictionary<int, ParameterSettings[]> masterSharedParamSettings = new Dictionary<int, ParameterSettings[]>(); + + [HideInInspector] + public ParameterSettings[] sharedParamSettings = new ParameterSettings[0]; + + [HideInInspector] + public int paramCount; + + private int bitsForTriggerIndex; + + private int bitsForStateIndex; + + private int bitsForTransIndex; + + private int bitsForLayerIndex; + + private bool defaultRootMotion; + + private int[] lastAnimationHash; + + private uint[] lastLayerWeight; + + private SmartVar[] lastSentParams; + + private Frame currentFrame; + + public static Dictionary<int, Stack<Frame[]>> masterSharedFramePool = new Dictionary<int, Stack<Frame[]>>(); + + private static List<Animator> foundAnimators = new List<Animator>(); + + private static List<SyncAnimator> foundSyncs = new List<SyncAnimator>(); + + private readonly Queue<AnimPassThru> passThruQueue = new Queue<AnimPassThru>(2); + + public override int ApplyOrder => 11; + + public override bool AllowReconstructionOfEmpty => false; + + protected override void PopulateFrames() + { + Initialize(); + int frameCount = TickEngineSettings.frameCount; + if (!masterSharedFramePool.TryGetValue(prefabInstanceId, out var value)) + { + value = new Stack<Frame[]>(); + masterSharedFramePool.Add(prefabInstanceId, value); + } + if (value.Count == 0) + { + frames = new Frame[frameCount + 1]; + for (int i = 0; i <= frameCount; i++) + { + frames[i] = new Frame(this, i); + } + } + else + { + frames = value.Pop(); + for (int j = 0; j <= frameCount; j++) + { + frames[j].Clear(); + } + } + } + + public override void OnAwake() + { + if (animator == null) + { + FindUnsyncedAnimator(); + } + base.OnAwake(); + ConnectSharedCaches(); + if ((bool)animator) + { + defaultRootMotion = animator.applyRootMotion; + } + } + + public override void OnJoinedRoom() + { + base.OnJoinedRoom(); + AutoRootMotion(base.IsMine); + } + + public override void OnStart() + { + base.OnStart(); + AutoRootMotion(base.IsMine); + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + AutoRootMotion(isMine); + } + + private void AutoRootMotion(bool isMine) + { + if (autoRootMotion && (bool)animator) + { + animator.applyRootMotion = isMine && defaultRootMotion; + } + } + + private void FindUnsyncedAnimator() + { + base.transform.GetNestedComponentsInChildren<Animator, NetObject>(foundAnimators); + base.transform.GetNestedComponentsInChildren<SyncAnimator, NetObject>(foundSyncs); + foreach (Animator foundAnimator in foundAnimators) + { + bool flag = false; + foreach (SyncAnimator foundSync in foundSyncs) + { + flag = false; + if (foundSync.animator == foundAnimator) + { + flag = true; + break; + } + } + if (!flag) + { + animator = foundAnimator; + break; + } + } + } + + private void Initialize() + { + bitsForTriggerIndex = (sharedTriggIndexes.Count - 1).GetBitsForMaxValue(); + bitsForStateIndex = (sharedStateIndexes.Count - 1).GetBitsForMaxValue(); + paramCount = animator.parameters.Length; + layerCount = animator.layerCount; + bitsForLayerIndex = layerCount.GetBitsForMaxValue(); + lastSentParams = new SmartVar[paramCount]; + ParameterSettings.RebuildParamSettings(animator, ref sharedParamSettings, ref paramCount, sharedParamDefaults); + lastAnimationHash = new int[layerCount]; + lastLayerWeight = new uint[layerCount]; + for (int i = 0; i < paramCount; i++) + { + lastSentParams[i] = sharedParamSettings[i].defaultValue; + } + } + + private void ConnectSharedCaches() + { + if (!masterSharedTriggHashes.ContainsKey(prefabInstanceId)) + { + sharedTriggHashes = new Dictionary<int, int>(); + for (int i = 0; i < sharedTriggIndexes.Count; i++) + { + if (sharedTriggHashes.ContainsKey(sharedTriggIndexes[i])) + { + Debug.LogError("There appear to be duplicate Trigger names in the animator controller on '" + base.name + "'. This will break " + GetType().Name + "'s ability to sync triggers."); + } + else + { + sharedTriggHashes.Add(sharedTriggIndexes[i], i); + } + } + masterSharedTriggHashes.Add(prefabInstanceId, sharedTriggHashes); + masterSharedTriggIndexes.Add(prefabInstanceId, sharedTriggIndexes); + } + else + { + sharedTriggHashes = masterSharedTriggHashes[prefabInstanceId]; + sharedTriggIndexes = masterSharedTriggIndexes[prefabInstanceId]; + } + if (!masterSharedStateHashes.ContainsKey(prefabInstanceId)) + { + sharedStateHashes = new Dictionary<int, int>(); + for (int j = 0; j < sharedStateIndexes.Count; j++) + { + if (sharedStateHashes.ContainsKey(sharedStateIndexes[j])) + { + Debug.LogError("There appear to be duplicate State names in the animator controller on '" + base.name + "'. This will break " + GetType().Name + "'s ability to sync states."); + } + else + { + sharedStateHashes.Add(sharedStateIndexes[j], j); + } + } + masterSharedStateHashes.Add(prefabInstanceId, sharedStateHashes); + masterSharedStateIndexes.Add(prefabInstanceId, sharedStateIndexes); + } + else + { + sharedStateHashes = masterSharedStateHashes[prefabInstanceId]; + sharedStateIndexes = masterSharedStateIndexes[prefabInstanceId]; + } + if (masterSharedParamDefaults.TryGetValue(prefabInstanceId, out var value)) + { + sharedParamDefaults = value; + } + else + { + masterSharedParamDefaults.Add(prefabInstanceId, sharedParamDefaults); + } + if (masterSharedParamSettings.TryGetValue(prefabInstanceId, out var value2)) + { + sharedParamSettings = value2; + } + else + { + masterSharedParamSettings.Add(prefabInstanceId, sharedParamSettings); + } + } + + private void OnDestroy() + { + masterSharedFramePool[prefabInstanceId].Push(frames); + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame frame = frames[frameId]; + if (frame.content == FrameContents.Empty) + { + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + buffer.WriteBool(b: true, ref bitposition); + bool isKeyframe = IsKeyframe(frameId); + return WriteAllToBuffer(frame, buffer, ref bitposition, isKeyframe); + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + bool isKeyframe = IsKeyframe(originFrameId); + Frame frame = (base.IsMine ? offtickFrame : frames[originFrameId]); + if (!buffer.ReadBool(ref bitposition)) + { + return SerializationFlags.None; + } + frame.content = FrameContents.Complete; + ReadAllFromBuffer(frame, buffer, ref bitposition, isKeyframe); + return SerializationFlags.HasContent; + } + + public virtual void OnCaptureCurrentState(int frameId) + { + Frame frame = frames[frameId]; + if (!base.isActiveAndEnabled || !animator.isActiveAndEnabled) + { + frame.content = FrameContents.Empty; + return; + } + if (syncParams) + { + CaptureParameters(frame); + } + if (syncPassThrus) + { + CapturePassThrus(frame); + } + if (syncStates) + { + CaptureStates(frame); + } + if (syncStates) + { + CaptureLayerWeights(frame); + } + frame.content = FrameContents.Complete; + } + + private SerializationFlags WriteAllToBuffer(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + SerializationFlags serializationFlags = SerializationFlags.None; + if (syncPassThrus) + { + serializationFlags |= WritePassThrus(frame, buffer, ref bitposition, isKeyframe); + } + if (syncParams) + { + serializationFlags |= WriteParameters(frame, buffer, ref bitposition, isKeyframe); + } + if (syncStates) + { + serializationFlags |= WriteStates(frame, buffer, ref bitposition, isKeyframe); + } + if (syncLayerWeights) + { + serializationFlags |= WriteLayerWeights(frame, buffer, ref bitposition, isKeyframe); + } + return serializationFlags; + } + + private void ReadAllFromBuffer(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + if (syncPassThrus) + { + ReadPassThrus(frame, buffer, ref bitposition, isKeyframe); + } + if (syncParams) + { + ReadParameters(frame, buffer, ref bitposition, isKeyframe); + } + if (syncStates) + { + ReadStates(frame, buffer, ref bitposition, isKeyframe); + } + if (syncLayerWeights) + { + ReadLayerWeights(frame, buffer, ref bitposition, isKeyframe); + } + } + + private SerializationFlags WriteParameters(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + SmartVar[] parameters = frame.parameters; + SerializationFlags serializationFlags = SerializationFlags.None; + for (int i = 0; i < paramCount; i++) + { + ParameterSettings parameterSettings = sharedParamSettings[i]; + if (!useGlobalParamSettings && !parameterSettings.include) + { + continue; + } + switch (parameterSettings.paramType) + { + case AnimatorControllerParameterType.Int: + { + int num3 = parameters[i]; + if (isKeyframe || num3 != (int)lastSentParams[i]) + { + if (!isKeyframe) + { + buffer.WriteBool(b: true, ref bitposition); + } + if (useGlobalParamSettings) + { + buffer.WriteSignedPackedBytes(num3, ref bitposition, 32); + } + else + { + parameterSettings.icrusher.WriteValue(num3, buffer, ref bitposition); + } + lastSentParams[i] = num3; + serializationFlags |= SerializationFlags.HasContent; + } + else if (!isKeyframe) + { + buffer.WriteBool(b: false, ref bitposition); + } + break; + } + case AnimatorControllerParameterType.Float: + { + float num = parameters[i]; + LiteFloatCrusher fcrusher = parameterSettings.fcrusher; + uint num2 = (uint)(useGlobalParamSettings ? HalfUtilities.Pack(num) : fcrusher.Encode(num)); + if (isKeyframe || num2 != lastSentParams[i].UInt) + { + if (!isKeyframe) + { + buffer.WriteBool(b: true, ref bitposition); + } + if (useGlobalParamSettings) + { + buffer.Write(num2, ref bitposition, 16); + } + else + { + fcrusher.WriteCValue(num2, buffer, ref bitposition); + } + lastSentParams[i] = num2; + serializationFlags |= SerializationFlags.HasContent; + } + else if (!isKeyframe) + { + buffer.WriteBool(b: false, ref bitposition); + } + break; + } + case AnimatorControllerParameterType.Bool: + { + bool flag2 = parameters[i]; + buffer.WriteBool(flag2, ref bitposition); + if (isKeyframe || flag2 != (bool)lastSentParams[i]) + { + serializationFlags |= SerializationFlags.HasContent; + } + break; + } + case AnimatorControllerParameterType.Trigger: + { + bool flag = parameters[i]; + buffer.WriteBool(flag, ref bitposition); + if (isKeyframe || flag != (bool)lastSentParams[i]) + { + serializationFlags |= SerializationFlags.HasContent; + } + break; + } + } + } + return serializationFlags; + } + + private void CaptureParameters(Frame frame) + { + SmartVar[] parameters = frame.parameters; + for (int i = 0; i < paramCount; i++) + { + ParameterSettings parameterSettings = sharedParamSettings[i]; + if (useGlobalParamSettings || parameterSettings.include) + { + AnimatorControllerParameterType paramType = parameterSettings.paramType; + int hash = parameterSettings.hash; + switch (paramType) + { + case AnimatorControllerParameterType.Float: + parameters[i] = animator.GetFloat(hash); + break; + case AnimatorControllerParameterType.Int: + parameters[i] = animator.GetInteger(hash); + break; + case AnimatorControllerParameterType.Bool: + parameters[i] = animator.GetBool(hash); + break; + case AnimatorControllerParameterType.Trigger: + parameters[i] = animator.GetBool(hash); + break; + } + } + } + } + + private void ReadParameters(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + SmartVar[] parameters = frame.parameters; + bool flag = frame == targFrame || frame == snapFrame; + for (int i = 0; i < paramCount; i++) + { + ParameterSettings parameterSettings = sharedParamSettings[i]; + if (!useGlobalParamSettings && !parameterSettings.include) + { + continue; + } + switch (parameterSettings.paramType) + { + case AnimatorControllerParameterType.Int: + if (isKeyframe || buffer.ReadBool(ref bitposition)) + { + int num = (useGlobalParamSettings ? buffer.ReadSignedPackedBytes(ref bitposition, 32) : parameterSettings.icrusher.ReadValue(buffer, ref bitposition)); + parameters[i] = num; + } + else if (!flag) + { + parameters[i] = SmartVar.None; + } + break; + case AnimatorControllerParameterType.Float: + if (isKeyframe || buffer.ReadBool(ref bitposition)) + { + parameters[i] = (useGlobalParamSettings ? buffer.ReadHalf(ref bitposition) : parameterSettings.fcrusher.ReadValue(buffer, ref bitposition)); + } + else if (!flag) + { + parameters[i] = SmartVar.None; + } + break; + case AnimatorControllerParameterType.Bool: + { + bool flag3 = buffer.ReadBool(ref bitposition); + parameters[i] = flag3; + break; + } + case AnimatorControllerParameterType.Trigger: + { + bool flag2 = buffer.ReadBool(ref bitposition); + parameters[i] = flag2; + break; + } + } + } + } + + private void CompleteTargetParameters() + { + SmartVar[] array = ((snapFrame != null) ? snapFrame.parameters : targFrame.parameters); + SmartVar[] parameters = targFrame.parameters; + for (int i = 0; i < paramCount; i++) + { + SmartVar smartVar = array[i]; + SmartVar smartVar2 = parameters[i]; + ParameterSettings parameterSettings = sharedParamSettings[i]; + if (smartVar.TypeCode == SmartVarTypeCode.None) + { + smartVar = (array[i] = parameterSettings.defaultValue); + } + if (smartVar2.TypeCode == SmartVarTypeCode.None) + { + parameters[i] = smartVar; + } + } + } + + private void InterpolateParams(float t) + { + SmartVar[] parameters = snapFrame.parameters; + SmartVar[] parameters2 = targFrame.parameters; + for (int i = 0; i < paramCount; i++) + { + ParameterSettings parameterSettings = sharedParamSettings[i]; + int hash = parameterSettings.hash; + if (!useGlobalParamSettings && !parameterSettings.include) + { + continue; + } + AnimatorControllerParameterType paramType = parameterSettings.paramType; + SmartVar smartVar = parameters[i]; + SmartVar smartVar2 = parameters2[i]; + if (smartVar.TypeCode == SmartVarTypeCode.None || smartVar2.TypeCode == SmartVarTypeCode.None) + { + continue; + } + switch (paramType) + { + case AnimatorControllerParameterType.Int: + { + if (!sharedParamDefaults.includeInts) + { + break; + } + if (t == 0f) + { + animator.SetInteger(hash, smartVar); + break; + } + ParameterInterpolation parameterInterpolation2 = ((!useGlobalParamSettings) ? parameterSettings.interpolate : sharedParamDefaults.interpolateInts); + if (parameterInterpolation2 != ParameterInterpolation.Hold) + { + int value = parameterInterpolation2 switch + { + ParameterInterpolation.Lerp => (int)Mathf.Lerp(smartVar, smartVar2, t), + ParameterInterpolation.Advance => smartVar2, + _ => parameterSettings.defaultValue, + }; + animator.SetInteger(hash, value); + } + break; + } + case AnimatorControllerParameterType.Float: + { + if (!sharedParamDefaults.includeFloats) + { + break; + } + if (t == 0f) + { + animator.SetFloat(hash, smartVar); + break; + } + ParameterInterpolation parameterInterpolation = ((!useGlobalParamSettings) ? parameterSettings.interpolate : sharedParamDefaults.interpolateFloats); + if (parameterInterpolation != ParameterInterpolation.Hold) + { + SmartVar smartVar3 = parameterInterpolation switch + { + ParameterInterpolation.Advance => smartVar2, + ParameterInterpolation.Lerp => Mathf.Lerp(smartVar, smartVar2, t), + _ => parameterSettings.defaultValue, + }; + animator.SetFloat(hash, smartVar3); + } + break; + } + case AnimatorControllerParameterType.Bool: + if (t == 0f && sharedParamDefaults.includeBools) + { + animator.SetBool(hash, smartVar); + } + break; + case AnimatorControllerParameterType.Trigger: + if (t == 0f && sharedParamDefaults.includeTriggers && (bool)smartVar) + { + animator.SetTrigger(hash); + } + break; + } + } + } + + private void ExtrapolateParams(Frame prev, Frame targ, Frame newtarg) + { + if (prev == null) + { + return; + } + SmartVar[] parameters = prev.parameters; + SmartVar[] parameters2 = targ.parameters; + for (int i = 0; i < paramCount; i++) + { + ParameterSettings parameterSettings = sharedParamSettings[i]; + AnimatorControllerParameterType paramType = parameterSettings.paramType; + if (useGlobalParamSettings || parameterSettings.include) + { + switch (paramType) + { + case AnimatorControllerParameterType.Float: + { + ParameterExtrapolation num = (useGlobalParamSettings ? sharedParamDefaults.extrapolateFloats : parameterSettings.extrapolate); + newtarg.parameters[i] = num switch + { + ParameterExtrapolation.Lerp => (float)parameters2[i] + ((float)parameters2[i] - (float)parameters[i]), + ParameterExtrapolation.Hold => parameters2[i], + _ => parameterSettings.defaultValue, + }; + break; + } + case AnimatorControllerParameterType.Int: + { + ParameterExtrapolation num2 = (useGlobalParamSettings ? sharedParamDefaults.extrapolateInts : parameterSettings.extrapolate); + newtarg.parameters[i] = num2 switch + { + ParameterExtrapolation.Lerp => (int)parameters2[i] + ((int)parameters2[i] - (int)parameters[i]), + ParameterExtrapolation.Hold => parameters2[i], + _ => parameterSettings.defaultValue, + }; + break; + } + case AnimatorControllerParameterType.Bool: + { + ParameterExtrapolation parameterExtrapolation2 = (useGlobalParamSettings ? sharedParamDefaults.extrapolateBools : parameterSettings.extrapolate); + newtarg.parameters[i] = ((parameterExtrapolation2 == ParameterExtrapolation.Hold) ? parameters2[i] : parameterSettings.defaultValue); + break; + } + default: + { + ParameterExtrapolation parameterExtrapolation = (useGlobalParamSettings ? sharedParamDefaults.extrapolateTriggers : parameterSettings.extrapolate); + newtarg.parameters[i] = ((parameterExtrapolation == ParameterExtrapolation.Hold) ? parameters2[i] : parameterSettings.defaultValue); + break; + } + } + } + } + } + + private void EnqueuePassthrough(PassThruType type, int hash, int layer, float ntime, float otime, float duration, LocalApplyTiming localApplyTiming) + { + AnimPassThru animPassThru = new AnimPassThru(type, hash, layer, ntime, otime, duration, localApplyTiming); + passThruQueue.Enqueue(animPassThru); + if (localApplyTiming == LocalApplyTiming.Immediately || !syncPassThrus) + { + ExecutePassThru(animPassThru); + } + } + + public void SetTrigger(string triggerName, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + int hash = Animator.StringToHash(triggerName); + EnqueuePassthrough(PassThruType.SetTrigger, hash, -1, -1f, -1f, -1f, localApplyTiming); + } + + public void SetTrigger(int hash, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + EnqueuePassthrough(PassThruType.SetTrigger, hash, -1, -1f, -1f, -1f, localApplyTiming); + } + + public void ResetTrigger(string triggerName, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + int hash = Animator.StringToHash(triggerName); + EnqueuePassthrough(PassThruType.ResetTrigger, hash, -1, -1f, -1f, -1f, localApplyTiming); + } + + public void ResetTrigger(int hash, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + EnqueuePassthrough(PassThruType.ResetTrigger, hash, -1, -1f, -1f, -1f, localApplyTiming); + } + + public void Play(string stateName, int layer = -1, float normalizedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + int hash = Animator.StringToHash(stateName); + EnqueuePassthrough(PassThruType.Play, hash, layer, normalizedTime, -1f, -1f, localApplyTiming); + } + + public void Play(int hash, int layer = -1, float normalizedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + EnqueuePassthrough(PassThruType.Play, hash, layer, normalizedTime, -1f, -1f, localApplyTiming); + } + + public void PlayInFixedTime(string stateName, int layer = -1, float fixedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + int hash = Animator.StringToHash(stateName); + EnqueuePassthrough(PassThruType.PlayFixed, hash, layer, -1f, fixedTime, -1f, localApplyTiming); + } + + public void PlayInFixedTime(int hash, int layer = -1, float fixedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + EnqueuePassthrough(PassThruType.PlayFixed, hash, layer, -1f, fixedTime, -1f, localApplyTiming); + } + + public void CrossFade(string stateName, float duration, int layer = -1, float normalizedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + int hash = Animator.StringToHash(stateName); + EnqueuePassthrough(PassThruType.CrossFade, hash, layer, normalizedTime, -1f, duration, localApplyTiming); + } + + public void CrossFade(int hash, float duration, int layer = -1, float normalizedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + EnqueuePassthrough(PassThruType.CrossFade, hash, layer, normalizedTime, -1f, duration, localApplyTiming); + } + + public void CrossFadeInFixedTime(string stateName, float duration, int layer = -1, float fixedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + int hash = Animator.StringToHash(stateName); + EnqueuePassthrough(PassThruType.CrossFadeFixed, hash, layer, -1f, fixedTime, duration, localApplyTiming); + } + + public void CrossFadeInFixedTime(int hash, float duration, int layer = -1, float fixedTime = 0f, LocalApplyTiming localApplyTiming = LocalApplyTiming.OnSend) + { + EnqueuePassthrough(PassThruType.CrossFadeFixed, hash, layer, -1f, fixedTime, duration, localApplyTiming); + } + + private void ExecutePassThruQueue(Frame frame) + { + Queue<AnimPassThru> passThrus = frame.passThrus; + while (passThrus.Count > 0) + { + AnimPassThru pt = passThrus.Dequeue(); + ExecutePassThru(pt); + } + } + + private void ExecutePassThru(AnimPassThru pt) + { + int hash = pt.hash; + switch (pt.passThruType) + { + case PassThruType.SetTrigger: + animator.SetTrigger(pt.hash); + break; + case PassThruType.ResetTrigger: + animator.ResetTrigger(pt.hash); + break; + case PassThruType.Play: + animator.Play(hash, pt.layer, pt.normlTime); + break; + case PassThruType.PlayFixed: + animator.PlayInFixedTime(hash, pt.layer, pt.fixedTime); + break; + case PassThruType.CrossFade: + animator.CrossFade(hash, pt.duration, pt.layer, pt.normlTime); + break; + case PassThruType.CrossFadeFixed: + animator.CrossFadeInFixedTime(hash, pt.duration, pt.layer, pt.fixedTime); + break; + } + } + + private SerializationFlags WritePassThrus(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + Queue<AnimPassThru> passThrus = frame.passThrus; + SerializationFlags result = ((passThrus.Count != 0) ? SerializationFlags.HasContent : SerializationFlags.None); + while (passThrus.Count > 0) + { + AnimPassThru pt = passThrus.Dequeue(); + PassThruType passThruType = pt.passThruType; + int hash = pt.hash; + bool flag = passThruType == PassThruType.SetTrigger || passThruType == PassThruType.ResetTrigger; + if (pt.localApplyTiming == LocalApplyTiming.OnSend) + { + ExecutePassThru(pt); + } + buffer.WriteBool(b: true, ref bitposition); + buffer.Write((uint)passThruType, ref bitposition, 3); + int value; + bool flag2 = (flag ? sharedTriggHashes.TryGetValue(hash, out value) : sharedStateHashes.TryGetValue(pt.hash, out value)); + buffer.WriteBool(flag2, ref bitposition); + if (flag2) + { + buffer.Write((uint)value, ref bitposition, flag ? bitsForTriggerIndex : bitsForStateIndex); + } + else + { + buffer.WriteSigned(pt.hash, ref bitposition, 32); + } + if (flag) + { + continue; + } + if (layerCount > 1) + { + buffer.Write((uint)(pt.layer + 1), ref bitposition, bitsForLayerIndex); + } + if (passThruType == PassThruType.Play || passThruType == PassThruType.CrossFade) + { + float normlTime = pt.normlTime; + if (normlTime == 0f) + { + buffer.WriteBool(b: false, ref bitposition); + } + else + { + buffer.WriteBool(b: true, ref bitposition); + buffer.WriteNorm(normlTime, ref bitposition, (int)passthruNormTimeCompress); + } + } + else + { + float fixedTime = pt.fixedTime; + if (fixedTime == 0f) + { + buffer.WriteBool(b: false, ref bitposition); + } + else + { + buffer.WriteBool(b: true, ref bitposition); + buffer.WriteHalf(fixedTime, ref bitposition); + } + } + if (passThruType == PassThruType.CrossFade || passThruType == PassThruType.CrossFadeFixed) + { + buffer.WriteHalf(pt.duration, ref bitposition); + } + } + buffer.WriteBool(b: false, ref bitposition); + return result; + } + + private void CapturePassThrus(Frame frame) + { + if (syncPassThrus) + { + while (passThruQueue.Count > 0) + { + frame.passThrus.Enqueue(passThruQueue.Dequeue()); + } + } + } + + private void ReadPassThrus(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + while (buffer.ReadBool(ref bitposition)) + { + PassThruType passThruType = (PassThruType)buffer.Read(ref bitposition, 3); + bool flag = passThruType == PassThruType.SetTrigger || passThruType == PassThruType.ResetTrigger; + int index; + if (buffer.ReadBool(ref bitposition)) + { + if (flag) + { + index = (int)buffer.Read(ref bitposition, bitsForTriggerIndex); + index = sharedTriggIndexes[index]; + } + else + { + index = (int)buffer.Read(ref bitposition, bitsForStateIndex); + index = sharedStateIndexes[index]; + } + } + else + { + index = buffer.ReadSigned(ref bitposition, 32); + } + if (flag) + { + frame.passThrus.Enqueue(new AnimPassThru(passThruType, index, -1, -1f, -1f, -1f)); + continue; + } + int layer = ((layerCount > 1) ? ((int)buffer.Read(ref bitposition, bitsForLayerIndex) - 1) : (-1)); + float normTime; + float otherTime; + if (passThruType == PassThruType.Play || passThruType == PassThruType.CrossFade) + { + normTime = (buffer.ReadBool(ref bitposition) ? buffer.ReadNorm(ref bitposition, (int)passthruNormTimeCompress) : 0f); + otherTime = -1f; + } + else + { + otherTime = (buffer.ReadBool(ref bitposition) ? buffer.ReadHalf(ref bitposition) : 0f); + normTime = -1f; + } + float duration = ((passThruType == PassThruType.CrossFade || passThruType == PassThruType.CrossFadeFixed) ? buffer.ReadHalf(ref bitposition) : (-1f)); + frame.passThrus.Enqueue(new AnimPassThru(passThruType, index, layer, normTime, otherTime, duration)); + } + } + + private void CaptureStates(Frame frame) + { + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + frame.layerWeights[i] = animator.GetLayerWeight(i); + if (animator.IsInTransition(i)) + { + frame.layerIsInTransition[i] = true; + continue; + } + AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(i); + frame.layerIsInTransition[i] = false; + frame.stateHashes[i] = currentAnimatorStateInfo.fullPathHash; + float normalizedTime = currentAnimatorStateInfo.normalizedTime; + if (normalizedTimeCompress == NormalizedFloatCompression.Full32 || normalizedTimeCompress == NormalizedFloatCompression.Half16) + { + frame.normalizedTime[i] = normalizedTime; + } + else if (currentAnimatorStateInfo.loop) + { + frame.normalizedTime[i] = ((normalizedTime > 1f) ? (normalizedTime % 1f) : normalizedTime); + } + else + { + frame.normalizedTime[i] = ((normalizedTime > 1f) ? 1f : ((normalizedTime < 0f) ? 0f : normalizedTime)); + } + } + } + + private SerializationFlags WriteStates(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + int?[] stateHashes = frame.stateHashes; + float[] normalizedTime = frame.normalizedTime; + float?[] layerWeights = frame.layerWeights; + bool[] layerIsInTransition = frame.layerIsInTransition; + SerializationFlags serializationFlags = SerializationFlags.None; + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + int? num2 = stateHashes[i]; + bool flag = !num2.HasValue || lastAnimationHash[i] != num2.Value; + if (isKeyframe || flag) + { + buffer.WriteBool(b: true, ref bitposition); + bool flag2 = layerIsInTransition[i]; + buffer.WriteBool(flag2, ref bitposition); + if (!flag2) + { + bool flag3 = sharedStateIndexes.IndexOf(num2.Value) != -1; + buffer.WriteBool(flag3, ref bitposition); + if (flag3) + { + buffer.Write((uint)sharedStateIndexes.IndexOf(num2.Value), ref bitposition, bitsForStateIndex); + } + else + { + buffer.WriteSigned(num2.Value, ref bitposition, 32); + } + float value = (normalizedTime[i] + 1f) * 0.5f; + buffer.WriteNorm(value, ref bitposition, (int)normalizedTimeCompress); + } + lastAnimationHash[i] = (num2.HasValue ? num2.Value : 0); + serializationFlags |= SerializationFlags.HasContent; + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + if (!syncLayerWeights || i == 0) + { + continue; + } + float? num3 = layerWeights[i]; + if (num3 == 1f) + { + buffer.WriteBool(b: true, ref bitposition); + serializationFlags |= SerializationFlags.HasContent; + continue; + } + buffer.WriteBool(b: false, ref bitposition); + if (num3 == 0f) + { + buffer.WriteBool(b: true, ref bitposition); + serializationFlags |= SerializationFlags.HasContent; + continue; + } + buffer.WriteBool(b: false, ref bitposition); + int bits = (int)layerWeightCompress; + uint num4 = num3.Value.CompressNorm(bits); + if (isKeyframe || lastLayerWeight[i] != num4) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write(num4, ref bitposition, bits); + lastLayerWeight[i] = num4; + serializationFlags |= SerializationFlags.HasContent; + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + } + return serializationFlags; + } + + private void ReadStates(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + int?[] stateHashes = frame.stateHashes; + float[] normalizedTime = frame.normalizedTime; + float?[] layerWeights = frame.layerWeights; + bool[] layerIsInTransition = frame.layerIsInTransition; + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + if (buffer.ReadBool(ref bitposition) && !(layerIsInTransition[i] = buffer.ReadBool(ref bitposition))) + { + bool num2 = buffer.ReadBool(ref bitposition); + int num3 = (num2 ? ((int)buffer.Read(ref bitposition, bitsForStateIndex)) : buffer.ReadSigned(ref bitposition, 32)); + if (num2) + { + num3 = sharedStateIndexes[num3]; + } + stateHashes[i] = num3; + float num4 = buffer.ReadNorm(ref bitposition, (int)normalizedTimeCompress) * 2f - 1f; + normalizedTime[i] = num4; + } + if (syncLayerWeights && i != 0) + { + if (buffer.ReadBool(ref bitposition)) + { + layerWeights[i] = 1f; + } + else if (buffer.ReadBool(ref bitposition)) + { + layerWeights[i] = 0f; + } + else if (buffer.ReadBool(ref bitposition)) + { + layerWeights[i] = buffer.ReadNorm(ref bitposition, (int)layerWeightCompress); + } + else + { + layerWeights[i] = null; + } + } + } + } + + private void ApplyState(Frame applyFrame) + { + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + int? num2 = applyFrame.stateHashes[i]; + bool flag = applyFrame.layerIsInTransition[i]; + if (!num2.HasValue) + { + continue; + } + if (!flag && num2.Value != 0) + { + animator.Play(num2.Value, i, applyFrame.normalizedTime[i]); + } + if (syncLayerWeights) + { + float? num3 = applyFrame.layerWeights[i]; + if (num3.HasValue) + { + animator.SetLayerWeight(i, num3.Value); + } + } + } + } + + private void CaptureLayerWeights(Frame frame) + { + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + frame.layerWeights[i] = animator.GetLayerWeight(i); + } + } + + private SerializationFlags WriteLayerWeights(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + float?[] layerWeights = frame.layerWeights; + SerializationFlags serializationFlags = SerializationFlags.None; + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + if (!syncLayerWeights || i == 0) + { + continue; + } + float? num2 = layerWeights[i]; + if (num2 == 1f) + { + buffer.WriteBool(b: true, ref bitposition); + serializationFlags |= SerializationFlags.HasContent; + continue; + } + buffer.WriteBool(b: false, ref bitposition); + if (num2 == 0f) + { + buffer.WriteBool(b: true, ref bitposition); + serializationFlags |= SerializationFlags.HasContent; + continue; + } + buffer.WriteBool(b: false, ref bitposition); + int bits = (int)layerWeightCompress; + uint num3 = num2.Value.CompressNorm(bits); + if (isKeyframe || lastLayerWeight[i] != num3) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write(num3, ref bitposition, bits); + lastLayerWeight[i] = num3; + serializationFlags |= SerializationFlags.HasContent; + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + } + return serializationFlags; + } + + private SerializationFlags ReadLayerWeights(Frame frame, byte[] buffer, ref int bitposition, bool isKeyframe) + { + float?[] layerWeights = frame.layerWeights; + SerializationFlags serializationFlags = SerializationFlags.None; + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + if (syncLayerWeights && i != 0) + { + if (buffer.ReadBool(ref bitposition)) + { + layerWeights[i] = 1f; + serializationFlags |= SerializationFlags.HasContent; + } + else if (buffer.ReadBool(ref bitposition)) + { + layerWeights[i] = 0f; + serializationFlags |= SerializationFlags.HasContent; + } + else if (buffer.ReadBool(ref bitposition)) + { + layerWeights[i] = buffer.ReadNorm(ref bitposition, (int)layerWeightCompress); + serializationFlags |= SerializationFlags.HasContent; + } + else + { + layerWeights[i] = null; + } + } + } + return SerializationFlags.HasContent; + } + + private void ApplyLayerWeights(Frame applyFrame) + { + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + if (syncLayerWeights) + { + float? num2 = applyFrame.layerWeights[i]; + if (num2.HasValue) + { + animator.SetLayerWeight(i, num2.Value); + } + } + } + } + + public override bool OnSnapshot(int prevFrameId, int snapFrameId, int targFrameId, bool prevIsValid, bool snapIsValid, bool targIsValid) + { + if (snapFrame != null && snapFrame.content != 0) + { + ApplyFrame(snapFrame); + } + if (!base.OnSnapshot(prevFrameId, snapFrameId, targFrameId, prevIsValid, snapIsValid, targIsValid)) + { + return false; + } + CompleteTargetParameters(); + return true; + } + + private void ApplyFrame(Frame frame) + { + if (syncStates) + { + ApplyState(frame); + } + if (syncLayerWeights) + { + ApplyLayerWeights(frame); + } + ExecutePassThruQueue(frame); + InterpolateParams(0f); + } + + public override bool OnInterpolate(int snapFrameId, int targFrameId, float t) + { + if (!base.OnInterpolate(snapFrameId, targFrameId, t)) + { + return false; + } + if (targFrame == null) + { + return false; + } + if (targFrame.content == FrameContents.Empty) + { + return false; + } + if (syncParams) + { + InterpolateParams(t); + } + return true; + } + + protected override void InterpolateFrame(Frame targframe, Frame startframe, Frame endframe, float t) + { + targframe.CopyFrom(endframe); + InterpolateState(targframe, startframe, endframe, t); + } + + protected override void ExtrapolateFrame(Frame prevframe, Frame snapframe, Frame targframe) + { + targframe.content = FrameContents.Partial; + ExtrapolateParams(prevframe, snapframe, targframe); + ExtrapolateState(); + } + + private void ExtrapolateState() + { + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + targFrame.stateHashes[i] = null; + } + } + + private void InterpolateState(Frame targFrame, Frame strFrame, Frame endFrame, float t) + { + int num = ((!syncLayers) ? 1 : layerCount); + for (int i = 0; i < num; i++) + { + int? num2 = strFrame.stateHashes[i]; + int? num3 = endFrame.stateHashes[i]; + targFrame.stateHashes[i] = num3; + float num4 = strFrame.normalizedTime[i]; + float b = endFrame.normalizedTime[i]; + if (num2 != num3 && num4 != 0f) + { + targFrame.normalizedTime[i] = Mathf.LerpUnclamped(num4, b, t); + } + else + { + targFrame.normalizedTime[i] = num4; + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncCannon.cs b/ROUNDS/Photon.Pun.Simple/SyncCannon.cs new file mode 100644 index 0000000..c985780 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncCannon.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using Photon.Pun.Simple.Pooling; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncCannon : SyncShootBase, IProjectileCannon +{ + [SerializeField] + public GameObject projPrefab; + + [SerializeField] + public Vector3 velocity = new Vector3(0f, 0f, 10f); + + [SerializeField] + [EnumMask(false, null)] + public RespondTo terminateOn = (RespondTo)12; + + [SerializeField] + [EnumMask(false, null)] + public RespondTo damageOn = (RespondTo)12; + + [Tooltip("Projectiles are advanced (lagCompensate * RTT) ms into the future on non-owner clients. This will better time align projectiles to the local players time frame (For example dodging a projectile locally is more likely to be how the shooter saw events as well). 0 = Fully in shooters time frame and 1 = Fully in the local players time frame.")] + [Range(0f, 1f)] + [SerializeField] + public float lagCompensate = 1f; + + protected static List<NetObject> reusableNetObjects = new List<NetObject>(); + + public override int ApplyOrder => 19; + + protected override void Reset() + { + base.Reset(); + } + + public override void OnAwake() + { + base.OnAwake(); + if (projPrefab == null) + { + projPrefab = ProjectileHelpers.GetPlaceholderProj(); + Pool.AddPrefabToPool(projPrefab, 8, 8, null, tidyUp: true); + } + else + { + Pool.AddPrefabToPool(projPrefab); + } + } + + protected override bool Trigger(Frame frame, int subFrameId, float timeshift = 0f) + { + Pool pool = Pool.Spawn(projPrefab, origin); + pool.GetComponent<IContactTrigger>().Proxy = contactTrigger; + IProjectile component = pool.GetComponent<IProjectile>(); + component.Initialize(this, frame.frameId, subFrameId, velocity, terminateOn, damageOn, lagCompensate * timeshift); + component.Owner = this; + return true; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncContact.cs b/ROUNDS/Photon.Pun.Simple/SyncContact.cs new file mode 100644 index 0000000..0bb96ed --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncContact.cs @@ -0,0 +1,249 @@ +using System.Collections.Generic; +using Photon.Compression; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncContact : SyncObject<SyncContact.Frame>, ISyncContact, IOnSnapshot, IOnNetSerialize, IOnAuthorityChanged, IOnCaptureState, ISerializationOptional +{ + public struct ContactRecord + { + public ContactType contactType; + + public int contactSystemViewID; + + public byte contactSystemIndex; + + public ContactRecord(int contactSystemViewID, byte contactSystemIndex, ContactType contactType) + { + this.contactSystemViewID = contactSystemViewID; + this.contactSystemIndex = contactSystemIndex; + this.contactType = contactType; + } + + public override string ToString() + { + return string.Concat(contactType, " view: ", contactSystemViewID, " index:", contactSystemIndex); + } + } + + public class Frame : FrameBase + { + public List<ContactRecord> contactRecords = new List<ContactRecord>(1); + + public Frame() + { + } + + public Frame(int frameId) + : base(frameId) + { + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + content = FrameContents.Empty; + contactRecords.Clear(); + } + + public static Frame Construct(int frameId) + { + return new Frame(frameId); + } + + public override void Clear() + { + base.Clear(); + contactRecords.Clear(); + } + } + + protected Frame currentState = new Frame(); + + protected IContactTrigger contactTrigger; + + protected Rigidbody rb; + + protected Rigidbody2D rb2d; + + protected bool _hasRigidbody; + + protected Queue<ContactEvent> queuedContactEvents = new Queue<ContactEvent>(); + + public bool HasRigidbody => _hasRigidbody; + + public GameObject VisiblePickupObj => base.gameObject; + + public override void OnAwake() + { + base.OnAwake(); + contactTrigger = GetComponent<IContactTrigger>(); + rb = GetComponentInParent<Rigidbody>(); + rb2d = GetComponentInParent<Rigidbody2D>(); + _hasRigidbody = (bool)rb || (bool)rb2d; + } + + public virtual void SyncContactEvent(ContactEvent contactEvent) + { + if (base.IsMine) + { + EnqueueEvent(contactEvent); + } + } + + protected virtual bool EnqueueEvent(ContactEvent contactEvent) + { + queuedContactEvents.Enqueue(contactEvent); + return true; + } + + public virtual void OnCaptureCurrentState(int frameId) + { + Frame frame = frames[frameId]; + frame.content = FrameContents.Empty; + while (queuedContactEvents.Count > 0) + { + ContactEvent contactEvent = queuedContactEvents.Dequeue(); + Consumption num = Contact(contactEvent); + if (num != 0) + { + frame.content = FrameContents.Complete; + List<ContactRecord> contactRecords = frame.contactRecords; + ContactRecord item = new ContactRecord(contactEvent.contactSystem.ViewID, contactEvent.contactSystem.SystemIndex, contactEvent.contactType); + contactRecords.Add(item); + } + if (num == Consumption.All) + { + break; + } + } + queuedContactEvents.Clear(); + } + + protected virtual Consumption Contact(ContactEvent contactEvent) + { + return contactTrigger.ContactCallbacks(contactEvent); + } + + protected virtual void Consume(Frame frame, ContactEvent contactEvent, Consumption consumed) + { + } + + public virtual SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame obj = frames[frameId]; + List<ContactRecord> contactRecords = obj.contactRecords; + if (obj.content == FrameContents.Complete) + { + int i = 0; + for (int count = contactRecords.Count; i < count; i++) + { + ContactRecord contactRecord = contactRecords[i]; + buffer.Write(1uL, ref bitposition, 1); + buffer.WritePackedBytes((uint)contactRecord.contactSystemViewID, ref bitposition, 32); + buffer.WritePackedBits(contactRecord.contactSystemIndex, ref bitposition, 8); + buffer.Write(contactRecord.contactType switch + { + ContactType.Stay => 1u, + ContactType.Hitscan => 3u, + ContactType.Enter => 0u, + _ => 2u, + }, ref bitposition, 2); + } + buffer.Write(0uL, ref bitposition, 1); + return (SerializationFlags)5; + } + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + Frame frame = frames[originFrameId]; + if (buffer.ReadBool(ref bitposition)) + { + do + { + List<ContactRecord> contactRecords = frame.contactRecords; + ContactRecord item = new ContactRecord((int)buffer.ReadPackedBytes(ref bitposition, 32), (byte)buffer.ReadPackedBits(ref bitposition, 8), (ContactType)(1 << (int)buffer.Read(ref bitposition, 2))); + contactRecords.Add(item); + } + while (buffer.ReadBool(ref bitposition)); + frame.content = FrameContents.Complete; + return SerializationFlags.HasContent; + } + frame.content = FrameContents.Empty; + return SerializationFlags.None; + } + + protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsValid, bool targIsValid) + { + base.ApplySnapshot(snapframe, targframe, snapIsValid, targIsValid); + if (snapframe.content != FrameContents.Complete) + { + return; + } + List<ContactRecord> contactRecords = snapframe.contactRecords; + int i = 0; + for (int count = contactRecords.Count; i < count; i++) + { + ContactRecord contactRecord = contactRecords[i]; + PhotonView photonView = PhotonNetwork.GetPhotonView(contactRecord.contactSystemViewID); + if (!photonView || !photonView.IsMine) + { + continue; + } + ContactManager component = photonView.GetComponent<ContactManager>(); + if ((bool)component) + { + IContactSystem contacting = component.GetContacting(contactRecord.contactSystemIndex); + ContactEvent contactEvent = new ContactEvent(contacting, contactTrigger, contactRecord.contactType); + Consumption consumption = Contact(contactEvent); + if (consumption != 0) + { + Consume(snapframe, contactEvent, consumption); + } + } + } + } + + protected static int ConvertMaskToIndex(int mask) + { + int num = 0; + if (mask > 32767) + { + mask >>= 16; + num += 16; + } + if (mask > 127) + { + mask >>= 8; + num += 8; + } + if (mask > 7) + { + mask >>= 4; + num += 4; + } + if (mask > 1) + { + mask >>= 2; + num += 2; + } + if (mask > 0) + { + num++; + } + return num; + } + + public static int ConvertIndexToMask(int index) + { + if (index == 0) + { + return 0; + } + return 1 << index - 1; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncContactScan.cs b/ROUNDS/Photon.Pun.Simple/SyncContactScan.cs new file mode 100644 index 0000000..a028b18 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncContactScan.cs @@ -0,0 +1,50 @@ +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncContactScan : SyncShootBase, IOnSnapshot, IOnAuthorityChanged +{ + public bool poke = true; + + public bool grab = true; + + public HitscanDefinition hitscanDefinition; + + [Tooltip("Render widgets that represent the shape of the hitscan when triggered.")] + public bool visualizeHitscan = true; + + public override int ApplyOrder => 17; + + protected override bool Trigger(Frame frame, int subFrameId, float timeshift = 0f) + { + if ((bool)GetComponent<SyncContact>() && !photonView.IsMine) + { + hitscanDefinition.VisualizeHitscan(origin); + return true; + } + int nearestIndex = -1; + RaycastHit[] rayhits; + Collider[] hits; + int num = hitscanDefinition.GenericHitscanNonAlloc(origin, out rayhits, out hits, ref nearestIndex, visualizeHitscan); + if (num <= 0) + { + return true; + } + for (int i = 0; i < num; i++) + { + IContactTrigger nestedComponentInParents = hits[i].transform.GetNestedComponentInParents<IContactTrigger, NetObject>(); + if (nestedComponentInParents != null && !(nestedComponentInParents.NetObj == contactTrigger.NetObj)) + { + if (poke) + { + contactTrigger.OnContact(nestedComponentInParents, ContactType.Hitscan); + } + if (grab) + { + nestedComponentInParents.OnContact(contactTrigger, ContactType.Hitscan); + } + } + } + return true; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncMoverBase.cs b/ROUNDS/Photon.Pun.Simple/SyncMoverBase.cs new file mode 100644 index 0000000..55f68ad --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncMoverBase.cs @@ -0,0 +1,85 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[Serializable] +public abstract class SyncMoverBase<TTRSDef, TFrame> : SyncObject<TFrame>, ITransformController, IOnPreSimulate, IOnPreUpdate where TTRSDef : TRSDefinitionBase, new() where TFrame : FrameBase, new() +{ + public enum MovementRelation + { + Absolute, + Relative + } + + [HideInInspector] + public TTRSDef posDef = new TTRSDef(); + + [HideInInspector] + public TTRSDef rotDef = new TTRSDef(); + + [HideInInspector] + public TTRSDef sclDef = new TTRSDef(); + + protected Rigidbody rb; + + protected Rigidbody2D rb2d; + + [NonSerialized] + public SyncTransform syncTransform; + + public virtual bool HandlesInterpolation => true; + + public virtual bool HandlesExtrapolation => true; + + public override void OnAwakeInitialize(bool isNetObject) + { + if (!isNetObject) + { + NetMasterCallbacks.onPreSimulates.Add(this); + NetMasterCallbacks.onPreUpdates.Add(this); + } + rb = GetComponent<Rigidbody>(); + rb2d = GetComponent<Rigidbody2D>(); + if (((bool)rb && !rb.isKinematic) || ((bool)rb2d && !rb2d.isKinematic)) + { + Debug.LogWarning(GetType().Name + " doesn't work with non-kinematic rigidbodies. Setting to kinematic."); + if ((bool)rb) + { + rb.isKinematic = true; + } + else + { + rb2d.isKinematic = true; + } + } + syncTransform = GetComponent<SyncTransform>(); + Recalculate(); + } + + public override void OnStartInitialize(bool isNetObject) + { + InitializeTRS(posDef, TRS.Position); + InitializeTRS(rotDef, TRS.Rotation); + InitializeTRS(sclDef, TRS.Scale); + } + + private void OnDestroy() + { + if (!netObj) + { + NetMasterCallbacks.onPreSimulates.Remove(this); + NetMasterCallbacks.onPreUpdates.Remove(this); + } + } + + public virtual void Recalculate() + { + } + + protected abstract void InitializeTRS(TTRSDef def, TRS type); + + public abstract void OnPreSimulate(int frameId, int subFrameId); + + public abstract void OnPreUpdate(); +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncNodeMover.cs b/ROUNDS/Photon.Pun.Simple/SyncNodeMover.cs new file mode 100644 index 0000000..86ce685 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncNodeMover.cs @@ -0,0 +1,369 @@ +using System; +using System.Collections.Generic; +using Photon.Compression; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncNodeMover : SyncMoverBase<SyncNodeMover.TRSDefinition, SyncNodeMover.Frame>, IOnPreUpdate, IOnPreSimulate, IOnCaptureState, IOnNetSerialize, IOnSnapshot, IOnInterpolate, IReadyable +{ + public enum Movement + { + Oscillate, + Trigger + } + + [Serializable] + public class Node + { + public Vector3[] trs = new Vector3[3] + { + new Vector3(0f, 0f, 0f), + new Vector3(0f, 0f, 0f), + new Vector3(1f, 1f, 1f) + }; + + public Vector3 Pos + { + get + { + return trs[0]; + } + set + { + trs[0] = value; + } + } + + public Vector3 Rot + { + get + { + return trs[1]; + } + set + { + trs[1] = value; + } + } + + public Vector3 Scl + { + get + { + return trs[2]; + } + set + { + trs[2] = value; + } + } + } + + [Serializable] + public class TRSDefinition : TRSDefinitionBase + { + public AxisMask includeAxes = AxisMask.XYZ; + + public MovementRelation relation = MovementRelation.Relative; + } + + public class Frame : FrameBase + { + public int targetNode; + + public float phase; + + public uint cphase; + + public Frame() + { + } + + public Frame(int frameId) + : base(frameId) + { + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + Frame frame = sourceFrame as Frame; + targetNode = frame.targetNode; + phase = frame.phase; + cphase = frame.cphase; + } + + public override void Clear() + { + base.Clear(); + targetNode = -1; + phase = -1f; + cphase = 0u; + } + + public bool Compare(Frame otherFrame) + { + if (targetNode != otherFrame.targetNode || phase != otherFrame.phase || cphase != otherFrame.cphase) + { + return false; + } + return true; + } + } + + [Range(0f, 2f)] + public float predictWithRTT = 1f; + + [HideInInspector] + public List<Node> nodes = new List<Node> + { + new Node(), + new Node() + }; + + [HideInInspector] + public Movement movement; + + [HideInInspector] + public float oscillatePeriod = 1f; + + [HideInInspector] + public AnimationCurve oscillateCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(0.5f, 1f), new Keyframe(1f, 0f)); + + [HideInInspector] + public LiteFloatCrusher floatCrusher = new LiteFloatCrusher(LiteFloatCompressType.Bits10, LiteFloatCrusher.Normalization.Positive); + + protected float currentPhase; + + protected int queuedTargetNode; + + protected int targetNode; + + protected double timeoffset; + + protected float snapPhase; + + protected float targPhase; + + protected float accumulatedTime; + + public Node StartNode => nodes[0]; + + public Node EndNode => nodes[nodes.Count - 1]; + + protected override void Reset() + { + base.Reset(); + oscillateCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(0.5f, 1f), new Keyframe(1f, 0f)); + } + + protected override void InitializeTRS(TRSDefinition def, TRS type) + { + if (movement != 0) + { + def.relation = MovementRelation.Relative; + } + if ((def.relation == MovementRelation.Relative && movement == Movement.Oscillate) || movement == Movement.Trigger) + { + Vector3 vector = type switch + { + TRS.Position => def.local ? base.transform.localPosition : base.transform.position, + TRS.Rotation => def.local ? base.transform.localEulerAngles : base.transform.eulerAngles, + _ => def.local ? base.transform.localScale : base.transform.lossyScale, + }; + nodes[0].trs[(int)type] += vector; + nodes[1].trs[(int)type] += vector; + } + } + + public override void OnPreSimulate(int frameId, int subFrameId) + { + if (base.isActiveAndEnabled && (!photonView || photonView.IsMine)) + { + OwnerInterpolate(); + } + } + + public override void OnPreUpdate() + { + if (base.isActiveAndEnabled && (!photonView || photonView.IsMine)) + { + OwnerInterpolate(); + } + } + + private void OwnerInterpolate() + { + if (timeoffset == 0.0) + { + timeoffset = DoubleTime.fixedTime; + } + if (movement == Movement.Oscillate) + { + currentPhase = TimeToPhase(DoubleTime.time - timeoffset); + float lerpT = OscillatePhaseToLerpT(currentPhase); + Oscillate(lerpT); + } + } + + public void Trigger(int targetNode) + { + queuedTargetNode = targetNode; + } + + public void TriggerMin() + { + } + + public void TriggerMax() + { + } + + private void TriggerLerp() + { + } + + private void Oscillate(float lerpT) + { + Node node = nodes[0]; + Node node2 = nodes[1]; + Vector3 pos = ((posDef.includeAxes == AxisMask.None) ? new Vector3(0f, 0f, 0f) : Vector3.Lerp(node.trs[0], node2.trs[0], lerpT)); + Vector3 rot = ((rotDef.includeAxes == AxisMask.None) ? new Vector3(0f, 0f, 0f) : Vector3.Lerp(node.trs[1], node2.trs[1], lerpT)); + Vector3 scl = ((sclDef.includeAxes == AxisMask.None) ? new Vector3(1f, 1f, 1f) : Vector3.Lerp(node.trs[2], node2.trs[2], lerpT)); + ApplyOscillate(pos, rot, scl); + } + + public void OnCaptureCurrentState(int frameId) + { + Frame obj = frames[frameId]; + obj.targetNode = targetNode; + obj.phase = currentPhase; + obj.cphase = (uint)floatCrusher.Encode(currentPhase); + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame frame = frames[frameId]; + if (movement == Movement.Oscillate) + { + floatCrusher.WriteValue(frame.phase, buffer, ref bitposition); + } + return SerializationFlags.HasContent; + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + Frame frame = frames[originFrameId]; + frame.content = FrameContents.Complete; + if (movement == Movement.Oscillate) + { + frame.cphase = (uint)floatCrusher.ReadCValue(buffer, ref bitposition); + frame.phase = floatCrusher.Decode(frame.cphase); + } + return SerializationFlags.HasContent; + } + + protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsVaid, bool targIsValid) + { + if (snapIsVaid && snapframe.content == FrameContents.Complete && movement == Movement.Oscillate) + { + if (predictWithRTT != 0f) + { + float num = (NetMaster.RTT + TickEngineSettings.targetBufferInterval) * predictWithRTT; + float num2 = snapframe.phase * oscillatePeriod + num; + float num3 = targframe.phase * oscillatePeriod + num; + snapPhase = TimeToPhase(num2); + targPhase = TimeToPhase(num3); + } + else + { + snapPhase = snapframe.phase; + targPhase = targframe.phase; + } + float lerpT = OscillatePhaseToLerpT(snapPhase); + Oscillate(lerpT); + } + } + + public override bool OnInterpolate(int snapFrameId, int targFrameId, float t) + { + if (!base.OnInterpolate(snapFrameId, targFrameId, t)) + { + return false; + } + switch (movement) + { + case Movement.Oscillate: + { + if (targPhase < snapPhase) + { + targPhase += 1f; + } + float num = Mathf.Lerp(snapPhase, targPhase, t); + if (num >= 1f) + { + num -= 1f; + } + float lerpT = OscillatePhaseToLerpT(num); + Oscillate(lerpT); + return true; + } + default: + return false; + } + } + + protected override void ConstructMissingFrame(Frame prevFrame, Frame snapframe, Frame targframe) + { + if (movement == Movement.Oscillate && snapframe.content == FrameContents.Complete) + { + float num = snapframe.phase * oscillatePeriod + TickEngineSettings.netTickInterval; + targframe.phase = TimeToPhase(num); + targframe.content = FrameContents.Complete; + } + } + + protected float OscillatePhaseToLerpT(float phase) + { + return oscillateCurve.Evaluate(phase); + } + + protected float TimeToPhase(double time) + { + return (float)(time % (double)oscillatePeriod) / oscillatePeriod; + } + + private void ApplyOscillate(Vector3 pos, Vector3 rot, Vector3 scl) + { + AxisMask includeAxes = posDef.includeAxes; + AxisMask includeAxes2 = rotDef.includeAxes; + AxisMask includeAxes3 = sclDef.includeAxes; + if (includeAxes3 != 0) + { + base.transform.localScale = new Vector3(((includeAxes3 & AxisMask.X) != 0) ? scl.x : base.transform.localScale.x, ((includeAxes3 & AxisMask.Y) != 0) ? scl.y : base.transform.localScale.y, ((includeAxes3 & AxisMask.Z) != 0) ? scl.z : base.transform.localScale.z); + } + if (includeAxes2 != 0) + { + if (rotDef.local) + { + base.transform.localEulerAngles = new Vector3(((includeAxes2 & AxisMask.X) != 0) ? rot.x : base.transform.localEulerAngles.x, ((includeAxes2 & AxisMask.Y) != 0) ? rot.y : base.transform.localEulerAngles.y, ((includeAxes2 & AxisMask.Z) != 0) ? rot.z : base.transform.localEulerAngles.z); + } + else + { + base.transform.eulerAngles = new Vector3(((includeAxes2 & AxisMask.X) != 0) ? rot.x : base.transform.eulerAngles.x, ((includeAxes2 & AxisMask.Y) != 0) ? rot.y : base.transform.eulerAngles.y, ((includeAxes2 & AxisMask.Z) != 0) ? rot.z : base.transform.eulerAngles.z); + } + } + if (includeAxes != 0) + { + if (posDef.local) + { + base.transform.localPosition = new Vector3(((includeAxes & AxisMask.X) != 0) ? pos.x : base.transform.localPosition.x, ((includeAxes & AxisMask.Y) != 0) ? pos.y : base.transform.localPosition.y, ((includeAxes & AxisMask.Z) != 0) ? pos.z : base.transform.localPosition.z); + } + else + { + base.transform.position = new Vector3(((includeAxes & AxisMask.X) != 0) ? pos.x : base.transform.position.x, ((includeAxes & AxisMask.Y) != 0) ? pos.y : base.transform.position.y, ((includeAxes & AxisMask.Z) != 0) ? pos.z : base.transform.position.z); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncObject.cs b/ROUNDS/Photon.Pun.Simple/SyncObject.cs new file mode 100644 index 0000000..bc4ed35 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncObject.cs @@ -0,0 +1,377 @@ +using System; +using emotitron.Utilities.GUIUtilities; +using Photon.Pun.Simple.Internal; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[HelpURL("https://doc.photonengine.com/en-us/pun/current/gameplay/simple/simplecoresynccomponents")] +public abstract class SyncObject : NetComponent, IOnEnable, IOnDisable, IApplyOrder +{ + public int _applyOrder = 13; + + [Tooltip("Every X Net Tick this object will serialize a full update, regardless of having changed or not.")] + [Range(1f, 12f)] + [HideInInspector] + [SerializeField] + protected int keyframeRate = 1; + + [Tooltip("When enabled, components will be instructed to check for changes and serialize them. When disabled, components will be instructed to ONLY send keyframes.")] + [HideInInspector] + [SerializeField] + protected bool useDeltas = true; + + private const string ALWAYS_READY_TOOLTIP = "When true, the NetObject will not factor this SyncObj's ready state into firing IOnNetObjReady callbacks."; + + [ShowIfInterface(typeof(IReadyable), "When true, the NetObject will not factor this SyncObj's ready state into firing IOnNetObjReady callbacks.")] + public bool _alwaysReady = true; + + private const string INCLUDE_SERIALIZATION_TOOLTIP = "When false, the NetObject will not serialize this SyncObj's state. This cannot be changed at runtime. Disable this component on the owner to disable sync at runtime instead."; + + [Tooltip("When false, the NetObject will not serialize this SyncObj's state. This cannot be changed at runtime. Disable this component on the owner to disable sync at runtime instead.")] + [HideInInspector] + public bool serializeThis = true; + + [NonSerialized] + protected int syncObjIndex; + + protected ReadyStateEnum _readyState; + + public Action<SyncObject, ReadyStateEnum> onReadyCallbacks; + + public virtual int ApplyOrder => _applyOrder; + + public bool UseDeltas + { + get + { + return useDeltas; + } + set + { + useDeltas = value; + } + } + + public virtual bool AlwaysReady => _alwaysReady; + + public virtual bool IncludeInSerialization => serializeThis; + + public bool SkipWhenEmpty => false; + + public int SyncObjIndex + { + get + { + return syncObjIndex; + } + set + { + syncObjIndex = value; + } + } + + public ReadyStateEnum ReadyState + { + get + { + return _readyState; + } + set + { + if (_readyState != value) + { + _readyState = value; + netObj.OnSyncObjReadyChange(this, _readyState); + if (onReadyCallbacks != null) + { + onReadyCallbacks(this, value); + } + } + } + } + + public bool IsKeyframe(int frameId) + { + if (keyframeRate != 0) + { + if (frameId % keyframeRate != 0) + { + return frameId == TickEngineSettings.frameCount; + } + return true; + } + return false; + } + + public virtual void ResetBuffers() + { + } + + public override void OnPostEnable() + { + base.OnPostEnable(); + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + if (controllerChanged) + { + if (!(this is IReadyable readyable) || readyable.AlwaysReady || _readyState != 0) + { + ReadyState = ReadyStateEnum.Ready; + } + else if (!base.isActiveAndEnabled) + { + ReadyState = ReadyStateEnum.Disabled; + } + else + { + ReadyState = ReadyStateEnum.Unready; + } + } + } + + public override void OnPostDisable() + { + base.OnPostDisable(); + ReadyState = ReadyStateEnum.Disabled; + } + + public override void OnAwake() + { + base.OnAwake(); + } + + protected virtual void OnEnable() + { + } + + protected int ConvertSecsToTicks(float seconds) + { + return (int)(seconds / (Time.fixedDeltaTime * (float)TickEngineSettings.sendEveryXTick)); + } +} +public abstract class SyncObject<TFrame> : SyncObject where TFrame : FrameBase +{ + [NonSerialized] + public TFrame[] frames; + + protected TFrame prevFrame; + + protected TFrame snapFrame; + + protected TFrame targFrame; + + protected TFrame offtickFrame; + + protected bool hadInitialSnapshot; + + public virtual bool AllowInterpolation => true; + + public virtual bool AllowReconstructionOfEmpty => true; + + public virtual bool AllowReconstructionOfPartial => true; + + public override void OnAwake() + { + if (keyframeRate > TickEngineSettings.MaxKeyframes) + { + keyframeRate = TickEngineSettings.MaxKeyframes; + Debug.LogWarning(base.name + "/" + GetType().Name + " keyframe setting exceeds max allowed for the current " + SettingsScriptableObject<TickEngineSettings>.single.name + ".frameCount setting. Reducing to " + keyframeRate); + } + base.OnAwake(); + PopulateFrames(); + offtickFrame = frames[TickEngineSettings.frameCount]; + } + + public override void OnPostDisable() + { + base.OnPostDisable(); + hadInitialSnapshot = false; + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + if (controllerChanged) + { + int controllerActorNr = photonView.ControllerActorNr; + int[] originHistory = netObj.originHistory; + int i = 0; + for (int frameCount = TickEngineSettings.frameCount; i < frameCount; i++) + { + if (controllerActorNr != originHistory[i]) + { + frames[i].Clear(); + } + } + } + hadInitialSnapshot = false; + } + + protected virtual void PopulateFrames() + { + FrameBase.PopulateFrames(ref frames); + } + + protected virtual void InitialCompleteSnapshot(TFrame frame) + { + } + + public virtual bool OnSnapshot(int prevFrameId, int snapFrameId, int targFrameId, bool prevIsValid, bool snapIsValid, bool targIsValid) + { + if (!base.enabled) + { + return false; + } + int frameCount = TickEngineSettings.frameCount; + int halfFrameCount = TickEngineSettings.halfFrameCount; + prevFrame = frames[prevFrameId]; + snapFrame = frames[snapFrameId]; + if (targFrameId < 0 || targFrameId >= frameCount) + { + Debug.Log("BAD FRAME ID " + targFrameId); + } + targFrame = frames[targFrameId]; + int num = snapFrameId + halfFrameCount; + if (num >= frameCount) + { + num -= frameCount; + } + frames[num].Clear(); + if (targIsValid) + { + switch (targFrame.content) + { + case FrameContents.Empty: + if (AllowReconstructionOfEmpty) + { + ReconstructEmptyFrame(); + } + break; + case FrameContents.Partial: + if (AllowReconstructionOfPartial) + { + ReconstructIncompleteFrame(); + } + break; + case FrameContents.NoChange: + targFrame.CopyFrom(snapFrame); + break; + } + } + else if (AllowReconstructionOfEmpty) + { + if (snapIsValid || snapFrame.content >= FrameContents.Extrapolated) + { + ConstructMissingFrame(prevFrame, snapFrame, targFrame); + } + else + { + targFrame.content = FrameContents.Empty; + } + } + else + { + targFrame.content = FrameContents.Empty; + } + if (_readyState != ReadyStateEnum.Ready) + { + TFrame val = snapFrame; + if (val.content == FrameContents.Complete) + { + InitialCompleteSnapshot(val); + base.ReadyState = ReadyStateEnum.Ready; + } + } + ApplySnapshot(snapFrame, targFrame, snapIsValid, targIsValid); + return true; + } + + protected virtual void ApplySnapshot(TFrame snapframe, TFrame targframe, bool snapIsValid, bool targIsValid) + { + } + + protected virtual void ReconstructEmptyFrame() + { + if (snapFrame.content == FrameContents.Extrapolated || snapFrame.content == FrameContents.Complete) + { + targFrame.content = FrameContents.Extrapolated; + targFrame.CopyFrom(snapFrame); + } + else + { + targFrame.content = FrameContents.Empty; + } + } + + protected virtual void ReconstructIncompleteFrame() + { + targFrame.CopyFrom(snapFrame); + targFrame.content = FrameContents.Partial; + } + + protected virtual void ConstructMissingFrame(TFrame prevFrame, TFrame snapframe, TFrame targframe) + { + if (snapframe.content == FrameContents.Empty) + { + targframe.content = FrameContents.Empty; + return; + } + if (!TickManager.perConnOffsets.TryGetValue(base.ControllerActorNr, out var _)) + { + Debug.LogError("CONN " + base.ControllerActorNr + " NOT ESTABLISHED IN TICK MANAGER YET."); + } + int frameId = targframe.frameId; + for (int i = 2; i <= 3; i++) + { + int num = frameId + i; + if (num >= TickEngineSettings.frameCount) + { + num -= TickEngineSettings.frameCount; + } + TFrame val = frames[num]; + if (netObj.frameValidMask[num] && val.content == FrameContents.Complete) + { + float t = 1f / (float)i; + InterpolateFrame(targframe, snapframe, val, t); + if (targframe.content != 0) + { + return; + } + } + } + targframe.content = FrameContents.Empty; + ExtrapolateFrame(prevFrame, snapframe, targframe); + } + + public virtual bool OnInterpolate(int snapFrameId, int targFrameId, float t) + { + if (!AllowInterpolation) + { + return false; + } + if (!base.isActiveAndEnabled) + { + return false; + } + if (base.IsMine) + { + return false; + } + return true; + } + + protected virtual void InterpolateFrame(TFrame targframe, TFrame startframe, TFrame endframe, float t) + { + targframe.Clear(); + } + + protected virtual void ExtrapolateFrame(TFrame prevframe, TFrame snapframe, TFrame targframe) + { + targframe.Clear(); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncOwner.cs b/ROUNDS/Photon.Pun.Simple/SyncOwner.cs new file mode 100644 index 0000000..b35e1b1 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncOwner.cs @@ -0,0 +1,149 @@ +using Photon.Compression; + +namespace Photon.Pun.Simple; + +public class SyncOwner : SyncObject<SyncOwner.Frame>, IOnCaptureState, IOnNetSerialize, IOnSnapshot, IUseKeyframes, IOnIncrementFrame +{ + public class Frame : FrameBase + { + public int ownerActorId; + + public bool ownerHasChanged; + + public override void Clear() + { + ownerActorId = -1; + ownerHasChanged = false; + base.Clear(); + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + Frame frame = sourceFrame as Frame; + ownerActorId = frame.ownerActorId; + ownerHasChanged = false; + } + } + + public bool reliableOwnerChange = true; + + protected bool pendingOwnerChange; + + protected int pendingOwnerId = -1; + + protected int ticksUntilOwnershipRetry = -1; + + public override int ApplyOrder => 21; + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + if (!isMine) + { + pendingOwnerChange = false; + ticksUntilOwnershipRetry = -1; + } + } + + public void TransferOwner(int newOwnerId) + { + if (photonView.IsMine) + { + pendingOwnerChange = true; + pendingOwnerId = newOwnerId; + } + } + + public void OnCaptureCurrentState(int frameId) + { + Frame frame = frames[frameId]; + if (pendingOwnerChange) + { + if (photonView.OwnerActorNr != 0) + { + ticksUntilOwnershipRetry = TickEngineSettings.frameCount; + } + NetMasterCallbacks.postCallbackActions.Enqueue(DeferredOwnerChange); + frame.ownerActorId = pendingOwnerId; + frame.ownerHasChanged = true; + pendingOwnerChange = false; + } + else + { + frames[frameId].ownerActorId = photonView.OwnerActorNr; + } + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame frame = frames[frameId]; + bool flag = frame.ownerHasChanged && (reliableOwnerChange || keyframeRate == 0 || (writeFlags & SerializationFlags.NewConnection) != 0); + if (!flag && !IsKeyframe(frameId)) + { + buffer.Write(0uL, ref bitposition, 1); + return SerializationFlags.None; + } + buffer.Write(1uL, ref bitposition, 1); + SerializationFlags serializationFlags = SerializationFlags.HasContent; + buffer.WritePackedBytes((uint)frame.ownerActorId, ref bitposition, 32); + if (flag) + { + serializationFlags |= SerializationFlags.ForceReliable; + } + return serializationFlags; + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival frameArrival) + { + Frame frame = frames[originFrameId]; + bool flag = buffer.Read(ref bitposition, 1) != 0; + int ownerActorId = (flag ? ((int)buffer.ReadPackedBytes(ref bitposition, 32)) : (-1)); + if (photonView.IsMine) + { + return SerializationFlags.None; + } + if (flag) + { + frame.content = FrameContents.Complete; + frame.ownerActorId = ownerActorId; + return SerializationFlags.HasContent; + } + frame.content = FrameContents.Empty; + return SerializationFlags.None; + } + + protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsValid, bool targIsValid) + { + if (snapIsValid && snapframe.content == FrameContents.Complete) + { + int ownerActorId = snapframe.ownerActorId; + pendingOwnerId = ownerActorId; + NetMasterCallbacks.postCallbackActions.Enqueue(DeferredOwnerChange); + ticksUntilOwnershipRetry = -1; + } + } + + protected void DeferredOwnerChange() + { + PhotonNetwork.CurrentRoom.Players.TryGetValue(pendingOwnerId, out var value); + photonView.SetOwnerInternal(value, pendingOwnerId); + } + + public void OnIncrementFrame(int newFrameId, int newSubFrameId, int previousFrameId, int prevSubFrameId) + { + if (!photonView.IsMine && newSubFrameId == 0 && ticksUntilOwnershipRetry >= 0) + { + if (ticksUntilOwnershipRetry == 0) + { + Debug.LogError(base.name + " FALLBACK OWNER CHANGE " + photonView.ControllerActorNr); + photonView.TransferOwnership(photonView.Controller); + ticksUntilOwnershipRetry = TickEngineSettings.frameCount; + } + else + { + ticksUntilOwnershipRetry--; + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncShootBase.cs b/ROUNDS/Photon.Pun.Simple/SyncShootBase.cs new file mode 100644 index 0000000..b199ee2 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncShootBase.cs @@ -0,0 +1,151 @@ +using Photon.Compression; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public abstract class SyncShootBase : SyncObject<SyncShootBase.Frame>, IOnNetSerialize, IOnPostSimulate, IOnPreUpdate, IOnIncrementFrame, IOnSnapshot, IOnInterpolate +{ + public class Frame : FrameBase + { + public uint triggerMask; + + public Frame() + { + } + + public Frame(int frameId) + : base(frameId) + { + } + + public override void CopyFrom(FrameBase sourceFrame) + { + triggerMask = 0u; + } + + public override void Clear() + { + base.Clear(); + triggerMask = 0u; + } + } + + [Tooltip("Specify the transform hitscans/projectiles will originate from. If null this gameObject will be used as the origin.")] + [SerializeField] + protected Transform origin; + + [SerializeField] + public KeyCode triggerKey; + + protected IContactTrigger contactTrigger; + + protected bool hasSyncContact; + + protected bool triggerQueued; + + public IContactTrigger ContactTrigger => contactTrigger; + + public override int ApplyOrder => 17; + + public override void OnAwakeInitialize(bool isNetObject) + { + base.OnAwakeInitialize(isNetObject); + contactTrigger = base.transform.GetNestedComponentInParents<IContactTrigger, NetObject>(); + hasSyncContact = contactTrigger.SyncContact != null; + if (origin == null) + { + origin = base.transform; + } + } + + public virtual void OnPreUpdate() + { + if (base.IsMine && Input.GetKeyDown(triggerKey)) + { + QueueTrigger(); + } + } + + public virtual void QueueTrigger() + { + if (base.enabled && base.gameObject.activeInHierarchy) + { + triggerQueued = true; + } + } + + public virtual SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame frame = frames[frameId]; + int sendEveryXTick = TickEngineSettings.sendEveryXTick; + if (frame.triggerMask != 0) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write(frame.triggerMask, ref bitposition, sendEveryXTick); + return SerializationFlags.HasContent; + } + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + + public virtual SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + Frame frame = frames[originFrameId]; + int sendEveryXTick = TickEngineSettings.sendEveryXTick; + if (buffer.ReadBool(ref bitposition)) + { + frame.triggerMask = buffer.ReadUInt32(ref bitposition, sendEveryXTick); + frame.content = FrameContents.Complete; + return SerializationFlags.HasContent; + } + frame.triggerMask = 0u; + frame.content = FrameContents.Empty; + return SerializationFlags.None; + } + + public virtual void OnPostSimulate(int frameId, int subFrameId, bool isNetTick) + { + if (!base.IsMine) + { + return; + } + Frame frame = frames[frameId]; + if (subFrameId == 0) + { + frame.Clear(); + } + if (triggerQueued) + { + frame.triggerMask |= (uint)(1 << subFrameId); + if (Trigger(frame, subFrameId)) + { + TriggerCosmetic(frame, subFrameId); + } + triggerQueued = false; + frame.content = FrameContents.Complete; + } + } + + public virtual void OnIncrementFrame(int newFrameId, int newSubFrameId, int previousFrameId, int prevSubFrameId) + { + if (!base.IsMine && targFrame != null && targFrame.content == FrameContents.Complete) + { + int offset = ((newSubFrameId == 0) ? (TickEngineSettings.sendEveryXTick - 1) : (newSubFrameId - 1)); + ApplySubframe(newFrameId, newSubFrameId, offset); + } + } + + protected virtual void ApplySubframe(int newFrameId, int newSubFrameId, int offset) + { + if ((targFrame.triggerMask & (1 << offset)) != 0L && Trigger(targFrame, newSubFrameId, NetMaster.RTT)) + { + TriggerCosmetic(targFrame, newSubFrameId, NetMaster.RTT); + } + } + + protected abstract bool Trigger(Frame frame, int subFrameId, float timeshift = 0f); + + protected virtual void TriggerCosmetic(Frame frame, int subFrameId, float timeshift = 0f) + { + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncSpawnTimer.cs b/ROUNDS/Photon.Pun.Simple/SyncSpawnTimer.cs new file mode 100644 index 0000000..98add3d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncSpawnTimer.cs @@ -0,0 +1,307 @@ +using System; +using Photon.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[DisallowMultipleComponent] +[RequireComponent(typeof(SyncState))] +public class SyncSpawnTimer : SyncObject<SyncSpawnTimer.Frame>, ISpawnController, ISerializationOptional, IOnNetSerialize, IUseKeyframes, IOnSnapshot, IOnCaptureState, IOnStateChange +{ + public class Frame : FrameBase + { + public int ticksUntilRespawn; + + public int ticksUntilDespawn; + + public Frame() + { + } + + public Frame(int frameId) + : base(frameId) + { + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + Frame frame = sourceFrame as Frame; + ticksUntilRespawn = frame.ticksUntilRespawn; + ticksUntilDespawn = frame.ticksUntilDespawn; + } + + public bool Compare(Frame otherFrame) + { + if (ticksUntilRespawn == otherFrame.ticksUntilRespawn) + { + return ticksUntilDespawn == otherFrame.ticksUntilDespawn; + } + return false; + } + } + + [HideInInspector] + [SerializeField] + public float initialDelay; + + [HideInInspector] + [SerializeField] + public bool respawnEnable = true; + + [EnumMask(true, typeof(ObjStateEditor))] + [HideInInspector] + [SerializeField] + public ObjState despawnOn = ObjState.Mounted; + + [Tooltip("Number of seconds after respawn trigger before respawn occurs.")] + [HideInInspector] + [SerializeField] + public float despawnDelay = 5f; + + [HideInInspector] + [SerializeField] + public bool despawnEnable; + + [EnumMask(true, typeof(ObjStateEditor))] + [HideInInspector] + [SerializeField] + public ObjState respawnOn; + + [Tooltip("Number of seconds after respawn trigger before respawn occurs.")] + [HideInInspector] + [SerializeField] + public float respawnDelay = 5f; + + protected SyncState syncState; + + [NonSerialized] + protected int ticksUntilRespawn = -1; + + [NonSerialized] + protected int ticksUntilDespawn = -1; + + [NonSerialized] + protected int spawnWaitAsTicks; + + [NonSerialized] + protected int respawnWaitAsTicks; + + [NonSerialized] + protected int despawnWaitAsTicks; + + [NonSerialized] + protected bool hadInitialSpawn; + + protected int bitsForTicksUntilRespawn; + + protected int bitsForTicksUntilDespawn; + + public override int ApplyOrder => 3; + + public override void OnAwake() + { + base.OnAwake(); + if ((bool)netObj) + { + syncState = netObj.GetComponent<SyncState>(); + } + spawnWaitAsTicks = ConvertSecsToTicks(initialDelay); + respawnWaitAsTicks = ConvertSecsToTicks(respawnDelay); + despawnWaitAsTicks = ConvertSecsToTicks(despawnDelay); + bitsForTicksUntilRespawn = Math.Max(respawnWaitAsTicks, spawnWaitAsTicks).GetBitsForMaxValue(); + bitsForTicksUntilDespawn = despawnWaitAsTicks.GetBitsForMaxValue(); + } + + public bool AllowNetObjectReadyCallback(bool ready) + { + if (ready && spawnWaitAsTicks >= 0) + { + return false; + } + return true; + } + + public override void OnJoinedRoom() + { + base.OnJoinedRoom(); + if (photonView.IsMine) + { + ticksUntilRespawn = spawnWaitAsTicks; + } + else + { + ticksUntilRespawn = -1; + } + } + + public override void OnStart() + { + base.OnStart(); + ticksUntilRespawn = spawnWaitAsTicks; + } + + public void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true) + { + if (newState == previousState) + { + return; + } + if (respawnEnable) + { + if (newState == ObjState.Despawned) + { + ticksUntilRespawn = respawnWaitAsTicks; + } + else if ((previousState & respawnOn) == 0 && (newState & respawnOn) != 0) + { + Debug.Log(string.Concat(Time.time, " ", base.name, " ", photonView.OwnerActorNr, " <b>Reset </b> ", previousState, " <> ", newState)); + ticksUntilRespawn = respawnWaitAsTicks; + } + } + if (despawnEnable && (previousState & despawnOn) == 0 && (newState & despawnOn) != 0) + { + ticksUntilDespawn = despawnWaitAsTicks; + } + } + + public virtual void OnCaptureCurrentState(int frameId) + { + Frame frame = frames[frameId]; + if (!hadInitialSpawn || respawnEnable) + { + if (ticksUntilRespawn == 0) + { + syncState.Respawn(immediate: false); + hadInitialSpawn = true; + } + ticksUntilRespawn--; + frame.ticksUntilRespawn = ticksUntilRespawn; + } + if (despawnEnable) + { + if (ticksUntilDespawn == 0) + { + syncState.Despawn(immediate: false); + } + ticksUntilDespawn--; + frame.ticksUntilDespawn = ticksUntilDespawn; + } + } + + public virtual SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame frame = frames[frameId]; + SerializationFlags serializationFlags = SerializationFlags.None; + if (!IsKeyframe(frameId)) + { + return serializationFlags; + } + if (respawnEnable) + { + int num = frame.ticksUntilRespawn; + if (num >= 0) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write((ulong)num, ref bitposition, bitsForTicksUntilRespawn); + serializationFlags |= SerializationFlags.HasContent; + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + } + if (despawnEnable) + { + int num2 = frame.ticksUntilDespawn; + if (num2 >= 0) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write((ulong)num2, ref bitposition, bitsForTicksUntilDespawn); + serializationFlags |= SerializationFlags.HasContent; + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + } + return serializationFlags; + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival frameArrival) + { + Frame frame = frames[originFrameId]; + SerializationFlags serializationFlags = SerializationFlags.None; + if (!IsKeyframe(originFrameId)) + { + frame.content = FrameContents.Empty; + return serializationFlags; + } + if (respawnEnable) + { + if (buffer.ReadBool(ref bitposition)) + { + frame.ticksUntilRespawn = (int)buffer.Read(ref bitposition, bitsForTicksUntilRespawn); + serializationFlags |= SerializationFlags.HasContent; + } + else + { + frame.ticksUntilRespawn = -1; + } + } + if (despawnEnable) + { + if (buffer.ReadBool(ref bitposition)) + { + frame.ticksUntilDespawn = (int)buffer.Read(ref bitposition, bitsForTicksUntilDespawn); + serializationFlags |= SerializationFlags.HasContent; + } + else + { + frame.ticksUntilDespawn = -1; + } + } + frame.content = FrameContents.Complete; + return serializationFlags; + } + + protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsValid, bool targIsValid) + { + if (snapIsValid && snapframe.content > FrameContents.Empty) + { + if (respawnEnable) + { + ticksUntilRespawn = snapframe.ticksUntilRespawn; + } + if (despawnEnable) + { + ticksUntilDespawn = snapframe.ticksUntilDespawn; + } + } + else + { + if (respawnEnable) + { + ticksUntilRespawn--; + targframe.ticksUntilRespawn = ticksUntilRespawn; + } + if (despawnEnable) + { + ticksUntilDespawn--; + targframe.ticksUntilDespawn = ticksUntilDespawn; + } + } + if (photonView.IsMine) + { + if (respawnEnable && ticksUntilRespawn == 0) + { + syncState.Respawn(immediate: false); + } + if (despawnEnable && ticksUntilDespawn == 0) + { + syncState.Despawn(immediate: false); + } + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncState.cs b/ROUNDS/Photon.Pun.Simple/SyncState.cs new file mode 100644 index 0000000..8153b31 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncState.cs @@ -0,0 +1,643 @@ +using System; +using System.Collections.Generic; +using Photon.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[DisallowMultipleComponent] +public class SyncState : SyncObject<SyncState.Frame>, IMountable, IOnCaptureState, IOnNetSerialize, IOnSnapshot, IReadyable, IOnNetObjReady, IUseKeyframes +{ + public class Frame : FrameBase + { + public enum Changes + { + None, + MountIdChange + } + + public ObjState state; + + public int? mountToViewID; + + public int? mountTypeId; + + public Frame() + { + } + + public Frame(int frameId) + : base(frameId) + { + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + Frame frame = sourceFrame as Frame; + state = frame.state; + mountToViewID = frame.mountToViewID; + mountTypeId = frame.mountTypeId; + } + + public override void Clear() + { + base.Clear(); + state = ObjState.Despawned; + mountToViewID = null; + mountTypeId = null; + } + + public bool Compare(Frame otherFrame) + { + if (state != otherFrame.state || mountToViewID != otherFrame.mountToViewID || mountTypeId != otherFrame.mountTypeId) + { + return false; + } + return true; + } + } + + [EnumMask(true, typeof(ObjStateEditor))] + public ObjState initialState; + + [EnumMask(true, typeof(ObjStateEditor))] + public ObjState respawnState = ObjState.Visible; + + [EnumMask(true, typeof(ObjStateEditor))] + public ObjState readyState = ObjState.Visible; + + [EnumMask(true, typeof(ObjStateEditor))] + public ObjState unreadyState; + + [Tooltip("Mount types this NetObject can be attached to.")] + public MountMaskSelector mountableTo; + + [Tooltip("Automatically return this object to its starting position and attach to original parent when ObjState changes from Despawned to any other state.")] + public bool autoReset = true; + + [Tooltip("Automatically will request ownership transfer to the owner of NetObjects this becomes attached to.")] + public bool autoOwnerChange = true; + + [Tooltip("Parent Mount changes will force the entire update from this client to send Reliable. This ensures a keyframe of parenting and position reaches all clients (which isn't certain with packetloss), but can cause a visible hanging if packetloss is present on the network.")] + public bool mountReliable = true; + + [NonSerialized] + protected Frame currentState = new Frame(); + + [NonSerialized] + protected Mount currentMount; + + [NonSerialized] + protected bool netObjIsReady; + + protected MountsManager mountsLookup; + + protected SyncTransform syncTransform; + + protected SyncOwner syncOwner; + + protected ISpawnController iSpawnController; + + protected Dictionary<int, int> mountTypeIdToIndex = new Dictionary<int, int>(); + + protected int[] indexToMountTypeId; + + protected int bitsForMountType; + + protected StateChangeInfo respawnStateInfo; + + [NonSerialized] + public List<IOnStateChange> onStateChangeCallbacks = new List<IOnStateChange>(); + + [NonSerialized] + public List<IFlagTeleport> flagTeleportCallbacks = new List<IFlagTeleport>(); + + protected Queue<StateChangeInfo> stateChangeQueue = new Queue<StateChangeInfo>(); + + protected Frame prevSerializedFrame; + + public override int ApplyOrder => 5; + + public Mount CurrentMount + { + get + { + return currentMount; + } + set + { + currentMount = value; + } + } + + public bool IsThrowable => true; + + public bool IsDroppable => true; + + public Rigidbody Rb => netObj.Rb; + + public Rigidbody2D Rb2d => netObj.Rb2D; + + public override bool AllowReconstructionOfEmpty => false; + + public override void OnAwake() + { + base.OnAwake(); + iSpawnController = GetComponent<ISpawnController>(); + syncTransform = GetComponent<SyncTransform>(); + syncOwner = GetComponent<SyncOwner>(); + base.transform.GetNestedComponentsInChildren<IOnStateChange, NetObject>(onStateChangeCallbacks); + base.transform.GetComponents(flagTeleportCallbacks); + mountsLookup = netObj.GetComponent<MountsManager>(); + } + + public override void OnStart() + { + ChangeState(new StateChangeInfo(initialState, base.transform.parent ? base.transform.parent.GetComponent<Mount>() : null, force: true)); + base.OnStart(); + respawnStateInfo = new StateChangeInfo(respawnState, base.transform.parent ? base.transform.parent.GetComponent<Mount>() : null, base.transform.localPosition, base.transform.localRotation, null, force: true); + int num = mountableTo.mask.CountTrueBits(out indexToMountTypeId, MountSettings.mountTypeCount); + bitsForMountType = num.GetBitsForMaxValue(); + for (int i = 0; i < num; i++) + { + mountTypeIdToIndex.Add(indexToMountTypeId[i], i); + } + } + + public override void OnJoinedRoom() + { + base.OnJoinedRoom(); + if (iSpawnController == null) + { + ChangeState(new StateChangeInfo(initialState, base.transform.parent ? base.transform.parent.GetComponent<Mount>() : null, force: true)); + } + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + stateChangeQueue.Clear(); + prevSerializedFrame = null; + } + + public virtual void OnNetObjReadyChange(bool ready) + { + netObjIsReady = ready; + if (!base.IsMine || iSpawnController == null || iSpawnController.AllowNetObjectReadyCallback(ready)) + { + if (ready) + { + ChangeState(new StateChangeInfo(readyState, currentMount, force: true)); + } + else + { + ChangeState(new StateChangeInfo(unreadyState, currentMount, force: true)); + } + } + } + + public void SoftMount(Mount attachTo) + { + ObjState itemState = (attachTo ? ((currentState.state & (ObjState)(-49)) | ObjState.Mounted) : (currentState.state & (ObjState)(-3))); + ChangeState(new StateChangeInfo(itemState, attachTo, force: false)); + } + + public void HardMount(Mount mountTo) + { + ObjState itemState = (mountTo ? ((currentState.state & (ObjState)(-49)) | (ObjState)14) : (currentState.state & (ObjState)(-15))); + ChangeState(new StateChangeInfo(itemState, mountTo, force: false)); + } + + public void Spawn() + { + } + + public void Respawn(bool immediate) + { + if (immediate) + { + ChangeState(respawnStateInfo); + } + else + { + stateChangeQueue.Enqueue(respawnStateInfo); + } + } + + public void Despawn(bool immediate) + { + if (immediate) + { + ChangeState(new StateChangeInfo(ObjState.Despawned, null, force: true)); + } + else + { + stateChangeQueue.Enqueue(new StateChangeInfo(ObjState.Despawned, null, force: true)); + } + } + + public void ImmediateUnmount() + { + stateChangeQueue.Clear(); + ChangeState(new StateChangeInfo((ObjState)49, null, force: true)); + } + + public void Drop(Mount newMount, bool force = false) + { + stateChangeQueue.Enqueue(new StateChangeInfo((ObjState)17, newMount, force)); + } + + public void Throw(Vector3 position, Quaternion rotation, Vector3 velocity) + { + stateChangeQueue.Enqueue(new StateChangeInfo((ObjState)49, null, position, rotation, velocity, force: false)); + } + + public void ThrowLocal(Transform origin, Vector3 offset, Vector3 velocity) + { + stateChangeQueue.Enqueue(new StateChangeInfo((ObjState)49, null, origin.TransformPoint(offset), origin.TransformPoint(velocity), force: false)); + } + + public virtual void QueueStateChange(ObjState newState, Mount newMount, bool force) + { + stateChangeQueue.Enqueue(new StateChangeInfo(newState, newMount, null, null, force)); + } + + public virtual void QueueStateChange(ObjState newState, Mount newMount, Vector3 offset, Vector3 velocity, bool force) + { + stateChangeQueue.Enqueue(new StateChangeInfo(newState, newMount, offset, velocity, force)); + } + + protected virtual void DequeueStateChanges() + { + while (stateChangeQueue.Count > 0) + { + StateChangeInfo stateChangeInfo = stateChangeQueue.Dequeue(); + ChangeState(stateChangeInfo); + } + } + + protected virtual void ChangeState(StateChangeInfo stateChangeInfo) + { + if (!base.gameObject) + { + Debug.LogWarning(base.name + " has been destroyed. Will not try to change state."); + return; + } + ObjState state = currentState.state; + Mount mount = currentMount; + ObjState objState = stateChangeInfo.objState; + Mount mount2 = stateChangeInfo.mount; + bool flag; + if (autoReset && state == ObjState.Despawned && objState != 0 && (objState & ObjState.Anchored) == 0) + { + StateChangeInfo stateChangeInfo2 = new StateChangeInfo(respawnStateInfo); + stateChangeInfo2.objState = stateChangeInfo.objState; + stateChangeInfo = stateChangeInfo2; + flag = true; + } + else + { + flag = false; + } + bool force = stateChangeInfo.force; + bool flag2 = objState != state; + bool flag3 = mount != mount2; + _ = base.transform.parent; + if (!force && !flag2 && !flag3) + { + return; + } + currentState.state = objState; + Mount prevMount = currentMount; + currentMount = mount2; + bool flag4 = (objState & ObjState.Mounted) != 0; + bool flag5 = flag4 && (object)mount2 == null; + if (flag4 && !flag5 && mount2 == null) + { + Debug.LogError("Invalid Mount!"); + InvalidMountHandler(objState, mount2, force); + return; + } + if (base.IsMine && (flag3 || flag)) + { + for (int i = 0; i < flagTeleportCallbacks.Count; i++) + { + flagTeleportCallbacks[i].FlagTeleport(); + } + } + if (flag3) + { + if (flag4) + { + currentState.mountToViewID = mount2.ViewID; + currentState.mountTypeId = mount2.mountType.id; + base.transform.parent = mount2.transform; + if ((objState & ObjState.AnchoredPosition) != 0) + { + base.transform.localPosition = default(Vector3); + } + if ((objState & ObjState.AnchoredRotation) != 0) + { + base.transform.localRotation = default(Quaternion); + } + } + else + { + currentState.mountToViewID = null; + currentState.mountTypeId = null; + base.transform.parent = null; + } + if (autoOwnerChange && (bool)mount2 && (object)mount != mount2) + { + ChangeOwnerToParentMountsOwner(); + } + Mount.ChangeMounting(this, prevMount, mount2); + } + Vector3? offsetPos = stateChangeInfo.offsetPos; + Quaternion? offsetRot = stateChangeInfo.offsetRot; + Vector3? velocity = stateChangeInfo.velocity; + if (offsetRot.HasValue) + { + base.transform.rotation = offsetRot.Value; + } + if (offsetPos.HasValue) + { + base.transform.position = offsetPos.Value; + } + if (velocity.HasValue) + { + Rigidbody rb = netObj.Rb; + if ((bool)rb) + { + rb.velocity = velocity.Value; + } + else + { + Rigidbody2D rb2D = netObj.Rb2D; + if ((bool)rb2D) + { + rb2D.velocity = velocity.Value; + } + } + } + if (flag3 || flag2 || force) + { + for (int j = 0; j < onStateChangeCallbacks.Count; j++) + { + onStateChangeCallbacks[j].OnStateChange(objState, state, base.transform, currentMount, netObjIsReady); + } + } + } + + private void ChangeOwnerToParentMountsOwner() + { + if (!base.IsMine) + { + return; + } + if (!syncOwner) + { + Debug.LogWarning(base.name + " cannot automatically change owner without a " + typeof(SyncOwner).Name + " component."); + } + else + { + if (currentMount == null) + { + return; + } + PhotonView photonView = currentMount.PhotonView; + if ((bool)photonView) + { + int newOwnerId = photonView.Owner?.ActorNumber ?? 0; + if (autoOwnerChange) + { + syncOwner.TransferOwner(newOwnerId); + } + } + else if (autoOwnerChange) + { + GetComponent<SyncOwner>().TransferOwner(0); + } + } + } + + protected virtual void InvalidMountHandler(ObjState newState, Mount newMount, bool force) + { + Debug.LogWarning("Invalid Mount Handled!!"); + ChangeState(new StateChangeInfo(ObjState.Visible, null, force: true)); + } + + public virtual bool ChangeMount(int newMountId) + { + if ((object)currentMount == null) + { + Debug.LogWarning("'" + base.name + "' is not currently mounted, so we cannot change to a different mount."); + return false; + } + if (((int)mountableTo & (1 << newMountId)) == 0) + { + Debug.LogWarning("'" + base.name + "' is trying to switch to a mount '" + MountSettings.GetName(newMountId) + "' , but mount is not set as valid in SyncState."); + return false; + } + Dictionary<int, Mount> mountIdLookup = currentMount.mountsLookup.mountIdLookup; + if (!mountIdLookup.ContainsKey(newMountId)) + { + Debug.LogWarning("'" + base.name + "' doesn't contain a mount for '" + MountSettings.GetName(newMountId) + "'."); + return false; + } + Mount mount = mountIdLookup[newMountId]; + ChangeState(new StateChangeInfo(currentState.state, mount, force: false)); + return true; + } + + public void OnCaptureCurrentState(int frameId) + { + DequeueStateChanges(); + frames[frameId].CopyFrom(currentState); + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + if (!base.enabled) + { + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + Frame frame = frames[frameId]; + bool flag = IsKeyframe(frameId); + bool flag2 = (writeFlags & SerializationFlags.NewConnection) != 0; + bool flag3 = prevSerializedFrame == null; + bool num = flag3 || frame.state != prevSerializedFrame.state; + bool flag4 = flag3 || frame.mountTypeId != prevSerializedFrame.mountTypeId || frame.mountToViewID != prevSerializedFrame.mountToViewID; + bool flag5 = flag2 || flag || flag3; + bool flag6 = num || flag4; + bool flag7 = flag5 || flag6; + bool flag8 = flag3 || flag2 || (keyframeRate == 0 && flag7) || (mountReliable && flag4); + if (!flag7 && !flag8) + { + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + buffer.WriteBool(b: true, ref bitposition); + SerializationFlags serializationFlags = SerializationFlags.HasContent; + if (flag8) + { + serializationFlags |= SerializationFlags.ForceReliable; + } + buffer.Write((ulong)frame.state, ref bitposition, 6); + if ((frame.state & ObjState.Mounted) != 0) + { + if (flag4 || flag5) + { + if (!flag) + { + buffer.Write(1uL, ref bitposition, 1); + } + buffer.WritePackedBytes((uint)frame.mountToViewID.Value, ref bitposition, 32); + if (bitsForMountType > 0) + { + int num2 = mountTypeIdToIndex[frame.mountTypeId.Value]; + buffer.Write((uint)num2, ref bitposition, bitsForMountType); + } + } + else if (!flag) + { + buffer.Write(0uL, ref bitposition, 1); + } + } + prevSerializedFrame = frame; + return serializationFlags; + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + Frame frame = frames[originFrameId]; + if (!buffer.ReadBool(ref bitposition)) + { + return SerializationFlags.None; + } + frame.state = (ObjState)buffer.Read(ref bitposition, 6); + if ((frame.state & ObjState.Mounted) == 0) + { + frame.content = FrameContents.Complete; + return SerializationFlags.HasContent; + } + if (IsKeyframe(originFrameId) || buffer.Read(ref bitposition, 1) == 1) + { + if ((frame.state & ObjState.Mounted) != 0) + { + frame.mountToViewID = (int)buffer.ReadPackedBytes(ref bitposition, 32); + if (bitsForMountType > 0) + { + int num = (int)buffer.Read(ref bitposition, bitsForMountType); + int value = indexToMountTypeId[num]; + frame.mountTypeId = value; + } + else + { + frame.mountTypeId = 0; + } + } + frame.content = FrameContents.Complete; + return SerializationFlags.HasContent; + } + frame.mountToViewID = null; + frame.mountTypeId = null; + frame.content = FrameContents.Partial; + return SerializationFlags.HasContent; + } + + protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsValid, bool targIsValid) + { + if (snapframe.content == FrameContents.Empty) + { + return; + } + if (targframe.content == FrameContents.Complete) + { + Transform newParent; + if (targframe.mountToViewID.HasValue) + { + Mount mount = GetMount(targframe.mountToViewID, targframe.mountTypeId); + newParent = (mount ? mount.transform.parent : null); + } + else + { + newParent = null; + } + if ((bool)syncTransform) + { + syncTransform.UpdateParent(targframe.state, newParent); + } + } + if (snapframe.content >= FrameContents.Extrapolated) + { + ApplyFrame(snapframe); + } + } + + private void ApplyFrame(Frame frame) + { + ObjState state = frame.state; + bool num = (state & ObjState.Mounted) != 0; + bool force = false; + Mount mount2; + if (num) + { + int? mountToViewID = frame.mountToViewID; + if (mountToViewID.HasValue) + { + int? mountTypeId = frame.mountTypeId; + Mount mount = GetMount(mountToViewID, mountTypeId); + if ((object)mount == currentMount && state == currentState.state) + { + return; + } + if ((bool)mount) + { + mount2 = mount; + base.ReadyState = ReadyStateEnum.Ready; + force = true; + } + else + { + mount2 = currentMount; + } + } + else if (currentMount == null) + { + mount2 = null; + } + else + { + base.ReadyState = ReadyStateEnum.Ready; + mount2 = currentMount; + force = true; + } + } + else + { + base.ReadyState = ReadyStateEnum.Ready; + force = true; + mount2 = null; + } + ChangeState(new StateChangeInfo(state, mount2, force)); + } + + public static Mount GetMount(int? viewID, int? mountId) + { + if (!viewID.HasValue || !mountId.HasValue) + { + return null; + } + PhotonView photonView = PhotonNetwork.GetPhotonView(viewID.Value); + MountsManager mountsManager = (photonView ? photonView.GetComponent<MountsManager>() : null); + if ((bool)mountsManager) + { + return mountsManager.mountIdLookup[mountId.Value]; + } + return null; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncTransform.cs b/ROUNDS/Photon.Pun.Simple/SyncTransform.cs new file mode 100644 index 0000000..208f2a3 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncTransform.cs @@ -0,0 +1,518 @@ +using System.Collections.Generic; +using emotitron.Compression; +using Photon.Compression; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[DisallowMultipleComponent] +public class SyncTransform : SyncObject<SyncTransform.Frame>, ISyncTransform, IOnSnapshot, IOnNetSerialize, IOnAuthorityChanged, IReadyable, IUseKeyframes, IDeltaFrameChangeDetect, IOnInterpolate, IOnCaptureState, IFlagTeleport +{ + public class Frame : FrameBase + { + public bool hasTeleported; + + public Matrix m; + + public CompressedMatrix cm; + + public SyncTransform owner; + + public Matrix telem; + + public CompressedMatrix telecm; + + public int parentHash; + + public int telePparentHash; + + public Frame() + { + m = new Matrix(); + cm = new CompressedMatrix(); + telem = new Matrix(); + telecm = new CompressedMatrix(); + parentHash = -2; + } + + public Frame(SyncTransform sst, int frameId) + : base(frameId) + { + m = new Matrix(); + cm = new CompressedMatrix(); + telem = new Matrix(); + telecm = new CompressedMatrix(); + sst.transformCrusher.Capture(sst.transform, cm, m); + Transform parent = sst.transform.parent; + parentHash = (parent ? parent.GetInstanceID() : (-1)); + } + + public Frame(Frame srcFrame, int frameId) + : base(frameId) + { + m = new Matrix(); + cm = new CompressedMatrix(); + telem = new Matrix(); + telecm = new CompressedMatrix(); + CopyFrom(srcFrame); + } + + public void Set(SyncTransform sst, int frameId) + { + sst.transformCrusher.Capture(sst.transform, cm, m); + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + Frame frame = sourceFrame as Frame; + if (frame.hasTeleported) + { + m.CopyFrom(frame.telem); + cm.CopyFrom(frame.telecm); + } + else + { + m.CopyFrom(frame.m); + cm.CopyFrom(frame.cm); + } + hasTeleported = false; + parentHash = frame.parentHash; + } + + public bool FastCompareCompressed(Frame other) + { + if (cm.Equals(other.cm)) + { + return true; + } + return false; + } + + public bool FastCompareUncompressed(Frame other) + { + if (m.position == other.m.position && m.rotation == other.m.rotation) + { + return m.scale == other.m.scale; + } + return false; + } + + public override void Clear() + { + base.Clear(); + hasTeleported = false; + parentHash = -2; + } + + public override string ToString() + { + return string.Concat("[", frameId, " ", m.position, " / ", m.rotation, "]"); + } + } + + [Tooltip("How lerping between tick states is achieved. 'Standard' is Linear. 'None' holds the previous state until t = 1. 'Catmull Rom' is experimental.")] + public Interpolation interpolation = Interpolation.Linear; + + [Tooltip("Percentage of extrapolation from previous values. [0 = No Extrapolation] [.5 = 50% extrapolation] [1 = Undampened]. This allows for gradual slowing down of motion when the buffer runs dry.")] + [Range(0f, 1f)] + public float extrapolateRatio = 0.5f; + + protected int extrapolationCount; + + [Tooltip("If the distance delta between snapshots exceeds this amount, object will move to new location without lerping. Set this to zero or less to disable (for some tiny CPU savings). You can manually flag a teleport by setting the HasTeleported property to True.")] + public float teleportThreshold = 5f; + + private float teleportThresholdSqrMag; + + [Tooltip("Entire tick update from this client (all objects being serialized) will be sent as Reliable when FlagTeleport() has been called.")] + public bool teleportReliable; + + public Dictionary<int, TransformCrusher> masterSharedCrushers = new Dictionary<int, TransformCrusher>(); + + public TransformCrusher transformCrusher = new TransformCrusher + { + PosCrusher = new ElementCrusher(TRSType.Position, enableTRSTypeSelector: false) + { + hideFieldName = true, + XCrusher = new FloatCrusher(Axis.X, TRSType.Position, showEnableToggle: true) + { + BitsDeterminedBy = BitsDeterminedBy.HalfFloat, + AccurateCenter = true + }, + YCrusher = new FloatCrusher(Axis.Y, TRSType.Position, showEnableToggle: true) + { + BitsDeterminedBy = BitsDeterminedBy.HalfFloat, + AccurateCenter = true + }, + ZCrusher = new FloatCrusher(Axis.Z, TRSType.Position, showEnableToggle: true) + { + BitsDeterminedBy = BitsDeterminedBy.HalfFloat, + AccurateCenter = true + } + }, + RotCrusher = new ElementCrusher(TRSType.Quaternion, enableTRSTypeSelector: false) + { + hideFieldName = true, + XCrusher = new FloatCrusher(Axis.X, TRSType.Euler, showEnableToggle: true) + { + Bits = 12, + AccurateCenter = true + }, + YCrusher = new FloatCrusher(Axis.Y, TRSType.Euler, showEnableToggle: true) + { + Bits = 12, + AccurateCenter = true + }, + ZCrusher = new FloatCrusher(Axis.Z, TRSType.Euler, showEnableToggle: true) + { + Bits = 12, + AccurateCenter = true + }, + QCrusher = new QuatCrusher(44, showEnableToggle: true, isStandalone: false) + }, + SclCrusher = new ElementCrusher(TRSType.Scale, enableTRSTypeSelector: false) + { + hideFieldName = true, + uniformAxes = ElementCrusher.UniformAxes.NonUniform, + XCrusher = new FloatCrusher(BitPresets.Bits8, -1f, 1f, Axis.X, TRSType.Scale, showEnableToggle: true) + { + TRSType = TRSType.Scale, + AccurateCenter = true, + BitsDeterminedBy = BitsDeterminedBy.SetBits + }, + YCrusher = new FloatCrusher(BitPresets.Bits8, -1f, 1f, Axis.Y, TRSType.Scale, showEnableToggle: true) + { + TRSType = TRSType.Scale, + AccurateCenter = true, + BitsDeterminedBy = BitsDeterminedBy.SetBits, + Enabled = false + }, + ZCrusher = new FloatCrusher(BitPresets.Bits8, -1f, 1f, Axis.Z, TRSType.Scale, showEnableToggle: true) + { + TRSType = TRSType.Scale, + AccurateCenter = true, + BitsDeterminedBy = BitsDeterminedBy.SetBits, + Enabled = false + } + } + }; + + protected bool hasTeleported; + + protected int teleNewParentId; + + protected Matrix preTeleportM = new Matrix(); + + protected CompressedMatrix preTeleportCM = new CompressedMatrix(); + + private Rigidbody rb; + + private Rigidbody2D rb2d; + + private List<ITransformController> iTransformControllers = new List<ITransformController>(1); + + protected bool allowInterpolation; + + protected bool allowReconstructionOfEmpty; + + public static Stack<Frame[]> framePool = new Stack<Frame[]>(); + + public Frame prevSentFrame; + + protected bool skipInterpolation; + + public override bool AllowInterpolation => allowInterpolation; + + public override bool AllowReconstructionOfEmpty => allowReconstructionOfEmpty; + + public override int ApplyOrder => 9; + + public void FlagTeleport() + { + if (base.IsMine) + { + if (!hasTeleported) + { + CaptureCurrent(preTeleportM, preTeleportCM); + } + hasTeleported = true; + } + } + + public void UpdateParent(ObjState state, Transform newParent) + { + teleNewParentId = (newParent ? newParent.GetInstanceID() : (((state & ObjState.Mounted) != 0) ? (-2) : (-1))); + } + + public override void OnAwake() + { + base.OnAwake(); + rb = GetComponent<Rigidbody>(); + rb2d = GetComponent<Rigidbody2D>(); + GetComponents(iTransformControllers); + teleportThresholdSqrMag = ((teleportThreshold <= 0f) ? 0f : (teleportThreshold * teleportThreshold)); + ConnectSharedCaches(); + allowInterpolation = true; + allowReconstructionOfEmpty = true; + for (int i = 0; i < iTransformControllers.Count; i++) + { + ITransformController transformController = iTransformControllers[i]; + allowInterpolation &= !transformController.HandlesInterpolation; + allowReconstructionOfEmpty &= !transformController.HandlesExtrapolation; + } + } + + private void ConnectSharedCaches() + { + if (masterSharedCrushers.ContainsKey(prefabInstanceId)) + { + transformCrusher = masterSharedCrushers[prefabInstanceId]; + } + else + { + masterSharedCrushers.Add(prefabInstanceId, transformCrusher); + } + } + + private void OnDestroy() + { + framePool.Push(frames); + } + + protected override void PopulateFrames() + { + int frameCount = TickEngineSettings.frameCount; + if (framePool.Count == 0) + { + frames = new Frame[frameCount + 1]; + frames[frameCount] = new Frame(this, frameCount); + for (int i = 0; i <= frameCount; i++) + { + frames[i] = new Frame(frames[frameCount], i); + } + } + else + { + frames = framePool.Pop(); + frames[frameCount].Set(this, frameCount); + for (int j = 0; j < frameCount; j++) + { + frames[j].CopyFrom(frames[frameCount]); + } + } + } + + protected void CaptureCurrent(Matrix m, CompressedMatrix cm, bool forceUseTransform = false) + { + if (forceUseTransform) + { + transformCrusher.Capture(base.transform, cm, m); + } + else if ((bool)rb) + { + transformCrusher.Capture(rb, cm, m); + } + else if ((bool)rb2d) + { + transformCrusher.Capture(rb2d, cm, m); + } + else + { + transformCrusher.Capture(base.transform, cm, m); + } + } + + public virtual void OnCaptureCurrentState(int frameId) + { + Frame frame = frames[frameId]; + frame.hasTeleported = hasTeleported; + if (hasTeleported) + { + frame.cm.CopyFrom(preTeleportCM); + frame.m.CopyFrom(preTeleportM); + CaptureCurrent(frame.telem, frame.telecm, forceUseTransform: true); + transformCrusher.Apply(base.transform, frame.telem); + hasTeleported = false; + } + else + { + CaptureCurrent(frame.m, frame.cm); + } + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + Frame frame = frames[frameId]; + bool flag = frame.hasTeleported; + bool flag2 = flag || (writeFlags & SerializationFlags.NewConnection) != 0; + if (!flag2 && !base.isActiveAndEnabled) + { + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + bool flag3 = IsKeyframe(frameId); + if (!flag2 && !flag3 && (!useDeltas || (prevSentFrame != null && frame.cm.Equals(prevSentFrame.cm)))) + { + buffer.WriteBool(b: false, ref bitposition); + prevSentFrame = frame; + return SerializationFlags.None; + } + SerializationFlags serializationFlags = SerializationFlags.HasContent; + buffer.WriteBool(b: true, ref bitposition); + buffer.WriteBool(flag, ref bitposition); + if (flag) + { + transformCrusher.Write(frame.telecm, buffer, ref bitposition); + if (teleportReliable) + { + serializationFlags |= SerializationFlags.ForceReliable; + } + } + transformCrusher.Write(frame.cm, buffer, ref bitposition); + transformCrusher.Decompress(frame.m, frame.cm); + prevSentFrame = frame; + return serializationFlags; + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + Frame frame = (photonView.IsMine ? offtickFrame : frames[originFrameId]); + if (!buffer.ReadBool(ref bitposition)) + { + frame.content = FrameContents.Empty; + return SerializationFlags.None; + } + frame.content = FrameContents.Complete; + if (frame.hasTeleported = buffer.ReadBool(ref bitposition)) + { + transformCrusher.Read(frame.telecm, buffer, ref bitposition); + transformCrusher.Decompress(frame.telem, frame.telecm); + } + transformCrusher.Read(frame.cm, buffer, ref bitposition); + transformCrusher.Decompress(frame.m, frame.cm); + return SerializationFlags.HasContent; + } + + public override bool OnSnapshot(int prevFrameId, int snapFrameId, int targFrameId, bool prevIsValid, bool snapIsValid, bool targIsValid) + { + if (!base.OnSnapshot(prevFrameId, snapFrameId, targFrameId, prevIsValid, snapIsValid, targIsValid)) + { + return false; + } + if (snapFrame.content == FrameContents.Empty) + { + return false; + } + if (targFrame.content == FrameContents.Empty) + { + return false; + } + bool flag = snapFrame.hasTeleported; + targFrame.parentHash = teleNewParentId; + skipInterpolation = false; + if (!flag && teleportThresholdSqrMag > 0f) + { + Vector3 position = targFrame.m.position; + Vector3 vector = (flag ? snapFrame.telem.position : snapFrame.m.position); + if (Vector3.SqrMagnitude(position - vector) > teleportThresholdSqrMag) + { + skipInterpolation = true; + } + } + ApplyFrame(snapFrame); + return true; + } + + protected void ApplyFrame(Frame frame) + { + transformCrusher.Apply(base.transform, frame.hasTeleported ? frame.telem : frame.m); + } + + public override bool OnInterpolate(int snapFrameId, int targFrameId, float t) + { + if (skipInterpolation) + { + return false; + } + if (!base.OnInterpolate(snapFrameId, targFrameId, t)) + { + return false; + } + if (interpolation == Interpolation.None) + { + return false; + } + if (targFrame == null) + { + return false; + } + if (snapFrame.content == FrameContents.Empty) + { + return false; + } + if (targFrame.content == FrameContents.Empty) + { + return false; + } + if (snapFrame.parentHash != targFrame.parentHash) + { + return false; + } + Matrix start = (snapFrame.hasTeleported ? snapFrame.telem : snapFrame.m); + if (interpolation == Interpolation.Linear) + { + Matrix.Lerp(Matrix.reusable, start, targFrame.m, t); + } + else + { + Matrix.CatmullRomLerpUnclamped(Matrix.reusable, prevFrame.m, snapFrame.m, targFrame.m, t); + } + transformCrusher.Apply(base.transform, Matrix.reusable); + return true; + } + + protected override void InterpolateFrame(Frame targframe, Frame startframe, Frame endframe, float t) + { + if (startframe.parentHash == -2 || startframe.parentHash != endframe.parentHash) + { + targFrame.content = FrameContents.Empty; + return; + } + targframe.CopyFrom(endframe); + Matrix.Lerp(targframe.m, startframe.hasTeleported ? startframe.telem : startframe.m, endframe.m, t); + transformCrusher.Compress(targframe.cm, targframe.m); + } + + protected override void ExtrapolateFrame(Frame prevframe, Frame snapframe, Frame targframe) + { + if (snapframe.content == FrameContents.Empty) + { + Debug.LogError(targframe.frameId + " Failed to extrapolate due to empty snapshot. Failsafing to current transform value."); + targframe.content = FrameContents.Empty; + return; + } + targframe.CopyFrom(snapframe); + targframe.parentHash = teleNewParentId; + if (snapframe.hasTeleported) + { + return; + } + switch (prevframe.content) + { + case FrameContents.Empty: + return; + case FrameContents.Complete: + { + int parentHash = prevframe.parentHash; + if (parentHash == -2 || prevframe.hasTeleported || parentHash != snapframe.parentHash) + { + return; + } + break; + } + } + Matrix.LerpUnclamped(targframe.m, prevframe.hasTeleported ? prevframe.telem : prevframe.m, snapframe.m, 1f + extrapolateRatio); + transformCrusher.Compress(targframe.cm, targframe.m); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/SyncVitals.cs b/ROUNDS/Photon.Pun.Simple/SyncVitals.cs new file mode 100644 index 0000000..342019d --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/SyncVitals.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using Photon.Compression; +using Photon.Pun.Simple.ContactGroups; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class SyncVitals : SyncObject<SyncVitals.Frame>, IVitalsSystem, IContactSystem, IOnSnapshot, IOnNetSerialize, IOnAuthorityChanged, IOnPostSimulate, IOnVitalValueChange, IOnVitalChange, IOnCaptureState, IUseKeyframes, IOnStateChange +{ + public class Frame : FrameBase + { + public VitalsData vitalsData; + + public Frame() + { + } + + public Frame(int frameId) + : base(frameId) + { + } + + public Frame(int frameId, Vitals vitals) + : base(frameId) + { + vitalsData = new VitalsData(vitals); + } + + public override void CopyFrom(FrameBase sourceFrame) + { + base.CopyFrom(sourceFrame); + VitalsData source = (sourceFrame as Frame).vitalsData; + vitalsData.CopyFrom(source); + } + } + + public Vitals vitals = new Vitals(); + + [SerializeField] + protected ContactGroupMaskSelector contactGroups; + + [Tooltip("Vital triggers/pickups must have this as a valid mount type. When pickups will attach to this mount when picked up.")] + public MountSelector defaultMounting = new MountSelector(0); + + [Tooltip("When root vital <= zero, syncState.Despawn() will be called. This allows for a default handling of object 'death'.")] + public bool autoDespawn = true; + + [Tooltip("When OnStateChange changes from ObjState.Despawned to any other state, vital values will be reset to their starting defaults.")] + public bool resetOnSpawn = true; + + [NonSerialized] + private VitalsData lastSentData; + + public List<IOnVitalsValueChange> OnVitalsValueChange = new List<IOnVitalsValueChange>(0); + + public List<IOnVitalsParamChange> OnVitalsParamChange = new List<IOnVitalsParamChange>(0); + + public List<IOnRootVitalBecameZero> OnRootVitalBecameZero = new List<IOnRootVitalBecameZero>(0); + + protected SyncState syncState; + + private Vital[] vitalArray; + + protected Vital rootVital; + + private int vitalsCount; + + protected int defaultMountingMask; + + protected bool isPredicted; + + private bool wasDespawned; + + public override int ApplyOrder => 15; + + public override bool AllowReconstructionOfEmpty => false; + + public byte SystemIndex { get; set; } + + public Vitals Vitals => vitals; + + public IContactGroupMask ValidContactGroups => contactGroups; + + public int ValidMountsMask => 1 << defaultMounting.id; + + public Mount DefaultMount { get; set; } + + protected override void PopulateFrames() + { + int frameCount = TickEngineSettings.frameCount; + frames = new Frame[frameCount + 1]; + for (int i = 0; i <= frameCount; i++) + { + frames[i] = new Frame(i, vitals); + } + } + + public override void OnAwake() + { + base.OnAwake(); + base.transform.EnsureRootComponentExists<ContactManager, NetObject>(); + if ((bool)netObj) + { + syncState = netObj.GetComponent<SyncState>(); + } + vitalArray = vitals.VitalArray; + vitalsCount = vitals.vitalDefs.Count; + rootVital = vitalArray[0]; + vitals.OnVitalValueChangeCallbacks.Add(this); + lastSentData = new VitalsData(vitals); + for (int i = 0; i < vitalsCount; i++) + { + vitalArray[i].ResetValues(); + } + defaultMountingMask = 1 << defaultMounting.id; + } + + public override void OnStart() + { + base.OnStart(); + MountsManager component = GetComponent<MountsManager>(); + if ((bool)component) + { + if (component.mountIdLookup.ContainsKey(defaultMounting.id)) + { + DefaultMount = component.mountIdLookup[defaultMounting.id]; + return; + } + Debug.LogWarning("Sync Vitals has a Default Mount setting of " + MountSettings.GetName(defaultMounting.id) + " but no such mount is defined yet on GameObject: '" + base.name + "'. Root mount will be used as a failsafe."); + defaultMounting.id = 0; + DefaultMount = component.mountIdLookup[0]; + } + } + + public override void OnAuthorityChanged(bool isMine, bool controllerChanged) + { + base.OnAuthorityChanged(isMine, controllerChanged); + OwnedIVitals.OnChangeAuthority(this, isMine, controllerChanged); + } + + public Consumption TryTrigger(IContactReactor icontactReactor, ContactEvent contactEvent, int compatibleMounts) + { + if (!(icontactReactor is IVitalsContactReactor vitalsContactReactor)) + { + return Consumption.None; + } + if ((int)contactGroups != 0) + { + int num = contactEvent.contactTrigger.ContactGroupsAssign?.Mask ?? 0; + if ((contactGroups.Mask & num) == 0) + { + return Consumption.None; + } + } + if (compatibleMounts != defaultMountingMask && (compatibleMounts & defaultMountingMask) == 0) + { + return Consumption.None; + } + Vital vital = vitals.GetVital(vitalsContactReactor.VitalNameType); + if (vital == null) + { + return Consumption.None; + } + double amountConsumed; + if (base.IsMine) + { + double discharge = vitalsContactReactor.DischargeValue(contactEvent.contactType); + amountConsumed = vitals.ApplyCharges(discharge, vitalsContactReactor.AllowOverload, vitalsContactReactor.Propagate); + } + else + { + amountConsumed = vital.TestApplyChange(vitalsContactReactor, contactEvent); + } + if (icontactReactor is IVitalsConsumable iva) + { + return TestConsumption(amountConsumed, iva, contactEvent); + } + return Consumption.None; + } + + protected Consumption TestConsumption(double amountConsumed, IVitalsConsumable iva, ContactEvent contactEvent) + { + Consumption consumption = iva.Consumption; + double num = iva.DischargeValue(contactEvent.contactType); + switch (consumption) + { + case Consumption.None: + return Consumption.None; + case Consumption.All: + if (amountConsumed != 0.0) + { + iva.Charges = 0.0; + return Consumption.All; + } + return Consumption.None; + default: + { + int result = ((amountConsumed != 0.0) ? ((num != amountConsumed) ? 1 : 3) : 0); + iva.Charges -= amountConsumed; + return (Consumption)result; + } + } + } + + public Mount TryPickup(IContactReactor reactor, ContactEvent contactEvent) + { + return DefaultMount; + } + + public void OnPostSimulate(int frameId, int subFrameId, bool isNetTick) + { + if (isNetTick) + { + vitals.Simulate(); + } + } + + public virtual void OnCaptureCurrentState(int frameId) + { + VitalData[] datas = frames[frameId].vitalsData.datas; + for (int i = 0; i < vitalsCount; i++) + { + datas[i] = vitalArray[i].VitalData; + } + } + + public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags) + { + if (!base.enabled) + { + buffer.WriteBool(b: false, ref bitposition); + return SerializationFlags.None; + } + Frame frame = frames[frameId]; + buffer.WriteBool(b: true, ref bitposition); + bool keyframe = IsKeyframe(frameId); + return vitals.Serialize(frame.vitalsData, lastSentData, buffer, ref bitposition, keyframe); + } + + public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival) + { + Frame frame = (base.IsMine ? offtickFrame : frames[originFrameId]); + if (!buffer.ReadBool(ref bitposition)) + { + return SerializationFlags.None; + } + bool keyframe = IsKeyframe(originFrameId); + SerializationFlags serializationFlags = vitals.Deserialize(frame.vitalsData, buffer, ref bitposition, keyframe); + frame.content = (((serializationFlags & SerializationFlags.IsComplete) != 0) ? FrameContents.Complete : (((serializationFlags & SerializationFlags.HasContent) != 0) ? FrameContents.Partial : FrameContents.Empty)); + return serializationFlags; + } + + [Obsolete("Use vitals.ApplyCharges() instead")] + public double ApplyDamage(double damage) + { + if (!base.IsMine) + { + return damage; + } + if (damage == 0.0) + { + return damage; + } + return vitals.ApplyCharges(damage, allowOverload: false, propagate: true); + } + + public void OnVitalValueChange(Vital vital) + { + if (vital.VitalData.Value <= 0.0) + { + RootVitalBecameZero(vital); + } + int i = 0; + for (int count = OnVitalsValueChange.Count; i < count; i++) + { + OnVitalsValueChange[i].OnVitalValueChange(vital); + } + } + + public void OnVitalParamChange(Vital vital) + { + Debug.LogError("Not implemented"); + int i = 0; + for (int count = OnVitalsParamChange.Count; i < count; i++) + { + OnVitalsParamChange[i].OnVitalParamChange(vital); + } + } + + protected virtual void RootVitalBecameZero(Vital vital) + { + int i = 0; + for (int count = OnRootVitalBecameZero.Count; i < count; i++) + { + OnRootVitalBecameZero[i].OnRootVitalBecameZero(vital, null); + } + if (autoDespawn && (bool)syncState && rootVital == vital) + { + syncState.Despawn(immediate: false); + } + } + + public void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true) + { + if (wasDespawned && newState != 0) + { + for (int i = 0; i < vitalsCount; i++) + { + vitalArray[i].ResetValues(); + } + } + wasDespawned = newState == ObjState.Despawned; + } + + protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsValid, bool targIsValid) + { + if (snapIsValid && snapframe.content >= FrameContents.Extrapolated) + { + vitals.Apply(snapFrame.vitalsData); + } + } + + protected override void InterpolateFrame(Frame targframe, Frame startframe, Frame endframe, float t) + { + targframe.CopyFrom(startframe); + } + + protected override void ExtrapolateFrame(Frame prevframe, Frame snapframe, Frame targframe) + { + VitalData[] datas = snapframe.vitalsData.datas; + VitalData[] datas2 = targframe.vitalsData.datas; + for (int i = 0; i < vitalsCount; i++) + { + datas2[i] = vitalArray[i].VitalDef.Extrapolate(datas[i]); + } + targframe.content = FrameContents.Extrapolated; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/TRS.cs b/ROUNDS/Photon.Pun.Simple/TRS.cs new file mode 100644 index 0000000..fbe4cb1 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/TRS.cs @@ -0,0 +1,8 @@ +namespace Photon.Pun.Simple; + +public enum TRS +{ + Position, + Rotation, + Scale +} diff --git a/ROUNDS/Photon.Pun.Simple/TRSDefinitionBase.cs b/ROUNDS/Photon.Pun.Simple/TRSDefinitionBase.cs new file mode 100644 index 0000000..9b1bbf7 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/TRSDefinitionBase.cs @@ -0,0 +1,9 @@ +using System; + +namespace Photon.Pun.Simple; + +[Serializable] +public class TRSDefinitionBase +{ + public bool local = true; +} diff --git a/ROUNDS/Photon.Pun.Simple/TeleportMarker.cs b/ROUNDS/Photon.Pun.Simple/TeleportMarker.cs new file mode 100644 index 0000000..2a46847 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/TeleportMarker.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using emotitron.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class TeleportMarker : MonoBehaviour +{ + public MarkerNameType markerType; + + public static Dictionary<int, List<TeleportMarker>> lookup = new Dictionary<int, List<TeleportMarker>>(); + + public static Dictionary<int, int> nexts = new Dictionary<int, int>(); + + private void OnEnable() + { + int hash = markerType.hash; + if (!lookup.ContainsKey(hash)) + { + lookup.Add(hash, new List<TeleportMarker>()); + } + lookup[hash].Add(this); + } + + private void OnDisable() + { + int hash = markerType.hash; + if (lookup.ContainsKey(hash) && lookup[hash].Contains(this)) + { + lookup[hash].Remove(this); + } + } + + public static TeleportMarker GetRandomMarker(int hash, float seed) + { + if (!lookup.ContainsKey(hash)) + { + return null; + } + List<TeleportMarker> list = lookup[hash]; + int index = Random.Range(0, list.Count); + return list[index]; + } + + public static TeleportMarker GetNextMarker(int hash) + { + if (!lookup.ContainsKey(hash)) + { + return null; + } + List<TeleportMarker> list = lookup[hash]; + int num = nexts[hash]; + num++; + if (num >= nexts.Count) + { + num = 0; + } + nexts[hash] = num; + return list[num]; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/TickEngineSettings.cs b/ROUNDS/Photon.Pun.Simple/TickEngineSettings.cs new file mode 100644 index 0000000..faea40c --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/TickEngineSettings.cs @@ -0,0 +1,153 @@ +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class TickEngineSettings : SettingsScriptableObject<TickEngineSettings> +{ + public enum FrameCountEnum + { + FrameCount12 = 12, + FrameCount30 = 30, + FrameCount60 = 60, + FrameCount120 = 120 + } + + public enum BufferCorrection + { + Manual, + Auto + } + + public enum LogInfoLevel + { + All, + WarningsAndErrors, + ErrorsOnly, + None + } + + [Space] + [Tooltip("Enable/Disable for the NetMaster timing callbacks. This needs to be enabled for networking to work.")] + public bool enableTickEngine = true; + + [Tooltip("Disable to pause sending Updates to Relay if no other Players are in the current Room. Default is false to save on data usage. Enable if your code requires updates to echo back to controller.")] + public bool sendWhenSolo; + + [Header("Debugging")] + [SerializeField] + private LogInfoLevel logLevel = LogInfoLevel.WarningsAndErrors; + + [Tooltip("The size of the circular buffer.")] + [SerializeField] + [HideInInspector] + private FrameCountEnum _frameCount = FrameCountEnum.FrameCount30; + + public static int frameCount; + + [SerializeField] + [HideInInspector] + private BufferCorrection _bufferCorrection; + + [Tooltip("Target size of the frame buffer. This is the number of frames in the buffer that is considered ideal. The lower the number the less latency, but with a greater risk of buffer underruns that lead to extrapolation/hitching.")] + [SerializeField] + [HideInInspector] + private int _targetBufferSize = 2; + + public static int targetBufferSize; + + [Tooltip("Buffer sizes above this value wll be considered to be excessive, and will trigger multiple frames being processed to shrink the buffer.")] + [SerializeField] + [HideInInspector] + private int _maxBufferSize = 3; + + public static int maxBufferSize; + + [Tooltip("Buffer sizes below this value will trigger the frames to hold for extra ticks in order to grow the buffer.")] + [SerializeField] + [HideInInspector] + private int _minBufferSize = 1; + + public static int minBufferSize; + + [Tooltip("The number of ticks a buffer will be allowed to be below the the Min Buffer Size before starting to correct. This value prevents overreaction to network hiccups and allows for a few ticks before applying harsh corrections. Ideally this value will be larger than Ticks Before Shrink.")] + [SerializeField] + [HideInInspector] + private int _ticksBeforeGrow = 8; + + public static int ticksBeforeGrow; + + [Tooltip("The number of ticks a buffer will be allowed to exceed Max Buffer Size before starting to correct. This value prevents overreaction to network hiccups and allows for a few ticks before applying harsh corrections. Ideally this value will be smaller than Ticks Before Grow.")] + [SerializeField] + [HideInInspector] + private int _ticksBeforeShrink = 5; + + public static int ticksBeforeShrink; + + [Tooltip("States are sent post PhysX/FixedUpdate. Setting this to a value greater than one reduces these sends by only sending every X fixed tick.\n1 = Every Tick\n2 = Every Other\n3 = Every Third, etc.")] + [SerializeField] + [HideInInspector] + private int _sendEveryXTick = 3; + + public static int sendEveryXTick = 3; + + [Space(4f)] + public static int halfFrameCount; + + public static int thirdFrameCount; + + public static int quaterFrameCount; + + public static int frameCountBits; + + public static float netTickInterval; + + public static float netTickIntervalInv; + + public static float targetBufferInterval; + + private static float secondsOfBuffer; + + private static float secondsOfHalfBuffer; + + private static float bufferTargSecs; + + public static LogInfoLevel LogLevel => SettingsScriptableObject<TickEngineSettings>.Single.logLevel; + + public static int MaxKeyframes => (int)SettingsScriptableObject<TickEngineSettings>.Single._frameCount / 3; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + public static void Bootstrap() + { + SettingsScriptableObject<TickEngineSettings>.Single.CalculateBufferValues(); + } + + private void CalculateBufferValues() + { + if (_bufferCorrection == BufferCorrection.Manual) + { + minBufferSize = _minBufferSize; + maxBufferSize = _maxBufferSize; + } + else + { + minBufferSize = _minBufferSize; + maxBufferSize = _maxBufferSize; + } + frameCount = (int)_frameCount; + halfFrameCount = frameCount / 2; + thirdFrameCount = frameCount / 3; + quaterFrameCount = frameCount / 4; + frameCountBits = frameCount.GetBitsForMaxValue(); + netTickInterval = Time.fixedDeltaTime * (float)_sendEveryXTick; + netTickIntervalInv = 1f / (Time.fixedDeltaTime * (float)_sendEveryXTick); + targetBufferInterval = Time.fixedDeltaTime * (float)_sendEveryXTick * (float)_targetBufferSize; + sendEveryXTick = _sendEveryXTick; + targetBufferSize = _targetBufferSize; + ticksBeforeGrow = _ticksBeforeGrow; + ticksBeforeShrink = _ticksBeforeShrink; + secondsOfBuffer = Time.fixedDeltaTime * (float)_sendEveryXTick * (float)frameCount; + secondsOfHalfBuffer = secondsOfBuffer * 0.5f; + bufferTargSecs = netTickInterval * (float)_targetBufferSize; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/Vital.cs b/ROUNDS/Photon.Pun.Simple/Vital.cs new file mode 100644 index 0000000..3dfa599 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Vital.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[Serializable] +public class Vital +{ + [SerializeField] + private VitalDefinition vitalDef; + + [NonSerialized] + private VitalData vitalData; + + public List<IOnVitalValueChange> OnValueChangeCallbacks = new List<IOnVitalValueChange>(0); + + public List<IOnVitalParamChange> OnParamChangeCallbacks = new List<IOnVitalParamChange>(0); + + public VitalDefinition VitalDef => vitalDef; + + public VitalData VitalData + { + get + { + return vitalData; + } + private set + { + vitalData = value; + } + } + + public double Value + { + get + { + return vitalData.Value; + } + set + { + if (value == double.NegativeInfinity) + { + return; + } + double value2 = vitalData.Value; + double num = Math.Max(Math.Min(value, vitalDef.MaxValue), 0.0); + vitalData.Value = num; + if (value2 != num) + { + for (int i = 0; i < OnValueChangeCallbacks.Count; i++) + { + OnValueChangeCallbacks[i].OnVitalValueChange(this); + } + } + } + } + + public int TicksUntilDecay + { + get + { + return vitalData.ticksUntilDecay; + } + set + { + vitalData.ticksUntilDecay = value; + } + } + + public int TicksUntilRegen + { + get + { + return vitalData.ticksUntilRegen; + } + set + { + vitalData.ticksUntilRegen = value; + } + } + + public Vital(VitalDefinition vitalDef) + { + this.vitalDef = vitalDef; + } + + public void Initialize(float tickDuration) + { + vitalDef.Initialize(tickDuration); + ResetValues(); + } + + public void ResetValues() + { + vitalData = vitalDef.GetDefaultData(); + for (int i = 0; i < OnValueChangeCallbacks.Count; i++) + { + OnValueChangeCallbacks[i].OnVitalValueChange(this); + } + } + + public void AddIOnVitalChange(IOnVitalChange cb) + { + if (cb is IOnVitalValueChange item) + { + OnValueChangeCallbacks.Add(item); + } + if (cb is IOnVitalParamChange item2) + { + OnParamChangeCallbacks.Add(item2); + } + } + + public void RemoveIOnVitalChange(IOnVitalChange cb) + { + if (cb is IOnVitalValueChange item) + { + OnValueChangeCallbacks.Remove(item); + } + if (cb is IOnVitalParamChange item2) + { + OnParamChangeCallbacks.Remove(item2); + } + } + + public void Apply(VitalData vdata) + { + Value = vdata.Value; + vitalData.ticksUntilDecay = vdata.ticksUntilDecay; + vitalData.ticksUntilRegen = vdata.ticksUntilRegen; + } + + public double ApplyCharges(double amt, bool allowOverload, bool ignoreAbsorbtion) + { + double num = (ignoreAbsorbtion ? amt : (amt * vitalDef.Absorbtion)); + double value = Value; + double num2 = value + num; + if (!allowOverload) + { + num2 = Math.Min(num2, vitalDef.FullValue); + } + Value = num2; + return Value - value; + } + + public bool IsFull(bool allowOverload) + { + return Value >= (allowOverload ? vitalDef.MaxValue : vitalDef.FullValue); + } + + public double ApplyChange(IVitalsContactReactor iVitalsAffector, ContactEvent contectEvent) + { + double amount = iVitalsAffector.DischargeValue(contectEvent.contactType); + return ApplyChange(amount, iVitalsAffector); + } + + public double ApplyChange(double amount, IVitalsContactReactor reactor = null) + { + double value = vitalData.Value; + double num = vitalData.Value + amount; + if (reactor != null && reactor.AllowOverload) + { + double maxValue = vitalDef.MaxValue; + if (value >= maxValue) + { + return 0.0; + } + if (num > maxValue) + { + num = maxValue; + } + } + else + { + double fullValue = vitalDef.FullValue; + if (value >= fullValue) + { + return 0.0; + } + if (num > fullValue) + { + num = fullValue; + } + } + Value = num; + return num - value; + } + + public void DisruptRegen() + { + vitalData.ticksUntilRegen = vitalDef.RegenDelayInTicks; + } + + public void DisruptDecay() + { + vitalData.ticksUntilDecay = vitalDef.DecayDelayInTicks; + } + + public double TestApplyChange(IVitalsContactReactor iVitalsAffector, ContactEvent contactEvent) + { + double charge = iVitalsAffector.DischargeValue(contactEvent.contactType); + return TestApplyChange(charge, iVitalsAffector); + } + + public double TestApplyChange(double charge, IVitalsContactReactor iVitalsAffector) + { + double value = vitalData.Value; + double num = vitalData.Value + charge; + if (iVitalsAffector != null && iVitalsAffector.AllowOverload) + { + double maxValue = vitalDef.MaxValue; + if (value >= maxValue) + { + return 0.0; + } + if (num > maxValue) + { + num = maxValue; + } + } + else + { + double maxValue2 = vitalDef.MaxValue; + if (value >= maxValue2) + { + return 0.0; + } + if (num > maxValue2) + { + num = maxValue2; + } + } + return num - value; + } + + public void Simulate() + { + if (vitalData.ticksUntilRegen > 0) + { + vitalData.ticksUntilRegen--; + } + else if (vitalData.Value < vitalDef.FullValue) + { + Value = Math.Min(vitalData.Value + vitalDef.RegenPerTick, vitalDef.FullValue); + } + if (vitalData.ticksUntilDecay > 0) + { + vitalData.ticksUntilDecay--; + } + else if (vitalData.Value > vitalDef.FullValue) + { + Value = Math.Max(vitalData.Value - vitalDef.DecayPerTick, vitalDef.FullValue); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalData.cs b/ROUNDS/Photon.Pun.Simple/VitalData.cs new file mode 100644 index 0000000..de26526 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalData.cs @@ -0,0 +1,34 @@ +namespace Photon.Pun.Simple; + +public struct VitalData +{ + private double _value; + + public int ticksUntilRegen; + + public int ticksUntilDecay; + + public double Value + { + get + { + return _value; + } + set + { + _value = value; + } + } + + public VitalData(double value, int ticksUntilDecay, int ticksUntilRegen) + { + _value = value; + this.ticksUntilDecay = ticksUntilDecay; + this.ticksUntilRegen = ticksUntilRegen; + } + + public override string ToString() + { + return _value + " ticksUntilDecay: " + ticksUntilDecay + " ticksUntilRegen: " + ticksUntilRegen; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalDefinition.cs b/ROUNDS/Photon.Pun.Simple/VitalDefinition.cs new file mode 100644 index 0000000..9be1e39 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalDefinition.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using Photon.Compression; +using Photon.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[Serializable] +public class VitalDefinition +{ + public List<IOnVitalValueChange> iOnVitalChange = new List<IOnVitalValueChange>(); + + [SerializeField] + private VitalNameType vitalName; + + [Tooltip("Values greater than this will degrade at the decay rate until this value is reached.")] + [SerializeField] + private double _fullValue; + + [Tooltip("The absolute greatest possible value. Values above Full Value are considered overloaded, and will decay down to Full Value.")] + [SerializeField] + private uint _maxValue; + + public double startValue; + + [Tooltip("Number of simulation ticks after damage until regeneration resumes.")] + [SerializeField] + private float regenDelay; + + [Tooltip("Amount per tick values less than Full Value will increase until Full Health is reached.")] + [SerializeField] + private double regenRate; + + [Tooltip("Number of simulation ticks after overload until decay resumes.")] + [SerializeField] + private float decayDelay; + + [Tooltip("Amount per tick overloaded values greater than Full Value will degrade until Full Health is reached.")] + [SerializeField] + private double decayRate; + + [Range(0f, 1f)] + [Tooltip("How much of the damage this vital absords, the remainder is passed through to the next lower stat. 0 = None (useless), 0.5 = Half, 1 = Full. The root vital (0) likely should always be 1.")] + [SerializeField] + private double absorption; + + private int _decayDelayInTicks; + + private int _regenDelayInTicks; + + private double _decayPerTick; + + private double _regenPerTick; + + private int bitsForValue; + + private int bitsForDecayDelay; + + private int bitsForRegenDelay; + + public VitalNameType VitalName => vitalName; + + public double FullValue => _fullValue; + + public double MaxValue => _maxValue; + + public double Absorbtion => absorption; + + public int DecayDelayInTicks => _decayDelayInTicks; + + public int RegenDelayInTicks => _regenDelayInTicks; + + public double DecayPerTick => _decayPerTick; + + public double RegenPerTick => _regenPerTick; + + public void AddIOnVitalChange(IOnVitalValueChange cb) + { + iOnVitalChange.Add(cb); + } + + public void RemoveIOnVitalChange(IOnVitalValueChange cb) + { + iOnVitalChange.Remove(cb); + } + + public VitalDefinition(double fullValue, uint maxValue, double startValue, double absorbtion, float regenDelay, double regenRate, float decayDelay, double decayRate, string name) + { + _fullValue = fullValue; + _maxValue = maxValue; + this.startValue = startValue; + absorption = absorbtion; + this.regenDelay = regenDelay; + this.regenRate = regenRate; + this.decayDelay = decayDelay; + this.decayRate = decayRate; + vitalName = new VitalNameType(name); + } + + public void Initialize(float tickDuration) + { + SetTickInterval(tickDuration); + } + + public void SetTickInterval(float tickInterval) + { + _decayDelayInTicks = (int)(decayDelay / tickInterval); + _regenDelayInTicks = (int)(regenDelay / tickInterval); + _decayPerTick = decayRate * (double)tickInterval; + _regenPerTick = regenRate * (double)tickInterval; + bitsForValue = _maxValue.GetBitsForMaxValue(); + bitsForDecayDelay = _decayDelayInTicks.GetBitsForMaxValue(); + bitsForRegenDelay = _regenDelayInTicks.GetBitsForMaxValue(); + } + + public VitalData GetDefaultData() + { + return new VitalData(startValue, _decayDelayInTicks, _regenDelayInTicks); + } + + public SerializationFlags Serialize(VitalData vitalData, VitalData prevVitalData, byte[] buffer, ref int bitposition, bool keyframe = true) + { + int ticksUntilDecay = vitalData.ticksUntilDecay; + int ticksUntilRegen = vitalData.ticksUntilRegen; + int num = (int)vitalData.Value; + int num2 = (int)prevVitalData.Value; + bool flag = num != num2; + if (keyframe) + { + buffer.Write((ulong)num, ref bitposition, bitsForValue); + } + else + { + buffer.WriteBool(flag, ref bitposition); + if (flag) + { + buffer.Write((ulong)num, ref bitposition, bitsForValue); + } + } + if (ticksUntilDecay > 0) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write((ulong)ticksUntilDecay, ref bitposition, bitsForDecayDelay); + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + if (ticksUntilRegen > 0) + { + buffer.WriteBool(b: true, ref bitposition); + buffer.Write((ulong)ticksUntilRegen, ref bitposition, bitsForRegenDelay); + } + else + { + buffer.WriteBool(b: false, ref bitposition); + } + if (!(flag || keyframe)) + { + return SerializationFlags.None; + } + return SerializationFlags.HasContent; + } + + public VitalData Deserialize(byte[] buffer, ref int bitposition, bool keyframe = true) + { + double value = ((keyframe || buffer.ReadBool(ref bitposition)) ? ((double)buffer.Read(ref bitposition, bitsForValue)) : double.NegativeInfinity); + return new VitalData(value, (int)(buffer.ReadBool(ref bitposition) ? buffer.Read(ref bitposition, bitsForDecayDelay) : 0), (int)(buffer.ReadBool(ref bitposition) ? buffer.Read(ref bitposition, bitsForRegenDelay) : 0)); + } + + public VitalData Extrapolate(VitalData prev) + { + int num = ((prev.ticksUntilRegen > 0) ? (prev.ticksUntilRegen - 1) : 0); + int num2 = ((prev.ticksUntilDecay > 0) ? (prev.ticksUntilDecay - 1) : 0); + double value = prev.Value; + return new VitalData((value > FullValue && num2 == 0) ? (value - _decayPerTick) : ((value < FullValue && num == 0) ? (value + _regenPerTick) : value), num2, num); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalNameType.cs b/ROUNDS/Photon.Pun.Simple/VitalNameType.cs new file mode 100644 index 0000000..21ade62 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalNameType.cs @@ -0,0 +1,41 @@ +using System; +using emotitron.Utilities; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[Serializable] +public struct VitalNameType +{ + [HideInInspector] + public VitalType type; + + [HideInInspector] + public int hash; + + [HideInInspector] + public string name; + + public static string[] enumNames = Enum.GetNames(typeof(VitalType)); + + public string[] EnumNames => enumNames; + + public VitalNameType(VitalType vitalType) + { + type = vitalType; + name = Enum.GetName(typeof(VitalType), vitalType); + hash = name.GetHashCode(); + } + + public VitalNameType(string name) + { + type = (VitalType)NameTypeUtils.GetVitalTypeForName(name, enumNames); + this.name = name; + hash = name.GetHashCode(); + } + + public override string ToString() + { + return string.Concat("VitalNameType: ", type, " ", name, " ", hash); + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalType.cs b/ROUNDS/Photon.Pun.Simple/VitalType.cs new file mode 100644 index 0000000..db18be5 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalType.cs @@ -0,0 +1,13 @@ +namespace Photon.Pun.Simple; + +public enum VitalType +{ + None, + Custom, + Health, + Armor, + Shield, + Energy, + Mana, + Rage +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalUI.cs b/ROUNDS/Photon.Pun.Simple/VitalUI.cs new file mode 100644 index 0000000..d590a34 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalUI.cs @@ -0,0 +1,160 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace Photon.Pun.Simple; + +public class VitalUI : VitalUIBase +{ + protected static GameObject vitalBarDefaultPrefab; + + public bool autoOffset = true; + + [Tooltip("Found children elements are nudged (value * vitalIndex). This is to automatically stagger multiple VitalUIs")] + public Vector3 offset = new Vector3(0f, 0.1f, 0f); + + public float widthMultiplier = 1f; + + [Tooltip("Search for UI elements in children of this GameObject.")] + [HideInInspector] + public bool searchChildren = true; + + [HideInInspector] + public Text UIText; + + [HideInInspector] + public Image UIImage; + + [HideInInspector] + public TextMesh textMesh; + + [HideInInspector] + public SpriteRenderer barSprite; + + [HideInInspector] + public SpriteRenderer backSprite; + + [HideInInspector] + public bool billboard = true; + + private const string PLACEHOLDER_CANVAS_NAME = "PLACEHOLDER_VITALS_CANVAS"; + + private static List<SpriteRenderer> resuableFindSpriteRend = new List<SpriteRenderer>(); + + protected override void Reset() + { + base.Reset(); + FindUIElements(); + } + + protected override void Awake() + { + base.Awake(); + FindUIElements(); + base.enabled = billboard; + } + + public override void Recalculate() + { + AutoAlign(); + if ((bool)backSprite) + { + backSprite.size = new Vector2(widthMultiplier, backSprite.size.y); + } + UpdateGraphics(vital); + } + + protected virtual void AutoAlign() + { + if (autoOffset && (bool)base.transform.parent) + { + base.transform.localPosition = offset * vitalIndex; + } + } + + public bool FindUIElements() + { + if (textMesh == null) + { + textMesh = (searchChildren ? GetComponentInChildren<TextMesh>() : GetComponent<TextMesh>()); + } + if (searchChildren) + { + GetComponentsInChildren(resuableFindSpriteRend); + } + else + { + GetComponents(resuableFindSpriteRend); + } + if (resuableFindSpriteRend.Count > 0 && barSprite == null) + { + barSprite = resuableFindSpriteRend[0]; + } + if (resuableFindSpriteRend.Count > 1 && backSprite == null) + { + backSprite = resuableFindSpriteRend[1]; + } + if (UIText == null) + { + UIText = (searchChildren ? GetComponentInChildren<Text>() : GetComponent<Text>()); + } + if (UIImage == null) + { + UIImage = (searchChildren ? GetComponentInChildren<Image>() : GetComponent<Image>()); + } + if (!textMesh && !barSprite && !UIText) + { + return UIImage; + } + return true; + } + + public override void UpdateGraphics(Vital vital) + { + if (vital == null) + { + return; + } + VitalDefinition vitalDef = vital.VitalDef; + double num = ((targetField == TargetField.Value) ? vital.VitalData.Value : ((targetField == TargetField.Max) ? vitalDef.FullValue : vitalDef.MaxValue)); + if (num == double.NegativeInfinity) + { + return; + } + if ((bool)textMesh) + { + textMesh.text = ((int)num).ToString(); + } + if ((bool)barSprite) + { + barSprite.size = new Vector2((float)(num / vitalDef.MaxValue * (double)widthMultiplier), barSprite.size.y); + } + if (UIText != null) + { + UIText.text = ((int)num).ToString(); + } + if (UIImage != null) + { + double maxValue = vitalDef.MaxValue; + if (UIImage.type == Image.Type.Filled && UIImage.sprite != null) + { + UIImage.fillAmount = (float)(num / maxValue * (double)widthMultiplier); + } + else + { + UIImage.rectTransform.localScale = new Vector3((float)(num / maxValue * (double)widthMultiplier), UIImage.rectTransform.localScale.y, UIImage.rectTransform.localScale.z); + } + } + } + + public void LateUpdate() + { + Camera main = Camera.main; + if ((bool)main) + { + base.transform.LookAt(main.transform, new Vector3(0f, 1f, 0f)); + Vector3 eulerAngles = base.transform.eulerAngles; + base.transform.eulerAngles = new Vector3(0f, eulerAngles.y + 180f, 0f); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalUIBase.cs b/ROUNDS/Photon.Pun.Simple/VitalUIBase.cs new file mode 100644 index 0000000..9876b77 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalUIBase.cs @@ -0,0 +1,134 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public abstract class VitalUIBase : VitalsUISrcBase, IOnVitalValueChange, IOnVitalChange, IOnChangeOwnedVitals +{ + public enum TargetField + { + Value, + Max, + MaxOverload + } + + [Tooltip("Which vital type will be monitored.")] + [HideInInspector] + public VitalNameType targetVital = new VitalNameType(VitalType.Health); + + [Tooltip("Which value to track. Typically this is value, but can be other VitalDefinition values like Max/Full.")] + [HideInInspector] + public TargetField targetField; + + [SerializeField] + [HideInInspector] + protected int vitalIndex = -1; + + [NonSerialized] + protected Vital vital; + + public Vitals Vitals + { + get + { + return vitals; + } + set + { + vitals = value; + if (value == null) + { + Vital = null; + } + else + { + Vital = vitals.GetVital(targetVital); + } + } + } + + public Vital Vital + { + get + { + return vital; + } + private set + { + if (vital != null) + { + vital.RemoveIOnVitalChange(this); + } + value?.AddIOnVitalChange(this); + vital = value; + UpdateGraphics(vital); + } + } + + public override IVitalsSystem ApplyVitalsSource(UnityEngine.Object vs) + { + IVitalsSystem vitalsSystem = base.ApplyVitalsSource(vs); + Vitals = vitalsSystem?.Vitals; + vitalIndex = vitalsSystem?.Vitals.GetVitalIndex(targetVital) ?? (-1); + return vitalsSystem; + } + + public abstract void Recalculate(); + + protected virtual void Awake() + { + ApplyVitalsSource(vitalsSource); + if (monitor == MonitorSource.Auto || monitor == MonitorSource.Owned) + { + OwnedIVitals.iOnChangeOwnedVitals.Add(this); + } + } + + protected virtual void Start() + { + if (vital != null) + { + UpdateGraphics(vital); + } + } + + protected virtual void OnDestroy() + { + if (monitor == MonitorSource.Auto || monitor == MonitorSource.Owned) + { + OwnedIVitals.iOnChangeOwnedVitals.Remove(this); + } + if (vital != null) + { + vital.RemoveIOnVitalChange(this); + } + } + + public override void OnChangeOwnedVitals(IVitalsSystem added, IVitalsSystem removed) + { + if (added != null) + { + vitalsSource = added as Component; + Vitals = added.Vitals; + } + else if (removed.Vitals == vitals) + { + IVitalsSystem lastItem = OwnedIVitals.LastItem; + if (lastItem != null) + { + Vitals = lastItem.Vitals; + } + } + } + + public void OnVitalParamChange(Vital vital) + { + } + + public virtual void OnVitalValueChange(Vital vital) + { + UpdateGraphics(vital); + } + + public abstract void UpdateGraphics(Vital vital); +} diff --git a/ROUNDS/Photon.Pun.Simple/Vitals.cs b/ROUNDS/Photon.Pun.Simple/Vitals.cs new file mode 100644 index 0000000..f037f28 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/Vitals.cs @@ -0,0 +1,270 @@ +using System; +using System.Collections.Generic; +using Photon.Compression; +using UnityEngine; + +namespace Photon.Pun.Simple; + +[Serializable] +public class Vitals : IOnVitalValueChange, IOnVitalChange, IOnVitalParamChange +{ + public List<IOnVitalValueChange> OnVitalValueChangeCallbacks = new List<IOnVitalValueChange>(); + + public List<IOnVitalParamChange> OnVitalParamChangeCallbacks = new List<IOnVitalParamChange>(); + + [HideInInspector] + public List<VitalDefinition> vitalDefs = new List<VitalDefinition> + { + new VitalDefinition(100.0, 125u, 125.0, 1.0, 1f, 1.0, 1f, 1.0, "Health"), + new VitalDefinition(100.0, 125u, 50.0, 0.6669999957084656, 1f, 1.0, 1f, 0.0, "Armor"), + new VitalDefinition(200.0, 250u, 100.0, 1.0, 1f, 20.0, 1f, 10.0, "Shield") + }; + + [NonSerialized] + private Vital[] vitalArray; + + private Dictionary<int, Vital> vitalLookup = new Dictionary<int, Vital>(); + + private int vitalCount; + + private bool initialized; + + public List<VitalDefinition> VitalDefs => vitalDefs; + + public Vital[] VitalArray + { + get + { + if (!initialized) + { + Initialize(); + } + return vitalArray; + } + } + + public void Initialize() + { + if (initialized) + { + return; + } + vitalCount = vitalDefs.Count; + vitalArray = new Vital[vitalCount]; + for (int i = 0; i < vitalCount; i++) + { + VitalDefinition vitalDefinition = vitalDefs[i]; + Vital vital = new Vital(vitalDefinition); + vitalArray[i] = vital; + vital.Initialize(TickEngineSettings.netTickInterval); + vital.AddIOnVitalChange(this); + int hash = vitalDefinition.VitalName.hash; + if (vitalDefinition.VitalName.type != 0) + { + if (!vitalLookup.ContainsKey(hash)) + { + vitalLookup.Add(hash, vital); + } + else + { + Debug.LogWarning("VitalNameType hash collision! Vitals cannot have more than one of each Vital Type in its list."); + } + } + } + initialized = true; + } + + public void ResetValues() + { + for (int i = 0; i < vitalCount; i++) + { + vitalArray[i].ResetValues(); + } + } + + public Vital GetVital(VitalNameType vitalNameType) + { + if (!initialized) + { + Initialize(); + } + vitalLookup.TryGetValue(vitalNameType.hash, out var value); + return value; + } + + public int GetVitalIndex(VitalNameType vitalNameType) + { + if (vitalDefs == null) + { + return -1; + } + int hash = vitalNameType.hash; + int i = 0; + for (int count = vitalDefs.Count; i < count; i++) + { + if (vitalDefs[i].VitalName.hash == hash) + { + return i; + } + } + return -1; + } + + public SerializationFlags Serialize(VitalsData vdata, VitalsData lastVData, byte[] buffer, ref int bitposition, bool keyframe) + { + VitalData[] datas = vdata.datas; + VitalData[] datas2 = lastVData.datas; + SerializationFlags serializationFlags = SerializationFlags.None; + int i = 0; + for (int num = vitalCount; i < num; i++) + { + serializationFlags |= vitalDefs[i].Serialize(datas[i], datas2[i], buffer, ref bitposition, keyframe); + } + return serializationFlags; + } + + public SerializationFlags Deserialize(VitalsData vdata, byte[] buffer, ref int bitposition, bool keyframe) + { + VitalData[] datas = vdata.datas; + bool flag = true; + bool flag2 = false; + for (int i = 0; i < vitalCount; i++) + { + datas[i] = vitalDefs[i].Deserialize(buffer, ref bitposition, keyframe); + if (datas[i].Value == double.NegativeInfinity) + { + flag = false; + } + else + { + flag2 = flag2 || true; + } + } + if (!flag) + { + if (!flag2) + { + return SerializationFlags.None; + } + return SerializationFlags.HasContent; + } + return (SerializationFlags)33; + } + + public void Apply(VitalsData vdata) + { + VitalData[] datas = vdata.datas; + for (int i = 0; i < vitalCount; i++) + { + vitalArray[i].Apply(datas[i]); + } + } + + private double ApplyCharges(int vitalIdx, double discharge, bool allowOverload, bool propagate) + { + double num = discharge; + double num2 = 0.0; + int num3 = vitalIdx; + while (num3 >= 0) + { + num2 += vitalArray[num3].ApplyCharges(num, allowOverload, !propagate); + if (propagate) + { + num -= num2; + if (num == 0.0) + { + break; + } + num3--; + continue; + } + return num2; + } + return num2; + } + + public double ApplyCharges(double discharge, bool allowOverload, bool propagate) + { + return ApplyCharges(vitalCount - 1, discharge, allowOverload, propagate); + } + + public double ApplyCharges(VitalNameType vitalNameType, double discharge, bool allowOverload, bool propagate) + { + int num; + if (vitalNameType.type == VitalType.None) + { + num = vitalCount - 1; + } + else + { + num = GetVitalIndex(vitalNameType); + if (num == -1) + { + return 0.0; + } + } + double num2 = ApplyCharges(num, discharge, allowOverload, propagate); + CheckForDisrupt(num2); + return num2; + } + + public void CheckForDisrupt(double consumed) + { + if (consumed != 0.0) + { + if (consumed > 0.0) + { + DisruptDecay(); + } + if (consumed < 0.0) + { + DisruptRegen(); + } + } + } + + public void DisruptRegen() + { + int i = 0; + for (int num = vitalCount; i < num; i++) + { + vitalArray[i].DisruptRegen(); + } + } + + public void DisruptDecay() + { + int i = 0; + for (int num = vitalCount; i < num; i++) + { + vitalArray[i].DisruptDecay(); + } + } + + public void OnVitalValueChange(Vital vital) + { + int i = 0; + for (int count = OnVitalValueChangeCallbacks.Count; i < count; i++) + { + OnVitalValueChangeCallbacks[i].OnVitalValueChange(vital); + } + } + + public void OnVitalParamChange(Vital vital) + { + int i = 0; + for (int count = OnVitalParamChangeCallbacks.Count; i < count; i++) + { + OnVitalParamChangeCallbacks[i].OnVitalParamChange(vital); + } + } + + public void Simulate() + { + int i = 0; + for (int num = vitalCount; i < num; i++) + { + vitalArray[i].Simulate(); + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalsContactReactor.cs b/ROUNDS/Photon.Pun.Simple/VitalsContactReactor.cs new file mode 100644 index 0000000..cbed2e4 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalsContactReactor.cs @@ -0,0 +1,201 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public class VitalsContactReactor : ContactReactorBase, IOnContactEvent, IVitalsContactReactor, IContactReactor, IOnStateChange +{ + [SerializeField] + [HideInInspector] + protected VitalNameType vitalNameType = new VitalNameType(VitalType.Health); + + [HideInInspector] + public double dischargeOnEnter = 20.0; + + [HideInInspector] + public double dischargeOnExit = 20.0; + + [HideInInspector] + public double dischargeOnScan = 20.0; + + [SerializeField] + [HideInInspector] + protected double dischargePerSec = 20.0; + + [Tooltip("Unconsumed values (remainders) should be passed through to the next vital in the stack of vitals.")] + public bool propagate; + + public bool allowOverload; + + [SerializeField] + protected bool isPickup = true; + + public bool useCharges; + + public double _charges = 50.0; + + [Tooltip("The Charges value that will be set on initialization, and whenever this object respawns.")] + [SerializeField] + protected double initialCharges = 50.0; + + public Consumption consumeDespawn; + + protected double valuePerFixed; + + public virtual VitalNameType VitalNameType => new VitalNameType(VitalType.None); + + public double DischargePerSec + { + get + { + return dischargePerSec; + } + internal set + { + valuePerFixed = value * (double)Time.fixedDeltaTime; + dischargePerSec = value; + } + } + + public virtual bool Propagate + { + get + { + return propagate; + } + set + { + propagate = value; + } + } + + public virtual bool AllowOverload + { + get + { + return allowOverload; + } + set + { + allowOverload = value; + } + } + + public override bool IsPickup => isPickup; + + public virtual double Charges => _charges; + + public virtual Consumption ConsumeCharges(double amount) + { + if (amount == 0.0) + { + return Consumption.None; + } + double val = _charges - amount; + double num = (_charges = ((initialCharges >= 0.0) ? Math.Max(val, 0.0) : Math.Min(val, 0.0))); + if (num != initialCharges) + { + if (num != 0.0) + { + return Consumption.Partial; + } + return Consumption.All; + } + return Consumption.None; + } + + protected virtual void Consume(Consumption consumed) + { + if (consumed != 0 && consumeDespawn != 0 && syncState != null) + { + if (consumed == Consumption.All) + { + syncState.Despawn(immediate: false); + } + else if (consumeDespawn == Consumption.Partial) + { + syncState.Despawn(immediate: false); + } + } + } + + public override void OnAwakeInitialize(bool isNetObject) + { + base.OnAwakeInitialize(isNetObject); + valuePerFixed = dischargePerSec * (double)Time.fixedDeltaTime; + } + + protected override Consumption ProcessContactEvent(ContactEvent contactEvent) + { + if (!(contactEvent.contactSystem is IVitalsSystem vitalsSystem)) + { + return Consumption.None; + } + double valueForTriggerType = GetValueForTriggerType(contactEvent.contactType); + double num = vitalsSystem.Vitals.ApplyCharges(vitalNameType, valueForTriggerType, allowOverload, propagate); + Consumption consumption; + if (useCharges) + { + consumption = ConsumeCharges(num); + } + else + { + if (num == 0.0) + { + return Consumption.None; + } + consumption = ((num != valueForTriggerType) ? Consumption.Partial : Consumption.All); + Consume(consumption); + } + if (isPickup && consumption != 0) + { + Mount mount = vitalsSystem.TryPickup(this, contactEvent); + if ((bool)mount) + { + syncState.HardMount(mount); + } + } + return consumption; + } + + public void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true) + { + if (previousState == ObjState.Despawned && (newState & ObjState.Visible) != 0) + { + _charges = initialCharges; + } + } + + public double DischargeValue(ContactType contactType = ContactType.Undefined) + { + double num = contactType switch + { + ContactType.Enter => dischargeOnEnter, + ContactType.Stay => dischargePerSec, + ContactType.Exit => dischargeOnExit, + ContactType.Hitscan => dischargeOnScan, + _ => 0.0, + }; + if (useCharges) + { + if (num >= 0.0) + { + return Math.Min(num, _charges); + } + return Math.Max(num, _charges); + } + return num; + } + + protected double GetValueForTriggerType(ContactType collideType) + { + return collideType switch + { + ContactType.Enter => dischargeOnEnter, + ContactType.Stay => valuePerFixed, + ContactType.Exit => dischargeOnExit, + ContactType.Hitscan => dischargeOnScan, + _ => 0.0, + }; + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalsData.cs b/ROUNDS/Photon.Pun.Simple/VitalsData.cs new file mode 100644 index 0000000..50dba91 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalsData.cs @@ -0,0 +1,24 @@ +namespace Photon.Pun.Simple; + +public class VitalsData +{ + public Vitals vitals; + + public VitalData[] datas; + + public VitalsData(Vitals vitals) + { + this.vitals = vitals; + datas = new VitalData[vitals.VitalArray.Length]; + } + + public void CopyFrom(VitalsData source) + { + VitalData[] array = source.datas; + int i = 0; + for (int num = array.Length; i < num; i++) + { + datas[i] = array[i]; + } + } +} diff --git a/ROUNDS/Photon.Pun.Simple/VitalsUISrcBase.cs b/ROUNDS/Photon.Pun.Simple/VitalsUISrcBase.cs new file mode 100644 index 0000000..6056317 --- /dev/null +++ b/ROUNDS/Photon.Pun.Simple/VitalsUISrcBase.cs @@ -0,0 +1,106 @@ +using System; +using UnityEngine; + +namespace Photon.Pun.Simple; + +public abstract class VitalsUISrcBase : MonoBehaviour, IOnChangeOwnedVitals +{ + public enum MonitorSource + { + Auto, + Owned, + Self, + GameObject + } + + [Tooltip("Where this VitalUI will look for Vitals data.")] + [HideInInspector] + public MonitorSource monitor; + + [Tooltip("Object that this VitalUI will search for an IVitalsSystem vitals data source.")] + [HideInInspector] + [SerializeField] + public UnityEngine.Object vitalsSource; + + [NonSerialized] + public Vitals vitals; + + public abstract void OnChangeOwnedVitals(IVitalsSystem added, IVitalsSystem removed); + + protected virtual void Reset() + { + ApplyVitalsSource(null); + } + + public virtual IVitalsSystem ApplyVitalsSource(UnityEngine.Object srcObj) + { + if (monitor == MonitorSource.Auto) + { + if (srcObj == null) + { + srcObj = (UnityEngine.Object)GetComponentInParent<IVitalsSystem>(); + monitor = MonitorSource.Self; + } + if (srcObj == null) + { + srcObj = (UnityEngine.Object)OwnedIVitals.LastItem; + monitor = MonitorSource.Owned; + } + } + Component component; + GameObject gameObject; + if (monitor == MonitorSource.Owned) + { + component = OwnedIVitals.LastItem as Component; + gameObject = null; + } + else if (monitor == MonitorSource.Self) + { + gameObject = base.gameObject; + component = null; + } + else + { + vitalsSource = srcObj; + gameObject = srcObj as GameObject; + component = srcObj as Component; + } + IVitalsSystem vitalsSystem; + if ((bool)gameObject) + { + vitalsSystem = FindIVitalComponentOnGameObj(gameObject); + if (vitalsSystem != null) + { + vitalsSource = (vitalsSystem as Component).gameObject; + } + } + else if ((bool)component) + { + vitalsSystem = component as IVitalsSystem; + if (monitor == MonitorSource.GameObject) + { + vitalsSource = component.gameObject; + } + } + else + { + vitalsSystem = null; + vitalsSource = null; + } + return vitalsSystem; + } + + private static IVitalsSystem FindIVitalComponentOnGameObj(GameObject go) + { + if ((bool)go) + { + IVitalsSystem vitalsSystem = go.GetComponentInParent<IVitalsSystem>(); + if (vitalsSystem == null) + { + vitalsSystem = go.GetComponentInChildren<IVitalsSystem>(); + } + return vitalsSystem; + } + return null; + } +} diff --git a/ROUNDS/Photon.Pun.UtilityScripts/CopyComponent.cs b/ROUNDS/Photon.Pun.UtilityScripts/CopyComponent.cs new file mode 100644 index 0000000..ab72641 --- /dev/null +++ b/ROUNDS/Photon.Pun.UtilityScripts/CopyComponent.cs @@ -0,0 +1,66 @@ +using System; +using System.Reflection; +using UnityEngine; + +namespace Photon.Pun.UtilityScripts; + +public static class CopyComponent +{ + public static Component ComponentCopy(this Component original, GameObject destination) + { + Type type = original.GetType(); + Component component = destination.AddComponent(type); + FieldInfo[] fields = type.GetFields(); + foreach (FieldInfo fieldInfo in fields) + { + fieldInfo.SetValue(component, fieldInfo.GetValue(original)); + } + return component; + } + + public static T GetCopyOf<T>(this T comp, T other) where T : Component + { + if ((UnityEngine.Object)comp == (UnityEngine.Object)null || (UnityEngine.Object)other == (UnityEngine.Object)null) + { + return comp; + } + Type type = comp.GetType(); + if (type != other.GetType()) + { + return null; + } + BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + PropertyInfo[] properties = type.GetProperties(bindingAttr); + foreach (PropertyInfo propertyInfo in properties) + { + if (!propertyInfo.CanWrite) + { + continue; + } + try + { + if (!Attribute.IsDefined(propertyInfo, typeof(ObsoleteAttribute))) + { + propertyInfo.SetValue(comp, propertyInfo.GetValue(other, null), null); + } + } + catch + { + } + } + FieldInfo[] fields = type.GetFields(bindingAttr); + foreach (FieldInfo fieldInfo in fields) + { + fieldInfo.SetValue(comp, fieldInfo.GetValue(other)); + } + return comp; + } + + public static T AddColliderCopy<T>(this GameObject go, T toAdd) where T : Collider + { + T obj = go.AddComponent(toAdd.GetType()).GetCopyOf(toAdd) as T; + obj.sharedMaterial = toAdd.sharedMaterial; + obj.isTrigger = toAdd.isTrigger; + return obj; + } +} diff --git a/ROUNDS/Photon.Pun/PlayerSyncPackage.cs b/ROUNDS/Photon.Pun/PlayerSyncPackage.cs new file mode 100644 index 0000000..c0a2bf4 --- /dev/null +++ b/ROUNDS/Photon.Pun/PlayerSyncPackage.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +namespace Photon.Pun; + +public class PlayerSyncPackage +{ + public Vector3 pos; + + public Vector3 dir; + + public Vector3 aim; + + public float sinceGrounded; + + public bool holdJump; + + public bool jump; + + public Vector2 vel; + + public float timeDelta; +} diff --git a/ROUNDS/Photon.Pun/ProjectileSyncPackage.cs b/ROUNDS/Photon.Pun/ProjectileSyncPackage.cs new file mode 100644 index 0000000..cb70ea7 --- /dev/null +++ b/ROUNDS/Photon.Pun/ProjectileSyncPackage.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace Photon.Pun; + +public class ProjectileSyncPackage +{ + public Vector3 pos; + + public Vector2 vel; + + public float timeDelta; +} diff --git a/ROUNDS/Photon.Pun/SyncPlayerMovement.cs b/ROUNDS/Photon.Pun/SyncPlayerMovement.cs new file mode 100644 index 0000000..7690d1a --- /dev/null +++ b/ROUNDS/Photon.Pun/SyncPlayerMovement.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun; + +[AddComponentMenu("Photon Networking/Photon Transform View")] +[RequireComponent(typeof(PhotonView))] +public class SyncPlayerMovement : MonoBehaviour, IPunObservable +{ + private PhotonView photonView; + + private CharacterData data; + + private float sincePushed; + + private bool didJump; + + private float lastTime; + + private List<PlayerSyncPackage> syncPackages = new List<PlayerSyncPackage>(); + + public void Awake() + { + photonView = GetComponent<PhotonView>(); + data = GetComponent<CharacterData>(); + if (!photonView.IsMine) + { + data.input.controlledElseWhere = true; + GetComponent<PlayerCollision>().checkForGoThroughWall = false; + return; + } + PlayerJump jump = data.jump; + jump.JumpAction = (Action)Delegate.Combine(jump.JumpAction, new Action(DoJump)); + data.weaponHandler.gun.AddAttackAction(SendShoot); + Block block = data.block; + block.BlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(block.BlockAction, new Action<BlockTrigger.BlockTriggerType>(SendBlock)); + } + + private void OnEnable() + { + syncPackages.Clear(); + } + + public void SetDontSyncFor(float t) + { + sincePushed = t * 0.5f; + } + + private void Update() + { + if (syncPackages.Count <= 0) + { + return; + } + if (syncPackages[0].timeDelta > 0f) + { + syncPackages[0].timeDelta -= Time.deltaTime * 1.5f * (1f + (float)syncPackages.Count * 0.1f); + return; + } + while (syncPackages.Count > 5) + { + syncPackages.RemoveAt(0); + } + sincePushed -= Time.deltaTime; + float t = Mathf.Clamp(1f - sincePushed * 5f, 0f, 1f); + base.transform.position = Vector2.Lerp(base.transform.position, syncPackages[0].pos, t); + data.playerVel.velocity = Vector2.Lerp(data.playerVel.velocity, syncPackages[0].vel, t); + data.input.direction = syncPackages[0].dir; + data.input.aimDirection = syncPackages[0].aim; + data.input.jumpIsPressed = syncPackages[0].holdJump; + data.sinceGrounded = syncPackages[0].sinceGrounded; + if (syncPackages[0].jump) + { + Jump(); + } + syncPackages.RemoveAt(0); + } + + private void SendBlock(BlockTrigger.BlockTriggerType blockTrigger) + { + SendBlock(blockTrigger, toAll: false); + } + + public void SendBlock(BlockTrigger.BlockTriggerType blockTrigger, bool toAll = false) + { + if (blockTrigger == BlockTrigger.BlockTriggerType.Default) + { + if (toAll) + { + data.view.RPC("RPCAO_DoBlock", RpcTarget.All); + } + else + { + data.view.RPC("RPCAO_DoBlock", RpcTarget.Others); + } + } + } + + [PunRPC] + public void RPCAO_DoBlock() + { + data.block.RPCA_DoBlock(firstBlock: true); + } + + public void SendBlock(BlockTrigger.BlockTriggerType blockTrigger, bool firstBlock, bool dontSetCD) + { + data.view.RPC("RPCA_DoBlock", RpcTarget.All, (int)blockTrigger, firstBlock, dontSetCD); + } + + [PunRPC] + public void RPCA_DoBlock(int blocktTrigger, bool firstBlock, bool dontSetCD) + { + data.block.RPCA_DoBlock(firstBlock, dontSetCD, (BlockTrigger.BlockTriggerType)blocktTrigger); + } + + public void SendShoot() + { + photonView.RPC("Shoot", RpcTarget.Others); + } + + [PunRPC] + public void Shoot() + { + data.weaponHandler.gun.Attack(0f, forceAttack: true); + } + + public void DoJump() + { + didJump = true; + } + + public void SendJump() + { + photonView.RPC("Jump", RpcTarget.Others); + } + + [PunRPC] + public void Jump() + { + data.jump.Jump(forceJump: true); + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (stream.IsWriting) + { + stream.SendNext(base.transform.position); + stream.SendNext(data.input.direction); + stream.SendNext(data.input.aimDirection); + stream.SendNext(data.input.jumpIsPressed); + stream.SendNext(data.playerVel.velocity); + stream.SendNext(didJump); + stream.SendNext(data.sinceGrounded); + didJump = false; + if (lastTime == 0f) + { + lastTime = Time.time; + } + stream.SendNext(Time.time - lastTime); + lastTime = Time.time; + } + else + { + PlayerSyncPackage playerSyncPackage = new PlayerSyncPackage(); + playerSyncPackage.pos = (Vector3)stream.ReceiveNext(); + playerSyncPackage.dir = (Vector3)stream.ReceiveNext(); + playerSyncPackage.aim = (Vector3)stream.ReceiveNext(); + playerSyncPackage.holdJump = (bool)stream.ReceiveNext(); + playerSyncPackage.vel = (Vector2)stream.ReceiveNext(); + playerSyncPackage.jump = (bool)stream.ReceiveNext(); + playerSyncPackage.sinceGrounded = (float)stream.ReceiveNext(); + playerSyncPackage.timeDelta = (float)stream.ReceiveNext(); + playerSyncPackage.timeDelta = Mathf.Clamp(playerSyncPackage.timeDelta, 0f, 0.1f); + syncPackages.Add(playerSyncPackage); + } + } +} diff --git a/ROUNDS/Photon.Pun/SyncProjectile.cs b/ROUNDS/Photon.Pun/SyncProjectile.cs new file mode 100644 index 0000000..7c79d87 --- /dev/null +++ b/ROUNDS/Photon.Pun/SyncProjectile.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun; + +[AddComponentMenu("Photon Networking/Photon Transform View")] +[RequireComponent(typeof(PhotonView))] +public class SyncProjectile : MonoBehaviour, IPunObservable +{ + public bool active; + + private PhotonView photonView; + + private MoveTransform move; + + private float lastTime; + + private List<ProjectileSyncPackage> syncPackages = new List<ProjectileSyncPackage>(); + + public void Awake() + { + photonView = GetComponent<PhotonView>(); + move = GetComponent<MoveTransform>(); + _ = photonView.IsMine; + } + + private void Update() + { + if (!active || syncPackages.Count <= 0) + { + return; + } + if (syncPackages[0].timeDelta > 0f) + { + syncPackages[0].timeDelta -= Time.deltaTime * 1.5f * (1f + (float)syncPackages.Count * 0.5f); + return; + } + if (syncPackages.Count > 2) + { + syncPackages.RemoveAt(0); + } + base.transform.position = syncPackages[0].pos; + move.velocity = syncPackages[0].vel; + syncPackages.RemoveAt(0); + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (!active) + { + return; + } + if (stream.IsWriting) + { + stream.SendNext(base.transform.position); + stream.SendNext(move.velocity); + if (lastTime == 0f) + { + lastTime = Time.time; + } + stream.SendNext(Time.time - lastTime); + lastTime = Time.time; + } + else + { + ProjectileSyncPackage projectileSyncPackage = new ProjectileSyncPackage(); + projectileSyncPackage.pos = (Vector3)stream.ReceiveNext(); + projectileSyncPackage.vel = (Vector3)stream.ReceiveNext(); + projectileSyncPackage.timeDelta = (float)stream.ReceiveNext(); + syncPackages.Add(projectileSyncPackage); + } + } +} diff --git a/ROUNDS/Photon.Realtime.Demo/ConnectAndJoinRandomLb.cs b/ROUNDS/Photon.Realtime.Demo/ConnectAndJoinRandomLb.cs new file mode 100644 index 0000000..f880325 --- /dev/null +++ b/ROUNDS/Photon.Realtime.Demo/ConnectAndJoinRandomLb.cs @@ -0,0 +1,133 @@ +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine; +using UnityEngine.UI; + +namespace Photon.Realtime.Demo; + +public class ConnectAndJoinRandomLb : MonoBehaviour, IConnectionCallbacks, IMatchmakingCallbacks, ILobbyCallbacks +{ + [SerializeField] + private AppSettings appSettings = new AppSettings(); + + private LoadBalancingClient lbc; + + private ConnectionHandler ch; + + public Text StateUiText; + + public void Start() + { + lbc = new LoadBalancingClient(); + lbc.AddCallbackTarget(this); + lbc.SerializationProtocol = SerializationProtocol.GpBinaryV16; + if (!lbc.ConnectUsingSettings(appSettings)) + { + Debug.LogError("Error while connecting"); + } + ch = base.gameObject.GetComponent<ConnectionHandler>(); + if (ch != null) + { + ch.Client = lbc; + ch.StartFallbackSendAckThread(); + } + } + + public void Update() + { + LoadBalancingClient loadBalancingClient = lbc; + if (loadBalancingClient != null) + { + loadBalancingClient.Service(); + Text stateUiText = StateUiText; + string text = loadBalancingClient.State.ToString(); + if (stateUiText != null && !stateUiText.text.Equals(text)) + { + stateUiText.text = "State: " + text; + } + } + } + + public void OnConnected() + { + } + + public void OnConnectedToMaster() + { + Debug.Log("OnConnectedToMaster"); + lbc.OpJoinRandomRoom(); + } + + public void OnDisconnected(DisconnectCause cause) + { + Debug.Log(string.Concat("OnDisconnected(", cause, ")")); + } + + public void OnCustomAuthenticationResponse(Dictionary<string, object> data) + { + } + + public void OnCustomAuthenticationFailed(string debugMessage) + { + } + + public void OnRegionListReceived(RegionHandler regionHandler) + { + Debug.Log("OnRegionListReceived"); + regionHandler.PingMinimumOfRegions(OnRegionPingCompleted, null); + } + + public void OnRoomListUpdate(List<RoomInfo> roomList) + { + } + + public void OnLobbyStatisticsUpdate(List<TypedLobbyInfo> lobbyStatistics) + { + } + + public void OnJoinedLobby() + { + } + + public void OnLeftLobby() + { + } + + public void OnFriendListUpdate(List<FriendInfo> friendList) + { + } + + public void OnCreatedRoom() + { + } + + public void OnCreateRoomFailed(short returnCode, string message) + { + } + + public void OnJoinedRoom() + { + Debug.Log("OnJoinedRoom"); + } + + public void OnJoinRoomFailed(short returnCode, string message) + { + } + + public void OnJoinRandomFailed(short returnCode, string message) + { + Debug.Log("OnJoinRandomFailed"); + lbc.OpCreateRoom(new EnterRoomParams()); + } + + public void OnLeftRoom() + { + } + + private void OnRegionPingCompleted(RegionHandler regionHandler) + { + Debug.Log("OnRegionPingCompleted " + regionHandler.BestRegion); + Debug.Log("RegionPingSummary: " + regionHandler.SummaryToCache); + lbc.ConnectToRegionMaster(regionHandler.BestRegion.Code); + } +} diff --git a/ROUNDS/Photon.Utilities/BitUtilities.cs b/ROUNDS/Photon.Utilities/BitUtilities.cs new file mode 100644 index 0000000..ca64c68 --- /dev/null +++ b/ROUNDS/Photon.Utilities/BitUtilities.cs @@ -0,0 +1,28 @@ +namespace Photon.Utilities; + +public static class BitUtilities +{ + public static int GetBitsForMaxValue(this int maxvalue) + { + for (int i = 0; i < 32; i++) + { + if (maxvalue >> i == 0) + { + return i; + } + } + return 32; + } + + public static int GetBitsForMaxValue(this uint maxvalue) + { + for (int i = 0; i < 32; i++) + { + if (maxvalue >> i == 0) + { + return i; + } + } + return 32; + } +} diff --git a/ROUNDS/Photon.Utilities/BitsPerRangeAttribute.cs b/ROUNDS/Photon.Utilities/BitsPerRangeAttribute.cs new file mode 100644 index 0000000..ab999cd --- /dev/null +++ b/ROUNDS/Photon.Utilities/BitsPerRangeAttribute.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +namespace Photon.Utilities; + +public class BitsPerRangeAttribute : PropertyAttribute +{ + public readonly int max; + + public readonly int min; + + public readonly string label; + + public readonly bool showLabel; + + public readonly string tooltip; + + public bool show; + + public BitsPerRangeAttribute(int min, int max, bool show, bool zeroBase = false, string label = "Max:", bool showLabel = true, string tooltip = "") + { + this.show = show; + this.min = min; + this.max = max; + this.label = label; + this.showLabel = showLabel; + this.tooltip = tooltip; + } +} diff --git a/ROUNDS/Photon.Utilities/BoundsTools.cs b/ROUNDS/Photon.Utilities/BoundsTools.cs new file mode 100644 index 0000000..3c141a7 --- /dev/null +++ b/ROUNDS/Photon.Utilities/BoundsTools.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Utilities; + +public static class BoundsTools +{ + public enum BoundsType + { + Both, + MeshRenderer, + Collider, + Manual + } + + private static readonly List<MeshFilter> meshFilters = new List<MeshFilter>(); + + private static readonly List<Renderer> meshRenderers = new List<Renderer>(); + + private static readonly List<Collider> colliders = new List<Collider>(); + + private static readonly List<Collider> validColliders = new List<Collider>(); + + private static readonly List<SpriteRenderer> spriteRenderers = new List<SpriteRenderer>(); + + private static readonly List<Collider2D> colliders2D = new List<Collider2D>(); + + private static readonly List<Collider2D> validColliders2D = new List<Collider2D>(); + + public static Bounds CollectMyBounds(this GameObject go, BoundsType factorIn, out int numOfBoundsFound, bool includeChildren = true, bool includeInactive = false) + { + if (!go.activeInHierarchy && includeInactive) + { + numOfBoundsFound = 0; + return default(Bounds); + } + bool num = factorIn == BoundsType.Both; + bool flag = num || factorIn == BoundsType.MeshRenderer; + bool num2 = num || factorIn == BoundsType.Collider; + meshFilters.Clear(); + meshRenderers.Clear(); + colliders.Clear(); + spriteRenderers.Clear(); + validColliders.Clear(); + validColliders2D.Clear(); + int num3 = 0; + if (flag && go.activeInHierarchy) + { + if (includeChildren) + { + go.GetComponentsInChildren(includeInactive, meshRenderers); + go.GetComponentsInChildren(includeInactive, meshFilters); + go.GetComponentsInChildren(includeInactive, spriteRenderers); + } + else + { + go.GetComponents(meshRenderers); + go.GetComponents(meshFilters); + go.GetComponents(spriteRenderers); + } + } + if (num2 && go.activeInHierarchy) + { + if (includeChildren) + { + go.GetComponentsInChildren(includeInactive, colliders); + go.GetComponentsInChildren(includeInactive, colliders2D); + } + else + { + go.GetComponents(colliders); + go.GetComponents(colliders2D); + } + } + for (int i = 0; i < meshFilters.Count; i++) + { + Renderer component = meshFilters[i].GetComponent<Renderer>(); + if ((bool)component && (component.enabled || includeInactive) && !meshRenderers.Contains(component)) + { + meshRenderers.Add(component); + } + } + for (int j = 0; j < colliders.Count; j++) + { + if ((colliders[j].enabled || includeInactive) && (bool)colliders[j]) + { + validColliders.Add(colliders[j]); + } + } + for (int k = 0; k < colliders2D.Count; k++) + { + if ((((bool)colliders2D[k] && colliders2D[k].enabled) || includeInactive) && (bool)colliders2D[k]) + { + validColliders2D.Add(colliders2D[k]); + } + } + numOfBoundsFound = meshRenderers.Count + spriteRenderers.Count + validColliders.Count + validColliders2D.Count; + if (numOfBoundsFound == 0) + { + return default(Bounds); + } + Bounds bounds; + if (meshRenderers.Count > 0) + { + bounds = meshRenderers[0].bounds; + } + else if (validColliders.Count > 0) + { + bounds = validColliders[0].bounds; + } + else if (validColliders2D.Count > 0 && (bool)validColliders2D[0]) + { + bounds = validColliders2D[0].bounds; + } + else + { + if (spriteRenderers.Count <= 0) + { + return default(Bounds); + } + bounds = spriteRenderers[0].bounds; + } + for (int l = 0; l < spriteRenderers.Count; l++) + { + num3++; + bounds.Encapsulate(spriteRenderers[l].bounds); + } + for (int m = 0; m < meshRenderers.Count; m++) + { + num3++; + bounds.Encapsulate(meshRenderers[m].bounds); + } + for (int n = 0; n < validColliders.Count; n++) + { + num3++; + bounds.Encapsulate(validColliders[n].bounds); + } + for (int num4 = 0; num4 < validColliders2D.Count; num4++) + { + num3++; + if ((bool)validColliders2D[num4]) + { + bounds.Encapsulate(validColliders2D[num4].bounds); + } + } + return bounds; + } + + public static Bounds CollectMyBounds(GameObject go, BoundsType factorIn, bool includeChildren = true) + { + int numOfBoundsFound; + return go.CollectMyBounds(factorIn, out numOfBoundsFound, includeChildren); + } +} diff --git a/ROUNDS/Photon.Utilities/CatmulRom.cs b/ROUNDS/Photon.Utilities/CatmulRom.cs new file mode 100644 index 0000000..e8eb3d1 --- /dev/null +++ b/ROUNDS/Photon.Utilities/CatmulRom.cs @@ -0,0 +1,117 @@ +using UnityEngine; + +namespace Photon.Utilities; + +public class CatmulRom +{ + public static float CatmullRomLerp(float pre, float start, float end, float post, float t) + { + while (t > 1f) + { + pre = start; + start = end; + end = post; + post = end + (end - start); + t -= 1f; + } + float num = 2f * start; + float num2 = end - pre; + float num3 = 2f * pre - 5f * start + 4f * end - post; + float num4 = 0f - pre + 3f * (start - end) + post; + float num5 = t * t; + return (num + num2 * t + num3 * num5 + num4 * num5 * t) * 0.5f; + } + + public static float CatmullRomLerp(float pre, float start, float end, float t) + { + float num = end + (end - start); + while (t > 1f) + { + pre = start; + start = end; + end = num; + num = end + (end - start); + t -= 1f; + } + float num2 = 2f * start; + float num3 = end - pre; + float num4 = 2f * pre - 5f * start + 4f * end - num; + float num5 = 0f - pre + 3f * (start - end) + num; + float num6 = t * t; + return (num2 + num3 * t + num4 * num6 + num5 * num6 * t) * 0.5f; + } + + public static Vector3 CatmullRomLerp(Vector2 pre, Vector2 start, Vector2 end, Vector2 post, float t) + { + while (t > 1f) + { + pre = start; + start = end; + end = post; + post = end + (end - start); + t -= 1f; + } + Vector2 vector = 2f * start; + Vector2 vector2 = end - pre; + Vector2 vector3 = 2f * pre - 5f * start + 4f * end - post; + Vector2 vector4 = -pre + 3f * (start - end) + post; + float num = t * t; + return (vector + vector2 * t + vector3 * num + vector4 * num * t) * 0.5f; + } + + public static Vector3 CatmullRomLerp(Vector2 pre, Vector2 start, Vector2 end, float t) + { + Vector2 vector = end + (end - start); + while (t > 1f) + { + pre = start; + start = end; + end = vector; + vector = end + (end - start); + t -= 1f; + } + Vector2 vector2 = 2f * start; + Vector2 vector3 = end - pre; + Vector2 vector4 = 2f * pre - 5f * start + 4f * end - vector; + Vector2 vector5 = -pre + 3f * (start - end) + vector; + float num = t * t; + return (vector2 + vector3 * t + vector4 * num + vector5 * num * t) * 0.5f; + } + + public static Vector3 CatmullRomLerp(Vector3 pre, Vector3 start, Vector3 end, Vector3 post, float t) + { + while (t > 1f) + { + pre = start; + start = end; + end = post; + post = end + (end - start); + t -= 1f; + } + Vector3 vector = 2f * start; + Vector3 vector2 = end - pre; + Vector3 vector3 = 2f * pre - 5f * start + 4f * end - post; + Vector3 vector4 = -pre + 3f * (start - end) + post; + float num = t * t; + return (vector + vector2 * t + vector3 * num + vector4 * num * t) * 0.5f; + } + + public static Vector3 CatmullRomLerp(Vector3 pre, Vector3 start, Vector3 end, float t) + { + Vector3 vector = end + (end - start); + while (t > 1f) + { + pre = start; + start = end; + end = vector; + vector = end + (end - start); + t -= 1f; + } + Vector3 vector2 = 2f * start; + Vector3 vector3 = end - pre; + Vector3 vector4 = 2f * pre - 5f * start + 4f * end - vector; + Vector3 vector5 = -pre + 3f * (start - end) + vector; + float num = t * t; + return (vector2 + vector3 * t + vector4 * num + vector5 * num * t) * 0.5f; + } +} diff --git a/ROUNDS/Photon.Utilities/DisableFieldAttribute.cs b/ROUNDS/Photon.Utilities/DisableFieldAttribute.cs new file mode 100644 index 0000000..a953872 --- /dev/null +++ b/ROUNDS/Photon.Utilities/DisableFieldAttribute.cs @@ -0,0 +1,9 @@ +using System; +using UnityEngine; + +namespace Photon.Utilities; + +[AttributeUsage(AttributeTargets.Field)] +public class DisableFieldAttribute : PropertyAttribute +{ +} diff --git a/ROUNDS/Photon.Utilities/EnumMaskAttribute.cs b/ROUNDS/Photon.Utilities/EnumMaskAttribute.cs new file mode 100644 index 0000000..98be0e9 --- /dev/null +++ b/ROUNDS/Photon.Utilities/EnumMaskAttribute.cs @@ -0,0 +1,18 @@ +using System; +using UnityEngine; + +namespace Photon.Utilities; + +[AttributeUsage(AttributeTargets.Field)] +public class EnumMaskAttribute : PropertyAttribute +{ + public bool definesZero; + + public Type castTo; + + public EnumMaskAttribute(bool definesZero = false, Type castTo = null) + { + this.castTo = castTo; + this.definesZero = definesZero; + } +} diff --git a/ROUNDS/Photon.Utilities/FastBitMask128.cs b/ROUNDS/Photon.Utilities/FastBitMask128.cs new file mode 100644 index 0000000..7aed7e5 --- /dev/null +++ b/ROUNDS/Photon.Utilities/FastBitMask128.cs @@ -0,0 +1,443 @@ +namespace Photon.Utilities; + +public struct FastBitMask128 +{ + private ulong seg1; + + private ulong seg2; + + private int bitcount; + + private int seg1bitcount; + + private int seg2bitcount; + + private ulong alltrue1; + + private ulong alltrue2; + + public ulong Seg1 => seg1; + + public ulong Seg2 => seg2; + + public ulong AllTrue1 => alltrue1; + + public ulong AllTrue2 => alltrue2; + + public int BitCount + { + get + { + return bitcount; + } + set + { + bitcount = value; + seg1bitcount = ((bitcount < 64) ? bitcount : 64); + seg2bitcount = ((bitcount > 64) ? (bitcount - 64) : 0); + alltrue1 = (ulong)((bitcount < 64) ? ((1L << bitcount) - 1) : (-1)); + alltrue2 = (ulong)((bitcount == 128) ? (-1) : ((bitcount > 64) ? ((1L << bitcount - 64) - 1) : 0)); + seg1 &= alltrue1; + seg2 &= alltrue2; + } + } + + public bool this[int bit] + { + get + { + if (bit < 64) + { + return (seg1 & (ulong)(1L << bit)) != 0; + } + return (seg2 & (ulong)(1L << bit - 64)) != 0; + } + set + { + if (value) + { + if (bit < 64) + { + seg1 |= (ulong)(1L << bit); + } + else + { + seg2 |= (ulong)(1L << bit - 64); + } + } + else if (bit < 64) + { + seg1 &= (ulong)(~(1L << bit)); + } + else + { + seg2 &= (ulong)(~(1L << bit - 64)); + } + } + } + + public bool AllAreFalse + { + get + { + if (bitcount != 0 && seg1 == 0L) + { + return seg2 == 0; + } + return false; + } + } + + public bool AllAreTrue + { + get + { + if (bitcount != 0) + { + if (seg1 == alltrue1) + { + return seg2 == alltrue2; + } + return false; + } + return true; + } + } + + public FastBitMask128(int bitcount) + { + seg1 = 0uL; + seg2 = 0uL; + this.bitcount = bitcount; + seg1bitcount = ((bitcount < 64) ? bitcount : 64); + seg2bitcount = ((bitcount > 64) ? (bitcount - 64) : 0); + alltrue1 = (ulong)((bitcount < 64) ? ((1L << bitcount) - 1) : (-1)); + alltrue2 = (ulong)((bitcount == 128) ? (-1) : ((bitcount > 64) ? ((1L << bitcount - 64) - 1) : 0)); + } + + public FastBitMask128(FastBitMask128 copyFrom) + { + seg1 = copyFrom.seg1; + seg2 = copyFrom.seg2; + bitcount = copyFrom.bitcount; + seg1bitcount = copyFrom.seg1bitcount; + seg2bitcount = copyFrom.seg2bitcount; + alltrue1 = copyFrom.alltrue1; + alltrue2 = copyFrom.alltrue2; + } + + public bool Get(int bit) + { + if (bit < 64) + { + return (seg1 & (ulong)(1L << bit)) != 0; + } + return (seg2 & (ulong)(1L << bit - 64)) != 0; + } + + public void Set(int bit, bool value) + { + if (value) + { + if (bit < 64) + { + seg1 |= (ulong)(1L << bit); + } + else + { + seg2 |= (ulong)(1L << bit - 64); + } + } + else if (bit < 64) + { + seg1 &= (ulong)(~(1L << bit)); + } + else + { + seg2 &= (ulong)(~(1L << bit - 64)); + } + } + + public void SetTrue(int bit) + { + if (bit < 64) + { + seg1 |= (ulong)(1L << bit); + } + else + { + seg2 |= (ulong)(1L << bit - 64); + } + } + + public void SetFalse(int bit) + { + if (bit < 64) + { + seg1 &= (ulong)(~(1L << bit)); + } + else + { + seg2 &= (ulong)(~(1L << bit - 64)); + } + } + + public void SetAllTrue() + { + seg1 = alltrue1; + seg2 = alltrue2; + } + + public void SetAllFalse() + { + seg1 = 0uL; + seg2 = 0uL; + } + + public void OR(FastBitMask128 other) + { + seg1 |= other.seg1; + seg2 |= other.seg2; + } + + public void OR(FastBitMask128 other, int otherOffset) + { + if (otherOffset == 0) + { + seg1 |= other.seg1; + seg2 |= other.seg2; + } + else if (otherOffset == 64) + { + seg2 |= other.seg1; + } + else if (otherOffset < 128) + { + if (otherOffset > 64) + { + seg2 |= seg1 << otherOffset - 64; + return; + } + seg1 |= other.seg1 << otherOffset; + seg2 |= other.seg1 >> 64 - otherOffset; + seg2 |= other.seg2 << otherOffset; + } + } + + public void AND(FastBitMask128 other) + { + seg1 &= other.seg1; + seg2 &= other.seg2; + } + + public void XOR(FastBitMask128 other) + { + seg1 ^= other.seg1; + seg2 ^= other.seg2; + } + + public static FastBitMask128 operator |(FastBitMask128 a, FastBitMask128 b) + { + FastBitMask128 result = new FastBitMask128(a); + result.seg1 = a.seg1 | b.seg1; + result.seg2 = a.seg2 | b.seg2; + return result; + } + + public static FastBitMask128 operator &(FastBitMask128 a, FastBitMask128 b) + { + FastBitMask128 result = new FastBitMask128(a); + result.seg1 = a.seg1 & b.seg1; + result.seg2 = a.seg2 & b.seg2; + return result; + } + + public static FastBitMask128 operator ^(FastBitMask128 a, FastBitMask128 b) + { + FastBitMask128 result = new FastBitMask128(a); + result.seg1 = (a.seg1 ^ b.seg1) & a.alltrue1; + result.seg2 = (a.seg2 ^ b.seg2) & a.alltrue2; + return result; + } + + public static FastBitMask128 operator !(FastBitMask128 a) + { + FastBitMask128 result = new FastBitMask128(a); + result.seg1 = ~a.seg1 & a.alltrue1; + result.seg2 = ~a.seg2 & a.alltrue2; + return result; + } + + public FastBitMask128 NOT() + { + FastBitMask128 result = new FastBitMask128(this); + result.seg1 = ~seg1 & alltrue1; + result.seg2 = ~seg2 & alltrue2; + return result; + } + + public int CountTrue() + { + int num; + if (seg1 == 0L) + { + num = 0; + } + else if (seg1 == alltrue1) + { + num = seg1bitcount; + } + else + { + num = 0; + for (ulong num2 = seg1; num2 != 0L; num2 >>= 1) + { + if ((num2 & 1) == 1) + { + num++; + } + } + } + if (seg2 == 0L) + { + return num; + } + if (seg2 == alltrue2) + { + return num + seg2bitcount; + } + for (ulong num3 = seg2; num3 != 0L; num3 >>= 1) + { + if ((num3 & 1) == 1) + { + num++; + } + } + return num; + } + + public int CountFalse() + { + int num; + if (seg1 == 0L) + { + num = 0; + } + else if (seg1 == alltrue1) + { + num = seg1bitcount; + } + else + { + num = 0; + for (ulong num2 = seg1; num2 != 0L; num2 >>= 1) + { + if ((num2 & 1) == 1) + { + num++; + } + } + } + if (seg2 == 0L) + { + return bitcount - num; + } + if (seg2 == alltrue2) + { + return bitcount - (num + seg2bitcount); + } + for (ulong num3 = seg2; num3 != 0L; num3 >>= 1) + { + if ((num3 & 1) == 1) + { + num++; + } + } + return bitcount - num; + } + + public void ClearBitsBefore(int start, int count) + { + ulong num = (ulong)((count == 64) ? (-1) : ((1L << count) - 1)); + int num2 = start - count; + if (bitcount > 64) + { + ulong num3; + ulong num4; + if (num2 >= 0) + { + num3 = num << num2; + num4 = num >> seg2bitcount - num2; + } + else + { + ulong num5 = num << bitcount + num2; + num3 = (num >> -num2) | num5; + num4 = num << seg2bitcount + num2; + } + seg1 &= ~num3; + seg2 &= ~num4 & alltrue2; + } + else + { + ulong num3; + ulong num4; + if (num2 >= 0) + { + num3 = num << num2; + num4 = num >> seg1bitcount - num2; + } + else + { + num3 = num >> -num2; + num4 = num << seg1bitcount + num2; + } + seg1 &= ~num3 & ~num4 & alltrue1; + } + } + + public int CountValidRange(int start, int lookahead) + { + int num = bitcount; + for (int num2 = lookahead; num2 >= 0; num2--) + { + int num3 = start + num2; + if (num3 >= num) + { + num3 -= num; + } + if (num3 < 64) + { + if ((seg1 & (ulong)(1L << num3)) != 0L) + { + return num2 + 1; + } + } + else if ((seg2 & (ulong)(1L << num3 - 64)) != 0L) + { + return num2 + 1; + } + } + return 0; + } + + public void Copy(FastBitMask128 other) + { + bitcount = other.bitcount; + seg1bitcount = other.seg1bitcount; + seg2bitcount = other.seg2bitcount; + seg1 = other.seg1; + seg2 = other.seg2; + alltrue1 = other.alltrue1; + alltrue2 = other.alltrue2; + } + + public bool Compare(FastBitMask128 other) + { + if (bitcount == other.bitcount && seg1 == other.seg1) + { + return seg2 == other.seg2; + } + return false; + } +} diff --git a/ROUNDS/Photon.Utilities/FastBitMask64.cs b/ROUNDS/Photon.Utilities/FastBitMask64.cs new file mode 100644 index 0000000..3489c9c --- /dev/null +++ b/ROUNDS/Photon.Utilities/FastBitMask64.cs @@ -0,0 +1,232 @@ +namespace Photon.Utilities; + +public struct FastBitMask64 +{ + public ulong bitmask; + + private int bitcount; + + private ulong alltrue; + + public int BitCount + { + get + { + return bitcount; + } + set + { + bitcount = value; + alltrue = (ulong)((bitcount < 64) ? ((1L << bitcount) - 1) : (-1)); + bitmask &= alltrue; + } + } + + public bool this[int bit] + { + get + { + return (bitmask & (ulong)(1L << bit)) != 0; + } + set + { + if (value) + { + bitmask |= (ulong)(1L << bit); + } + else + { + bitmask &= (ulong)(~(1L << bit)); + } + } + } + + public bool AllAreFalse + { + get + { + if (bitcount != 0) + { + return bitmask == 0; + } + return false; + } + } + + public bool AllAreTrue + { + get + { + if (bitcount != 0) + { + return bitmask == alltrue; + } + return true; + } + } + + public FastBitMask64(int bitcount) + { + bitmask = 0uL; + this.bitcount = bitcount; + alltrue = (ulong)((bitcount < 64) ? ((1L << bitcount) - 1) : (-1)); + } + + private FastBitMask64(FastBitMask64 copyFrom) + { + bitmask = copyFrom.bitmask; + bitcount = copyFrom.bitcount; + alltrue = copyFrom.alltrue; + } + + public bool Get(int bit) + { + return (bitmask & (ulong)(1L << bit)) != 0; + } + + public void Set(int bit, bool value) + { + if (value) + { + bitmask |= (ulong)(1L << bit); + } + else + { + bitmask &= (ulong)(~(1L << bit)); + } + } + + public void SetTrue(int bit) + { + bitmask |= (ulong)(1L << bit); + } + + public void SetFalse(int bit) + { + bitmask &= (ulong)(~(1L << bit)); + } + + public void SetAllTrue() + { + bitmask = alltrue; + } + + public void SetAllFalse() + { + bitmask = 0uL; + } + + public void OR(FastBitMask64 other) + { + bitmask |= other.bitmask; + } + + public void AND(FastBitMask64 other) + { + bitmask &= other.bitmask; + } + + public void XOR(FastBitMask64 other) + { + bitmask ^= other.bitmask; + } + + public int CountTrue() + { + int num; + if (bitmask == 0L) + { + num = 0; + } + else if (bitmask == alltrue) + { + num = bitcount; + } + else + { + num = 0; + for (ulong num2 = bitmask; num2 != 0L; num2 >>= 1) + { + if ((num2 & 1) == 1) + { + num++; + } + } + } + return num; + } + + public int CountFalse() + { + if (bitmask == 0L) + { + return bitcount; + } + if (bitmask == alltrue) + { + return 0; + } + int num = 0; + int i = 0; + for (int num2 = bitcount; i < num2; i++) + { + if ((bitmask & (ulong)(1L << i)) == 0L) + { + num++; + } + } + return num; + } + + public void ClearBitsBefore(int start, int count) + { + ulong num = (ulong)((count == 64) ? (-1) : ((1L << count) - 1)); + int num2 = start - count; + ulong num3; + ulong num4; + if (num2 >= 0) + { + num3 = num << num2; + num4 = num >> bitcount - num2; + } + else + { + num3 = num >> -num2; + num4 = num << bitcount + num2; + } + bitmask &= ~num3 & ~num4 & alltrue; + } + + public int CountValidRange(int start, int lookahead) + { + for (int num = lookahead; num >= 0; num--) + { + int num2 = start + num; + if (num2 >= bitcount) + { + num2 -= bitcount; + } + if ((bitmask & (ulong)(1L << num2)) != 0L) + { + return num + 1; + } + } + return 0; + } + + public void Copy(FastBitMask64 other) + { + bitcount = other.bitcount; + bitmask = other.bitmask; + alltrue = other.alltrue; + } + + public bool Compare(FastBitMask64 other) + { + if (bitcount == other.bitcount) + { + return bitmask == other.bitmask; + } + return false; + } +} diff --git a/ROUNDS/Photon.Utilities/FastBitMask64Ext.cs b/ROUNDS/Photon.Utilities/FastBitMask64Ext.cs new file mode 100644 index 0000000..5427908 --- /dev/null +++ b/ROUNDS/Photon.Utilities/FastBitMask64Ext.cs @@ -0,0 +1,5 @@ +namespace Photon.Utilities; + +public static class FastBitMask64Ext +{ +} diff --git a/ROUNDS/Photon.Utilities/FastBitMaskExt.cs b/ROUNDS/Photon.Utilities/FastBitMaskExt.cs new file mode 100644 index 0000000..53cae08 --- /dev/null +++ b/ROUNDS/Photon.Utilities/FastBitMaskExt.cs @@ -0,0 +1,5 @@ +namespace Photon.Utilities; + +public static class FastBitMaskExt +{ +} diff --git a/ROUNDS/Photon.Utilities/MinMaxRangeAttribute.cs b/ROUNDS/Photon.Utilities/MinMaxRangeAttribute.cs new file mode 100644 index 0000000..8e4b130 --- /dev/null +++ b/ROUNDS/Photon.Utilities/MinMaxRangeAttribute.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace Photon.Utilities; + +public class MinMaxRangeAttribute : PropertyAttribute +{ + public readonly float max; + + public readonly float min; + + public MinMaxRangeAttribute(float min, float max) + { + this.min = min; + this.max = max; + } +} diff --git a/ROUNDS/Photon.Utilities/ReadOnlyAttribute.cs b/ROUNDS/Photon.Utilities/ReadOnlyAttribute.cs new file mode 100644 index 0000000..71e83a0 --- /dev/null +++ b/ROUNDS/Photon.Utilities/ReadOnlyAttribute.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +namespace Photon.Utilities; + +public class ReadOnlyAttribute : PropertyAttribute +{ +} diff --git a/ROUNDS/Photon.Utilities/SettingsScriptableObject.cs b/ROUNDS/Photon.Utilities/SettingsScriptableObject.cs new file mode 100644 index 0000000..f94e33f --- /dev/null +++ b/ROUNDS/Photon.Utilities/SettingsScriptableObject.cs @@ -0,0 +1,54 @@ +using System; +using UnityEngine; + +namespace Photon.Utilities; + +public abstract class SettingsScriptableObject<T> : SettingsScriptableObjectBase where T : SettingsScriptableObjectBase +{ + public static string AssetName = typeof(T).Name; + + public static Action OnSingletonReady; + + public static T single; + + public static T Single + { + get + { + if (!(UnityEngine.Object)single) + { + single = Resources.Load<T>(AssetName); + if ((bool)(UnityEngine.Object)single) + { + single.Initialize(); + } + } + return single; + } + } + + protected virtual void Awake() + { + T val = single; + Initialize(); + if ((UnityEngine.Object)val == (UnityEngine.Object)null && (UnityEngine.Object)single != (UnityEngine.Object)null && OnSingletonReady != null) + { + OnSingletonReady(); + } + } + + protected virtual void OnEnable() + { + T val = single; + Initialize(); + if ((UnityEngine.Object)val == (UnityEngine.Object)null && (UnityEngine.Object)single != (UnityEngine.Object)null && OnSingletonReady != null) + { + OnSingletonReady(); + } + } + + public override void Initialize() + { + single = this as T; + } +} diff --git a/ROUNDS/Photon.Utilities/SettingsScriptableObjectBase.cs b/ROUNDS/Photon.Utilities/SettingsScriptableObjectBase.cs new file mode 100644 index 0000000..8f0a763 --- /dev/null +++ b/ROUNDS/Photon.Utilities/SettingsScriptableObjectBase.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +namespace Photon.Utilities; + +public abstract class SettingsScriptableObjectBase : ScriptableObject +{ + public abstract void Initialize(); +} diff --git a/ROUNDS/Photon.Utilities/SingleUnityLayer.cs b/ROUNDS/Photon.Utilities/SingleUnityLayer.cs new file mode 100644 index 0000000..162aadf --- /dev/null +++ b/ROUNDS/Photon.Utilities/SingleUnityLayer.cs @@ -0,0 +1,29 @@ +using System; +using UnityEngine; + +namespace Photon.Utilities; + +[Serializable] +public class SingleUnityLayer +{ + [SerializeField] + [HideInInspector] + private int m_LayerIndex; + + public int LayerIndex => m_LayerIndex; + + public int Mask => 1 << m_LayerIndex; + + public void Set(int _layerIndex) + { + if (_layerIndex > 0 && _layerIndex < 32) + { + m_LayerIndex = _layerIndex; + } + } + + public static implicit operator int(SingleUnityLayer m) + { + return m.LayerIndex; + } +} diff --git a/ROUNDS/Photon.Utilities/SmartVar.cs b/ROUNDS/Photon.Utilities/SmartVar.cs new file mode 100644 index 0000000..e8bf082 --- /dev/null +++ b/ROUNDS/Photon.Utilities/SmartVar.cs @@ -0,0 +1,271 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace Photon.Utilities; + +[Serializable] +[StructLayout(LayoutKind.Explicit)] +public struct SmartVar +{ + [FieldOffset(0)] + public SmartVarTypeCode TypeCode; + + [FieldOffset(4)] + public int Int; + + [FieldOffset(4)] + public uint UInt; + + [FieldOffset(4)] + public bool Bool; + + [FieldOffset(4)] + public float Float; + + [FieldOffset(4)] + public byte Byte8; + + [FieldOffset(4)] + public short Short; + + [FieldOffset(4)] + public ushort UShort; + + [FieldOffset(4)] + public char Char; + + public static readonly SmartVar None = new SmartVar + { + TypeCode = SmartVarTypeCode.None + }; + + public static implicit operator SmartVar(int v) + { + SmartVar result = default(SmartVar); + result.Int = v; + result.TypeCode = SmartVarTypeCode.Int; + return result; + } + + public static implicit operator SmartVar(uint v) + { + SmartVar result = default(SmartVar); + result.UInt = v; + result.TypeCode = SmartVarTypeCode.Uint; + return result; + } + + public static implicit operator SmartVar(float v) + { + SmartVar result = default(SmartVar); + result.Float = v; + result.TypeCode = SmartVarTypeCode.Float; + return result; + } + + public static implicit operator SmartVar(bool v) + { + SmartVar result = default(SmartVar); + result.Bool = v; + result.TypeCode = SmartVarTypeCode.Bool; + return result; + } + + public static implicit operator SmartVar(byte v) + { + SmartVar result = default(SmartVar); + result.Byte8 = v; + result.TypeCode = SmartVarTypeCode.Byte; + return result; + } + + public static implicit operator SmartVar(short v) + { + SmartVar result = default(SmartVar); + result.Short = v; + result.TypeCode = SmartVarTypeCode.Short; + return result; + } + + public static implicit operator SmartVar(ushort v) + { + SmartVar result = default(SmartVar); + result.UShort = v; + result.TypeCode = SmartVarTypeCode.UShort; + return result; + } + + public static implicit operator SmartVar(char v) + { + SmartVar result = default(SmartVar); + result.Char = v; + result.TypeCode = SmartVarTypeCode.Char; + return result; + } + + public static implicit operator int(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Int) + { + return v.Int; + } + UnityEngine.Debug.Log(v.TypeCode); + throw new InvalidCastException(); + } + + public static implicit operator uint(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Uint) + { + return v.UInt; + } + throw new InvalidCastException(); + } + + public static implicit operator float(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Float) + { + return v.Float; + } + UnityEngine.Debug.LogError(string.Concat("cant cast ", v.TypeCode, " to single float")); + throw new InvalidCastException(); + } + + public static implicit operator bool(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Bool) + { + return v.Bool; + } + throw new InvalidCastException(); + } + + public static implicit operator byte(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Byte) + { + return v.Byte8; + } + throw new InvalidCastException(); + } + + public static implicit operator short(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Short) + { + return v.Short; + } + throw new InvalidCastException(); + } + + public static implicit operator ushort(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.UShort) + { + return v.UShort; + } + throw new InvalidCastException(); + } + + public static implicit operator char(SmartVar v) + { + if (v.TypeCode == SmartVarTypeCode.Char) + { + return v.Char; + } + throw new InvalidCastException(); + } + + public SmartVar Copy() + { + SmartVar result = default(SmartVar); + result.TypeCode = TypeCode; + result.Int = Int; + return result; + } + + public string ToStringVerbose() + { + string text = TypeCode.ToString() + " "; + if (TypeCode == SmartVarTypeCode.None) + { + return text; + } + if (TypeCode == SmartVarTypeCode.Bool) + { + return text + Bool; + } + if (TypeCode == SmartVarTypeCode.Int) + { + return text + Int; + } + if (TypeCode == SmartVarTypeCode.Uint) + { + return text + UInt; + } + if (TypeCode == SmartVarTypeCode.Float) + { + return text + Float; + } + if (TypeCode == SmartVarTypeCode.Short) + { + return text + Short; + } + if (TypeCode == SmartVarTypeCode.UShort) + { + return text + UShort; + } + if (TypeCode == SmartVarTypeCode.Byte) + { + return text + Byte8; + } + if (TypeCode == SmartVarTypeCode.Char) + { + return text + Char; + } + return text; + } + + public override string ToString() + { + if (TypeCode == SmartVarTypeCode.None) + { + return ""; + } + if (TypeCode == SmartVarTypeCode.Bool) + { + return Bool.ToString(); + } + if (TypeCode == SmartVarTypeCode.Int) + { + return Int.ToString(); + } + if (TypeCode == SmartVarTypeCode.Uint) + { + return UInt.ToString(); + } + if (TypeCode == SmartVarTypeCode.Float) + { + return Float.ToString(); + } + if (TypeCode == SmartVarTypeCode.Short) + { + return Short.ToString(); + } + if (TypeCode == SmartVarTypeCode.UShort) + { + return UShort.ToString(); + } + if (TypeCode == SmartVarTypeCode.Byte) + { + return Byte8.ToString(); + } + if (TypeCode == SmartVarTypeCode.Char) + { + return Char.ToString(); + } + return ""; + } +} diff --git a/ROUNDS/Photon.Utilities/SmartVarTypeCode.cs b/ROUNDS/Photon.Utilities/SmartVarTypeCode.cs new file mode 100644 index 0000000..1c109c9 --- /dev/null +++ b/ROUNDS/Photon.Utilities/SmartVarTypeCode.cs @@ -0,0 +1,14 @@ +namespace Photon.Utilities; + +public enum SmartVarTypeCode +{ + None, + Int, + Uint, + Bool, + Float, + Byte, + Short, + UShort, + Char +} diff --git a/ROUNDS/Photon.Utilities/VersaMaskAttribute.cs b/ROUNDS/Photon.Utilities/VersaMaskAttribute.cs new file mode 100644 index 0000000..bd8288a --- /dev/null +++ b/ROUNDS/Photon.Utilities/VersaMaskAttribute.cs @@ -0,0 +1,17 @@ +using System; +using UnityEngine; + +namespace Photon.Utilities; + +public class VersaMaskAttribute : PropertyAttribute +{ + public bool definesZero; + + public Type castTo; + + public VersaMaskAttribute(bool definesZero = false, Type castTo = null) + { + this.definesZero = definesZero; + this.castTo = castTo; + } +} diff --git a/ROUNDS/PhotonMapObject.cs b/ROUNDS/PhotonMapObject.cs new file mode 100644 index 0000000..8bfe674 --- /dev/null +++ b/ROUNDS/PhotonMapObject.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class PhotonMapObject : MonoBehaviour +{ + private Map map; + + private bool photonSpawned; + + private float counter; + + private bool waitingToBeRemoved; + + private void Awake() + { + if (base.transform.parent != null) + { + UnityEngine.Object.DestroyImmediate(GetComponent<PhotonView>()); + } + } + + private void Start() + { + Rigidbody2D component = GetComponent<Rigidbody2D>(); + component.isKinematic = true; + component.simulated = false; + if (base.transform.parent == null) + { + photonSpawned = true; + base.transform.SetParent(MapManager.instance.currentMap.Map.transform, worldPositionStays: true); + map = GetComponentInParent<Map>(); + map.missingObjects--; + Map obj = map; + obj.mapIsReadyAction = (Action)Delegate.Combine(obj.mapIsReadyAction, new Action(Go)); + if (map.hasRope && !GetComponent<PhotonView>().IsMine) + { + component.gravityScale = 0f; + } + } + else + { + map = GetComponentInParent<Map>(); + Map obj2 = map; + obj2.mapIsReadyEarlyAction = (Action)Delegate.Combine(obj2.mapIsReadyEarlyAction, new Action(GoEarly)); + } + } + + private void GoEarly() + { + if (waitingToBeRemoved) + { + UnityEngine.Object.DestroyImmediate(base.gameObject); + } + } + + private void Go() + { + StartCoroutine(IGo()); + } + + private IEnumerator IGo() + { + Rigidbody2D rig = GetComponent<Rigidbody2D>(); + yield return new WaitForSeconds(0f); + yield return new WaitForSeconds(0f); + yield return new WaitForSeconds(0f); + rig.isKinematic = false; + rig.simulated = true; + if ((bool)rig) + { + for (float i = 0f; i < 1f; i += Time.deltaTime * 1f) + { + rig.velocity -= rig.velocity * i * 0.05f; + yield return null; + } + } + } + + private void Update() + { + if (waitingToBeRemoved || photonSpawned) + { + return; + } + counter += Mathf.Clamp(Time.deltaTime, 0f, 0.1f); + if ((PhotonNetwork.OfflineMode && counter > 1f && map.hasEntered) || ((bool)map && map.hasEntered && map.LoadedForAll())) + { + if (PhotonNetwork.IsMasterClient) + { + PhotonNetwork.Instantiate("4 Map Objects/" + base.gameObject.name.Split(char.Parse(" "))[0], base.transform.position, base.transform.rotation, 0); + } + map.missingObjects++; + waitingToBeRemoved = true; + } + } +} diff --git a/ROUNDS/PhysicsFunctions.cs b/ROUNDS/PhysicsFunctions.cs new file mode 100644 index 0000000..61cad4c --- /dev/null +++ b/ROUNDS/PhysicsFunctions.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class PhysicsFunctions : MonoBehaviour +{ + private static LayerMask mask = LayerMask.GetMask("Default", "IgnorePlayer", "IgnoreMap"); + + public static Vector2 ObstructionPoint(Vector2 from, Vector2 to) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(from, to - from, Vector2.Distance(from, to), mask); + if ((bool)raycastHit2D.transform) + { + return raycastHit2D.point; + } + return to; + } +} diff --git a/ROUNDS/PickerType.cs b/ROUNDS/PickerType.cs new file mode 100644 index 0000000..b4f79a2 --- /dev/null +++ b/ROUNDS/PickerType.cs @@ -0,0 +1,5 @@ +public enum PickerType +{ + Team, + Player +} diff --git a/ROUNDS/Platform.cs b/ROUNDS/Platform.cs new file mode 100644 index 0000000..9d25a0b --- /dev/null +++ b/ROUNDS/Platform.cs @@ -0,0 +1,203 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +public class Platform +{ + private List<BoxCollider2D> m_boxColliders = new List<BoxCollider2D>(); + + private List<Vector2> m_platformPoints = new List<Vector2>(); + + public List<Vector2> m_edges = new List<Vector2>(); + + private static float EPSILON = Mathf.Epsilon * 10f; + + private int m_lastCalculatedClosestPoint = -1; + + public List<BoxCollider2D> BoxColliders => m_boxColliders; + + public List<Vector2> PlatformPoints + { + get + { + return m_platformPoints; + } + set + { + m_platformPoints = value; + } + } + + public List<Vector2> Edges => m_edges; + + public Color Color { get; set; } + + public Platform() + { + Color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)); + } + + public bool ContainsCollider(BoxCollider2D collider) + { + foreach (BoxCollider2D boxCollider in m_boxColliders) + { + if (collider == boxCollider) + { + return true; + } + } + return false; + } + + public void AddCollider(BoxCollider2D collider) + { + m_boxColliders.Add(collider); + } + + public void AddPlatformPoint(Vector2 point) + { + m_platformPoints.Add(point); + } + + public float GetClosestDistance(Vector2 position) + { + float num = float.MaxValue; + for (int i = 0; i < m_edges.Count; i++) + { + float num2 = Vector2.Distance(position, m_edges[i]); + if (num2 < num) + { + m_lastCalculatedClosestPoint = i; + num = num2; + } + } + return num; + } + + public bool IsPositionOutsidePlatform(Vector2 position) + { + Vector2 vector = m_edges[m_lastCalculatedClosestPoint]; + if (position.x > vector.x && m_lastCalculatedClosestPoint == m_edges.Count - 1) + { + return true; + } + if (position.x < vector.x && m_lastCalculatedClosestPoint == 0) + { + return true; + } + return false; + } + + public Vector2 GetPointOnPath(Vector2 position) + { + Vector2 vector = m_edges[m_lastCalculatedClosestPoint]; + if (position.x > vector.x && m_lastCalculatedClosestPoint == m_edges.Count - 1) + { + return vector; + } + if (position.x < vector.x && m_lastCalculatedClosestPoint == 0) + { + return vector; + } + int index = -1; + int num = 0; + if (position.x > vector.x) + { + index = m_lastCalculatedClosestPoint + 1; + num = 1; + } + else if (position.x <= vector.x) + { + index = m_lastCalculatedClosestPoint - 1; + num = -1; + } + if (num == 1) + { + return GetClosestPointOnLineSegment(vector, m_edges[index], position); + } + return GetClosestPointOnLineSegment(m_edges[index], vector, position); + } + + private Vector2 Project(Vector2 line1, Vector2 line2, Vector2 toProject) + { + float num = (line2.y - line1.y) / (line2.x - line1.x); + float num2 = line1.y - num * line1.x; + float x = (num * toProject.y + toProject.x - num * num2) / (num * num + 1f); + float y = (num * num * toProject.y + num * toProject.x + num2) / (num * num + 1f); + return new Vector2(x, y); + } + + public static Vector2 GetClosestPointOnLineSegment(Vector2 A, Vector2 B, Vector2 P) + { + Vector2 lhs = P - A; + Vector2 vector = B - A; + float sqrMagnitude = vector.sqrMagnitude; + float num = Vector2.Dot(lhs, vector) / sqrMagnitude; + if (num < 0f) + { + return A; + } + if (num > 1f) + { + return B; + } + return A + vector * num; + } + + public void PostProcessPlatformPoints() + { + int mask = LayerMask.GetMask("Default"); + List<Vector2> list = new List<Vector2>(m_platformPoints.OrderBy((Vector2 v) => v.x).ToArray()); + new HashSet<int>(); + for (int num = list.Count - 1; num > 0; num--) + { + if (Physics2D.OverlapCircle(list[num] + new Vector2(0f, 0.25f), 0.2f, mask) != null) + { + list.RemoveAt(num); + } + } + m_platformPoints = list; + DetectEdges(); + } + + public void DetectEdges() + { + if (m_platformPoints.Count == 0) + { + return; + } + List<Vector2> list = new List<Vector2>(); + for (int i = 0; i < m_platformPoints.Count - 2; i++) + { + Vector2 item = m_platformPoints[i]; + Vector2 item2 = m_platformPoints[i + 1]; + if (i == 0) + { + list.Add(item); + } + else if (i == m_platformPoints.Count - 3) + { + list.Add(item2); + } + else if (item2.y - item.y > Mathf.Epsilon) + { + list.Add(item); + list.Add(item2); + } + } + m_edges = list; + } + + public void DrawGizmos() + { + Gizmos.color = Color; + for (int i = 0; i < m_edges.Count; i++) + { + Gizmos.DrawSphere(m_edges[i], 0.2f); + } + for (int j = 0; j < m_edges.Count - 1; j++) + { + Gizmos.DrawLine(m_edges[j], m_edges[j + 1]); + } + } +} diff --git a/ROUNDS/PlayLineAnimation.cs b/ROUNDS/PlayLineAnimation.cs new file mode 100644 index 0000000..01cea4d --- /dev/null +++ b/ROUNDS/PlayLineAnimation.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class PlayLineAnimation : MonoBehaviour +{ + private LineEffect lineEffect; + + public AnimationCurve offsetCurve; + + public float offsetSpeed = 1f; + + public AnimationCurve widthCurve; + + public float widthSpeed = 1f; + + private void Start() + { + lineEffect = GetComponent<LineEffect>(); + } + + public void PlayOffset() + { + lineEffect.PlayAnim(LineEffect.AnimType.Offset, offsetCurve, offsetSpeed); + } + + public void PlayWidth() + { + lineEffect.PlayAnim(LineEffect.AnimType.Width, widthCurve, widthSpeed); + } +} diff --git a/ROUNDS/Player.cs b/ROUNDS/Player.cs new file mode 100644 index 0000000..d912f63 --- /dev/null +++ b/ROUNDS/Player.cs @@ -0,0 +1,153 @@ +using System; +using ExitGames.Client.Photon; +using Photon.Pun; +using UnityEngine; + +public class Player : MonoBehaviour +{ + public int playerID; + + public int teamID; + + [HideInInspector] + public CharacterData data; + + public PlayerSkinBank colors; + + private void Awake() + { + data = GetComponent<CharacterData>(); + } + + private void Start() + { + if (!data.view.IsMine) + { + ReadPlayerID(); + ReadTeamID(); + PlayerAssigner.instance.OtherPlayerWasCreated(); + } + else + { + int num = 0; + if (!PhotonNetwork.OfflineMode) + { + try + { + num = 0; + PlayerFace playerFace = CharacterCreatorHandler.instance.selectedPlayerFaces[num]; + data.view.RPC("RPCA_SetFace", RpcTarget.All, playerFace.eyeID, playerFace.eyeOffset, playerFace.mouthID, playerFace.mouthOffset, playerFace.detailID, playerFace.detailOffset, playerFace.detail2ID, playerFace.detail2Offset); + } + catch + { + } + } + else if (GM_ArmsRace.instance != null) + { + GM_ArmsRace instance = GM_ArmsRace.instance; + instance.StartGameAction = (Action)Delegate.Combine(instance.StartGameAction, new Action(GetFaceOffline)); + } + } + PlayerManager.instance.PlayerJoined(this); + } + + public void GetFaceOffline() + { + PlayerFace playerFace = CharacterCreatorHandler.instance.selectedPlayerFaces[playerID]; + data.view.RPC("RPCA_SetFace", RpcTarget.All, playerFace.eyeID, playerFace.eyeOffset, playerFace.mouthID, playerFace.mouthOffset, playerFace.detailID, playerFace.detailOffset, playerFace.detail2ID, playerFace.detail2Offset); + } + + [PunRPC] + public void RPCA_SetFace(int eyeID, Vector2 eyeOffset, int mouthID, Vector2 mouthOffset, int detailID, Vector2 detailOffset, int detail2ID, Vector2 detail2Offset) + { + PlayerFace face = PlayerFace.CreateFace(eyeID, eyeOffset, mouthID, mouthOffset, detailID, detailOffset, detail2ID, detail2Offset); + GetComponentInChildren<CharacterCreatorItemEquipper>().EquipFace(face); + } + + internal void Call_AllGameFeel(Vector2 vector2) + { + data.view.RPC("RPCA_AllGameFeel", RpcTarget.All, vector2); + } + + [PunRPC] + internal void RPCA_AllGameFeel(Vector2 vector2) + { + GamefeelManager.instance.AddGameFeel(vector2); + } + + public void AssignPlayerID(int ID) + { + playerID = ID; + SetColors(); + if (!PhotonNetwork.OfflineMode) + { + Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; + if (customProperties.ContainsKey("PlayerID")) + { + customProperties["PlayerID"] = playerID; + } + else + { + customProperties.Add("PlayerID", playerID); + } + PhotonNetwork.LocalPlayer.SetCustomProperties(customProperties); + } + } + + internal float GetRadius() + { + return 5f; + } + + private void ReadPlayerID() + { + if (!PhotonNetwork.OfflineMode) + { + playerID = (int)data.view.Owner.CustomProperties["PlayerID"]; + SetColors(); + } + } + + public void AssignTeamID(int ID) + { + teamID = ID; + if (!PhotonNetwork.OfflineMode) + { + Hashtable customProperties = PhotonNetwork.LocalPlayer.CustomProperties; + if (customProperties.ContainsKey("TeamID")) + { + customProperties["TeamID"] = playerID; + } + else + { + customProperties.Add("TeamID", teamID); + } + PhotonNetwork.LocalPlayer.SetCustomProperties(customProperties); + } + } + + private void ReadTeamID() + { + if (!PhotonNetwork.OfflineMode) + { + teamID = (int)data.view.Owner.CustomProperties["TeamID"]; + } + } + + public void SetColors() + { + SetTeamColor.TeamColorThis(base.gameObject, PlayerSkinBank.GetPlayerSkinColors(playerID)); + } + + public PlayerSkin GetTeamColors() + { + return PlayerSkinBank.GetPlayerSkinColors(playerID); + } + + internal void FullReset() + { + data.weaponHandler.NewGun(); + data.stats.ResetStats(); + data.block.ResetStats(); + } +} diff --git a/ROUNDS/PlayerAI.cs b/ROUNDS/PlayerAI.cs new file mode 100644 index 0000000..f7a3d38 --- /dev/null +++ b/ROUNDS/PlayerAI.cs @@ -0,0 +1,119 @@ +using UnityEngine; + +public class PlayerAI : MonoBehaviour +{ + private float range = 6f; + + private CharacterData data; + + private GeneralInput input; + + private Vector3 moveDir = Vector3.zero; + + private Vector3 aimDir = Vector3.zero; + + private Vector3 targetPos; + + private Player target; + + private bool canSeeTarget; + + private float untilNextDataUpdate; + + private float getRandomTargetPosCounter; + + private bool isShooting; + + private float distanceToTarget = 5f; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + input = data.input; + } + + private void Update() + { + target = PlayerManager.instance.GetOtherPlayer(data.player); + untilNextDataUpdate -= TimeHandler.deltaTime; + if (!target) + { + return; + } + canSeeTarget = PlayerManager.instance.CanSeePlayer(base.transform.position, target).canSee; + input.ResetInput(); + if (!canSeeTarget) + { + getRandomTargetPosCounter -= TimeHandler.deltaTime; + if (getRandomTargetPosCounter < 0f) + { + getRandomTargetPosCounter = Random.Range(0.5f, 2f); + GetRandomPos(); + } + } + if (untilNextDataUpdate <= 0f) + { + if (Random.value < 0.25f / Mathf.Clamp(distanceToTarget * 0.1f, 0.1f, 10f) && canSeeTarget) + { + input.shieldWasPressed = true; + } + if (Random.value < 0.4f && canSeeTarget) + { + isShooting = true; + } + else + { + isShooting = false; + } + if (Random.value < 0.2f || data.isWallGrab) + { + input.jumpWasPressed = true; + } + untilNextDataUpdate = Random.Range(0f, 0.25f); + UpdateData(); + } + input.shootIsPressed = isShooting; + input.shootWasPressed = isShooting; + input.aimDirection = aimDir; + input.direction = moveDir; + } + + private void GetRandomPos() + { + Vector3 vector = Vector3.zero; + int num = 200; + while (vector == Vector3.zero && num > 0) + { + num--; + Vector3 vector2 = base.transform.position + Vector3.up * 5f + (Vector3)Random.insideUnitCircle * 15f; + if (data.ThereIsGroundBelow(vector2, 8f)) + { + vector = vector2; + } + } + targetPos = vector; + } + + private void UpdateData() + { + if (canSeeTarget) + { + targetPos = target.transform.position; + } + distanceToTarget = Vector3.Distance(base.transform.position, target.transform.position); + aimDir = (targetPos - base.transform.position).normalized; + moveDir = aimDir; + if (moveDir.x > 0f) + { + moveDir.x = 1f; + } + if (moveDir.x < 0f) + { + moveDir.x = -1f; + } + if (canSeeTarget && distanceToTarget < range && data.ThereIsGroundBelow(base.transform.position, 10f)) + { + moveDir = Vector3.zero; + } + } +} diff --git a/ROUNDS/PlayerAIDavid.cs b/ROUNDS/PlayerAIDavid.cs new file mode 100644 index 0000000..bb0b654 --- /dev/null +++ b/ROUNDS/PlayerAIDavid.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using Landfall.AI; +using UnityEngine; + +public class PlayerAIDavid : MonoBehaviour +{ + public static int[] topology = new int[4] { 2, 10, 16, 5 }; + + [SerializeField] + private bool m_useWeights; + + [SerializeField] + private WeightDataAsset m_weightData; + + private PlayerAPI m_api; + + private NeuralNet m_neuralNet; + + private double[] m_cachedInput; + + private float m_startTime; + + private Vector2 m_movement = Vector2.zero; + + private float m_aiTimer; + + private void Awake() + { + m_api = GetComponentInParent<PlayerAPI>(); + m_cachedInput = new double[2]; + m_neuralNet = new NeuralNet(topology); + if (m_weightData != null && m_useWeights) + { + m_neuralNet.SetWeights(m_weightData.m_weightDatas[m_weightData.m_weightDatas.Count - 1].m_weights); + } + m_startTime = Time.time + 0.8f; + } + + public void SetWeights(double[] weights) + { + m_neuralNet.SetWeights(new List<double>(weights)); + } + + public void SetWeights(List<double> weights) + { + m_neuralNet.SetWeights(weights); + } + + private void Update() + { + if (Time.time < m_startTime) + { + return; + } + if (m_aiTimer >= 0.1f) + { + m_aiTimer -= 0.1f; + Vector3 vector = m_api.OtherPlayerPosition() - m_api.PlayerPosition(); + m_cachedInput[0] = vector.x; + m_cachedInput[1] = vector.y; + m_neuralNet.FeedForward(m_cachedInput, 1.0); + double[] results = m_neuralNet.GetResults(); + m_api.SetAimDirection(new Vector2((float)results[3], (float)results[4])); + if (results[0] > 0.5) + { + m_api.Jump(); + } + if (results[1] > 0.5) + { + m_api.Attack(); + } + Vector2 zero = Vector2.zero; + if (results[2] > 0.5) + { + zero.x = 1f; + } + else if (results[2] < -0.5) + { + zero.x = -1f; + } + m_movement = zero; + } + m_api.Move(m_movement); + m_aiTimer += TimeHandler.deltaTime; + } +} diff --git a/ROUNDS/PlayerAIMinion.cs b/ROUNDS/PlayerAIMinion.cs new file mode 100644 index 0000000..8aea87b --- /dev/null +++ b/ROUNDS/PlayerAIMinion.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +public class PlayerAIMinion : MonoBehaviour +{ + public AnimationCurve m_AimCompensastionCurve; + + public float range = 5f; + + private PlayerAPI api; + + private Vector2 moveDirection; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + moveDirection = api.data.master.data.aimDirection; + if (moveDirection.x > 0.5f) + { + moveDirection.x = 1f; + } + else if (moveDirection.x < -0.5f) + { + moveDirection.x = -1f; + } + else + { + moveDirection.x = 0f; + } + moveDirection.y = 0f; + base.transform.root.gameObject.AddComponent<RemoveAfterSeconds>().seconds = 4f; + } + + private void Update() + { + Player otherPlayer = PlayerManager.instance.GetOtherPlayer(api.data.master); + api.Move(moveDirection); + if (api.data.isWallGrab) + { + api.Jump(); + } + if (!api.data.isGrounded) + { + api.Jump(); + } + if ((bool)otherPlayer) + { + api.SetAimDirection(GetAimDirForHitting(otherPlayer.transform.position)); + if (PlayerManager.instance.CanSeePlayer(base.transform.position, otherPlayer).canSee && Vector2.Distance(base.transform.position, otherPlayer.transform.position) < range) + { + api.Attack(); + } + } + } + + private Vector2 GetAimDirForHitting(Vector3 point) + { + Vector3 vector = point - base.transform.position; + api.SetAimDirection(vector); + api.GetMyBullet(); + float time = Mathf.Abs(point.x - base.transform.position.x); + return point + Vector3.up * m_AimCompensastionCurve.Evaluate(time) - base.transform.position; + } +} diff --git a/ROUNDS/PlayerAIPetter.cs b/ROUNDS/PlayerAIPetter.cs new file mode 100644 index 0000000..0c235f5 --- /dev/null +++ b/ROUNDS/PlayerAIPetter.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +public class PlayerAIPetter : MonoBehaviour +{ + private PlayerAPI api; + + public LayerMask m_layer; + + public AnimationCurve aimCurve; + + public float m_shootRandom = 0.9f; + + public float m_predDist = 1f; + + public float m_timeSinceGround = 0.1f; + + private BoxCollider2D m_collider; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + m_collider = api.GetComponentInChildren<BoxCollider2D>(); + } + + private void Update() + { + if ((double)Random.Range(0f, 1f) > 0.9) + { + api.Move(api.TowardsOtherPlayer() * -1f); + } + else + { + api.Move(api.TowardsOtherPlayer()); + } + PredictionHit(); + api.Attack(); + if ((double)Random.Range(0f, 1f) > 0.9) + { + api.Jump(); + } + AutoBlock(); + } + + private void AutoBlock() + { + foreach (BulletWrapper allBullet in api.GetAllBullets()) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(allBullet.projectileMovement.transform.position, ((Vector2)allBullet.projectileMovement.velocity).normalized, allBullet.velocity.magnitude * 5f * TimeHandler.deltaTime, m_layer); + if ((bool)raycastHit2D.transform && (!allBullet.projectileHit.ownPlayer || allBullet.projectileHit.ownPlayer != api.player) && raycastHit2D.transform.root == base.transform.root) + { + Debug.Log("BLICOK"); + api.Block(); + } + } + } + + private void PredictionHit() + { + if ((bool)api.GetOtherPlayer()) + { + float magnitude = (api.OtherPlayerPosition() - base.transform.position).magnitude; + Vector2 vector = api.GetOtherPlayer().data.playerVel.velocity * m_predDist * 0.1f * magnitude * 0.05f; + api.SetAimDirection(api.TowardsOtherPlayer() + Vector2.up * aimCurve.Evaluate(magnitude) + vector); + } + } +} diff --git a/ROUNDS/PlayerAIPhilip.cs b/ROUNDS/PlayerAIPhilip.cs new file mode 100644 index 0000000..25e6c79 --- /dev/null +++ b/ROUNDS/PlayerAIPhilip.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAIPhilip : MonoBehaviour +{ + private enum BattleMorale : byte + { + Blood, + Coward, + Defend + } + + private enum BattleBehaviour : byte + { + Attack, + HighGround, + MoveSegments + } + + private PlayerAPI m_PlayerAPI; + + private Player m_Enemy; + + private BattleMorale m_CurrentMorale; + + private BattleBehaviour m_CurrentBehaviour; + + private Vector2 m_Direction; + + private Vector2 m_TargetPos; + + private Vector2[] m_Boundaries; + + private Vector2[] m_Segments; + + private int m_CurrentSegment; + + private float m_Tick; + + private int m_BehaviourChangeTick; + + private int m_BehaviourTimeMin = 3; + + private int m_BehaviourTimeMax = 8; + + private float m_AttackDistance = 15f; + + private void Awake() + { + InitReferences(); + MakeBoundaries(); + NextBehaviour(); + } + + private void InitReferences() + { + m_PlayerAPI = GetComponentInParent<PlayerAPI>(); + } + + private void MakeBoundaries() + { + int num = 20; + int num2 = 35; + Vector2 vector = new Vector2(num2, num); + Vector2 vector2 = new Vector2(-num2, num); + Vector2 vector3 = new Vector2(num2, -num); + Vector2 vector4 = new Vector2(-num2, -num); + m_Boundaries = new Vector2[4] { vector, vector2, vector3, vector4 }; + m_Segments = new Vector2[4] + { + vector / 2f, + vector2 / 2f, + vector3 / 2f, + vector4 / 2f + }; + } + + private bool CheckForValidEnemy() + { + m_Enemy = m_PlayerAPI.GetOtherPlayer(); + return m_Enemy != null; + } + + private void Start() + { + CheckForValidEnemy(); + } + + private void Update() + { + if (CheckForValidEnemy()) + { + CheckMorale(); + CheckDirection(); + CheckGround(); + Move(); + Jump(); + DoAim(); + ShouldAttack(); + ShouldBlock(); + TickBehaviour(); + } + } + + private void SeedBehaviourChange() + { + m_BehaviourChangeTick = UnityEngine.Random.Range(m_BehaviourTimeMin, m_BehaviourTimeMax); + } + + private void TickBehaviour() + { + m_Tick += TimeHandler.deltaTime; + if (m_Tick >= (float)m_BehaviourChangeTick) + { + NextBehaviour(); + } + } + + private void NextBehaviour() + { + ResetTick(); + int length = Enum.GetValues(typeof(BattleBehaviour)).Length; + m_CurrentBehaviour = (BattleBehaviour)UnityEngine.Random.Range(0, length); + SeedBehaviourChange(); + CheckBehaviour(); + } + + private void ResetTick() + { + m_Tick = 0f; + } + + private void ShouldBlock() + { + if (CheckIncommingBullets()) + { + m_PlayerAPI.Block(); + } + } + + private bool CheckIncommingBullets() + { + Vector3 vector = m_PlayerAPI.PlayerPosition(); + Vector2 a = new Vector2(vector.x, vector.y); + float num = 1.5f; + List<BulletWrapper> allBullets = m_PlayerAPI.GetAllBullets(); + int count = allBullets.Count; + for (int i = 0; i < count; i++) + { + Vector2 vector2 = allBullets[i].projectileHit.transform.position; + float num2 = Vector2.Distance(a, vector2); + if (num2 <= num && Vector2.Distance(a, vector2 + allBullets[i].velocity.normalized) < num2) + { + return true; + } + } + return false; + } + + private void ShouldAttack() + { + if (CanSee() && Vector3.Distance(m_PlayerAPI.PlayerPosition(), m_PlayerAPI.OtherPlayerPosition()) <= m_AttackDistance) + { + m_PlayerAPI.Attack(); + } + } + + private bool CanSee() + { + Vector2 vector = m_PlayerAPI.TowardsOtherPlayer(); + Vector3 vector2 = new Vector3(vector.x, vector.y, 0f); + vector2.Normalize(); + Collider2D collider = Physics2D.Raycast(base.transform.position + vector2, vector2, 20f).collider; + if ((bool)collider && (bool)collider.GetComponent<Player>()) + { + return true; + } + return false; + } + + private void DoAim() + { + m_PlayerAPI.SetAimDirection(m_PlayerAPI.TowardsOtherPlayer() + m_PlayerAPI.GetOtherPlayer().data.playerVel.velocity * 0.1f); + } + + private void Move() + { + m_PlayerAPI.Move(m_Direction); + } + + private void Jump() + { + m_PlayerAPI.Jump(); + } + + private void CheckGround() + { + Vector2 vector = m_PlayerAPI.PlayerPosition(); + if (!(vector.y < 0f) || m_PlayerAPI.CheckGroundBelow(vector + Vector2.down * 0.5f, 10f)) + { + return; + } + m_Direction = Vector2.right; + float num = float.PositiveInfinity; + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position + Vector3.right, Vector2.right, 5f); + if ((bool)raycastHit2D.collider) + { + num = raycastHit2D.distance; + } + raycastHit2D = Physics2D.Raycast(base.transform.position + Vector3.left, Vector2.left, 5f); + if ((bool)raycastHit2D.collider) + { + if (raycastHit2D.distance < num) + { + m_Direction = Vector2.left; + } + } + else + { + m_Direction = Vector2.right; + } + } + + private void CheckDirection() + { + if (m_CurrentBehaviour == BattleBehaviour.Attack) + { + switch (m_CurrentMorale) + { + case BattleMorale.Blood: + m_Direction = m_PlayerAPI.TowardsOtherPlayer(); + break; + case BattleMorale.Coward: + m_Direction = -m_PlayerAPI.TowardsOtherPlayer(); + break; + case BattleMorale.Defend: + m_Direction = -m_PlayerAPI.TowardsOtherPlayer(); + break; + } + } + else + { + Vector3 vector = m_PlayerAPI.PlayerPosition(); + Vector2 vector2 = new Vector2(vector.x, vector.y); + m_Direction = m_TargetPos - vector2; + } + } + + private void CheckBehaviour() + { + switch (m_CurrentBehaviour) + { + case BattleBehaviour.HighGround: + m_TargetPos = m_Segments[0]; + break; + case BattleBehaviour.MoveSegments: + { + int max = m_Segments.Length; + int num; + for (num = UnityEngine.Random.Range(0, max); num == m_CurrentSegment; num = UnityEngine.Random.Range(0, max)) + { + } + m_CurrentSegment = num; + m_TargetPos = m_Segments[m_CurrentSegment]; + break; + } + case BattleBehaviour.Attack: + break; + } + } + + private void CheckMorale() + { + if (m_PlayerAPI.CanShoot()) + { + m_CurrentMorale = BattleMorale.Blood; + } + } +} diff --git a/ROUNDS/PlayerAIWilhelm.cs b/ROUNDS/PlayerAIWilhelm.cs new file mode 100644 index 0000000..b71a530 --- /dev/null +++ b/ROUNDS/PlayerAIWilhelm.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class PlayerAIWilhelm : MonoBehaviour +{ + private PlayerAPI api; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + } + + private void Update() + { + api.Move(api.TowardsOtherPlayer()); + api.SetAimDirection(api.TowardsOtherPlayer() + api.GetOtherPlayer().data.playerVel.velocity * 0.1f); + api.Attack(); + api.Jump(); + api.Block(); + } +} diff --git a/ROUNDS/PlayerAIZorro.cs b/ROUNDS/PlayerAIZorro.cs new file mode 100644 index 0000000..c475f3f --- /dev/null +++ b/ROUNDS/PlayerAIZorro.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAIZorro : MonoBehaviour +{ + public AnimationCurve m_AimCompensastionCurve; + + public LayerMask m_MapMask; + + public LayerMask m_PlayerMask; + + private PlayerAPI api; + + private Camera m_camera; + + private int framesSinceShot; + + private Vector3[] surfacesToHideOn; + + private Vector3 m_CurrentHidePos; + + private float tiemSpentOverDeath; + + private float timeSinceCouldShoot; + + private void Start() + { + api = GetComponentInParent<PlayerAPI>(); + m_camera = Camera.main; + HealthHandler healthHandler = api.player.data.healthHandler; + healthHandler.delayedReviveAction = (Action)Delegate.Combine(healthHandler.delayedReviveAction, new Action(Init)); + } + + public void Init() + { + StopAllCoroutines(); + BakeMapSurfaces(); + StartCoroutine(GetNewPos()); + } + + private void Update() + { + framesSinceShot++; + if (api.CanShoot()) + { + timeSinceCouldShoot += TimeHandler.deltaTime; + } + else + { + timeSinceCouldShoot = 0f; + } + Vector3 vector = api.OtherPlayerPosition() + (Vector3)api.GetOtherPlayer().data.playerVel.velocity * Vector3.Distance(base.transform.position, api.OtherPlayerPosition()) * 0.01f + Vector3.down * api.GetOtherPlayer().data.playerVel.velocity.y * Vector3.Distance(base.transform.position, api.OtherPlayerPosition()) * 0.005f; + bool flag = false; + if (Physics2D.Raycast(base.transform.position, Vector3.down, 18f, m_MapMask).transform == null) + { + flag = false; + tiemSpentOverDeath += TimeHandler.deltaTime; + } + else + { + flag = true; + tiemSpentOverDeath = 0f; + } + if (api.CanBlock() && Vector3.Distance(base.transform.position, api.OtherPlayerPosition()) > 5f && (flag || tiemSpentOverDeath < 0.25f)) + { + api.Move(vector - base.transform.position + new Vector3(Mathf.PerlinNoise(Time.time, 0f) * 5f * Mathf.Sin(Time.time * 2f), 0f, 0f)); + } + else + { + api.Move(m_CurrentHidePos - base.transform.position + new Vector3(Mathf.PerlinNoise(Time.time, 0f) * 8f * Mathf.Sin(Time.time * 3f), 0f, 0f)); + } + api.Jump(); + ShootAt(vector); + MakeSureToBlock(); + } + + public void MakeSureToBlock() + { + BulletWrapper[] array = api.GetAllBullets().ToArray(); + for (int i = 0; i < array.Length; i++) + { + float num = Vector3.Distance(array[i].projectileMovement.transform.position, base.transform.position); + float num2 = Vector3.Angle(array[i].velocity.normalized, base.transform.position - array[i].projectileMovement.transform.position); + if (num < 1.3f && num2 < 65f && framesSinceShot >= 4) + { + api.Block(); + } + } + } + + public BulletWrapper GetMostDangerousBullet(BulletWrapper[] bullets, out bool exsists) + { + float num = 999999f; + int num2 = -1; + for (int i = 0; i < bullets.Length; i++) + { + float num3 = Vector3.Distance(bullets[i].projectileMovement.transform.position, base.transform.position); + if (num3 < num && num3 < 5f) + { + num = num3; + num2 = i; + } + } + if (num2 != -1) + { + exsists = true; + return bullets[num2]; + } + exsists = false; + return new BulletWrapper(); + } + + public BulletWrapper[] GetAllBulletsComingAtMe() + { + List<BulletWrapper> list = new List<BulletWrapper>(); + BulletWrapper[] array = api.GetAllBullets().ToArray(); + for (int i = 0; i < array.Length; i++) + { + if (Vector3.Angle(array[i].velocity.normalized, base.transform.position - array[i].projectileMovement.transform.position) < 35f) + { + list.Add(array[i]); + } + } + return list.ToArray(); + } + + public void ShootAt(Vector3 point) + { + api.SetAimDirection(GetAimDirForHitting(point)); + api.Attack(); + } + + private Vector2 GetAimDirForHitting(Vector3 point) + { + Vector3 vector = point - base.transform.position; + api.SetAimDirection(vector); + api.GetMyBullet(); + float time = Mathf.Abs(point.x - base.transform.position.x); + Vector3 vector2 = point + Vector3.up * m_AimCompensastionCurve.Evaluate(time); + Debug.DrawLine(point, vector2, Color.red, 0.2f); + return vector2 - base.transform.position; + } + + public void BakeMapSurfaces() + { + Vector2 vector = m_camera.ViewportToWorldPoint(new Vector3(1f, 1f)); + Vector2 vector2 = m_camera.ViewportToWorldPoint(new Vector3(0f, 1f)); + Vector2 vector3 = m_camera.ViewportToWorldPoint(new Vector3(1f, 0f)); + Vector2 vector4 = m_camera.ViewportToWorldPoint(new Vector3(0f, 0f)); + Vector3 v = m_camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f)); + Debug.DrawLine(vector, v, Color.cyan); + Debug.DrawLine(vector2, v, Color.cyan); + Debug.DrawLine(vector3, v, Color.cyan); + Debug.DrawLine(vector4, v, Color.cyan); + List<Vector3> list = new List<Vector3>(); + for (int i = 0; i < 360; i++) + { + for (int j = 0; j < 40; j++) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(new Vector2(Mathf.Lerp(vector2.x, vector.x, (float)i / 359f), Mathf.Lerp(vector3.y, vector.y, (float)j / 39f)), Vector3.down, 6f, m_MapMask); + if ((bool)raycastHit2D.transform) + { + list.Add(raycastHit2D.point); + } + } + } + List<Vector3> list2 = new List<Vector3>(); + for (int k = 0; k < list.Count; k++) + { + if (Physics2D.OverlapCircleAll(list[k] + Vector3.up * 0.26f, 0.1f, m_MapMask).Length != 0) + { + list2.Add(list[k]); + } + } + for (int l = 0; l < list2.Count; l++) + { + list.Remove(list2[l]); + } + Debug.Log("Points: " + list.Count); + for (int m = 0; m < list.Count; m++) + { + Debug.DrawLine(list[m], list[m] + Vector3.up * 0.2f, Color.magenta, 1000f); + } + surfacesToHideOn = list.ToArray(); + } + + private IEnumerator GetNewPos() + { + while (true) + { + m_CurrentHidePos = GetPosAwayFrom(api.OtherPlayerPosition()); + yield return new WaitForSeconds(4f); + } + } + + public Vector3 GetPosAwayFrom(Vector3 point) + { + Vector3 result; + do + { + result = surfacesToHideOn[UnityEngine.Random.Range(0, surfacesToHideOn.Length)]; + } + while (!(Mathf.Abs(result.x - point.x) > 13f)); + return result; + } +} diff --git a/ROUNDS/PlayerAPI.cs b/ROUNDS/PlayerAPI.cs new file mode 100644 index 0000000..3edf9c5 --- /dev/null +++ b/ROUNDS/PlayerAPI.cs @@ -0,0 +1,172 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAPI : MonoBehaviour +{ + public Player player; + + public CharacterData data; + + private GeneralInput input; + + private bool movedThisFrame; + + private bool attackedThisFrame; + + private bool blockedThisFrame; + + private void Awake() + { + player = GetComponent<Player>(); + data = GetComponent<CharacterData>(); + input = GetComponent<GeneralInput>(); + } + + public void Move(Vector2 direction) + { + direction = Vector2.ClampMagnitude(direction, 1f); + movedThisFrame = true; + data.input.direction = direction; + } + + public void Jump() + { + data.jump.Jump(); + } + + public void Attack() + { + attackedThisFrame = true; + data.input.shootWasPressed = true; + data.input.shootIsPressed = true; + } + + public void Block() + { + data.input.shieldWasPressed = true; + } + + public void SetAimDirection(Vector2 direction) + { + data.input.aimDirection = direction; + } + + public void AimForOtherPlayer() + { + Player otherPlayer = PlayerManager.instance.GetOtherPlayer(player); + if ((bool)otherPlayer) + { + data.input.aimDirection = otherPlayer.transform.position - base.transform.position; + } + } + + public Vector2 TowardsOtherPlayer() + { + if (PlayerManager.instance.players.Count < 2) + { + return Vector2.zero; + } + return PlayerManager.instance.GetOtherPlayer(player).transform.position - base.transform.position; + } + + public RaycastHit2D RayCastDirection(Vector2 direction, float distance) + { + return Physics2D.Raycast(base.transform.position, direction, distance); + } + + public bool CheckGroundBelow(Vector2 pos, float range) + { + return data.ThereIsGroundBelow(pos, range); + } + + public bool CanBlock() + { + return !data.block.IsOnCD(); + } + + public Player GetOtherPlayer() + { + return PlayerManager.instance.GetOtherPlayer(player); + } + + public Vector3 OtherPlayerPosition() + { + Player otherPlayer = PlayerManager.instance.GetOtherPlayer(player); + if ((bool)otherPlayer) + { + return otherPlayer.transform.position; + } + return Vector3.zero; + } + + public Vector3 PlayerPosition() + { + return base.transform.position; + } + + public List<BulletWrapper> GetAllBullets() + { + List<BulletWrapper> list = new List<BulletWrapper>(); + ProjectileHit[] array = Object.FindObjectsOfType<ProjectileHit>(); + for (int i = 0; i < array.Length; i++) + { + BulletWrapper bulletWrapper = new BulletWrapper(); + bulletWrapper.projectileHit = array[i].GetComponent<ProjectileHit>(); + bulletWrapper.projectileMovement = array[i].GetComponent<MoveTransform>(); + bulletWrapper.damage = bulletWrapper.projectileHit.damage; + bulletWrapper.velocity = bulletWrapper.projectileMovement.velocity; + list.Add(bulletWrapper); + } + return list; + } + + public SpawnedAttack[] GetAllSpawnedAttacks() + { + return Object.FindObjectsOfType<SpawnedAttack>(); + } + + public bool CanShoot() + { + return player.data.weaponHandler.gun.IsReady(); + } + + public BulletWrapper GetMyBullet() + { + BulletWrapper bulletWrapper = new BulletWrapper(); + GameObject objectToSpawn = player.data.weaponHandler.gun.projectiles[0].objectToSpawn; + MoveTransform component = objectToSpawn.GetComponent<MoveTransform>(); + ProjectileHit component2 = objectToSpawn.GetComponent<ProjectileHit>(); + bulletWrapper.projectileMovement = component; + bulletWrapper.projectileHit = component2; + bulletWrapper.damage = component2.damage; + bulletWrapper.velocity = player.data.aimDirection.normalized * component.localForce.magnitude + component.worldForce; + return bulletWrapper; + } + + private void Update() + { + if (blockedThisFrame) + { + blockedThisFrame = false; + } + else + { + data.input.shieldWasPressed = false; + } + if (movedThisFrame) + { + movedThisFrame = false; + } + else + { + data.input.direction = Vector3.zero; + } + if (attackedThisFrame) + { + attackedThisFrame = false; + return; + } + data.input.shootWasPressed = false; + data.input.shootIsPressed = false; + } +} diff --git a/ROUNDS/PlayerActions.cs b/ROUNDS/PlayerActions.cs new file mode 100644 index 0000000..8c6d6f1 --- /dev/null +++ b/ROUNDS/PlayerActions.cs @@ -0,0 +1,131 @@ +using System; +using InControl; + +public class PlayerActions : PlayerActionSet +{ + public PlayerAction Fire; + + public PlayerAction Block; + + public PlayerAction Jump; + + public PlayerAction Left; + + public PlayerAction Right; + + public PlayerAction Up; + + public PlayerAction Down; + + public PlayerTwoAxisAction Move; + + public PlayerTwoAxisAction Aim; + + public PlayerAction AimLeft; + + public PlayerAction AimRight; + + public PlayerAction AimUp; + + public PlayerAction AimDown; + + public PlayerAction Start; + + public PlayerActions() + { + Fire = CreatePlayerAction("Fire"); + Start = CreatePlayerAction("Start"); + Block = CreatePlayerAction("Block"); + Jump = CreatePlayerAction("Jump"); + Left = CreatePlayerAction("Move Left"); + Right = CreatePlayerAction("Move Right"); + Up = CreatePlayerAction("Move Up"); + Down = CreatePlayerAction("Move Down"); + AimLeft = CreatePlayerAction("Aim Left"); + AimRight = CreatePlayerAction("Aim Right"); + AimUp = CreatePlayerAction("Aim Up"); + AimDown = CreatePlayerAction("Aim Down"); + Move = CreateTwoAxisPlayerAction(Left, Right, Down, Up); + Aim = CreateTwoAxisPlayerAction(AimLeft, AimRight, AimDown, AimUp); + } + + public static PlayerActions CreateWithKeyboardBindings() + { + PlayerActions playerActions = new PlayerActions(); + playerActions.Fire.AddDefaultBinding(Mouse.LeftButton); + playerActions.Block.AddDefaultBinding(Mouse.RightButton); + playerActions.Jump.AddDefaultBinding(Key.Space); + playerActions.Up.AddDefaultBinding(Key.W); + playerActions.Down.AddDefaultBinding(Key.S); + playerActions.Left.AddDefaultBinding(Key.A); + playerActions.Right.AddDefaultBinding(Key.D); + playerActions.Start.AddDefaultBinding(Key.Return); + playerActions.ListenOptions.IncludeUnknownControllers = true; + playerActions.ListenOptions.MaxAllowedBindings = 4u; + playerActions.ListenOptions.UnsetDuplicateBindingsOnSet = true; + playerActions.ListenOptions.OnBindingFound = delegate(PlayerAction action, BindingSource binding) + { + if (binding == new KeyBindingSource(Key.Escape)) + { + action.StopListeningForBinding(); + return false; + } + return true; + }; + BindingListenOptions bindingListenOptions = playerActions.ListenOptions; + bindingListenOptions.OnBindingAdded = (Action<PlayerAction, BindingSource>)Delegate.Combine(bindingListenOptions.OnBindingAdded, (Action<PlayerAction, BindingSource>)delegate(PlayerAction action, BindingSource binding) + { + Debug.Log("Binding added... " + binding.DeviceName + ": " + binding.Name); + }); + BindingListenOptions bindingListenOptions2 = playerActions.ListenOptions; + bindingListenOptions2.OnBindingRejected = (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)Delegate.Combine(bindingListenOptions2.OnBindingRejected, (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)delegate(PlayerAction action, BindingSource binding, BindingSourceRejectionType reason) + { + Debug.Log("Binding rejected... " + reason); + }); + return playerActions; + } + + public static PlayerActions CreateWithControllerBindings() + { + PlayerActions playerActions = new PlayerActions(); + playerActions.Fire.AddDefaultBinding(InputControlType.Action3); + playerActions.Fire.AddDefaultBinding(InputControlType.RightTrigger); + playerActions.Block.AddDefaultBinding(InputControlType.Action2); + playerActions.Block.AddDefaultBinding(InputControlType.LeftTrigger); + playerActions.Jump.AddDefaultBinding(InputControlType.Action1); + playerActions.Jump.AddDefaultBinding(InputControlType.LeftBumper); + playerActions.Jump.AddDefaultBinding(InputControlType.RightBumper); + playerActions.Start.AddDefaultBinding(InputControlType.Start); + playerActions.Left.AddDefaultBinding(InputControlType.LeftStickLeft); + playerActions.Right.AddDefaultBinding(InputControlType.LeftStickRight); + playerActions.Up.AddDefaultBinding(InputControlType.LeftStickUp); + playerActions.Down.AddDefaultBinding(InputControlType.LeftStickDown); + playerActions.AimLeft.AddDefaultBinding(InputControlType.RightStickLeft); + playerActions.AimRight.AddDefaultBinding(InputControlType.RightStickRight); + playerActions.AimUp.AddDefaultBinding(InputControlType.RightStickUp); + playerActions.AimDown.AddDefaultBinding(InputControlType.RightStickDown); + playerActions.ListenOptions.IncludeUnknownControllers = true; + playerActions.ListenOptions.MaxAllowedBindings = 4u; + playerActions.ListenOptions.UnsetDuplicateBindingsOnSet = true; + playerActions.ListenOptions.OnBindingFound = delegate(PlayerAction action, BindingSource binding) + { + if (binding == new KeyBindingSource(Key.Escape)) + { + action.StopListeningForBinding(); + return false; + } + return true; + }; + BindingListenOptions bindingListenOptions = playerActions.ListenOptions; + bindingListenOptions.OnBindingAdded = (Action<PlayerAction, BindingSource>)Delegate.Combine(bindingListenOptions.OnBindingAdded, (Action<PlayerAction, BindingSource>)delegate(PlayerAction action, BindingSource binding) + { + Debug.Log("Binding added... " + binding.DeviceName + ": " + binding.Name); + }); + BindingListenOptions bindingListenOptions2 = playerActions.ListenOptions; + bindingListenOptions2.OnBindingRejected = (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)Delegate.Combine(bindingListenOptions2.OnBindingRejected, (Action<PlayerAction, BindingSource, BindingSourceRejectionType>)delegate(PlayerAction action, BindingSource binding, BindingSourceRejectionType reason) + { + Debug.Log("Binding rejected... " + reason); + }); + return playerActions; + } +} diff --git a/ROUNDS/PlayerAssigner.cs b/ROUNDS/PlayerAssigner.cs new file mode 100644 index 0000000..d4c4880 --- /dev/null +++ b/ROUNDS/PlayerAssigner.cs @@ -0,0 +1,220 @@ +using System.Collections; +using System.Collections.Generic; +using InControl; +using Photon.Pun; +using SoundImplementation; +using UnityEngine; + +public class PlayerAssigner : MonoBehaviour +{ + public GameObject player1AI; + + public GameObject player2AI; + + public static PlayerAssigner instance; + + public GameObject playerPrefab; + + public int maxPlayers = 4; + + public List<CharacterData> players = new List<CharacterData>(4); + + private bool playersCanJoin; + + private int playerIDToSet = -1; + + private int teamIDToSet = -1; + + private bool waitingForRegisterResponse; + + private bool hasCreatedLocalPlayer; + + private void Awake() + { + instance = this; + } + + internal void SetPlayersCanJoin(bool canJoin) + { + playersCanJoin = canJoin; + } + + private void Start() + { + InputManager.OnDeviceDetached += OnDeviceDetached; + } + + private void LateUpdate() + { + if (!playersCanJoin || players.Count >= maxPlayers || DevConsole.isTyping) + { + return; + } + if (Input.GetKeyDown(KeyCode.B) && !GameManager.lockInput) + { + StartCoroutine(CreatePlayer(null, isAI: true)); + } + if (Input.GetKey(KeyCode.Space)) + { + bool flag = true; + for (int i = 0; i < players.Count; i++) + { + if (players[i].playerActions.Device == null) + { + flag = false; + } + } + if (flag) + { + StartCoroutine(CreatePlayer(null)); + } + } + for (int j = 0; j < InputManager.ActiveDevices.Count; j++) + { + InputDevice inputDevice = InputManager.ActiveDevices[j]; + if (JoinButtonWasPressedOnDevice(inputDevice) && ThereIsNoPlayerUsingDevice(inputDevice)) + { + StartCoroutine(CreatePlayer(inputDevice)); + } + } + } + + private bool JoinButtonWasPressedOnDevice(InputDevice inputDevice) + { + if (!inputDevice.Action1.WasPressed && !inputDevice.Action2.WasPressed && !inputDevice.Action3.WasPressed) + { + return inputDevice.Action4.WasPressed; + } + return true; + } + + private CharacterData FindPlayerUsingDevice(InputDevice inputDevice) + { + int count = players.Count; + for (int i = 0; i < count; i++) + { + CharacterData characterData = players[i]; + if (characterData.playerActions.Device == inputDevice) + { + return characterData; + } + } + return null; + } + + public void ClearPlayers() + { + players.Clear(); + } + + private bool ThereIsNoPlayerUsingDevice(InputDevice inputDevice) + { + return FindPlayerUsingDevice(inputDevice) == null; + } + + private void OnDeviceDetached(InputDevice inputDevice) + { + CharacterData characterData = FindPlayerUsingDevice(inputDevice); + if (characterData != null) + { + RemovePlayer(characterData); + } + } + + [PunRPC] + public void RPCM_RequestTeamAndPlayerID(int askingPlayer) + { + int count = PlayerManager.instance.players.Count; + int num = ((count % 2 != 0) ? 1 : 0); + GetComponent<PhotonView>().RPC("RPC_ReturnPlayerAndTeamID", PhotonNetwork.CurrentRoom.GetPlayer(askingPlayer), count, num); + waitingForRegisterResponse = true; + } + + [PunRPC] + public void RPC_ReturnPlayerAndTeamID(int teamId, int playerID) + { + waitingForRegisterResponse = false; + playerIDToSet = playerID; + teamIDToSet = teamId; + } + + public void OtherPlayerWasCreated() + { + waitingForRegisterResponse = false; + } + + public IEnumerator CreatePlayer(InputDevice inputDevice, bool isAI = false) + { + if (waitingForRegisterResponse || (!PhotonNetwork.OfflineMode && hasCreatedLocalPlayer) || players.Count >= maxPlayers) + { + yield break; + } + if (!PhotonNetwork.OfflineMode && !PhotonNetwork.IsMasterClient) + { + GetComponent<PhotonView>().RPC("RPCM_RequestTeamAndPlayerID", RpcTarget.MasterClient, PhotonNetwork.LocalPlayer.ActorNumber); + waitingForRegisterResponse = true; + } + while (waitingForRegisterResponse) + { + yield return null; + } + if (!PhotonNetwork.OfflineMode) + { + if (PhotonNetwork.IsMasterClient) + { + playerIDToSet = PlayerManager.instance.players.Count; + teamIDToSet = ((playerIDToSet % 2 != 0) ? 1 : 0); + } + } + else + { + playerIDToSet = PlayerManager.instance.players.Count; + teamIDToSet = ((playerIDToSet % 2 != 0) ? 1 : 0); + } + hasCreatedLocalPlayer = true; + SoundPlayerStatic.Instance.PlayPlayerAdded(); + Vector3 position = Vector3.up * 100f; + CharacterData component = PhotonNetwork.Instantiate(playerPrefab.name, position, Quaternion.identity, 0).GetComponent<CharacterData>(); + if (isAI) + { + GameObject original = player1AI; + if (players.Count > 0) + { + original = player2AI; + } + component.GetComponent<CharacterData>().SetAI(); + Object.Instantiate(original, component.transform.position, component.transform.rotation, component.transform); + } + else + { + if (inputDevice != null) + { + component.input.inputType = GeneralInput.InputType.Controller; + component.playerActions = PlayerActions.CreateWithControllerBindings(); + } + else + { + component.input.inputType = GeneralInput.InputType.Keyboard; + component.playerActions = PlayerActions.CreateWithKeyboardBindings(); + } + component.playerActions.Device = inputDevice; + } + players.Add(component); + RegisterPlayer(component, teamIDToSet, playerIDToSet); + } + + private void RegisterPlayer(CharacterData player, int teamID, int playerID) + { + PlayerManager.RegisterPlayer(player.player); + player.player.AssignPlayerID(playerID); + player.player.AssignTeamID(teamID); + } + + private void RemovePlayer(CharacterData player) + { + } + + private void AssignPlayer(CharacterData player, InputDevice device) + { + } +} diff --git a/ROUNDS/PlayerAudioModifyers.cs b/ROUNDS/PlayerAudioModifyers.cs new file mode 100644 index 0000000..7f82b58 --- /dev/null +++ b/ROUNDS/PlayerAudioModifyers.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAudioModifyers : MonoBehaviour +{ + public List<AudioModifyer> modifyers = new List<AudioModifyer>(); + + public static List<CardAudioModifier> activeModifyer = new List<CardAudioModifier>(); + + public void AddToStack(CardAudioModifier mod) + { + int num = -1; + for (int i = 0; i < modifyers.Count; i++) + { + if (modifyers[i].modifier.stackName == mod.stackName) + { + num = i; + break; + } + } + if (num != -1) + { + modifyers[num].stacks++; + return; + } + AudioModifyer audioModifyer = new AudioModifyer(); + audioModifyer.modifier = new CardAudioModifier(); + audioModifyer.modifier.stackName = mod.stackName; + audioModifyer.modifier.stackType = mod.stackType; + audioModifyer.stacks = 1; + activeModifyer.Add(audioModifyer.modifier); + modifyers.Add(audioModifyer); + } + + public void SetStacks() + { + for (int i = 0; i < activeModifyer.Count; i++) + { + _ = activeModifyer[i].stackType; + _ = 1; + _ = activeModifyer[i].stackType; + } + for (int j = 0; j < modifyers.Count; j++) + { + _ = modifyers[j].modifier.stackType; + _ = 1; + _ = modifyers[j].modifier.stackType; + } + } +} diff --git a/ROUNDS/PlayerChat.cs b/ROUNDS/PlayerChat.cs new file mode 100644 index 0000000..61c9578 --- /dev/null +++ b/ROUNDS/PlayerChat.cs @@ -0,0 +1,87 @@ +using System.Collections; +using TMPro; +using UnityEngine; + +public class PlayerChat : MonoBehaviour +{ + public float spring = 15f; + + public float damper = 15f; + + public float impulse; + + public float targetScale; + + private TextMeshProUGUI messageText; + + private ScaleShake scaleShake; + + private float currentScale; + + private float vel; + + public Transform target; + + private Screenshaker shaker; + + private float sinceType; + + public float shakeAmount; + + public float shakeSpeed = 1f; + + private void Start() + { + messageText = target.GetComponentInChildren<TextMeshProUGUI>(); + shaker = target.GetComponentInChildren<Screenshaker>(); + target.transform.localScale = Vector3.zero; + } + + private void Update() + { + sinceType -= Time.unscaledDeltaTime; + if (sinceType < 0f) + { + targetScale = 0f; + } + else + { + targetScale = 1f; + } + vel = FRILerp.Lerp(vel, (targetScale - currentScale) * spring, damper); + currentScale += Time.unscaledDeltaTime * vel; + if (currentScale < 0f) + { + vel = 0f; + currentScale = 0f; + } + target.transform.localScale = Vector3.one * currentScale; + } + + public void Send(string message) + { + message = ChatFilter.instance.FilterMessage(message); + messageText.text = message; + if (sinceType > 0f) + { + vel += impulse; + } + sinceType = 2f + (float)message.Length * 0.05f; + targetScale = 1f; + if (message.ToUpper() == message) + { + StartCoroutine(ShakeOverTime(sinceType)); + } + } + + private IEnumerator ShakeOverTime(float t) + { + float a = t; + while (a > 0f) + { + shaker.OnUIGameFeel(shakeAmount * Random.insideUnitCircle); + a -= Time.unscaledDeltaTime * shakeSpeed; + yield return null; + } + } +} diff --git a/ROUNDS/PlayerDoBlock.cs b/ROUNDS/PlayerDoBlock.cs new file mode 100644 index 0000000..5f14851 --- /dev/null +++ b/ROUNDS/PlayerDoBlock.cs @@ -0,0 +1,23 @@ +using Photon.Pun; +using UnityEngine; + +public class PlayerDoBlock : MonoBehaviour +{ + private CharacterData data; + + private SyncPlayerMovement sync; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + sync = GetComponentInParent<SyncPlayerMovement>(); + } + + public void DoBlock() + { + if (data.view.IsMine) + { + sync.SendBlock(BlockTrigger.BlockTriggerType.Default, firstBlock: true, dontSetCD: true); + } + } +} diff --git a/ROUNDS/PlayerEffects.cs b/ROUNDS/PlayerEffects.cs new file mode 100644 index 0000000..c122706 --- /dev/null +++ b/ROUNDS/PlayerEffects.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +public class PlayerEffects : MonoBehaviour +{ + public float lifeSteal; + + private void Start() + { + } +} diff --git a/ROUNDS/PlayerFace.cs b/ROUNDS/PlayerFace.cs new file mode 100644 index 0000000..f6e69f3 --- /dev/null +++ b/ROUNDS/PlayerFace.cs @@ -0,0 +1,84 @@ +using System; +using UnityEngine; + +[Serializable] +public class PlayerFace +{ + public int eyeID; + + public Vector2 eyeOffset; + + public int mouthID; + + public Vector2 mouthOffset; + + public int detailID; + + public Vector2 detailOffset; + + public int detail2ID; + + public Vector2 detail2Offset; + + public void LoadFace(string key) + { + eyeID = PlayerPrefs.GetInt("eyeID-" + key); + eyeOffset.x = PlayerPrefs.GetFloat("eyeOffsetX-" + key); + eyeOffset.y = PlayerPrefs.GetFloat("eyeOffsetY-" + key); + mouthID = PlayerPrefs.GetInt("mouthID-" + key); + mouthOffset.x = PlayerPrefs.GetFloat("mouthOffsetX-" + key); + mouthOffset.y = PlayerPrefs.GetFloat("mouthOffsetY-" + key); + detailID = PlayerPrefs.GetInt("detailID-" + key); + detailOffset.x = PlayerPrefs.GetFloat("detailOffsetX-" + key); + detailOffset.y = PlayerPrefs.GetFloat("detailOffsetY-" + key); + detail2ID = PlayerPrefs.GetInt("detail2ID-" + key); + detail2Offset.x = PlayerPrefs.GetFloat("detail2OffsetX-" + key); + detail2Offset.y = PlayerPrefs.GetFloat("detail2OffsetY-" + key); + } + + internal static PlayerFace CopyFace(PlayerFace currentPlayerFace) + { + return new PlayerFace + { + eyeID = currentPlayerFace.eyeID, + eyeOffset = currentPlayerFace.eyeOffset, + mouthID = currentPlayerFace.mouthID, + mouthOffset = currentPlayerFace.mouthOffset, + detailID = currentPlayerFace.detailID, + detailOffset = currentPlayerFace.detailOffset, + detail2ID = currentPlayerFace.detail2ID, + detail2Offset = currentPlayerFace.detail2Offset + }; + } + + internal static PlayerFace CreateFace(int eyeID, Vector2 eyeOffset, int mouthID, Vector2 mouthOffset, int detailID, Vector2 detailOffset, int detail2ID, Vector2 detail2Offset) + { + return new PlayerFace + { + eyeID = eyeID, + eyeOffset = eyeOffset, + mouthID = mouthID, + mouthOffset = mouthOffset, + detailID = detailID, + detailOffset = detailOffset, + detail2ID = detail2ID, + detail2Offset = detail2Offset + }; + } + + public void SaveFace(string key) + { + PlayerPrefs.SetInt("eyeID-" + key, eyeID); + PlayerPrefs.SetFloat("eyeOffsetX-" + key, eyeOffset.x); + PlayerPrefs.SetFloat("eyeOffsetY-" + key, eyeOffset.y); + PlayerPrefs.SetInt("mouthID-" + key, mouthID); + PlayerPrefs.SetFloat("mouthOffsetX-" + key, mouthOffset.x); + PlayerPrefs.SetFloat("mouthOffsetY-" + key, mouthOffset.y); + PlayerPrefs.SetInt("detailID-" + key, detailID); + PlayerPrefs.SetFloat("detailOffsetX-" + key, detailOffset.x); + PlayerPrefs.SetFloat("detailOffsetY-" + key, detailOffset.y); + PlayerPrefs.SetInt("detail2ID-" + key, detail2ID); + PlayerPrefs.SetFloat("detail2OffsetX-" + key, detail2Offset.x); + PlayerPrefs.SetFloat("detail2OffsetY-" + key, detail2Offset.y); + } +} diff --git a/ROUNDS/PlayerFlyParticle.cs b/ROUNDS/PlayerFlyParticle.cs new file mode 100644 index 0000000..a58db02 --- /dev/null +++ b/ROUNDS/PlayerFlyParticle.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class PlayerFlyParticle : MonoBehaviour +{ + private ParticleSystem part; + + private HealthHandler health; + + private void Start() + { + part = GetComponent<ParticleSystem>(); + health = GetComponentInParent<HealthHandler>(); + } + + private void Update() + { + if (part.isPlaying) + { + if (health.flyingFor < 0f) + { + part.Stop(); + } + } + else if (health.flyingFor > 0f) + { + part.Play(); + } + } +} diff --git a/ROUNDS/PlayerImmunity.cs b/ROUNDS/PlayerImmunity.cs new file mode 100644 index 0000000..791fadf --- /dev/null +++ b/ROUNDS/PlayerImmunity.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerImmunity : MonoBehaviour +{ + private List<Immunities> immunities = new List<Immunities>(); + + private void Start() + { + } + + private void Update() + { + for (int num = immunities.Count - 1; num >= 0; num--) + { + immunities[num].time -= TimeHandler.deltaTime; + if (immunities[num].time <= 0f) + { + immunities.RemoveAt(num); + } + } + } + + public bool IsImune(float time, float dmg, string name) + { + for (int i = 0; i < immunities.Count; i++) + { + if (immunities[i].name == name) + { + if (dmg > immunities[i].dmg) + { + immunities[i].dmg = dmg; + immunities[i].name = name; + immunities[i].time = time; + return false; + } + return true; + } + } + immunities.Add(new Immunities(time, dmg, name)); + return false; + } +} diff --git a/ROUNDS/PlayerInRangeSlow.cs b/ROUNDS/PlayerInRangeSlow.cs new file mode 100644 index 0000000..dd1f0cf --- /dev/null +++ b/ROUNDS/PlayerInRangeSlow.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +public class PlayerInRangeSlow : MonoBehaviour +{ + public float slowAmount = 0.1f; + + public float maxSlow = 0.5f; + + private PlayerInRangeTrigger trigger; + + private AttackLevel level; + + private void Start() + { + trigger = GetComponent<PlayerInRangeTrigger>(); + level = GetComponent<AttackLevel>(); + } + + private void Update() + { + if (trigger.inRange) + { + trigger.target.data.stats.AddSlowAddative(slowAmount * (float)level.attackLevel, maxSlow + ((float)level.attackLevel - 1f) * 0.25f); + } + } +} diff --git a/ROUNDS/PlayerInRangeTrigger.cs b/ROUNDS/PlayerInRangeTrigger.cs new file mode 100644 index 0000000..a6bad07 --- /dev/null +++ b/ROUNDS/PlayerInRangeTrigger.cs @@ -0,0 +1,79 @@ +using UnityEngine; +using UnityEngine.Events; + +public class PlayerInRangeTrigger : MonoBehaviour +{ + public enum TargetType + { + Any, + OtherPlayer + } + + public TargetType targetType; + + public float range = 5f; + + public float cooldown; + + public bool repeating; + + private float counter; + + private bool done; + + [HideInInspector] + public bool inRange; + + public UnityEvent triggerEvent; + + [HideInInspector] + public Player target; + + private Player ownPlayer; + + public bool scaleWithRange; + + private void Start() + { + ownPlayer = base.transform.root.GetComponent<Player>(); + if (!ownPlayer) + { + ownPlayer = base.transform.root.GetComponentInParent<SpawnedAttack>().spawner; + } + if (scaleWithRange) + { + range *= base.transform.localScale.x; + } + } + + private void Update() + { + counter += TimeHandler.deltaTime; + inRange = false; + target = null; + if (done) + { + return; + } + Player player = null; + if (targetType == TargetType.OtherPlayer) + { + player = PlayerManager.instance.GetOtherPlayer(ownPlayer); + } + if (targetType == TargetType.Any) + { + player = PlayerManager.instance.GetClosestPlayer(base.transform.position); + } + if (PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee && Vector3.Distance(base.transform.position, player.transform.position) < range * base.transform.root.localScale.x && !player.data.dead && counter >= cooldown) + { + counter = 0f; + triggerEvent.Invoke(); + inRange = true; + target = player; + if (!repeating) + { + done = true; + } + } + } +} diff --git a/ROUNDS/PlayerManager.cs b/ROUNDS/PlayerManager.cs new file mode 100644 index 0000000..1c72689 --- /dev/null +++ b/ROUNDS/PlayerManager.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class PlayerManager : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent[] soundCharacterSpawn; + + public static PlayerManager instance; + + public LayerMask canSeePlayerMask; + + public List<Player> players = new List<Player>(); + + public PhotonView view; + + private Action<Player, int> PlayerDiedAction; + + private bool playersShouldBeActive; + + public AnimationCurve playerMoveCurve; + + public Action<Player> PlayerJoinedAction { get; internal set; } + + private void Awake() + { + instance = this; + view = GetComponent<PhotonView>(); + } + + public Player GetOtherPlayer(Player asker) + { + return GetClosestPlayerInTeam(asker.transform.position, GetOtherTeam(asker.teamID)); + } + + public Player GetClosestPlayer(Vector2 refPos, bool needVision = false) + { + Player result = null; + float num = float.PositiveInfinity; + for (int i = 0; i < players.Count; i++) + { + if (!players[i].data.dead) + { + float num2 = Vector2.Distance(refPos, players[i].data.playerVel.position); + if ((!needVision || CanSeePlayer(refPos, players[i]).canSee) && num2 < num) + { + num = num2; + result = players[i]; + } + } + } + return result; + } + + internal Player GetPlayerWithActorID(int actorID) + { + for (int i = 0; i < players.Count; i++) + { + if (players[i].data.view.OwnerActorNr == actorID) + { + return players[i]; + } + } + return null; + } + + public Player GetClosestPlayerInTeam(Vector3 position, int team, bool needVision = false) + { + float num = float.MaxValue; + Player[] playersInTeam = GetPlayersInTeam(team); + Player result = null; + for (int i = 0; i < playersInTeam.Length; i++) + { + if (!players[i].data.dead) + { + float num2 = Vector2.Distance(position, playersInTeam[i].transform.position); + if ((!needVision || CanSeePlayer(position, playersInTeam[i]).canSee) && num2 < num) + { + num = num2; + result = playersInTeam[i]; + } + } + } + return result; + } + + public Player GetClosestPlayer(Vector2 refPos, Vector2 forward) + { + Player result = null; + float num = float.PositiveInfinity; + for (int i = 0; i < players.Count; i++) + { + if (!players[i].data.dead && CanSeePlayer(refPos, players[i]).canSee) + { + float num2 = Vector2.Distance(refPos, players[i].data.playerVel.position); + num2 += Vector2.Angle(forward, players[i].data.playerVel.position - refPos); + if (num2 < num) + { + num = num2; + result = players[i]; + } + } + } + return result; + } + + public CanSeeInfo CanSeePlayer(Vector2 from, Player player) + { + CanSeeInfo canSeeInfo = new CanSeeInfo(); + canSeeInfo.canSee = true; + canSeeInfo.distance = float.PositiveInfinity; + if (!player) + { + canSeeInfo.canSee = false; + return canSeeInfo; + } + RaycastHit2D[] array = Physics2D.RaycastAll(from, (player.data.playerVel.position - from).normalized, Vector2.Distance(from, player.data.playerVel.position), canSeePlayerMask); + for (int i = 0; i < array.Length; i++) + { + if ((bool)array[i].transform && !array[i].transform.root.GetComponent<SpawnedAttack>() && !array[i].transform.root.GetComponent<Player>() && array[i].distance < canSeeInfo.distance) + { + canSeeInfo.canSee = false; + canSeeInfo.hitPoint = array[i].point; + canSeeInfo.distance = array[i].distance; + } + } + return canSeeInfo; + } + + internal Player GetPlayerWithID(int playerID) + { + for (int i = 0; i < players.Count; i++) + { + if (players[i].playerID == playerID) + { + return players[i]; + } + } + return null; + } + + public Player GetLastPlayerAlive() + { + Player result = null; + for (int i = 0; i < players.Count; i++) + { + if (!players[i].data.dead) + { + result = players[i]; + break; + } + } + return result; + } + + public int GetLastTeamAlive() + { + return GetLastPlayerAlive().teamID; + } + + public int TeamsAlive() + { + bool flag = false; + bool flag2 = false; + for (int i = 0; i < players.Count; i++) + { + if (players[i].teamID == 0 && !players[i].data.dead) + { + flag = true; + } + if (players[i].teamID == 1 && !players[i].data.dead) + { + flag2 = true; + } + } + int num = 0; + if (flag) + { + num++; + } + if (flag2) + { + num++; + } + return num; + } + + public static void RegisterPlayer(Player player) + { + instance.players.Add(player); + if (instance.playersShouldBeActive) + { + player.data.isPlaying = true; + } + } + + public void RemovePlayer(Player player) + { + players.Remove(player); + UnityEngine.Object.Destroy(player.gameObject); + } + + public void RemovePlayers() + { + for (int num = players.Count - 1; num >= 0; num--) + { + if ((bool)players[num]) + { + UnityEngine.Object.Destroy(players[num].gameObject); + } + } + players.Clear(); + PlayerAssigner.instance.ClearPlayers(); + } + + public void RevivePlayers() + { + for (int i = 0; i < players.Count; i++) + { + players[i].data.healthHandler.Revive(); + players[i].GetComponent<GeneralInput>().enabled = true; + } + } + + [PunRPC] + public void RPCA_MovePlayers() + { + MovePlayers(MapManager.instance.GetSpawnPoints()); + } + + public void MovePlayers(SpawnPoint[] spawnPoints) + { + for (int i = 0; i < players.Count; i++) + { + StartCoroutine(Move(players[i].data.playerVel, spawnPoints[i].localStartPos)); + int num; + for (num = i; num >= soundCharacterSpawn.Length; num -= soundCharacterSpawn.Length) + { + } + SoundManager.Instance.Play(soundCharacterSpawn[num], players[i].transform); + } + } + + public void AddPlayerDiedAction(Action<Player, int> action) + { + PlayerDiedAction = (Action<Player, int>)Delegate.Combine(PlayerDiedAction, action); + } + + public void PlayerDied(Player player) + { + int num = 0; + for (int i = 0; i < players.Count; i++) + { + if (!instance.players[i].data.dead) + { + num++; + } + } + if (PlayerDiedAction != null) + { + PlayerDiedAction(player, num); + } + } + + public PlayerSkin GetColorFromTeam(int teamID) + { + return PlayerSkinBank.GetPlayerSkinColors(GetPlayersInTeam(teamID)[0].playerID); + } + + public PlayerSkin GetColorFromPlayer(int playerID) + { + return PlayerSkinBank.GetPlayerSkinColors(playerID); + } + + public Player[] GetPlayersInTeam(int teamID) + { + List<Player> list = new List<Player>(); + for (int i = 0; i < players.Count; i++) + { + if (players[i].teamID == teamID) + { + list.Add(players[i]); + } + } + return list.ToArray(); + } + + internal Player GetFirstPlayerInTeam(int teamID) + { + return GetPlayersInTeam(teamID)[0]; + } + + public int GetOtherTeam(int team) + { + if (team == 0) + { + return 1; + } + return 0; + } + + public void SetPlayersPlaying(bool playing) + { + playersShouldBeActive = playing; + for (int i = 0; i < players.Count; i++) + { + players[i].data.isPlaying = playing; + } + } + + public void SetPlayersSimulated(bool simulated) + { + playersShouldBeActive = simulated; + for (int i = 0; i < players.Count; i++) + { + players[i].data.playerVel.simulated = simulated; + } + } + + internal void SetPlayersVisible(bool visible) + { + for (int i = 0; i < players.Count; i++) + { + players[i].data.gameObject.transform.position = Vector3.up * 200f; + } + } + + public void PlayerJoined(Player player) + { + if (PlayerJoinedAction != null) + { + PlayerJoinedAction(player); + } + } + + private IEnumerator Move(PlayerVelocity player, Vector3 targetPos) + { + Debug.Log("MOVE PLAYERS START " + Time.unscaledTime); + player.GetComponent<Player>().data.isPlaying = false; + player.simulated = false; + player.isKinematic = true; + Vector3 distance = targetPos - player.transform.position; + Vector3 targetStartPos = player.transform.position; + PlayerCollision col = player.GetComponent<PlayerCollision>(); + float t = playerMoveCurve.keys[playerMoveCurve.keys.Length - 1].time; + float c = 0f; + while (c < t) + { + col.IgnoreWallForFrames(2); + c += Mathf.Clamp(Time.unscaledDeltaTime, 0f, 0.02f); + player.transform.position = targetStartPos + distance * playerMoveCurve.Evaluate(c); + yield return null; + } + int frames = 0; + while (frames < 10) + { + player.transform.position = targetStartPos + distance; + frames++; + yield return null; + } + player.simulated = true; + player.isKinematic = false; + Debug.Log("MOVE PLAYERS END " + Time.unscaledTime); + player.GetComponent<Player>().data.isPlaying = true; + player.GetComponent<Player>().data.healthHandler.Revive(); + CardChoiceVisuals.instance.Hide(); + } + + private void Update() + { + if (Input.GetKeyDown(KeyCode.R) && !DevConsole.isTyping && Application.isEditor) + { + ResetCharacters(); + } + } + + internal void ResetCharacters() + { + CardBarHandler.instance.ResetCardBards(); + for (int i = 0; i < players.Count; i++) + { + players[i].FullReset(); + } + } + + public PlayerActions[] GetActionsFromTeam(int selectingTeamID) + { + List<PlayerActions> list = new List<PlayerActions>(); + for (int i = 0; i < players.Count; i++) + { + if (players[i].teamID == selectingTeamID) + { + list.Add(players[i].data.playerActions); + } + } + return list.ToArray(); + } + + public PlayerActions[] GetActionsFromPlayer(int selectingPlayerID) + { + List<PlayerActions> list = new List<PlayerActions>(); + for (int i = 0; i < players.Count; i++) + { + if (players[i].playerID == selectingPlayerID) + { + list.Add(players[i].data.playerActions); + } + } + return list.ToArray(); + } +} diff --git a/ROUNDS/PlayerName.cs b/ROUNDS/PlayerName.cs new file mode 100644 index 0000000..30fc4cc --- /dev/null +++ b/ROUNDS/PlayerName.cs @@ -0,0 +1,11 @@ +using Photon.Pun; +using TMPro; +using UnityEngine; + +public class PlayerName : MonoBehaviour +{ + private void Start() + { + GetComponentInParent<TextMeshProUGUI>().text = GetComponentInParent<PhotonView>().Owner.NickName; + } +} diff --git a/ROUNDS/PlayerSkin.cs b/ROUNDS/PlayerSkin.cs new file mode 100644 index 0000000..446a0cd --- /dev/null +++ b/ROUNDS/PlayerSkin.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class PlayerSkin : MonoBehaviour +{ + public Color color; + + public Color backgroundColor; + + public Color winText; + + public Color particleEffect; +} diff --git a/ROUNDS/PlayerSkinBank.cs b/ROUNDS/PlayerSkinBank.cs new file mode 100644 index 0000000..0a5bcd5 --- /dev/null +++ b/ROUNDS/PlayerSkinBank.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +[CreateAssetMenu(fileName = "Skin Bank", menuName = "Custom/Skin Bank", order = 99999)] +public class PlayerSkinBank : ScriptableObject +{ + [Serializable] + public struct PlayerSkinInstance + { + public PlayerSkin currentPlayerSkin; + } + + private static PlayerSkinBank instance; + + public PlayerSkinInstance[] skins = new PlayerSkinInstance[0]; + + private static PlayerSkinBank Instance + { + get + { + if (instance == null) + { + instance = Resources.Load("SkinBank") as PlayerSkinBank; + } + return instance; + } + } + + public static PlayerSkin GetPlayerSkinColors(int team) + { + return Instance.skins[team].currentPlayerSkin; + } + + public static PlayerSkinInstance GetPlayerSkin(int team) + { + return Instance.skins[team]; + } +} diff --git a/ROUNDS/PlayerSkinHandler.cs b/ROUNDS/PlayerSkinHandler.cs new file mode 100644 index 0000000..3c23236 --- /dev/null +++ b/ROUNDS/PlayerSkinHandler.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +public class PlayerSkinHandler : MonoBehaviour +{ + public bool simpleSkin; + + private PlayerSkinParticle[] skins; + + private CharacterData data; + + private bool inited; + + private void Start() + { + Init(); + } + + private void Init() + { + if (!inited) + { + inited = true; + ToggleSimpleSkin(simpleSkin); + data = GetComponentInParent<CharacterData>(); + if (!simpleSkin) + { + GameObject gameObject = Object.Instantiate(PlayerSkinBank.GetPlayerSkinColors(data.player.playerID).gameObject, base.transform.position, base.transform.rotation, base.transform); + skins = gameObject.GetComponentsInChildren<PlayerSkinParticle>(); + } + } + } + + public void TakeDamageBlink(Vector2 damage, bool selfDamage) + { + BlinkColor(Color.white * 0.95f); + } + + public void BlinkColor(Color blinkColor) + { + if (skins != null) + { + for (int i = 0; i < skins.Length; i++) + { + skins[i].BlinkColor(blinkColor); + } + } + } + + public void InitSpriteMask(int spriteLayerID) + { + Init(); + for (int i = 0; i < skins.Length; i++) + { + skins[i].Init(spriteLayerID); + } + } + + public void ToggleSimpleSkin(bool isSimple) + { + simpleSkin = isSimple; + GetComponent<SetPlayerSpriteLayer>().ToggleSimple(isSimple); + } +} diff --git a/ROUNDS/PlayerSkinParticle.cs b/ROUNDS/PlayerSkinParticle.cs new file mode 100644 index 0000000..22c2f99 --- /dev/null +++ b/ROUNDS/PlayerSkinParticle.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +public class PlayerSkinParticle : MonoBehaviour +{ + private Color startColor1; + + private Color startColor2; + + private ParticleSystem.MainModule main; + + private ParticleSystem part; + + private ParticleSystem.Particle[] particles; + + private float counter; + + public void Init(int spriteLayerID) + { + part = GetComponent<ParticleSystem>(); + part.GetComponent<ParticleSystemRenderer>().sortingLayerID = spriteLayerID; + main = part.main; + startColor1 = main.startColor.colorMin; + startColor2 = main.startColor.colorMax; + part.Play(); + } + + private void Update() + { + counter += TimeHandler.deltaTime; + } + + private void OnEnable() + { + if ((bool)part) + { + part.Play(); + } + } + + public void BlinkColor(Color blinkColor) + { + if (!(counter < 0.1f)) + { + counter = 0f; + particles = new ParticleSystem.Particle[part.main.maxParticles]; + int num = part.GetParticles(particles); + for (int i = 0; i < num; i++) + { + particles[i].startColor = blinkColor; + } + part.SetParticles(particles, num); + } + } +} diff --git a/ROUNDS/PlayerSounds.cs b/ROUNDS/PlayerSounds.cs new file mode 100644 index 0000000..aeffb32 --- /dev/null +++ b/ROUNDS/PlayerSounds.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using Sonigon; +using UnityEngine; + +public class PlayerSounds : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterJump; + + public SoundEvent soundCharacterJumpBig; + + public SoundEvent soundCharacterJumpEnsnare; + + public SoundEvent soundCharacterLand; + + public SoundEvent soundCharacterLandBig; + + private SoundParameterIntensity parameterIntensityLand = new SoundParameterIntensity(0f); + + public SoundEvent soundCharacterStickWall; + + public SoundEvent soundCharacterStickWallBig; + + private SoundParameterIntensity parameterIntensityStickWall = new SoundParameterIntensity(0f); + + public SoundEvent soundCharacterDamageScreenEdge; + + private CharacterData data; + + private List<EnsnareEffect> ensnareEffectList = new List<EnsnareEffect>(); + + private bool ensnareEnabled; + + public void AddEnsnareEffect(EnsnareEffect ensnareEffect) + { + ensnareEffectList.Add(ensnareEffect); + } + + public void RemoveEnsnareEffect(EnsnareEffect ensnareEffect) + { + ensnareEffectList.Remove(ensnareEffect); + } + + private void Start() + { + data = GetComponent<CharacterData>(); + CharacterData characterData = data; + characterData.TouchGroundAction = (Action<float, Vector3, Vector3, Transform>)Delegate.Combine(characterData.TouchGroundAction, new Action<float, Vector3, Vector3, Transform>(TouchGround)); + CharacterData characterData2 = data; + characterData2.TouchWallAction = (Action<float, Vector3, Vector3>)Delegate.Combine(characterData2.TouchWallAction, new Action<float, Vector3, Vector3>(TouchWall)); + PlayerJump jump = data.jump; + jump.JumpAction = (Action)Delegate.Combine(jump.JumpAction, new Action(Jump)); + } + + public void Jump() + { + ensnareEnabled = false; + for (int num = ensnareEffectList.Count - 1; num >= 0; num--) + { + if (ensnareEffectList[num] == null) + { + ensnareEffectList.RemoveAt(num); + } + } + for (int i = 0; i < ensnareEffectList.Count; i++) + { + if (ensnareEffectList[i].soundEnsnareJumpChange) + { + ensnareEnabled = true; + } + } + if (ensnareEnabled) + { + if (ensnareEnabled) + { + SoundManager.Instance.Play(soundCharacterJumpEnsnare, base.transform); + } + } + else if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterJumpBig, base.transform); + } + else + { + SoundManager.Instance.Play(soundCharacterJump, base.transform); + } + } + + public void TouchGround(float sinceGrounded, Vector3 pos, Vector3 normal, Transform ground) + { + if (sinceGrounded > 0.05f) + { + parameterIntensityLand.intensity = sinceGrounded; + if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterLandBig, base.transform, parameterIntensityLand); + } + else + { + SoundManager.Instance.Play(soundCharacterLand, base.transform, parameterIntensityLand); + } + } + } + + public void TouchWall(float sinceWall, Vector3 pos, Vector3 normal) + { + float num = sinceWall; + if (data.sinceGrounded < num) + { + num = data.sinceGrounded; + } + if (num > 0.05f) + { + parameterIntensityStickWall.intensity = num; + if (data.stats.SoundTransformScaleThresholdReached()) + { + SoundManager.Instance.Play(soundCharacterStickWallBig, base.transform, parameterIntensityStickWall); + } + else + { + SoundManager.Instance.Play(soundCharacterStickWall, base.transform, parameterIntensityStickWall); + } + } + } +} diff --git a/ROUNDS/PlayerSpawnVisualEffect.cs b/ROUNDS/PlayerSpawnVisualEffect.cs new file mode 100644 index 0000000..a0f86ba --- /dev/null +++ b/ROUNDS/PlayerSpawnVisualEffect.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using UnityEngine; + +public class PlayerSpawnVisualEffect : MonoBehaviour +{ + public Dictionary<string, GameObject> visualEffects; + + public void RPCA_SpawnVisualEffect(string effect) + { + Object.Instantiate(visualEffects[effect], base.transform.position, base.transform.rotation, base.transform); + } +} diff --git a/ROUNDS/PlayerWobblePosition.cs b/ROUNDS/PlayerWobblePosition.cs new file mode 100644 index 0000000..6d05434 --- /dev/null +++ b/ROUNDS/PlayerWobblePosition.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +public class PlayerWobblePosition : MonoBehaviour +{ + private Vector3 physicsPos; + + public float drag = 15f; + + public float spring = 1000f; + + public float multiplier = 1f; + + public float prediction; + + private Vector3 velocity; + + private Player player; + + private void Start() + { + physicsPos = base.transform.position; + player = GetComponentInParent<Player>(); + } + + private void Update() + { + float num = Mathf.Clamp(TimeHandler.deltaTime, 0f, 0.03f); + Vector3 position = player.transform.position; + if (prediction > 0f) + { + position += (Vector3)player.data.playerVel.velocity * prediction; + } + velocity += (position - physicsPos) * num * spring; + velocity -= velocity * drag * num; + physicsPos += num * multiplier * velocity; + base.transform.position = physicsPos; + } +} diff --git a/ROUNDS/Point.cs b/ROUNDS/Point.cs new file mode 100644 index 0000000..aa901d5 --- /dev/null +++ b/ROUNDS/Point.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class Point : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/PointVisualizer.cs b/ROUNDS/PointVisualizer.cs new file mode 100644 index 0000000..dc2e55b --- /dev/null +++ b/ROUNDS/PointVisualizer.cs @@ -0,0 +1,292 @@ +using System.Collections; +using Sirenix.OdinInspector; +using Sonigon; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class PointVisualizer : MonoBehaviour +{ + public SoundEvent soundWinRound; + + public SoundEvent sound_UI_Arms_Race_A_Ball_Shrink_Go_To_Left_Corner; + + public SoundEvent sound_UI_Arms_Race_B_Ball_Go_Down_Then_Expand; + + public SoundEvent sound_UI_Arms_Race_C_Ball_Pop_Shake; + + public static PointVisualizer instance; + + public AnimationCurve moveCurve; + + public AnimationCurve scaleCurve; + + public float timeBetween; + + public float timeToMove = 0.2f; + + public float timeToScale = 0.2f; + + public TextMeshProUGUI text; + + public GameObject bg; + + public Transform orangeBall; + + public Transform blueBall; + + private RectTransform orangeBallRT; + + private RectTransform blueBallRT; + + public Image orangeFill; + + public Image blueFill; + + private Vector3 orangeVel; + + private Vector3 blueVel; + + private Vector3 orangeSP; + + private Vector3 blueSP; + + private float ballBaseSize = 200f; + + private float ballSmallSize = 20f; + + private float bigBallScale = 900f; + + private void Awake() + { + instance = this; + } + + private void Start() + { + orangeBallRT = orangeBall.GetComponent<RectTransform>(); + blueBallRT = blueBall.GetComponent<RectTransform>(); + orangeSP = orangeBall.GetComponent<RectTransform>().anchoredPosition; + blueSP = blueBall.GetComponent<RectTransform>().anchoredPosition; + Close(); + } + + [Button] + private void TestWinSequence() + { + StartCoroutine(DoWinSequence(2, 1, 2, 1, orangeWinner: true)); + } + + [Button] + private void TestPoint() + { + StartCoroutine(DoSequence(1, 0, orangeWinner: true)); + } + + [Button] + private void Reset() + { + StartCoroutine(DoSequence(0, 0, orangeWinner: true)); + } + + public void ResetPoints() + { + orangeFill.fillAmount = 0f; + blueFill.fillAmount = 0f; + } + + private void ResetBalls() + { + orangeBallRT.sizeDelta = Vector2.one * ballBaseSize; + blueBallRT.sizeDelta = Vector2.one * ballBaseSize; + orangeBall.GetComponent<RectTransform>().anchoredPosition = orangeSP; + blueBall.GetComponent<RectTransform>().anchoredPosition = blueSP; + orangeVel = Vector3.zero; + blueVel = Vector3.zero; + } + + public IEnumerator DoWinSequence(int orangePoints, int bluePoints, int orangeRounds, int blueRounds, bool orangeWinner) + { + yield return new WaitForSecondsRealtime(0.35f); + SoundManager.Instance.Play(soundWinRound, base.transform); + ResetBalls(); + bg.SetActive(value: true); + blueBall.gameObject.SetActive(value: true); + orangeBall.gameObject.SetActive(value: true); + yield return new WaitForSecondsRealtime(0.2f); + GamefeelManager.instance.AddUIGameFeelOverTime(10f, 0.1f); + DoShowPoints(orangePoints, bluePoints, orangeWinner); + yield return new WaitForSecondsRealtime(0.35f); + SoundManager.Instance.Play(sound_UI_Arms_Race_A_Ball_Shrink_Go_To_Left_Corner, base.transform); + float c3 = 0f; + while (c3 < timeToScale) + { + if (orangeWinner) + { + orangeBallRT.sizeDelta = Vector2.LerpUnclamped(orangeBallRT.sizeDelta, Vector2.one * ballSmallSize, scaleCurve.Evaluate(c3 / timeToScale)); + } + else + { + blueBallRT.sizeDelta = Vector2.LerpUnclamped(blueBallRT.sizeDelta, Vector2.one * ballSmallSize, scaleCurve.Evaluate(c3 / timeToScale)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + yield return new WaitForSecondsRealtime(timeBetween); + c3 = 0f; + while (c3 < timeToMove) + { + if (orangeWinner) + { + orangeBall.position = Vector3.LerpUnclamped(orangeBall.position, UIHandler.instance.roundCounterSmall.GetPointPos(0), scaleCurve.Evaluate(c3 / timeToMove)); + } + else + { + blueBall.position = Vector3.LerpUnclamped(blueBall.position, UIHandler.instance.roundCounterSmall.GetPointPos(1), scaleCurve.Evaluate(c3 / timeToMove)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + SoundManager.Instance.Play(sound_UI_Arms_Race_B_Ball_Go_Down_Then_Expand, base.transform); + if (orangeWinner) + { + orangeBall.position = UIHandler.instance.roundCounterSmall.GetPointPos(0); + } + else + { + blueBall.position = UIHandler.instance.roundCounterSmall.GetPointPos(1); + } + yield return new WaitForSecondsRealtime(timeBetween); + c3 = 0f; + while (c3 < timeToMove) + { + if (!orangeWinner) + { + orangeBall.position = Vector3.LerpUnclamped(orangeBall.position, CardChoiceVisuals.instance.transform.position, scaleCurve.Evaluate(c3 / timeToMove)); + } + else + { + blueBall.position = Vector3.LerpUnclamped(blueBall.position, CardChoiceVisuals.instance.transform.position, scaleCurve.Evaluate(c3 / timeToMove)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + if (!orangeWinner) + { + orangeBall.position = CardChoiceVisuals.instance.transform.position; + } + else + { + blueBall.position = CardChoiceVisuals.instance.transform.position; + } + yield return new WaitForSecondsRealtime(timeBetween); + c3 = 0f; + while (c3 < timeToScale) + { + if (!orangeWinner) + { + orangeBallRT.sizeDelta = Vector2.LerpUnclamped(orangeBallRT.sizeDelta, Vector2.one * bigBallScale, scaleCurve.Evaluate(c3 / timeToScale)); + } + else + { + blueBallRT.sizeDelta = Vector2.LerpUnclamped(blueBallRT.sizeDelta, Vector2.one * bigBallScale, scaleCurve.Evaluate(c3 / timeToScale)); + } + c3 += Time.unscaledDeltaTime; + yield return null; + } + SoundManager.Instance.Play(sound_UI_Arms_Race_C_Ball_Pop_Shake, base.transform); + GamefeelManager.instance.AddUIGameFeelOverTime(10f, 0.2f); + CardChoiceVisuals.instance.Show(orangeWinner ? 1 : 0); + UIHandler.instance.roundCounterSmall.UpdateRounds(orangeRounds, blueRounds); + UIHandler.instance.roundCounterSmall.UpdatePoints(0, 0); + DoShowPoints(0, 0, orangeWinner); + Close(); + } + + private void MoveTowards() + { + } + + public IEnumerator DoSequence(int currentOrange, int currentBlue, bool orangeWinner) + { + yield return new WaitForSecondsRealtime(0.45f); + SoundManager.Instance.Play(soundWinRound, base.transform); + ResetBalls(); + bg.SetActive(value: true); + blueBall.gameObject.SetActive(value: true); + orangeBall.gameObject.SetActive(value: true); + yield return new WaitForSecondsRealtime(0.2f); + GamefeelManager.instance.AddUIGameFeelOverTime(10f, 0.1f); + DoShowPoints(currentOrange, currentBlue, orangeWinner); + yield return new WaitForSecondsRealtime(1.8f); + orangeBall.GetComponent<CurveAnimation>().PlayOut(); + blueBall.GetComponent<CurveAnimation>().PlayOut(); + yield return new WaitForSecondsRealtime(0.25f); + Close(); + } + + public void DoShowPoints(int currentOrange, int currentBlue, bool orangeWinner) + { + orangeFill.fillAmount = (float)currentOrange * 0.5f; + blueFill.fillAmount = (float)currentBlue * 0.5f; + if (orangeWinner) + { + text.color = PlayerSkinBank.GetPlayerSkinColors(0).winText; + } + else + { + text.color = PlayerSkinBank.GetPlayerSkinColors(1).winText; + } + if (orangeWinner) + { + if (currentOrange > 1) + { + RoundOrange(); + } + else + { + HalfOrange(); + } + } + else if (currentBlue > 1) + { + RoundOBlue(); + } + else + { + HalfBlue(); + } + } + + private void Close() + { + text.text = ""; + bg.SetActive(value: false); + blueBall.gameObject.SetActive(value: false); + orangeBall.gameObject.SetActive(value: false); + } + + private void HalfOrange() + { + text.text = "HALF ORANGE"; + } + + private void RoundOrange() + { + text.text = "ROUND ORANGE"; + } + + private void HalfBlue() + { + text.text = "HALF BLUE"; + } + + private void RoundOBlue() + { + text.text = "ROUND BLUE"; + } + + private void Update() + { + } +} diff --git a/ROUNDS/PopUpHandler.cs b/ROUNDS/PopUpHandler.cs new file mode 100644 index 0000000..198c9b8 --- /dev/null +++ b/ROUNDS/PopUpHandler.cs @@ -0,0 +1,97 @@ +using System; +using UnityEngine; + +public class PopUpHandler : MonoBehaviour +{ + public enum YesNo + { + Yes, + No + } + + public CurveAnimation yesAnim; + + public CurveAnimation noAnim; + + public bool isPicking; + + public GeneralParticleSystem yesPart; + + public GeneralParticleSystem noPart; + + public GeneralInput playerInput; + + private Action<YesNo> fToCall; + + private YesNo currentYesNo; + + private void Start() + { + } + + public void StartPicking(Player player, Action<YesNo> functionToCall) + { + PlayerManager.instance.RevivePlayers(); + PlayerManager.instance.SetPlayersSimulated(simulated: true); + isPicking = true; + fToCall = functionToCall; + yesPart.particleSettings.color = PlayerManager.instance.GetColorFromTeam(player.teamID).winText; + noPart.particleSettings.color = PlayerManager.instance.GetColorFromTeam(player.teamID).winText; + yesPart.loop = true; + yesPart.Play(); + yesAnim.PlayIn(); + noPart.loop = true; + noPart.Play(); + } + + private void DonePicking() + { + fToCall(currentYesNo); + isPicking = false; + noPart.loop = false; + yesPart.loop = false; + } + + private void Update() + { + if (!isPicking) + { + return; + } + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + if (PlayerManager.instance.players[i].data.view.IsMine) + { + playerInput = PlayerManager.instance.players[i].data.input; + if (playerInput.stickPressDir == GeneralInput.StickDirection.Left && currentYesNo != 0) + { + currentYesNo = YesNo.Yes; + UpdateUI(); + } + if (playerInput.stickPressDir == GeneralInput.StickDirection.Right && currentYesNo != YesNo.No) + { + currentYesNo = YesNo.No; + UpdateUI(); + } + if (playerInput.acceptWasPressed) + { + DonePicking(); + } + } + } + } + + private void UpdateUI() + { + if (currentYesNo == YesNo.Yes) + { + yesAnim.PlayIn(); + noAnim.PlayOut(); + } + else + { + yesAnim.PlayOut(); + noAnim.PlayIn(); + } + } +} diff --git a/ROUNDS/Populate.cs b/ROUNDS/Populate.cs new file mode 100644 index 0000000..b59ce59 --- /dev/null +++ b/ROUNDS/Populate.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using UnityEngine; + +public class Populate : MonoBehaviour +{ + public GameObject target; + + public bool setTargetsActive; + + public bool includeTargetInList = true; + + public int times = 5; + + public List<GameObject> DoPopulate() + { + List<GameObject> list = new List<GameObject>(); + if (includeTargetInList) + { + list.Add(target); + } + for (int i = 0; i < times; i++) + { + GameObject gameObject = Object.Instantiate(target, target.transform.position, base.transform.transform.rotation, base.transform); + gameObject.transform.localScale = target.transform.localScale; + list.Add(gameObject); + if (setTargetsActive) + { + gameObject.SetActive(value: true); + } + } + return list; + } + + public List<T> DoPopulate<T>(bool addComponentIfMissing = true) where T : MonoBehaviour + { + List<T> list = new List<T>(); + if (includeTargetInList && target != null) + { + T val = target.GetComponent<T>(); + if ((Object)val == (Object)null && addComponentIfMissing) + { + val = target.AddComponent<T>(); + } + if (!((Object)val != (Object)null)) + { + Debug.LogError("Could not find component"); + return null; + } + list.Add(val); + } + for (int i = 0; i < times; i++) + { + GameObject gameObject = Object.Instantiate(target, target.transform.position, base.transform.transform.rotation, target.transform.transform.parent); + gameObject.transform.localScale = target.transform.localScale; + T val2 = gameObject.GetComponent<T>(); + if ((Object)val2 == (Object)null && addComponentIfMissing) + { + val2 = gameObject.AddComponent<T>(); + } + if ((Object)val2 != (Object)null) + { + list.Add(val2); + } + if (setTargetsActive) + { + gameObject.SetActive(value: true); + } + } + return list; + } +} diff --git a/ROUNDS/PositionNoise.cs b/ROUNDS/PositionNoise.cs new file mode 100644 index 0000000..07b6d8a --- /dev/null +++ b/ROUNDS/PositionNoise.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class PositionNoise : CardAnimation +{ + public float amount; + + public float speed = 1f; + + private float startSeed; + + private Vector3 startPos; + + private void Start() + { + startPos = base.transform.localPosition; + startSeed = Random.Range(0f, 100000f); + } + + private void Update() + { + Vector2 vector = new Vector2(Mathf.PerlinNoise(startSeed + Time.unscaledTime * speed, startSeed + Time.unscaledTime * speed - 0.5f), Mathf.PerlinNoise(startSeed + Time.unscaledTime * speed, startSeed + Time.unscaledTime * speed) - 0.5f); + base.transform.localPosition = startPos + (Vector3)vector * amount; + } +} diff --git a/ROUNDS/PowerUps.cs b/ROUNDS/PowerUps.cs new file mode 100644 index 0000000..64f3ae7 --- /dev/null +++ b/ROUNDS/PowerUps.cs @@ -0,0 +1,66 @@ +using UnityEngine; + +public class PowerUps : MonoBehaviour +{ + public GameObject weapon; + + public float damage = 1f; + + public float knockback = 1f; + + public float attackSpeed = 1f; + + public float projectileSpeed = 1f; + + public float spread; + + public float evenSpread; + + public float gravity = 1f; + + public int projectiles = 1; + + public int reflects; + + public int smartBounce; + + public int bulletPortal; + + public int randomBounces; + + public int bursts = 1; + + public float lifeSteal; + + public float projectileSize; + + public float damageAfterDistanceMultiplier = 1f; + + public float distancceForDamageAfterDistanceMultiplier = 5f; + + public float timeToReachFullMovementMultiplier; + + public ObjectsToSpawn[] objectsToSpawn; + + public bool waveMovement; + + public bool teleport; + + public bool spawnSkelletonSquare; + + public float explodeNearEnemyRange; + + public float explodeNearEnemyDamage; + + public float hitMovementMultiplier = 1f; + + private void Start() + { + EffectWeapon(weapon); + } + + private void EffectWeapon(GameObject weapon) + { + weapon.GetComponent<Gun>(); + } +} diff --git a/ROUNDS/ProjectileCollision.cs b/ROUNDS/ProjectileCollision.cs new file mode 100644 index 0000000..8833660 --- /dev/null +++ b/ROUNDS/ProjectileCollision.cs @@ -0,0 +1,86 @@ +using UnityEngine; + +public class ProjectileCollision : ProjectileHitSurface +{ + public bool scaleWithDMG; + + public float health; + + private float deathThreshold; + + private RayHitReflect reflect; + + private ChildRPC rpc; + + private float startDMG; + + private bool hasCollided; + + public GameObject sparkObject; + + private void Start() + { + rpc = GetComponentInParent<ChildRPC>(); + rpc.childRPCs.Add("KillBullet", Die); + reflect = GetComponentInParent<RayHitReflect>(); + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + if (scaleWithDMG) + { + base.transform.localScale *= (componentInParent.damage / 55f + 1f) * 0.5f; + health = componentInParent.damage; + } + startDMG = componentInParent.damage; + deathThreshold = health * 0.1f; + } + + public override HasToStop HitSurface(HitInfo hit, GameObject projectile) + { + if (Vector2.Angle(base.transform.root.forward, projectile.transform.forward) < 45f) + { + return HasToStop.HasToStop; + } + if ((bool)reflect && reflect.timeOfBounce + 0.5f > Time.time) + { + return HasToStop.HasToStop; + } + ProjectileCollision componentInChildren = projectile.GetComponentInChildren<ProjectileCollision>(); + if ((bool)componentInChildren) + { + reflect = componentInChildren.GetComponentInParent<RayHitReflect>(); + if ((bool)reflect && reflect.timeOfBounce + 0.5f > Time.time) + { + return HasToStop.HasToStop; + } + float dmg = health; + float dmg2 = componentInChildren.health; + componentInChildren.TakeDamage(dmg); + TakeDamage(dmg2); + } + return HasToStop.HasToStop; + } + + public void TakeDamage(float dmg) + { + if (!hasCollided) + { + health -= dmg; + if ((bool)rpc && health < deathThreshold) + { + rpc.CallFunction("KillBullet"); + } + } + } + + public void Die() + { + if (!hasCollided) + { + hasCollided = true; + RaycastHit2D raycastHit2D = default(RaycastHit2D); + raycastHit2D.normal = -base.transform.root.forward; + raycastHit2D.point = base.transform.position; + Object.Instantiate(sparkObject, base.transform.position, base.transform.rotation).transform.localScale = Vector3.one * ((startDMG / 55f + 1f) * 0.5f); + GetComponentInParent<ProjectileHit>().Hit(HitInfo.GetHitInfo(raycastHit2D), forceCall: true); + } + } +} diff --git a/ROUNDS/ProjectileHit.cs b/ROUNDS/ProjectileHit.cs new file mode 100644 index 0000000..1bb6175 --- /dev/null +++ b/ROUNDS/ProjectileHit.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Photon.Pun; +using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Events; + +public class ProjectileHit : RayHit +{ + [HideInInspector] + public bool canPushBox = true; + + public float force; + + public float damage; + + public float stun; + + public float percentageDamage; + + public float movementSlow; + + public float shake; + + public ObjectsToSpawn[] objectsToSpawn; + + public PlayerSkin team; + + [HideInInspector] + public Player ownPlayer; + + [HideInInspector] + public GameObject ownWeapon; + + public AnimationCurve effectOverTimeCurve; + + [HideInInspector] + public List<RayHitEffect> effects; + + private List<HealthHandler> playersHit = new List<HealthHandler>(); + + public Color projectileColor = Color.black; + + private Action hitAction; + + private Action<HitInfo> hitActionWithData; + + [HideInInspector] + public bool unblockable; + + [HideInInspector] + public bool fullSelfDamage; + + [FoldoutGroup("Special", 0)] + public UnityEvent deathEvent; + + [FoldoutGroup("Special", 0)] + public bool destroyOnBlock; + + [FoldoutGroup("Special", 0)] + public float holdPlayerFor = 0.5f; + + [FoldoutGroup("Special", 0)] + public string bulletImmunity = ""; + + private SpawnedAttack spawnedAttack; + + [HideInInspector] + public float sinceReflect = 10f; + + [HideInInspector] + public float dealDamageMultiplierr = 1f; + + internal bool hasControl; + + [HideInInspector] + public PhotonView view; + + private MoveTransform move; + + [HideInInspector] + public bool bulletCanDealDeamage = true; + + [HideInInspector] + public bool isAllowedToSpawnObjects = true; + + public bool sendCollisions = true; + + public Dictionary<string, Action> customActions = new Dictionary<string, Action>(); + + public Dictionary<string, Action<Vector2, Vector2>> customActionsV2V2 = new Dictionary<string, Action<Vector2, Vector2>>(); + + private void Start() + { + move = GetComponent<MoveTransform>(); + view = GetComponent<PhotonView>(); + effects.AddRange(GetComponentsInChildren<RayHitEffect>()); + effects.Sort((RayHitEffect p1, RayHitEffect p2) => p2.priority.CompareTo(p1.priority)); + spawnedAttack = GetComponent<SpawnedAttack>(); + if ((bool)spawnedAttack && !ownPlayer) + { + ownPlayer = spawnedAttack.spawner; + } + if ((bool)ownPlayer && !fullSelfDamage) + { + StartCoroutine(HoldPlayer(ownPlayer.GetComponent<HealthHandler>())); + } + damage *= base.transform.localScale.x; + force *= Mathf.Pow(damage / 55f, 2f); + } + + public void ResortHitEffects() + { + effects.Sort((RayHitEffect p1, RayHitEffect p2) => p2.priority.CompareTo(p1.priority)); + } + + private IEnumerator HoldPlayer(HealthHandler player) + { + if ((bool)player) + { + playersHit.Add(player); + } + yield return new WaitForSeconds(holdPlayerFor); + if (playersHit.Contains(player)) + { + playersHit.Remove(player); + } + } + + private void Update() + { + sinceReflect += TimeHandler.deltaTime; + } + + public void AddPlayerToHeld(HealthHandler health) + { + StartCoroutine(HoldPlayer(health)); + } + + public void RemoveOwnPlayerFromPlayersHit() + { + if ((bool)ownPlayer && playersHit.Contains(ownPlayer.GetComponent<HealthHandler>())) + { + playersHit.Remove(ownPlayer.GetComponent<HealthHandler>()); + } + } + + public override void Hit(HitInfo hit, bool forceCall = false) + { + int num = -1; + if ((bool)hit.transform) + { + PhotonView component = hit.transform.root.GetComponent<PhotonView>(); + if ((bool)component) + { + num = component.ViewID; + } + } + int num2 = -1; + if (num == -1) + { + Collider2D[] componentsInChildren = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i] == hit.collider) + { + num2 = i; + } + } + } + HealthHandler healthHandler = null; + if ((bool)hit.transform) + { + healthHandler = hit.transform.GetComponent<HealthHandler>(); + } + bool flag = false; + if ((bool)healthHandler) + { + if (playersHit.Contains(healthHandler)) + { + return; + } + if (view.IsMine && healthHandler.GetComponent<Block>().IsBlocking()) + { + flag = true; + } + StartCoroutine(HoldPlayer(healthHandler)); + } + if (view.IsMine || forceCall) + { + if (sendCollisions) + { + view.RPC("RPCA_DoHit", RpcTarget.All, hit.point, hit.normal, (Vector2)move.velocity, num, num2, flag); + } + else + { + RPCA_DoHit(hit.point, hit.normal, move.velocity, num, num2, flag); + } + } + } + + [PunRPC] + public void RPCA_DoHit(Vector2 hitPoint, Vector2 hitNormal, Vector2 vel, int viewID = -1, int colliderID = -1, bool wasBlocked = false) + { + HitInfo hitInfo = new HitInfo(); + if ((bool)move) + { + move.velocity = vel; + } + hitInfo.point = hitPoint; + hitInfo.normal = hitNormal; + hitInfo.collider = null; + if (viewID != -1) + { + PhotonView photonView = PhotonNetwork.GetPhotonView(viewID); + hitInfo.collider = photonView.GetComponentInChildren<Collider2D>(); + hitInfo.transform = photonView.transform; + } + else if (colliderID != -1) + { + hitInfo.collider = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>()[colliderID]; + hitInfo.transform = hitInfo.collider.transform; + } + HealthHandler healthHandler = null; + if ((bool)hitInfo.transform) + { + healthHandler = hitInfo.transform.GetComponent<HealthHandler>(); + } + if (isAllowedToSpawnObjects) + { + base.transform.position = hitInfo.point; + } + if ((bool)hitInfo.collider) + { + ProjectileHitSurface component = hitInfo.collider.GetComponent<ProjectileHitSurface>(); + if ((bool)component && component.HitSurface(hitInfo, base.gameObject) == ProjectileHitSurface.HasToStop.HasToStop) + { + return; + } + } + if ((bool)healthHandler) + { + Block component2 = healthHandler.GetComponent<Block>(); + if (wasBlocked) + { + component2.DoBlock(base.gameObject, base.transform.forward, hitInfo.point); + if (destroyOnBlock) + { + DestroyMe(); + } + sinceReflect = 0f; + return; + } + CharacterStatModifiers component3 = healthHandler.GetComponent<CharacterStatModifiers>(); + if (movementSlow != 0f && !wasBlocked) + { + component3.RPCA_AddSlow(movementSlow); + } + } + float num = 1f; + PlayerVelocity playerVelocity = null; + if ((bool)hitInfo.transform) + { + playerVelocity = hitInfo.transform.GetComponentInParent<PlayerVelocity>(); + } + if ((bool)hitInfo.collider) + { + Damagable componentInParent = hitInfo.collider.GetComponentInParent<Damagable>(); + if ((bool)componentInParent) + { + if ((bool)healthHandler && percentageDamage != 0f) + { + damage += healthHandler.GetComponent<CharacterData>().maxHealth * percentageDamage; + } + if (hasControl) + { + if (bulletImmunity != "" && (bool)healthHandler) + { + healthHandler.GetComponent<PlayerImmunity>().IsImune(0.1f, (bulletCanDealDeamage ? damage : 1f) * dealDamageMultiplierr, bulletImmunity); + } + if ((bool)componentInParent.GetComponent<DamagableEvent>()) + { + componentInParent.CallTakeDamage(base.transform.forward * damage * dealDamageMultiplierr, hitInfo.point, ownWeapon, ownPlayer); + } + else + { + componentInParent.CallTakeDamage(base.transform.forward * (bulletCanDealDeamage ? damage : 1f) * dealDamageMultiplierr, hitInfo.point, ownWeapon, ownPlayer); + } + } + } + } + if ((bool)playerVelocity) + { + float num2 = 1f; + float num3 = Mathf.Clamp(playerVelocity.mass / 100f * num2, 0f, 1f) * num2; + float num4 = 1f; + playerVelocity.AddForce(-playerVelocity.velocity * 0.1f * playerVelocity.mass, ForceMode2D.Impulse); + if ((bool)healthHandler) + { + num *= 3f; + if (hasControl) + { + healthHandler.CallTakeForce(base.transform.forward * num4 * num3 * force); + } + } + } + if (isAllowedToSpawnObjects && !wasBlocked) + { + GamefeelManager.GameFeel(base.transform.forward * num * shake); + DynamicParticles.instance.PlayBulletHit(damage, base.transform, hitInfo, projectileColor); + for (int i = 0; i < objectsToSpawn.Length; i++) + { + ObjectsToSpawn.SpawnObject(base.transform, hitInfo, objectsToSpawn[i], healthHandler, team, damage, spawnedAttack, wasBlocked); + } + base.transform.position = hitInfo.point + hitInfo.normal * 0.01f; + } + if ((bool)hitInfo.transform) + { + NetworkPhysicsObject component4 = hitInfo.transform.GetComponent<NetworkPhysicsObject>(); + if ((bool)component4 && canPushBox) + { + component4.BulletPush(base.transform.forward * (force * 0.5f + damage * 100f), hitInfo.transform.InverseTransformPoint(hitInfo.point), spawnedAttack.spawner.data); + } + } + bool flag = false; + if (effects != null && effects.Count != 0) + { + for (int j = 0; j < effects.Count; j++) + { + HasToReturn num5 = effects[j].DoHitEffect(hitInfo); + if (num5 == HasToReturn.hasToReturn) + { + flag = true; + } + if (num5 == HasToReturn.hasToReturnNow) + { + return; + } + } + } + if (!flag) + { + if (hitAction != null) + { + hitAction(); + } + if (hitActionWithData != null) + { + hitActionWithData(hitInfo); + } + deathEvent.Invoke(); + DestroyMe(); + } + } + + private void DestroyMe() + { + if ((bool)view) + { + if (view.IsMine) + { + PhotonNetwork.Destroy(base.gameObject); + } + } + else + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + [PunRPC] + public void RPCA_CallCustomAction(string actionKey) + { + customActions[actionKey](); + } + + [PunRPC] + public void RPCA_CallCustomActionV2V2(string actionKey, Vector2 v1, Vector2 v2) + { + customActionsV2V2[actionKey](v1, v2); + } + + public void AddHitAction(Action action) + { + hitAction = (Action)Delegate.Combine(hitAction, action); + } + + public void AddHitActionWithData(Action<HitInfo> action) + { + hitActionWithData = (Action<HitInfo>)Delegate.Combine(hitActionWithData, action); + } +} diff --git a/ROUNDS/ProjectileHitEmpower.cs b/ROUNDS/ProjectileHitEmpower.cs new file mode 100644 index 0000000..3672ce1 --- /dev/null +++ b/ROUNDS/ProjectileHitEmpower.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +public class ProjectileHitEmpower : RayHitEffect +{ + private bool done; + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (done) + { + return HasToReturn.canContinue; + } + GetComponentInParent<SpawnedAttack>().spawner.data.block.DoBlockAtPosition(firstBlock: true, dontSetCD: true, BlockTrigger.BlockTriggerType.Empower, hit.point - (Vector2)base.transform.forward * 0.05f, onlyBlockEffects: true); + done = true; + return HasToReturn.canContinue; + } +} diff --git a/ROUNDS/ProjectileHitSurface.cs b/ROUNDS/ProjectileHitSurface.cs new file mode 100644 index 0000000..04ae8f6 --- /dev/null +++ b/ROUNDS/ProjectileHitSurface.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public abstract class ProjectileHitSurface : MonoBehaviour +{ + public enum HasToStop + { + HasToStop, + CanKeepGoing + } + + public abstract HasToStop HitSurface(HitInfo hit, GameObject projectile); +} diff --git a/ROUNDS/ProjectileHitSurfaceShield.cs b/ROUNDS/ProjectileHitSurfaceShield.cs new file mode 100644 index 0000000..1587a0c --- /dev/null +++ b/ROUNDS/ProjectileHitSurfaceShield.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class ProjectileHitSurfaceShield : ProjectileHitSurface +{ + public override HasToStop HitSurface(HitInfo hit, GameObject projectile) + { + if (Vector3.Angle(base.transform.parent.forward, projectile.transform.forward) < 90f) + { + return HasToStop.HasToStop; + } + return HasToStop.CanKeepGoing; + } +} diff --git a/ROUNDS/ProjectileInit.cs b/ROUNDS/ProjectileInit.cs new file mode 100644 index 0000000..3200eac --- /dev/null +++ b/ROUNDS/ProjectileInit.cs @@ -0,0 +1,49 @@ +using Photon.Pun; +using UnityEngine; + +public class ProjectileInit : MonoBehaviour +{ + private Gun[] guns; + + [PunRPC] + internal void RPCA_Init(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.GetPlayerWithActorID(senderID).data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + internal void OFFLINE_Init(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.players[senderID].data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + [PunRPC] + internal void RPCA_Init_SeparateGun(int senderID, int gunID, int nrOfProj, float dmgM, float randomSeed) + { + GetChildGunWithID(gunID, PlayerManager.instance.GetPlayerWithActorID(senderID).gameObject).BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + internal void OFFLINE_Init_SeparateGun(int senderID, int gunID, int nrOfProj, float dmgM, float randomSeed) + { + GetChildGunWithID(gunID, PlayerManager.instance.players[senderID].gameObject).BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed); + } + + private Gun GetChildGunWithID(int id, GameObject player) + { + if (guns == null) + { + guns = player.GetComponentsInChildren<Gun>(); + } + return guns[id]; + } + + [PunRPC] + internal void RPCA_Init_noAmmoUse(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.GetPlayerWithActorID(senderID).data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed, useAmmo: false); + } + + internal void OFFLINE_Init_noAmmoUse(int senderID, int nrOfProj, float dmgM, float randomSeed) + { + PlayerManager.instance.players[senderID].data.weaponHandler.gun.BulletInit(base.gameObject, nrOfProj, dmgM, randomSeed, useAmmo: false); + } +} diff --git a/ROUNDS/ProjectilesToSpawn.cs b/ROUNDS/ProjectilesToSpawn.cs new file mode 100644 index 0000000..e92840b --- /dev/null +++ b/ROUNDS/ProjectilesToSpawn.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine; + +[Serializable] +public class ProjectilesToSpawn +{ + public GameObject objectToSpawn; + + public int numberOfSpawns = 1; +} diff --git a/ROUNDS/Properties/AssemblyInfo.cs b/ROUNDS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bbd7eef --- /dev/null +++ b/ROUNDS/Properties/AssemblyInfo.cs @@ -0,0 +1,5 @@ +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyVersion("0.0.0.0")] diff --git a/ROUNDS/PublicInt.cs b/ROUNDS/PublicInt.cs new file mode 100644 index 0000000..98472b9 --- /dev/null +++ b/ROUNDS/PublicInt.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class PublicInt : MonoBehaviour +{ + public int theInt; +} diff --git a/ROUNDS/QuitButton.cs b/ROUNDS/QuitButton.cs new file mode 100644 index 0000000..a441c3e --- /dev/null +++ b/ROUNDS/QuitButton.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class QuitButton : MonoBehaviour +{ + public void Quit() + { + Application.Quit(); + } +} diff --git a/ROUNDS/ROUNDS.csproj b/ROUNDS/ROUNDS.csproj new file mode 100644 index 0000000..3c3f39d --- /dev/null +++ b/ROUNDS/ROUNDS.csproj @@ -0,0 +1,314 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <AssemblyName>Assembly-CSharp</AssemblyName> + <GenerateAssemblyInfo>False</GenerateAssemblyInfo> + <TargetFramework>netstandard2.1</TargetFramework> + </PropertyGroup> + <PropertyGroup> + <LangVersion>11.0</LangVersion> + <AllowUnsafeBlocks>True</AllowUnsafeBlocks> + </PropertyGroup> + <PropertyGroup /> + <ItemGroup> + <Reference Include="AmplifyColor"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\AmplifyColor.dll</HintPath> + </Reference> + <Reference Include="Assembly-CSharp-firstpass"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath> + </Reference> + <Reference Include="BitpackersASMDEF"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\BitpackersASMDEF.dll</HintPath> + </Reference> + <Reference Include="ByteConverter"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\ByteConverter.dll</HintPath> + </Reference> + <Reference Include="EmoCompressUtilsASMDEF"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\EmoCompressUtilsASMDEF.dll</HintPath> + </Reference> + <Reference Include="FloatCrusher"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\FloatCrusher.dll</HintPath> + </Reference> + <Reference Include="HalfFloatASMDEF"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\HalfFloatASMDEF.dll</HintPath> + </Reference> + <Reference Include="HalFloat"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\HalFloat.dll</HintPath> + </Reference> + <Reference Include="InControl"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\InControl.dll</HintPath> + </Reference> + <Reference Include="Mono.Security"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Mono.Security.dll</HintPath> + </Reference> + <Reference Include="Photon3Unity3D"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Photon3Unity3D.dll</HintPath> + </Reference> + <Reference Include="PhotonChat"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\PhotonChat.dll</HintPath> + </Reference> + <Reference Include="PhotonRealtime"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\PhotonRealtime.dll</HintPath> + </Reference> + <Reference Include="PhotonUnityNetworking"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\PhotonUnityNetworking.dll</HintPath> + </Reference> + <Reference Include="PhotonUnityNetworking.Demos"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\PhotonUnityNetworking.Demos.dll</HintPath> + </Reference> + <Reference Include="PhotonUnityNetworking.Utilities"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\PhotonUnityNetworking.Utilities.dll</HintPath> + </Reference> + <Reference Include="PhotonWebSocket"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\PhotonWebSocket.dll</HintPath> + </Reference> + <Reference Include="QuatCompress"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\QuatCompress.dll</HintPath> + </Reference> + <Reference Include="Sirenix.OdinInspector.Attributes"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Sirenix.OdinInspector.Attributes.dll</HintPath> + </Reference> + <Reference Include="Sirenix.OdinInspector.CompatibilityLayer"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Sirenix.OdinInspector.CompatibilityLayer.dll</HintPath> + </Reference> + <Reference Include="Sirenix.Serialization"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Sirenix.Serialization.dll</HintPath> + </Reference> + <Reference Include="Sirenix.Serialization.Config"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Sirenix.Serialization.Config.dll</HintPath> + </Reference> + <Reference Include="Sirenix.Utilities"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Sirenix.Utilities.dll</HintPath> + </Reference> + <Reference Include="SonigonAudioEngine.Runtime"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\SonigonAudioEngine.Runtime.dll</HintPath> + </Reference> + <Reference Include="System.Configuration"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\System.Configuration.dll</HintPath> + </Reference> + <Reference Include="System.Diagnostics.StackTrace"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\System.Diagnostics.StackTrace.dll</HintPath> + </Reference> + <Reference Include="System.EnterpriseServices"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\System.EnterpriseServices.dll</HintPath> + </Reference> + <Reference Include="System.Globalization.Extensions"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\System.Globalization.Extensions.dll</HintPath> + </Reference> + <Reference Include="System.ServiceModel.Internals"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\System.ServiceModel.Internals.dll</HintPath> + </Reference> + <Reference Include="System.Xml.XPath.XDocument"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\System.Xml.XPath.XDocument.dll</HintPath> + </Reference> + <Reference Include="Unity.Analytics.DataPrivacy"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Unity.Analytics.DataPrivacy.dll</HintPath> + </Reference> + <Reference Include="Unity.Analytics.StandardEvents"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Unity.Analytics.StandardEvents.dll</HintPath> + </Reference> + <Reference Include="Unity.Postprocessing.Runtime"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Unity.Postprocessing.Runtime.dll</HintPath> + </Reference> + <Reference Include="Unity.TextMeshPro"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\Unity.TextMeshPro.dll</HintPath> + </Reference> + <Reference Include="UnityEngine"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.AccessibilityModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.AIModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.AIModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.AnimationModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.AnimationModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ARModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ARModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.AssetBundleModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.AudioModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.AudioModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.BaselibModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.BaselibModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ClothModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ClothModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ClusterInputModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ClusterInputModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ClusterRendererModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ClusterRendererModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.CoreModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.CoreModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.CrashReportingModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.CrashReportingModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.DirectorModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.DirectorModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.FileSystemHttpModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.FileSystemHttpModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.GameCenterModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.GameCenterModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.GridModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.GridModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.HotReloadModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.HotReloadModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ImageConversionModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ImageConversionModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.IMGUIModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.InputModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.InputModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.JSONSerializeModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.JSONSerializeModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.LocalizationModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.LocalizationModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.Networking"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.Networking.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ParticleSystemModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.PerformanceReportingModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.PerformanceReportingModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.Physics2DModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.Physics2DModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.PhysicsModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ProfilerModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ProfilerModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.Purchasing"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.Purchasing.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.ScreenCaptureModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.ScreenCaptureModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.SharedInternalsModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.SharedInternalsModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.SpatialTracking"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.SpatialTracking.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.SpriteMaskModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.SpriteMaskModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.SpriteShapeModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.SpriteShapeModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.StreamingModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.StreamingModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.StyleSheetsModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.StyleSheetsModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.SubstanceModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.SubstanceModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TerrainModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TerrainModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TerrainPhysicsModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TerrainPhysicsModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TextCoreModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TextRenderingModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TilemapModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TilemapModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.Timeline"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.Timeline.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TimelineModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TimelineModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.TLSModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.TLSModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UI"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UI.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UIElementsModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UIModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UIModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UmbraModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UmbraModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UNETModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UNETModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityAnalyticsModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityAnalyticsModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityConnectModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityConnectModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityTestProtocolModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityTestProtocolModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityWebRequestAssetBundleModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityWebRequestAssetBundleModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityWebRequestAudioModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityWebRequestModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityWebRequestTextureModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityWebRequestTextureModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.UnityWebRequestWWWModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.VehiclesModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.VehiclesModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.VFXModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.VFXModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.VideoModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.VideoModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.VRModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.VRModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.WindModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.WindModule.dll</HintPath> + </Reference> + <Reference Include="UnityEngine.XRModule"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\UnityEngine.XRModule.dll</HintPath> + </Reference> + <Reference Include="websocket-sharp"> + <HintPath>C:\Program Files (x86)\Steam\steamapps\common\ROUNDS\Rounds_Data\Managed\websocket-sharp.dll</HintPath> + </Reference> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/ROUNDS/ROUNDS.sln b/ROUNDS/ROUNDS.sln new file mode 100644 index 0000000..bf51249 --- /dev/null +++ b/ROUNDS/ROUNDS.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33213.308 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ROUNDS", "ROUNDS.csproj", "{5CF6872B-A812-4D53-B272-8BF2DF30AEC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5CF6872B-A812-4D53-B272-8BF2DF30AEC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CF6872B-A812-4D53-B272-8BF2DF30AEC0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CF6872B-A812-4D53-B272-8BF2DF30AEC0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CF6872B-A812-4D53-B272-8BF2DF30AEC0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AEBCC7CF-5EC9-45BD-A8C4-7EB11DB24D63} + EndGlobalSection +EndGlobal diff --git a/ROUNDS/RadarShot.cs b/ROUNDS/RadarShot.cs new file mode 100644 index 0000000..ad589db --- /dev/null +++ b/ROUNDS/RadarShot.cs @@ -0,0 +1,61 @@ +using System.Collections; +using UnityEngine; + +public class RadarShot : MonoBehaviour +{ + private WeaponHandler wh; + + private Player player; + + public ParticleSystem[] boops; + + public float range = 12f; + + private void Start() + { + wh = GetComponentInParent<WeaponHandler>(); + player = GetComponentInParent<Player>(); + } + + public void Go() + { + Player closestPlayerInTeam = PlayerManager.instance.GetClosestPlayerInTeam(base.transform.position, PlayerManager.instance.GetOtherTeam(player.teamID), needVision: true); + if ((bool)closestPlayerInTeam && Vector2.Distance(player.transform.position, closestPlayerInTeam.transform.position) < range) + { + StartCoroutine(FollowTarget(closestPlayerInTeam)); + if (player.data.view.IsMine) + { + StartCoroutine(ShootAttacks(closestPlayerInTeam, GetComponent<AttackLevel>().attackLevel)); + } + } + } + + private IEnumerator ShootAttacks(Player target, int shots) + { + for (int i = 0; i < shots; i++) + { + yield return new WaitForSeconds(0.1f); + wh.gun.forceShootDir = wh.gun.GetRangeCompensation(Vector3.Distance(target.transform.position, player.transform.position)) * Vector3.up + target.transform.position - player.transform.position; + wh.gun.Attack(0f, forceAttack: true, 1f, 1f, useAmmo: false); + wh.gun.forceShootDir = Vector3.zero; + } + } + + private IEnumerator FollowTarget(Player target) + { + for (int i = 0; i < boops.Length; i++) + { + boops[i].Play(); + } + float c = 0f; + while (c < 1f) + { + c += TimeHandler.deltaTime; + for (int j = 0; j < boops.Length; j++) + { + boops[j].transform.position = target.transform.position; + } + yield return null; + } + } +} diff --git a/ROUNDS/Rage.cs b/ROUNDS/Rage.cs new file mode 100644 index 0000000..0e514dd --- /dev/null +++ b/ROUNDS/Rage.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class Rage : MonoBehaviour +{ + private Player player; + + private AttackLevel level; + + public AnimationCurve curve; + + public AnimationCurve partCurve; + + private ParticleSystem.EmissionModule part; + + private void Start() + { + player = GetComponentInParent<Player>(); + level = GetComponentInParent<AttackLevel>(); + part = GetComponentInChildren<ParticleSystem>().emission; + player.data.SetWobbleObjectChild(GetComponentInChildren<ParticleSystem>().transform); + } + + private void Update() + { + float healthPercentage = player.data.HealthPercentage; + player.data.stats.rageSpeed = Mathf.Pow(curve.Evaluate(healthPercentage), level.LevelScale()); + part.rateOverTime = partCurve.Evaluate(player.data.stats.rageSpeed); + } +} diff --git a/ROUNDS/RayCastTrail.cs b/ROUNDS/RayCastTrail.cs new file mode 100644 index 0000000..4d508bd --- /dev/null +++ b/ROUNDS/RayCastTrail.cs @@ -0,0 +1,106 @@ +using System.Collections; +using System.Linq; +using UnityEngine; + +public class RayCastTrail : MonoBehaviour +{ + public LayerMask mask; + + public LayerMask playerMask; + + public LayerMask ignoreWallsMask; + + public int teamID = -1; + + private float timeAtSpawn; + + public float size; + + public float extraSize; + + private MoveTransform move; + + private Vector3 lastPos; + + private RayHit rayHit; + + private Rigidbody2D ignoredRig; + + private void Awake() + { + timeAtSpawn = Time.time; + } + + private void Start() + { + rayHit = GetComponent<RayHit>(); + ProjectileHit component = GetComponent<ProjectileHit>(); + if ((bool)component) + { + size = Mathf.Clamp(Mathf.Pow(component.damage, 0.85f) / 400f, 0f, 100f) + 0.3f + extraSize; + } + move = GetComponent<MoveTransform>(); + lastPos = base.transform.position; + } + + private void OnEnable() + { + lastPos = base.transform.position; + } + + private void Update() + { + RaycastHit2D[] first = Physics2D.RaycastAll(lastPos, base.transform.position - lastPos, Vector3.Distance(base.transform.position, lastPos), mask); + RaycastHit2D[] second = Physics2D.CircleCastAll(lastPos, size, base.transform.position - lastPos, Vector3.Distance(base.transform.position, lastPos), playerMask); + RaycastHit2D[] array = first.Concat(second).ToArray(); + RaycastHit2D raycastHit2D = default(RaycastHit2D); + raycastHit2D.distance = float.PositiveInfinity; + for (int i = 0; i < array.Length; i++) + { + if (!array[i] || array[i].transform.root == base.transform.root) + { + continue; + } + Player component = array[i].transform.root.GetComponent<Player>(); + if ((!component || component.playerID != teamID || !(timeAtSpawn + 0.2f >= Time.time)) && (!ignoredRig || !(ignoredRig == array[i].rigidbody))) + { + ProjectileHitSurface component2 = array[i].collider.GetComponent<ProjectileHitSurface>(); + if ((!component2 || component2.HitSurface(HitInfo.GetHitInfo(array[i]), base.gameObject) != 0) && array[i].distance < raycastHit2D.distance) + { + raycastHit2D = array[i]; + } + } + } + if ((bool)raycastHit2D.transform) + { + rayHit.Hit(HitInfo.GetHitInfo(raycastHit2D)); + } + if ((bool)GridVisualizer.instance) + { + GridVisualizer.instance.BulletCall(base.transform.position); + } + lastPos = base.transform.position; + } + + public void WasBlocked() + { + timeAtSpawn = 0f; + } + + public void MoveRay() + { + lastPos = base.transform.position; + } + + public void IgnoreRigFor(Rigidbody2D rig, float time) + { + StartCoroutine(DoIgnoreRigFor(rig, time)); + } + + private IEnumerator DoIgnoreRigFor(Rigidbody2D rig, float time) + { + ignoredRig = rig; + yield return new WaitForSeconds(time); + ignoredRig = null; + } +} diff --git a/ROUNDS/RayHit.cs b/ROUNDS/RayHit.cs new file mode 100644 index 0000000..22dce01 --- /dev/null +++ b/ROUNDS/RayHit.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class RayHit : MonoBehaviour +{ + public abstract void Hit(HitInfo hit, bool forceCall = false); +} diff --git a/ROUNDS/RayHitBash.cs b/ROUNDS/RayHitBash.cs new file mode 100644 index 0000000..e56603e --- /dev/null +++ b/ROUNDS/RayHitBash.cs @@ -0,0 +1,80 @@ +using UnityEngine; + +public class RayHitBash : RayHitEffect +{ + public float triggerChancePerTenDamage = 0.1f; + + public float baseTriggerChance = 0.2f; + + [Space(15f)] + public float stunMultiplier = 1f; + + public float stunTimePerTenDamage = 0.1f; + + public float baseStunTime = 1f; + + public bool cannotPermaStun; + + [Space(15f)] + public float stunTimeThreshold = 0.2f; + + public float stunTimeExponent = 1f; + + public float multiplierPerTenMeterTravelled; + + private MoveTransform move; + + private float multiplier = 1f; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + multiplier = base.transform.localScale.x; + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (!hit.transform) + { + return HasToReturn.canContinue; + } + StunHandler component = hit.transform.GetComponent<StunHandler>(); + if ((bool)component) + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + float num = 25f; + if ((bool)componentInParent) + { + num = componentInParent.damage; + } + float num2 = triggerChancePerTenDamage * num * 0.1f; + num2 += baseTriggerChance; + if (Random.value < num2) + { + float num3 = baseStunTime + stunTimePerTenDamage * num * 0.1f; + SetMultiplier(); + num3 *= stunMultiplier; + num3 = Mathf.Pow(num3, stunTimeExponent); + num3 *= multiplier; + if (cannotPermaStun) + { + num3 = Mathf.Clamp(num3, 0f, GetComponentInParent<SpawnedAttack>().spawner.data.weaponHandler.gun.attackSpeed * GetComponentInParent<SpawnedAttack>().spawner.data.stats.attackSpeedMultiplier + 0.3f); + } + if (num3 > stunTimeThreshold) + { + component.AddStun(num3); + } + } + } + return HasToReturn.canContinue; + } + + private void SetMultiplier() + { + float distanceTravelled = move.distanceTravelled; + if (multiplierPerTenMeterTravelled != 0f) + { + stunMultiplier = distanceTravelled * multiplierPerTenMeterTravelled * 0.1f; + } + } +} diff --git a/ROUNDS/RayHitBulletSound.cs b/ROUNDS/RayHitBulletSound.cs new file mode 100644 index 0000000..0e3d86c --- /dev/null +++ b/ROUNDS/RayHitBulletSound.cs @@ -0,0 +1,60 @@ +using Sonigon; +using UnityEngine; + +public class RayHitBulletSound : RayHitEffect +{ + [Header("Sound Settings")] + public bool disableImpact; + + public bool playLocalImpact; + + public SoundEvent soundLocalImpact; + + public bool localImpactVelocityToIntensity; + + private ProjectileHit projectileHit; + + private RayHitReflect rayHitReflect; + + private MoveTransform moveTransform; + + private SoundParameterIntensity soundIntensity = new SoundParameterIntensity(); + + private void Start() + { + projectileHit = GetComponent<ProjectileHit>(); + rayHitReflect = GetComponent<RayHitReflect>(); + moveTransform = GetComponent<MoveTransform>(); + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (disableImpact) + { + return HasToReturn.canContinue; + } + if (localImpactVelocityToIntensity) + { + soundIntensity.intensity = moveTransform.velocity.magnitude; + } + if (playLocalImpact) + { + if (soundLocalImpact != null && hit.collider != null && hit.collider.tag != "Player") + { + if (localImpactVelocityToIntensity) + { + SoundManager.Instance.PlayAtPosition(soundLocalImpact, SoundManager.Instance.GetTransform(), hit.point, soundIntensity); + } + else + { + SoundManager.Instance.PlayAtPosition(soundLocalImpact, SoundManager.Instance.GetTransform(), hit.point); + } + } + } + else + { + projectileHit.ownPlayer.data.weaponHandler.gun.soundGun.PlayImpact(hit, rayHitReflect); + } + return HasToReturn.canContinue; + } +} diff --git a/ROUNDS/RayHitDrill.cs b/ROUNDS/RayHitDrill.cs new file mode 100644 index 0000000..db2ee90 --- /dev/null +++ b/ROUNDS/RayHitDrill.cs @@ -0,0 +1,124 @@ +using UnityEngine; + +public class RayHitDrill : RayHitEffect +{ + public float metersOfDrilling = 1f; + + private MoveTransform move; + + private ProjectileHit proj; + + public bool mainDrill; + + private ChildRPC rpc; + + private int sinceDrill = 10; + + public float speedModFlat = 0.5f; + + public float speedMod = 0.1f; + + private bool done; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + proj = GetComponentInParent<ProjectileHit>(); + proj.canPushBox = false; + RayHitDrill[] componentsInChildren = base.transform.root.GetComponentsInChildren<RayHitDrill>(); + if (componentsInChildren.Length == 1) + { + mainDrill = true; + } + bool flag = false; + int num = -1; + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].mainDrill) + { + flag = true; + num = i; + } + } + if (flag) + { + if (componentsInChildren[num] != this) + { + componentsInChildren[num].metersOfDrilling += metersOfDrilling; + } + } + else + { + mainDrill = true; + } + if (mainDrill) + { + rpc = GetComponentInParent<ChildRPC>(); + rpc.childRPCsVector2.Add("DrillStop", RPCA_Deactivate); + } + } + + private void Update() + { + if (mainDrill && proj.view.IsMine) + { + if (sinceDrill > 2 && !proj.isAllowedToSpawnObjects) + { + rpc.CallFunction("DrillStop", base.transform.position); + } + sinceDrill++; + } + } + + public void RPCA_Deactivate(Vector2 tpPos) + { + base.transform.position = tpPos; + proj.isAllowedToSpawnObjects = true; + move.simulationSpeed /= speedModFlat; + move.simulationSpeed *= move.localForce.magnitude * speedMod; + proj.sendCollisions = true; + base.transform.GetChild(0).gameObject.SetActive(value: false); + if (metersOfDrilling < 2f) + { + metersOfDrilling = -1f; + } + } + + private void OnDestroy() + { + if (mainDrill && !proj.isAllowedToSpawnObjects) + { + Object.Instantiate(GetComponentInChildren<ParticleSystem>(includeInactive: true).gameObject, base.transform.position, base.transform.rotation).SetActive(value: true); + } + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (!mainDrill) + { + return HasToReturn.canContinue; + } + if (proj.isAllowedToSpawnObjects) + { + base.transform.root.position = hit.point; + move.simulationSpeed *= speedModFlat; + move.simulationSpeed /= move.localForce.magnitude * speedMod; + base.transform.GetChild(0).gameObject.SetActive(value: true); + base.transform.GetComponentInChildren<TrailRenderer>().Clear(); + } + sinceDrill = 0; + proj.isAllowedToSpawnObjects = false; + proj.sendCollisions = false; + metersOfDrilling -= move.velocity.magnitude * TimeHandler.deltaTime * move.simulationSpeed; + if (metersOfDrilling <= 0f) + { + done = true; + return HasToReturn.canContinue; + } + if (!hit.transform || (bool)hit.transform.root.GetComponent<Player>()) + { + return HasToReturn.canContinue; + } + return HasToReturn.hasToReturnNow; + } +} diff --git a/ROUNDS/RayHitEffect.cs b/ROUNDS/RayHitEffect.cs new file mode 100644 index 0000000..647dfa8 --- /dev/null +++ b/ROUNDS/RayHitEffect.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public abstract class RayHitEffect : MonoBehaviour +{ + public int priority; + + public abstract HasToReturn DoHitEffect(HitInfo hit); +} diff --git a/ROUNDS/RayHitPoison.cs b/ROUNDS/RayHitPoison.cs new file mode 100644 index 0000000..240f2eb --- /dev/null +++ b/ROUNDS/RayHitPoison.cs @@ -0,0 +1,36 @@ +using Sonigon; +using UnityEngine; + +public class RayHitPoison : RayHitEffect +{ + [Header("Sounds")] + public SoundEvent soundEventDamageOverTime; + + [Header("Settings")] + public float time = 2f; + + public float interval = 0.5f; + + public Color color = Color.red; + + private void Start() + { + GetComponentInParent<ProjectileHit>().bulletCanDealDeamage = false; + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if (!hit.transform) + { + return HasToReturn.canContinue; + } + RayHitPoison[] componentsInChildren = base.transform.root.GetComponentsInChildren<RayHitPoison>(); + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + DamageOverTime component = hit.transform.GetComponent<DamageOverTime>(); + if ((bool)component) + { + component.TakeDamageOverTime(componentInParent.damage * base.transform.forward / componentsInChildren.Length, base.transform.position, time, interval, color, soundEventDamageOverTime, GetComponentInParent<ProjectileHit>().ownWeapon, GetComponentInParent<ProjectileHit>().ownPlayer); + } + return HasToReturn.canContinue; + } +} diff --git a/ROUNDS/RayHitReflect.cs b/ROUNDS/RayHitReflect.cs new file mode 100644 index 0000000..182aa73 --- /dev/null +++ b/ROUNDS/RayHitReflect.cs @@ -0,0 +1,61 @@ +using System; +using UnityEngine; + +public class RayHitReflect : RayHitEffect +{ + private MoveTransform move; + + private ProjectileHit projHit; + + public int reflects = 1; + + public float speedM = 1f; + + public float dmgM = 1f; + + [HideInInspector] + public float timeOfBounce = -10000f; + + public Action<HitInfo> reflectAction; + + private void Start() + { + move = GetComponent<MoveTransform>(); + projHit = GetComponent<ProjectileHit>(); + } + + public override HasToReturn DoHitEffect(HitInfo hit) + { + if ((bool)hit.transform && (bool)hit.transform.GetComponent<Player>()) + { + reflects -= 10; + } + if (reflects <= 0) + { + return HasToReturn.canContinue; + } + if (reflectAction != null) + { + reflectAction(hit); + } + move.velocity = Vector2.Reflect(move.velocity, hit.normal); + move.velocity *= speedM; + projHit.damage *= dmgM; + projHit.shake *= dmgM; + if (dmgM > 1f) + { + float num = dmgM - 1f; + num *= 0.6f; + dmgM = num + 1f; + ScaleTrailFromDamage componentInChildren = GetComponentInChildren<ScaleTrailFromDamage>(); + if ((bool)componentInChildren) + { + componentInChildren.Rescale(); + } + } + timeOfBounce = Time.time; + base.transform.position = (Vector3)hit.point + move.velocity.normalized * 0.1f; + reflects--; + return HasToReturn.hasToReturn; + } +} diff --git a/ROUNDS/RaycastForward.cs b/ROUNDS/RaycastForward.cs new file mode 100644 index 0000000..14d176f --- /dev/null +++ b/ROUNDS/RaycastForward.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class RaycastForward : MonoBehaviour +{ + public LayerMask mask; + + public float distance = 100f; + + public RaycastHit2D hit; + + private void LateUpdate() + { + hit = Physics2D.Raycast(base.transform.position, base.transform.forward, distance, mask); + } +} diff --git a/ROUNDS/RaycastSetScale.cs b/ROUNDS/RaycastSetScale.cs new file mode 100644 index 0000000..5c60b4c --- /dev/null +++ b/ROUNDS/RaycastSetScale.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class RaycastSetScale : MonoBehaviour +{ + private RaycastForward raycast; + + private void Start() + { + raycast = GetComponent<RaycastForward>(); + } + + private void LateUpdate() + { + if ((bool)raycast.hit.transform) + { + base.transform.localScale = new Vector3(base.transform.localScale.x, base.transform.localScale.y, raycast.hit.distance); + } + else + { + base.transform.localScale = new Vector3(base.transform.localScale.x, base.transform.localScale.y, raycast.distance); + } + } +} diff --git a/ROUNDS/ReflectEvent.cs b/ROUNDS/ReflectEvent.cs new file mode 100644 index 0000000..eb3dab6 --- /dev/null +++ b/ROUNDS/ReflectEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine.Events; + +public class ReflectEvent : RayHitEffect +{ + public UnityEvent bounceEvent; + + public override HasToReturn DoHitEffect(HitInfo hit) + { + bounceEvent.Invoke(); + return HasToReturn.canContinue; + } +} diff --git a/ROUNDS/RegenerateAfterStandStill.cs b/ROUNDS/RegenerateAfterStandStill.cs new file mode 100644 index 0000000..471aa10 --- /dev/null +++ b/ROUNDS/RegenerateAfterStandStill.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class RegenerateAfterStandStill : MonoBehaviour +{ + private CharacterData data; + + public float heal = 2f; + + private PlayerInRangeTrigger trigger; + + private void Start() + { + trigger = GetComponent<PlayerInRangeTrigger>(); + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + if (trigger.inRange) + { + data.healthHandler.Heal(heal); + } + } +} diff --git a/ROUNDS/RegionSelector.cs b/ROUNDS/RegionSelector.cs new file mode 100644 index 0000000..439279d --- /dev/null +++ b/ROUNDS/RegionSelector.cs @@ -0,0 +1,23 @@ +using TMPro; +using UnityEngine; + +public class RegionSelector : MonoBehaviour +{ + private TMP_Dropdown dropDown; + + public static string region = ""; + + private void Start() + { + dropDown = GetComponent<TMP_Dropdown>(); + region = dropDown.options[PlayerPrefs.GetInt("Region", 0)].text; + dropDown.value = PlayerPrefs.GetInt("Region", 0); + NetworkConnectionHandler.instance.hasRegionSelect = true; + } + + public void OnValueChanged() + { + PlayerPrefs.SetInt("Region", dropDown.value); + region = dropDown.options[dropDown.value].text; + } +} diff --git a/ROUNDS/ReloadTigger.cs b/ROUNDS/ReloadTigger.cs new file mode 100644 index 0000000..3a4c093 --- /dev/null +++ b/ROUNDS/ReloadTigger.cs @@ -0,0 +1,40 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class ReloadTigger : MonoBehaviour +{ + public UnityEvent reloadDoneEvent; + + public UnityEvent outOfAmmoEvent; + + private void Start() + { + CharacterStatModifiers componentInParent = GetComponentInParent<CharacterStatModifiers>(); + componentInParent.OnReloadDoneAction = (Action<int>)Delegate.Combine(componentInParent.OnReloadDoneAction, new Action<int>(OnReloadDone)); + CharacterStatModifiers componentInParent2 = GetComponentInParent<CharacterStatModifiers>(); + componentInParent2.OutOfAmmpAction = (Action<int>)Delegate.Combine(componentInParent2.OutOfAmmpAction, new Action<int>(OnOutOfAmmo)); + } + + private void OnDestroy() + { + CharacterStatModifiers componentInParent = GetComponentInParent<CharacterStatModifiers>(); + componentInParent.OnReloadDoneAction = (Action<int>)Delegate.Remove(componentInParent.OnReloadDoneAction, new Action<int>(OnReloadDone)); + CharacterStatModifiers componentInParent2 = GetComponentInParent<CharacterStatModifiers>(); + componentInParent2.OutOfAmmpAction = (Action<int>)Delegate.Remove(componentInParent2.OutOfAmmpAction, new Action<int>(OnOutOfAmmo)); + } + + private void OnReloadDone(int bulletsReloaded) + { + reloadDoneEvent.Invoke(); + } + + private void OnOutOfAmmo(int bulletsReloaded) + { + outOfAmmoEvent.Invoke(); + } + + private void Update() + { + } +} diff --git a/ROUNDS/RemoteControl.cs b/ROUNDS/RemoteControl.cs new file mode 100644 index 0000000..c0049bb --- /dev/null +++ b/ROUNDS/RemoteControl.cs @@ -0,0 +1,128 @@ +using Photon.Pun; +using Sonigon; +using SoundImplementation; +using UnityEngine; + +public class RemoteControl : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundRemoteSteeringLoop; + + private bool soundIsPlaying; + + [Header("Settings")] + public bool snap; + + public float rotateSpeed = 1f; + + private SpawnedAttack spawned; + + private MoveTransform move; + + private float startVelocity; + + private bool isOn; + + private ProjectileHit hit; + + private ParticleSystem part; + + public ParticleSystem boopPart; + + private float c; + + private PhotonView view; + + private ChildRPC childRPC; + + private void OnDestroy() + { + if (soundRemoteSteeringLoop != null && spawned != null && spawned.spawner != null && soundIsPlaying) + { + soundIsPlaying = false; + SoundStaticRemoteControl.remoteControl.AddNumberOf(spawned.spawner.transform, -1); + if (SoundStaticRemoteControl.remoteControl.GetNumberOf(spawned.spawner.transform) <= 0) + { + SoundManager.Instance.Stop(soundRemoteSteeringLoop, spawned.spawner.transform); + } + } + } + + private void Start() + { + childRPC = GetComponentInParent<ChildRPC>(); + view = GetComponentInParent<PhotonView>(); + hit = GetComponentInParent<ProjectileHit>(); + move = GetComponentInParent<MoveTransform>(); + spawned = GetComponentInParent<SpawnedAttack>(); + startVelocity = move.velocity.magnitude; + part = GetComponentInChildren<ParticleSystem>(); + GetComponentInParent<SyncProjectile>().active = true; + if (soundRemoteSteeringLoop != null && spawned != null && spawned.spawner != null && !soundIsPlaying) + { + soundIsPlaying = true; + if (SoundStaticRemoteControl.remoteControl.GetNumberOf(spawned.spawner.transform) <= 0) + { + SoundManager.Instance.Play(soundRemoteSteeringLoop, spawned.spawner.transform); + } + SoundStaticRemoteControl.remoteControl.AddNumberOf(spawned.spawner.transform, 1); + } + } + + public void ToggleOn(bool isOn) + { + } + + private void Update() + { + if (!view.IsMine) + { + return; + } + Vector3 zero = Vector3.zero; + if (spawned.spawner.data.playerActions.Device != null) + { + zero = spawned.spawner.data.input.aimDirection; + } + else + { + zero = MainCam.instance.cam.ScreenToWorldPoint(Input.mousePosition) - base.transform.position; + zero.z = 0f; + zero.Normalize(); + } + zero += Vector3.Cross(Vector3.forward, zero) * move.selectedSpread; + c += TimeHandler.deltaTime; + if (snap) + { + if (spawned.spawner.data.block.blockedThisFrame) + { + part.Play(); + move.velocity *= -1f; + base.enabled = false; + } + } + else if (zero.magnitude > 0.2f && hit.sinceReflect > 2f) + { + move.velocity = Vector3.RotateTowards(move.velocity, zero.normalized * startVelocity, rotateSpeed * TimeHandler.deltaTime, rotateSpeed * TimeHandler.deltaTime * 10f); + if (c > 0.1f) + { + boopPart.transform.parent.rotation = Quaternion.LookRotation(zero); + boopPart?.Emit(1); + c = 0f; + } + if (!isOn) + { + move.simulateGravity++; + } + isOn = true; + } + else + { + if (isOn) + { + move.simulateGravity--; + } + isOn = false; + } + } +} diff --git a/ROUNDS/RemoveAfterSeconds.cs b/ROUNDS/RemoveAfterSeconds.cs new file mode 100644 index 0000000..8232562 --- /dev/null +++ b/ROUNDS/RemoveAfterSeconds.cs @@ -0,0 +1,54 @@ +using UnityEngine; + +public class RemoveAfterSeconds : MonoBehaviour +{ + public float seconds = 3f; + + private float startSeconds; + + public bool shrink; + + public bool scaleWithScale; + + private float shrinkSpeed = 1f; + + private Vector3 startScale; + + private AnimationCurve curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + + private float counter; + + private void Start() + { + startSeconds = seconds; + startScale = base.transform.localScale; + shrinkSpeed = Random.Range(1.5f, 2.5f); + } + + private void Update() + { + seconds -= TimeHandler.deltaTime * (scaleWithScale ? (1f / base.transform.localScale.x) : 1f); + if (!(seconds < 0f)) + { + return; + } + if (shrink) + { + counter += Time.deltaTime * shrinkSpeed; + base.transform.localScale = Vector3.Lerp(startScale, Vector3.zero, curve.Evaluate(counter)); + if (counter > 1f) + { + Object.Destroy(base.gameObject); + } + } + else + { + Object.Destroy(base.gameObject); + } + } + + public void ResetCounter() + { + seconds = startSeconds; + } +} diff --git a/ROUNDS/RemoveAfterSecondsScale.cs b/ROUNDS/RemoveAfterSecondsScale.cs new file mode 100644 index 0000000..967091c --- /dev/null +++ b/ROUNDS/RemoveAfterSecondsScale.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class RemoveAfterSecondsScale : MonoBehaviour +{ + private void Start() + { + GetComponent<RemoveAfterSeconds>().seconds *= base.transform.localScale.x; + } +} diff --git a/ROUNDS/RescaleFromDamage.cs b/ROUNDS/RescaleFromDamage.cs new file mode 100644 index 0000000..f9e8a29 --- /dev/null +++ b/ROUNDS/RescaleFromDamage.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class RescaleFromDamage : MonoBehaviour +{ + private ProjectileHit hit; + + private float startScale; + + private void Start() + { + startScale = base.transform.localScale.x; + } + + public void Rescale() + { + if (!hit) + { + hit = GetComponentInParent<ProjectileHit>(); + } + if ((bool)hit) + { + base.transform.localScale = Vector3.one * startScale * (hit.damage / 55f); + } + } +} diff --git a/ROUNDS/RescaleFromDamagePart.cs b/ROUNDS/RescaleFromDamagePart.cs new file mode 100644 index 0000000..ebc37f7 --- /dev/null +++ b/ROUNDS/RescaleFromDamagePart.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +public class RescaleFromDamagePart : MonoBehaviour +{ + private ProjectileHit hit; + + private float startSize; + + private ParticleSystem part; + + private void Start() + { + part = GetComponent<ParticleSystem>(); + startSize = part.startSize; + } + + public void Rescale() + { + if (!hit) + { + hit = GetComponentInParent<ProjectileHit>(); + } + if ((bool)hit) + { + part.startSize = startSize * (hit.damage / 55f); + } + } +} diff --git a/ROUNDS/ResetBlock.cs b/ROUNDS/ResetBlock.cs new file mode 100644 index 0000000..9371a2f --- /dev/null +++ b/ROUNDS/ResetBlock.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +public class ResetBlock : MonoBehaviour +{ + private Block block; + + private void Start() + { + block = base.transform.root.GetComponent<Block>(); + } + + public void Go() + { + block.ResetCD(soundPlay: false); + } +} diff --git a/ROUNDS/RespawnEvent.cs b/ROUNDS/RespawnEvent.cs new file mode 100644 index 0000000..7abb88d --- /dev/null +++ b/ROUNDS/RespawnEvent.cs @@ -0,0 +1,19 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +public class RespawnEvent : MonoBehaviour +{ + public UnityEvent reviveEvent; + + private void Start() + { + HealthHandler healthHandler = GetComponentInParent<Player>().data.healthHandler; + healthHandler.reviveAction = (Action)Delegate.Combine(healthHandler.reviveAction, new Action(DoEvent)); + } + + public void DoEvent() + { + reviveEvent.Invoke(); + } +} diff --git a/ROUNDS/RigLookUp.cs b/ROUNDS/RigLookUp.cs new file mode 100644 index 0000000..2f62a80 --- /dev/null +++ b/ROUNDS/RigLookUp.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class RigLookUp : MonoBehaviour +{ + private Rigidbody2D rig; + + public float force; + + private void Start() + { + rig = GetComponent<Rigidbody2D>(); + } + + private void FixedUpdate() + { + rig.AddTorque(Vector3.Cross(base.transform.up, Vector3.up).normalized.z * force * rig.mass * Vector3.Angle(base.transform.up, Vector3.up), ForceMode2D.Force); + } +} diff --git a/ROUNDS/RightLeftMirrorSpring.cs b/ROUNDS/RightLeftMirrorSpring.cs new file mode 100644 index 0000000..b13966c --- /dev/null +++ b/ROUNDS/RightLeftMirrorSpring.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +public class RightLeftMirrorSpring : MonoBehaviour +{ + public Vector3 leftPos; + + private Vector3 rightPos; + + public float leftRot; + + public float rightRot; + + private Vector3 posVel; + + private float rotVel; + + public float drag = 25f; + + public float spring = 25f; + + private Holdable holdable; + + private float currentRot; + + private void Start() + { + currentRot = base.transform.localEulerAngles.z; + holdable = base.transform.root.GetComponent<Holdable>(); + rightPos = base.transform.localPosition; + } + + private void Update() + { + if ((bool)holdable && (bool)holdable.holder) + { + bool num = base.transform.root.position.x - 0.1f < holdable.holder.transform.position.x; + Vector3 vector = (num ? leftPos : rightPos); + float num2 = (num ? leftRot : rightRot); + posVel = FRILerp.Lerp(posVel, (vector - base.transform.localPosition) * spring, drag); + rotVel = FRILerp.Lerp(rotVel, (num2 - currentRot) * spring, drag); + currentRot += rotVel * TimeHandler.deltaTime; + base.transform.localPosition += posVel * TimeHandler.deltaTime; + base.transform.localEulerAngles = new Vector3(0f, 0f, currentRot); + } + } +} diff --git a/ROUNDS/RingHandler.cs b/ROUNDS/RingHandler.cs new file mode 100644 index 0000000..10ac321 --- /dev/null +++ b/ROUNDS/RingHandler.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class RingHandler : MonoBehaviour +{ + public float timeBeforeRing = 30f; + + public static RingHandler instance; + + private CodeAnimation code; + + private float counter; + + private void Awake() + { + instance = this; + } + + private void Start() + { + code = GetComponent<CodeAnimation>(); + } + + private void Update() + { + if (GameManager.instance.isPlaying) + { + if (code.currentState != 0 && counter > timeBeforeRing && !code.isPlaying) + { + code.PlayIn(); + } + counter += TimeHandler.deltaTime; + } + else + { + if (code.currentState != CodeAnimationInstance.AnimationUse.Out && !code.isPlaying) + { + code.PlayOut(); + } + counter = 0f; + } + } + + public Vector2 ClosestPoint(Vector2 pos) + { + return pos.normalized * Radius(); + } + + public float Radius() + { + return base.transform.localScale.x * 95f; + } +} diff --git a/ROUNDS/RotSpring.cs b/ROUNDS/RotSpring.cs new file mode 100644 index 0000000..402fa90 --- /dev/null +++ b/ROUNDS/RotSpring.cs @@ -0,0 +1,43 @@ +using UnityEngine; + +public class RotSpring : MonoBehaviour +{ + public bool x; + + public bool y; + + public bool z; + + public float target; + + public float spring; + + public float damper; + + private float currentValue; + + private float vel; + + private void Start() + { + if (x) + { + currentValue = base.transform.localEulerAngles.x; + } + else if (y) + { + currentValue = base.transform.localEulerAngles.y; + } + else if (z) + { + currentValue = base.transform.localEulerAngles.z; + } + } + + private void Update() + { + vel = FRILerp.Lerp(vel, (target - currentValue) * spring, damper); + currentValue += vel * TimeHandler.deltaTime; + base.transform.localEulerAngles = new Vector3(x ? currentValue : 0f, y ? currentValue : 0f, z ? currentValue : 0f); + } +} diff --git a/ROUNDS/Rotate.cs b/ROUNDS/Rotate.cs new file mode 100644 index 0000000..04f9889 --- /dev/null +++ b/ROUNDS/Rotate.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class Rotate : MonoBehaviour +{ + public float speed; + + private void Update() + { + base.transform.Rotate(Vector3.forward * speed * TimeHandler.deltaTime, Space.World); + } +} diff --git a/ROUNDS/RotatingShooter.cs b/ROUNDS/RotatingShooter.cs new file mode 100644 index 0000000..cdeef51 --- /dev/null +++ b/ROUNDS/RotatingShooter.cs @@ -0,0 +1,69 @@ +using System.Collections; +using Sirenix.OdinInspector; +using UnityEngine; + +public class RotatingShooter : MonoBehaviour +{ + private Gun gun; + + [HideInInspector] + public float charge; + + public int bulletsToFire = 10; + + private int currentBulletsToFire = 10; + + private float degreesPerBullet; + + [FoldoutGroup("Weird settings", 0)] + public bool destroyAfterAttack = true; + + [FoldoutGroup("Weird settings", 0)] + public bool disableTrailRenderer = true; + + private AttackLevel level; + + private void Start() + { + level = GetComponentInParent<AttackLevel>(); + gun = GetComponent<Gun>(); + if (disableTrailRenderer) + { + base.transform.root.GetComponentInChildren<TrailRenderer>(includeInactive: true).enabled = false; + } + } + + public void Attack() + { + currentBulletsToFire = bulletsToFire; + if ((bool)level) + { + currentBulletsToFire = bulletsToFire * level.attackLevel; + } + degreesPerBullet = 360f / (float)currentBulletsToFire; + StartCoroutine(RotateAndShoot()); + } + + private IEnumerator RotateAndShoot() + { + int shotsToMake = Mathf.Clamp(Mathf.RoundToInt(0.5f / gun.attackSpeed), 1, 5); + for (int i = 0; i < shotsToMake; i++) + { + for (int num = currentBulletsToFire; num > 0; num--) + { + base.transform.localEulerAngles = new Vector3(0f, (float)num * degreesPerBullet, 0f); + gun.Attack(gun.currentCharge, forceAttack: true); + } + if (shotsToMake > i) + { + yield return new WaitForSeconds(0.1f); + } + } + base.transform.localEulerAngles = new Vector3(0f, 0f, 0f); + yield return null; + if (destroyAfterAttack) + { + Object.Destroy(base.transform.root.gameObject); + } + } +} diff --git a/ROUNDS/RotationHandler.cs b/ROUNDS/RotationHandler.cs new file mode 100644 index 0000000..121bda8 --- /dev/null +++ b/ROUNDS/RotationHandler.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class RotationHandler : MonoBehaviour +{ + private CharacterData data; + + private PlayerVelocity rig; + + public float torque; + + private void Start() + { + data = GetComponent<CharacterData>(); + rig = GetComponent<PlayerVelocity>(); + } + + private void FixedUpdate() + { + rig.AddTorque(torque * TimeHandler.timeScale * (Vector3.Angle(Vector3.up, base.transform.up) * Vector3.Cross(Vector3.up, base.transform.up).normalized).z); + } +} diff --git a/ROUNDS/RoundCounter.cs b/ROUNDS/RoundCounter.cs new file mode 100644 index 0000000..6666a25 --- /dev/null +++ b/ROUNDS/RoundCounter.cs @@ -0,0 +1,124 @@ +using UnityEngine; +using UnityEngine.UI; + +public class RoundCounter : MonoBehaviour +{ + public int p1Rounds; + + public int p2Rounds; + + public int p1Points; + + public int p2Points; + + public Transform p1Parent; + + public Transform p2Parent; + + public Color offColor; + + public Populate p1Populate; + + public Populate p2Populate; + + private int roundsNeeded; + + private void Start() + { + p1Parent.gameObject.SetActive(value: true); + p2Parent.gameObject.SetActive(value: true); + } + + public void UpdateRounds(int r1, int r2) + { + p1Rounds = r1; + p2Rounds = r2; + ReDraw(); + } + + private void Clear() + { + for (int i = 0; i < p1Parent.childCount; i++) + { + if (p1Populate.transform.GetChild(i).gameObject.activeSelf) + { + Object.Destroy(p1Populate.transform.GetChild(i).gameObject); + } + } + for (int j = 0; j < p2Parent.childCount; j++) + { + if (p2Populate.transform.GetChild(j).gameObject.activeSelf) + { + Object.Destroy(p2Populate.transform.GetChild(j).gameObject); + } + } + } + + private void Populate() + { + p1Populate.times = roundsNeeded; + p1Populate.DoPopulate(); + p2Populate.times = roundsNeeded; + p2Populate.DoPopulate(); + } + + public void UpdatePoints(int p1, int p2) + { + p1Points = p1; + p2Points = p2; + ReDraw(); + } + + private void ReDraw() + { + for (int i = 0; i < p1Parent.childCount; i++) + { + if (p1Rounds + p1Points > i) + { + p1Parent.GetChild(i).GetComponentInChildren<Image>().color = PlayerSkinBank.GetPlayerSkinColors(0).winText; + if (p1Rounds > i) + { + p1Parent.GetChild(i).localScale = Vector3.one; + } + } + else + { + p1Parent.GetChild(i).GetComponentInChildren<Image>().color = offColor; + p1Parent.GetChild(i).localScale = Vector3.one * 0.3f; + } + } + for (int j = 0; j < p2Parent.childCount; j++) + { + if (p2Rounds + p2Points > j) + { + p2Parent.GetChild(j).GetComponentInChildren<Image>().color = PlayerSkinBank.GetPlayerSkinColors(1).winText; + if (p2Rounds > j) + { + p2Parent.GetChild(j).localScale = Vector3.one; + } + } + else + { + p2Parent.GetChild(j).GetComponentInChildren<Image>().color = offColor; + p2Parent.GetChild(j).localScale = Vector3.one * 0.3f; + } + } + } + + internal Vector3 GetPointPos(int teamID) + { + if (teamID == 0) + { + return p1Parent.GetChild(p1Rounds).transform.position; + } + return p2Parent.GetChild(p2Rounds).transform.position; + } + + internal void SetNumberOfRounds(int roundsToWinGame) + { + roundsNeeded = roundsToWinGame; + Clear(); + Populate(); + ReDraw(); + } +} diff --git a/ROUNDS/RoundModifier.cs b/ROUNDS/RoundModifier.cs new file mode 100644 index 0000000..d1c1ac6 --- /dev/null +++ b/ROUNDS/RoundModifier.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Round")] +public class RoundModifier : ProceduralImageModifier +{ + public override Vector4 CalculateRadius(Rect imageRect) + { + float num = Mathf.Min(imageRect.width, imageRect.height) * 0.5f; + return new Vector4(num, num, num, num); + } +} diff --git a/ROUNDS/Rounds/FakeParticle.cs b/ROUNDS/Rounds/FakeParticle.cs new file mode 100644 index 0000000..99b91ab --- /dev/null +++ b/ROUNDS/Rounds/FakeParticle.cs @@ -0,0 +1,63 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +namespace Rounds; + +[ExecuteInEditMode] +public class FakeParticle : MonoBehaviour +{ + [OnValueChanged("OnChangedValue", false)] + public float m_ScaleFactor = 1f; + + private Material m_material; + + private SpriteRenderer m_renderer; + + private MaterialPropertyBlock m_propertyBlock; + + private void OnEnable() + { + m_renderer = GetComponent<SpriteRenderer>(); + m_propertyBlock = new MaterialPropertyBlock(); + if (m_material == null) + { + m_material = FakeParticleDB.GetParticleMaterial(); + } + if (m_renderer == null) + { + Debug.LogError("No Sprite Renderer on " + base.gameObject.name + " and it's needed for a FakeParticle.", base.gameObject); + } + else + { + OnChangedValueInit(); + } + } + + private void Update() + { + OnChangedValue(); + } + + private void OnDisable() + { + m_renderer.material = FakeParticleDB.GetDefaultMaterial(); + } + + private void OnChangedValue() + { + m_renderer.material = m_material; + m_renderer.GetPropertyBlock(m_propertyBlock); + m_propertyBlock.SetFloat("_ScaleFactor", m_ScaleFactor); + m_propertyBlock.SetFloat("_Offset", Random.Range(0, 1000)); + m_renderer.SetPropertyBlock(m_propertyBlock); + } + + private void OnChangedValueInit() + { + m_renderer.material = m_material; + m_renderer.GetPropertyBlock(m_propertyBlock); + m_propertyBlock.SetFloat("_ScaleFactor", m_ScaleFactor); + m_propertyBlock.SetFloat("_Offset", Random.Range(0, 1000)); + m_renderer.SetPropertyBlock(m_propertyBlock); + } +} diff --git a/ROUNDS/RunSmoke.cs b/ROUNDS/RunSmoke.cs new file mode 100644 index 0000000..6e45d62 --- /dev/null +++ b/ROUNDS/RunSmoke.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +public class RunSmoke : MonoBehaviour +{ + private CharacterData data; + + private ParticleSystem part; + + private float c; + + private bool groundedLastFrame; + + private ParticleSystem.MainModule partVel; + + private bool didTryToEmit; + + private Vector3 vel; + + private void Start() + { + part = GetComponent<ParticleSystem>(); + data = GetComponentInParent<CharacterData>(); + partVel = part.main; + } + + private void Update() + { + didTryToEmit = false; + if (data.isGrounded && Mathf.Abs(data.playerVel.velocity.x) > 5f) + { + base.transform.position = new Vector3(data.transform.position.x, data.groundPos.y, 5f); + Go(); + } + else if (data.isWallGrab && data.wallDistance < 0.7f && data.playerVel.velocity.magnitude > 5f) + { + base.transform.position = new Vector3(data.wallPos.x, data.transform.position.y, 5f); + Go(); + } + if (didTryToEmit) + { + vel = Vector3.Lerp(vel, data.playerVel.velocity, TimeHandler.deltaTime * 2f); + } + else + { + vel = Vector3.Lerp(vel, Vector3.zero, TimeHandler.deltaTime * 10f); + } + } + + private void Go() + { + didTryToEmit = true; + c += TimeHandler.deltaTime; + if (c > 0.02f) + { + c = 0f; + float num = 2f; + part.transform.rotation = Quaternion.LookRotation(vel); + partVel.startSpeedMultiplier = data.playerVel.velocity.magnitude * num; + part.Emit(2); + } + } +} diff --git a/ROUNDS/SFLight.cs b/ROUNDS/SFLight.cs new file mode 100644 index 0000000..8ff6e38 --- /dev/null +++ b/ROUNDS/SFLight.cs @@ -0,0 +1,350 @@ +using System.Collections.Generic; +using UnityEngine; + +[RequireComponent(typeof(RectTransform))] +public class SFLight : MonoBehaviour +{ + private class VertexArray + { + public int capacity; + + public int size; + + public Vector3[] verts; + + public Vector4[] tangents; + + public Vector2[] uvs; + + public int[] tris; + + public VertexArray(int segments) + { + capacity = segments; + size = 0; + verts = new Vector3[segments * 4]; + tangents = new Vector4[segments * 4]; + uvs = new Vector2[segments * 4]; + tris = new int[segments * 6]; + } + } + + [Tooltip("The radius of the light source. Larger lights cast softer shadows.")] + public float _radius = 0.5f; + + [Tooltip("The brightness of the light. (Ignored when using non-linear light blending.) Allows for colors brighter than 1.0 in HDR lighting situations.")] + public float _intensity = 1f; + + [Tooltip("The color of the light.")] + public Color _color = Color.white; + + [Tooltip("The shape of the light.")] + public Texture2D _cookieTexture; + + [Tooltip("Which layers cast shadows.")] + public LayerMask _shadowLayers = -1; + + [Tooltip("Allows the light cookie to move off the light plane. Use gently as it can cause shadows to look weird.")] + public bool _parallaxLight; + + private RectTransform _rt; + + public static List<SFLight> _lights = new List<SFLight>(); + + private Rect _cullBounds; + + private static int GROWTH_NUM = 4; + + private static int GROWTH_DENOM = 3; + + private static VertexArray[] vertexArrays = new VertexArray[40]; + + public float radius + { + get + { + return _radius; + } + set + { + _radius = value; + } + } + + public float intensity + { + get + { + return _intensity; + } + set + { + _intensity = value; + } + } + + public Color color + { + get + { + return _color; + } + set + { + _color = value; + } + } + + public Texture2D cookieTexture + { + get + { + return _cookieTexture; + } + set + { + _cookieTexture = value; + } + } + + public LayerMask shadowLayers + { + get + { + return _shadowLayers; + } + set + { + _shadowLayers = value; + } + } + + public bool parallaxLight + { + get + { + return _parallaxLight; + } + set + { + _parallaxLight = value; + } + } + + public Rect _bounds => _rt.rect; + + public Rect _CullBounds => _cullBounds; + + private void OnEnable() + { + _lights.Add(this); + } + + private void OnDisable() + { + _lights.Remove(this); + } + + public Matrix4x4 _ModelMatrix(bool forceProjection) + { + if (!_rt) + { + _rt = GetComponent<RectTransform>(); + } + Matrix4x4 localToWorldMatrix = _rt.localToWorldMatrix; + if (!_parallaxLight || forceProjection) + { + localToWorldMatrix.SetRow(2, new Vector4(0f, 0f, 1f, 0f)); + } + return localToWorldMatrix; + } + + public Matrix4x4 _CookieMatrix() + { + if (!_rt) + { + _rt = GetComponent<RectTransform>(); + } + Vector2 vector = _rt.sizeDelta / 2f; + Vector2 vector2 = Vector2.one - 2f * _rt.pivot; + Matrix4x4 identity = Matrix4x4.identity; + identity.SetRow(0, new Vector4(vector.x, 0f, 0f, vector2.x * vector.x)); + identity.SetRow(1, new Vector4(0f, vector.y, 0f, vector2.y * vector.y)); + return identity; + } + + private static Rect Union(Rect r1, Rect r2) + { + return Rect.MinMaxRect(Mathf.Min(r1.xMin, r2.xMin), Mathf.Min(r1.yMin, r2.yMin), Mathf.Max(r1.xMax, r2.xMax), Mathf.Max(r1.yMax, r2.yMax)); + } + + private static Rect QuadrantCull(Rect cull, Matrix4x4 mvp, Rect r) + { + if (!SFRenderer._FastCull(mvp, r)) + { + return cull; + } + return Union(cull, r); + } + + public Rect _CalcCullBounds(Matrix4x4 vpMatrix) + { + Matrix4x4 matrix4x = _ModelMatrix(forceProjection: true); + Matrix4x4 mvp = vpMatrix * matrix4x; + Rect rect = new Rect(0f - _radius, 0f - _radius, 2f * _radius, 2f * _radius); + Rect rect2 = _rt.rect; + Rect cull = rect; + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect2.xMin, rect2.yMin, rect.xMax, rect.yMax)); + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect.xMin, rect2.yMin, rect2.xMax, rect.yMax)); + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect2.xMin, rect.yMin, rect.xMax, rect2.yMax)); + cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect.xMin, rect.yMin, rect2.xMax, rect2.yMax)); + return _cullBounds = SFRenderer._TransformRect(matrix4x, cull); + } + + private VertexArray GetVertexArray(int segments) + { + int num = 0; + int num2 = 4; + while (segments > num2) + { + num2 = num2 * GROWTH_NUM / GROWTH_DENOM; + num++; + } + if (num >= vertexArrays.Length) + { + Debug.LogError("SFSS: Maximum vertexes per light exceeded. (" + num2 + ")"); + return null; + } + if (vertexArrays[num] == null) + { + vertexArrays[num] = new VertexArray(num2); + } + return vertexArrays[num]; + } + + private void BatchPath(SFPolygon poly, int pathIndex, Matrix4x4 t, ref int j, bool flipped, Vector3 properties, Vector3[] verts, Vector4[] tangents, Vector2[] uvs, int[] tris) + { + Vector2[] path = poly.GetPath(pathIndex); + int num; + Vector2 vector; + if (poly.looped) + { + num = 0; + vector = Transform(t, path[^1]); + } + else + { + num = 1; + vector = Transform(t, path[0]); + } + for (int i = num; i < path.Length; i++) + { + Vector2 vector2 = Transform(t, path[i]); + Vector4 vector3 = (flipped ? new Vector4(vector2.x, vector2.y, vector.x, vector.y) : new Vector4(vector.x, vector.y, vector2.x, vector2.y)); + verts[j * 4] = properties; + tangents[j * 4] = vector3; + uvs[j * 4] = new Vector2(0f, 0f); + verts[j * 4 + 1] = properties; + tangents[j * 4 + 1] = vector3; + uvs[j * 4 + 1] = new Vector2(1f, 0f); + verts[j * 4 + 2] = properties; + tangents[j * 4 + 2] = vector3; + uvs[j * 4 + 2] = new Vector2(0f, 1f); + verts[j * 4 + 3] = properties; + tangents[j * 4 + 3] = vector3; + uvs[j * 4 + 3] = new Vector2(1f, 1f); + tris[j * 6] = j * 4; + tris[j * 6 + 1] = j * 4 + 1; + tris[j * 6 + 2] = j * 4 + 2; + tris[j * 6 + 3] = j * 4 + 1; + tris[j * 6 + 4] = j * 4 + 3; + tris[j * 6 + 5] = j * 4 + 2; + j++; + vector = vector2; + } + } + + public Mesh _BuildShadowMesh(Mesh mesh, List<SFPolygon> polys, float minLightPenetration) + { + int num = 0; + for (int i = 0; i < polys.Count; i++) + { + if (((int)polys[i].shadowLayers & (int)shadowLayers) == 0) + { + continue; + } + SFPolygon sFPolygon = polys[i]; + int activePath = sFPolygon.activePath; + bool looped = sFPolygon.looped; + if (activePath >= 0) + { + num += sFPolygon.GetPath(activePath).Length - ((!looped) ? 1 : 0); + continue; + } + int pathCount = sFPolygon.pathCount; + for (int j = 0; j < pathCount; j++) + { + num += sFPolygon.GetPath(j).Length - ((!looped) ? 1 : 0); + } + } + VertexArray vertexArray = GetVertexArray(num); + Vector3[] verts = vertexArray.verts; + Vector4[] tangents = vertexArray.tangents; + Vector2[] uvs = vertexArray.uvs; + int[] tris = vertexArray.tris; + if (num == 0 || vertexArray.capacity == 0) + { + return null; + } + if (!_rt) + { + _rt = GetComponent<RectTransform>(); + } + Matrix4x4 worldToLocalMatrix = _rt.worldToLocalMatrix; + int j2 = 0; + for (int k = 0; k < polys.Count; k++) + { + SFPolygon sFPolygon2 = polys[k]; + if (((int)sFPolygon2.shadowLayers & (int)shadowLayers) == 0) + { + continue; + } + Matrix4x4 matrix4x = sFPolygon2._GetMatrix(); + Matrix4x4 t = worldToLocalMatrix * matrix4x; + bool flipped = Det2x3(matrix4x) < 0f; + float y = Mathf.Max(sFPolygon2._lightPenetration, minLightPenetration); + Vector3 properties = new Vector3(_radius, y, sFPolygon2._opacity); + int activePath2 = sFPolygon2.activePath; + if (activePath2 >= 0) + { + BatchPath(sFPolygon2, activePath2, t, ref j2, flipped, properties, verts, tangents, uvs, tris); + continue; + } + int pathCount2 = sFPolygon2.pathCount; + for (int l = 0; l < pathCount2; l++) + { + BatchPath(sFPolygon2, l, t, ref j2, flipped, properties, verts, tangents, uvs, tris); + } + } + for (int m = 6 * num; m < 6 * vertexArray.size; m++) + { + vertexArray.tris[m] = 0; + } + mesh.vertices = verts; + mesh.tangents = tangents; + mesh.uv = uvs; + mesh.triangles = tris; + vertexArray.size = num; + return mesh; + } + + private static float Det2x3(Matrix4x4 m) + { + return m[0] * m[5] - m[1] * m[4]; + } + + private static Vector2 Transform(Matrix4x4 m, Vector2 p) + { + return new Vector2(p.x * m[0] + p.y * m[4] + m[12], p.x * m[1] + p.y * m[5] + m[13]); + } +} diff --git a/ROUNDS/SFPolygon.cs b/ROUNDS/SFPolygon.cs new file mode 100644 index 0000000..c806c1c --- /dev/null +++ b/ROUNDS/SFPolygon.cs @@ -0,0 +1,338 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class SFPolygon : MonoBehaviour +{ + private Transform _t; + + private Rect _bounds; + + private Rect _worldBounds; + + [SerializeField] + private Vector2[] _verts = new Vector2[3]; + + [SerializeField] + private Vector2[][] _paths; + + public int _activePath; + + public bool _looped; + + public LayerMask _shadowLayers = -1; + + public float _lightPenetration; + + public float _opacity = 1f; + + public static List<SFPolygon> _polygons = new List<SFPolygon>(); + + public Rect _WorldBounds => _worldBounds; + + public int pathCount + { + get + { + if (_paths != null) + { + return _paths.Length + 1; + } + return 1; + } + set + { + int num = value - 1; + if (value == pathCount) + { + return; + } + if (value < 1) + { + Debug.LogError("pathCount must be positive."); + return; + } + if (value == 1) + { + _paths = null; + } + else if (_paths == null) + { + _paths = new Vector2[num][]; + for (int i = 0; i < _paths.Length; i++) + { + _paths[i] = _verts; + } + } + else + { + Vector2[][] paths = _paths; + _paths = new Vector2[num][]; + if (num > paths.Length) + { + int j; + for (j = 0; j < paths.Length; j++) + { + _paths[j] = paths[j]; + } + for (; j < num; j++) + { + _paths[j] = _verts; + } + } + else + { + for (int k = 0; k < num; k++) + { + _paths[k] = paths[k]; + } + } + } + _UpdateBounds(); + } + } + + public Vector2[] verts + { + get + { + return _verts; + } + set + { + _verts = value; + } + } + + public int activePath + { + get + { + return _activePath; + } + set + { + _activePath = value; + } + } + + public bool looped + { + get + { + return _looped; + } + set + { + _looped = value; + } + } + + public LayerMask shadowLayers + { + get + { + return _shadowLayers; + } + set + { + _shadowLayers = value; + } + } + + public float lightPenetration + { + get + { + return _lightPenetration; + } + set + { + _lightPenetration = value; + } + } + + public float opacity + { + get + { + return _opacity; + } + set + { + _opacity = value; + } + } + + public Matrix4x4 _GetMatrix() + { + if (!_t) + { + _t = base.transform; + } + return _t.localToWorldMatrix; + } + + private void PathBounds(Vector2[] path, int i0, ref float l, ref float b, ref float r, ref float t) + { + for (int j = i0; j < path.Length; j++) + { + Vector2 vector = path[j]; + l = Mathf.Min(vector.x, l); + r = Mathf.Max(vector.x, r); + b = Mathf.Min(vector.y, b); + t = Mathf.Max(vector.y, t); + } + } + + public void _UpdateBounds() + { + float l; + float r; + float b; + float t; + if (_activePath > 0) + { + Vector2 vector = GetPath(_activePath)[0]; + l = (r = vector.x); + b = (t = vector.y); + PathBounds(_verts, 1, ref l, ref b, ref r, ref t); + } + else + { + Vector2 vector2 = _verts[0]; + l = (r = vector2.x); + b = (t = vector2.y); + PathBounds(_verts, 1, ref l, ref b, ref r, ref t); + int num = pathCount; + for (int i = 1; i < num; i++) + { + PathBounds(GetPath(i), 0, ref l, ref b, ref r, ref t); + } + } + _bounds = Rect.MinMaxRect(l, b, r, t); + } + + public void _CacheWorldBounds() + { + if (!_t) + { + _t = base.transform; + } + _worldBounds = SFRenderer._TransformRect(_t.localToWorldMatrix, _bounds); + } + + public Vector2[] GetPath(int index) + { + if (index != 0) + { + return _paths[index - 1]; + } + return _verts; + } + + public void SetPath(int index, Vector2[] path) + { + SetPathRaw(index, path); + _UpdateBounds(); + } + + private void SetPathRaw(int index, Vector2[] path) + { + if (index == 0) + { + _verts = path; + } + else + { + _paths[index - 1] = path; + } + } + + private void OnEnable() + { + _polygons.Add(this); + } + + private void OnDisable() + { + _polygons.Remove(this); + } + + private void Start() + { + _UpdateBounds(); + } + + public void CopyFromCollider(Collider2D collider) + { + PolygonCollider2D polygonCollider2D = collider as PolygonCollider2D; + BoxCollider2D boxCollider2D = collider as BoxCollider2D; + if ((bool)polygonCollider2D) + { + looped = true; + int num2 = (pathCount = polygonCollider2D.pathCount); + int num3 = num2; + for (int i = 0; i < num3; i++) + { + Vector2[] path = polygonCollider2D.GetPath(i); + for (int j = 0; j < path.Length; j++) + { + path[j] += polygonCollider2D.offset; + } + Array.Reverse((Array)path); + SetPathRaw(i, path); + } + _UpdateBounds(); + } + else if ((bool)boxCollider2D) + { + SetBoxVerts(boxCollider2D.offset - 0.5f * boxCollider2D.size, boxCollider2D.offset + 0.5f * boxCollider2D.size); + } + else + { + Debug.LogWarning("CopyFromCollider() only works with polygon and box colliders."); + } + } + + public void _CopyFromCollider() + { + Collider2D component = GetComponent<Collider2D>(); + if ((bool)component) + { + CopyFromCollider(component); + return; + } + Debug.LogWarning("GameObject has no polygon or box collider. Adding default SFPolygon shape instead."); + SetBoxVerts(-Vector2.one, Vector2.one); + } + + private void SetBoxVerts(Vector2 min, Vector2 max) + { + looped = true; + pathCount = 1; + verts = new Vector2[4] + { + new Vector2(max.x, max.y), + new Vector2(max.x, min.y), + new Vector2(min.x, min.y), + new Vector2(min.x, max.y) + }; + } + + public void _FlipInsideOut(int index) + { + if (index == -1) + { + int num = pathCount; + for (int i = 0; i < num; i++) + { + Array.Reverse((Array)GetPath(i)); + } + } + else + { + Array.Reverse((Array)GetPath(index)); + } + } +} diff --git a/ROUNDS/SFRenderer.cs b/ROUNDS/SFRenderer.cs new file mode 100644 index 0000000..e19e13b --- /dev/null +++ b/ROUNDS/SFRenderer.cs @@ -0,0 +1,621 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +[ExecuteInEditMode] +public class SFRenderer : MonoBehaviour +{ + public bool _renderInSceneView = true; + + private RenderTexture _lightMap; + + private RenderTexture _ShadowMap; + + [Tooltip("Blend the lights in linear space rather than gamma space. Nonlinear blending prevents oversaturation, but can cause draw order artifacts.")] + public bool _linearLightBlending = true; + + public bool _shadows = true; + + [Tooltip("The global ambient light color- the ambient light is used to light your scene when no lights are affecting part of it. A darker grey, blue, or yellow is often a good place to start. Alpha unused. ")] + public Color _ambientLight = Color.black; + + [Tooltip("Exposure is a multiplier applied to all lights in this renderer. Use to adjust all your lights at once. Particularly useful if you're using HDR lighting, otherwise it can be used to cause oversaturation.")] + [FormerlySerializedAs("_globalDynamicRange")] + public float _exposure = 1f; + + [Tooltip("Scale of the render texture for the colored lights. Larger numbers will give you blockier lights, but will run faster. Since lighting tends to be pretty diffuse, high numbers like 8 usually look good here. Recommended values are between 8 - 32.")] + public float _lightMapScale = 8f; + + [Tooltip("Scale of the render texture for the colored lights. Larger numbers will give you blockier shadows, but will run faster. Blocky shadows tend to look worse than blocky lights, so this should usually be lower than the light map scale. Recommended values are between 2 - 8. Less if you have a lot of sharp shadows.")] + public float _shadowMapScale = 4f; + + [Tooltip("How far will light penetrate into each shadow casting object. Makes it look like objects that are casting shadows are illuminated by the lights.")] + public float _minLightPenetration = 0.2f; + + [Tooltip("Extra darkening to apply to shadows to hide precision artifacts in the seams.")] + public float _shadowCompensation = 1.01f; + + [Tooltip("The color of the fog color. The alpha controls the fog's strength.")] + public Color _fogColor = new Color(1f, 1f, 1f, 0f); + + [Tooltip("The scatter color is the color that the fog will glow when it is lit. Alpha is unused. Black disables illumination effects on the fog.")] + public Color _scatterColor = new Color(0f, 0f, 0f, 0f); + + [Tooltip("What percentage of unshadowed/shadowed light should apply to the fog. At 1.0, your shadows will be fully applied to the scattered light in your fog.")] + public float _softHardMix; + + private Rect _extents = Rect.MinMaxRect(-1f, -1f, 1f, 1f); + + private Material _shadowMaskMaterial; + + private Material _linearLightMaterial; + + private Material _softLightMaterial; + + private Material _HDRClampMaterial; + + private Material _fogMaterial; + + private Mesh _mesh; + + private bool UV_STARTS_AT_TOP; + + private static Matrix4x4 TEXTURE_FLIP_MATRIX = Matrix4x4.Scale(new Vector3(1f, -1f, 1f)); + + private RenderTextureFormat lightmapFormat = RenderTextureFormat.ARGB1555; + + private RenderTextureFormat lightmapFormatHDR = RenderTextureFormat.ARGB1555; + + private List<SFPolygon> _perLightCulledPolygons = new List<SFPolygon>(); + + private List<SFLight> _culledLights = new List<SFLight>(); + + private List<SFPolygon> _culledPolygons = new List<SFPolygon>(); + + public bool linearLightBlending + { + get + { + return _linearLightBlending; + } + set + { + _linearLightBlending = value; + } + } + + public bool shadows + { + get + { + return _shadows; + } + set + { + _shadows = value; + } + } + + public Color ambientLight + { + get + { + return _ambientLight; + } + set + { + _ambientLight = value; + } + } + + public float exposure + { + get + { + return _exposure; + } + set + { + _exposure = value; + } + } + + public float lightMapScale + { + get + { + return _lightMapScale; + } + set + { + _lightMapScale = value; + } + } + + public float shadowMapScale + { + get + { + return _shadowMapScale; + } + set + { + _shadowMapScale = value; + } + } + + public float minLightPenetration + { + get + { + return _minLightPenetration; + } + set + { + _minLightPenetration = value; + } + } + + public float shadowCompensation + { + get + { + return _shadowCompensation; + } + set + { + _shadowCompensation = Mathf.Clamp(value, 1f, 2f); + } + } + + public Color fogColor + { + get + { + return _fogColor; + } + set + { + _fogColor = value; + } + } + + public Color scatterColor + { + get + { + return _scatterColor; + } + set + { + _scatterColor = value; + } + } + + public float softHardMix + { + get + { + return _softHardMix; + } + set + { + _softHardMix = value; + } + } + + [Obsolete("Please use SFRenderer.exposure instead.")] + public float globalIlluminationScale + { + get + { + return _exposure; + } + set + { + _exposure = value; + } + } + + [Obsolete("Please use SFRenderer.exposure instead.")] + public float globalDynamicRange + { + get + { + return _exposure; + } + set + { + _exposure = value; + } + } + + public Rect extents + { + get + { + return _extents; + } + set + { + _extents = value; + } + } + + private Material shadowMaskMaterial + { + get + { + if (_shadowMaskMaterial == null) + { + _shadowMaskMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/ShadowMask")); + _shadowMaskMaterial.hideFlags = HideFlags.HideAndDontSave; + } + return _shadowMaskMaterial; + } + } + + private Material lightMaterial + { + get + { + if (_linearLightMaterial == null) + { + _linearLightMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/LightBlendLinear")); + _linearLightMaterial.hideFlags = HideFlags.HideAndDontSave; + _softLightMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/LightBlendSoft")); + _softLightMaterial.hideFlags = HideFlags.HideAndDontSave; + } + if (!_linearLightBlending) + { + return _softLightMaterial; + } + return _linearLightMaterial; + } + } + + private Material HDRClampMaterial + { + get + { + if (_HDRClampMaterial == null) + { + _HDRClampMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/HDRClamp")); + _HDRClampMaterial.hideFlags = HideFlags.HideAndDontSave; + } + return _HDRClampMaterial; + } + } + + private Material fogMaterial + { + get + { + if (_fogMaterial == null) + { + _fogMaterial = new Material(Shader.Find("Hidden/SFSoftShadows/FogLayer")); + _fogMaterial.hideFlags = HideFlags.HideAndDontSave; + } + return _fogMaterial; + } + } + + private Mesh sharedMesh + { + get + { + if (_mesh == null) + { + _mesh = new Mesh(); + _mesh.MarkDynamic(); + _mesh.hideFlags = HideFlags.HideAndDontSave; + } + return _mesh; + } + } + + private void ScenePreRender(Camera camera) + { + if (_renderInSceneView && camera.cameraType == CameraType.SceneView) + { + OnPreRender(); + } + } + + private void ScenePostRender(Camera camera) + { + if (_renderInSceneView && camera.cameraType == CameraType.SceneView) + { + OnPostRender(); + } + } + + private void OnEnable() + { + if (Application.isEditor) + { + Camera.onPreRender = (Camera.CameraCallback)Delegate.Combine(Camera.onPreRender, new Camera.CameraCallback(ScenePreRender)); + Camera.onPostRender = (Camera.CameraCallback)Delegate.Combine(Camera.onPostRender, new Camera.CameraCallback(ScenePostRender)); + } + } + + private void OnDisable() + { + if (Application.isEditor) + { + Camera.onPreRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPreRender, new Camera.CameraCallback(ScenePreRender)); + Camera.onPostRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPostRender, new Camera.CameraCallback(ScenePostRender)); + } + } + + private void Start() + { + GraphicsDeviceType graphicsDeviceType = SystemInfo.graphicsDeviceType; + UV_STARTS_AT_TOP = graphicsDeviceType == GraphicsDeviceType.Direct3D9 || graphicsDeviceType == GraphicsDeviceType.Direct3D11 || graphicsDeviceType == GraphicsDeviceType.Direct3D12 || graphicsDeviceType == GraphicsDeviceType.Metal; + if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32)) + { + lightmapFormat = RenderTextureFormat.ARGB32; + } + else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.BGRA32)) + { + lightmapFormat = RenderTextureFormat.BGRA32; + } + if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) + { + lightmapFormatHDR = RenderTextureFormat.ARGBHalf; + } + else if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)) + { + lightmapFormatHDR = RenderTextureFormat.ARGBFloat; + } + Debug.Log(string.Concat("SFSS init: ", graphicsDeviceType, ", ", UV_STARTS_AT_TOP ? "UV_STARTS_AT_TOP, " : "", lightmapFormat, ", ", lightmapFormatHDR)); + } + + private void OnDestroy() + { + if ((bool)_mesh) + { + UnityEngine.Object.DestroyImmediate(_mesh); + } + } + + public static Rect _TransformRect(Matrix4x4 m, Rect r) + { + Vector4 vector = m.MultiplyPoint3x4(new Vector4(r.x + 0.5f * r.width, r.y + 0.5f * r.height, 0f, 1f)); + float num = 0.5f * Mathf.Max(Mathf.Abs(r.width * m[0] + r.height * m[4]), Mathf.Abs(r.width * m[0] - r.height * m[4])); + float num2 = 0.5f * Mathf.Max(Mathf.Abs(r.width * m[1] + r.height * m[5]), Mathf.Abs(r.width * m[1] - r.height * m[5])); + return new Rect(vector.x - num, vector.y - num2, 2f * num, 2f * num2); + } + + private static Vector2 ClampedProjection(Matrix4x4 m, float x, float y) + { + float num = Math.Max(0f, x * m[3] + y * m[7] + m[15]); + return new Vector2((x * m[0] + y * m[4] + m[12]) / num, (x * m[1] + y * m[5] + m[13]) / num); + } + + private static Rect ScissorRect(Matrix4x4 mvp, float w, float h) + { + Vector2 vector = ClampedProjection(mvp, -1f, -1f); + Vector2 vector2 = ClampedProjection(mvp, 1f, -1f); + Vector2 vector3 = ClampedProjection(mvp, 1f, 1f); + Vector2 vector4 = ClampedProjection(mvp, -1f, 1f); + float num = Mathf.Min(Mathf.Min(vector.x, vector2.x), Mathf.Min(vector3.x, vector4.x)); + float num2 = Mathf.Min(Mathf.Min(vector.y, vector2.y), Mathf.Min(vector3.y, vector4.y)); + float num3 = Mathf.Max(Mathf.Max(vector.x, vector2.x), Mathf.Max(vector3.x, vector4.x)); + float num4 = Mathf.Max(Mathf.Max(vector.y, vector2.y), Mathf.Max(vector3.y, vector4.y)); + return Rect.MinMaxRect(Mathf.Max(0f, Mathf.Floor((0.5f * num + 0.5f) * w)), Mathf.Max(0f, Mathf.Floor((0.5f * num2 + 0.5f) * h)), Mathf.Min(w, Mathf.Ceil((0.5f * num3 + 0.5f) * w)), Mathf.Min(h, Mathf.Ceil((0.5f * num4 + 0.5f) * h))); + } + + private static Matrix4x4 ClipMatrix(Rect r, float dw, float dh) + { + float num = r.x * dw - 1f; + float num2 = r.y * dh - 1f; + return Matrix4x4.Ortho(num, num + r.width * dw, num2, num2 + r.height * dh, -1f, 1f); + } + + private static void CullPolys(List<SFPolygon> polys, Rect bounds, List<SFPolygon> culledPolygons) + { + for (int i = 0; i < polys.Count; i++) + { + SFPolygon sFPolygon = polys[i]; + if (bounds.Overlaps(sFPolygon._WorldBounds)) + { + culledPolygons.Add(sFPolygon); + } + } + } + + private Matrix4x4 TextureProjectionMatrix(Matrix4x4 m) + { + m.SetRow(2, new Vector4(0f, 0f, 1f, 0f)); + Matrix4x4 matrix4x = m.inverse; + if (UV_STARTS_AT_TOP) + { + matrix4x = TEXTURE_FLIP_MATRIX * matrix4x * TEXTURE_FLIP_MATRIX; + } + return matrix4x; + } + + private void RenderLightMap(Matrix4x4 viewMatrix, Matrix4x4 projection, Matrix4x4 vpMatrix, RenderTexture target, List<SFLight> lights, List<SFPolygon> polys, Color ambient, bool hdr) + { + int width = target.width; + int height = target.height; + Rect screenRect = new Rect(-1f, -1f, 2f, 2f); + Rect sourceRect = new Rect(0f, 0f, 1f, 1f); + Graphics.SetRenderTarget(target); + GL.Clear(clearDepth: false, clearColor: true, ambient); + for (int i = 0; i < lights.Count; i++) + { + SFLight sFLight = lights[i]; + if (!sFLight.enabled) + { + continue; + } + Matrix4x4 matrix4x = sFLight._ModelMatrix(forceProjection: false) * sFLight._CookieMatrix(); + Rect rect = ScissorRect(vpMatrix * matrix4x, width, height); + Matrix4x4 matrix4x2 = ClipMatrix(rect, 2f / (float)width, 2f / (float)height) * projection; + GL.Viewport(rect); + GL.LoadProjectionMatrix(matrix4x2); + if (polys != null && (int)sFLight._shadowLayers != 0) + { + CullPolys(polys, sFLight._CalcCullBounds(vpMatrix), _perLightCulledPolygons); + Mesh mesh = sFLight._BuildShadowMesh(sharedMesh, _perLightCulledPolygons, _minLightPenetration); + _perLightCulledPolygons.Clear(); + if (mesh != null) + { + shadowMaskMaterial.SetPass(0); + Graphics.DrawMeshNow(mesh, sFLight._ModelMatrix(forceProjection: true)); + mesh.Clear(); + } + if (hdr) + { + Graphics.DrawTexture(screenRect, Texture2D.blackTexture, HDRClampMaterial); + } + } + Texture2D texture2D = sFLight._cookieTexture; + if (!texture2D) + { + texture2D = Texture2D.whiteTexture; + } + Material material = lightMaterial; + if (_linearLightBlending) + { + material.SetFloat("_intensity", sFLight._intensity); + } + GL.LoadProjectionMatrix(TextureProjectionMatrix(matrix4x2 * viewMatrix * matrix4x)); + Graphics.DrawTexture(screenRect, texture2D, sourceRect, 0, 0, 0, 0, sFLight._color, material); + } + } + + private RenderTexture GetTexture(Camera cam, Matrix4x4 extensionInv, float downscale) + { + Vector4 vector = extensionInv * cam.pixelRect.size / downscale; + RenderTextureFormat format = (cam.allowHDR ? lightmapFormatHDR : lightmapFormat); + return RenderTexture.GetTemporary((int)vector.x, (int)vector.y, 0, format); + } + + public static bool _FastCull(Matrix4x4 mvp, Rect bounds) + { + Vector2 center = bounds.center; + Vector2 vector = 0.5f * bounds.size; + Vector4 vector2 = mvp * new Vector4(center.x, center.y, 0f, 1f); + float num = vector.x * Mathf.Abs(mvp[0]) + vector.y * Mathf.Abs(mvp[4]); + float num2 = vector.x * Mathf.Abs(mvp[1]) + vector.y * Mathf.Abs(mvp[5]); + float num3 = vector.x * Mathf.Abs(mvp[2]) + vector.y * Mathf.Abs(mvp[6]); + float num4 = Mathf.Max(0f, vector2.w + vector.x * Mathf.Abs(mvp[3]) + vector.y * Mathf.Abs(mvp[7])); + if (Mathf.Abs(vector2.x) - num < num4 && Mathf.Abs(vector2.y) - num2 < num4) + { + return Mathf.Abs(vector2.z) - num3 < num4; + } + return false; + } + + private static Rect CullLights(Matrix4x4 vpMatrix, List<SFLight> lights, List<SFLight> culledLights) + { + float num = float.PositiveInfinity; + float num2 = float.PositiveInfinity; + float num3 = float.NegativeInfinity; + float num4 = float.NegativeInfinity; + for (int i = 0; i < lights.Count; i++) + { + SFLight sFLight = lights[i]; + if (_FastCull(vpMatrix * sFLight._ModelMatrix(forceProjection: false), sFLight._bounds)) + { + culledLights.Add(sFLight); + if ((int)sFLight._shadowLayers != 0) + { + Rect rect = sFLight._CalcCullBounds(vpMatrix); + num = Mathf.Min(num, rect.xMin); + num2 = Mathf.Min(num2, rect.yMin); + num3 = Mathf.Max(num3, rect.xMax); + num4 = Mathf.Max(num4, rect.yMax); + } + } + } + return Rect.MinMaxRect(num, num2, num3, num4); + } + + private void OnPreRender() + { + Color color = _ambientLight; + color.a = 1f; + Matrix4x4 matrix4x = Matrix4x4.Ortho(_extents.xMin, _extents.xMax, _extents.yMin, _extents.yMax, 1f, -1f); + Matrix4x4 inverse = matrix4x.inverse; + RenderBuffer activeColorBuffer = Graphics.activeColorBuffer; + RenderBuffer activeDepthBuffer = Graphics.activeDepthBuffer; + Camera current = Camera.current; + bool allowHDR = current.allowHDR; + Matrix4x4 worldToCameraMatrix = current.worldToCameraMatrix; + Matrix4x4 matrix4x2 = matrix4x * current.projectionMatrix; + Matrix4x4 vpMatrix = matrix4x2 * worldToCameraMatrix; + List<SFLight> lights = SFLight._lights; + List<SFPolygon> list = SFPolygon._polygons; + if (!Application.isPlaying) + { + lights = new List<SFLight>(from o in UnityEngine.Object.FindObjectsOfType<SFLight>() + where o.isActiveAndEnabled + select o); + list = new List<SFPolygon>(from o in UnityEngine.Object.FindObjectsOfType<SFPolygon>() + where o.isActiveAndEnabled + select o); + foreach (SFPolygon item in list) + { + item._UpdateBounds(); + } + } + Rect bounds = CullLights(vpMatrix, lights, _culledLights); + GL.PushMatrix(); + _lightMap = GetTexture(current, inverse, _lightMapScale); + RenderLightMap(worldToCameraMatrix, matrix4x2, vpMatrix, _lightMap, _culledLights, null, color, allowHDR); + if (_shadows) + { + for (int i = 0; i < list.Count; i++) + { + list[i]._CacheWorldBounds(); + } + CullPolys(list, bounds, _culledPolygons); + Shader.SetGlobalFloat("_SFShadowCompensation", _shadowCompensation); + _ShadowMap = GetTexture(current, inverse, _shadowMapScale); + RenderLightMap(worldToCameraMatrix, matrix4x2, vpMatrix, _ShadowMap, _culledLights, _culledPolygons, color, allowHDR); + _culledPolygons.Clear(); + } + GL.PopMatrix(); + _culledLights.Clear(); + Graphics.SetRenderTarget(null); + GL.Viewport(current.pixelRect); + Shader.SetGlobalMatrix("_SFProjection", matrix4x * Camera.current.projectionMatrix); + Shader.SetGlobalColor("_SFAmbientLight", color); + Shader.SetGlobalFloat("_SFExposure", _exposure); + Shader.SetGlobalTexture("_SFLightMap", _lightMap); + Shader.SetGlobalTexture("_SFLightMapWithShadows", _shadows ? _ShadowMap : _lightMap); + Graphics.SetRenderTarget(activeColorBuffer, activeDepthBuffer); + } + + private void OnPostRender() + { + if (_fogColor.a + _scatterColor.r + _scatterColor.g + _scatterColor.b > 0f) + { + GL.PushMatrix(); + GL.LoadProjectionMatrix(Matrix4x4.identity); + Color value = _scatterColor; + value.a = _softHardMix; + Material material = fogMaterial; + material.SetColor("_FogColor", _fogColor); + material.SetColor("_Scatter", value); + material.SetPass(0); + Graphics.DrawTexture(new Rect(-1f, -1f, 2f, 2f), Texture2D.blackTexture, material); + GL.PopMatrix(); + } + Shader.SetGlobalColor("_SFAmbientLight", Color.white); + Shader.SetGlobalFloat("_SFExposure", 1f); + Shader.SetGlobalTexture("_SFLightMap", Texture2D.whiteTexture); + Shader.SetGlobalTexture("_SFLightMapWithShadows", Texture2D.whiteTexture); + RenderTexture.ReleaseTemporary(_lightMap); + _lightMap = null; + RenderTexture.ReleaseTemporary(_ShadowMap); + _ShadowMap = null; + } +} diff --git a/ROUNDS/SFSample.cs b/ROUNDS/SFSample.cs new file mode 100644 index 0000000..8a0d194 --- /dev/null +++ b/ROUNDS/SFSample.cs @@ -0,0 +1,73 @@ +using UnityEngine; + +[RequireComponent(typeof(Renderer))] +public class SFSample : MonoBehaviour +{ + private Material _material; + + public Vector2 _samplePosition = Vector2.zero; + + public bool _lineSample; + + public Vector2 samplePosition + { + get + { + return _samplePosition; + } + set + { + _samplePosition = value; + if ((bool)_material) + { + _material.SetVector("_SamplePosition", _samplePosition); + } + } + } + + public bool lineSample + { + get + { + return _lineSample; + } + set + { + _lineSample = value; + if ((bool)_material) + { + if (value) + { + _material.EnableKeyword("LINESAMPLE_ON"); + _material.DisableKeyword("FIXEDSAMPLEPOINT_ON"); + } + else + { + _material.DisableKeyword("LINESAMPLE_ON"); + _material.EnableKeyword("FIXEDSAMPLEPOINT_ON"); + } + } + } + } + + private void Start() + { + Renderer component = GetComponent<Renderer>(); + Material sharedMaterial = component.sharedMaterial; + if (sharedMaterial == null || sharedMaterial.shader.name != "Sprites/SFSoftShadow") + { + Debug.LogError("SFSample requires the attached renderer to be using the Sprites/SFSoftShadow shader."); + return; + } + _material = new Material(sharedMaterial); + component.material = _material; + _material.SetFloat("_SoftHardMix", sharedMaterial.GetFloat("_SoftHardMix")); + samplePosition = _samplePosition; + lineSample = _lineSample; + } + + private void OnDrawGizmosSelected() + { + Gizmos.DrawIcon(base.transform.TransformPoint(_samplePosition), "SFDotGizmo.psd"); + } +} diff --git a/ROUNDS/Saw.cs b/ROUNDS/Saw.cs new file mode 100644 index 0000000..19ebe25 --- /dev/null +++ b/ROUNDS/Saw.cs @@ -0,0 +1,83 @@ +using UnityEngine; + +public class Saw : MonoBehaviour +{ + public Player owner; + + public float range = 3f; + + public float damage = 10f; + + public float force; + + public float shake = 1f; + + public ParticleSystem[] parts; + + public Transform sparkTransform; + + private Vector3 forceDir; + + private void Start() + { + owner = base.transform.root.GetComponent<SpawnedAttack>().spawner; + } + + private void Update() + { + Player player = null; + for (int i = 0; i < PlayerManager.instance.players.Count; i++) + { + Player player2 = PlayerManager.instance.players[i]; + if (player2 != owner && Vector3.Distance(player2.transform.position, base.transform.transform.position) < range * base.transform.localScale.x) + { + player = player2; + } + } + if ((bool)player && PlayerManager.instance.CanSeePlayer(base.transform.position, player).canSee) + { + Vector3 normalized = (player.transform.position - base.transform.position).normalized; + if (damage != 0f) + { + player.data.healthHandler.TakeDamage(TimeHandler.deltaTime * damage * normalized, base.transform.position, null, owner); + } + if (force != 0f) + { + float num = Mathf.Clamp(1f - Vector2.Distance(base.transform.position, player.transform.position) / range, 0f, 1f); + ForceMultiplier component = player.GetComponent<ForceMultiplier>(); + if ((bool)component) + { + num *= component.multiplier; + } + forceDir = normalized; + forceDir.y *= 0.5f; + player.data.playerVel.AddForce(forceDir * base.transform.localScale.x * num * TimeHandler.deltaTime * force, ForceMode2D.Force); + player.data.healthHandler.TakeForce(forceDir * num * 0.0005f * TimeHandler.deltaTime * force); + } + for (int j = 0; j < parts.Length; j++) + { + if (!parts[j].isPlaying) + { + parts[j].Play(); + } + } + if ((bool)sparkTransform) + { + sparkTransform.transform.position = player.transform.position; + if (normalized != Vector3.zero) + { + sparkTransform.rotation = Quaternion.LookRotation(normalized); + } + } + GamefeelManager.GameFeel((normalized + Random.onUnitSphere).normalized * shake * TimeHandler.deltaTime * 20f); + return; + } + for (int k = 0; k < parts.Length; k++) + { + if (parts[k].isPlaying) + { + parts[k].Stop(); + } + } + } +} diff --git a/ROUNDS/ScaleEvent.cs b/ROUNDS/ScaleEvent.cs new file mode 100644 index 0000000..923132d --- /dev/null +++ b/ROUNDS/ScaleEvent.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +public class ScaleEvent : MonoBehaviour +{ + public ScaleEventInstace[] events; + + private void Start() + { + ScaleEventInstace scaleEventInstace = null; + float num = 0f; + for (int i = 0; i < events.Length; i++) + { + if (base.transform.localScale.x > events[i].threshold && events[i].threshold > num) + { + num = events[i].threshold; + scaleEventInstace = events[i]; + } + } + scaleEventInstace?.scaleEvent.Invoke(); + } +} diff --git a/ROUNDS/ScaleEventInstace.cs b/ROUNDS/ScaleEventInstace.cs new file mode 100644 index 0000000..391d8f7 --- /dev/null +++ b/ROUNDS/ScaleEventInstace.cs @@ -0,0 +1,10 @@ +using System; +using UnityEngine.Events; + +[Serializable] +public class ScaleEventInstace +{ + public UnityEvent scaleEvent; + + public float threshold = 1f; +} diff --git a/ROUNDS/ScaleShake.cs b/ROUNDS/ScaleShake.cs new file mode 100644 index 0000000..b2a25b2 --- /dev/null +++ b/ROUNDS/ScaleShake.cs @@ -0,0 +1,76 @@ +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class ScaleShake : MonoBehaviour +{ + public bool useTimeScale = true; + + public float targetScale = 1f; + + public float multiplier = 1f; + + private float velocity; + + public float drag = 1f; + + public float spring = 1f; + + public float clampVelocity; + + internal float high; + + internal float low; + + private void Update() + { + float num = Mathf.Clamp(useTimeScale ? TimeHandler.deltaTime : Time.unscaledDeltaTime, 0f, 0.02f); + if (clampVelocity != 0f) + { + velocity = Mathf.Clamp(velocity, 0f - clampVelocity, clampVelocity); + } + velocity += (targetScale - base.transform.localScale.x) * num * 50f * spring; + velocity -= drag * velocity * 20f * num; + base.transform.localScale += Vector3.one * (velocity * 10f * num); + } + + public void AddForce(float force) + { + velocity += force * multiplier * 5f; + } + + public void AddForce() + { + velocity += 1f * multiplier * 5f; + } + + public void SetTarget(float target) + { + targetScale = target; + } + + public void SetHigh() + { + targetScale = high; + } + + public void SetLow() + { + targetScale = low; + } + + public void ScaleOutRootPhoton() + { + StartCoroutine(GoAwayOutRootPhoton()); + } + + private IEnumerator GoAwayOutRootPhoton() + { + while (base.transform.localScale.x > 0f) + { + targetScale = 0f; + yield return null; + } + PhotonNetwork.Destroy(base.transform.root.gameObject); + } +} diff --git a/ROUNDS/ScaleTrailFromDamage.cs b/ROUNDS/ScaleTrailFromDamage.cs new file mode 100644 index 0000000..ffe41a8 --- /dev/null +++ b/ROUNDS/ScaleTrailFromDamage.cs @@ -0,0 +1,61 @@ +using UnityEngine; + +public class ScaleTrailFromDamage : MonoBehaviour +{ + private float startWidth; + + private float startTime; + + private void Start() + { + float num = 55f; + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + GetComponentInParent<RayCastTrail>(); + if ((bool)componentInParent) + { + num = componentInParent.damage; + } + TrailRenderer componentInChildren = GetComponentInChildren<TrailRenderer>(); + startWidth = componentInChildren.widthMultiplier; + startTime = componentInChildren.time; + if ((bool)componentInChildren) + { + componentInChildren.widthMultiplier *= (1f + num / 55f) / 2f; + componentInChildren.time *= Mathf.Clamp((1f + num / 55f) / 2f, 0f, 25f); + if (num > 100f) + { + componentInChildren.numCapVertices = 5; + } + if (num > 500f) + { + componentInChildren.numCapVertices = 10; + } + } + } + + public void Rescale() + { + float num = 55f; + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + RayCastTrail componentInParent2 = GetComponentInParent<RayCastTrail>(); + if ((bool)componentInParent) + { + num = componentInParent.damage; + } + TrailRenderer componentInChildren = GetComponentInChildren<TrailRenderer>(); + if ((bool)componentInChildren) + { + _ = componentInParent2.extraSize; + componentInChildren.widthMultiplier = startWidth * ((1f + num / 55f) / 2f); + componentInChildren.time = startTime * Mathf.Clamp((1f + num / 55f) / 2f, 0f, 25f); + if (num > 100f) + { + componentInChildren.numCapVertices = 5; + } + if (num > 100f) + { + componentInChildren.numCapVertices = 10; + } + } + } +} diff --git a/ROUNDS/ScaleWithHp.cs b/ROUNDS/ScaleWithHp.cs new file mode 100644 index 0000000..5649021 --- /dev/null +++ b/ROUNDS/ScaleWithHp.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class ScaleWithHp : MonoBehaviour +{ + private DamagableEvent dmg; + + public AnimationCurve curve; + + private void Start() + { + dmg = GetComponentInParent<DamagableEvent>(); + } + + private void Update() + { + base.transform.localScale = Vector3.one * curve.Evaluate(dmg.currentHP); + } +} diff --git a/ROUNDS/ScreenEdgeBounce.cs b/ROUNDS/ScreenEdgeBounce.cs new file mode 100644 index 0000000..21c8b69 --- /dev/null +++ b/ROUNDS/ScreenEdgeBounce.cs @@ -0,0 +1,132 @@ +using Photon.Pun; +using UnityEngine; + +public class ScreenEdgeBounce : MonoBehaviour +{ + private float sinceBounce = 1f; + + private Camera mainCam; + + private RayHitReflect reflect; + + private Vector2 lastNormal; + + private ProjectileHit projHit; + + private bool done; + + private RayHitBulletSound bulletSound; + + private PhotonView view; + + private void Start() + { + GetComponentInParent<ChildRPC>().childRPCsVector2Vector2IntInt.Add("ScreenBounce", DoHit); + view = GetComponentInParent<PhotonView>(); + bulletSound = GetComponentInParent<RayHitBulletSound>(); + projHit = GetComponentInParent<ProjectileHit>(); + ScreenEdgeBounce[] componentsInChildren = base.transform.root.GetComponentsInChildren<ScreenEdgeBounce>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (i > 0) + { + Object.Destroy(componentsInChildren[i]); + } + } + mainCam = MainCam.instance.transform.GetComponent<Camera>(); + reflect = GetComponentInParent<RayHitReflect>(); + } + + private void Update() + { + if (!view.IsMine || done) + { + return; + } + Vector3 vector = mainCam.WorldToScreenPoint(base.transform.position); + vector.x /= Screen.width; + vector.y /= Screen.height; + vector = new Vector3(Mathf.Clamp(vector.x, 0f, 1f), Mathf.Clamp(vector.y, 0f, 1f), vector.z); + if (vector.x != 0f && vector.x != 1f && vector.y != 1f && vector.y != 0f) + { + return; + } + Vector2 vector2 = Vector2.zero; + if (vector.x == 0f) + { + vector2 = Vector2.right; + } + else if (vector.x == 1f) + { + vector2 = -Vector2.right; + } + if (vector.y == 0f) + { + vector2 = Vector2.up; + } + else if (vector.y == 1f) + { + vector2 = -Vector2.up; + } + if (lastNormal == vector2 && Vector2.Angle(vector2, base.transform.forward) < 90f) + { + lastNormal = vector2; + return; + } + lastNormal = vector2; + vector.x *= Screen.width; + vector.y *= Screen.height; + RaycastHit2D raycastHit2D = default(RaycastHit2D); + raycastHit2D.normal = vector2; + raycastHit2D.point = mainCam.ScreenToWorldPoint(vector); + int num = -1; + if ((bool)raycastHit2D.transform) + { + PhotonView component = raycastHit2D.transform.root.GetComponent<PhotonView>(); + if ((bool)component) + { + num = component.ViewID; + } + } + int intData = -1; + if (num == -1) + { + Collider2D[] componentsInChildren = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i] == raycastHit2D.collider) + { + intData = i; + } + } + } + GetComponentInParent<ChildRPC>().CallFunction("ScreenBounce", raycastHit2D.point, raycastHit2D.normal, num, intData); + if (reflect.reflects <= 0) + { + done = true; + } + sinceBounce = 0f; + } + + private void DoHit(Vector2 hitPos, Vector2 hitNormal, int viewID = -1, int colliderID = -1) + { + HitInfo hitInfo = new HitInfo(); + hitInfo.point = hitPos; + hitInfo.normal = hitNormal; + hitInfo.collider = null; + if (viewID != -1) + { + PhotonView photonView = PhotonNetwork.GetPhotonView(viewID); + hitInfo.collider = photonView.GetComponentInChildren<Collider2D>(); + hitInfo.transform = photonView.transform; + } + else if (colliderID != -1) + { + hitInfo.collider = MapManager.instance.currentMap.Map.GetComponentsInChildren<Collider2D>()[colliderID]; + hitInfo.transform = hitInfo.collider.transform; + } + DynamicParticles.instance.PlayBulletHit(projHit.damage, base.transform, hitInfo, projHit.projectileColor); + bulletSound.DoHitEffect(hitInfo); + reflect.DoHitEffect(hitInfo); + } +} diff --git a/ROUNDS/Screenshaker.cs b/ROUNDS/Screenshaker.cs new file mode 100644 index 0000000..d845eae --- /dev/null +++ b/ROUNDS/Screenshaker.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +public class Screenshaker : GameFeeler +{ + public bool ignoreTimeScale; + + public float spring = 100f; + + public float damper = 100f; + + public float shakeforce = 10f; + + public float threshold; + + private Vector2 velocity; + + private float clamp = 100f; + + private void Update() + { + float num = Mathf.Clamp(ignoreTimeScale ? Time.unscaledDeltaTime : TimeHandler.deltaTime, 0f, 0.015f); + velocity -= velocity.normalized * Mathf.Pow(velocity.magnitude, 0.8f) * damper * num; + velocity -= (Vector2)base.transform.localPosition * num * spring; + base.transform.position += (Vector3)velocity * num; + } + + private void ShakeInternal(Vector2 direction) + { + if (!(direction.magnitude < threshold)) + { + direction = Vector2.ClampMagnitude(direction, clamp); + velocity += direction * shakeforce; + } + } + + public override void OnGameFeel(Vector2 feelDirection) + { + if (!ignoreTimeScale) + { + feelDirection = Vector2.ClampMagnitude(feelDirection, clamp); + ShakeInternal(feelDirection); + } + } + + public override void OnUIGameFeel(Vector2 feelDirection) + { + if (ignoreTimeScale) + { + feelDirection = Vector2.ClampMagnitude(feelDirection, clamp); + ShakeInternal(feelDirection); + } + } +} diff --git a/ROUNDS/ServerMessage.cs b/ROUNDS/ServerMessage.cs new file mode 100644 index 0000000..71a6921 --- /dev/null +++ b/ROUNDS/ServerMessage.cs @@ -0,0 +1 @@ +public delegate void ServerMessage(string message); diff --git a/ROUNDS/SetActive.cs b/ROUNDS/SetActive.cs new file mode 100644 index 0000000..5856366 --- /dev/null +++ b/ROUNDS/SetActive.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SetActive : MonoBehaviour +{ + public void DoSetActive(bool active) + { + base.gameObject.SetActive(active); + } +} diff --git a/ROUNDS/SetColorByBlockCD.cs b/ROUNDS/SetColorByBlockCD.cs new file mode 100644 index 0000000..05e0083 --- /dev/null +++ b/ROUNDS/SetColorByBlockCD.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +public class SetColorByBlockCD : MonoBehaviour +{ + private Block block; + + private SpriteRenderer spriteRend; + + public Color onCDColor; + + public Color offCDColor; + + private bool isOnCD; + + private void Start() + { + block = GetComponentInParent<Block>(); + spriteRend = GetComponent<SpriteRenderer>(); + } + + private void Update() + { + if (isOnCD != block.IsOnCD()) + { + isOnCD = block.IsOnCD(); + if (isOnCD) + { + spriteRend.color = onCDColor; + } + else + { + spriteRend.color = offCDColor; + } + } + } +} diff --git a/ROUNDS/SetEmissionOverTimeByVelocity.cs b/ROUNDS/SetEmissionOverTimeByVelocity.cs new file mode 100644 index 0000000..f8aa877 --- /dev/null +++ b/ROUNDS/SetEmissionOverTimeByVelocity.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class SetEmissionOverTimeByVelocity : MonoBehaviour +{ + private ParticleSystem part; + + public AnimationCurve curve; + + private PlayerVelocity rig; + + private void Start() + { + rig = GetComponentInParent<PlayerVelocity>(); + part = GetComponent<ParticleSystem>(); + } + + private void Update() + { + ParticleSystem.EmissionModule emission = part.emission; + emission.rateOverDistance = curve.Evaluate(rig.velocity.magnitude); + } +} diff --git a/ROUNDS/SetLocalScale.cs b/ROUNDS/SetLocalScale.cs new file mode 100644 index 0000000..4f97804 --- /dev/null +++ b/ROUNDS/SetLocalScale.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class SetLocalScale : MonoBehaviour +{ + public Vector3 localScale = Vector3.one; + + public void Set() + { + base.transform.localScale = localScale; + } +} diff --git a/ROUNDS/SetOfflineMode.cs b/ROUNDS/SetOfflineMode.cs new file mode 100644 index 0000000..bc6a98e --- /dev/null +++ b/ROUNDS/SetOfflineMode.cs @@ -0,0 +1,30 @@ +using Photon.Pun; +using UnityEngine; + +public class SetOfflineMode : MonoBehaviour +{ + public bool doIt = true; + + private void Awake() + { + if (doIt) + { + SetOffline(); + } + } + + public void SetOffline() + { + PhotonNetwork.OfflineMode = true; + PhotonNetwork.JoinRandomRoom(); + } + + public void SetOnline() + { + if (PhotonNetwork.InRoom) + { + PhotonNetwork.LeaveRoom(); + } + PhotonNetwork.OfflineMode = false; + } +} diff --git a/ROUNDS/SetParticleTimeAfterSecondsToRemove.cs b/ROUNDS/SetParticleTimeAfterSecondsToRemove.cs new file mode 100644 index 0000000..8229d6a --- /dev/null +++ b/ROUNDS/SetParticleTimeAfterSecondsToRemove.cs @@ -0,0 +1,13 @@ +using UnityEngine; + +public class SetParticleTimeAfterSecondsToRemove : MonoBehaviour +{ + private void Start() + { + ParticleSystem component = GetComponent<ParticleSystem>(); + component.Stop(); + ParticleSystem.MainModule main = component.main; + main.duration = GetComponentInParent<RemoveAfterSeconds>().seconds - main.startLifetime.constant; + component.Play(); + } +} diff --git a/ROUNDS/SetPlayerSpriteLayer.cs b/ROUNDS/SetPlayerSpriteLayer.cs new file mode 100644 index 0000000..cd0ba36 --- /dev/null +++ b/ROUNDS/SetPlayerSpriteLayer.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +public class SetPlayerSpriteLayer : MonoBehaviour +{ + private SpriteMask[] sprites; + + private bool simpleSkin; + + private void Start() + { + simpleSkin = GetComponent<PlayerSkinHandler>().simpleSkin; + Player componentInParent = GetComponentInParent<Player>(); + int num = SortingLayer.NameToID("Player" + (componentInParent.playerID + 1)); + setSpriteLayerOfChildren(GetComponentInParent<Holding>().holdable.gameObject, num); + setSpriteLayerOfChildren(base.gameObject, num); + if (!simpleSkin) + { + GetComponent<PlayerSkinHandler>().InitSpriteMask(num); + } + } + + private void setSpriteLayerOfChildren(GameObject obj, int layer) + { + sprites = obj.transform.root.GetComponentsInChildren<SpriteMask>(); + for (int i = 0; i < sprites.Length; i++) + { + if (simpleSkin) + { + sprites[i].enabled = false; + sprites[i].GetComponent<SpriteRenderer>().enabled = true; + } + else + { + sprites[i].frontSortingLayerID = layer; + sprites[i].backSortingLayerID = layer; + } + } + } + + public void ToggleSimple(bool isSimple) + { + simpleSkin = isSimple; + } +} diff --git a/ROUNDS/SetRotation.cs b/ROUNDS/SetRotation.cs new file mode 100644 index 0000000..284ccf4 --- /dev/null +++ b/ROUNDS/SetRotation.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +public class SetRotation : MonoBehaviour +{ + public float setRot; + + public float addRot; + + public float extraSetPerLevel; + + private float rot; + + private bool inited; + + private void Init() + { + if (!inited) + { + inited = true; + int attackLevel = GetComponentInParent<AttackLevel>().attackLevel; + setRot += (float)attackLevel * extraSetPerLevel; + } + } + + public void Set() + { + Init(); + rot = setRot; + base.transform.localRotation = Quaternion.Euler(new Vector3(rot, 0f, 0f)); + } + + public void Add() + { + Init(); + rot += addRot; + base.transform.localRotation = Quaternion.Euler(new Vector3(rot, 0f, 0f)); + } +} diff --git a/ROUNDS/SetScaleFromSizeAndExtraSize.cs b/ROUNDS/SetScaleFromSizeAndExtraSize.cs new file mode 100644 index 0000000..22b2849 --- /dev/null +++ b/ROUNDS/SetScaleFromSizeAndExtraSize.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class SetScaleFromSizeAndExtraSize : MonoBehaviour +{ + public float scalePerSize; + + private void Start() + { + float size = GetComponentInParent<RayCastTrail>().size; + base.transform.localScale *= size * scalePerSize; + } +} diff --git a/ROUNDS/SetScaleToZero.cs b/ROUNDS/SetScaleToZero.cs new file mode 100644 index 0000000..e72085e --- /dev/null +++ b/ROUNDS/SetScaleToZero.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SetScaleToZero : MonoBehaviour +{ + private void Start() + { + base.transform.localScale = Vector3.zero; + } +} diff --git a/ROUNDS/SetSpawnedParticleColor.cs b/ROUNDS/SetSpawnedParticleColor.cs new file mode 100644 index 0000000..fc9052b --- /dev/null +++ b/ROUNDS/SetSpawnedParticleColor.cs @@ -0,0 +1,30 @@ +using System; +using UnityEngine; + +public class SetSpawnedParticleColor : MonoBehaviour +{ + private Color myColor; + + private void Start() + { + SpawnObjects component = GetComponent<SpawnObjects>(); + component.SpawnedAction = (Action<GameObject>)Delegate.Combine(component.SpawnedAction, new Action<GameObject>(Go)); + myColor = PlayerSkinBank.GetPlayerSkinColors(GetComponentInParent<SpawnedAttack>().spawner.playerID).particleEffect; + } + + private void Go(GameObject spawned) + { + ParticleSystem[] componentsInChildren = spawned.GetComponentsInChildren<ParticleSystem>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].startColor = myColor; + } + LineEffect[] componentsInChildren2 = spawned.GetComponentsInChildren<LineEffect>(); + for (int j = 0; j < componentsInChildren2.Length; j++) + { + componentsInChildren2[j].useColorOverTime = false; + componentsInChildren2[j].GetComponent<LineRenderer>().startColor = myColor; + componentsInChildren2[j].GetComponent<LineRenderer>().endColor = myColor; + } + } +} diff --git a/ROUNDS/SetSpecificArt.cs b/ROUNDS/SetSpecificArt.cs new file mode 100644 index 0000000..b673df8 --- /dev/null +++ b/ROUNDS/SetSpecificArt.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using UnityEngine.Rendering.PostProcessing; + +public class SetSpecificArt : MonoBehaviour +{ + public PostProcessProfile profile; + + public string artName; + + public bool playOnStart; + + private void Start() + { + if (playOnStart) + { + if ((bool)profile) + { + ArtHandler.instance.ApplyPost(profile); + } + if (artName != "") + { + ArtHandler.instance.SetSpecificArt(artName); + } + } + } + + public void Go() + { + if ((bool)profile) + { + ArtHandler.instance.ApplyPost(profile); + } + if (artName != "") + { + ArtHandler.instance.SetSpecificArt(artName); + } + } +} diff --git a/ROUNDS/SetSpriteColor.cs b/ROUNDS/SetSpriteColor.cs new file mode 100644 index 0000000..8b27d60 --- /dev/null +++ b/ROUNDS/SetSpriteColor.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class SetSpriteColor : MonoBehaviour +{ + private SpriteRenderer sprite; + + public Color[] cols; + + private void Start() + { + sprite = GetComponent<SpriteRenderer>(); + } + + public void SetColor(int id) + { + sprite.color = cols[id]; + } +} diff --git a/ROUNDS/SetTeamColor.cs b/ROUNDS/SetTeamColor.cs new file mode 100644 index 0000000..479c1d3 --- /dev/null +++ b/ROUNDS/SetTeamColor.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEngine.Events; + +public class SetTeamColor : MonoBehaviour +{ + public enum ColorType + { + Main, + Background, + Particle, + WinText + } + + private SpriteRenderer m_spriteRenderer; + + private ParticleSystem m_particleSystem; + + private LineRenderer m_lineRenderer; + + public UnityEvent SetColorEvent; + + private MeshRenderer meshRend; + + public ColorType colorType; + + private void Awake() + { + m_spriteRenderer = GetComponent<SpriteRenderer>(); + meshRend = GetComponent<MeshRenderer>(); + m_lineRenderer = GetComponent<LineRenderer>(); + } + + public void Set(PlayerSkin teamColor) + { + Color color = teamColor.color; + if (colorType == ColorType.Background) + { + color = teamColor.backgroundColor; + } + if (colorType == ColorType.Particle) + { + color = teamColor.particleEffect; + } + if (colorType == ColorType.WinText) + { + color = teamColor.winText; + } + if ((bool)m_lineRenderer) + { + m_lineRenderer.startColor = color; + m_lineRenderer.endColor = color; + } + else if ((bool)m_spriteRenderer) + { + m_spriteRenderer.color = color; + } + else if ((bool)meshRend) + { + meshRend.material.color = color; + } + else + { + m_particleSystem = GetComponent<ParticleSystem>(); + if ((bool)m_particleSystem) + { + ParticleSystem.MainModule main = m_particleSystem.main; + main.startColor = color; + } + } + SetColorEvent.Invoke(); + } + + public static void TeamColorThis(GameObject go, PlayerSkin teamColor) + { + if (!(teamColor == null)) + { + SetTeamColor[] componentsInChildren = go.GetComponentsInChildren<SetTeamColor>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].Set(teamColor); + } + } + } +} diff --git a/ROUNDS/SetTeamColorFromParentPlayer.cs b/ROUNDS/SetTeamColorFromParentPlayer.cs new file mode 100644 index 0000000..26e6615 --- /dev/null +++ b/ROUNDS/SetTeamColorFromParentPlayer.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +public class SetTeamColorFromParentPlayer : MonoBehaviour +{ + private void Start() + { + Player player = GetComponentInParent<Player>(); + if (!player) + { + player = GetComponentInParent<SpawnedAttack>().spawner; + } + GetComponent<SetTeamColor>().Set(PlayerSkinBank.GetPlayerSkinColors(player.playerID)); + } +} diff --git a/ROUNDS/SetTeamColorFromSpawnedAttack.cs b/ROUNDS/SetTeamColorFromSpawnedAttack.cs new file mode 100644 index 0000000..6130323 --- /dev/null +++ b/ROUNDS/SetTeamColorFromSpawnedAttack.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SetTeamColorFromSpawnedAttack : MonoBehaviour +{ + private void Start() + { + GetComponent<SetTeamColor>().Set(PlayerSkinBank.GetPlayerSkinColors(GetComponentInParent<SpawnedAttack>().spawner.playerID)); + } +} diff --git a/ROUNDS/SetTeamColorSpecific.cs b/ROUNDS/SetTeamColorSpecific.cs new file mode 100644 index 0000000..d5e9fe8 --- /dev/null +++ b/ROUNDS/SetTeamColorSpecific.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class SetTeamColorSpecific : MonoBehaviour +{ + public Color[] colors; + + private void Start() + { + Player player = GetComponentInParent<Player>(); + if (!player) + { + player = GetComponentInParent<SpawnedAttack>().spawner; + } + ParticleSystem component = GetComponent<ParticleSystem>(); + if ((bool)component) + { + _ = component.main; + component.startColor = colors[player.playerID]; + } + LineRenderer component2 = GetComponent<LineRenderer>(); + if ((bool)component2) + { + component2.startColor = colors[player.playerID]; + component2.endColor = colors[player.playerID]; + } + } +} diff --git a/ROUNDS/SetTextColor.cs b/ROUNDS/SetTextColor.cs new file mode 100644 index 0000000..16e8a70 --- /dev/null +++ b/ROUNDS/SetTextColor.cs @@ -0,0 +1,12 @@ +using TMPro; +using UnityEngine; + +public class SetTextColor : MonoBehaviour +{ + public Color[] colors; + + public void SetColor(int id) + { + GetComponent<TextMeshProUGUI>().color = colors[id]; + } +} diff --git a/ROUNDS/ShieldCharge.cs b/ROUNDS/ShieldCharge.cs new file mode 100644 index 0000000..a2860d1 --- /dev/null +++ b/ROUNDS/ShieldCharge.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Sonigon; +using UnityEngine; + +public class ShieldCharge : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundShieldCharge; + + [Header("Settings")] + public float damagePerLevel; + + [Header("Settings")] + public float knockBackPerLevel; + + public float forcePerLevel; + + public float timePerLevel; + + public ParticleSystem hitPart; + + public float shake; + + public float damage; + + public float knockBack; + + public float stopForce; + + public AnimationCurve forceCurve; + + public float force; + + public float drag; + + public float time; + + private CharacterData data; + + private AttackLevel level; + + private Vector3 dir; + + private bool cancelForce; + + private List<CharacterData> hitDatas = new List<CharacterData>(); + + private float blockTime; + + private void Start() + { + level = GetComponent<AttackLevel>(); + data = GetComponentInParent<CharacterData>(); + PlayerCollision component = data.GetComponent<PlayerCollision>(); + component.collideWithPlayerAction = (Action<Vector2, Vector2, Player>)Delegate.Combine(component.collideWithPlayerAction, new Action<Vector2, Vector2, Player>(Collide)); + GetComponentInParent<ChildRPC>().childRPCsVector2Vector2Int.Add("ShieldChargeCollide", RPCA_Collide); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(DoBlock)); + } + + private void OnDestroy() + { + PlayerCollision component = data.GetComponent<PlayerCollision>(); + component.collideWithPlayerAction = (Action<Vector2, Vector2, Player>)Delegate.Remove(component.collideWithPlayerAction, new Action<Vector2, Vector2, Player>(Collide)); + GetComponentInParent<ChildRPC>().childRPCsVector2Vector2Int.Remove("ShieldChargeCollide"); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(DoBlock)); + } + + private void Update() + { + blockTime -= TimeHandler.deltaTime; + } + + public void DoBlock(BlockTrigger.BlockTriggerType trigger) + { + if (trigger != BlockTrigger.BlockTriggerType.ShieldCharge) + { + Charge(trigger); + } + } + + public void Charge(BlockTrigger.BlockTriggerType trigger) + { + StartCoroutine(DoCharge(trigger)); + } + + private IEnumerator DoCharge(BlockTrigger.BlockTriggerType trigger) + { + SoundManager.Instance.Play(soundShieldCharge, base.transform); + cancelForce = false; + hitDatas.Clear(); + if (trigger == BlockTrigger.BlockTriggerType.Empower) + { + Vector3 currentPos = base.transform.position; + yield return new WaitForSeconds(0f); + dir = (currentPos - base.transform.position).normalized; + } + else + { + dir = data.aimDirection; + } + float usedTime = (blockTime = time + (float)level.LevelsUp() * timePerLevel); + float num = time * 0.1f + (float)level.LevelsUp() * time * 0.15f; + for (int i = 0; i < level.LevelsUp(); i++) + { + float num2 = time / (float)level.attackLevel; + _ = time; + num += num2; + StartCoroutine(DelayBlock(num)); + } + float c = 0f; + while (c < 1f) + { + c += Time.fixedDeltaTime / usedTime; + if (!cancelForce) + { + data.healthHandler.TakeForce(dir * forceCurve.Evaluate(c) * (force + (float)level.LevelsUp() * forcePerLevel), ForceMode2D.Force, forceIgnoreMass: true, ignoreBlock: true); + data.healthHandler.TakeForce(-data.playerVel.velocity * drag * Time.fixedDeltaTime, ForceMode2D.Force, forceIgnoreMass: true, ignoreBlock: true); + } + data.sinceGrounded = 0f; + yield return new WaitForFixedUpdate(); + } + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.ShieldCharge); + } + + private IEnumerator DelayBlock(float delay) + { + yield return new WaitForSeconds(delay); + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.ShieldCharge); + } + + public void RPCA_Collide(Vector2 pos, Vector2 colDir, int playerID) + { + CharacterData componentInParent = PlayerManager.instance.GetPlayerWithID(playerID).gameObject.GetComponentInParent<CharacterData>(); + if ((bool)componentInParent) + { + cancelForce = true; + hitPart.transform.rotation = Quaternion.LookRotation(dir); + hitPart.Play(); + componentInParent.healthHandler.TakeDamage(dir * (damage + (float)level.LevelsUp() * damagePerLevel), base.transform.position, null, data.player); + componentInParent.healthHandler.TakeForce(dir * (knockBack + (float)level.LevelsUp() * knockBackPerLevel)); + data.healthHandler.TakeForce(-dir * knockBack, ForceMode2D.Impulse, forceIgnoreMass: false, ignoreBlock: true); + data.healthHandler.TakeForce(-dir * stopForce, ForceMode2D.Impulse, forceIgnoreMass: true, ignoreBlock: true); + data.block.RPCA_DoBlock(firstBlock: false, dontSetCD: true, BlockTrigger.BlockTriggerType.ShieldCharge); + GamefeelManager.GameFeel(dir * shake); + } + } + + public void Collide(Vector2 pos, Vector2 colDir, Player player) + { + if (!data.view.IsMine || blockTime < 0f) + { + return; + } + CharacterData componentInParent = player.gameObject.GetComponentInParent<CharacterData>(); + if (!hitDatas.Contains(componentInParent)) + { + hitDatas.Add(componentInParent); + if ((bool)componentInParent) + { + GetComponentInParent<ChildRPC>().CallFunction("ShieldChargeCollide", pos, colDir, player.playerID); + } + } + } +} diff --git a/ROUNDS/ShootPos.cs b/ROUNDS/ShootPos.cs new file mode 100644 index 0000000..ca75170 --- /dev/null +++ b/ROUNDS/ShootPos.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class ShootPos : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/SilenceHandler.cs b/ROUNDS/SilenceHandler.cs new file mode 100644 index 0000000..a1cab30 --- /dev/null +++ b/ROUNDS/SilenceHandler.cs @@ -0,0 +1,70 @@ +using Photon.Pun; +using UnityEngine; + +public class SilenceHandler : MonoBehaviour +{ + [Header("Settings")] + public CodeAnimation codeAnim; + + private Player player; + + private CharacterData data; + + private void Start() + { + player = GetComponent<Player>(); + data = player.data; + } + + private void Update() + { + if (data.silenceTime > 0f) + { + data.silenceTime -= TimeHandler.deltaTime; + if (!data.isSilenced) + { + StartSilence(); + } + } + else if (data.isSilenced) + { + StopSilence(); + } + } + + private void StartSilence() + { + player.data.input.silencedInput = true; + codeAnim.PlayIn(); + data.isSilenced = true; + } + + public void StopSilence() + { + player.data.input.silencedInput = false; + if (codeAnim.currentState == CodeAnimationInstance.AnimationUse.In) + { + codeAnim.PlayOut(); + } + data.isSilenced = false; + data.silenceTime = 0f; + } + + private void OnDisable() + { + codeAnim.transform.localScale = Vector3.zero; + } + + [PunRPC] + public void RPCA_AddSilence(float f) + { + if (f > data.silenceTime) + { + data.silenceTime = f; + } + if (!data.isSilenced) + { + StartSilence(); + } + } +} diff --git a/ROUNDS/SimulatedSelection.cs b/ROUNDS/SimulatedSelection.cs new file mode 100644 index 0000000..d80866b --- /dev/null +++ b/ROUNDS/SimulatedSelection.cs @@ -0,0 +1,33 @@ +using UnityEngine; +using UnityEngine.UI; + +public class SimulatedSelection : MonoBehaviour +{ + private HoverEvent hoverEvent; + + private Button button; + + private void Start() + { + hoverEvent = GetComponent<HoverEvent>(); + button = GetComponent<Button>(); + } + + private void OnDisable() + { + Deselect(); + } + + public void Select() + { + hoverEvent.OnPointerEnter(null); + button.targetGraphic.color = button.colors.highlightedColor; + } + + public void Deselect() + { + hoverEvent.OnPointerExit(null); + button.OnDeselect(null); + button.targetGraphic.color = button.colors.normalColor; + } +} diff --git a/ROUNDS/SkipIntro.cs b/ROUNDS/SkipIntro.cs new file mode 100644 index 0000000..809d294 --- /dev/null +++ b/ROUNDS/SkipIntro.cs @@ -0,0 +1,38 @@ +using InControl; +using UnityEngine; + +public class SkipIntro : MonoBehaviour +{ + public static bool hasShown; + + public ListMenuPage target; + + private void Start() + { + if (hasShown) + { + Skip(); + } + hasShown = true; + } + + private void Update() + { + for (int i = 0; i < InputManager.ActiveDevices.Count; i++) + { + if (InputManager.ActiveDevices[i].AnyButton.WasPressed) + { + Skip(); + } + } + if (Input.GetKeyDown(KeyCode.Escape)) + { + Skip(); + } + } + + private void Skip() + { + target.Open(); + } +} diff --git a/ROUNDS/SliceEffect.cs b/ROUNDS/SliceEffect.cs new file mode 100644 index 0000000..e8f1021 --- /dev/null +++ b/ROUNDS/SliceEffect.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class SliceEffect : MonoBehaviour +{ +} diff --git a/ROUNDS/SoundAudioListenerPosition.cs b/ROUNDS/SoundAudioListenerPosition.cs new file mode 100644 index 0000000..be8fbd3 --- /dev/null +++ b/ROUNDS/SoundAudioListenerPosition.cs @@ -0,0 +1,38 @@ +using UnityEngine; + +public class SoundAudioListenerPosition : MonoBehaviour +{ + private float positionZaxis = -50f; + + private AudioListener audioListener; + + private Transform audioListenerTransform; + + private Transform cachedTransform; + + private Vector3 postion; + + private void Awake() + { + audioListener = Object.FindObjectOfType<AudioListener>(); + if (audioListener == null) + { + Debug.LogError("No AudioListener Found"); + } + else + { + audioListenerTransform = audioListener.transform; + } + cachedTransform = base.transform; + } + + private void Update() + { + if (audioListenerTransform != null) + { + postion = cachedTransform.position; + postion.z = positionZaxis; + audioListenerTransform.position = postion; + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundAnimationPlay.cs b/ROUNDS/SoundImplementation/SoundAnimationPlay.cs new file mode 100644 index 0000000..05c8b8f --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundAnimationPlay.cs @@ -0,0 +1,17 @@ +using System; +using Sonigon; + +namespace SoundImplementation; + +[Serializable] +public class SoundAnimationPlay +{ + public SoundEvent soundEvent; + + public CurveAnimationUse curveAnimationUse; + + public float soundDelay; + + [NonSerialized] + public bool soundHasPlayed; +} diff --git a/ROUNDS/SoundImplementation/SoundEnvironmentRigidbody.cs b/ROUNDS/SoundImplementation/SoundEnvironmentRigidbody.cs new file mode 100644 index 0000000..335a17f --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundEnvironmentRigidbody.cs @@ -0,0 +1,33 @@ +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +public class SoundEnvironmentRigidbody : MonoBehaviour +{ + public SoundEvent soundMoveLoop; + + private Rigidbody2D cachedRigidbody2D; + + private bool soundIsPlaying; + + private SoundParameterIntensity parameterIntensity = new SoundParameterIntensity(0f, UpdateMode.Continuous); + + private void Awake() + { + cachedRigidbody2D = GetComponent<Rigidbody2D>(); + } + + private void FixedUpdate() + { + if (cachedRigidbody2D != null && soundMoveLoop != null) + { + if (!soundIsPlaying) + { + soundIsPlaying = true; + SoundManager.Instance.Play(soundMoveLoop, base.transform, parameterIntensity); + } + parameterIntensity.intensity = cachedRigidbody2D.velocity.magnitude; + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundGun.cs b/ROUNDS/SoundImplementation/SoundGun.cs new file mode 100644 index 0000000..82684cf --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundGun.cs @@ -0,0 +1,435 @@ +using System; +using System.Collections.Generic; +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +[Serializable] +public class SoundGun +{ + private Gun parentGun; + + private Transform gunTransform; + + [Header("Sound Shot")] + public int howManyShotModifiers = 3; + + [Range(-12f, 0f)] + public float shotModifierLowerVolumeDbIf2 = -3f; + + [Range(-12f, 0f)] + public float shotModifierLowerVolumeDbIf3 = -6f; + + public SoundShotModifier soundShotModifierBasic; + + private List<SoundShotModifier> soundShotModifierAllList = new List<SoundShotModifier>(); + + private List<SoundShotModifier> soundShotModifierCurrentList = new List<SoundShotModifier>(); + + private bool singleAutoIsPlaying; + + private bool shotgunAutoIsPlaying; + + [Header("Sound Impact")] + public int howManyImpactModifiers = 2; + + [Range(-12f, 0f)] + public float impactModifierLowerVolumeDbIf2 = -3f; + + [Range(-12f, 0f)] + public float impactModifierLowerVolumeDbIf3 = -6f; + + public SoundImpactModifier soundImpactModifierBasic; + + public SoundImpactModifier soundImpactModifierDamageToExplosionMedium; + + public SoundImpactModifier soundImpactModifierDamageToExplosionHuge; + + private SoundParameterIntensity soundDamageToExplosionParameterIntensity = new SoundParameterIntensity(0f); + + public SoundEvent soundImpactBounce; + + public SoundEvent soundImpactBullet; + + private List<SoundImpactModifier> soundImpactModifierAllList = new List<SoundImpactModifier>(); + + private List<SoundImpactModifier> soundImpactModifierCurrentList = new List<SoundImpactModifier>(); + + private SoundParameterVolumeDecibel soundParameterVolumeDecibelShot = new SoundParameterVolumeDecibel(); + + private SoundParameterVolumeDecibel soundParameterVolumeDecibelImpact = new SoundParameterVolumeDecibel(); + + private bool autoFirstShot = true; + + private float autoStartTime; + + private float autoTimeSinceStart; + + private int autoShotsCalculate; + + private float autoDelayBetweenShotsDefault = 0.05f; + + private float autoDelayBetweenShotsNew; + + private SoundParameterPitchRatio autoPitchRatio = new SoundParameterPitchRatio(1f, UpdateMode.Continuous); + + private float autoPitchThresholdLow = 0.5f; + + private float autoPitchThresholdHigh = 3f; + + public void SetGun(Gun gun) + { + parentGun = gun; + } + + public void SetGunTransform(Transform transform) + { + gunTransform = transform; + } + + public void PlayImpact(HitInfo hit, RayHitReflect rayHitReflect) + { + bool flag = false; + if (hit.transform != null) + { + if (hit.transform.tag == "Player") + { + flag = true; + } + } + else + { + SoundManager.Instance.PlayAtPosition(soundImpactBullet, SoundManager.Instance.GetTransform(), hit.point, soundParameterVolumeDecibelImpact); + } + if (rayHitReflect != null && rayHitReflect.reflects > 0 && !flag) + { + SoundManager.Instance.PlayAtPosition(soundImpactBounce, SoundManager.Instance.GetTransform(), hit.point, soundParameterVolumeDecibelImpact); + } + else + { + PlayImpactModifiers(flag, hit.point); + } + } + + private void PlayImpactModifiers(bool isPlayer, Vector2 position) + { + for (int i = 0; i < soundImpactModifierCurrentList.Count; i++) + { + if (soundImpactModifierCurrentList[i] != null) + { + if (isPlayer) + { + SoundManager.Instance.PlayAtPosition(soundImpactModifierCurrentList[i].impactCharacter, SoundManager.Instance.GetTransform(), position, soundParameterVolumeDecibelImpact, soundDamageToExplosionParameterIntensity); + } + else + { + SoundManager.Instance.PlayAtPosition(soundImpactModifierCurrentList[i].impactEnvironment, SoundManager.Instance.GetTransform(), position, soundParameterVolumeDecibelImpact, soundDamageToExplosionParameterIntensity); + } + } + } + } + + public void ClearSoundModifiers() + { + soundShotModifierAllList.Clear(); + soundImpactModifierAllList.Clear(); + RefreshSoundModifiers(); + } + + public void AddSoundShotModifier(SoundShotModifier soundShotModifier) + { + if (soundShotModifier != null) + { + soundShotModifierAllList.Insert(0, soundShotModifier); + } + } + + public void AddSoundImpactModifier(SoundImpactModifier soundImpactModifier) + { + if (soundImpactModifier != null) + { + soundImpactModifierAllList.Insert(0, soundImpactModifier); + } + } + + public void RefreshSoundModifiers() + { + StopAutoPlayTail(); + if (howManyShotModifiers < 1) + { + howManyShotModifiers = 1; + } + if (howManyImpactModifiers < 1) + { + howManyImpactModifiers = 1; + } + int num = 0; + for (int i = 0; i < soundShotModifierAllList.Count; i++) + { + if (num < soundShotModifierAllList[i].priority) + { + num = soundShotModifierAllList[i].priority; + } + } + soundShotModifierCurrentList.Clear(); + int num2 = 0; + for (int num3 = num; num3 >= 0; num3--) + { + for (int j = 0; j < soundShotModifierAllList.Count; j++) + { + if (soundShotModifierAllList[j].priority == num3 && !soundShotModifierCurrentList.Contains(soundShotModifierAllList[j])) + { + soundShotModifierCurrentList.Add(soundShotModifierAllList[j]); + num2++; + } + if (num2 >= howManyShotModifiers) + { + break; + } + } + if (num2 >= howManyShotModifiers) + { + break; + } + } + if (soundShotModifierCurrentList.Count == 0) + { + soundShotModifierCurrentList.Add(soundShotModifierBasic); + } + if (soundShotModifierCurrentList.Count == 1) + { + soundParameterVolumeDecibelShot.volumeDecibel = 0f; + } + else if (soundShotModifierCurrentList.Count == 2) + { + soundParameterVolumeDecibelShot.volumeDecibel = shotModifierLowerVolumeDbIf2; + } + else if (soundShotModifierCurrentList.Count == 3) + { + soundParameterVolumeDecibelShot.volumeDecibel = shotModifierLowerVolumeDbIf3; + } + soundDamageToExplosionParameterIntensity.intensity = parentGun.damage; + if (soundImpactModifierDamageToExplosionMedium != null && soundImpactModifierDamageToExplosionHuge != null) + { + if (parentGun.damage > 2.6f) + { + if (parentGun.damage > 8f) + { + if (!soundImpactModifierAllList.Contains(soundImpactModifierDamageToExplosionHuge)) + { + soundImpactModifierAllList.Insert(0, soundImpactModifierDamageToExplosionHuge); + } + soundImpactModifierAllList.Remove(soundImpactModifierDamageToExplosionMedium); + } + else + { + if (!soundImpactModifierAllList.Contains(soundImpactModifierDamageToExplosionMedium)) + { + soundImpactModifierAllList.Insert(0, soundImpactModifierDamageToExplosionMedium); + } + soundImpactModifierAllList.Remove(soundImpactModifierDamageToExplosionHuge); + } + } + else + { + soundImpactModifierAllList.Remove(soundImpactModifierDamageToExplosionMedium); + soundImpactModifierAllList.Remove(soundImpactModifierDamageToExplosionHuge); + } + } + int num4 = 0; + for (int k = 0; k < soundImpactModifierAllList.Count; k++) + { + if (num4 < soundImpactModifierAllList[k].priority) + { + num4 = soundImpactModifierAllList[k].priority; + } + } + soundImpactModifierCurrentList.Clear(); + int num5 = 0; + for (int num6 = num4; num6 >= 0; num6--) + { + for (int l = 0; l < soundImpactModifierAllList.Count; l++) + { + if (soundImpactModifierAllList[l].priority == num6 && !soundImpactModifierCurrentList.Contains(soundImpactModifierAllList[l])) + { + soundImpactModifierCurrentList.Add(soundImpactModifierAllList[l]); + num5++; + } + if (num5 >= howManyImpactModifiers) + { + break; + } + } + if (num5 >= howManyImpactModifiers) + { + break; + } + } + if (soundImpactModifierCurrentList.Count == 0) + { + soundImpactModifierCurrentList.Add(soundImpactModifierBasic); + } + if (soundImpactModifierCurrentList.Count == 1) + { + soundParameterVolumeDecibelImpact.volumeDecibel = 0f; + } + else if (soundImpactModifierCurrentList.Count == 2) + { + soundParameterVolumeDecibelImpact.volumeDecibel = impactModifierLowerVolumeDbIf2; + } + else if (soundImpactModifierCurrentList.Count == 3) + { + soundParameterVolumeDecibelImpact.volumeDecibel = impactModifierLowerVolumeDbIf3; + } + } + + public void StopAutoPlayTail() + { + autoFirstShot = true; + StopInternalSingleAutoPlayTail(); + StopInternalShotgunAutoPlayTail(); + } + + private void StopInternalSingleAutoPlayTail() + { + if (!singleAutoIsPlaying) + { + return; + } + singleAutoIsPlaying = false; + for (int i = 0; i < soundShotModifierCurrentList.Count; i++) + { + if (soundShotModifierCurrentList[i] != null) + { + SoundManager.Instance.Stop(soundShotModifierCurrentList[i].singleAutoLoop, gunTransform); + SoundManager.Instance.Play(soundShotModifierCurrentList[i].singleAutoTail, gunTransform, soundParameterVolumeDecibelShot, autoPitchRatio); + } + } + } + + private void StopInternalShotgunAutoPlayTail() + { + if (!shotgunAutoIsPlaying) + { + return; + } + shotgunAutoIsPlaying = false; + for (int i = 0; i < soundShotModifierCurrentList.Count; i++) + { + if (soundShotModifierCurrentList[i] != null) + { + SoundManager.Instance.Stop(soundShotModifierCurrentList[i].shotgunAutoLoop, gunTransform); + SoundManager.Instance.Play(soundShotModifierCurrentList[i].shotgunAutoTail, gunTransform, soundParameterVolumeDecibelShot); + } + } + } + + private void PlaySingle() + { + StopInternalSingleAutoPlayTail(); + StopInternalShotgunAutoPlayTail(); + for (int i = 0; i < soundShotModifierCurrentList.Count; i++) + { + if (soundShotModifierCurrentList[i] != null) + { + SoundManager.Instance.Play(soundShotModifierCurrentList[i].single, gunTransform, soundParameterVolumeDecibelShot); + } + } + } + + private void PlayShotgun() + { + StopInternalSingleAutoPlayTail(); + StopInternalShotgunAutoPlayTail(); + for (int i = 0; i < soundShotModifierCurrentList.Count; i++) + { + if (soundShotModifierCurrentList[i] != null) + { + SoundManager.Instance.Play(soundShotModifierCurrentList[i].shotgun, gunTransform, soundParameterVolumeDecibelShot); + } + } + } + + private void PlaySingleAuto() + { + StopInternalShotgunAutoPlayTail(); + if (singleAutoIsPlaying) + { + return; + } + singleAutoIsPlaying = true; + for (int i = 0; i < soundShotModifierCurrentList.Count; i++) + { + if (soundShotModifierCurrentList[i] != null) + { + SoundManager.Instance.Play(soundShotModifierCurrentList[i].singleAutoLoop, gunTransform, soundParameterVolumeDecibelShot, autoPitchRatio); + } + } + } + + private void PlayShotgunAuto() + { + StopInternalSingleAutoPlayTail(); + if (shotgunAutoIsPlaying) + { + return; + } + shotgunAutoIsPlaying = true; + for (int i = 0; i < soundShotModifierCurrentList.Count; i++) + { + if (soundShotModifierCurrentList[i] != null) + { + SoundManager.Instance.Play(soundShotModifierCurrentList[i].shotgunAutoLoop, gunTransform, soundParameterVolumeDecibelShot); + } + } + } + + public void PlayShot(int currentNumberOfProjectiles) + { + if ((parentGun.bursts > 0 && !parentGun.useCharge && !parentGun.dontAllowAutoFire) || (parentGun.attackSpeed / parentGun.attackSpeedMultiplier < 0.15f && !parentGun.useCharge && !parentGun.dontAllowAutoFire)) + { + if (currentNumberOfProjectiles > 1) + { + PlayShotgunAuto(); + return; + } + if (autoFirstShot) + { + autoFirstShot = false; + autoShotsCalculate = 0; + autoStartTime = Time.realtimeSinceStartup; + } + else + { + autoShotsCalculate++; + autoTimeSinceStart = Time.realtimeSinceStartup - autoStartTime; + autoDelayBetweenShotsNew = autoTimeSinceStart / (float)autoShotsCalculate; + autoPitchRatio.pitchRatio = autoDelayBetweenShotsDefault / autoDelayBetweenShotsNew; + } + if (autoPitchRatio.pitchRatio < autoPitchThresholdLow) + { + if (!singleAutoIsPlaying && !shotgunAutoIsPlaying) + { + PlaySingle(); + } + } + else if (autoPitchRatio.pitchRatio > autoPitchThresholdHigh) + { + PlayShotgunAuto(); + } + else if (!shotgunAutoIsPlaying) + { + PlaySingleAuto(); + } + } + else if (currentNumberOfProjectiles > 1) + { + PlayShotgun(); + } + else + { + PlaySingle(); + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundHierarchyDepth.cs b/ROUNDS/SoundImplementation/SoundHierarchyDepth.cs new file mode 100644 index 0000000..048df36 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundHierarchyDepth.cs @@ -0,0 +1,9 @@ +namespace SoundImplementation; + +public enum SoundHierarchyDepth +{ + dontPlay, + bulletParent, + bulletChild, + bulletChildChild +} diff --git a/ROUNDS/SoundImplementation/SoundHierarchyPlay.cs b/ROUNDS/SoundImplementation/SoundHierarchyPlay.cs new file mode 100644 index 0000000..567b0c4 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundHierarchyPlay.cs @@ -0,0 +1,105 @@ +using System; +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +public class SoundHierarchyPlay : MonoBehaviour +{ + [NonSerialized] + public Transform instanceIDTransform; + + [NonSerialized] + public SoundHierarchySpawn soundHierarchySpawn; + + [NonSerialized] + public SoundHierarchyDepth soundHierarchyDepth; + + private SoundParameterIntensity soundParameterIntensityParentContinious = new SoundParameterIntensity(1f, UpdateMode.Continuous); + + private SoundParameterIntensity soundParameterIntensityChildOnce = new SoundParameterIntensity(0f); + + private Vector3 lastPosition; + + private Transform transformPosition; + + private bool bulletHasTriggered; + + private bool stopOnDisablePlaying; + + private Transform GetCurrentInstanceIDTransform() + { + if (soundHierarchySpawn.soundPolyGrouping == SoundPolyGrouping.global) + { + return SoundManager.Instance.GetTransform(); + } + return instanceIDTransform; + } + + private void FixedUpdate() + { + if (soundHierarchyDepth == SoundHierarchyDepth.bulletParent && soundHierarchySpawn.soundParentVelocityToIntensity && bulletHasTriggered && soundHierarchySpawn != null) + { + soundParameterIntensityParentContinious.intensity = Vector3.Distance(lastPosition, transformPosition.position); + lastPosition = transformPosition.position; + } + } + + private void OnDisable() + { + if (bulletHasTriggered && stopOnDisablePlaying) + { + stopOnDisablePlaying = false; + SoundManager.Instance.StopAtPosition(soundHierarchySpawn.soundChildChildStopOnDisable, transformPosition); + } + } + + public void PlayBullet() + { + transformPosition = base.transform; + bulletHasTriggered = true; + lastPosition = transformPosition.position; + if (soundHierarchyDepth == SoundHierarchyDepth.bulletParent) + { + if (soundHierarchySpawn.soundParent != null) + { + if (soundHierarchySpawn.soundParentVelocityToIntensity) + { + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundParent, GetCurrentInstanceIDTransform(), transformPosition, soundParameterIntensityParentContinious); + } + else + { + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundParent, GetCurrentInstanceIDTransform(), transformPosition); + } + } + if (soundHierarchySpawn.soundParentStopOnDisable != null) + { + stopOnDisablePlaying = true; + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundParentStopOnDisable, GetCurrentInstanceIDTransform(), transformPosition); + } + } + else if (soundHierarchyDepth == SoundHierarchyDepth.bulletChild && soundHierarchySpawn.soundChild != null) + { + if (soundHierarchySpawn.soundChildVelocityToIntensity) + { + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundChild, GetCurrentInstanceIDTransform(), transformPosition, soundParameterIntensityChildOnce); + } + else + { + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundChild, GetCurrentInstanceIDTransform(), transformPosition); + } + } + else if (soundHierarchyDepth == SoundHierarchyDepth.bulletChildChild) + { + if (soundHierarchySpawn.soundChildChild != null) + { + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundChildChild, GetCurrentInstanceIDTransform(), transformPosition); + } + if (soundHierarchySpawn.soundChildChildStopOnDisable != null) + { + stopOnDisablePlaying = true; + SoundManager.Instance.PlayAtPosition(soundHierarchySpawn.soundChildChildStopOnDisable, GetCurrentInstanceIDTransform(), transformPosition); + } + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundHierarchySpawn.cs b/ROUNDS/SoundImplementation/SoundHierarchySpawn.cs new file mode 100644 index 0000000..02e84db --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundHierarchySpawn.cs @@ -0,0 +1,37 @@ +using System; +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +[Serializable] +public class SoundHierarchySpawn +{ + public SoundPolyGrouping soundPolyGrouping = SoundPolyGrouping.perPlayer; + + [Header("Sound Parent")] + public SoundEvent soundParent; + + public bool soundParentVelocityToIntensity; + + public SoundEvent soundParentStopOnDisable; + + [Header("Sound Child")] + public SoundEvent soundChild; + + public bool soundChildVelocityToIntensity; + + [Header("Sound Child Child")] + public SoundEvent soundChildChild; + + public SoundEvent soundChildChildStopOnDisable; + + public bool IfAnySoundIsNotNull() + { + if (soundParent != null || soundParentStopOnDisable != null || soundChild != null || soundChildChild != null || soundChildChildStopOnDisable != null) + { + return true; + } + return false; + } +} diff --git a/ROUNDS/SoundImplementation/SoundImpactModifier.cs b/ROUNDS/SoundImplementation/SoundImpactModifier.cs new file mode 100644 index 0000000..669fab0 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundImpactModifier.cs @@ -0,0 +1,18 @@ +using System; +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +[Serializable] +[CreateAssetMenu(fileName = "_SoundImpactModifier", menuName = "Sound Implementation/Sound Impact Modifier", order = 1)] +public class SoundImpactModifier : ScriptableObject +{ + [Header("Sound Priority")] + public int priority; + + [Header("Sound Events")] + public SoundEvent impactCharacter; + + public SoundEvent impactEnvironment; +} diff --git a/ROUNDS/SoundImplementation/SoundMusicManager.cs b/ROUNDS/SoundImplementation/SoundMusicManager.cs new file mode 100644 index 0000000..6de83c4 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundMusicManager.cs @@ -0,0 +1,145 @@ +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +public class SoundMusicManager : MonoBehaviour +{ + private bool isGoingToDelete; + + private bool useDontDestroyOnLoad; + + private bool debugMusicPlay; + + [Header("Music, press Pause to toggle the volume of the music")] + public SoundEvent musicMainMenu; + + public SoundEvent musicIngame; + + private bool musicFirstPlay; + + private bool musicMainMenuPlaying; + + private bool musicIngamePlaying; + + private SoundParameterIntensity musicIntensityIngame = new SoundParameterIntensity(1f, UpdateMode.Continuous); + + public SoundEvent ambience; + + private bool ambiencePlaying; + + public static SoundMusicManager Instance { get; private set; } + + public void PlayMainMenu() + { + StopAmbience(); + if (!musicMainMenuPlaying) + { + musicMainMenuPlaying = true; + if (SoundVolumeManager.Instance.mainMenuFirstTime) + { + SoundVolumeManager.Instance.mainMenuFirstTime = false; + SoundManager.Instance.PlayMusic(musicMainMenu, true, true, new SoundParameterFadeInLength()); + } + else + { + SoundManager.Instance.PlayMusic(musicMainMenu); + } + musicIngamePlaying = false; + if (debugMusicPlay) + { + Debug.LogWarning("MUSIC: PlayMainMenu"); + } + } + } + + public void PlayIngame(bool isCard) + { + PlayAmbience(); + if (isCard) + { + musicIntensityIngame.intensity = 0f; + if (debugMusicPlay) + { + Debug.LogWarning("MUSIC: Ingame Instensity 0"); + } + } + else + { + musicIntensityIngame.intensity = 1f; + if (debugMusicPlay) + { + Debug.LogWarning("MUSIC: Ingame Instensity 1"); + } + } + if (!musicIngamePlaying) + { + musicIngamePlaying = true; + SoundManager.Instance.PlayMusic(musicIngame, true, true, musicIntensityIngame); + musicMainMenuPlaying = false; + if (debugMusicPlay) + { + Debug.LogWarning("MUSIC: PlayIngame"); + } + } + } + + public void StopAllMusic() + { + SoundManager.Instance.StopAllMusic(); + musicMainMenuPlaying = false; + musicIngamePlaying = false; + } + + private void PlayAmbience() + { + if (!ambiencePlaying) + { + ambiencePlaying = true; + SoundManager.Instance.Play(ambience, base.transform); + } + } + + private void StopAmbience() + { + if (ambiencePlaying) + { + ambiencePlaying = false; + SoundManager.Instance.Stop(ambience, base.transform); + } + } + + private void Start() + { + if (!musicFirstPlay) + { + musicFirstPlay = true; + PlayMainMenu(); + } + } + + private void Awake() + { + InstanceCheck(); + if (useDontDestroyOnLoad && !isGoingToDelete) + { + Object.DontDestroyOnLoad(base.gameObject); + } + } + + private void InstanceCheck() + { + if (Instance == null) + { + Instance = this; + } + else if (Instance != this) + { + isGoingToDelete = true; + if (Application.isPlaying) + { + Object.Destroy(base.gameObject); + } + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundOnePerPlayer.cs b/ROUNDS/SoundImplementation/SoundOnePerPlayer.cs new file mode 100644 index 0000000..7e268db --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundOnePerPlayer.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace SoundImplementation; + +public class SoundOnePerPlayer +{ + private List<Transform> remoteControlPlayerTransformList = new List<Transform>(); + + private List<int> remoteControlNumberOfList = new List<int>(); + + private void AddTransformToList(Transform transform) + { + remoteControlPlayerTransformList.Add(transform); + remoteControlNumberOfList.Add(0); + } + + public int GetNumberOf(Transform transform) + { + for (int i = 0; i < remoteControlPlayerTransformList.Count; i++) + { + if (remoteControlPlayerTransformList[i] == transform) + { + return remoteControlNumberOfList[i]; + } + } + AddTransformToList(transform); + return GetNumberOf(transform); + } + + public void AddNumberOf(Transform transform, int toAdd) + { + for (int i = 0; i < remoteControlPlayerTransformList.Count; i++) + { + if (remoteControlPlayerTransformList[i] == transform) + { + remoteControlNumberOfList[i] += toAdd; + return; + } + } + AddTransformToList(transform); + AddNumberOf(transform, toAdd); + } +} diff --git a/ROUNDS/SoundImplementation/SoundPlayerStatic.cs b/ROUNDS/SoundImplementation/SoundPlayerStatic.cs new file mode 100644 index 0000000..5c06251 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundPlayerStatic.cs @@ -0,0 +1,104 @@ +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +public class SoundPlayerStatic : MonoBehaviour +{ + [SerializeField] + private SoundEvent soundButtonHover; + + [SerializeField] + private SoundEvent soundButtonClick; + + [SerializeField] + private SoundEvent soundMatchFound; + + [SerializeField] + private SoundEvent soundPlayerAdded; + + [SerializeField] + private SoundEvent soundPlayerBallAppear; + + [SerializeField] + private SoundEvent soundPlayerBallDisappear; + + [SerializeField] + private SoundEvent soundLevelTransitionIn; + + [SerializeField] + private SoundEvent soundLevelTransitionOut; + + private bool isGoingToDelete; + + private bool useDontDestroyOnLoad = true; + + private bool debugInstanceDestroyed = true; + + public static SoundPlayerStatic Instance { get; private set; } + + public void PlayButtonHover() + { + SoundManager.Instance.Play(soundButtonHover, base.transform); + } + + public void PlayButtonClick() + { + SoundManager.Instance.Play(soundButtonClick, base.transform); + } + + public void PlayMatchFound() + { + SoundManager.Instance.Play(soundMatchFound, base.transform); + } + + public void PlayPlayerAdded() + { + SoundManager.Instance.Play(soundPlayerAdded, base.transform); + } + + public void PlayPlayerBallAppear() + { + SoundManager.Instance.Play(soundPlayerBallAppear, base.transform); + } + + public void PlayPlayerBallDisappear() + { + SoundManager.Instance.Play(soundPlayerBallDisappear, base.transform); + } + + public void PlayLevelTransitionIn() + { + SoundManager.Instance.Play(soundLevelTransitionIn, base.transform); + } + + public void PlayLevelTransitionOut() + { + SoundManager.Instance.Play(soundLevelTransitionOut, base.transform); + } + + private void Awake() + { + InstanceCheck(); + if (useDontDestroyOnLoad && !isGoingToDelete) + { + Object.DontDestroyOnLoad(base.gameObject); + } + } + + private void InstanceCheck() + { + if (Instance == null) + { + Instance = this; + } + else if (Instance != this) + { + isGoingToDelete = true; + if (Application.isPlaying) + { + Object.Destroy(base.gameObject); + } + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundPolyGrouping.cs b/ROUNDS/SoundImplementation/SoundPolyGrouping.cs new file mode 100644 index 0000000..2928753 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundPolyGrouping.cs @@ -0,0 +1,7 @@ +namespace SoundImplementation; + +public enum SoundPolyGrouping +{ + global, + perPlayer +} diff --git a/ROUNDS/SoundImplementation/SoundShotModifier.cs b/ROUNDS/SoundImplementation/SoundShotModifier.cs new file mode 100644 index 0000000..2e6de58 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundShotModifier.cs @@ -0,0 +1,26 @@ +using System; +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +[Serializable] +[CreateAssetMenu(fileName = "_SoundShotModifier", menuName = "Sound Implementation/Sound Shot Modifier", order = 0)] +public class SoundShotModifier : ScriptableObject +{ + [Header("Sound Priority")] + public int priority; + + [Header("Sound Events")] + public SoundEvent single; + + public SoundEvent singleAutoLoop; + + public SoundEvent singleAutoTail; + + public SoundEvent shotgun; + + public SoundEvent shotgunAutoLoop; + + public SoundEvent shotgunAutoTail; +} diff --git a/ROUNDS/SoundImplementation/SoundStaticRemoteControl.cs b/ROUNDS/SoundImplementation/SoundStaticRemoteControl.cs new file mode 100644 index 0000000..2ed14f4 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundStaticRemoteControl.cs @@ -0,0 +1,6 @@ +namespace SoundImplementation; + +public static class SoundStaticRemoteControl +{ + public static SoundOnePerPlayer remoteControl = new SoundOnePerPlayer(); +} diff --git a/ROUNDS/SoundImplementation/SoundUnityEventPlayer.cs b/ROUNDS/SoundImplementation/SoundUnityEventPlayer.cs new file mode 100644 index 0000000..65e4fe1 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundUnityEventPlayer.cs @@ -0,0 +1,107 @@ +using Sonigon; +using UnityEngine; + +namespace SoundImplementation; + +public class SoundUnityEventPlayer : MonoBehaviour +{ + public bool triggerStartOnStart; + + public bool triggerStartOnEnable; + + public bool triggerEndOnDestroy; + + public bool triggerEndOnDisable; + + public bool useLocalTransformForInstanceID; + + public SoundEvent soundStart; + + public SoundEvent soundStartLoop; + + public SoundEvent soundEnd; + + private bool soundStartLoopPlaying; + + private bool initialized; + + private Transform transformPosition; + + private void Initialize() + { + if (!initialized) + { + initialized = true; + transformPosition = base.transform; + } + } + + private Transform GetTransformInstanceID() + { + if (useLocalTransformForInstanceID) + { + return transformPosition; + } + return SoundManager.Instance.GetTransform(); + } + + private void Start() + { + if (triggerStartOnStart) + { + PlayStart(); + } + } + + private void OnEnable() + { + if (triggerStartOnEnable) + { + PlayStart(); + } + } + + public void PlayStart() + { + Initialize(); + if (soundStart != null) + { + SoundManager.Instance.PlayAtPosition(soundStart, GetTransformInstanceID(), transformPosition); + } + if (soundStartLoop != null) + { + soundStartLoopPlaying = true; + SoundManager.Instance.PlayAtPosition(soundStartLoop, GetTransformInstanceID(), transformPosition); + } + } + + private void OnDestroy() + { + if (triggerEndOnDestroy) + { + PlayEnd(); + } + } + + private void OnDisable() + { + if (triggerEndOnDisable) + { + PlayEnd(); + } + } + + public void PlayEnd() + { + Initialize(); + if (soundEnd != null) + { + SoundManager.Instance.PlayAtPosition(soundEnd, GetTransformInstanceID(), transformPosition); + } + if (soundStartLoopPlaying && soundStartLoop != null) + { + soundStartLoopPlaying = false; + SoundManager.Instance.StopAtPosition(soundStartLoop, transformPosition); + } + } +} diff --git a/ROUNDS/SoundImplementation/SoundVolumeManager.cs b/ROUNDS/SoundImplementation/SoundVolumeManager.cs new file mode 100644 index 0000000..abbd5a5 --- /dev/null +++ b/ROUNDS/SoundImplementation/SoundVolumeManager.cs @@ -0,0 +1,71 @@ +using UnityEngine; +using UnityEngine.Audio; + +namespace SoundImplementation; + +public class SoundVolumeManager : MonoBehaviour +{ + public bool mainMenuFirstTime = true; + + private bool isGoingToDelete; + + private bool useDontDestroyOnLoad = true; + + private bool debugInstanceDestroyed = true; + + public AudioMixer audioMixer; + + private float mixerLowestVolDb = -60f; + + private string masterName = "MasterPrivateVol"; + + private float masterVolOffsetDb = 16f; + + private string musName = "MUSVol"; + + private float musVolOffsetDb = 10f; + + private string sfxName = "SFXVol"; + + private float sfxVolOffsetDb = 10f; + + public static SoundVolumeManager Instance { get; private set; } + + public void SetAudioMixerVolumes(float masterVol, float musicVol, float sfxVol) + { + masterVol = (1f - masterVol) * mixerLowestVolDb; + musicVol = (1f - musicVol) * mixerLowestVolDb; + sfxVol = (1f - sfxVol) * mixerLowestVolDb; + masterVol = ((!(masterVol <= mixerLowestVolDb)) ? (masterVol + masterVolOffsetDb) : (-80f)); + musicVol = ((!(musicVol <= mixerLowestVolDb)) ? (musicVol + musVolOffsetDb) : (-80f)); + sfxVol = ((!(sfxVol <= mixerLowestVolDb)) ? (sfxVol + sfxVolOffsetDb) : (-80f)); + audioMixer.SetFloat(masterName, masterVol); + audioMixer.SetFloat(musName, musicVol); + audioMixer.SetFloat(sfxName, sfxVol); + } + + private void Awake() + { + InstanceCheck(); + if (useDontDestroyOnLoad && !isGoingToDelete) + { + Object.DontDestroyOnLoad(base.gameObject); + } + } + + private void InstanceCheck() + { + if (Instance == null) + { + Instance = this; + } + else if (Instance != this) + { + isGoingToDelete = true; + if (Application.isPlaying) + { + Object.Destroy(base.gameObject); + } + } + } +} diff --git a/ROUNDS/SpawnBulletHit.cs b/ROUNDS/SpawnBulletHit.cs new file mode 100644 index 0000000..27ba4e7 --- /dev/null +++ b/ROUNDS/SpawnBulletHit.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +public class SpawnBulletHit : MonoBehaviour +{ + private void Start() + { + } + + private void Update() + { + } +} diff --git a/ROUNDS/SpawnMinion.cs b/ROUNDS/SpawnMinion.cs new file mode 100644 index 0000000..2b28914 --- /dev/null +++ b/ROUNDS/SpawnMinion.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +public class SpawnMinion : MonoBehaviour +{ + public GameObject card; + + public GameObject minionAI; + + public GameObject minion; + + private CharacterData data; + + private AttackLevel level; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + level = GetComponentInParent<AttackLevel>(); + } + + public void Go() + { + for (int i = 0; i < level.attackLevel; i++) + { + GameObject gameObject = Object.Instantiate(minion, base.transform.position + Vector3.up * (((float)i + 1f) * 0.5f), base.transform.rotation); + Object.Instantiate(minionAI, gameObject.transform.position, gameObject.transform.rotation, gameObject.transform); + CharacterData component = gameObject.GetComponent<CharacterData>(); + component.SetAI(data.player); + component.player.playerID = data.player.playerID; + component.isPlaying = true; + card.GetComponent<ApplyCardStats>().Pick(component.player.teamID, forcePick: true); + gameObject.GetComponentInChildren<PlayerSkinHandler>().ToggleSimpleSkin(isSimple: true); + component.healthHandler.DestroyOnDeath = true; + } + } +} diff --git a/ROUNDS/SpawnObjectEffect.cs b/ROUNDS/SpawnObjectEffect.cs new file mode 100644 index 0000000..a383ff9 --- /dev/null +++ b/ROUNDS/SpawnObjectEffect.cs @@ -0,0 +1,101 @@ +using Sirenix.OdinInspector; +using UnityEngine; + +public class SpawnObjectEffect : MonoBehaviour +{ + public enum Dir + { + TowardsEnemy, + DamageDirction, + ReverseDamageDir, + TowardsRecentlyDamaged + } + + public Dir dir; + + [FoldoutGroup("Gun", 0)] + public bool spawnAttack; + + [FoldoutGroup("Gun", 0)] + public float bulletDamageMultiplier = 0.5f; + + [FoldoutGroup("Gun", 0)] + public int numberOfattacks = 1; + + [FoldoutGroup("Gun", 0)] + public float spread; + + [FoldoutGroup("Gun", 0)] + public float gravityMultiplier = 1f; + + [FoldoutGroup("Gun", 0)] + public float speedMultiplier = 1f; + + [FoldoutGroup("Gun", 0)] + public float extraSpread; + + [FoldoutGroup("Gun", 0)] + public float recoilMultiplier = 1f; + + [FoldoutGroup("Gun", 0)] + public int maxBullets = 100; + + private Holding holding; + + private Gun gun; + + private Player player; + + private void Start() + { + holding = GetComponentInParent<Holding>(); + player = GetComponentInParent<Player>(); + } + + public void DoEffect(Vector2 dmg) + { + int num = 0; + if (!spawnAttack) + { + return; + } + for (int i = 0; i < numberOfattacks; i++) + { + if (!gun && (bool)holding && (bool)holding.holdable) + { + gun = holding.holdable.GetComponent<Gun>(); + } + if ((bool)gun) + { + Quaternion rotation = gun.transform.rotation; + Vector3 vector = (PlayerManager.instance.GetOtherPlayer(player).transform.position - base.transform.position).normalized; + if (dir == Dir.DamageDirction) + { + vector = dmg.normalized; + } + if (dir == Dir.ReverseDamageDir) + { + vector = -dmg.normalized; + } + if (dir == Dir.TowardsRecentlyDamaged) + { + vector = (player.data.lastDamagedPlayer.transform.position - base.transform.position).normalized; + } + gun.transform.rotation = Quaternion.LookRotation(Vector3.forward, vector + gun.transform.right * Random.Range(0f - spread, spread)); + gun.projectileSpeed *= speedMultiplier; + gun.gravity *= gravityMultiplier; + gun.spread += extraSpread; + gun.Attack(1f, forceAttack: true, bulletDamageMultiplier, recoilMultiplier); + num += (int)((float)gun.numberOfProjectiles + gun.chargeNumberOfProjectilesTo); + gun.projectileSpeed /= speedMultiplier; + gun.gravity /= gravityMultiplier; + gun.spread -= extraSpread; + gun.transform.rotation = rotation; + if (num > maxBullets) + { + break; + } + } + } + } +} diff --git a/ROUNDS/SpawnObjectOnDealDamage.cs b/ROUNDS/SpawnObjectOnDealDamage.cs new file mode 100644 index 0000000..be5b365 --- /dev/null +++ b/ROUNDS/SpawnObjectOnDealDamage.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using UnityEngine.Events; + +public class SpawnObjectOnDealDamage : DealtDamageEffect +{ + public UnityEvent triggerEvent; + + public float damageNeeded = 25f; + + public float cd = 0.2f; + + private float time; + + private float damageDealt; + + private SpawnObjectEffect spawn; + + private DamageEffect dmgEffect; + + public bool allowSelfDmg; + + private void Start() + { + spawn = GetComponent<SpawnObjectEffect>(); + dmgEffect = GetComponent<DamageEffect>(); + } + + public override void DealtDamage(Vector2 damage, bool selfDamage, Player damagedPlayer = null) + { + if (selfDamage && !allowSelfDmg) + { + return; + } + damageDealt += damage.magnitude; + if (damageDealt > damageNeeded && Time.time > time + cd) + { + time = Time.time; + damageDealt = 0f; + if ((bool)spawn) + { + spawn.DoEffect(damage); + } + if ((bool)dmgEffect) + { + dmgEffect.DoDamageEffect(damage, selfDamage, damagedPlayer); + } + triggerEvent.Invoke(); + } + } +} diff --git a/ROUNDS/SpawnObjectOnDealtDamage.cs b/ROUNDS/SpawnObjectOnDealtDamage.cs new file mode 100644 index 0000000..0c4d8cf --- /dev/null +++ b/ROUNDS/SpawnObjectOnDealtDamage.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +public class SpawnObjectOnDealtDamage : WasDealtDamageEffect +{ + public float damageNeeded = 25f; + + public float cd = 0.2f; + + public bool allowSelfDamage; + + private float time; + + private float damageDealt; + + private SpawnObjectEffect spawn; + + private void Start() + { + spawn = GetComponent<SpawnObjectEffect>(); + } + + public override void WasDealtDamage(Vector2 damage, bool selfDamage) + { + if (!selfDamage || allowSelfDamage) + { + damageDealt += damage.magnitude; + if (damageDealt > damageNeeded && Time.time > time + cd) + { + time = Time.time; + damageDealt = 0f; + spawn.DoEffect(damage); + } + } + } +} diff --git a/ROUNDS/SpawnObjects.cs b/ROUNDS/SpawnObjects.cs new file mode 100644 index 0000000..8f00c7a --- /dev/null +++ b/ROUNDS/SpawnObjects.cs @@ -0,0 +1,83 @@ +using System; +using Photon.Pun; +using UnityEngine; + +public class SpawnObjects : MonoBehaviour +{ + public enum SpawnRot + { + Identity, + TransformRotation + } + + public GameObject[] objectToSpawn; + + public SpawnRot spawnRot; + + public bool inheritScale; + + public bool destroyObject; + + public bool destroyRoot; + + private PhotonView view; + + public Action<GameObject> SpawnedAction; + + [HideInInspector] + public GameObject mostRecentlySpawnedObject; + + private void ConfigureObject(GameObject go) + { + SpawnedAttack spawnedAttack = go.GetComponent<SpawnedAttack>(); + if (!spawnedAttack) + { + spawnedAttack = go.AddComponent<SpawnedAttack>(); + } + spawnedAttack.spawner = base.transform.root.GetComponent<Player>(); + if (!spawnedAttack.spawner) + { + SpawnedAttack componentInParent = base.transform.GetComponentInParent<SpawnedAttack>(); + if ((bool)componentInParent) + { + componentInParent.CopySpawnedAttackTo(go); + } + } + AttackLevel componentInParent2 = GetComponentInParent<AttackLevel>(); + if ((bool)componentInParent2) + { + spawnedAttack.attackLevel = componentInParent2.attackLevel; + } + if (inheritScale) + { + go.transform.localScale *= base.transform.localScale.x; + } + if (SpawnedAction != null) + { + SpawnedAction(go); + } + } + + public void Spawn() + { + for (int i = 0; i < objectToSpawn.Length; i++) + { + Quaternion rotation = Quaternion.identity; + if (spawnRot == SpawnRot.TransformRotation) + { + rotation = base.transform.rotation; + } + GameObject go = UnityEngine.Object.Instantiate(objectToSpawn[i], base.transform.position, rotation); + ConfigureObject(go); + mostRecentlySpawnedObject = go; + } + if (destroyObject) + { + UnityEngine.Object.Destroy(base.gameObject); + } + if (destroyRoot) + { + UnityEngine.Object.Destroy(base.transform.root.gameObject); + } + } +} diff --git a/ROUNDS/SpawnPoint.cs b/ROUNDS/SpawnPoint.cs new file mode 100644 index 0000000..5a4a0cf --- /dev/null +++ b/ROUNDS/SpawnPoint.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +public class SpawnPoint : MonoBehaviour +{ + public int ID; + + public int TEAMID; + + public Vector3 localStartPos; + + private void Awake() + { + localStartPos = base.transform.localPosition; + } +} diff --git a/ROUNDS/SpawnStaticRemnant.cs b/ROUNDS/SpawnStaticRemnant.cs new file mode 100644 index 0000000..9e0a67e --- /dev/null +++ b/ROUNDS/SpawnStaticRemnant.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class SpawnStaticRemnant : MonoBehaviour +{ + public GameObject remnantSource; + + private AttackLevel level; + + private Color remnantColor; + + private void Start() + { + remnantColor = PlayerSkinBank.GetPlayerSkinColors(base.transform.GetComponentInParent<Player>().playerID).winText; + level = GetComponent<AttackLevel>(); + } + + public void Go() + { + GameObject gameObject = Object.Instantiate(remnantSource, base.transform.position, base.transform.rotation); + SpriteRenderer[] componentsInChildren = base.transform.root.GetComponentsInChildren<SpriteRenderer>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (componentsInChildren[i].transform.lossyScale.x != 0f && componentsInChildren[i].transform.lossyScale.y != 0f && componentsInChildren[i].transform.lossyScale.z != 0f && (!(componentsInChildren[i].transform.parent.name != "Art") || !(componentsInChildren[i].transform.parent.parent.name != "Face"))) + { + Vector3 lossyScale = componentsInChildren[i].transform.lossyScale; + GameObject gameObject2 = Object.Instantiate(componentsInChildren[i].gameObject, componentsInChildren[i].transform.position, componentsInChildren[i].transform.rotation, gameObject.transform.GetChild(0)); + gameObject2.transform.localScale = lossyScale; + Strip(gameObject2); + SpriteRenderer component = gameObject2.GetComponent<SpriteRenderer>(); + component.enabled = true; + component.color = remnantColor; + SpriteMask component2 = gameObject2.GetComponent<SpriteMask>(); + if ((bool)component2) + { + Object.Destroy(component2); + } + } + } + gameObject.GetComponentInChildren<ParticleSystem>().startColor = PlayerSkinBank.GetPlayerSkinColors(base.transform.GetComponentInParent<Player>().playerID).particleEffect; + gameObject.AddComponent<SpawnedAttack>().spawner = base.transform.root.GetComponent<Player>(); + gameObject.transform.localScale *= 1f + (float)(level.attackLevel - 1) * 0.3f; + } + + private void Strip(GameObject go) + { + MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + Object.Destroy(componentsInChildren[i]); + } + } +} diff --git a/ROUNDS/SpawnedAttack.cs b/ROUNDS/SpawnedAttack.cs new file mode 100644 index 0000000..8a4a096 --- /dev/null +++ b/ROUNDS/SpawnedAttack.cs @@ -0,0 +1,63 @@ +using Photon.Pun; +using UnityEngine; + +public class SpawnedAttack : MonoBehaviour +{ + public Player spawner; + + public int attackLevel; + + public int attackID; + + public PhotonView view; + + private void Awake() + { + view = GetComponent<PhotonView>(); + } + + [PunRPC] + public void RPCA_SetSpawner(int spawnerID) + { + spawner = PhotonNetwork.GetPhotonView(spawnerID).GetComponent<Player>(); + } + + public void CopySpawnedAttackTo(GameObject to) + { + SpawnedAttack spawnedAttack = to.GetComponent<SpawnedAttack>(); + if (!spawnedAttack) + { + spawnedAttack = to.AddComponent<SpawnedAttack>(); + } + spawnedAttack.spawner = spawner; + spawnedAttack.attackLevel = attackLevel; + } + + public void SetColor(Color color) + { + TrailRenderer[] componentsInChildren = GetComponentsInChildren<TrailRenderer>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].startColor = color; + componentsInChildren[i].endColor = color; + } + ProjectileHit component = GetComponent<ProjectileHit>(); + if ((bool)component) + { + component.projectileColor = color; + } + } + + public bool IsMine() + { + if ((bool)view) + { + return view.IsMine; + } + if ((bool)spawner) + { + return spawner.data.view.IsMine; + } + return false; + } +} diff --git a/ROUNDS/SpawnedAttack_ParentPlayer.cs b/ROUNDS/SpawnedAttack_ParentPlayer.cs new file mode 100644 index 0000000..f77247f --- /dev/null +++ b/ROUNDS/SpawnedAttack_ParentPlayer.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class SpawnedAttack_ParentPlayer : MonoBehaviour +{ + private void Start() + { + GetComponent<SpawnedAttack>().spawner = GetComponentInParent<Player>(); + } +} diff --git a/ROUNDS/Spring.cs b/ROUNDS/Spring.cs new file mode 100644 index 0000000..35cb057 --- /dev/null +++ b/ROUNDS/Spring.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +public class Spring : MonoBehaviour +{ + public float spring = 1f; + + private Rigidbody2D rig; + + private Vector3 up; + + private void Start() + { + rig = GetComponent<Rigidbody2D>(); + up = base.transform.up; + } + + private void FixedUpdate() + { + if ((bool)rig) + { + rig.AddTorque((Vector3.Cross(base.transform.up, up).normalized * Vector3.Angle(base.transform.up, up)).z * spring * rig.mass); + } + } +} diff --git a/ROUNDS/StandStillTrigger.cs b/ROUNDS/StandStillTrigger.cs new file mode 100644 index 0000000..b5dc487 --- /dev/null +++ b/ROUNDS/StandStillTrigger.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +public class StandStillTrigger : MonoBehaviour +{ + public float sinceStandStill; + + private CharacterData data; + + private void Start() + { + data = base.transform.GetComponentInParent<CharacterData>(); + } + + private void Update() + { + if (data.isGrounded && data.input.direction.magnitude < 0.1f) + { + sinceStandStill += TimeHandler.deltaTime; + } + else + { + sinceStandStill = 0f; + } + } +} diff --git a/ROUNDS/StartEvent.cs b/ROUNDS/StartEvent.cs new file mode 100644 index 0000000..b05cd6e --- /dev/null +++ b/ROUNDS/StartEvent.cs @@ -0,0 +1,12 @@ +using UnityEngine; +using UnityEngine.Events; + +public class StartEvent : MonoBehaviour +{ + public UnityEvent startEvent; + + private void Start() + { + startEvent.Invoke(); + } +} diff --git a/ROUNDS/StatsAfterDealingDamage.cs b/ROUNDS/StatsAfterDealingDamage.cs new file mode 100644 index 0000000..d228813 --- /dev/null +++ b/ROUNDS/StatsAfterDealingDamage.cs @@ -0,0 +1,68 @@ +using UnityEngine; +using UnityEngine.Events; + +public class StatsAfterDealingDamage : MonoBehaviour +{ + public float duration = 3f; + + public float movementSpeedMultiplier = 1f; + + public float jumpMultiplier = 1f; + + public float hpMultiplier = 1f; + + public UnityEvent startEvent; + + public UnityEvent endEvent; + + private bool isOn; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + bool flag = data.stats.sinceDealtDamage < duration; + if (isOn != flag) + { + isOn = flag; + _ = base.transform.localScale; + if (isOn) + { + data.health *= hpMultiplier; + data.maxHealth *= hpMultiplier; + data.stats.movementSpeed *= movementSpeedMultiplier; + data.stats.jump *= jumpMultiplier; + data.stats.ConfigureMassAndSize(); + startEvent.Invoke(); + } + else + { + data.health /= hpMultiplier; + data.maxHealth /= hpMultiplier; + data.stats.movementSpeed /= movementSpeedMultiplier; + data.stats.jump /= jumpMultiplier; + data.stats.ConfigureMassAndSize(); + endEvent.Invoke(); + } + } + } + + public void Interupt() + { + if (isOn) + { + data.health /= hpMultiplier; + data.maxHealth /= hpMultiplier; + data.stats.movementSpeed /= movementSpeedMultiplier; + data.stats.jump /= jumpMultiplier; + data.stats.ConfigureMassAndSize(); + endEvent.Invoke(); + isOn = false; + } + } +} diff --git a/ROUNDS/StatsWhenFullHP.cs b/ROUNDS/StatsWhenFullHP.cs new file mode 100644 index 0000000..21166c7 --- /dev/null +++ b/ROUNDS/StatsWhenFullHP.cs @@ -0,0 +1,58 @@ +using Sonigon; +using UnityEngine; + +public class StatsWhenFullHP : MonoBehaviour +{ + public bool playSound; + + public SoundEvent soundPristineGrow; + + public SoundEvent soundPristineShrink; + + public float healthMultiplier = 1f; + + public float sizeMultiplier = 1f; + + public float healthThreshold = 0.95f; + + private CharacterData data; + + private bool isOn; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + private void Update() + { + bool flag = data.health / data.maxHealth >= healthThreshold; + if (flag == isOn) + { + return; + } + isOn = flag; + if (isOn) + { + if (playSound) + { + SoundManager.Instance.PlayAtPosition(soundPristineGrow, SoundManager.Instance.GetTransform(), base.transform); + } + data.health *= healthMultiplier; + data.maxHealth *= healthMultiplier; + data.stats.sizeMultiplier *= sizeMultiplier; + data.stats.ConfigureMassAndSize(); + } + else + { + if (playSound) + { + SoundManager.Instance.PlayAtPosition(soundPristineShrink, SoundManager.Instance.GetTransform(), base.transform); + } + data.health /= healthMultiplier; + data.maxHealth /= healthMultiplier; + data.stats.sizeMultiplier /= sizeMultiplier; + data.stats.ConfigureMassAndSize(); + } + } +} diff --git a/ROUNDS/SteamManager.cs b/ROUNDS/SteamManager.cs new file mode 100644 index 0000000..9f30390 --- /dev/null +++ b/ROUNDS/SteamManager.cs @@ -0,0 +1,99 @@ +using System; +using System.Text; +using Steamworks; +using UnityEngine; + +[DisallowMultipleComponent] +public class SteamManager : MonoBehaviour +{ + protected static bool s_EverInitialized; + + protected static SteamManager s_instance; + + protected bool m_bInitialized; + + protected SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook; + + protected static SteamManager Instance + { + get + { + if (s_instance == null) + { + return new GameObject("SteamManager").AddComponent<SteamManager>(); + } + return s_instance; + } + } + + public static bool Initialized => Instance.m_bInitialized; + + protected static void SteamAPIDebugTextHook(int nSeverity, StringBuilder pchDebugText) + { + } + + protected virtual void Awake() + { + if (s_instance != null) + { + UnityEngine.Object.Destroy(base.gameObject); + return; + } + s_instance = this; + if (s_EverInitialized) + { + throw new Exception("Tried to Initialize the SteamAPI twice in one session!"); + } + UnityEngine.Object.DontDestroyOnLoad(base.gameObject); + if (!Packsize.Test()) + { + Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this); + } + if (!DllCheck.Test()) + { + Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this); + } + m_bInitialized = SteamAPI.Init(); + if (!m_bInitialized) + { + Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this); + } + else + { + s_EverInitialized = true; + } + } + + protected virtual void OnEnable() + { + if (s_instance == null) + { + s_instance = this; + } + if (m_bInitialized && m_SteamAPIWarningMessageHook == null) + { + m_SteamAPIWarningMessageHook = SteamAPIDebugTextHook; + SteamClient.SetWarningMessageHook(m_SteamAPIWarningMessageHook); + } + } + + protected virtual void OnDestroy() + { + if (!(s_instance != this)) + { + s_instance = null; + if (m_bInitialized) + { + SteamAPI.Shutdown(); + } + } + } + + protected virtual void Update() + { + if (m_bInitialized) + { + SteamAPI.RunCallbacks(); + } + } +} diff --git a/ROUNDS/StopRecursion.cs b/ROUNDS/StopRecursion.cs new file mode 100644 index 0000000..e77fbb7 --- /dev/null +++ b/ROUNDS/StopRecursion.cs @@ -0,0 +1,5 @@ +using UnityEngine; + +public class StopRecursion : MonoBehaviour +{ +} diff --git a/ROUNDS/StunHandler.cs b/ROUNDS/StunHandler.cs new file mode 100644 index 0000000..bb3f93e --- /dev/null +++ b/ROUNDS/StunHandler.cs @@ -0,0 +1,102 @@ +using Sonigon; +using UnityEngine; + +public class StunHandler : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterStunLoop; + + private bool soundStunIsPlaying; + + [Header("Settings")] + public CodeAnimation codeAnim; + + private Player player; + + private CharacterData data; + + private void Start() + { + player = GetComponent<Player>(); + data = player.data; + } + + private void Update() + { + if (data.stunTime > 0f) + { + data.stunTime -= TimeHandler.deltaTime; + data.sinceGrounded = 0f; + if (!data.isStunned) + { + StartStun(); + } + } + else if (data.isStunned) + { + StopStun(); + } + if (data.isStunned && data.isPlaying && !data.dead) + { + if (!soundStunIsPlaying) + { + soundStunIsPlaying = true; + SoundManager.Instance.Play(soundCharacterStunLoop, base.transform); + } + } + else if (soundStunIsPlaying) + { + soundStunIsPlaying = false; + SoundManager.Instance.Stop(soundCharacterStunLoop, base.transform); + } + } + + private void StartStun() + { + player.data.playerVel.velocity *= 0f; + player.data.playerVel.isKinematic = true; + player.data.input.stunnedInput = true; + codeAnim.PlayIn(); + data.isStunned = true; + } + + public void StopStun() + { + player.data.playerVel.isKinematic = false; + player.data.input.stunnedInput = false; + if (codeAnim.currentState == CodeAnimationInstance.AnimationUse.In) + { + codeAnim.PlayOut(); + } + data.isStunned = false; + data.stunTime = 0f; + } + + private void OnDisable() + { + codeAnim.transform.localScale = Vector3.zero; + soundStunIsPlaying = false; + SoundManager.Instance.Stop(soundCharacterStunLoop, base.transform); + } + + private void OnDestroy() + { + soundStunIsPlaying = false; + SoundManager.Instance.Stop(soundCharacterStunLoop, base.transform); + } + + public void AddStun(float f) + { + if (!data.block.IsBlocking()) + { + if (f > data.stunTime) + { + data.stunTime = f; + } + if (!data.isStunned) + { + StartStun(); + } + } + } +} diff --git a/ROUNDS/StunPlayer.cs b/ROUNDS/StunPlayer.cs new file mode 100644 index 0000000..c131626 --- /dev/null +++ b/ROUNDS/StunPlayer.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class StunPlayer : MonoBehaviour +{ + public enum TargetPlayer + { + OtherPlayer, + Self + } + + public TargetPlayer targetPlayer; + + public float time = 0.5f; + + private Player target; + + public void Go() + { + if (!target) + { + target = GetComponentInParent<Player>(); + if (targetPlayer == TargetPlayer.OtherPlayer) + { + target = PlayerManager.instance.GetOtherPlayer(target); + } + } + target.data.stunHandler.AddStun(time); + } +} diff --git a/ROUNDS/SuperBasicController.cs b/ROUNDS/SuperBasicController.cs new file mode 100644 index 0000000..6456afc --- /dev/null +++ b/ROUNDS/SuperBasicController.cs @@ -0,0 +1,327 @@ +using Photon.Pun; +using Photon.Pun.Simple; +using UnityEngine; + +public class SuperBasicController : NetComponent +{ + public bool is2D; + + [Range(0f, 300f)] + public float turnSpeed = 150f; + + [Range(0f, 4f)] + public float moveSpeed = 4f; + + public bool autoMove = true; + + private Vector3 targRotDelta; + + private Vector3 targPosDelta; + + private float appliedDeltaT; + + private Animator animator; + + private SyncAnimator syncAnimator; + + private SyncTransform syncTransform; + + private SyncCannon syncLauncher; + + private SyncContactScan syncHitscan; + + private bool triggerJump; + + private bool triggerFade; + + private bool triggerTurnLeft; + + private bool triggerUpperBodyRun; + + private bool triggerUpperBodyIdle; + + private bool triggerTeleport; + + private bool freakingOut; + + private bool triggerHitscan; + + private bool triggerProjectile; + + private bool triggerBlend; + + public override void OnAwake() + { + base.OnAwake(); + animator = base.transform.GetNestedComponentInChildren<Animator, NetObject>(includeInactive: true); + syncAnimator = base.transform.GetNestedComponentInChildren<SyncAnimator, NetObject>(includeInactive: true); + syncTransform = GetComponent<SyncTransform>(); + syncLauncher = base.transform.GetNestedComponentInChildren<SyncCannon, NetObject>(includeInactive: true); + syncHitscan = base.transform.GetNestedComponentInChildren<SyncContactScan, NetObject>(includeInactive: true); + } + + private void Update() + { + if (!base.IsMine) + { + return; + } + float t = (Time.time - Time.fixedTime) / Time.fixedDeltaTime; + Interpolate(t); + if (Input.GetKeyDown(KeyCode.Space)) + { + triggerJump = true; + } + if (Input.GetKeyDown(KeyCode.Alpha2)) + { + triggerFade = true; + } + if (Input.GetKeyDown(KeyCode.Alpha1)) + { + triggerTurnLeft = true; + } + if (Input.GetKeyDown(KeyCode.Alpha4)) + { + if (freakingOut) + { + triggerUpperBodyIdle = true; + } + else + { + triggerUpperBodyRun = true; + } + freakingOut = !freakingOut; + } + if (Input.GetKeyDown(KeyCode.F)) + { + triggerProjectile = true; + } + if (Input.GetKeyDown(KeyCode.R)) + { + triggerHitscan = true; + } + if (Input.GetKeyDown(KeyCode.T)) + { + triggerTeleport = true; + } + if (Input.GetKeyDown(KeyCode.B)) + { + triggerBlend = true; + } + } + + private void FixedUpdate() + { + if (!base.IsMine) + { + return; + } + Vector3 move = new Vector3(0f, 0f, 0f); + Vector3 turn = new Vector3(0f, 0f, 0f); + if ((bool)animator && animator.isActiveAndEnabled) + { + if (Input.GetKey(KeyCode.W)) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", 1f); + } + else if (Input.GetKey(KeyCode.S)) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", -0.5f); + } + else + { + animator.SetBool("walking", value: false); + animator.SetFloat("speed", 0f); + } + if (triggerJump) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("jump"); + } + triggerJump = false; + } + else if (triggerTurnLeft) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("turnLeft"); + } + triggerTurnLeft = false; + } + if (triggerFade) + { + if ((bool)syncAnimator) + { + syncAnimator.CrossFadeInFixedTime("Jump", 0.25f); + } + triggerFade = false; + } + if (triggerBlend) + { + animator.SetFloat("blender", Mathf.Abs(Mathf.Sin(Time.time))); + } + else + { + animator.SetFloat("blender", -1f); + } + if (triggerUpperBodyRun) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("upperBodyRun"); + } + triggerUpperBodyRun = false; + } + else if (triggerUpperBodyIdle) + { + if ((bool)syncAnimator) + { + syncAnimator.SetTrigger("upperBodyIdle"); + } + triggerUpperBodyIdle = false; + } + } + if (!animator || !animator.applyRootMotion) + { + if (Input.GetKey(KeyCode.W)) + { + move += Vector3.forward; + } + else if (Input.GetKey(KeyCode.S)) + { + move -= Vector3.forward; + } + } + if (Input.GetKey(KeyCode.A)) + { + move -= Vector3.right; + } + if (Input.GetKey(KeyCode.D)) + { + move += Vector3.right; + } + if (Input.GetKey(KeyCode.E)) + { + turn += Vector3.up; + } + if (Input.GetKey(KeyCode.Q)) + { + turn -= Vector3.up; + } + if (Input.touchCount > 0) + { + Touch touch = Input.GetTouch(0); + Vector2 vector = new Vector2(touch.rawPosition.x / (float)Screen.width, touch.rawPosition.y / (float)Screen.height); + if (vector.y > 0.66f) + { + if (vector.x > 0.66f) + { + triggerHitscan = true; + } + else if (vector.x < 0.33f) + { + triggerJump = true; + } + } + else if (vector.y < 0.33f) + { + if (vector.x > 0.66f) + { + move += Vector3.right; + } + else if (vector.x < 0.33f) + { + move -= Vector3.right; + } + else if ((bool)animator) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", -0.5f); + } + } + else if (vector.x > 0.66f) + { + turn += Vector3.up; + } + else if (vector.x < 0.33f) + { + turn -= Vector3.up; + } + else if ((bool)animator) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", 1f); + } + } + if (autoMove && !Application.isFocused) + { + turn += new Vector3(0f, Mathf.Sin(Time.time * 0.5f), 0f); + if ((bool)animator) + { + animator.SetBool("walking", value: true); + animator.SetFloat("speed", Mathf.Sin(Time.time) * 0.5f); + } + } + Interpolate(1f); + Move(move, turn); + appliedDeltaT = 0f; + if (triggerHitscan) + { + if ((bool)syncHitscan) + { + syncHitscan.QueueTrigger(); + } + triggerHitscan = false; + } + if (triggerProjectile) + { + if ((bool)syncLauncher) + { + syncLauncher.QueueTrigger(); + } + triggerProjectile = false; + } + if (triggerTeleport) + { + if ((bool)syncTransform) + { + syncTransform.FlagTeleport(); + base.transform.localPosition = default(Vector3); + base.transform.localRotation = default(Quaternion); + } + triggerTeleport = false; + } + } + + private void OnAnimatorMove() + { + if (base.IsMine) + { + animator.ApplyBuiltinRootMotion(); + base.transform.rotation = animator.rootRotation; + base.transform.position = animator.rootPosition; + } + } + + private void Move(Vector3 move, Vector3 turn) + { + if (is2D) + { + move = new Vector3(move.x, move.z, 0f); + turn = new Vector3(0f, 0f, turn.y); + } + targRotDelta = turn * turnSpeed * Time.fixedDeltaTime; + targPosDelta = move * moveSpeed * Time.fixedDeltaTime; + } + + private void Interpolate(float t) + { + t -= appliedDeltaT; + appliedDeltaT += t; + base.transform.rotation = base.transform.rotation * Quaternion.Euler(targRotDelta * t); + base.transform.position += base.transform.rotation * (targPosDelta * t); + } +} diff --git a/ROUNDS/SwordArtMove.cs b/ROUNDS/SwordArtMove.cs new file mode 100644 index 0000000..b521e51 --- /dev/null +++ b/ROUNDS/SwordArtMove.cs @@ -0,0 +1,61 @@ +using UnityEngine; + +public class SwordArtMove : MonoBehaviour +{ + private MoveTransform move; + + public LayerMask mask; + + public AnimationCurve heightCurve; + + public AnimationCurve AwayCurve; + + private Vector3 startUp; + + private Vector3 startForward; + + private Vector3 startPos; + + public float multiplier = 1f; + + public float heightMultiplier = 1f; + + public float awayMultiplier = 1f; + + public float speed = 1f; + + private float counter; + + private ParticleSystem[] parts; + + private void Start() + { + parts = GetComponentsInChildren<ParticleSystem>(); + move = GetComponentInParent<MoveTransform>(); + move.enabled = false; + startForward = base.transform.forward; + startUp = Vector3.Cross(base.transform.forward, Vector3.forward); + startPos = base.transform.position; + awayMultiplier *= Mathf.Pow(move.localForce.magnitude / 40f * 2f, 0.45f); + awayMultiplier /= 1f + move.drag * 0.05f; + speed *= Mathf.Pow(awayMultiplier, 0.3f); + } + + private void Update() + { + counter += TimeHandler.deltaTime * speed; + Vector3 vector = startPos + (heightCurve.Evaluate(counter) * heightMultiplier * startUp + AwayCurve.Evaluate(counter) * awayMultiplier * startForward) * multiplier; + RaycastHit2D raycastHit2D = Physics2D.Raycast(startPos, (vector - startPos).normalized, Vector3.Distance(vector, startPos), mask); + if ((bool)raycastHit2D.transform && !raycastHit2D.collider.GetComponent<Damagable>()) + { + vector = raycastHit2D.point + raycastHit2D.normal * 0.1f; + for (int i = 0; i < parts.Length; i++) + { + parts[i].transform.position = (Vector3)raycastHit2D.point + Vector3.forward * 8f; + parts[i].transform.rotation = Quaternion.LookRotation(raycastHit2D.normal); + parts[i].Emit(1); + } + } + base.transform.root.position = vector; + } +} diff --git a/ROUNDS/TasteOfBlood.cs b/ROUNDS/TasteOfBlood.cs new file mode 100644 index 0000000..1a7ed41 --- /dev/null +++ b/ROUNDS/TasteOfBlood.cs @@ -0,0 +1,66 @@ +using System; +using UnityEngine; + +public class TasteOfBlood : MonoBehaviour +{ + public AnimationCurve attackSpeedCurve; + + public float decaySpeed = 1f; + + private float damageValue; + + private CharacterStatModifiers stats; + + private ParticleSystem part; + + private CharacterData data; + + private bool isOn; + + private void Start() + { + part = GetComponentInChildren<ParticleSystem>(); + stats = GetComponentInParent<CharacterStatModifiers>(); + CharacterStatModifiers characterStatModifiers = stats; + characterStatModifiers.DealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(characterStatModifiers.DealtDamageAction, new Action<Vector2, bool>(DealtDamage)); + data = GetComponentInParent<CharacterData>(); + } + + public void DealtDamage(Vector2 damage, bool selfDamage) + { + if (!selfDamage) + { + damageValue += damage.magnitude; + } + damageValue = Mathf.Clamp(damageValue, 0f, 50f); + } + + private void Update() + { + if (!data.isPlaying) + { + damageValue = 0f; + } + if (damageValue > 0f) + { + damageValue -= TimeHandler.deltaTime * decaySpeed; + isOn = true; + } + else + { + isOn = false; + } + if (damageValue > 10f) + { + if (!part.isPlaying) + { + part.Play(); + } + } + else if (part.isPlaying) + { + part.Stop(); + } + stats.tasteOfBloodSpeed = attackSpeedCurve.Evaluate(damageValue); + } +} diff --git a/ROUNDS/Teleport.cs b/ROUNDS/Teleport.cs new file mode 100644 index 0000000..614ccdc --- /dev/null +++ b/ROUNDS/Teleport.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections; +using UnityEngine; + +public class Teleport : MonoBehaviour +{ + public ParticleSystem[] parts; + + public ParticleSystem[] remainParts; + + public float distance = 10f; + + public LayerMask mask; + + private CharacterData data; + + private AttackLevel level; + + private void Start() + { + parts = GetComponentsInChildren<ParticleSystem>(); + data = GetComponentInParent<CharacterData>(); + level = GetComponentInParent<AttackLevel>(); + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Combine(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(Go)); + } + + private void OnDestroy() + { + Block componentInParent = GetComponentInParent<Block>(); + componentInParent.SuperFirstBlockAction = (Action<BlockTrigger.BlockTriggerType>)Delegate.Remove(componentInParent.SuperFirstBlockAction, new Action<BlockTrigger.BlockTriggerType>(Go)); + } + + public void Go(BlockTrigger.BlockTriggerType triggerType) + { + StartCoroutine(DelayMove(triggerType, base.transform.position)); + } + + private IEnumerator DelayMove(BlockTrigger.BlockTriggerType triggerType, Vector3 beforePos) + { + if (triggerType == BlockTrigger.BlockTriggerType.Empower) + { + yield return new WaitForSeconds(0f); + } + Vector3 position = base.transform.position; + Vector3 position2 = base.transform.position; + int num = 10; + float num2 = distance * (float)level.attackLevel / (float)num; + for (int i = 0; i < num; i++) + { + position += num2 * data.aimDirection; + if (!Physics2D.OverlapCircle(position, 0.5f)) + { + position2 = position; + } + } + for (int j = 0; j < remainParts.Length; j++) + { + remainParts[j].transform.position = base.transform.root.position; + remainParts[j].Play(); + } + GetComponentInParent<PlayerCollision>().IgnoreWallForFrames(2); + if (triggerType == BlockTrigger.BlockTriggerType.Empower) + { + position2 = beforePos; + } + base.transform.root.position = position2; + for (int k = 0; k < parts.Length; k++) + { + parts[k].transform.position = position2; + parts[k].Play(); + } + data.playerVel.velocity *= 0f; + data.sinceGrounded = 0f; + } +} diff --git a/ROUNDS/TeleportToOpponent.cs b/ROUNDS/TeleportToOpponent.cs new file mode 100644 index 0000000..193c632 --- /dev/null +++ b/ROUNDS/TeleportToOpponent.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class TeleportToOpponent : MonoBehaviour +{ + public float time = 0.5f; + + public ParticleSystem from; + + public ParticleSystem to; + + private Player target; + + private void Start() + { + } + + public void Go() + { + if (!target) + { + target = PlayerManager.instance.GetOtherPlayer(GetComponentInParent<Player>()); + } + from.Play(); + base.transform.root.transform.position = target.transform.position + (target.transform.position - base.transform.position).normalized; + to.Play(); + } +} diff --git a/ROUNDS/TextFlicker.cs b/ROUNDS/TextFlicker.cs new file mode 100644 index 0000000..e710a43 --- /dev/null +++ b/ROUNDS/TextFlicker.cs @@ -0,0 +1,35 @@ +using TMPro; +using UnityEngine; + +public class TextFlicker : MonoBehaviour +{ + public string[] strings; + + public float rate = 0.2f; + + private float counter; + + private int currentID; + + private TextMeshProUGUI text; + + private void Start() + { + text = GetComponent<TextMeshProUGUI>(); + } + + private void Update() + { + counter += Time.deltaTime; + if (counter > rate) + { + counter = 0f; + currentID++; + if (currentID >= strings.Length) + { + currentID = 0; + } + text.text = strings[currentID]; + } + } +} diff --git a/ROUNDS/ThereCanOnlyBeOne.cs b/ROUNDS/ThereCanOnlyBeOne.cs new file mode 100644 index 0000000..78dd68d --- /dev/null +++ b/ROUNDS/ThereCanOnlyBeOne.cs @@ -0,0 +1,30 @@ +using UnityEngine; +using UnityEngine.Events; + +public class ThereCanOnlyBeOne : MonoBehaviour +{ + public UnityEvent PokeEvent; + + private void Start() + { + bool flag = false; + ThereCanOnlyBeOne[] componentsInChildren = base.transform.root.GetComponentsInChildren<ThereCanOnlyBeOne>(); + for (int i = 0; i < componentsInChildren.Length; i++) + { + if (!(componentsInChildren[i] == this)) + { + flag = true; + componentsInChildren[i].Poke(); + } + } + if (flag) + { + Object.Destroy(base.gameObject); + } + } + + public void Poke() + { + PokeEvent.Invoke(); + } +} diff --git a/ROUNDS/Thruster.cs b/ROUNDS/Thruster.cs new file mode 100644 index 0000000..2555c98 --- /dev/null +++ b/ROUNDS/Thruster.cs @@ -0,0 +1,85 @@ +using UnityEngine; + +public class Thruster : MonoBehaviour +{ + public float force; + + public float drag; + + public float pow = 1f; + + public float physicsObjectM = 1f; + + private FollowLocalPos follow; + + private Rigidbody2D rig; + + private Vector2 startForward; + + private NetworkPhysicsObject pushed; + + private Player player; + + private bool checkedForPlayer; + + private void Start() + { + force *= Mathf.Pow(base.transform.localScale.x, pow); + drag *= Mathf.Pow(base.transform.localScale.x, pow); + follow = GetComponent<FollowLocalPos>(); + if ((bool)follow.target) + { + pushed = follow.target.gameObject.GetComponent<NetworkPhysicsObject>(); + } + float num = 1f; + if (!follow.targetPlayer) + { + num = 0.2f; + } + else if ((bool)pushed) + { + num = 0.5f; + } + ParticleSystem.MainModule main = GetComponentInChildren<ParticleSystem>().main; + main.duration *= num; + GetComponent<DelayEvent>().time *= num; + GetComponent<RemoveAfterSeconds>().seconds *= num; + startForward = base.transform.forward; + } + + private void FixedUpdate() + { + if (!follow) + { + return; + } + if ((bool)follow.target) + { + if ((bool)player) + { + if ((bool)player) + { + player.data.healthHandler.TakeForce(startForward * force, ForceMode2D.Force); + } + else + { + rig.AddForce(startForward * force, ForceMode2D.Force); + } + } + else if (!checkedForPlayer) + { + player = follow.target.transform.root.GetComponent<Player>(); + checkedForPlayer = true; + if (!player && !pushed) + { + base.enabled = false; + } + } + } + if ((bool)pushed && pushed.photonView.IsMine) + { + pushed.RPCA_SendForce(base.transform.forward * force * physicsObjectM, pushed.transform.InverseTransformPoint(base.transform.position)); + } + + } +} diff --git a/ROUNDS/TickMover.cs b/ROUNDS/TickMover.cs new file mode 100644 index 0000000..841ffc4 --- /dev/null +++ b/ROUNDS/TickMover.cs @@ -0,0 +1,41 @@ +using Photon.Pun.Simple; +using UnityEngine; + +public class TickMover : MonoBehaviour, IOnPostSimulate +{ + private Vector3 rotationPerTick; + + private TextMesh tickText; + + private void Awake() + { + NetMasterCallbacks.RegisterCallbackInterfaces(this); + rotationPerTick = new Vector3(0f, 0f, 360f * (Time.fixedDeltaTime * (float)TickEngineSettings.sendEveryXTick)); + tickText = GetComponentInChildren<TextMesh>(); + if (!tickText) + { + tickText = GetComponentInParent<TextMesh>(); + } + if ((bool)tickText) + { + tickText.text = ""; + } + } + + private void OnDestroy() + { + NetMasterCallbacks.RegisterCallbackInterfaces(this, register: false, delay: true); + } + + public void OnPostSimulate(int frameId, int subFrameId, bool isNetTick) + { + if (isNetTick) + { + base.transform.eulerAngles -= rotationPerTick; + if ((bool)tickText) + { + tickText.text = frameId.ToString(); + } + } + } +} diff --git a/ROUNDS/TimeHandler.cs b/ROUNDS/TimeHandler.cs new file mode 100644 index 0000000..f038df5 --- /dev/null +++ b/ROUNDS/TimeHandler.cs @@ -0,0 +1,96 @@ +using System.Collections; +using Photon.Pun; +using UnityEngine; + +public class TimeHandler : MonoBehaviour +{ + public AnimationCurve slowDown; + + public AnimationCurve speedUp; + + public float baseTimeScale = 0.85f; + + public float gameOverTime = 1f; + + public float gameStartTime; + + public float timeStop = 1f; + + public static float timeScale = 1f; + + public static TimeHandler instance; + + public static float deltaTime; + + public static float fixedDeltaTime; + + private void Awake() + { + instance = this; + } + + private void Update() + { + float num = baseTimeScale; + if (gameOverTime < 1f) + { + num *= gameOverTime; + } + if (gameStartTime < 1f) + { + num *= gameStartTime; + } + if (timeStop < 1f) + { + num *= timeStop; + } + if (PhotonNetwork.OfflineMode && EscapeMenuHandler.isEscMenu) + { + num *= 0f; + } + timeScale = num; + deltaTime = Time.deltaTime * timeScale; + fixedDeltaTime = Time.fixedDeltaTime * timeScale; + Time.timeScale = 1f; + } + + public void StartGame() + { + gameStartTime = 1f; + } + + public void DoSpeedUp() + { + StartCoroutine(DoCurve(speedUp)); + } + + public void DoSlowDown() + { + StartCoroutine(DoCurve(slowDown)); + } + + private IEnumerator DoCurve(AnimationCurve curve) + { + float c = 0f; + float t = curve.keys[curve.keys.Length - 1].time; + while (c < t) + { + gameOverTime = curve.Evaluate(c); + c += Time.unscaledDeltaTime; + yield return null; + } + gameOverTime = curve.Evaluate(t); + } + + public void HitStop() + { + StartCoroutine(DoHitStop()); + } + + private IEnumerator DoHitStop() + { + timeStop = 0f; + yield return new WaitForSeconds(0.3f); + timeStop = 1f; + } +} diff --git a/ROUNDS/ToggleStats.cs b/ROUNDS/ToggleStats.cs new file mode 100644 index 0000000..726a307 --- /dev/null +++ b/ROUNDS/ToggleStats.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +public class ToggleStats : MonoBehaviour +{ + public float movementSpeedMultiplier = 1f; + + public float hpMultiplier = 1f; + + private CharacterData data; + + private void Start() + { + data = GetComponentInParent<CharacterData>(); + } + + public void TurnOn() + { + data.health *= hpMultiplier; + data.maxHealth *= hpMultiplier; + data.stats.movementSpeed *= movementSpeedMultiplier; + data.stats.ConfigureMassAndSize(); + } + + public void TurnOff() + { + data.health /= hpMultiplier; + data.maxHealth /= hpMultiplier; + data.stats.movementSpeed /= movementSpeedMultiplier; + data.stats.ConfigureMassAndSize(); + } +} diff --git a/ROUNDS/ToggleUnparented.cs b/ROUNDS/ToggleUnparented.cs new file mode 100644 index 0000000..bacb60a --- /dev/null +++ b/ROUNDS/ToggleUnparented.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class ToggleUnparented : MonoBehaviour +{ + private Unparent[] unparents; + + private void Awake() + { + unparents = GetComponentsInChildren<Unparent>(); + } + + private void OnDisable() + { + for (int i = 0; i < unparents.Length; i++) + { + unparents[i].gameObject.SetActive(value: false); + } + GetComponent<Holding>().holdable.gameObject.SetActive(value: false); + } + + private void OnEnable() + { + for (int i = 0; i < unparents.Length; i++) + { + unparents[i].gameObject.SetActive(value: true); + } + GetComponent<Holding>().holdable.gameObject.SetActive(value: false); + } +} diff --git a/ROUNDS/TracerRound.cs b/ROUNDS/TracerRound.cs new file mode 100644 index 0000000..201a5f7 --- /dev/null +++ b/ROUNDS/TracerRound.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +public class TracerRound : MonoBehaviour +{ + public GameObject bullet; + + public GameObject bulletSpawnPos; + + private TracerTarget target; + + private MoveTransform move; + + private bool done; + + private void Start() + { + move = GetComponent<MoveTransform>(); + bullet = Object.Instantiate(bullet, bulletSpawnPos.transform.position, bulletSpawnPos.transform.rotation); + bullet.GetComponent<ProjectileHit>().damage *= base.transform.localScale.x; + GetComponentInParent<SpawnedAttack>().CopySpawnedAttackTo(bullet); + target = bullet.GetComponent<TracerTarget>(); + GetComponentInParent<ProjectileHit>().AddHitActionWithData(Hit); + bullet.GetComponentInParent<ProjectileHit>().AddHitActionWithData(Hit); + } + + public void Hit(HitInfo hit) + { + if ((bool)hit.transform.root.GetComponent<Player>()) + { + base.transform.SetParent(null); + base.gameObject.AddComponent<RemoveAfterSeconds>().seconds = 10f; + base.gameObject.AddComponent<FollowTransform>().target = hit.transform; + } + } + + private void Update() + { + if (target != null) + { + target.SetPos(base.transform.position, Vector3.Cross(Vector3.forward, base.transform.forward), move); + } + if (bullet == null && !done) + { + done = true; + GetComponentInChildren<ParticleSystem>().Stop(); + } + } +} diff --git a/ROUNDS/TracerTarget.cs b/ROUNDS/TracerTarget.cs new file mode 100644 index 0000000..19b6b67 --- /dev/null +++ b/ROUNDS/TracerTarget.cs @@ -0,0 +1,65 @@ +using UnityEngine; + +public class TracerTarget : MonoBehaviour +{ + private MoveTransform move; + + public bool hasPos; + + public float drag; + + public float spring; + + public AnimationCurve curve; + + public float cosScale = 1f; + + public float cosAmount; + + private float random; + + private float c; + + private bool done; + + private Vector3 tPos; + + private Vector3 upDir; + + private MoveTransform mTrans; + + private void Start() + { + move = GetComponent<MoveTransform>(); + random = Random.Range(0f, 1000f); + SetPos(base.transform.forward * 100f, base.transform.up, null); + } + + private void Update() + { + float num = 1f; + if ((bool)mTrans) + { + num += mTrans.velocity.magnitude * 0.1f; + } + if ((bool)mTrans && !done) + { + tPos += base.transform.forward + base.transform.forward * 10f; + } + c += TimeHandler.deltaTime; + if (hasPos) + { + move.velocity += cosAmount * Mathf.Cos((Time.time + random) * cosScale) * upDir * CappedDeltaTime.time / num; + move.velocity += (tPos - base.transform.position).normalized * spring * CappedDeltaTime.time * curve.Evaluate(c) * num; + move.velocity -= move.velocity * CappedDeltaTime.time * drag * curve.Evaluate(c); + } + } + + public void SetPos(Vector3 targetPos, Vector3 up, MoveTransform move) + { + mTrans = move; + hasPos = true; + tPos = targetPos; + upDir = up; + } +} diff --git a/ROUNDS/TrickShot.cs b/ROUNDS/TrickShot.cs new file mode 100644 index 0000000..cdb0b0e --- /dev/null +++ b/ROUNDS/TrickShot.cs @@ -0,0 +1,87 @@ +using Sonigon; +using UnityEngine; + +public class TrickShot : MonoBehaviour +{ + [Header("Sound")] + public SoundEvent soundGrowExplosion; + + public SoundEvent soundGrowWail; + + private bool soundGrowExplosionPlayed; + + private bool soundGrowWailPlayed; + + private SoundParameterIntensity soundIntensity = new SoundParameterIntensity(0f); + + [Header("Settings")] + public float muiltiplier = 1f; + + public float removeAt = 30f; + + private ProjectileHit projectileHit; + + private MoveTransform move; + + private ScaleTrailFromDamage trail; + + private float lastDistanceTravelled; + + private void Awake() + { + trail = base.transform.root.GetComponentInChildren<ScaleTrailFromDamage>(); + } + + private void Start() + { + projectileHit = GetComponentInParent<ProjectileHit>(); + move = GetComponentInParent<MoveTransform>(); + if (projectileHit != null) + { + if (soundGrowExplosion != null) + { + projectileHit.AddHitActionWithData(SoundPlayGrowExplosion); + } + if (soundGrowWail != null) + { + soundGrowWailPlayed = true; + SoundManager.Instance.Play(soundGrowWail, projectileHit.ownPlayer.transform); + } + } + } + + public void SoundPlayGrowExplosion(HitInfo hit) + { + if (!soundGrowExplosionPlayed) + { + soundGrowExplosionPlayed = true; + if (soundGrowExplosion != null) + { + SoundManager.Instance.PlayAtPosition(soundGrowExplosion, projectileHit.ownPlayer.transform, hit.point, soundIntensity); + } + if (soundGrowWailPlayed) + { + SoundManager.Instance.Stop(soundGrowWail, projectileHit.ownPlayer.transform); + } + } + } + + private void Update() + { + if (move.distanceTravelled > removeAt) + { + Object.Destroy(this); + return; + } + soundIntensity.intensity = move.distanceTravelled / removeAt; + float num = move.distanceTravelled - lastDistanceTravelled; + lastDistanceTravelled = move.distanceTravelled; + float num2 = 1f + num * TimeHandler.deltaTime * base.transform.localScale.x * muiltiplier; + projectileHit.damage *= num2; + projectileHit.shake *= num2; + if ((bool)trail) + { + trail.Rescale(); + } + } +} diff --git a/ROUNDS/TwitchAudienceVisualizer.cs b/ROUNDS/TwitchAudienceVisualizer.cs new file mode 100644 index 0000000..db00690 --- /dev/null +++ b/ROUNDS/TwitchAudienceVisualizer.cs @@ -0,0 +1,147 @@ +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +public class TwitchAudienceVisualizer : MonoBehaviour +{ + private const int MAXIMUM_MSG_PER_PLAYER_IN_AUDIENCE = 100; + + private const int MAXIMUM_MSG_PER_SECOND = 10; + + private float m_RecieveRate; + + private float m_LastRecievedTime; + + public float countDownSpeed = 2f; + + public float totalAmountOfTime = 30f; + + [SerializeField] + private GameObject m_TwitchChatObject; + + public ProceduralImage border; + + public TextMeshProUGUI audioenceText; + + private Screenshaker shake; + + private bool m_IsAudition; + + private bool m_IsReadyToSpawnChatObjects; + + private ListMenuPage m_Page; + + public static TwitchAudienceVisualizer instance; + + private Dictionary<string, int> m_MsgsPerTwitchUser = new Dictionary<string, int>(); + + private int currentViewerScore; + + private void Awake() + { + instance = this; + m_RecieveRate = 0.1f; + } + + private void Start() + { + m_Page = GetComponentInParent<ListMenuPage>(); + shake = GetComponentInChildren<Screenshaker>(); + TwitchUIHandler.Instance.AddMsgAction(Chat); + StartAudition(); + } + + public void Chat(string msg, string from) + { + if (!m_IsAudition) + { + return; + } + if (!m_MsgsPerTwitchUser.ContainsKey(from)) + { + m_MsgsPerTwitchUser.Add(from, 0); + } + if (m_MsgsPerTwitchUser[from] >= 100) + { + return; + } + m_MsgsPerTwitchUser[from]++; + if (Time.unscaledTime >= m_LastRecievedTime + m_RecieveRate) + { + m_LastRecievedTime = Time.unscaledTime; + if (m_IsReadyToSpawnChatObjects) + { + SpawnChatObject(msg, from); + } + } + currentViewerScore += 100; + shake.OnUIGameFeel(Random.insideUnitCircle.normalized); + } + + private void SpawnChatObject(string msg, string from) + { + Object.Instantiate(m_TwitchChatObject).GetComponentInChildren<TextMeshProUGUI>().text = msg; + } + + private void StartAudition() + { + m_IsAudition = true; + m_MsgsPerTwitchUser = new Dictionary<string, int>(); + StartCoroutine(DoAudition()); + } + + private void Shake(float m = 1f) + { + shake.OnUIGameFeel(Random.insideUnitCircle.normalized * m); + } + + private IEnumerator DoAudition() + { + border.fillAmount = 0f; + audioenceText.text = ""; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(3f); + audioenceText.text = "3"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(3f); + audioenceText.text = "2"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(3f); + audioenceText.text = "1"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(10f); + audioenceText.text = "CHAT"; + yield return new WaitForSecondsRealtime(2f / countDownSpeed); + Shake(10f); + audioenceText.text = "MAKE"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(10f); + audioenceText.text = "SOME"; + yield return new WaitForSecondsRealtime(1f / countDownSpeed); + Shake(10f); + audioenceText.text = "NOISE"; + float t = 0f; + while (t < 1f) + { + t += Time.unscaledDeltaTime; + Shake(3f - t); + yield return null; + } + yield return new WaitForSecondsRealtime(0.5f / countDownSpeed); + m_IsReadyToSpawnChatObjects = true; + float c = totalAmountOfTime; + while (c > 0f) + { + border.fillAmount = c / totalAmountOfTime; + c -= Time.unscaledDeltaTime; + audioenceText.text = currentViewerScore + "\n<size=50>AUDIENCE RATING</size>"; + yield return null; + } + m_IsAudition = false; + m_IsReadyToSpawnChatObjects = false; + m_Page.Close(); + NetworkConnectionHandler.instance.TwitchJoin(currentViewerScore); + } +} diff --git a/ROUNDS/TwitchChatMessage.cs b/ROUNDS/TwitchChatMessage.cs new file mode 100644 index 0000000..e82fb14 --- /dev/null +++ b/ROUNDS/TwitchChatMessage.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +public class TwitchChatMessage : MonoBehaviour +{ + private void Start() + { + base.transform.SetParent(TwitchAudienceVisualizer.instance.transform); + base.transform.localScale = Vector3.one; + GetComponent<RectTransform>().anchoredPosition = new Vector2(Random.Range(-850, 850), Random.Range(-475, 475)); + } +} diff --git a/ROUNDS/TwitchIrc.cs b/ROUNDS/TwitchIrc.cs new file mode 100644 index 0000000..8c062c0 --- /dev/null +++ b/ROUNDS/TwitchIrc.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections; +using System.IO; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using Irc; +using UnityEngine; + +public class TwitchIrc : MonoBehaviour +{ + public UserJoined OnUserJoined; + + public UserLeft OnUserLeft; + + public ChannelMessage OnChannelMessage; + + public ServerMessage OnServerMessage; + + public Connected OnConnected; + + public ExceptionThrown OnExceptionThrown; + + private const string ServerName = "irc.twitch.tv"; + + private const int ServerPort = 6667; + + public static TwitchIrc Instance; + + public bool ConnectOnAwake; + + public string Username; + + public string OauthToken; + + public string Channel; + + private TcpClient irc; + + private NetworkStream stream; + + private string inputLine; + + private StreamReader reader; + + private StreamWriter writer; + + public void Connect() + { + if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(OauthToken)) + { + return; + } + try + { + irc = new TcpClient("irc.twitch.tv", 6667); + stream = irc.GetStream(); + reader = new StreamReader(stream); + writer = new StreamWriter(stream); + Send("USER " + Username + "tmi twitch :" + Username); + Send("PASS " + OauthToken); + Send("NICK " + Username); + StartCoroutine("Listen"); + } + catch (Exception exeption) + { + if (OnExceptionThrown != null) + { + OnExceptionThrown(exeption); + } + } + } + + public void Disconnect() + { + irc = null; + StopCoroutine("Listen"); + if (stream != null) + { + stream.Dispose(); + } + if (writer != null) + { + writer.Dispose(); + } + if (reader != null) + { + reader.Dispose(); + } + } + + public void JoinChannel() + { + if (!string.IsNullOrEmpty(Channel)) + { + if (Channel[0] != '#') + { + Channel = "#" + Channel; + } + if (irc != null && irc.Connected) + { + Send("JOIN " + Channel); + } + } + } + + public void LeaveChannel() + { + Send("PART " + Channel); + } + + public void Message(string message) + { + Send("PRIVMSG " + Channel + " :" + message); + } + + private IEnumerator Listen() + { + while (true) + { + if (stream.DataAvailable && (inputLine = reader.ReadLine()) != null) + { + ParseData(inputLine); + } + yield return null; + } + } + + private void ParseData(string data) + { + string[] array = data.Split(' '); + if (data.Length > 4 && data.Substring(0, 4) == "PING") + { + Send("PONG " + array[1]); + return; + } + switch (array[1]) + { + case "001": + Send("MODE " + Username + " +B"); + OnConnected(); + break; + case "JOIN": + if (Instance.OnUserJoined != null) + { + Instance.OnUserJoined(new UserJoinedEventArgs(array[2], array[0].Substring(1, array[0].IndexOf("!") - 1))); + } + break; + case "PRIVMSG": + if (array[2].ToLower() != Username.ToLower() && OnChannelMessage != null) + { + OnChannelMessage(new ChannelMessageEventArgs(array[2], array[0].Substring(1, array[0].IndexOf('!') - 1), JoinArray(array, 3))); + } + break; + case "PART": + case "QUIT": + if (OnUserLeft != null) + { + OnUserLeft(new UserLeftEventArgs(array[2], array[0].Substring(1, data.IndexOf("!") - 1))); + } + break; + default: + if (array.Length > 3 && OnServerMessage != null) + { + OnServerMessage(JoinArray(array, 3)); + } + break; + } + } + + private string StripMessage(string message) + { + foreach (Match item in new Regex("\u0003(?:\\d{1,2}(?:,\\d{1,2})?)?").Matches(message)) + { + message = message.Replace(item.Value, ""); + } + if (message == "") + { + return ""; + } + if (message.Substring(0, 1) == ":" && message.Length > 2) + { + return message.Substring(1, message.Length - 1); + } + return message; + } + + private string JoinArray(string[] strArray, int startIndex) + { + return StripMessage(string.Join(" ", strArray, startIndex, strArray.Length - startIndex)); + } + + private void Send(string message) + { + writer.WriteLine(message); + writer.Flush(); + } + + private void OnConnectedToServer() + { + JoinChannel(); + } + + private void Awake() + { + Instance = this; + OnConnected = (Connected)Delegate.Combine(OnConnected, new Connected(OnConnectedToServer)); + if (ConnectOnAwake) + { + Connect(); + } + } + + private void OnDisable() + { + Disconnect(); + } +} diff --git a/ROUNDS/TwitchIrcExample.cs b/ROUNDS/TwitchIrcExample.cs new file mode 100644 index 0000000..dc08227 --- /dev/null +++ b/ROUNDS/TwitchIrcExample.cs @@ -0,0 +1,88 @@ +using System; +using Irc; +using UnityEngine; +using UnityEngine.UI; + +public class TwitchIrcExample : MonoBehaviour +{ + public InputField UsernameText; + + public InputField TokenText; + + public InputField ChannelText; + + public Text ChatText; + + public InputField MessageText; + + private void Start() + { + TwitchIrc instance = TwitchIrc.Instance; + instance.OnChannelMessage = (ChannelMessage)Delegate.Combine(instance.OnChannelMessage, new ChannelMessage(OnChannelMessage)); + TwitchIrc instance2 = TwitchIrc.Instance; + instance2.OnUserLeft = (UserLeft)Delegate.Combine(instance2.OnUserLeft, new UserLeft(OnUserLeft)); + TwitchIrc instance3 = TwitchIrc.Instance; + instance3.OnUserJoined = (UserJoined)Delegate.Combine(instance3.OnUserJoined, new UserJoined(OnUserJoined)); + TwitchIrc instance4 = TwitchIrc.Instance; + instance4.OnServerMessage = (ServerMessage)Delegate.Combine(instance4.OnServerMessage, new ServerMessage(OnServerMessage)); + TwitchIrc instance5 = TwitchIrc.Instance; + instance5.OnExceptionThrown = (ExceptionThrown)Delegate.Combine(instance5.OnExceptionThrown, new ExceptionThrown(OnExceptionThrown)); + } + + public void Connect() + { + TwitchIrc.Instance.Username = UsernameText.text; + TwitchIrc.Instance.OauthToken = TokenText.text; + TwitchIrc.Instance.Channel = ChannelText.text; + TwitchIrc.Instance.Connect(); + } + + public void MessageSend() + { + if (!string.IsNullOrEmpty(MessageText.text)) + { + TwitchIrc.Instance.Message(MessageText.text); + Text chatText = ChatText; + chatText.text = chatText.text + "<b>" + TwitchIrc.Instance.Username + "</b>: " + MessageText.text + "\n"; + MessageText.text = ""; + } + } + + public void GoUrl(string url) + { + Application.OpenURL(url); + } + + private void OnServerMessage(string message) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>SERVER:</b> " + message + "\n"; + Debug.Log(message); + } + + private void OnChannelMessage(ChannelMessageEventArgs channelMessageArgs) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>" + channelMessageArgs.From + ":</b> " + channelMessageArgs.Message + "\n"; + Debug.Log("MESSAGE: " + channelMessageArgs.From + ": " + channelMessageArgs.Message); + } + + private void OnUserJoined(UserJoinedEventArgs userJoinedArgs) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>USER JOINED:</b> " + userJoinedArgs.User + "\n"; + Debug.Log("USER JOINED: " + userJoinedArgs.User); + } + + private void OnUserLeft(UserLeftEventArgs userLeftArgs) + { + Text chatText = ChatText; + chatText.text = chatText.text + "<b>USER JOINED:</b> " + userLeftArgs.User + "\n"; + Debug.Log("USER JOINED: " + userLeftArgs.User); + } + + private void OnExceptionThrown(Exception exeption) + { + Debug.Log(exeption); + } +} diff --git a/ROUNDS/TwitchUIHandler.cs b/ROUNDS/TwitchUIHandler.cs new file mode 100644 index 0000000..c69fc7a --- /dev/null +++ b/ROUNDS/TwitchUIHandler.cs @@ -0,0 +1,154 @@ +using System; +using Irc; +using Steamworks; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class TwitchUIHandler : MonoBehaviour +{ + private const string TWITCH_OAUTH_PLAYERPREF_KEY = "TwitchOauth"; + + private const string TWITCH_NAME_PLAYERPREF_KEY = "TwitchName"; + + [SerializeField] + private TMP_InputField m_UserNameText; + + [SerializeField] + private TMP_InputField m_OauthText; + + [SerializeField] + private Button m_GetOAuthButton; + + [SerializeField] + private ListMenuPage m_TwitchBar; + + private Action<string, string> m_OnMsgAction; + + private bool m_Connected; + + public static string OAUTH_KEY + { + get + { + return PlayerPrefs.GetString("TwitchOauth" + SteamUser.GetSteamID().ToString(), string.Empty); + } + private set + { + PlayerPrefs.SetString("TwitchOauth" + SteamUser.GetSteamID().ToString(), value); + } + } + + public static string TWITCH_NAME_KEY + { + get + { + return PlayerPrefs.GetString("TwitchName" + SteamUser.GetSteamID().ToString(), string.Empty); + } + private set + { + PlayerPrefs.SetString("TwitchName" + SteamUser.GetSteamID().ToString(), value); + } + } + + public static TwitchUIHandler Instance { get; private set; } + + private void Awake() + { + Instance = this; + InitListeners(); + } + + private void Start() + { + TwitchIrc instance = TwitchIrc.Instance; + instance.OnChannelMessage = (ChannelMessage)Delegate.Combine(instance.OnChannelMessage, new ChannelMessage(OnChannelMessage)); + TwitchIrc instance2 = TwitchIrc.Instance; + instance2.OnUserLeft = (UserLeft)Delegate.Combine(instance2.OnUserLeft, new UserLeft(OnUserLeft)); + TwitchIrc instance3 = TwitchIrc.Instance; + instance3.OnUserJoined = (UserJoined)Delegate.Combine(instance3.OnUserJoined, new UserJoined(OnUserJoined)); + TwitchIrc instance4 = TwitchIrc.Instance; + instance4.OnServerMessage = (ServerMessage)Delegate.Combine(instance4.OnServerMessage, new ServerMessage(OnServerMessage)); + TwitchIrc instance5 = TwitchIrc.Instance; + instance5.OnExceptionThrown = (ExceptionThrown)Delegate.Combine(instance5.OnExceptionThrown, new ExceptionThrown(OnExceptionThrown)); + if (!string.IsNullOrEmpty(OAUTH_KEY)) + { + m_OauthText.text = OAUTH_KEY; + } + if (!string.IsNullOrEmpty(TWITCH_NAME_KEY)) + { + m_UserNameText.text = TWITCH_NAME_KEY; + } + } + + private void InitListeners() + { + m_GetOAuthButton.onClick.AddListener(GetOauth); + } + + public void AddMsgAction(Action<string, string> a) + { + m_OnMsgAction = (Action<string, string>)Delegate.Combine(m_OnMsgAction, a); + } + + public void OnContinueClick() + { + OAUTH_KEY = m_OauthText.text; + TWITCH_NAME_KEY = m_UserNameText.text.ToLower(); + TwitchIrc.Instance.Username = TWITCH_NAME_KEY; + TwitchIrc.Instance.OauthToken = OAUTH_KEY; + TwitchIrc.Instance.Channel = TWITCH_NAME_KEY; + TwitchIrc.Instance.Connect(); + } + + private void GetOauth() + { + Application.OpenURL("http://twitchapps.com/tmi/"); + } + + public void MessageSend() + { + } + + public void GoUrl(string url) + { + Application.OpenURL(url); + } + + private void OnServerMessage(string message) + { + Debug.Log(message); + } + + private void OnChannelMessage(ChannelMessageEventArgs channelMessageArgs) + { + m_OnMsgAction?.Invoke(channelMessageArgs.Message, channelMessageArgs.From); + } + + private void OnUserJoined(UserJoinedEventArgs userJoinedArgs) + { + if (userJoinedArgs.User.ToUpper() == TwitchIrc.Instance.Username.ToUpper()) + { + Debug.Log("LOCAL USER JOINED!"); + ConnectedToTwitch(); + } + } + + private void ConnectedToTwitch() + { + if (!m_Connected) + { + m_Connected = true; + m_TwitchBar.Open(); + } + } + + private void OnUserLeft(UserLeftEventArgs userLeftArgs) + { + } + + private void OnExceptionThrown(Exception exeption) + { + Debug.Log(exeption); + } +} diff --git a/ROUNDS/UIHandler.cs b/ROUNDS/UIHandler.cs new file mode 100644 index 0000000..72d0b63 --- /dev/null +++ b/ROUNDS/UIHandler.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections; +using Sonigon; +using TMPro; +using UnityEngine; + +public class UIHandler : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundTextAppear; + + public SoundEvent soundTextDisappear; + + public static UIHandler instance; + + [Header("Settings")] + public TextMeshProUGUI gameOverText; + + public GeneralParticleSystem gameOverTextPart; + + public GeneralParticleSystem roundBackgroundPart; + + public GeneralParticleSystem roundTextPart; + + public CodeAnimation roundCounterAnim; + + public RoundCounter roundCounter; + + public RoundCounter roundCounterSmall; + + public CodeAnimation roundCounterAnimSmall; + + public GameObject pickerObject; + + public GeneralParticleSystem pickerPart; + + public GeneralParticleSystem joinGamePart; + + public TextMeshProUGUI jointGameText; + + public PopUpHandler popUpHandler; + + private void Awake() + { + instance = this; + popUpHandler = base.transform.root.GetComponentInChildren<PopUpHandler>(); + } + + public void ShowJoinGameText(string text, Color color) + { + SoundManager.Instance.Play(soundTextAppear, base.transform); + if (text != "") + { + jointGameText.text = text; + } + if (color != Color.black) + { + joinGamePart.particleSettings.color = color; + } + joinGamePart.loop = true; + joinGamePart.Play(); + } + + internal void SetNumberOfRounds(int roundsToWinGame) + { + roundCounter.SetNumberOfRounds(roundsToWinGame); + roundCounterSmall.SetNumberOfRounds(roundsToWinGame); + } + + public void HideJoinGameText() + { + SoundManager.Instance.Play(soundTextDisappear, base.transform); + joinGamePart.Stop(); + } + + public void DisplayScreenText(Color color, string text, float speed) + { + gameOverTextPart.particleSettings.color = color; + gameOverTextPart.duration = 60f / speed; + gameOverTextPart.Play(); + gameOverText.text = text; + } + + public void DisplayScreenTextLoop(string text) + { + gameOverTextPart.duration = 60f; + gameOverTextPart.loop = true; + gameOverTextPart.Play(); + gameOverText.text = text; + } + + public void DisplayScreenTextLoop(Color color, string text) + { + gameOverTextPart.particleSettings.color = color; + gameOverTextPart.duration = 60f; + gameOverTextPart.loop = true; + gameOverTextPart.Play(); + gameOverText.text = text; + } + + public void StopScreenTextLoop() + { + gameOverTextPart.loop = false; + } + + public void ShowAddPoint(Color color, string winTextBefore, string text, float speed) + { + gameOverTextPart.particleSettings.color = color; + gameOverTextPart.duration = 60f / speed; + gameOverTextPart.Play(); + StartCoroutine(DoShowAddPoint(winTextBefore, text)); + } + + private IEnumerator DoShowAddPoint(string winTextBefore, string text) + { + gameOverText.text = winTextBefore; + yield return new WaitForSecondsRealtime(0.7f); + gameOverText.text = text; + } + + public void ShowRoundOver(int p1Rounds, int p2Rounds) + { + roundCounter.gameObject.SetActive(value: true); + roundBackgroundPart.Play(); + roundTextPart.Play(); + roundCounterAnim.PlayIn(); + roundCounter.UpdateRounds(p1Rounds, p2Rounds); + } + + public void ShowRoundCounterSmall(int p1Rounds, int p2Rounds, int p1Points, int p2Points) + { + roundCounterSmall.gameObject.SetActive(value: true); + roundCounterSmall.UpdateRounds(p1Rounds, p2Rounds); + roundCounterSmall.UpdatePoints(p1Points, p2Points); + if (roundCounterAnimSmall.currentState != 0) + { + roundCounterAnimSmall.PlayIn(); + } + } + + public void HideRoundCounterSmall() + { + roundCounterAnimSmall.PlayOut(); + } + + public void ShowPicker(int pickerID, PickerType pickerType = PickerType.Team) + { + pickerObject.SetActive(value: true); + if (pickerType == PickerType.Team) + { + pickerPart.particleSettings.color = PlayerManager.instance.GetColorFromTeam(pickerID).winText; + } + if (pickerType == PickerType.Player) + { + pickerPart.particleSettings.color = PlayerManager.instance.GetColorFromPlayer(pickerID).winText; + } + pickerPart.loop = true; + pickerPart.Play(); + } + + public void StopShowPicker() + { + StartCoroutine(DoStopShowPicker()); + } + + private IEnumerator DoStopShowPicker() + { + pickerPart.loop = false; + yield return new WaitForSeconds(0.3f); + pickerObject.SetActive(value: false); + } + + internal void DisplayYesNoLoop(Player pickingPlayer, Action<PopUpHandler.YesNo> functionToCall) + { + popUpHandler.StartPicking(pickingPlayer, functionToCall); + } +} diff --git a/ROUNDS/UniformModifier.cs b/ROUNDS/UniformModifier.cs new file mode 100644 index 0000000..9278ed7 --- /dev/null +++ b/ROUNDS/UniformModifier.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEngine.UI.ProceduralImage; + +[ModifierID("Uniform")] +public class UniformModifier : ProceduralImageModifier +{ + [SerializeField] + private float radius; + + public float Radius + { + get + { + return radius; + } + set + { + radius = value; + base._Graphic.SetVerticesDirty(); + } + } + + public override Vector4 CalculateRadius(Rect imageRect) + { + float num = radius; + return new Vector4(num, num, num, num); + } +} diff --git a/ROUNDS/UnityEngine.UI.ProceduralImage/ModifierID.cs b/ROUNDS/UnityEngine.UI.ProceduralImage/ModifierID.cs new file mode 100644 index 0000000..79933de --- /dev/null +++ b/ROUNDS/UnityEngine.UI.ProceduralImage/ModifierID.cs @@ -0,0 +1,16 @@ +using System; + +namespace UnityEngine.UI.ProceduralImage; + +[AttributeUsage(AttributeTargets.Class)] +public class ModifierID : Attribute +{ + private string name; + + public string Name => name; + + public ModifierID(string name) + { + this.name = name; + } +} diff --git a/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImage.cs b/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImage.cs new file mode 100644 index 0000000..c18fe41 --- /dev/null +++ b/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImage.cs @@ -0,0 +1,221 @@ +using System; +using UnityEngine.Events; + +namespace UnityEngine.UI.ProceduralImage; + +[ExecuteInEditMode] +[AddComponentMenu("UI/Procedural Image")] +public class ProceduralImage : Image +{ + [SerializeField] + private float borderWidth; + + private ProceduralImageModifier modifier; + + private static Material materialInstance; + + [SerializeField] + private float falloffDistance = 1f; + + private static Material DefaultProceduralImageMaterial + { + get + { + if (materialInstance == null) + { + materialInstance = new Material(Shader.Find("UI/Procedural UI Image")); + } + return materialInstance; + } + set + { + materialInstance = value; + } + } + + public float BorderWidth + { + get + { + return borderWidth; + } + set + { + borderWidth = value; + SetVerticesDirty(); + } + } + + public float FalloffDistance + { + get + { + return falloffDistance; + } + set + { + falloffDistance = value; + SetVerticesDirty(); + } + } + + protected ProceduralImageModifier Modifier + { + get + { + if (modifier == null) + { + modifier = GetComponent<ProceduralImageModifier>(); + if (modifier == null) + { + ModifierType = typeof(FreeModifier); + } + } + return modifier; + } + set + { + modifier = value; + } + } + + public System.Type ModifierType + { + get + { + return Modifier.GetType(); + } + set + { + if (modifier != null && modifier.GetType() != value) + { + if (GetComponent<ProceduralImageModifier>() != null) + { + Object.DestroyImmediate(GetComponent<ProceduralImageModifier>()); + } + base.gameObject.AddComponent(value); + Modifier = GetComponent<ProceduralImageModifier>(); + SetAllDirty(); + } + else if (modifier == null) + { + base.gameObject.AddComponent(value); + Modifier = GetComponent<ProceduralImageModifier>(); + SetAllDirty(); + } + } + } + + public override Material material + { + get + { + if (m_Material == null) + { + return DefaultProceduralImageMaterial; + } + return base.material; + } + set + { + base.material = value; + } + } + + protected override void OnEnable() + { + base.OnEnable(); + Init(); + } + + protected override void OnDisable() + { + base.OnDisable(); + m_OnDirtyVertsCallback = (UnityAction)Delegate.Remove(m_OnDirtyVertsCallback, new UnityAction(OnVerticesDirty)); + } + + private void Init() + { + FixTexCoordsInCanvas(); + m_OnDirtyVertsCallback = (UnityAction)Delegate.Combine(m_OnDirtyVertsCallback, new UnityAction(OnVerticesDirty)); + base.preserveAspect = false; + material = null; + if (base.sprite == null) + { + base.sprite = EmptySprite.Get(); + } + } + + protected void OnVerticesDirty() + { + if (base.sprite == null) + { + base.sprite = EmptySprite.Get(); + } + } + + protected void FixTexCoordsInCanvas() + { + Canvas componentInParent = GetComponentInParent<Canvas>(); + if (componentInParent != null) + { + FixTexCoordsInCanvas(componentInParent); + } + } + + protected void FixTexCoordsInCanvas(Canvas c) + { + c.additionalShaderChannels |= AdditionalCanvasShaderChannels.TexCoord1 | AdditionalCanvasShaderChannels.TexCoord2 | AdditionalCanvasShaderChannels.TexCoord3; + } + + private Vector4 FixRadius(Vector4 vec) + { + Rect rect = base.rectTransform.rect; + vec = new Vector4(Mathf.Max(vec.x, 0f), Mathf.Max(vec.y, 0f), Mathf.Max(vec.z, 0f), Mathf.Max(vec.w, 0f)); + float num = Mathf.Min(Mathf.Min(Mathf.Min(Mathf.Min(rect.width / (vec.x + vec.y), rect.width / (vec.z + vec.w)), rect.height / (vec.x + vec.w)), rect.height / (vec.z + vec.y)), 1f); + return vec * num; + } + + protected override void OnPopulateMesh(VertexHelper toFill) + { + base.OnPopulateMesh(toFill); + EncodeAllInfoIntoVertices(toFill, CalculateInfo()); + } + + protected override void OnTransformParentChanged() + { + base.OnTransformParentChanged(); + FixTexCoordsInCanvas(); + } + + private ProceduralImageInfo CalculateInfo() + { + Rect pixelAdjustedRect = GetPixelAdjustedRect(); + float pixelSize = 1f / Mathf.Max(0f, falloffDistance); + Vector4 vector = FixRadius(Modifier.CalculateRadius(pixelAdjustedRect)); + float num = Mathf.Min(pixelAdjustedRect.width, pixelAdjustedRect.height); + return new ProceduralImageInfo(pixelAdjustedRect.width + falloffDistance, pixelAdjustedRect.height + falloffDistance, falloffDistance, pixelSize, vector / num, borderWidth / num * 2f); + } + + private void EncodeAllInfoIntoVertices(VertexHelper vh, ProceduralImageInfo info) + { + UIVertex vertex = default(UIVertex); + Vector2 uv = new Vector2(info.width, info.height); + Vector2 uv2 = new Vector2(EncodeFloats_0_1_16_16(info.radius.x, info.radius.y), EncodeFloats_0_1_16_16(info.radius.z, info.radius.w)); + Vector2 uv3 = new Vector2((info.borderWidth == 0f) ? 1f : Mathf.Clamp01(info.borderWidth), info.pixelSize); + for (int i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vertex, i); + vertex.position += ((Vector3)vertex.uv0 - new Vector3(0.5f, 0.5f)) * info.fallOffDistance; + vertex.uv1 = uv; + vertex.uv2 = uv2; + vertex.uv3 = uv3; + vh.SetUIVertex(vertex, i); + } + } + + private float EncodeFloats_0_1_16_16(float a, float b) + { + return Vector2.Dot(rhs: new Vector2(1f, 1.5259022E-05f), lhs: new Vector2(Mathf.Floor(a * 65534f) / 65535f, Mathf.Floor(b * 65534f) / 65535f)); + } +} diff --git a/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImageInfo.cs b/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImageInfo.cs new file mode 100644 index 0000000..e31e348 --- /dev/null +++ b/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImageInfo.cs @@ -0,0 +1,26 @@ +namespace UnityEngine.UI.ProceduralImage; + +public struct ProceduralImageInfo +{ + public float width; + + public float height; + + public float fallOffDistance; + + public Vector4 radius; + + public float borderWidth; + + public float pixelSize; + + public ProceduralImageInfo(float width, float height, float fallOffDistance, float pixelSize, Vector4 radius, float borderWidth) + { + this.width = Mathf.Abs(width); + this.height = Mathf.Abs(height); + this.fallOffDistance = Mathf.Max(0f, fallOffDistance); + this.radius = radius; + this.borderWidth = Mathf.Max(borderWidth, 0f); + this.pixelSize = Mathf.Max(0f, pixelSize); + } +} diff --git a/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImageModifier.cs b/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImageModifier.cs new file mode 100644 index 0000000..0b2593b --- /dev/null +++ b/ROUNDS/UnityEngine.UI.ProceduralImage/ProceduralImageModifier.cs @@ -0,0 +1,21 @@ +namespace UnityEngine.UI.ProceduralImage; + +[DisallowMultipleComponent] +public abstract class ProceduralImageModifier : MonoBehaviour +{ + protected Graphic graphic; + + protected Graphic _Graphic + { + get + { + if (graphic == null) + { + graphic = GetComponent<Graphic>(); + } + return graphic; + } + } + + public abstract Vector4 CalculateRadius(Rect imageRect); +} diff --git a/ROUNDS/Unparent.cs b/ROUNDS/Unparent.cs new file mode 100644 index 0000000..cc69c83 --- /dev/null +++ b/ROUNDS/Unparent.cs @@ -0,0 +1,44 @@ +using System.Collections; +using UnityEngine; + +public class Unparent : MonoBehaviour +{ + public Transform parent; + + public bool follow; + + public float destroyDelay; + + private bool done; + + private void Start() + { + parent = base.transform.root; + } + + private void LateUpdate() + { + if (!done) + { + if (base.transform.root != null) + { + base.transform.SetParent(null, worldPositionStays: true); + } + if (follow && (bool)parent) + { + base.transform.position = parent.transform.position; + } + if (!parent) + { + StartCoroutine(DelayRemove()); + done = true; + } + } + } + + private IEnumerator DelayRemove() + { + yield return new WaitForSeconds(destroyDelay); + Object.Destroy(base.gameObject); + } +} diff --git a/ROUNDS/UnparentObject.cs b/ROUNDS/UnparentObject.cs new file mode 100644 index 0000000..258fafa --- /dev/null +++ b/ROUNDS/UnparentObject.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +public class UnparentObject : MonoBehaviour +{ + public void Unparent() + { + base.transform.SetParent(base.transform.root); + } +} diff --git a/ROUNDS/UnparentOnHit.cs b/ROUNDS/UnparentOnHit.cs new file mode 100644 index 0000000..50266c7 --- /dev/null +++ b/ROUNDS/UnparentOnHit.cs @@ -0,0 +1,38 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Events; + +public class UnparentOnHit : MonoBehaviour +{ + public float destroyAfterSeconds = 2f; + + public UnityEvent unparentEvent; + + private bool done; + + private void Start() + { + ProjectileHit componentInParent = GetComponentInParent<ProjectileHit>(); + if ((bool)componentInParent) + { + componentInParent.AddHitAction(Unparent); + } + } + + public void Unparent() + { + if (!done) + { + done = true; + base.transform.SetParent(null, worldPositionStays: true); + StartCoroutine(DelayDestroy()); + unparentEvent.Invoke(); + } + } + + private IEnumerator DelayDestroy() + { + yield return new WaitForSeconds(destroyAfterSeconds); + Object.Destroy(base.gameObject); + } +} diff --git a/ROUNDS/UserJoined.cs b/ROUNDS/UserJoined.cs new file mode 100644 index 0000000..8c1335f --- /dev/null +++ b/ROUNDS/UserJoined.cs @@ -0,0 +1,3 @@ +using Irc; + +public delegate void UserJoined(UserJoinedEventArgs userJoinedArgs); diff --git a/ROUNDS/UserLeft.cs b/ROUNDS/UserLeft.cs new file mode 100644 index 0000000..4527020 --- /dev/null +++ b/ROUNDS/UserLeft.cs @@ -0,0 +1,3 @@ +using Irc; + +public delegate void UserLeft(UserLeftEventArgs userLeftArgs); diff --git a/ROUNDS/VelocityStretch.cs b/ROUNDS/VelocityStretch.cs new file mode 100644 index 0000000..2875de5 --- /dev/null +++ b/ROUNDS/VelocityStretch.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class VelocityStretch : MonoBehaviour +{ + private Rigidbody2D rig; + + public float amount = 1f; + + private void Start() + { + rig = GetComponentInParent<Rigidbody2D>(); + } + + private void Update() + { + base.transform.localScale = Vector3.one + new Vector3(Mathf.Abs(rig.velocity.x), Mathf.Abs(rig.velocity.y), 0f) * amount; + } +} diff --git a/ROUNDS/WallRayCaster.cs b/ROUNDS/WallRayCaster.cs new file mode 100644 index 0000000..b7d5c52 --- /dev/null +++ b/ROUNDS/WallRayCaster.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +public class WallRayCaster : MonoBehaviour +{ + public float rayLength = 0.7f; + + public LayerMask mask; + + private GeneralInput input; + + private CharacterData data; + + private Rigidbody2D rig; + + private void Start() + { + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + rig = GetComponent<Rigidbody2D>(); + } + + private void Update() + { + } + + public void RayCast(Vector3 dir, float offset = 0f) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(base.transform.position + base.transform.up * offset, dir, rayLength * base.transform.localScale.x, mask); + if ((bool)raycastHit2D.transform && !raycastHit2D.collider.GetComponent<DamageBox>() && Vector3.Angle(raycastHit2D.normal, Vector3.up) > 70f && Vector3.Angle(raycastHit2D.normal, Vector3.up) < 110f) + { + data.TouchWall(raycastHit2D.normal, raycastHit2D.point); + } + } +} diff --git a/ROUNDS/WasDealtDamageEffect.cs b/ROUNDS/WasDealtDamageEffect.cs new file mode 100644 index 0000000..58d0ea4 --- /dev/null +++ b/ROUNDS/WasDealtDamageEffect.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public abstract class WasDealtDamageEffect : MonoBehaviour +{ + public abstract void WasDealtDamage(Vector2 damage, bool selfDamage); +} diff --git a/ROUNDS/WasDealtDamageTrigger.cs b/ROUNDS/WasDealtDamageTrigger.cs new file mode 100644 index 0000000..a8fdcd4 --- /dev/null +++ b/ROUNDS/WasDealtDamageTrigger.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using UnityEngine.Events; + +public class WasDealtDamageTrigger : WasDealtDamageEffect +{ + public float damageNeeded = 25f; + + public float cd = 0.2f; + + public bool allowSelfDamage; + + private float time; + + private float damageDealt; + + public UnityEvent triggerEvent; + + private void Start() + { + } + + public override void WasDealtDamage(Vector2 damage, bool selfDamage) + { + if (!selfDamage || allowSelfDamage) + { + damageDealt += damage.magnitude; + if (damageDealt > damageNeeded && Time.time > time + cd) + { + time = Time.time; + damageDealt = 0f; + triggerEvent.Invoke(); + } + } + } +} diff --git a/ROUNDS/Weapon.cs b/ROUNDS/Weapon.cs new file mode 100644 index 0000000..d7b81f2 --- /dev/null +++ b/ROUNDS/Weapon.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public abstract class Weapon : MonoBehaviour +{ + public Holdable holdable; + + [HideInInspector] + public float sinceAttack = 10f; + + private void Start() + { + holdable = GetComponent<Holdable>(); + } + + private void Update() + { + } + + public abstract bool Attack(float charge, bool forceAttack = false, float damageM = 1f, float recoilMultiplier = 1f, bool useAmmo = true); +} diff --git a/ROUNDS/WeaponHandler.cs b/ROUNDS/WeaponHandler.cs new file mode 100644 index 0000000..35be82f --- /dev/null +++ b/ROUNDS/WeaponHandler.cs @@ -0,0 +1,173 @@ +using System.Collections; +using Sonigon; +using UnityEngine; + +public class WeaponHandler : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundCharacterCantShoot; + + private bool soundFireHold; + + [Header("Settings")] + public Gun gun; + + private Holding holding; + + private GeneralInput input; + + private CharacterData data; + + private float heatSinceAttack; + + private float heat; + + public float heatPerBullet = 0.1f; + + public float secondsBeforeStartToCool = 0.1f; + + public float coolPerSecond = 0.2f; + + public float overHeatTime = 1f; + + public float resetSpeed = 2f; + + public bool isOverHeated; + + private bool hasBeenHeated; + + public SpriteRenderer heatRenderer; + + private Transform overHeatPivot; + + public Color overHeatColor; + + private Color baseHeatColor; + + internal void DoReload() + { + gun.GetComponentInChildren<GunAmmo>().ReloadAmmo(); + } + + private void Awake() + { + holding = GetComponent<Holding>(); + input = GetComponent<GeneralInput>(); + data = GetComponent<CharacterData>(); + } + + private void Start() + { + overHeatPivot = heatRenderer.transform.parent; + baseHeatColor = heatRenderer.color; + } + + private void Update() + { + if (!gun.holdable.holder && (bool)data) + { + gun.holdable.holder = data; + } + if (data.playerVel.simulated) + { + gun.attackSpeedMultiplier = data.stats.attackSpeedMultiplier; + heatSinceAttack += TimeHandler.deltaTime; + Attack(); + OverHeat(); + } + } + + private void Attack() + { + if (!gun || !gun.IsReady()) + { + return; + } + if (input.shootIsPressed) + { + if (!soundFireHold) + { + soundFireHold = true; + if (gun.isReloading || data.isSilenced) + { + SoundManager.Instance.Play(soundCharacterCantShoot, base.transform); + } + } + } + else + { + soundFireHold = false; + } + if (gun.bursts == 0 && (!soundFireHold || gun.isReloading || data.isSilenced)) + { + gun.soundGun.StopAutoPlayTail(); + } + if ((!input.shootWasPressed || gun.useCharge) && (!input.shootWasReleased || !gun.useCharge) && (!(gun.attackSpeed / data.stats.attackSpeedMultiplier < 0.3f) || !input.shootIsPressed || gun.useCharge || gun.dontAllowAutoFire)) + { + return; + } + if (isOverHeated) + { + heatRenderer.GetComponent<CodeAnimation>().PlayBoop(); + gun.sinceAttack = 0f; + return; + } + gun.Attack(0f); + if (heat >= 1f) + { + StartCoroutine(DoOverHeat()); + isOverHeated = true; + } + heatSinceAttack = 0f; + } + + internal void NewGun() + { + gun.ResetStats(); + gun.soundGun.ClearSoundModifiers(); + } + + private void OverHeat() + { + if (!isOverHeated) + { + if (heatSinceAttack > secondsBeforeStartToCool) + { + heat -= TimeHandler.deltaTime * coolPerSecond; + } + SetOverHeatColor(); + } + } + + private IEnumerator DoOverHeat() + { + SetOverHeatColor(); + yield return new WaitForSeconds(overHeatTime); + while (heat > 0f) + { + heat -= resetSpeed * TimeHandler.deltaTime; + SetOverHeatColor(); + yield return null; + } + isOverHeated = false; + } + + private void SetOverHeatColor() + { + heat = Mathf.Clamp(heat, 0f, 1f); + heatRenderer.color = Color.Lerp(baseHeatColor, overHeatColor, heat); + if (heat > 0.25f || hasBeenHeated) + { + hasBeenHeated = true; + overHeatPivot.transform.localScale = new Vector3(heat, 1f, 1f); + } + else + { + overHeatPivot.transform.localScale = new Vector3(0f, 1f, 1f); + } + if (heat == 0f) + { + hasBeenHeated = false; + } + } +} diff --git a/ROUNDS/ZapEffect.cs b/ROUNDS/ZapEffect.cs new file mode 100644 index 0000000..9215e60 --- /dev/null +++ b/ROUNDS/ZapEffect.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +public class ZapEffect : MonoBehaviour +{ + public float damage; + + public float range = 1f; + + private void Start() + { + damage *= base.transform.localScale.x; + range *= (1f + base.transform.localScale.x) * 0.5f; + Player closestPlayer = PlayerManager.instance.GetClosestPlayer(base.transform.position, needVision: true); + if ((bool)closestPlayer && Vector3.Distance(base.transform.position, closestPlayer.transform.position) < range) + { + closestPlayer.data.healthHandler.TakeDamage(damage * (closestPlayer.transform.position - base.transform.position).normalized, base.transform.position, null, PlayerManager.instance.GetOtherPlayer(closestPlayer)); + GetComponentInChildren<LineEffect>(includeInactive: true).Play(base.transform, closestPlayer.transform, 2f); + } + } +} diff --git a/ROUNDS/Zip.cs b/ROUNDS/Zip.cs new file mode 100644 index 0000000..1f2c02c --- /dev/null +++ b/ROUNDS/Zip.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +public class Zip : MonoBehaviour +{ + public float multiplier = 1f; + + public float turn = 0.2f; + + private float count; + + private int up = 1; + + private void Start() + { + } + + private void Update() + { + count += TimeHandler.deltaTime; + if (count > turn) + { + count = 0f; + up *= -1; + } + base.transform.root.position += base.transform.up * multiplier * up * Time.smoothDeltaTime; + } +} diff --git a/ROUNDS/Zop.cs b/ROUNDS/Zop.cs new file mode 100644 index 0000000..b167832 --- /dev/null +++ b/ROUNDS/Zop.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class Zop : MonoBehaviour +{ + public float turn = 0.2f; + + private float count; + + private int sinceSwitch = 1; + + private bool up; + + private MoveTransform move; + + public bool randomZop; + + private void Start() + { + move = GetComponentInParent<MoveTransform>(); + if (base.transform.forward.x < 0f) + { + up = true; + } + } + + private void Update() + { + count += TimeHandler.deltaTime; + if (!(count > turn)) + { + return; + } + if (up) + { + move.velocity = move.velocity.magnitude * Vector3.Cross(base.transform.forward, Vector3.forward); + } + else + { + move.velocity = move.velocity.magnitude * -Vector3.Cross(base.transform.forward, Vector3.forward); + } + count = 0f; + if (!randomZop || !(Random.value > 0.8f)) + { + sinceSwitch++; + if (sinceSwitch == 2) + { + up = !up; + sinceSwitch = 0; + } + } + } +} diff --git a/ROUNDS/_Player/CharacterData.cs b/ROUNDS/_Player/CharacterData.cs new file mode 100644 index 0000000..2f41ef3 --- /dev/null +++ b/ROUNDS/_Player/CharacterData.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using Photon.Pun; +using UnityEngine; + +public class CharacterData : MonoBehaviour +{ + public Vector3 aimDirection; + + public List<CardInfo> currentCards; + + public float sinceGroundedMultiplierWhenWallGrab = 0.2f; + + public PlayerActions playerActions; + + public ParticleSystem[] landParts; + + public int jumps = 1; + + public int currentJumps = 1; + + public bool isPlaying; + + public bool dead; + + public bool isStunned; + + public bool isSilenced; + + public float stunTime; + + public float silenceTime; + + public float health = 100f; + + public float maxHealth = 100f; + + public AnimationCurve slamCurve; + + public Vector3 wallPos; + + public Vector2 wallNormal; + + public Vector3 groundPos; + + public Transform hand; + + public float sinceWallGrab = float.PositiveInfinity; + + public bool isWallGrab; + + public float wallDistance = 1f; + + private bool wasWallGrabLastFrame; + + public float sinceGrounded; + + public bool isGrounded = true; + + private bool wasGroundedLastFrame = true; + + public Player player; + + public float sinceJump = 1f; + + public PlayerVelocity playerVel; + + public HealthHandler healthHandler; + + public GeneralInput input; + + public PlayerMovement movement; + + public PlayerJump jump; + + public Block block; + + public CharacterStatModifiers stats; + + public WeaponHandler weaponHandler; + + public StunHandler stunHandler; + + public SilenceHandler silenceHandler; + + public Player lastSourceOfDamage; + + public Player master; + + public Player lastDamagedPlayer; + + public Collider2D mainCol; + + public PlayerSounds playerSounds; + + private Transform wobblePos; + + private LayerMask groundMask; + + public PhotonView view; + + private CrownPos crownPos; + + public Rigidbody2D standOnRig; + + public Action<float, Vector3, Vector3, Transform> TouchGroundAction; + + public Action<float, Vector3, Vector3> TouchWallAction; + + public float HealthPercentage + { + get + { + return health / maxHealth; + } + internal set + { + } + } + + private void Awake() + { + crownPos = GetComponentInChildren<CrownPos>(); + view = GetComponent<PhotonView>(); + mainCol = GetComponent<Collider2D>(); + wobblePos = GetComponentInChildren<PlayerWobblePosition>().transform; + stats = GetComponent<CharacterStatModifiers>(); + player = GetComponent<Player>(); + weaponHandler = GetComponent<WeaponHandler>(); + block = GetComponent<Block>(); + input = GetComponent<GeneralInput>(); + movement = GetComponent<PlayerMovement>(); + jump = GetComponent<PlayerJump>(); + stunHandler = GetComponent<StunHandler>(); + silenceHandler = GetComponent<SilenceHandler>(); + hand = GetComponentInChildren<HandPos>().transform; + playerVel = GetComponent<PlayerVelocity>(); + healthHandler = GetComponent<HealthHandler>(); + playerSounds = GetComponent<PlayerSounds>(); + } + + internal Vector3 GetCrownPos() + { + if ((bool)crownPos) + { + return crownPos.transform.position + Vector3.up * crownPos.GetOffset(); + } + Debug.LogError("NO CROWN POS!?"); + return Vector3.up * 1000f; + } + + private void Start() + { + groundMask = LayerMask.GetMask("Default"); + if (!view.IsMine) + { + PlayerManager.RegisterPlayer(player); + } + } + + private void Update() + { + if (!playerVel.simulated) + { + sinceGrounded = 0f; + } + sinceJump += TimeHandler.deltaTime; + Wall(); + } + + private void FixedUpdate() + { + Ground(); + } + + private void Ground() + { + if (!isPlaying) + { + return; + } + if (!isGrounded) + { + sinceGrounded += TimeHandler.fixedDeltaTime * ((isWallGrab && wallDistance < 0.7f) ? sinceGroundedMultiplierWhenWallGrab : 1f); + if (sinceGrounded < 0f) + { + sinceGrounded = Mathf.Lerp(sinceGrounded, 0f, TimeHandler.fixedDeltaTime * 15f); + } + } + if (!wasGroundedLastFrame) + { + isGrounded = false; + } + wasGroundedLastFrame = false; + } + + private void Wall() + { + if (!isWallGrab) + { + sinceWallGrab += TimeHandler.deltaTime; + } + if (!wasWallGrabLastFrame) + { + isWallGrab = false; + } + wasWallGrabLastFrame = false; + } + + public void TouchGround(Vector3 pos, Vector3 groundNormal, Rigidbody2D groundRig, Transform groundTransform = null) + { + if (sinceJump > 0.2f) + { + currentJumps = jumps; + } + if (TouchGroundAction != null) + { + TouchGroundAction(sinceGrounded, pos, groundNormal, groundTransform); + } + if (groundRig == null) + { + standOnRig = null; + } + else if (!groundRig.GetComponent<NetworkPhysicsObject>()) + { + standOnRig = groundRig; + } + if (playerVel.velocity.y < -20f && !isGrounded) + { + for (int i = 0; i < landParts.Length; i++) + { + landParts[i].transform.localScale = Vector3.one * Mathf.Clamp((0f - playerVel.velocity.y) / 40f, 0.5f, 1f) * 0.5f; + landParts[i].transform.position = new Vector3(base.transform.position.x + playerVel.velocity.x * 0.03f, pos.y, 5f); + landParts[i].transform.rotation = Quaternion.LookRotation(groundNormal); + landParts[i].Play(); + } + GamefeelManager.instance.AddGameFeel(Vector2.down * Mathf.Clamp((sinceGrounded - 0.5f) * 1f, 0f, 4f)); + } + groundPos = pos; + wasGroundedLastFrame = true; + isGrounded = true; + sinceGrounded = 0f; + } + + public void TouchWall(Vector2 normal, Vector3 pos) + { + if (isGrounded) + { + return; + } + wallNormal = normal; + wallPos = pos; + groundPos = pos; + wallDistance = Vector2.Distance(base.transform.position, pos); + if (!(sinceJump < 0.15f)) + { + currentJumps = jumps; + if (TouchWallAction != null) + { + TouchWallAction(sinceWallGrab, pos, normal); + } + _ = sinceWallGrab; + _ = 0.15f; + sinceWallGrab = 0f; + wasWallGrabLastFrame = true; + isWallGrab = true; + } + } + + public bool ThereIsGroundBelow(Vector3 pos, float range = 5f) + { + RaycastHit2D raycastHit2D = Physics2D.Raycast(pos, Vector2.down, range, groundMask); + if ((bool)raycastHit2D.transform && raycastHit2D.distance > 0.1f) + { + return true; + } + return false; + } + + public void SetAI(Player aiMaster = null) + { + master = aiMaster; + input.controlledElseWhere = true; + GetComponent<PlayerAPI>().enabled = true; + } + + public void SetWobbleObjectChild(Transform obj) + { + obj.transform.SetParent(wobblePos, worldPositionStays: true); + } +} diff --git a/ROUNDS/_Player/PlayerCollision.cs b/ROUNDS/_Player/PlayerCollision.cs new file mode 100644 index 0000000..6055a69 --- /dev/null +++ b/ROUNDS/_Player/PlayerCollision.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections; +using Photon.Pun; +using Sonigon; +using UnityEngine; + +public class PlayerCollision : MonoBehaviour +{ + [Header("Sounds")] + public SoundEvent soundBounce; + + [Header("Settings")] + public LayerMask mask; + + private Vector2 lastPos; + + public bool checkForGoThroughWall = true; + + private int ignoreWallFor; + + private Collider2D col; + + private CircleCollider2D cirCol; + + private PlayerVelocity vel; + + private CharacterData data; + + public Action<Vector2, Vector2, Player> collideWithPlayerAction; + + public float bounceTreshold = 1f; + + private bool isBounce; + + public void IgnoreWallForFrames(int frames) + { + ignoreWallFor = frames; + } + + private void Start() + { + data = GetComponent<CharacterData>(); + col = GetComponent<Collider2D>(); + cirCol = GetComponent<CircleCollider2D>(); + vel = GetComponent<PlayerVelocity>(); + } + + private void FixedUpdate() + { + if (checkForGoThroughWall && ignoreWallFor <= 0) + { + RaycastHit2D raycastHit2D = default(RaycastHit2D); + RaycastHit2D[] array = Physics2D.RaycastAll(lastPos, (Vector2)base.transform.position - lastPos, Vector2.Distance(base.transform.position, lastPos), mask); + for (int i = 0; i < array.Length; i++) + { + if (!(array[i].transform.root == base.transform.root)) + { + Debug.DrawLine(lastPos, array[i].point, Color.green, 1f); + if (!(Vector2.Angle(array[i].normal, (Vector2)base.transform.position - lastPos) < 90f) && (!raycastHit2D.transform || array[i].distance < raycastHit2D.distance)) + { + raycastHit2D = array[i]; + } + } + } + if ((bool)raycastHit2D) + { + base.transform.position = raycastHit2D.point + raycastHit2D.normal * 0.5f; + if (data.healthHandler.flyingFor > 0f) + { + DoBounce(raycastHit2D); + } + } + } + ignoreWallFor--; + lastPos = base.transform.position; + float num = cirCol.radius * base.transform.localScale.x; + float num2 = cirCol.radius * base.transform.localScale.x * 0.75f; + RaycastHit2D[] array2 = Physics2D.CircleCastAll(lastPos, num, (Vector2)base.transform.position - lastPos, Vector2.Distance(base.transform.position, lastPos), mask); + for (int j = 0; j < array2.Length; j++) + { + if (array2[j].transform.root == base.transform.root) + { + continue; + } + Vector2 vector = base.transform.position; + Vector2 point = array2[j].point; + float num3 = Vector2.Distance(vector, point); + Vector2 normalized = (vector - point).normalized; + float value = num + (0f - num3); + float value2 = num2 + (0f - num3); + value = Mathf.Clamp(value, 0f, 10f); + value2 = Mathf.Clamp(value2, 0f, 10f); + NetworkPhysicsObject component = array2[j].transform.GetComponent<NetworkPhysicsObject>(); + if ((bool)component) + { + component.Push(data); + } + if (vel.simulated || !vel.isKinematic) + { + vel.transform.position += (Vector3)normalized * value2; + if (Mathf.Abs(normalized.y) < 0.45f && Mathf.Abs(data.input.direction.x) > 0.1f && Vector3.Angle(data.input.direction, normalized) > 90f) + { + data.TouchWall(normalized, point); + } + vel.velocity += normalized * value * 10f * TimeHandler.timeScale; + vel.velocity -= vel.velocity * value * 1f * TimeHandler.timeScale; + } + Player componentInParent = array2[j].transform.GetComponentInParent<Player>(); + if (componentInParent != null && collideWithPlayerAction != null) + { + collideWithPlayerAction(point, value * normalized, componentInParent); + } + if (data.healthHandler.flyingFor > 0f) + { + DoBounce(array2[j]); + } + } + lastPos = base.transform.position; + } + + private void DoBounce(RaycastHit2D hit) + { + if (!(Vector2.Angle(data.playerVel.velocity, hit.normal) < 90f) && !isBounce && data.view.IsMine && data.playerVel.velocity.magnitude > bounceTreshold) + { + data.view.RPC("RPCADoBounce", RpcTarget.All, hit.normal, base.transform.position); + } + } + + [PunRPC] + private void RPCADoBounce(Vector2 hit, Vector3 playerPos) + { + base.transform.position = playerPos; + StartCoroutine(IDoBounce(Vector2.Reflect(data.playerVel.velocity, hit))); + SoundManager.Instance.Play(soundBounce, base.transform); + } + + public IEnumerator IDoBounce(Vector2 targetVel) + { + isBounce = true; + data.stunHandler.AddStun(0.2f); + data.healthHandler.CallTakeDamage(targetVel.normalized * 5f, base.transform.position); + GamefeelManager.instance.AddGameFeel(targetVel.normalized * 4f); + yield return new WaitForSeconds(0.25f); + data.playerVel.velocity = targetVel; + isBounce = false; + } + + private void OnDisable() + { + isBounce = false; + } +} diff --git a/ROUNDS/_Player/PlayerDoJump.cs b/ROUNDS/_Player/PlayerDoJump.cs new file mode 100644 index 0000000..9d718be --- /dev/null +++ b/ROUNDS/_Player/PlayerDoJump.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class PlayerDoJump : MonoBehaviour +{ + private PlayerJump jump; + + public float multiplier = 0.25f; + + private void Start() + { + jump = GetComponentInParent<PlayerJump>(); + } + + public void DoJump() + { + jump.Jump(forceJump: true, multiplier); + } +} diff --git a/ROUNDS/_Player/PlayerFollowGround.cs b/ROUNDS/_Player/PlayerFollowGround.cs new file mode 100644 index 0000000..c200f89 --- /dev/null +++ b/ROUNDS/_Player/PlayerFollowGround.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +public class PlayerFollowGround : MonoBehaviour +{ + private CharacterData data; + + private Vector2 lastPos; + + private Rigidbody2D lastRig; + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + private void FixedUpdate() + { + if (data.standOnRig == null || !data.isGrounded) + { + lastPos = Vector2.zero; + return; + } + if (lastPos != Vector2.zero && data.standOnRig == lastRig) + { + data.playerVel.transform.position = data.playerVel.position + (data.standOnRig.position - lastPos); + } + lastPos = data.standOnRig.position; + lastRig = data.standOnRig; + } +} diff --git a/ROUNDS/_Player/PlayerJump.cs b/ROUNDS/_Player/PlayerJump.cs new file mode 100644 index 0000000..3bad574 --- /dev/null +++ b/ROUNDS/_Player/PlayerJump.cs @@ -0,0 +1,85 @@ +using System; +using UnityEngine; + +public class PlayerJump : MonoBehaviour +{ + private CharacterData data; + + public float upForce; + + private CharacterStatModifiers stats; + + public ParticleSystem[] jumpPart; + + public float sideForce = 1f; + + public Action JumpAction; + + private void Start() + { + stats = GetComponent<CharacterStatModifiers>(); + data = GetComponent<CharacterData>(); + } + + private void Update() + { + if (data.input.jumpWasPressed) + { + Jump(); + } + if (data.input.jumpIsPressed && data.sinceJump < 0.2f) + { + data.playerVel.AddForce(Vector2.up * TimeHandler.deltaTime * 2f * data.stats.jump * data.playerVel.mass * (1f - stats.GetSlow()) * upForce, ForceMode2D.Force); + } + } + + public void Jump(bool forceJump = false, float multiplier = 1f) + { + if (!forceJump && (data.sinceJump < 0.1f || (data.currentJumps <= 0 && data.sinceWallGrab > 0.1f))) + { + return; + } + Vector3 vector = Vector3.up; + Vector3 vector2 = data.groundPos; + if (JumpAction != null) + { + JumpAction(); + } + bool flag = false; + if (data.sinceWallGrab < 0.1f && !data.isGrounded) + { + vector = Vector2.up * 0.8f + data.wallNormal * 0.4f; + vector2 = data.wallPos; + data.currentJumps = data.jumps; + flag = true; + } + else + { + if (data.sinceGrounded > 0.05f) + { + vector2 = base.transform.position; + } + data.currentJumps = data.jumps; + } + if (data.playerVel.velocity.y < 0f) + { + data.playerVel.velocity = new Vector2(data.playerVel.velocity.x, 0f); + } + data.sinceGrounded = 0f; + data.sinceJump = 0f; + data.isGrounded = false; + data.isWallGrab = false; + data.currentJumps--; + data.playerVel.AddForce(vector * multiplier * 0.01f * data.stats.jump * data.playerVel.mass * (1f - stats.GetSlow()) * upForce, ForceMode2D.Impulse); + if (!flag) + { + data.playerVel.AddForce(Vector2.right * multiplier * sideForce * 0.01f * data.stats.jump * data.playerVel.mass * (1f - stats.GetSlow()) * data.playerVel.velocity.x, ForceMode2D.Impulse); + } + for (int i = 0; i < jumpPart.Length; i++) + { + jumpPart[i].transform.position = new Vector3(vector2.x, vector2.y, 5f) - vector * 0f; + jumpPart[i].transform.rotation = Quaternion.LookRotation(data.playerVel.velocity); + jumpPart[i].Play(); + } + } +} diff --git a/ROUNDS/_Player/PlayerMovement.cs b/ROUNDS/_Player/PlayerMovement.cs new file mode 100644 index 0000000..d3af00e --- /dev/null +++ b/ROUNDS/_Player/PlayerMovement.cs @@ -0,0 +1,71 @@ +using UnityEngine; + +public class PlayerMovement : MonoBehaviour +{ + public float force; + + public float airControl = 0.3f; + + public float extraDrag; + + public float extraAngularDrag; + + public float wallGrabDrag; + + private CharacterData data; + + private CharacterStatModifiers stats; + + private float multiplier = 1f; + + private void Start() + { + data = GetComponent<CharacterData>(); + stats = GetComponent<CharacterStatModifiers>(); + } + + private void FixedUpdate() + { + if (!data.isPlaying) + { + return; + } + Move(data.input.direction); + if (data.isWallGrab && data.wallDistance < 0.7f) + { + Vector2 velocity = data.playerVel.velocity; + if (data.input.direction.y >= 0f) + { + _ = data.input.direction.x; + _ = 0f; + } + data.playerVel.velocity = velocity; + } + data.playerVel.velocity -= data.playerVel.velocity * TimeHandler.timeScale * 0.01f * 0.1f * extraDrag * multiplier; + data.playerVel.angularVelocity -= data.playerVel.angularVelocity * TimeHandler.timeScale * 0.01f * 0.1f * extraAngularDrag * multiplier; + } + + private void Update() + { + } + + public void Move(Vector2 direction) + { + UpdateMultiplier(); + if (!data.isStunned) + { + direction.y = Mathf.Clamp(direction.y, -1f, 0f); + direction.y *= 2f; + data.playerVel.AddForce(direction * TimeHandler.timeScale * (1f - stats.GetSlow()) * stats.movementSpeed * force * data.playerVel.mass * 0.01f * multiplier, ForceMode2D.Force); + } + } + + private void UpdateMultiplier() + { + multiplier = 1f; + if (!data.isGrounded) + { + multiplier = airControl; + } + } +} diff --git a/ROUNDS/_Player/PlayerVelocity.cs b/ROUNDS/_Player/PlayerVelocity.cs new file mode 100644 index 0000000..47822f6 --- /dev/null +++ b/ROUNDS/_Player/PlayerVelocity.cs @@ -0,0 +1,82 @@ +using UnityEngine; + +public class PlayerVelocity : MonoBehaviour +{ + internal bool simulated = true; + + internal bool isKinematic; + + internal Vector2 velocity; + + internal float mass = 100f; + + internal float angularVelocity; + + private CharacterData data; + + public Vector2 position + { + get + { + return base.transform.position; + } + set + { + base.transform.position = value; + } + } + + internal void AddTorque(float v) + { + } + + private void Start() + { + data = GetComponent<CharacterData>(); + } + + private void FixedUpdate() + { + if (data.isPlaying) + { + if (isKinematic) + { + velocity *= 0f; + } + if (simulated && !isKinematic) + { + velocity += Vector2.down * Time.fixedDeltaTime * TimeHandler.timeScale * 20f; + base.transform.position += Time.fixedDeltaTime * TimeHandler.timeScale * (Vector3)velocity; + base.transform.position = new Vector3(base.transform.position.x, base.transform.position.y, 0f); + } + } + } + + internal void AddForce(Vector2 force, ForceMode2D forceMode) + { + if (forceMode == ForceMode2D.Force) + { + force *= 0.02f; + } + else + { + force *= 1f; + } + velocity += force / mass; + } + + internal void AddForce(Vector3 force, ForceMode2D forceMode) + { + AddForce((Vector2)force, forceMode); + } + + internal void AddForce(Vector2 force) + { + AddForce(force, ForceMode2D.Force); + } + + internal void AddForce(Vector3 force) + { + AddForce((Vector2)force, ForceMode2D.Force); + } +} diff --git a/ROUNDS/bin/Debug/netstandard2.1/AmplifyColor.dll b/ROUNDS/bin/Debug/netstandard2.1/AmplifyColor.dll Binary files differnew file mode 100644 index 0000000..fdad077 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/AmplifyColor.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp-firstpass.dll b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp-firstpass.dll Binary files differnew file mode 100644 index 0000000..4e302e5 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp-firstpass.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.deps.json b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.deps.json new file mode 100644 index 0000000..b335122 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.deps.json @@ -0,0 +1,1426 @@ +{ + "runtimeTarget": { + "name": ".NETStandard,Version=v2.1/", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETStandard,Version=v2.1": {}, + ".NETStandard,Version=v2.1/": { + "Assembly-CSharp/1.0.0": { + "dependencies": { + "AmplifyColor": "0.0.0.0", + "Assembly-CSharp-firstpass": "0.0.0.0", + "BitpackersASMDEF": "0.0.0.0", + "ByteConverter": "1.0.0.0", + "EmoCompressUtilsASMDEF": "0.0.0.0", + "FloatCrusher": "4.0.0.0", + "HalfFloatASMDEF": "0.0.0.0", + "HalFloat": "1.0.0.0", + "InControl": "0.0.0.0", + "Mono.Security": "4.0.0.0", + "Photon3Unity3D": "4.1.4.8", + "PhotonChat": "0.0.0.0", + "PhotonRealtime": "0.0.0.0", + "PhotonUnityNetworking.Demos": "0.0.0.0", + "PhotonUnityNetworking": "0.0.0.0", + "PhotonUnityNetworking.Utilities": "0.0.0.0", + "PhotonWebSocket": "0.0.0.0", + "QuatCompress": "2.0.0.0", + "Sirenix.OdinInspector.Attributes": "2.1.6.0", + "Sirenix.OdinInspector.CompatibilityLayer": "0.0.0.0", + "Sirenix.Serialization.Config": "2.1.6.0", + "Sirenix.Serialization": "2.1.6.0", + "Sirenix.Utilities": "2.1.6.0", + "SonigonAudioEngine.Runtime": "0.0.0.0", + "System.Configuration": "4.0.0.0", + "System.Diagnostics.StackTrace": "4.1.1.0", + "System.EnterpriseServices": "4.0.0.0", + "System.Globalization.Extensions": "4.1.1.0", + "System.ServiceModel.Internals": "0.0.0.0", + "System.Xml.XPath.XDocument": "4.1.1.0", + "Unity.Analytics.DataPrivacy": "0.0.0.0", + "Unity.Analytics.StandardEvents": "1.0.0.0", + "Unity.Postprocessing.Runtime": "0.0.0.0", + "Unity.TextMeshPro": "0.0.0.0", + "UnityEngine.AccessibilityModule": "0.0.0.0", + "UnityEngine.AIModule": "0.0.0.0", + "UnityEngine.AnimationModule": "0.0.0.0", + "UnityEngine.ARModule": "0.0.0.0", + "UnityEngine.AssetBundleModule": "0.0.0.0", + "UnityEngine.AudioModule": "0.0.0.0", + "UnityEngine.BaselibModule": "0.0.0.0", + "UnityEngine.ClothModule": "0.0.0.0", + "UnityEngine.ClusterInputModule": "0.0.0.0", + "UnityEngine.ClusterRendererModule": "0.0.0.0", + "UnityEngine.CoreModule": "0.0.0.0", + "UnityEngine.CrashReportingModule": "0.0.0.0", + "UnityEngine.DirectorModule": "0.0.0.0", + "UnityEngine": "0.0.0.0", + "UnityEngine.FileSystemHttpModule": "0.0.0.0", + "UnityEngine.GameCenterModule": "0.0.0.0", + "UnityEngine.GridModule": "0.0.0.0", + "UnityEngine.HotReloadModule": "0.0.0.0", + "UnityEngine.ImageConversionModule": "0.0.0.0", + "UnityEngine.IMGUIModule": "0.0.0.0", + "UnityEngine.InputModule": "0.0.0.0", + "UnityEngine.JSONSerializeModule": "0.0.0.0", + "UnityEngine.LocalizationModule": "0.0.0.0", + "UnityEngine.Networking": "1.0.0.0", + "UnityEngine.ParticleSystemModule": "0.0.0.0", + "UnityEngine.PerformanceReportingModule": "0.0.0.0", + "UnityEngine.Physics2DModule": "0.0.0.0", + "UnityEngine.PhysicsModule": "0.0.0.0", + "UnityEngine.ProfilerModule": "0.0.0.0", + "UnityEngine.Purchasing": "0.0.0.0", + "UnityEngine.ScreenCaptureModule": "0.0.0.0", + "UnityEngine.SharedInternalsModule": "0.0.0.0", + "UnityEngine.SpatialTracking": "0.0.0.0", + "UnityEngine.SpriteMaskModule": "0.0.0.0", + "UnityEngine.SpriteShapeModule": "0.0.0.0", + "UnityEngine.StreamingModule": "0.0.0.0", + "UnityEngine.StyleSheetsModule": "0.0.0.0", + "UnityEngine.SubstanceModule": "0.0.0.0", + "UnityEngine.TerrainModule": "0.0.0.0", + "UnityEngine.TerrainPhysicsModule": "0.0.0.0", + "UnityEngine.TextCoreModule": "0.0.0.0", + "UnityEngine.TextRenderingModule": "0.0.0.0", + "UnityEngine.TilemapModule": "0.0.0.0", + "UnityEngine.Timeline": "1.0.0.0", + "UnityEngine.TimelineModule": "0.0.0.0", + "UnityEngine.TLSModule": "0.0.0.0", + "UnityEngine.UI": "1.0.0.0", + "UnityEngine.UIElementsModule": "0.0.0.0", + "UnityEngine.UIModule": "0.0.0.0", + "UnityEngine.UmbraModule": "0.0.0.0", + "UnityEngine.UNETModule": "0.0.0.0", + "UnityEngine.UnityAnalyticsModule": "0.0.0.0", + "UnityEngine.UnityConnectModule": "0.0.0.0", + "UnityEngine.UnityTestProtocolModule": "0.0.0.0", + "UnityEngine.UnityWebRequestAssetBundleModule": "0.0.0.0", + "UnityEngine.UnityWebRequestAudioModule": "0.0.0.0", + "UnityEngine.UnityWebRequestModule": "0.0.0.0", + "UnityEngine.UnityWebRequestTextureModule": "0.0.0.0", + "UnityEngine.UnityWebRequestWWWModule": "0.0.0.0", + "UnityEngine.VehiclesModule": "0.0.0.0", + "UnityEngine.VFXModule": "0.0.0.0", + "UnityEngine.VideoModule": "0.0.0.0", + "UnityEngine.VRModule": "0.0.0.0", + "UnityEngine.WindModule": "0.0.0.0", + "UnityEngine.XRModule": "0.0.0.0", + "websocket-sharp": "1.0.2.59611" + }, + "runtime": { + "Assembly-CSharp.dll": {} + } + }, + "AmplifyColor/0.0.0.0": { + "runtime": { + "AmplifyColor.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "Assembly-CSharp-firstpass/0.0.0.0": { + "runtime": { + "Assembly-CSharp-firstpass.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "BitpackersASMDEF/0.0.0.0": { + "runtime": { + "BitpackersASMDEF.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "ByteConverter/1.0.0.0": { + "runtime": { + "ByteConverter.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "EmoCompressUtilsASMDEF/0.0.0.0": { + "runtime": { + "EmoCompressUtilsASMDEF.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "FloatCrusher/4.0.0.0": { + "runtime": { + "FloatCrusher.dll": { + "assemblyVersion": "4.0.0.0", + "fileVersion": "4.0.0.0" + } + } + }, + "HalfFloatASMDEF/0.0.0.0": { + "runtime": { + "HalfFloatASMDEF.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "HalFloat/1.0.0.0": { + "runtime": { + "HalFloat.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "InControl/0.0.0.0": { + "runtime": { + "InControl.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "Mono.Security/4.0.0.0": { + "runtime": { + "Mono.Security.dll": { + "assemblyVersion": "4.0.0.0", + "fileVersion": "4.0.0.0" + } + } + }, + "Photon3Unity3D/4.1.4.8": { + "runtime": { + "Photon3Unity3D.dll": { + "assemblyVersion": "4.1.4.8", + "fileVersion": "4.1.4.8" + } + } + }, + "PhotonChat/0.0.0.0": { + "runtime": { + "PhotonChat.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "PhotonRealtime/0.0.0.0": { + "runtime": { + "PhotonRealtime.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "PhotonUnityNetworking.Demos/0.0.0.0": { + "runtime": { + "PhotonUnityNetworking.Demos.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "PhotonUnityNetworking/0.0.0.0": { + "runtime": { + "PhotonUnityNetworking.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "PhotonUnityNetworking.Utilities/0.0.0.0": { + "runtime": { + "PhotonUnityNetworking.Utilities.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "PhotonWebSocket/0.0.0.0": { + "runtime": { + "PhotonWebSocket.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "QuatCompress/2.0.0.0": { + "runtime": { + "QuatCompress.dll": { + "assemblyVersion": "2.0.0.0", + "fileVersion": "2.0.0.0" + } + } + }, + "Sirenix.OdinInspector.Attributes/2.1.6.0": { + "runtime": { + "Sirenix.OdinInspector.Attributes.dll": { + "assemblyVersion": "2.1.6.0", + "fileVersion": "2.1.6.0" + } + } + }, + "Sirenix.OdinInspector.CompatibilityLayer/0.0.0.0": { + "runtime": { + "Sirenix.OdinInspector.CompatibilityLayer.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "Sirenix.Serialization.Config/2.1.6.0": { + "runtime": { + "Sirenix.Serialization.Config.dll": { + "assemblyVersion": "2.1.6.0", + "fileVersion": "2.1.6.0" + } + } + }, + "Sirenix.Serialization/2.1.6.0": { + "runtime": { + "Sirenix.Serialization.dll": { + "assemblyVersion": "2.1.6.0", + "fileVersion": "2.1.6.0" + } + } + }, + "Sirenix.Utilities/2.1.6.0": { + "runtime": { + "Sirenix.Utilities.dll": { + "assemblyVersion": "2.1.6.0", + "fileVersion": "2.1.6.0" + } + } + }, + "SonigonAudioEngine.Runtime/0.0.0.0": { + "runtime": { + "SonigonAudioEngine.Runtime.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "System.Configuration/4.0.0.0": { + "runtime": { + "System.Configuration.dll": { + "assemblyVersion": "4.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "System.Diagnostics.StackTrace/4.1.1.0": { + "runtime": { + "System.Diagnostics.StackTrace.dll": { + "assemblyVersion": "4.1.1.0", + "fileVersion": "4.0.0.0" + } + } + }, + "System.EnterpriseServices/4.0.0.0": { + "runtime": { + "System.EnterpriseServices.dll": { + "assemblyVersion": "4.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "System.Globalization.Extensions/4.1.1.0": { + "runtime": { + "System.Globalization.Extensions.dll": { + "assemblyVersion": "4.1.1.0", + "fileVersion": "4.0.0.0" + } + } + }, + "System.ServiceModel.Internals/0.0.0.0": { + "runtime": { + "System.ServiceModel.Internals.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "4.0.30319.17020" + } + } + }, + "System.Xml.XPath.XDocument/4.1.1.0": { + "runtime": { + "System.Xml.XPath.XDocument.dll": { + "assemblyVersion": "4.1.1.0", + "fileVersion": "4.0.0.0" + } + } + }, + "Unity.Analytics.DataPrivacy/0.0.0.0": { + "runtime": { + "Unity.Analytics.DataPrivacy.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "Unity.Analytics.StandardEvents/1.0.0.0": { + "runtime": { + "Unity.Analytics.StandardEvents.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "Unity.Postprocessing.Runtime/0.0.0.0": { + "runtime": { + "Unity.Postprocessing.Runtime.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "Unity.TextMeshPro/0.0.0.0": { + "runtime": { + "Unity.TextMeshPro.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.AccessibilityModule/0.0.0.0": { + "runtime": { + "UnityEngine.AccessibilityModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.AIModule/0.0.0.0": { + "runtime": { + "UnityEngine.AIModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.AnimationModule/0.0.0.0": { + "runtime": { + "UnityEngine.AnimationModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ARModule/0.0.0.0": { + "runtime": { + "UnityEngine.ARModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.AssetBundleModule/0.0.0.0": { + "runtime": { + "UnityEngine.AssetBundleModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.AudioModule/0.0.0.0": { + "runtime": { + "UnityEngine.AudioModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.BaselibModule/0.0.0.0": { + "runtime": { + "UnityEngine.BaselibModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ClothModule/0.0.0.0": { + "runtime": { + "UnityEngine.ClothModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ClusterInputModule/0.0.0.0": { + "runtime": { + "UnityEngine.ClusterInputModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ClusterRendererModule/0.0.0.0": { + "runtime": { + "UnityEngine.ClusterRendererModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.CoreModule/0.0.0.0": { + "runtime": { + "UnityEngine.CoreModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.CrashReportingModule/0.0.0.0": { + "runtime": { + "UnityEngine.CrashReportingModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.DirectorModule/0.0.0.0": { + "runtime": { + "UnityEngine.DirectorModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine/0.0.0.0": { + "runtime": { + "UnityEngine.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.FileSystemHttpModule/0.0.0.0": { + "runtime": { + "UnityEngine.FileSystemHttpModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.GameCenterModule/0.0.0.0": { + "runtime": { + "UnityEngine.GameCenterModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.GridModule/0.0.0.0": { + "runtime": { + "UnityEngine.GridModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.HotReloadModule/0.0.0.0": { + "runtime": { + "UnityEngine.HotReloadModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ImageConversionModule/0.0.0.0": { + "runtime": { + "UnityEngine.ImageConversionModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.IMGUIModule/0.0.0.0": { + "runtime": { + "UnityEngine.IMGUIModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.InputModule/0.0.0.0": { + "runtime": { + "UnityEngine.InputModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.JSONSerializeModule/0.0.0.0": { + "runtime": { + "UnityEngine.JSONSerializeModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.LocalizationModule/0.0.0.0": { + "runtime": { + "UnityEngine.LocalizationModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.Networking/1.0.0.0": { + "runtime": { + "UnityEngine.Networking.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "UnityEngine.ParticleSystemModule/0.0.0.0": { + "runtime": { + "UnityEngine.ParticleSystemModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.PerformanceReportingModule/0.0.0.0": { + "runtime": { + "UnityEngine.PerformanceReportingModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.Physics2DModule/0.0.0.0": { + "runtime": { + "UnityEngine.Physics2DModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.PhysicsModule/0.0.0.0": { + "runtime": { + "UnityEngine.PhysicsModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ProfilerModule/0.0.0.0": { + "runtime": { + "UnityEngine.ProfilerModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.Purchasing/0.0.0.0": { + "runtime": { + "UnityEngine.Purchasing.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.ScreenCaptureModule/0.0.0.0": { + "runtime": { + "UnityEngine.ScreenCaptureModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.SharedInternalsModule/0.0.0.0": { + "runtime": { + "UnityEngine.SharedInternalsModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.SpatialTracking/0.0.0.0": { + "runtime": { + "UnityEngine.SpatialTracking.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.SpriteMaskModule/0.0.0.0": { + "runtime": { + "UnityEngine.SpriteMaskModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.SpriteShapeModule/0.0.0.0": { + "runtime": { + "UnityEngine.SpriteShapeModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.StreamingModule/0.0.0.0": { + "runtime": { + "UnityEngine.StreamingModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.StyleSheetsModule/0.0.0.0": { + "runtime": { + "UnityEngine.StyleSheetsModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.SubstanceModule/0.0.0.0": { + "runtime": { + "UnityEngine.SubstanceModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.TerrainModule/0.0.0.0": { + "runtime": { + "UnityEngine.TerrainModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.TerrainPhysicsModule/0.0.0.0": { + "runtime": { + "UnityEngine.TerrainPhysicsModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.TextCoreModule/0.0.0.0": { + "runtime": { + "UnityEngine.TextCoreModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.TextRenderingModule/0.0.0.0": { + "runtime": { + "UnityEngine.TextRenderingModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.TilemapModule/0.0.0.0": { + "runtime": { + "UnityEngine.TilemapModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.Timeline/1.0.0.0": { + "runtime": { + "UnityEngine.Timeline.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "UnityEngine.TimelineModule/0.0.0.0": { + "runtime": { + "UnityEngine.TimelineModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.TLSModule/0.0.0.0": { + "runtime": { + "UnityEngine.TLSModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UI/1.0.0.0": { + "runtime": { + "UnityEngine.UI.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "UnityEngine.UIElementsModule/0.0.0.0": { + "runtime": { + "UnityEngine.UIElementsModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UIModule/0.0.0.0": { + "runtime": { + "UnityEngine.UIModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UmbraModule/0.0.0.0": { + "runtime": { + "UnityEngine.UmbraModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UNETModule/0.0.0.0": { + "runtime": { + "UnityEngine.UNETModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityAnalyticsModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityAnalyticsModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityConnectModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityConnectModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityTestProtocolModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityTestProtocolModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityWebRequestAssetBundleModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityWebRequestAssetBundleModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityWebRequestAudioModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityWebRequestAudioModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityWebRequestModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityWebRequestModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityWebRequestTextureModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityWebRequestTextureModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.UnityWebRequestWWWModule/0.0.0.0": { + "runtime": { + "UnityEngine.UnityWebRequestWWWModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.VehiclesModule/0.0.0.0": { + "runtime": { + "UnityEngine.VehiclesModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.VFXModule/0.0.0.0": { + "runtime": { + "UnityEngine.VFXModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.VideoModule/0.0.0.0": { + "runtime": { + "UnityEngine.VideoModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.VRModule/0.0.0.0": { + "runtime": { + "UnityEngine.VRModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.WindModule/0.0.0.0": { + "runtime": { + "UnityEngine.WindModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "UnityEngine.XRModule/0.0.0.0": { + "runtime": { + "UnityEngine.XRModule.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "websocket-sharp/1.0.2.59611": { + "runtime": { + "websocket-sharp.dll": { + "assemblyVersion": "1.0.2.59611", + "fileVersion": "1.0.2.59611" + } + } + } + } + }, + "libraries": { + "Assembly-CSharp/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "AmplifyColor/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Assembly-CSharp-firstpass/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "BitpackersASMDEF/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "ByteConverter/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "EmoCompressUtilsASMDEF/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "FloatCrusher/4.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "HalfFloatASMDEF/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "HalFloat/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "InControl/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Mono.Security/4.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Photon3Unity3D/4.1.4.8": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "PhotonChat/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "PhotonRealtime/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "PhotonUnityNetworking.Demos/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "PhotonUnityNetworking/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "PhotonUnityNetworking.Utilities/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "PhotonWebSocket/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "QuatCompress/2.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Sirenix.OdinInspector.Attributes/2.1.6.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Sirenix.OdinInspector.CompatibilityLayer/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Sirenix.Serialization.Config/2.1.6.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Sirenix.Serialization/2.1.6.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Sirenix.Utilities/2.1.6.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "SonigonAudioEngine.Runtime/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Configuration/4.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Diagnostics.StackTrace/4.1.1.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.EnterpriseServices/4.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Globalization.Extensions/4.1.1.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.ServiceModel.Internals/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Xml.XPath.XDocument/4.1.1.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Unity.Analytics.DataPrivacy/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Unity.Analytics.StandardEvents/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Unity.Postprocessing.Runtime/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Unity.TextMeshPro/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.AccessibilityModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.AIModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.AnimationModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ARModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.AssetBundleModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.AudioModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.BaselibModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ClothModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ClusterInputModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ClusterRendererModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.CoreModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.CrashReportingModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.DirectorModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.FileSystemHttpModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.GameCenterModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.GridModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.HotReloadModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ImageConversionModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.IMGUIModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.InputModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.JSONSerializeModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.LocalizationModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.Networking/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ParticleSystemModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.PerformanceReportingModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.Physics2DModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.PhysicsModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ProfilerModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.Purchasing/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.ScreenCaptureModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.SharedInternalsModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.SpatialTracking/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.SpriteMaskModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.SpriteShapeModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.StreamingModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.StyleSheetsModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.SubstanceModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TerrainModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TerrainPhysicsModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TextCoreModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TextRenderingModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TilemapModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.Timeline/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TimelineModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.TLSModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UI/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UIElementsModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UIModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UmbraModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UNETModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityAnalyticsModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityConnectModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityTestProtocolModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityWebRequestAssetBundleModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityWebRequestAudioModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityWebRequestModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityWebRequestTextureModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.UnityWebRequestWWWModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.VehiclesModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.VFXModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.VideoModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.VRModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.WindModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine.XRModule/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "websocket-sharp/1.0.2.59611": { + "type": "reference", + "serviceable": false, + "sha512": "" + } + } +}
\ No newline at end of file diff --git a/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.dll b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.dll Binary files differnew file mode 100644 index 0000000..2870daf --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.pdb b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.pdb Binary files differnew file mode 100644 index 0000000..7c1e353 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Assembly-CSharp.pdb diff --git a/ROUNDS/bin/Debug/netstandard2.1/BitpackersASMDEF.dll b/ROUNDS/bin/Debug/netstandard2.1/BitpackersASMDEF.dll Binary files differnew file mode 100644 index 0000000..c72d178 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/BitpackersASMDEF.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/ByteConverter.dll b/ROUNDS/bin/Debug/netstandard2.1/ByteConverter.dll Binary files differnew file mode 100644 index 0000000..be00852 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/ByteConverter.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/EmoCompressUtilsASMDEF.dll b/ROUNDS/bin/Debug/netstandard2.1/EmoCompressUtilsASMDEF.dll Binary files differnew file mode 100644 index 0000000..13d00ec --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/EmoCompressUtilsASMDEF.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/FloatCrusher.dll b/ROUNDS/bin/Debug/netstandard2.1/FloatCrusher.dll Binary files differnew file mode 100644 index 0000000..53e50e7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/FloatCrusher.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/HalFloat.dll b/ROUNDS/bin/Debug/netstandard2.1/HalFloat.dll Binary files differnew file mode 100644 index 0000000..d3501a8 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/HalFloat.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/HalfFloatASMDEF.dll b/ROUNDS/bin/Debug/netstandard2.1/HalfFloatASMDEF.dll Binary files differnew file mode 100644 index 0000000..e7e00a7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/HalfFloatASMDEF.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/InControl.dll b/ROUNDS/bin/Debug/netstandard2.1/InControl.dll Binary files differnew file mode 100644 index 0000000..4e9c094 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/InControl.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Mono.Security.dll b/ROUNDS/bin/Debug/netstandard2.1/Mono.Security.dll Binary files differnew file mode 100644 index 0000000..a9377a7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Mono.Security.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Photon3Unity3D.dll b/ROUNDS/bin/Debug/netstandard2.1/Photon3Unity3D.dll Binary files differnew file mode 100644 index 0000000..8f82fac --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Photon3Unity3D.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/PhotonChat.dll b/ROUNDS/bin/Debug/netstandard2.1/PhotonChat.dll Binary files differnew file mode 100644 index 0000000..98b08fb --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/PhotonChat.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/PhotonRealtime.dll b/ROUNDS/bin/Debug/netstandard2.1/PhotonRealtime.dll Binary files differnew file mode 100644 index 0000000..dcc4e9d --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/PhotonRealtime.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.Demos.dll b/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.Demos.dll Binary files differnew file mode 100644 index 0000000..a749129 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.Demos.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.Utilities.dll b/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.Utilities.dll Binary files differnew file mode 100644 index 0000000..7f616a2 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.Utilities.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.dll b/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.dll Binary files differnew file mode 100644 index 0000000..819a722 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/PhotonUnityNetworking.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/PhotonWebSocket.dll b/ROUNDS/bin/Debug/netstandard2.1/PhotonWebSocket.dll Binary files differnew file mode 100644 index 0000000..fafc485 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/PhotonWebSocket.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/QuatCompress.dll b/ROUNDS/bin/Debug/netstandard2.1/QuatCompress.dll Binary files differnew file mode 100644 index 0000000..5eaafe4 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/QuatCompress.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Sirenix.OdinInspector.Attributes.dll b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.OdinInspector.Attributes.dll Binary files differnew file mode 100644 index 0000000..c4d1f3d --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.OdinInspector.Attributes.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Sirenix.OdinInspector.CompatibilityLayer.dll b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.OdinInspector.CompatibilityLayer.dll Binary files differnew file mode 100644 index 0000000..6bb1f45 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.OdinInspector.CompatibilityLayer.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Serialization.Config.dll b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Serialization.Config.dll Binary files differnew file mode 100644 index 0000000..49727b8 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Serialization.Config.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Serialization.dll b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Serialization.dll Binary files differnew file mode 100644 index 0000000..36cc8a7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Serialization.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Utilities.dll b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Utilities.dll Binary files differnew file mode 100644 index 0000000..eb2b50a --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Sirenix.Utilities.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/SonigonAudioEngine.Runtime.dll b/ROUNDS/bin/Debug/netstandard2.1/SonigonAudioEngine.Runtime.dll Binary files differnew file mode 100644 index 0000000..b534b95 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/SonigonAudioEngine.Runtime.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/System.Configuration.dll b/ROUNDS/bin/Debug/netstandard2.1/System.Configuration.dll Binary files differnew file mode 100644 index 0000000..714c954 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/System.Configuration.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/System.Diagnostics.StackTrace.dll b/ROUNDS/bin/Debug/netstandard2.1/System.Diagnostics.StackTrace.dll Binary files differnew file mode 100644 index 0000000..a9bdde4 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/System.Diagnostics.StackTrace.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/System.EnterpriseServices.dll b/ROUNDS/bin/Debug/netstandard2.1/System.EnterpriseServices.dll Binary files differnew file mode 100644 index 0000000..83c12c3 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/System.EnterpriseServices.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/System.Globalization.Extensions.dll b/ROUNDS/bin/Debug/netstandard2.1/System.Globalization.Extensions.dll Binary files differnew file mode 100644 index 0000000..c5a425f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/System.Globalization.Extensions.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/System.ServiceModel.Internals.dll b/ROUNDS/bin/Debug/netstandard2.1/System.ServiceModel.Internals.dll Binary files differnew file mode 100644 index 0000000..7c9e4f9 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/System.ServiceModel.Internals.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/System.Xml.XPath.XDocument.dll b/ROUNDS/bin/Debug/netstandard2.1/System.Xml.XPath.XDocument.dll Binary files differnew file mode 100644 index 0000000..b61d964 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/System.Xml.XPath.XDocument.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Unity.Analytics.DataPrivacy.dll b/ROUNDS/bin/Debug/netstandard2.1/Unity.Analytics.DataPrivacy.dll Binary files differnew file mode 100644 index 0000000..bd8107f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Unity.Analytics.DataPrivacy.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Unity.Analytics.StandardEvents.dll b/ROUNDS/bin/Debug/netstandard2.1/Unity.Analytics.StandardEvents.dll Binary files differnew file mode 100644 index 0000000..b8e7ea7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Unity.Analytics.StandardEvents.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Unity.Postprocessing.Runtime.dll b/ROUNDS/bin/Debug/netstandard2.1/Unity.Postprocessing.Runtime.dll Binary files differnew file mode 100644 index 0000000..c41b606 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Unity.Postprocessing.Runtime.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/Unity.TextMeshPro.dll b/ROUNDS/bin/Debug/netstandard2.1/Unity.TextMeshPro.dll Binary files differnew file mode 100644 index 0000000..5c8f06b --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/Unity.TextMeshPro.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AIModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AIModule.dll Binary files differnew file mode 100644 index 0000000..9aae0a0 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AIModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ARModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ARModule.dll Binary files differnew file mode 100644 index 0000000..9963d22 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ARModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AccessibilityModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AccessibilityModule.dll Binary files differnew file mode 100644 index 0000000..b928cba --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AccessibilityModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AnimationModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AnimationModule.dll Binary files differnew file mode 100644 index 0000000..ca21101 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AnimationModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AssetBundleModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AssetBundleModule.dll Binary files differnew file mode 100644 index 0000000..bb9e09b --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AssetBundleModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AudioModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AudioModule.dll Binary files differnew file mode 100644 index 0000000..95dad10 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.AudioModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.BaselibModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.BaselibModule.dll Binary files differnew file mode 100644 index 0000000..c947b97 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.BaselibModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClothModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClothModule.dll Binary files differnew file mode 100644 index 0000000..1292474 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClothModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClusterInputModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClusterInputModule.dll Binary files differnew file mode 100644 index 0000000..3449bd0 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClusterInputModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClusterRendererModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClusterRendererModule.dll Binary files differnew file mode 100644 index 0000000..a64ac45 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ClusterRendererModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.CoreModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.CoreModule.dll Binary files differnew file mode 100644 index 0000000..55cea3c --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.CoreModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.CrashReportingModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.CrashReportingModule.dll Binary files differnew file mode 100644 index 0000000..2cf7ec5 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.CrashReportingModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.DirectorModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.DirectorModule.dll Binary files differnew file mode 100644 index 0000000..6bf7138 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.DirectorModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.FileSystemHttpModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.FileSystemHttpModule.dll Binary files differnew file mode 100644 index 0000000..ad9c9a0 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.FileSystemHttpModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.GameCenterModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.GameCenterModule.dll Binary files differnew file mode 100644 index 0000000..d4e7172 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.GameCenterModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.GridModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.GridModule.dll Binary files differnew file mode 100644 index 0000000..d4ab8a8 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.GridModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.HotReloadModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.HotReloadModule.dll Binary files differnew file mode 100644 index 0000000..0420a42 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.HotReloadModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.IMGUIModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.IMGUIModule.dll Binary files differnew file mode 100644 index 0000000..469d9aa --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.IMGUIModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ImageConversionModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ImageConversionModule.dll Binary files differnew file mode 100644 index 0000000..54629f7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ImageConversionModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.InputModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.InputModule.dll Binary files differnew file mode 100644 index 0000000..b9bf3fd --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.InputModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.JSONSerializeModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.JSONSerializeModule.dll Binary files differnew file mode 100644 index 0000000..dbe606b --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.JSONSerializeModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.LocalizationModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.LocalizationModule.dll Binary files differnew file mode 100644 index 0000000..85d22b6 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.LocalizationModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Networking.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Networking.dll Binary files differnew file mode 100644 index 0000000..1865c32 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Networking.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ParticleSystemModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ParticleSystemModule.dll Binary files differnew file mode 100644 index 0000000..4f521f6 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ParticleSystemModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.PerformanceReportingModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.PerformanceReportingModule.dll Binary files differnew file mode 100644 index 0000000..39e261f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.PerformanceReportingModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Physics2DModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Physics2DModule.dll Binary files differnew file mode 100644 index 0000000..a4fc4b0 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Physics2DModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.PhysicsModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.PhysicsModule.dll Binary files differnew file mode 100644 index 0000000..bc73d6b --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.PhysicsModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ProfilerModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ProfilerModule.dll Binary files differnew file mode 100644 index 0000000..faa7b88 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ProfilerModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Purchasing.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Purchasing.dll Binary files differnew file mode 100644 index 0000000..a4af5b3 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Purchasing.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ScreenCaptureModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ScreenCaptureModule.dll Binary files differnew file mode 100644 index 0000000..d19fb01 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.ScreenCaptureModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SharedInternalsModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SharedInternalsModule.dll Binary files differnew file mode 100644 index 0000000..147b2ba --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SharedInternalsModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpatialTracking.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpatialTracking.dll Binary files differnew file mode 100644 index 0000000..ccaac44 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpatialTracking.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpriteMaskModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpriteMaskModule.dll Binary files differnew file mode 100644 index 0000000..63fe37f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpriteMaskModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpriteShapeModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpriteShapeModule.dll Binary files differnew file mode 100644 index 0000000..21388e7 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SpriteShapeModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.StreamingModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.StreamingModule.dll Binary files differnew file mode 100644 index 0000000..c7af1e6 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.StreamingModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.StyleSheetsModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.StyleSheetsModule.dll Binary files differnew file mode 100644 index 0000000..c782175 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.StyleSheetsModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SubstanceModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SubstanceModule.dll Binary files differnew file mode 100644 index 0000000..c7879ad --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.SubstanceModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TLSModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TLSModule.dll Binary files differnew file mode 100644 index 0000000..6ffbccd --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TLSModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TerrainModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TerrainModule.dll Binary files differnew file mode 100644 index 0000000..b79ad00 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TerrainModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TerrainPhysicsModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TerrainPhysicsModule.dll Binary files differnew file mode 100644 index 0000000..f3c956d --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TerrainPhysicsModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TextCoreModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TextCoreModule.dll Binary files differnew file mode 100644 index 0000000..3f8c45d --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TextCoreModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TextRenderingModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TextRenderingModule.dll Binary files differnew file mode 100644 index 0000000..cc1eb8f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TextRenderingModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TilemapModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TilemapModule.dll Binary files differnew file mode 100644 index 0000000..a3712ec --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TilemapModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Timeline.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Timeline.dll Binary files differnew file mode 100644 index 0000000..2283dda --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.Timeline.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TimelineModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TimelineModule.dll Binary files differnew file mode 100644 index 0000000..2c57729 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.TimelineModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UI.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UI.dll Binary files differnew file mode 100644 index 0000000..b55de0b --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UI.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UIElementsModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UIElementsModule.dll Binary files differnew file mode 100644 index 0000000..b04ba76 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UIElementsModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UIModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UIModule.dll Binary files differnew file mode 100644 index 0000000..d76fd3a --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UIModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UNETModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UNETModule.dll Binary files differnew file mode 100644 index 0000000..8282190 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UNETModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UmbraModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UmbraModule.dll Binary files differnew file mode 100644 index 0000000..68ef7e8 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UmbraModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityAnalyticsModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityAnalyticsModule.dll Binary files differnew file mode 100644 index 0000000..7f34e4d --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityAnalyticsModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityConnectModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityConnectModule.dll Binary files differnew file mode 100644 index 0000000..9664608 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityConnectModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityTestProtocolModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityTestProtocolModule.dll Binary files differnew file mode 100644 index 0000000..734ab31 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityTestProtocolModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestAssetBundleModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestAssetBundleModule.dll Binary files differnew file mode 100644 index 0000000..8a44ab4 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestAssetBundleModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestAudioModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestAudioModule.dll Binary files differnew file mode 100644 index 0000000..c7161cb --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestAudioModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestModule.dll Binary files differnew file mode 100644 index 0000000..613a337 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestTextureModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestTextureModule.dll Binary files differnew file mode 100644 index 0000000..d503771 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestTextureModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestWWWModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestWWWModule.dll Binary files differnew file mode 100644 index 0000000..7bb4eee --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.UnityWebRequestWWWModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VFXModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VFXModule.dll Binary files differnew file mode 100644 index 0000000..86df7fa --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VFXModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VRModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VRModule.dll Binary files differnew file mode 100644 index 0000000..6d345f6 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VRModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VehiclesModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VehiclesModule.dll Binary files differnew file mode 100644 index 0000000..ba6f51f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VehiclesModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VideoModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VideoModule.dll Binary files differnew file mode 100644 index 0000000..488b508 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.VideoModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.WindModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.WindModule.dll Binary files differnew file mode 100644 index 0000000..d9158d4 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.WindModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.XRModule.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.XRModule.dll Binary files differnew file mode 100644 index 0000000..a105196 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.XRModule.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.dll b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.dll Binary files differnew file mode 100644 index 0000000..e8c17a4 --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/UnityEngine.dll diff --git a/ROUNDS/bin/Debug/netstandard2.1/websocket-sharp.dll b/ROUNDS/bin/Debug/netstandard2.1/websocket-sharp.dll Binary files differnew file mode 100644 index 0000000..6ec719f --- /dev/null +++ b/ROUNDS/bin/Debug/netstandard2.1/websocket-sharp.dll diff --git a/ROUNDS/emotitron.Utilities.Example/BasicController.cs b/ROUNDS/emotitron.Utilities.Example/BasicController.cs new file mode 100644 index 0000000..9601cab --- /dev/null +++ b/ROUNDS/emotitron.Utilities.Example/BasicController.cs @@ -0,0 +1,289 @@ +using emotitron.Compression; +using Photon.Compression; +using Photon.Pun; +using UnityEngine; + +namespace emotitron.Utilities.Example; + +public class BasicController : MonoBehaviour +{ + public enum Timing + { + Auto, + Fixed, + Update, + LateUpdate + } + + private PhotonView pv; + + private Rigidbody rb; + + private Rigidbody2D rb2D; + + [HideInInspector] + public TransformCrusher TransformCrusherRef; + + private TransformCrusher tc; + + public Timing timing = Timing.Fixed; + + public bool moveRelative = true; + + [Space] + public KeyCode moveLeft = KeyCode.A; + + public KeyCode moveRight = KeyCode.D; + + public KeyCode moveFwd = KeyCode.W; + + public KeyCode moveBwd = KeyCode.S; + + public KeyCode moveUp = KeyCode.Space; + + public KeyCode moveDn = KeyCode.Z; + + [Space] + public KeyCode pitchPos = KeyCode.R; + + public KeyCode pitchNeg = KeyCode.C; + + public KeyCode yawPos = KeyCode.E; + + public KeyCode yawNeg = KeyCode.Q; + + public KeyCode rollPos = KeyCode.Alpha4; + + public KeyCode rollNeg = KeyCode.Alpha4; + + [Space] + public bool clampToCrusher; + + public float moveSpeed = 5f; + + public float turnSpeed = 60f; + + public float moveForce = 12f; + + public float turnForce = 100f; + + public float scaleSpeed = 1f; + + private bool isMine; + + private bool IsMine + { + get + { + if (!(pv == null)) + { + return pv.IsMine; + } + return true; + } + } + + private void Awake() + { + rb = GetComponent<Rigidbody>(); + rb2D = GetComponent<Rigidbody2D>(); + pv = GetComponent<PhotonView>(); + } + + private void Start() + { + if (GetComponent<IHasTransformCrusher>() != null) + { + tc = GetComponent<IHasTransformCrusher>().TC; + } + if (!IsMine) + { + if ((bool)rb) + { + rb.isKinematic = true; + } + if ((bool)rb2D) + { + rb2D.isKinematic = true; + } + } + } + + private void FixedUpdate() + { + if (timing == Timing.Fixed || (timing == Timing.Auto && (bool)rb)) + { + Apply(); + } + } + + private void Update() + { + if (timing == Timing.Update || (timing == Timing.Auto && !rb)) + { + Apply(); + } + } + + private void LateUpdate() + { + if (timing == Timing.LateUpdate) + { + Apply(); + } + } + + private void SumKeys(out Vector3 move, out Vector3 turn) + { + move = new Vector3(0f, 0f, 0f); + if (Input.touchCount > 0) + { + Vector2 rawPosition = Input.GetTouch(0).rawPosition; + if (rawPosition.x < (float)Screen.width * 0.333f) + { + move.x -= 1f; + } + else if (rawPosition.x > (float)Screen.width * 0.666f) + { + move.x += 1f; + } + if (rawPosition.y < (float)Screen.height * 0.333f) + { + move.z -= 1f; + } + else if (rawPosition.y > (float)Screen.height * 0.666f) + { + move.z += 1f; + } + } + if (Input.GetKey(moveRight)) + { + move.x += 1f; + } + if (Input.GetKey(moveLeft)) + { + move.x -= 1f; + } + if (Input.GetKey(moveUp)) + { + move.y += 1f; + } + if (Input.GetKey(moveDn)) + { + move.y -= 1f; + } + if (Input.GetKey(moveFwd)) + { + move.z += 1f; + } + if (Input.GetKey(moveBwd)) + { + move.z -= 1f; + } + move = Vector3.ClampMagnitude(move, 1f); + turn = new Vector3(0f, 0f, 0f); + if (Input.GetKey(pitchPos)) + { + turn.x += 1f; + } + if (Input.GetKey(pitchNeg)) + { + turn.x -= 1f; + } + if (Input.GetKey(yawPos)) + { + turn.y += 1f; + } + if (Input.GetKey(yawNeg)) + { + turn.y -= 1f; + } + if (Input.GetKey(rollPos)) + { + turn.z += 1f; + } + if (Input.GetKey(rollNeg)) + { + turn.z -= 1f; + } + } + + private void Apply() + { + if (!IsMine) + { + return; + } + SumKeys(out var move, out var turn); + if ((bool)rb && !rb.isKinematic) + { + if ((bool)rb && clampToCrusher && tc != null) + { + rb.MovePosition(tc.PosCrusher.Clamp(rb.position)); + } + move *= moveForce * Time.deltaTime; + if (moveRelative) + { + rb.AddRelativeForce(move, ForceMode.VelocityChange); + } + else + { + rb.AddForce(move, ForceMode.VelocityChange); + } + } + else if ((bool)rb2D && !rb2D.isKinematic) + { + if ((bool)rb2D && clampToCrusher && tc != null) + { + rb2D.MovePosition(tc.PosCrusher.Clamp(rb2D.position)); + } + move *= moveForce * Time.deltaTime; + if (moveRelative) + { + rb2D.AddRelativeForce(move, ForceMode2D.Impulse); + } + else + { + rb2D.AddForce(move, ForceMode2D.Impulse); + } + } + else + { + Vector3 vector = (rb ? rb.position : base.transform.position); + if (moveRelative) + { + vector += base.transform.localRotation * move * moveSpeed * Time.deltaTime; + } + else + { + vector += move * moveSpeed * Time.deltaTime; + } + if (clampToCrusher && tc != null && tc.PosCrusher != null) + { + vector = tc.PosCrusher.Clamp(vector); + } + if ((bool)rb) + { + rb.MovePosition(vector); + } + else + { + base.transform.position = vector; + } + } + if ((bool)rb && !rb.isKinematic) + { + turn *= turnForce * Time.deltaTime; + rb.AddRelativeTorque(turn, ForceMode.VelocityChange); + } + else if (clampToCrusher && tc != null && tc.RotCrusher.TRSType != TRSType.Quaternion) + { + Vector3 localEulerAngles = tc.RotCrusher.Clamp(base.transform.eulerAngles += turn * turnSpeed * Time.deltaTime); + base.transform.localEulerAngles = localEulerAngles; + } + else + { + base.transform.rotation *= Quaternion.Euler(turn * turnSpeed * Time.deltaTime); + } + } +} diff --git a/ROUNDS/emotitron.Utilities.GUIUtilities/ShowIfInterfaceAttribute.cs b/ROUNDS/emotitron.Utilities.GUIUtilities/ShowIfInterfaceAttribute.cs new file mode 100644 index 0000000..37ccae3 --- /dev/null +++ b/ROUNDS/emotitron.Utilities.GUIUtilities/ShowIfInterfaceAttribute.cs @@ -0,0 +1,29 @@ +using System; +using UnityEngine; + +namespace emotitron.Utilities.GUIUtilities; + +public class ShowIfInterfaceAttribute : PropertyAttribute +{ + public readonly Type type; + + public readonly string tooltip; + + public readonly float min; + + public readonly float max; + + public ShowIfInterfaceAttribute(Type type, string tooltip) + { + this.type = type; + this.tooltip = tooltip; + } + + public ShowIfInterfaceAttribute(Type type, string tooltip, float min, float max) + { + this.type = type; + this.tooltip = tooltip; + this.min = min; + this.max = max; + } +} diff --git a/ROUNDS/emotitron.Utilities.GUIUtilities/ValueTypeAttribute.cs b/ROUNDS/emotitron.Utilities.GUIUtilities/ValueTypeAttribute.cs new file mode 100644 index 0000000..045853b --- /dev/null +++ b/ROUNDS/emotitron.Utilities.GUIUtilities/ValueTypeAttribute.cs @@ -0,0 +1,18 @@ +using System; +using UnityEngine; + +namespace emotitron.Utilities.GUIUtilities; + +[AttributeUsage(AttributeTargets.Field)] +public class ValueTypeAttribute : PropertyAttribute +{ + public string labeltag; + + public float width; + + public ValueTypeAttribute(string labeltag, float width = 48f) + { + this.labeltag = labeltag; + this.width = width; + } +} diff --git a/ROUNDS/emotitron.Utilities.Networking/AutoDestroyWrongNetLib.cs b/ROUNDS/emotitron.Utilities.Networking/AutoDestroyWrongNetLib.cs new file mode 100644 index 0000000..5ccd8f2 --- /dev/null +++ b/ROUNDS/emotitron.Utilities.Networking/AutoDestroyWrongNetLib.cs @@ -0,0 +1,25 @@ +using UnityEngine; + +namespace emotitron.Utilities.Networking; + +public class AutoDestroyWrongNetLib : MonoBehaviour +{ + public enum NetLib + { + UNET, + PUN, + PUN2, + PUNAndPUN2 + } + + [SerializeField] + public NetLib netLib; + + private void Awake() + { + if ((netLib & NetLib.PUN2) == 0) + { + Object.Destroy(base.gameObject); + } + } +} diff --git a/ROUNDS/emotitron.Utilities/MarkerNameType.cs b/ROUNDS/emotitron.Utilities/MarkerNameType.cs new file mode 100644 index 0000000..58f6617 --- /dev/null +++ b/ROUNDS/emotitron.Utilities/MarkerNameType.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +namespace emotitron.Utilities; + +[Serializable] +public struct MarkerNameType +{ + [HideInInspector] + public MarkerType type; + + [HideInInspector] + public int hash; + + [HideInInspector] + public string name; + + public static string[] enumNames = Enum.GetNames(typeof(MarkerType)); + + public MarkerNameType(MarkerType vitalType) + { + type = vitalType; + name = Enum.GetName(typeof(MarkerType), vitalType); + hash = name.GetHashCode(); + } + + public MarkerNameType(string name) + { + type = (MarkerType)NameTypeUtils.GetVitalTypeForName(name, enumNames); + this.name = name; + hash = name.GetHashCode(); + } + + public override string ToString() + { + return string.Concat("NameType: ", type, " ", name, " ", hash); + } +} diff --git a/ROUNDS/emotitron.Utilities/MarkerType.cs b/ROUNDS/emotitron.Utilities/MarkerType.cs new file mode 100644 index 0000000..5555cda --- /dev/null +++ b/ROUNDS/emotitron.Utilities/MarkerType.cs @@ -0,0 +1,10 @@ +namespace emotitron.Utilities; + +public enum MarkerType +{ + None, + Custom, + Default, + Player, + NPC +} diff --git a/ROUNDS/emotitron.Utilities/NameTypeUtils.cs b/ROUNDS/emotitron.Utilities/NameTypeUtils.cs new file mode 100644 index 0000000..9cbb9c9 --- /dev/null +++ b/ROUNDS/emotitron.Utilities/NameTypeUtils.cs @@ -0,0 +1,16 @@ +namespace emotitron.Utilities; + +public static class NameTypeUtils +{ + public static int GetVitalTypeForName(string name, string[] enumNames) + { + for (int i = 0; i < enumNames.Length; i++) + { + if (name == enumNames[i]) + { + return i; + } + } + return 1; + } +} diff --git a/ROUNDS/emotitron/TestEnum.cs b/ROUNDS/emotitron/TestEnum.cs new file mode 100644 index 0000000..7339e2e --- /dev/null +++ b/ROUNDS/emotitron/TestEnum.cs @@ -0,0 +1,9 @@ +namespace emotitron; + +public enum TestEnum +{ + None, + Some, + SomeMore, + All +} diff --git a/ROUNDS/emotitron/TestPackObject.cs b/ROUNDS/emotitron/TestPackObject.cs new file mode 100644 index 0000000..4ce82e3 --- /dev/null +++ b/ROUNDS/emotitron/TestPackObject.cs @@ -0,0 +1,50 @@ +using Photon.Compression; +using Photon.Pun.Simple; +using UnityEngine; + +namespace emotitron; + +[PackObject(DefaultKeyRate.Every, defaultInclusion = DefaultPackInclusion.Explicit)] +public class TestPackObject : NetComponent, IOnPreSimulate, IOnInterpolate +{ + [SyncHalfFloat(IndicatorBit.None, KeyRate.UseDefault, snapshotCallback = "SnapshotHook", applyCallback = "RotationHook", setValueTiming = SetValueTiming.BeforeCallback, interpolate = true, keyRate = KeyRate.Every)] + public float rotation; + + [SyncRangedInt(-1, 2, IndicatorBits.None, KeyRate.UseDefault)] + public int intoroboto; + + public void RotationHook(float newrot, float oldrot) + { + base.transform.localEulerAngles = new Vector3(0f, rotation, 0f); + } + + public void SnapshotHook(float snap, float targ) + { + } + + public void OnPreSimulate(int frameId, int subFrameId) + { + if (photonView.IsMine) + { + rotation = (Mathf.Sin(Time.time) + 0.5f) * 120f; + base.transform.localEulerAngles = new Vector3(0f, rotation, 0f); + } + } + + public void FixedUpdate() + { + } + + private void Update() + { + } + + public bool OnInterpolate(int snapFrameId, int targFrameId, float t) + { + if (!base.PhotonView.IsMine) + { + base.transform.localEulerAngles = new Vector3(0f, rotation, 0f); + } + return true; + } +} diff --git a/ROUNDS/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs b/ROUNDS/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs new file mode 100644 index 0000000..8bf3a42 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.0/.NETStandard,Version=v2.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// <autogenerated /> +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] diff --git a/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.GeneratedMSBuildEditorConfig.editorconfig b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..e80af31 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,3 @@ +is_global = true +build_property.RootNamespace = ROUNDS +build_property.ProjectDir = D:\Documents\Unity\Decompile\Rounds\ROUNDS\ diff --git a/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.assets.cache b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.assets.cache Binary files differnew file mode 100644 index 0000000..f40fb67 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.assets.cache diff --git a/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.AssemblyReference.cache b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.AssemblyReference.cache Binary files differnew file mode 100644 index 0000000..6702ccf --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.AssemblyReference.cache diff --git a/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.CoreCompileInputs.cache b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..abbaf43 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +445aef3d0251eab34a429825d3dd3504bfc2f382 diff --git a/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.FileListAbsolute.txt b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..1b64ba9 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.0/ROUNDS.csproj.FileListAbsolute.txt @@ -0,0 +1,3 @@ +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.0\ROUNDS.csproj.AssemblyReference.cache +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.0\ROUNDS.GeneratedMSBuildEditorConfig.editorconfig +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.0\ROUNDS.csproj.CoreCompileInputs.cache diff --git a/ROUNDS/obj/Debug/netstandard2.1/.NETStandard,Version=v2.1.AssemblyAttributes.cs b/ROUNDS/obj/Debug/netstandard2.1/.NETStandard,Version=v2.1.AssemblyAttributes.cs new file mode 100644 index 0000000..348b87f --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/.NETStandard,Version=v2.1.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// <autogenerated /> +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] diff --git a/ROUNDS/obj/Debug/netstandard2.1/Assembly-CSharp.dll b/ROUNDS/obj/Debug/netstandard2.1/Assembly-CSharp.dll Binary files differnew file mode 100644 index 0000000..2870daf --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/Assembly-CSharp.dll diff --git a/ROUNDS/obj/Debug/netstandard2.1/Assembly-CSharp.pdb b/ROUNDS/obj/Debug/netstandard2.1/Assembly-CSharp.pdb Binary files differnew file mode 100644 index 0000000..7c1e353 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/Assembly-CSharp.pdb diff --git a/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.GeneratedMSBuildEditorConfig.editorconfig b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..e80af31 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,3 @@ +is_global = true +build_property.RootNamespace = ROUNDS +build_property.ProjectDir = D:\Documents\Unity\Decompile\Rounds\ROUNDS\ diff --git a/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.assets.cache b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.assets.cache Binary files differnew file mode 100644 index 0000000..f554f65 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.assets.cache diff --git a/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.AssemblyReference.cache b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.AssemblyReference.cache Binary files differnew file mode 100644 index 0000000..53a865b --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.AssemblyReference.cache diff --git a/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.CopyComplete b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.CopyComplete new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.CopyComplete diff --git a/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.CoreCompileInputs.cache b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..f9f483a --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +fd3f160051944d1de016472d977614e781ca5a2c diff --git a/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.FileListAbsolute.txt b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..c6d9d07 --- /dev/null +++ b/ROUNDS/obj/Debug/netstandard2.1/ROUNDS.csproj.FileListAbsolute.txt @@ -0,0 +1,109 @@ +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.1\ROUNDS.csproj.AssemblyReference.cache +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.1\ROUNDS.GeneratedMSBuildEditorConfig.editorconfig +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.1\ROUNDS.csproj.CoreCompileInputs.cache +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Assembly-CSharp.deps.json +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Assembly-CSharp.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Assembly-CSharp.pdb +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\AmplifyColor.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Assembly-CSharp-firstpass.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\BitpackersASMDEF.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\ByteConverter.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\EmoCompressUtilsASMDEF.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\FloatCrusher.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\HalfFloatASMDEF.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\HalFloat.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\InControl.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Mono.Security.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Photon3Unity3D.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\PhotonChat.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\PhotonRealtime.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\PhotonUnityNetworking.Demos.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\PhotonUnityNetworking.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\PhotonUnityNetworking.Utilities.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\PhotonWebSocket.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\QuatCompress.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Sirenix.OdinInspector.Attributes.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Sirenix.OdinInspector.CompatibilityLayer.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Sirenix.Serialization.Config.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Sirenix.Serialization.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Sirenix.Utilities.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\SonigonAudioEngine.Runtime.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\System.Configuration.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\System.Diagnostics.StackTrace.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\System.EnterpriseServices.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\System.Globalization.Extensions.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\System.ServiceModel.Internals.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\System.Xml.XPath.XDocument.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Unity.Analytics.DataPrivacy.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Unity.Analytics.StandardEvents.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Unity.Postprocessing.Runtime.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\Unity.TextMeshPro.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.AccessibilityModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.AIModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.AnimationModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ARModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.AssetBundleModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.AudioModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.BaselibModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ClothModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ClusterInputModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ClusterRendererModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.CoreModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.CrashReportingModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.DirectorModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.FileSystemHttpModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.GameCenterModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.GridModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.HotReloadModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ImageConversionModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.IMGUIModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.InputModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.JSONSerializeModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.LocalizationModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.Networking.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ParticleSystemModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.PerformanceReportingModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.Physics2DModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.PhysicsModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ProfilerModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.Purchasing.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.ScreenCaptureModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.SharedInternalsModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.SpatialTracking.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.SpriteMaskModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.SpriteShapeModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.StreamingModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.StyleSheetsModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.SubstanceModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TerrainModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TerrainPhysicsModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TextCoreModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TextRenderingModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TilemapModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.Timeline.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TimelineModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.TLSModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UI.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UIElementsModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UIModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UmbraModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UNETModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityAnalyticsModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityConnectModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityTestProtocolModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityWebRequestAssetBundleModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityWebRequestAudioModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityWebRequestModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityWebRequestTextureModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.UnityWebRequestWWWModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.VehiclesModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.VFXModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.VideoModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.VRModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.WindModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\UnityEngine.XRModule.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\bin\Debug\netstandard2.1\websocket-sharp.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.1\ROUNDS.csproj.CopyComplete +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.1\Assembly-CSharp.dll +D:\Documents\Unity\Decompile\Rounds\ROUNDS\obj\Debug\netstandard2.1\Assembly-CSharp.pdb diff --git a/ROUNDS/obj/ROUNDS.csproj.nuget.dgspec.json b/ROUNDS/obj/ROUNDS.csproj.nuget.dgspec.json new file mode 100644 index 0000000..47f97c6 --- /dev/null +++ b/ROUNDS/obj/ROUNDS.csproj.nuget.dgspec.json @@ -0,0 +1,67 @@ +{ + "format": 1, + "restore": { + "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj": {} + }, + "projects": { + "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj", + "projectName": "Assembly-CSharp", + "projectPath": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj", + "packagesPath": "C:\\Users\\Administrator\\.nuget\\packages\\", + "outputPath": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\Administrator\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netstandard2.1" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netstandard2.1": { + "targetAlias": "netstandard2.1", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "netstandard2.1": { + "targetAlias": "netstandard2.1", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "NETStandard.Library": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.201\\RuntimeIdentifierGraph.json" + } + } + } + } +}
\ No newline at end of file diff --git a/ROUNDS/obj/ROUNDS.csproj.nuget.g.props b/ROUNDS/obj/ROUNDS.csproj.nuget.g.props new file mode 100644 index 0000000..ccfb216 --- /dev/null +++ b/ROUNDS/obj/ROUNDS.csproj.nuget.g.props @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> + <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess> + <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool> + <ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile> + <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> + <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Administrator\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders> + <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> + <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.4.0</NuGetToolVersion> + </PropertyGroup> + <ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> + <SourceRoot Include="C:\Users\Administrator\.nuget\packages\" /> + <SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/ROUNDS/obj/ROUNDS.csproj.nuget.g.targets b/ROUNDS/obj/ROUNDS.csproj.nuget.g.targets new file mode 100644 index 0000000..3dc06ef --- /dev/null +++ b/ROUNDS/obj/ROUNDS.csproj.nuget.g.targets @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
\ No newline at end of file diff --git a/ROUNDS/obj/project.assets.json b/ROUNDS/obj/project.assets.json new file mode 100644 index 0000000..e8b73d7 --- /dev/null +++ b/ROUNDS/obj/project.assets.json @@ -0,0 +1,73 @@ +{ + "version": 3, + "targets": { + ".NETStandard,Version=v2.1": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + ".NETStandard,Version=v2.1": [] + }, + "packageFolders": { + "C:\\Users\\Administrator\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj", + "projectName": "Assembly-CSharp", + "projectPath": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj", + "packagesPath": "C:\\Users\\Administrator\\.nuget\\packages\\", + "outputPath": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\Administrator\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netstandard2.1" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netstandard2.1": { + "targetAlias": "netstandard2.1", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "netstandard2.1": { + "targetAlias": "netstandard2.1", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "NETStandard.Library": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\7.0.201\\RuntimeIdentifierGraph.json" + } + } + } +}
\ No newline at end of file diff --git a/ROUNDS/obj/project.nuget.cache b/ROUNDS/obj/project.nuget.cache new file mode 100644 index 0000000..94970c7 --- /dev/null +++ b/ROUNDS/obj/project.nuget.cache @@ -0,0 +1,8 @@ +{ + "version": 2, + "dgSpecHash": "g9+dUSYJ0z+WUUe9SaWEOwzvksCFUhrXh05AZG0aXqSVrMxvjVFVEdVaIODCx5y9bM7mhNdslnf8W0Y9wpBkjg==", + "success": true, + "projectFilePath": "D:\\Documents\\Unity\\Decompile\\Rounds\\ROUNDS\\ROUNDS.csproj", + "expectedPackageFiles": [], + "logs": [] +}
\ No newline at end of file |