using MiniJSON; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Player : MonoBehaviour { private Item netItem; public bool ForceLocal; public bool IsLocal { get { return ForceLocal || (netItem != null && netItem.IsLocal); } } private UIHookup uiHookup; private CharacterController charControl; private PlayerFade playerFade; private Vector3 fadeSpot; private Camera playerFadeCam; private Transform fadeCamRoot; private Vector3 startCamShift; private Vector3 endCamShift; private float camHeight; private float camOffsetZ; public float DefaultMaxHealth = 1; private float maxHealth = 0; private float health = 0; private float cooldownBaseScale = 1; public GameObject MeshRoot; public enum PlayerState { Remote, Normal, Attacking, Dead } public PlayerState State { get; private set; } // Start is called before the first frame update void Awake() { if (shiftTween == null) shiftTween = new SimpleTween(); shiftTween.Stop(); netItem = GetComponentInChildren<Item>(); castLight = transform.Find("CastLight").gameObject; if (attackTween == null) attackTween = new SimpleTween(); uiHookup = FindObjectOfType<UIHookup>(); if (ForceLocal) { StartLocal(); } viewRadius = DefaultViewRadius; State = PlayerState.Remote; } public GameObject PlayerMesh; private Image attackCooldownImage; private GameObject castLight; private float bottomOffset; public float BottomOffset { get { return bottomOffset; } } void StartLocal() { State = PlayerState.Normal; maxHealth = DefaultMaxHealth; health = DefaultMaxHealth; castLight.SetActive(true); charControl = GetComponentInChildren<CharacterController>(); charControl.enabled = true; bottomOffset = -charControl.center.y + charControl.height * 0.5f; playerFade = FindObjectOfType<PlayerFade>(); if (playerFade != null) { playerFadeCam = playerFade.GetComponent<Camera>(); fadeSpot = transform.position; if (playerFadeCam != null) { fadeCamRoot = playerFadeCam.transform.root; startCamShift = playerFadeCam.transform.localPosition; camHeight = startCamShift.y; camOffsetZ = startCamShift.z; ShiftCamera(); // shift instantly in the XZ plane fadeCamRoot.position = SlowFollowXZ(transform.position, fadeCamRoot.position, 1); } } cooldownBaseScale = uiHookup.AttackCooldown.localScale.x; attackCooldownImage = uiHookup.AttackCooldown.GetComponentInChildren<Image>(); // scale to 0; uiHookup.AttackCooldown.localScale = new Vector3(0, 0, 1); //netItem.GetNetHost().SpawnItemLocal("test", // i => // { // i.transform.position = transform.position; // } //); } private float attackBuildup = 0; private float attackCooldown = 0; void TakeDamage(object detailsObj) { Dictionary<string, object> details = detailsObj as Dictionary<string, object>; if (details != null && details.ContainsKey("damage")) { float damage = details.Key("damage", Convert.ToSingle); health -= damage; if (health < 0) { health = 0; // TODO die State = PlayerState.Dead; netItem.DestroyItem(); } //Rect hRect = uiHookup.Health.rect; //hRect.width = uiHookup.HealthWidth * Vector3 scale = uiHookup.Health.localScale; scale.x = (health / maxHealth); ; uiHookup.Health.localScale = scale; } } private SimpleTween shiftTween; private void ShiftCamera() { startCamShift = playerFadeCam.transform.localPosition; endCamShift = new Vector3(UnityEngine.Random.Range(-0.5f, 0.5f), camHeight + UnityEngine.Random.Range(-0.4f, 0.4f), UnityEngine.Random.Range(camOffsetZ - 0.4f, camOffsetZ + 0.4f)); shiftTween.Init(v => playerFadeCam.transform.localPosition = startCamShift * (1 - v) + endCamShift * v, SimpleTween.QuadEaseInOut, 0, 1, UnityEngine.Random.Range(5f, 10f)); shiftTween.OnFinish = ShiftCamera; } private void OnDestroy() { shiftTween.Stop(); attackTween.Stop(); } void StartRemote() { if (PlayerMesh != null) { foreach (MeshRenderer mr in PlayerMesh.GetComponentsInChildren<MeshRenderer>()) { if (mr.sharedMaterial.name == "Player") { Material m = mr.material; m.DisableKeyword("_EMISSION"); m.globalIlluminationFlags = MaterialGlobalIlluminationFlags.EmissiveIsBlack; m.SetColor("_EmissionColor", Color.black); } } } } public float Speed; private List<Touch> touches = new List<Touch>(); public float MoveTouchFullZone = 0.7f; public float MoveTouchRadiusSize = 1.45f; public float AttackTouchRadiusSize = 1.45f; public float DefaultViewRadius = 5.5f; private float viewRadius; public float CamFollowAmount = 0.9f; public float SpotFollowAmount = 0.95f; private Vector3 SlowFollowXZ(Vector3 target, Vector3 current, float factor) { Vector2 currentXZ = new Vector2(current.x, current.z); Vector2 targetXZ = new Vector2(target.x, target.z); float followThisFrame = 1 - Mathf.Pow(1 - factor, Time.deltaTime); Vector2 newCurrentXZ = targetXZ * followThisFrame + currentXZ * (1 - followThisFrame); current.x = newCurrentXZ.x; current.z = newCurrentXZ.y; return current; } private bool touchInAttack = false; // Update is called once per frame void Update() { if (IsLocal && charControl != null) { RaycastHit hit; if (Physics.Raycast(new Ray(transform.position, Vector3.down), out hit, 10f)) { Vector3 pos = transform.position; pos.y = hit.point.y + (bottomOffset + 0.01f); transform.position = pos; } Vector3 wantMove = new Vector3(); if (Input.GetKey(KeyCode.UpArrow)) { wantMove.z += 1; } if (Input.GetKey(KeyCode.DownArrow)) { wantMove.z -= 1; } if (Input.GetKey(KeyCode.RightArrow)) { wantMove.x += 1; } if (Input.GetKey(KeyCode.LeftArrow)) { wantMove.x -= 1; } wantMove.Normalize(); if (uiHookup != null && uiHookup.MainCanvas != null) { touches.Clear(); touches.AddRange(Input.touches); if (Input.GetMouseButton(0)) { touches.Add(new Touch { position = Input.mousePosition }); } bool wasInAttackTouch = touchInAttack; touchInAttack = false; foreach (Touch touch in touches) { // movement touch float radius = uiHookup.MoveTouch.rect.width * 0.5f * MoveTouchRadiusSize; Vector2 diff = new Vector2(); RectTransformUtility.ScreenPointToLocalPointInRectangle(uiHookup.MoveTouch, touch.position, null, out diff); if (diff.magnitude < radius) { wantMove = new Vector3(diff.x, 0, diff.y) / (radius * MoveTouchFullZone); if (wantMove.magnitude > 1) wantMove.Normalize(); break; } } foreach (Touch touch in touches) { float radius = uiHookup.AttackTouch.rect.width * 0.5f * AttackTouchRadiusSize; Vector2 diff = new Vector2(); RectTransformUtility.ScreenPointToLocalPointInRectangle(uiHookup.AttackTouch, touch.position, null, out diff); if (diff.magnitude < radius && diff.magnitude > 0.2f) { if (!wasInAttackTouch && State == PlayerState.Normal && attackCooldown == 0) { Attack(new Vector3(diff.x, 0, diff.y)); } touchInAttack = true; break; } } } if (playerFade != null && playerFadeCam != null) { Vector3 playerScreen3 = playerFadeCam.WorldToScreenPoint(fadeSpot); Vector3 edgeScreen3 = playerFadeCam.WorldToScreenPoint(fadeSpot + playerFadeCam.transform.right * viewRadius); Vector2 playerScreen2 = new Vector2(playerScreen3.x / playerFadeCam.pixelWidth, playerScreen3.y / playerFadeCam.pixelHeight); Vector2 edgeScreen2 = new Vector2(edgeScreen3.x / playerFadeCam.pixelWidth, edgeScreen3.y / playerFadeCam.pixelHeight); float radius = (edgeScreen2 - playerScreen2).magnitude; playerFade.SetFadeParams(radius, playerScreen2); fadeCamRoot.position = SlowFollowXZ(transform.position, fadeCamRoot.position, SpotFollowAmount); //playerFadeCam.transform.LookAt(fadeCamRoot, Vector3.up); fadeSpot = SlowFollowXZ(transform.position, fadeSpot, CamFollowAmount); } if (wantMove.sqrMagnitude > 0 && State == PlayerState.Normal) { wantMove *= Speed * Time.deltaTime; wantMove.y = -0.1f * Time.deltaTime; CollisionFlags flags = charControl.Move(wantMove); } if (attackCooldown > 0) { attackCooldownImage.color = new Color(1, 0, 0, 0.5f); attackCooldown = Math.Max(0, attackCooldown - Time.deltaTime * AttackCooldownRate); uiHookup.AttackCooldown.localScale = new Vector3(attackCooldown, attackCooldown, 1) * cooldownBaseScale; } else { attackCooldownImage.color = new Color(0, 0, 1, 0.5f); attackBuildup = Math.Max(0, attackBuildup - Time.deltaTime * AttackBuildupRate); uiHookup.AttackCooldown.localScale = new Vector3(attackBuildup, attackBuildup, 1) * cooldownBaseScale; } } } public float AttackBuildupStep = 0.2f; public float AttackBuildupRate = 1; public float AttackCooldownRate = 0.5f; private SimpleTween attackTween; public float AttackTime = 0.2f; public float AttackDist = 2f; public float Damage = 1f; private Vector3 attackDelta; private Vector3 lastAttackPos; private void Attack(Vector3 attackDir) { attackBuildup += AttackBuildupStep; if (attackBuildup > 1) { attackBuildup = 0; attackCooldown = 1; } State = PlayerState.Attacking; attackDelta = attackDir.normalized * AttackDist; Vector3 startPos = transform.position; lastAttackPos = startPos; attackTween.Init( v => { lastAttackPos = transform.position; transform.position = startPos + attackDelta * v; MeshRoot.transform.localScale = new Vector3(1, 1, 1) * (v * 0.3f + 1.0f); }, SimpleTween.QuadEaseOut, 0, 1, AttackTime); attackTween.OnFinish = FinishedAttack; } public float AttackWait = 0.8f; void OnTriggerEnter(Collider other) { if (State == PlayerState.Attacking) { Virus v = other.GetComponentInParent<Virus>(); if (v == null) { transform.position = lastAttackPos; FinishedAttack(); } else { Item virusItem = v.GetComponentInChildren<Item>(); if (virusItem != null && netItem.GetNetHost() != null) { netItem.GetNetHost().SendItemCommand(virusItem.Key, "TakeDamage", new Dictionary<string, object> { { "damage", Damage } }); } } } } private void FinishedAttack() { MeshRoot.transform.localScale = new Vector3(1, 1, 1); State = PlayerState.Normal; attackTween.Stop(); /* if (UnityEngine.Random.Range(0, 1) < 0.4f) { targetPlayer = null; PathToPlayer(); return; } if (targetPlayer != null && DistToTarget <= AttackMaxDist) { attackTimer.Start(AttackWait, CheckAttackTarget); } else { targetPlayer = null; PathToPlayer(); } */ } }