using MiniJSON;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
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>();
viewRadius = DefaultViewRadius;
State = PlayerState.Remote;
if (ForceLocal)
{
StartLocal();
}
}
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);
AddShadow addShadow = FindObjectOfType<AddShadow>();
Light pointLight = GetComponentsInChildren<Light>().FirstOrDefault(l => l.type == LightType.Point);
if (pointLight != null)
{
pointLight.enabled = false;
addShadow.PointLight = pointLight;
}
//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();
}
*/
}
}