871 lines
27 KiB
C#
871 lines
27 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Assets.HeroEditor4D.Common.Scripts.CharacterScripts;
|
|
using Assets.HeroEditor4D.Common.Scripts.Enums;
|
|
using Mirror;
|
|
using TMPro;
|
|
using Firebase.Firestore;
|
|
using Firebase.Extensions;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using GooglePlayGames;
|
|
using UnityEngine.SocialPlatforms;
|
|
using Firebase.Auth;
|
|
using UnityEngine.UI;
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
|
|
public class playerNetwork : NetworkBehaviour
|
|
{
|
|
public const float ATTACK_COOLDOWN = 0.6f;
|
|
[HideInInspector]
|
|
public StatManager statManager;
|
|
//public const int XPFORLEVEL = 10;
|
|
[SyncVar(hook =nameof(OnHealthChanged))] public int health = 100;
|
|
public Character4D character;
|
|
public characterManager characterMan;
|
|
|
|
[SyncVar(hook =nameof(OnDirectionChanged))]
|
|
public Vector2 directionNetwork;
|
|
[SyncVar(hook =nameof(OnAnimChanged))]
|
|
public int animIntNetwork;
|
|
|
|
[SyncVar(hook = nameof(onKillCountChange))]
|
|
public int enemyKillCount;
|
|
// public int xp { get{
|
|
// int val = 0;
|
|
// for(int i =5; i <= enemyKillCount; i+=5){
|
|
// val = enemyKillCount;
|
|
// }
|
|
// return val;
|
|
// }}
|
|
[SyncVar(hook = nameof(OnXpChanged))]
|
|
public int XP;
|
|
|
|
|
|
public int lvl2 { get{
|
|
return GetLevelForKills2(enemyKillCount);
|
|
}}
|
|
|
|
public int GetLevelForKills2(int kills){
|
|
int val = 0;
|
|
for(int i =10; i <= kills; i+=10){
|
|
val ++;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
|
|
public int lvl{
|
|
get{
|
|
return GetLevelByXp(XP);
|
|
}
|
|
}
|
|
|
|
|
|
public int GetLevelByXp(int xp){
|
|
// int level = Mathf.CeilToInt(Mathf.Sqrt(xp/100f));
|
|
// if(level <= 0){level = 1;}
|
|
|
|
// return level;
|
|
|
|
int level = Mathf.CeilToInt(Mathf.Log(xp / 100f,2) + 1);
|
|
if(level <=0){level = 1;}
|
|
return level;
|
|
// int level = 1;
|
|
// int xpNeeded = 100;
|
|
|
|
// while (xp >= xpNeeded)
|
|
// {
|
|
// level++;
|
|
// xpNeeded = 100 * (int)Mathf.Pow(2, level - 1);
|
|
// }
|
|
|
|
// return level - 1;
|
|
}
|
|
|
|
public int GetXpForLevel(int level){
|
|
if (level <= 0)
|
|
level = 1;
|
|
|
|
return Mathf.FloorToInt(100 * Mathf.Pow(2, level - 1));
|
|
}
|
|
|
|
|
|
public float XpSliderVal{
|
|
get{
|
|
|
|
int nextLevelXp = GetXpForLevel(lvl);
|
|
int prevLevelXp = GetXpForLevel(lvl-1);
|
|
|
|
if(nextLevelXp == prevLevelXp){
|
|
prevLevelXp = 0;
|
|
}
|
|
|
|
int range = nextLevelXp - prevLevelXp;
|
|
// Debug.Log($"{XP-prevLevelXp} / {range}");
|
|
//Debug.Log($"next : {nextLevelXp}, prev: {prevLevelXp}, xp:{XP}, xpSince:{XP-prevLevelXp}");
|
|
return ((float)(XP-prevLevelXp) / (float)range);
|
|
// int nextLevel = lvl+1;
|
|
|
|
// int curLevelXp = lvl * lvl;
|
|
// int nextLevelXp = nextLevel * nextLevel;
|
|
// // Debug.Log($"Xp Calc: {XP}-{curLevelXp}/{nextLevelXp} - {curLevelXp}");
|
|
// // Debug.Log($"{curLevelXp-XP}/{nextLevelXp - curLevelXp}");
|
|
// if(XP == 0){return 0;}
|
|
// return 1f - ((float)(curLevelXp - XP) / (float)(nextLevelXp- curLevelXp));
|
|
}
|
|
|
|
}
|
|
|
|
[SyncVar]
|
|
public string playerName;
|
|
[SyncVar]
|
|
public int playerCoin;
|
|
|
|
[SyncVar]
|
|
public string myCharJson;
|
|
|
|
public TMP_Text txtEnemyKillCount;
|
|
public TMP_Text txtPlayerName;
|
|
public TMP_Text questText;
|
|
public GameObject questUI;
|
|
public TMP_Text coinText;
|
|
public TMP_Text xpText;
|
|
public TMP_Text lvlText;
|
|
public Slider xpSlider;
|
|
public GameObject[] xpSliderSlots;
|
|
public TMP_Text xpEnableTxt;
|
|
//public TMP_Text attackDmgEnableTxt;
|
|
|
|
public GameObject canvas;
|
|
public Slider healthBar;
|
|
public Slider armorBar;
|
|
public Inventory inventory;
|
|
public static Transform localPlayerTransform;
|
|
public GameObject healthVfx;
|
|
public GameObject damageVfx;
|
|
|
|
public GameObject levelUpVfx;
|
|
public QuestScriptable currentQuest;
|
|
public List<QuestAction> questActions;
|
|
public List<string> completedQuests;
|
|
|
|
public GameObject projectile;
|
|
public GameObject arrowRange;
|
|
|
|
public string selectedCharacterJson = CharacterSelection.selectedCharJson;
|
|
|
|
public void SetActiveQuest(QuestScriptable questData){
|
|
currentQuest = questData;
|
|
questText.text = questData.questTitle;
|
|
questUI.SetActive(true);
|
|
|
|
foreach(QuestAction quest in questActions){
|
|
if(quest.questData == questData){
|
|
quest.activate();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void CompleteQuest(QuestScriptable questData){
|
|
if(questData != currentQuest){
|
|
Debug.LogError("Completed a quest that wasnt active");
|
|
return;
|
|
}
|
|
completedQuests.Add(currentQuest.questName);
|
|
currentQuest = null;
|
|
|
|
questText.text = "Quest Completed!";
|
|
playerCoin += questData.rewardAmount;
|
|
coinText.text = playerCoin.ToString();
|
|
//add delay
|
|
StartCoroutine(DelayUI());
|
|
|
|
|
|
}
|
|
public void CancelledQuest(){
|
|
|
|
questText.text = "Quest Cancelled: " + currentQuest.questTitle;
|
|
//
|
|
currentQuest = null;
|
|
|
|
StartCoroutine(DelayUI());
|
|
|
|
}
|
|
IEnumerator DelayUI(){
|
|
yield return new WaitForSecondsRealtime(10f);
|
|
questUI.SetActive(false);
|
|
}
|
|
|
|
public static void registerQuestAction(QuestAction action){
|
|
localPlayerTransform.GetComponent<playerNetwork>().questActions.Add(action);
|
|
}
|
|
|
|
|
|
void Start(){
|
|
|
|
// for(int i =0; i < 2000; i+=10){
|
|
// int level = GetLevelByXp(i);
|
|
// int xp = GetXpForLevel(level);
|
|
// Debug.Log($"{i} : {level} : {xp}");
|
|
// }
|
|
|
|
if(!isLocalPlayer){
|
|
canvas.SetActive(false);
|
|
if(!isServer){
|
|
CmdRequestCharJson();
|
|
}
|
|
}else{
|
|
|
|
localPlayerTransform = transform;
|
|
cameraRPG.instance.SetTarget(transform);
|
|
#if UNITY_EDITOR
|
|
ResetHealthAndArmor();
|
|
#else
|
|
LoadPlayerData();
|
|
#endif
|
|
|
|
statManager.OnStatsChanged += ConfigArmorHealthSliders;
|
|
|
|
if(isServer){
|
|
playerName = gplayAuth.userNameCloud;
|
|
myCharJson = CharacterSelection.selectedCharJson;
|
|
RpcBroadcastCharJson(CharacterSelection.selectedCharJson);
|
|
}
|
|
else{
|
|
CmdSetName(gplayAuth.userNameCloud);
|
|
|
|
CmdSetCharJson(CharacterSelection.selectedCharJson);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void LoadCharFromJson(string json){
|
|
if(json.Length <=0){return;}
|
|
character.FromJson(json,true);
|
|
}
|
|
|
|
public void SavePlayerData(){
|
|
#if UNITY_EDITOR
|
|
return;
|
|
#endif
|
|
Debug.Log("*** Save Method Got Called ! ***");
|
|
|
|
if(!isLoaded){
|
|
Debug.Log("*** Save Method Return ***");
|
|
return;
|
|
}
|
|
FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
|
|
|
|
//int playerCoin = int.Parse(coins.text);
|
|
Dictionary<string, object> saveValues = new Dictionary<string, object>{
|
|
|
|
{"playerInventory" , JsonConvert.SerializeObject(inventory.inventoryManager.GetEntries())},
|
|
{"playerHealth" , health},
|
|
{"playerCoin", playerCoin},
|
|
{"killCount", enemyKillCount},
|
|
{"xp", XP},
|
|
{"completedQuest", completedQuests},
|
|
{"playerStats", statManager.PlayerStats},
|
|
{"characterJson", selectedCharacterJson},
|
|
|
|
};
|
|
|
|
DocumentReference docRef = db.Collection("PlayerData").Document(gplayAuth.userID);
|
|
docRef.SetAsync(saveValues).ContinueWithOnMainThread(task => {
|
|
if(task.IsCompleted){
|
|
Debug.Log("**** Save Completed Firestore ****");
|
|
}
|
|
else{
|
|
Debug.Log("**** Failed to save data to firestore ****");
|
|
}
|
|
});
|
|
}
|
|
public bool isLoaded = false;
|
|
public void LoadPlayerData(){
|
|
#if UNITY_EDITOR
|
|
return;
|
|
#endif
|
|
Debug.Log("**** Data Load method got called ****");
|
|
FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
|
|
DocumentReference docRef = db.Collection("PlayerData").Document(gplayAuth.userID);
|
|
|
|
docRef.GetSnapshotAsync().ContinueWithOnMainThread(task => {
|
|
DocumentSnapshot snapshot = task.Result;
|
|
if(snapshot.Exists){
|
|
Debug.Log("**** Found previous Data to load ****");
|
|
//load data
|
|
// Dictionary<string,object> dic = snapshot.ToDictionary(ServerTimestampBehavior.Estimate);
|
|
// Debug.Log("Reading data");
|
|
// foreach(KeyValuePair<string,object> item in dic){
|
|
// Debug.Log(item.Key + " : " +item.Value.ToString());
|
|
// }
|
|
//saveNameTxt.text = snapshot.GetValue<string>("playerName");
|
|
//load kills
|
|
int _enemyKillCount = snapshot.GetValue<int>("killCount");
|
|
SetEnemyKillCount(_enemyKillCount);
|
|
//load XP
|
|
XP = snapshot.GetValue<int>("xp");
|
|
//Load coin
|
|
int _playerCoin = snapshot.GetValue<int>("playerCoin");
|
|
SetPlayerCoins(_playerCoin);
|
|
// coinText.text = snapshot.GetValue<int>("playerCoin").ToString();
|
|
|
|
//Load Health
|
|
int savedHealth = snapshot.GetValue<int>("playerHealth");
|
|
SetHealth(savedHealth);
|
|
ResetHealthAndArmor();
|
|
healthBar.value =(savedHealth);
|
|
armorBar.value = savedHealth;
|
|
//load Inventory
|
|
Dictionary<int, string> inventoryGetData = JsonConvert.DeserializeObject<Dictionary<int, string>>(snapshot.GetValue<string>("playerInventory"));
|
|
inventory.inventoryManager.SetInventory(inventoryGetData);
|
|
|
|
completedQuests = snapshot.GetValue<List<string>>("completedQuest");
|
|
//stats
|
|
statManager.loadFromCloudSave(snapshot.GetValue<Dictionary<string, int>>("playerStats"));
|
|
|
|
|
|
isLoaded = true;
|
|
}else{
|
|
//show error previous data doesnt exists to load
|
|
Debug.Log("**** No previous data to load ****");
|
|
isLoaded = true;
|
|
|
|
}
|
|
});
|
|
}
|
|
[Command]
|
|
void CmdSetName(string nameValue){
|
|
playerName = nameValue;
|
|
}
|
|
|
|
[Command(requiresAuthority =false)]
|
|
void CmdRequestCharJson(){
|
|
RpcBroadcastCharJson(myCharJson);
|
|
}
|
|
|
|
[Command]
|
|
void CmdSetCharJson(string newValue){
|
|
myCharJson = newValue;
|
|
RpcBroadcastCharJson(newValue);
|
|
LoadCharFromJson(newValue);
|
|
}
|
|
[ClientRpc]
|
|
void RpcBroadcastCharJson(string newValue){
|
|
LoadCharFromJson(newValue);
|
|
}
|
|
|
|
void OnDirectionChanged(Vector2 oldVal, Vector2 newVal){
|
|
character.SetDirection(newVal);
|
|
}
|
|
|
|
void OnAnimChanged(int oldVal, int newVal){
|
|
if(isLocalPlayer){return;}
|
|
character.AnimationManager.SetState((CharacterState)newVal);
|
|
}
|
|
|
|
rangeEnemyFinder rangeEnemyFind;
|
|
|
|
enemyScript closestEnemy => rangeEnemyFind.targetEnemy;
|
|
void Awake(){
|
|
rangeEnemyFind = GetComponent<rangeEnemyFinder>();
|
|
}
|
|
|
|
float attackTimer = 0;
|
|
[HideInInspector]
|
|
public PlayerAttack playerAttack;
|
|
void Update(){
|
|
if(isLocalPlayer){
|
|
|
|
if(attackTimer >0){attackTimer-=Time.deltaTime;}
|
|
|
|
if(isServer){
|
|
SetAnimationData(character.Direction, character.Animator.GetInteger("State"));
|
|
}else{
|
|
CmdUpdateAnim(character.Direction, character.Animator.GetInteger("State"));
|
|
}
|
|
|
|
healthBar.value =(health);
|
|
armorBar.value = health;
|
|
txtEnemyKillCount.text = enemyKillCount.ToString();
|
|
coinText.text = playerCoin.ToString();
|
|
txtPlayerName.text = gplayAuth.userNameCloud;
|
|
}
|
|
ShowXP();
|
|
ShowLevel();
|
|
|
|
}
|
|
|
|
[Command]
|
|
void CmdUpdateAnim(Vector2 direction, int animState){
|
|
SetAnimationData(direction, animState);
|
|
}
|
|
|
|
void SetAnimationData(Vector2 direction, int animState){
|
|
directionNetwork = direction;
|
|
animIntNetwork = animState;
|
|
if(!isLocalPlayer){
|
|
character.AnimationManager.SetState((CharacterState)animState);
|
|
character.SetDirection(direction);
|
|
}
|
|
}
|
|
|
|
void OnHealthChanged(int oldVal, int newVal){
|
|
|
|
if(!isLocalPlayer){return;}
|
|
//
|
|
if(oldVal < newVal){
|
|
GameObject newObject = Instantiate(healthVfx , character.characterTransform());
|
|
newObject.transform.localPosition = Vector3.zero;
|
|
newObject.transform.parent = transform;
|
|
|
|
//StartCoroutine (Couroutine_autoDisableVFX(newObject));
|
|
vfxScript vfxSc = newObject.AddComponent<vfxScript>();
|
|
|
|
}else if (oldVal > newVal ){
|
|
//damage VFX
|
|
GameObject newObject = Instantiate(damageVfx , character.characterTransform());
|
|
newObject.transform.localPosition = new Vector3(0, 5f, 0);
|
|
newObject.transform.parent = transform;
|
|
|
|
//StartCoroutine (Couroutine_autoDisableVFX(newObject));
|
|
vfxScript vfxSc = newObject.AddComponent<vfxScript>();
|
|
// vfxSc.offsetVFX = new Vector3(0, 5f, 0);
|
|
// vfxSc.target = character.characterTransform();
|
|
}
|
|
|
|
SavePlayerData();
|
|
healthBar.value =(newVal);
|
|
armorBar.value = newVal;
|
|
}
|
|
|
|
// IEnumerator Couroutine_autoDisableVFX(GameObject go){
|
|
// yield return new WaitForSecondsRealtime(5f);
|
|
// Destroy(go);
|
|
// }
|
|
|
|
void onKillCountChange(int oldval, int newval){
|
|
|
|
if(!isLocalPlayer){return;}
|
|
// int prevLevel = GetLevelForKills(oldval);
|
|
// int newLevel = GetLevelForKills(newval);
|
|
SavePlayerData();
|
|
|
|
// if(newLevel > prevLevel){
|
|
// StartCoroutine(uiTxtDelay(25f));
|
|
// }
|
|
// if(enemyKillCount == 5 ){
|
|
// //SavePlayerData();
|
|
// //QuestComplete();
|
|
// AddCoin();
|
|
// }
|
|
}
|
|
|
|
void OnXpChanged(int oldVal, int newVal){
|
|
if(!isLocalPlayer){return;}
|
|
|
|
int prevLevel = GetLevelByXp(oldVal);
|
|
int newLevle = GetLevelByXp(newVal);
|
|
|
|
if(newLevle > prevLevel){
|
|
int levelChange = newLevle - prevLevel;
|
|
GameObject newObject = Instantiate(levelUpVfx , character.characterTransform());
|
|
newObject.transform.localPosition = Vector3.zero;
|
|
newObject.transform.parent = transform;
|
|
StartCoroutine(uiTxtDelay(25f, levelChange));
|
|
}
|
|
}
|
|
|
|
public void SetHealth(int newvalue){
|
|
if(isServer){
|
|
health = newvalue;
|
|
healthBar.value =(newvalue);
|
|
armorBar.value = newvalue;
|
|
}else{
|
|
CmdSetHealth(newvalue);
|
|
}
|
|
}
|
|
|
|
public void SetEnemyKillCount(int newValue){
|
|
if(isServer){
|
|
enemyKillCount = newValue;
|
|
}else{
|
|
CmdSetEnemyKillCount(newValue);
|
|
}
|
|
}
|
|
|
|
public void SetPlayerCoins(int newVal){
|
|
if(isServer){
|
|
playerCoin = newVal;
|
|
}else{
|
|
CmdSetPlayerCoin(newVal);
|
|
}
|
|
}
|
|
|
|
[Command]
|
|
void CmdSetPlayerCoin(int newVal){
|
|
playerCoin = newVal;
|
|
}
|
|
|
|
[Command]
|
|
void CmdSetEnemyKillCount(int newValue){
|
|
enemyKillCount = newValue;
|
|
}
|
|
|
|
[Command]
|
|
void CmdSetHealth(int newValue){
|
|
health = newValue;
|
|
}
|
|
|
|
public void TakeDamage(int attackDamage){
|
|
serverTakeDmg(attackDamage);
|
|
// if(isLocalPlayer){
|
|
// takedmg(attackDamage);
|
|
// }else if(isServer){
|
|
// RpcTakeDamage(attackDamage);
|
|
// }
|
|
}
|
|
|
|
void serverTakeDmg(int damage){
|
|
health -= damage;
|
|
if(health <=0){
|
|
RpcDeath();
|
|
death();
|
|
}
|
|
}
|
|
|
|
float xpTimer = 0;
|
|
public void ShowXP(){
|
|
if(xpTimer >0){xpTimer -= Time.deltaTime;return;}
|
|
|
|
xpTimer = 1;
|
|
xpText.text = (Mathf.RoundToInt(XP/100f) * 100f).ToString();
|
|
xpSlider.value = XpSliderVal;
|
|
|
|
for(int i=0; i < 10; i++){
|
|
float val = (float)i /10f;
|
|
xpSliderSlots[i].SetActive(xpSlider.value > val);
|
|
}
|
|
}
|
|
public void ShowLevel(){
|
|
lvlText.text = lvl.ToString();
|
|
}
|
|
|
|
public void OnEnemyKilled(int enemyLevel){
|
|
//disable take damage and disable healthbar going backwards
|
|
int prevValue = lvl;
|
|
// SavePlayerData();
|
|
enemyKillCount++;
|
|
//XP += (int)(enemyScript.XP_GAIN * (enemyLevel/2f));
|
|
XP += enemyScript.XP_GAIN_Base + Mathf.FloorToInt(enemyScript.XP_GAIN * (enemyLevel-1));
|
|
}
|
|
|
|
IEnumerator uiTxtDelay (float delayTime, int levelChange){
|
|
//enable
|
|
xpEnableTxt.gameObject.SetActive(true);
|
|
//int attackDamageChange= 5 * levelChange;
|
|
|
|
//attackDmgEnableTxt.gameObject.SetActive(true);
|
|
//attackDmgEnableTxt.text = "Attack Damage + " + attackDamageChange;
|
|
yield return new WaitForSecondsRealtime(delayTime);
|
|
//disable
|
|
xpEnableTxt.gameObject.SetActive(false);
|
|
//attackDmgEnableTxt.gameObject.SetActive(false);
|
|
|
|
}
|
|
// public void QuestComplete(){
|
|
// //task completion logic
|
|
// // Strikethrough the text
|
|
|
|
// //questText.text = "<s>Kill 5 Enemies to claim 100Golds</s> Completed";
|
|
// Debug.Log("First quest completed");
|
|
// }
|
|
public void AddCoin(){
|
|
|
|
playerCoin += 100;
|
|
coinText.text = playerCoin.ToString();
|
|
}
|
|
|
|
[ClientRpc]
|
|
public void RpcDeath(){
|
|
death();
|
|
}
|
|
public bool isDead = false;
|
|
public void death(){
|
|
Debug.Log("Death called");
|
|
character.AnimationManager.Die();
|
|
isDead = true;
|
|
|
|
StartCoroutine(CouroutineWaitDeath());
|
|
// throw new System.Exception();
|
|
}
|
|
|
|
IEnumerator CouroutineWaitDeath (){
|
|
yield return new WaitForSecondsRealtime(3);
|
|
isDead = false;
|
|
playerRespawn();
|
|
|
|
}
|
|
|
|
public void OnAttack(){
|
|
if(attackTimer > 0){
|
|
return;
|
|
}
|
|
characterMan.SetActiveWeapon(78);
|
|
|
|
attackTimer = ATTACK_COOLDOWN;
|
|
if(isLocalPlayer){
|
|
PlayAttackAnim();
|
|
playerAttack.Attack(false);
|
|
if(isServer){
|
|
RpcPlayAttackAnim();
|
|
}else{
|
|
CmdPlayAttackAnim();
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializeField] public float arrowSpeed = 2.0f;
|
|
[SerializeField] public float arrowShootOffset = 1;
|
|
[SerializeField] public float arrowShootHeightOffset = 1;
|
|
|
|
public void OnRangeAttack(){
|
|
if(attackTimer>0){
|
|
return;
|
|
}
|
|
if(closestEnemy==null){return;}
|
|
|
|
attackTimer = ATTACK_COOLDOWN;
|
|
|
|
characterMan.EquipBow();
|
|
PlayAttackAnim();
|
|
|
|
StartCoroutine(ArrowShootDelay());
|
|
// arrowRange.transform.position = startingPosition;
|
|
|
|
//TODO: Deal Damage once it hits enemy
|
|
|
|
}
|
|
public float arrowDelay;
|
|
IEnumerator ArrowShootDelay (){
|
|
|
|
yield return new WaitForSeconds(arrowDelay);
|
|
|
|
Vector3 startingPosition = transform.position ;
|
|
Vector3 destination = closestEnemy.transform.position;
|
|
|
|
//TODO: Move attack projectile from startingPosition to destination
|
|
Vector3 direction = (destination - startingPosition).normalized;
|
|
startingPosition += (direction * arrowShootOffset);
|
|
startingPosition += (Vector3.up * arrowShootHeightOffset);
|
|
destination += (Vector3.up * arrowShootHeightOffset);
|
|
// Quaternion rotation = Quaternion.LookRotation(direction);
|
|
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
|
|
Quaternion rotation = Quaternion.Euler(0,0,angle - 90f);
|
|
|
|
GameObject newArrow = Instantiate(arrowRange , transform.position + (direction * arrowShootOffset) , rotation);
|
|
|
|
StartCoroutine(moveArrow(newArrow.transform , startingPosition , destination , closestEnemy));
|
|
|
|
}
|
|
public int RangeDmg = 10;
|
|
|
|
IEnumerator moveArrow (Transform arrow , Vector3 start, Vector3 destination, enemyScript target ){
|
|
|
|
float dist = Vector3.Distance(start , destination);
|
|
|
|
float duration = dist/arrowSpeed;
|
|
|
|
float timer = 0f;
|
|
|
|
while(timer < duration){
|
|
|
|
arrow.position = Vector3.Lerp(start , destination , timer/duration);
|
|
|
|
timer += Time.deltaTime;
|
|
yield return null;
|
|
}
|
|
|
|
target.TakeDamage(RangeDmg, netId);
|
|
|
|
Destroy(arrow.gameObject);
|
|
|
|
}
|
|
|
|
public int MagicAttackWeaponIndex = 52;
|
|
public void OnMagicAttack(){
|
|
if(attackTimer > 0){
|
|
return;
|
|
}
|
|
|
|
attackTimer = ATTACK_COOLDOWN;
|
|
// characterMan.SetActiveWeapon(MagicAttackWeaponIndex);
|
|
if(isLocalPlayer){
|
|
PlayAttackAnim();
|
|
//?
|
|
playerAttack.MagicalAttack();
|
|
playerAttack.Attack(true);
|
|
if(isServer){
|
|
RpcPlayAttackAnim();
|
|
}else{
|
|
CmdPlayAttackAnim();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Command]
|
|
void CmdPlayAttackAnim(){
|
|
PlayAttackAnim();
|
|
RpcPlayAttackAnim();
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcPlayAttackAnim(){
|
|
if(isLocalPlayer){return;}
|
|
PlayAttackAnim();
|
|
}
|
|
|
|
void PlayAttackAnim(){
|
|
switch (character.WeaponType)
|
|
{
|
|
case WeaponType.Melee1H:
|
|
case WeaponType.Paired:
|
|
character.AnimationManager.Slash(twoHanded: false);
|
|
break;
|
|
case WeaponType.Melee2H:
|
|
character.AnimationManager.Slash(twoHanded: true);
|
|
break;
|
|
case WeaponType.Bow:
|
|
character.AnimationManager.ShotBow();
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void playerRespawn(){
|
|
Debug.Log("Respawning");
|
|
// healthBar.SetMaxHealth(statManager.GetEffectiveValue("health"));
|
|
ResetHealthAndArmor();
|
|
healthBar.value = health;
|
|
|
|
character.AnimationManager.SetState(CharacterState.Idle);
|
|
Transform newSpawnLocationPlayer = GameManager.instance.spawnPointsPlayer.GetChild(Random.Range(0,GameManager.instance.spawnPointsPlayer.childCount));
|
|
transform.position = newSpawnLocationPlayer.position;
|
|
}
|
|
|
|
void ResetHealthAndArmor(){
|
|
healthBar.maxValue = statManager.GetEffectiveValue("health");
|
|
health = statManager.GetEffectiveValue("health") + statManager.GetEffectiveValue("defence");
|
|
|
|
// Debug.Log($"Setting armor bar, maxVal:{health}, minVal:{healthBar.maxValue}, val:{health}");
|
|
armorBar.maxValue = health;
|
|
armorBar.minValue = healthBar.maxValue;
|
|
armorBar.value = health;
|
|
}
|
|
|
|
void ConfigArmorHealthSliders(){
|
|
healthBar.maxValue = statManager.GetEffectiveValue("health");
|
|
float maxHealth = statManager.GetEffectiveValue("health") + statManager.GetEffectiveValue("defence");
|
|
// Debug.Log($"Setting armor bar, maxVal:{health}, minVal:{healthBar.maxValue}, val:{health}");
|
|
armorBar.maxValue = maxHealth;
|
|
armorBar.minValue = healthBar.maxValue;
|
|
armorBar.value = health;
|
|
healthBar.value = health;
|
|
}
|
|
|
|
//Pickup
|
|
public void PickupObject(pickup item){
|
|
if(!isServer){ Debug.LogError("Cant call command on client, 403"); return; }
|
|
if(isLocalPlayer){
|
|
pickupObject(item.lootData.type);
|
|
}else{
|
|
RpcPickupObject(item.lootData.type);
|
|
|
|
}
|
|
}
|
|
|
|
[ClientRpc]
|
|
void RpcPickupObject(string type){
|
|
if(isLocalPlayer){
|
|
pickupObject(type);
|
|
}
|
|
}
|
|
|
|
void pickupObject(string type){
|
|
|
|
inventory.AddItem(type);
|
|
}
|
|
|
|
public void DropPickup(string type){
|
|
if(isServer){
|
|
GameManager.instance.SpawnPickup(type,transform.position + new Vector3(0.85f,0.6f));
|
|
}else{
|
|
CmdDropPickup(type);
|
|
}
|
|
}
|
|
|
|
[Command]
|
|
void CmdDropPickup(string type){
|
|
GameManager.instance.SpawnPickup(type,transform.position + new Vector3(4,0));
|
|
}
|
|
|
|
int magicalDmg = 0;
|
|
|
|
public void MagicalAttack(Vector3 direction, float magicalProjectileSpawnOffset, int dmg)
|
|
{
|
|
if (isServer)
|
|
{
|
|
magicalAttack(direction, magicalProjectileSpawnOffset, dmg);
|
|
}
|
|
else
|
|
{
|
|
CmdMagicalAttack(direction, magicalProjectileSpawnOffset, dmg);
|
|
}
|
|
}
|
|
|
|
[Command]
|
|
void CmdMagicalAttack(Vector3 direction, float magicalProjectileSpawnOffset, int dmg)
|
|
{
|
|
magicalAttack(direction, magicalProjectileSpawnOffset, dmg);
|
|
}
|
|
|
|
void magicalAttack(Vector3 direction, float magicalProjectileSpawnOffset, int dmg)
|
|
{
|
|
magicalDmg = dmg;
|
|
GameObject projectileSpawned = Instantiate(projectile, transform.position + (direction * magicalProjectileSpawnOffset), Quaternion.identity);
|
|
RangeProjectile _projectile = projectileSpawned.GetComponent<RangeProjectile>();
|
|
_projectile.direction = direction;
|
|
_projectile.OnHit.AddListener(OnMagicalHit);
|
|
_projectile.shooterId = netId;
|
|
|
|
NetworkServer.Spawn(projectileSpawned);
|
|
}
|
|
|
|
void OnMagicalHit(enemyScript victim)
|
|
{
|
|
//magical damage with intelligance stat ?
|
|
//int damageamount = magicalDmg + (lvl * 5);
|
|
int damageamount = magicalDmg + (statManager.GetEffectiveValue("intelligence")*2);
|
|
Debug.Log("magic damage amount " + damageamount);
|
|
victim.TakeMagicalDamage(damageamount, netId);
|
|
}
|
|
|
|
|
|
|
|
public void GoBackMenu(){
|
|
startClient.instance.networkManager.StopClient();
|
|
SceneManager.LoadScene("GameLogin");
|
|
|
|
#if UNITY_EDITOR || UNITY_SERVER || UNITY_STANDALONE_WIN
|
|
#else
|
|
PlayGamesPlatform.Instance.SignOut();
|
|
Firebase.Auth.FirebaseAuth.DefaultInstance.SignOut();
|
|
#endif
|
|
|
|
}
|
|
}
|