playerNetwork.cs 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Assets.HeroEditor4D.Common.Scripts.CharacterScripts;
  4. using Assets.HeroEditor4D.Common.Scripts.Enums;
  5. using Mirror;
  6. using TMPro;
  7. using Firebase.Firestore;
  8. using Firebase.Extensions;
  9. using Unity.VisualScripting;
  10. using UnityEngine;
  11. using UnityEngine.SceneManagement;
  12. using GooglePlayGames;
  13. using UnityEngine.SocialPlatforms;
  14. using Firebase.Auth;
  15. using UnityEngine.UI;
  16. using Newtonsoft.Json;
  17. public class playerNetwork : NetworkBehaviour
  18. {
  19. public static playerNetwork localPlayer;
  20. public invitePlayer invitePlayer;
  21. public const float ATTACK_COOLDOWN = 0.6f;
  22. [HideInInspector]
  23. public StatManager statManager;
  24. //public const int XPFORLEVEL = 10;
  25. [SyncVar(hook = nameof(OnHealthChanged))] public int health = 100;
  26. public Character4D character;
  27. public characterManager characterMan;
  28. [SyncVar(hook = nameof(OnDirectionChanged))]
  29. public Vector2 directionNetwork;
  30. [SyncVar(hook = nameof(OnAnimChanged))]
  31. public int animIntNetwork;
  32. [SyncVar(hook = nameof(onKillCountChange))]
  33. public int enemyKillCount;
  34. // public int xp { get{
  35. // int val = 0;
  36. // for(int i =5; i <= enemyKillCount; i+=5){
  37. // val = enemyKillCount;
  38. // }
  39. // return val;
  40. // }}
  41. [SyncVar(hook = nameof(OnXpChanged))]
  42. public int XP;
  43. [SyncVar]
  44. public string myPartyOwner;
  45. public int lvl2
  46. {
  47. get
  48. {
  49. return GetLevelForKills2(enemyKillCount);
  50. }
  51. }
  52. public int GetLevelForKills2(int kills)
  53. {
  54. int val = 0;
  55. for (int i = 10; i <= kills; i += 10)
  56. {
  57. val++;
  58. }
  59. return val;
  60. }
  61. public int lvl
  62. {
  63. get
  64. {
  65. return GetLevelByXp(XP);
  66. }
  67. }
  68. public int GetLevelByXp(int xp)
  69. {
  70. // int level = Mathf.CeilToInt(Mathf.Sqrt(xp/100f));
  71. // if(level <= 0){level = 1;}
  72. // return level;
  73. int level = Mathf.CeilToInt(Mathf.Log(xp / 100f, 2) + 1);
  74. if (level <= 0) { level = 1; }
  75. return level;
  76. // int level = 1;
  77. // int xpNeeded = 100;
  78. // while (xp >= xpNeeded)
  79. // {
  80. // level++;
  81. // xpNeeded = 100 * (int)Mathf.Pow(2, level - 1);
  82. // }
  83. // return level - 1;
  84. }
  85. public int GetXpForLevel(int level)
  86. {
  87. if (level <= 0)
  88. level = 1;
  89. return Mathf.FloorToInt(100 * Mathf.Pow(2, level - 1));
  90. }
  91. public float XpSliderVal
  92. {
  93. get
  94. {
  95. int nextLevelXp = GetXpForLevel(lvl);
  96. int prevLevelXp = GetXpForLevel(lvl - 1);
  97. if (nextLevelXp == prevLevelXp)
  98. {
  99. prevLevelXp = 0;
  100. }
  101. int range = nextLevelXp - prevLevelXp;
  102. // Debug.Log($"{XP-prevLevelXp} / {range}");
  103. //Debug.Log($"next : {nextLevelXp}, prev: {prevLevelXp}, xp:{XP}, xpSince:{XP-prevLevelXp}");
  104. return ((float)(XP - prevLevelXp) / (float)range);
  105. // int nextLevel = lvl+1;
  106. // int curLevelXp = lvl * lvl;
  107. // int nextLevelXp = nextLevel * nextLevel;
  108. // // Debug.Log($"Xp Calc: {XP}-{curLevelXp}/{nextLevelXp} - {curLevelXp}");
  109. // // Debug.Log($"{curLevelXp-XP}/{nextLevelXp - curLevelXp}");
  110. // if(XP == 0){return 0;}
  111. // return 1f - ((float)(curLevelXp - XP) / (float)(nextLevelXp- curLevelXp));
  112. }
  113. }
  114. [SyncVar]
  115. public string playerName;
  116. [SyncVar]
  117. public int playerCoin;
  118. [SyncVar]
  119. public string myCharJson;
  120. public TMP_Text txtEnemyKillCount;
  121. public TMP_Text txtPlayerName;
  122. public TMP_Text questText;
  123. public GameObject questUI;
  124. public TMP_Text coinText;
  125. public TMP_Text xpText;
  126. public TMP_Text lvlText;
  127. public Slider xpSlider;
  128. public GameObject[] xpSliderSlots;
  129. public TMP_Text xpEnableTxt;
  130. //public TMP_Text attackDmgEnableTxt;
  131. public GameObject canvas;
  132. public Slider healthBar;
  133. public Slider armorBar;
  134. public Inventory inventory;
  135. public static Transform localPlayerTransform;
  136. public GameObject healthVfx;
  137. public GameObject damageVfx;
  138. public GameObject levelUpVfx;
  139. public QuestScriptable currentQuest;
  140. public List<QuestAction> questActions;
  141. public List<string> completedQuests;
  142. public GameObject projectile;
  143. public GameObject arrowRange;
  144. public string selectedCharacterJson = CharacterSelection.selectedCharJson;
  145. public void SetActiveQuest(QuestScriptable questData)
  146. {
  147. currentQuest = questData;
  148. questText.text = questData.questTitle;
  149. questUI.SetActive(true);
  150. foreach (QuestAction quest in questActions)
  151. {
  152. if (quest.questData == questData)
  153. {
  154. quest.activate();
  155. }
  156. }
  157. }
  158. public void CompleteQuest(QuestScriptable questData)
  159. {
  160. if (questData != currentQuest)
  161. {
  162. Debug.LogError("Completed a quest that wasnt active");
  163. return;
  164. }
  165. completedQuests.Add(currentQuest.questName);
  166. currentQuest = null;
  167. questText.text = "Quest Completed!";
  168. playerCoin += questData.rewardAmount;
  169. coinText.text = playerCoin.ToString();
  170. //add delay
  171. StartCoroutine(DelayUI());
  172. }
  173. public void CancelledQuest()
  174. {
  175. questText.text = "Quest Cancelled: " + currentQuest.questTitle;
  176. //
  177. currentQuest = null;
  178. StartCoroutine(DelayUI());
  179. }
  180. IEnumerator DelayUI()
  181. {
  182. yield return new WaitForSecondsRealtime(10f);
  183. questUI.SetActive(false);
  184. }
  185. public static void registerQuestAction(QuestAction action)
  186. {
  187. localPlayerTransform.GetComponent<playerNetwork>().questActions.Add(action);
  188. }
  189. void Awake()
  190. {
  191. invitePlayer = GetComponent<invitePlayer>();
  192. rangeEnemyFind = GetComponent<rangeEnemyFinder>();
  193. }
  194. void Start()
  195. {
  196. #if UNITY_EDITOR
  197. if (isServer)
  198. {
  199. playerName = "Player" + Random.Range(0, 100);
  200. }
  201. #endif
  202. if (!isLocalPlayer)
  203. {
  204. canvas.SetActive(false);
  205. if (!isServer)
  206. {
  207. CmdRequestCharJson();
  208. }
  209. }
  210. else
  211. {
  212. localPlayerTransform = transform;
  213. localPlayer = this;
  214. cameraRPG.instance.SetTarget(transform);
  215. #if UNITY_EDITOR
  216. ResetHealthAndArmor();
  217. #else
  218. LoadPlayerData();
  219. #endif
  220. statManager.OnStatsChanged += ConfigArmorHealthSliders;
  221. if (isServer)
  222. {
  223. playerName = gplayAuth.userNameCloud;
  224. myCharJson = CharacterSelection.selectedCharJson;
  225. RpcBroadcastCharJson(CharacterSelection.selectedCharJson);
  226. }
  227. else
  228. {
  229. if (gplayAuth.userNameCloud.Length > 0)
  230. {
  231. CmdSetName(gplayAuth.userNameCloud);
  232. }
  233. else
  234. {
  235. CmdSetName("Player" + Random.Range(0, 100));
  236. }
  237. CmdSetCharJson(CharacterSelection.selectedCharJson);
  238. }
  239. }
  240. }
  241. [Command]
  242. public void CmdInvitePlayer(string otherPlayerName)
  243. {
  244. if (myPartyOwner == null || myPartyOwner.Length == 0)
  245. {
  246. FindPlayerByName(otherPlayerName).ShowInvite(playerName);
  247. }
  248. else
  249. {
  250. FindPlayerByName(otherPlayerName).ShowInvite(myPartyOwner);
  251. }
  252. }
  253. public void ShowInvite(string ownerName)
  254. {
  255. RpcInvitePlayer(ownerName);
  256. }
  257. [ClientRpc]
  258. void RpcInvitePlayer(string playerName)
  259. {
  260. if (!isLocalPlayer) { return; }
  261. invitePlayer.ShowInvite(playerName);
  262. }
  263. [Command]
  264. public void CmdAcceptInvite(string otherPlayerName)
  265. {
  266. myPartyOwner = otherPlayerName;
  267. Debug.Log("Invite accepted: " + myPartyOwner);
  268. }
  269. [Command]
  270. public void CmdLeaveParty()
  271. {
  272. myPartyOwner = null;
  273. }
  274. playerNetwork FindPlayerByName(string playerName)
  275. {
  276. playerNetwork[] players = FindObjectsOfType<playerNetwork>();
  277. foreach (playerNetwork player in players)
  278. {
  279. if (player.playerName == playerName)
  280. {
  281. return player;
  282. }
  283. }
  284. return null;
  285. }
  286. void LoadCharFromJson(string json)
  287. {
  288. if (json.Length <= 0) { return; }
  289. character.FromJson(json, true);
  290. }
  291. public void SavePlayerData()
  292. {
  293. #if UNITY_EDITOR
  294. return;
  295. #endif
  296. Debug.Log("*** Save Method Got Called ! ***");
  297. if (!isLoaded)
  298. {
  299. Debug.Log("*** Save Method Return ***");
  300. return;
  301. }
  302. FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
  303. //int playerCoin = int.Parse(coins.text);
  304. Dictionary<string, object> saveValues = new Dictionary<string, object>{
  305. {"playerInventory" , JsonConvert.SerializeObject(inventory.inventoryManager.GetEntries())},
  306. {"playerHealth" , health},
  307. {"playerCoin", playerCoin},
  308. {"killCount", enemyKillCount},
  309. {"xp", XP},
  310. {"completedQuest", completedQuests},
  311. {"playerStats", statManager.PlayerStats},
  312. {"characterJson", selectedCharacterJson},
  313. };
  314. DocumentReference docRef = db.Collection("PlayerData").Document(gplayAuth.userID);
  315. docRef.SetAsync(saveValues).ContinueWithOnMainThread(task =>
  316. {
  317. if (task.IsCompleted)
  318. {
  319. Debug.Log("**** Save Completed Firestore ****");
  320. }
  321. else
  322. {
  323. Debug.Log("**** Failed to save data to firestore ****");
  324. }
  325. });
  326. }
  327. public bool isLoaded = false;
  328. public void LoadPlayerData()
  329. {
  330. #if UNITY_EDITOR
  331. return;
  332. #endif
  333. Debug.Log("**** Data Load method got called ****");
  334. FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
  335. DocumentReference docRef = db.Collection("PlayerData").Document(gplayAuth.userID);
  336. docRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
  337. {
  338. DocumentSnapshot snapshot = task.Result;
  339. if (snapshot.Exists)
  340. {
  341. Debug.Log("**** Found previous Data to load ****");
  342. //load data
  343. // Dictionary<string,object> dic = snapshot.ToDictionary(ServerTimestampBehavior.Estimate);
  344. // Debug.Log("Reading data");
  345. // foreach(KeyValuePair<string,object> item in dic){
  346. // Debug.Log(item.Key + " : " +item.Value.ToString());
  347. // }
  348. //saveNameTxt.text = snapshot.GetValue<string>("playerName");
  349. //load kills
  350. int _enemyKillCount = snapshot.GetValue<int>("killCount");
  351. SetEnemyKillCount(_enemyKillCount);
  352. //load XP
  353. XP = snapshot.GetValue<int>("xp");
  354. //Load coin
  355. int _playerCoin = snapshot.GetValue<int>("playerCoin");
  356. SetPlayerCoins(_playerCoin);
  357. // coinText.text = snapshot.GetValue<int>("playerCoin").ToString();
  358. //Load Health
  359. int savedHealth = snapshot.GetValue<int>("playerHealth");
  360. SetHealth(savedHealth);
  361. ResetHealthAndArmor();
  362. healthBar.value = (savedHealth);
  363. armorBar.value = savedHealth;
  364. //load Inventory
  365. Dictionary<int, string> inventoryGetData = JsonConvert.DeserializeObject<Dictionary<int, string>>(snapshot.GetValue<string>("playerInventory"));
  366. inventory.inventoryManager.SetInventory(inventoryGetData);
  367. completedQuests = snapshot.GetValue<List<string>>("completedQuest");
  368. //stats
  369. statManager.loadFromCloudSave(snapshot.GetValue<Dictionary<string, int>>("playerStats"));
  370. isLoaded = true;
  371. }
  372. else
  373. {
  374. //show error previous data doesnt exists to load
  375. Debug.Log("**** No previous data to load ****");
  376. isLoaded = true;
  377. }
  378. });
  379. }
  380. [Command]
  381. void CmdSetName(string nameValue)
  382. {
  383. playerName = nameValue;
  384. }
  385. [Command(requiresAuthority = false)]
  386. void CmdRequestCharJson()
  387. {
  388. RpcBroadcastCharJson(myCharJson);
  389. }
  390. [Command]
  391. void CmdSetCharJson(string newValue)
  392. {
  393. myCharJson = newValue;
  394. RpcBroadcastCharJson(newValue);
  395. LoadCharFromJson(newValue);
  396. }
  397. [ClientRpc]
  398. void RpcBroadcastCharJson(string newValue)
  399. {
  400. LoadCharFromJson(newValue);
  401. }
  402. void OnDirectionChanged(Vector2 oldVal, Vector2 newVal)
  403. {
  404. character.SetDirection(newVal);
  405. }
  406. void OnAnimChanged(int oldVal, int newVal)
  407. {
  408. if (isLocalPlayer) { return; }
  409. character.AnimationManager.SetState((CharacterState)newVal);
  410. }
  411. rangeEnemyFinder rangeEnemyFind;
  412. enemyScript closestEnemy => rangeEnemyFind.targetEnemy;
  413. float attackTimer = 0;
  414. [HideInInspector]
  415. public PlayerAttack playerAttack;
  416. void Update()
  417. {
  418. if (isLocalPlayer)
  419. {
  420. if (attackTimer > 0) { attackTimer -= Time.deltaTime; }
  421. if (isServer)
  422. {
  423. SetAnimationData(character.Direction, character.Animator.GetInteger("State"));
  424. }
  425. else
  426. {
  427. CmdUpdateAnim(character.Direction, character.Animator.GetInteger("State"));
  428. }
  429. healthBar.value = (health);
  430. armorBar.value = health;
  431. txtEnemyKillCount.text = enemyKillCount.ToString();
  432. coinText.text = playerCoin.ToString();
  433. txtPlayerName.text = gplayAuth.userNameCloud;
  434. if (myPartyOwner != null && myPartyOwner.Length > 0)
  435. {
  436. invitePlayer.InParty(myPartyOwner);
  437. }
  438. else
  439. {
  440. invitePlayer.InParty("");
  441. }
  442. }
  443. ShowXP();
  444. ShowLevel();
  445. }
  446. [Command]
  447. void CmdUpdateAnim(Vector2 direction, int animState)
  448. {
  449. SetAnimationData(direction, animState);
  450. }
  451. void SetAnimationData(Vector2 direction, int animState)
  452. {
  453. directionNetwork = direction;
  454. animIntNetwork = animState;
  455. if (!isLocalPlayer)
  456. {
  457. character.AnimationManager.SetState((CharacterState)animState);
  458. character.SetDirection(direction);
  459. }
  460. }
  461. void OnHealthChanged(int oldVal, int newVal)
  462. {
  463. if (!isLocalPlayer) { return; }
  464. //
  465. if (oldVal < newVal)
  466. {
  467. GameObject newObject = Instantiate(healthVfx, character.characterTransform());
  468. newObject.transform.localPosition = Vector3.zero;
  469. newObject.transform.parent = transform;
  470. //StartCoroutine (Couroutine_autoDisableVFX(newObject));
  471. vfxScript vfxSc = newObject.AddComponent<vfxScript>();
  472. }
  473. else if (oldVal > newVal)
  474. {
  475. //damage VFX
  476. GameObject newObject = Instantiate(damageVfx, character.characterTransform());
  477. newObject.transform.localPosition = new Vector3(0, 5f, 0);
  478. newObject.transform.parent = transform;
  479. //StartCoroutine (Couroutine_autoDisableVFX(newObject));
  480. vfxScript vfxSc = newObject.AddComponent<vfxScript>();
  481. // vfxSc.offsetVFX = new Vector3(0, 5f, 0);
  482. // vfxSc.target = character.characterTransform();
  483. }
  484. SavePlayerData();
  485. healthBar.value = (newVal);
  486. armorBar.value = newVal;
  487. }
  488. // IEnumerator Couroutine_autoDisableVFX(GameObject go){
  489. // yield return new WaitForSecondsRealtime(5f);
  490. // Destroy(go);
  491. // }
  492. void onKillCountChange(int oldval, int newval)
  493. {
  494. if (!isLocalPlayer) { return; }
  495. // int prevLevel = GetLevelForKills(oldval);
  496. // int newLevel = GetLevelForKills(newval);
  497. SavePlayerData();
  498. // if(newLevel > prevLevel){
  499. // StartCoroutine(uiTxtDelay(25f));
  500. // }
  501. // if(enemyKillCount == 5 ){
  502. // //SavePlayerData();
  503. // //QuestComplete();
  504. // AddCoin();
  505. // }
  506. }
  507. void OnXpChanged(int oldVal, int newVal)
  508. {
  509. if (!isLocalPlayer) { return; }
  510. int prevLevel = GetLevelByXp(oldVal);
  511. int newLevle = GetLevelByXp(newVal);
  512. if (newLevle > prevLevel)
  513. {
  514. int levelChange = newLevle - prevLevel;
  515. GameObject newObject = Instantiate(levelUpVfx, character.characterTransform());
  516. newObject.transform.localPosition = Vector3.zero;
  517. newObject.transform.parent = transform;
  518. StartCoroutine(uiTxtDelay(25f, levelChange));
  519. }
  520. }
  521. public void SetHealth(int newvalue)
  522. {
  523. if (isServer)
  524. {
  525. health = newvalue;
  526. healthBar.value = (newvalue);
  527. armorBar.value = newvalue;
  528. }
  529. else
  530. {
  531. CmdSetHealth(newvalue);
  532. }
  533. }
  534. public void SetEnemyKillCount(int newValue)
  535. {
  536. if (isServer)
  537. {
  538. enemyKillCount = newValue;
  539. }
  540. else
  541. {
  542. CmdSetEnemyKillCount(newValue);
  543. }
  544. }
  545. public void SetPlayerCoins(int newVal)
  546. {
  547. if (isServer)
  548. {
  549. playerCoin = newVal;
  550. }
  551. else
  552. {
  553. CmdSetPlayerCoin(newVal);
  554. }
  555. }
  556. [Command]
  557. void CmdSetPlayerCoin(int newVal)
  558. {
  559. playerCoin = newVal;
  560. }
  561. [Command]
  562. void CmdSetEnemyKillCount(int newValue)
  563. {
  564. enemyKillCount = newValue;
  565. }
  566. [Command]
  567. void CmdSetHealth(int newValue)
  568. {
  569. health = newValue;
  570. }
  571. public void TakeDamage(int attackDamage)
  572. {
  573. serverTakeDmg(attackDamage);
  574. // if(isLocalPlayer){
  575. // takedmg(attackDamage);
  576. // }else if(isServer){
  577. // RpcTakeDamage(attackDamage);
  578. // }
  579. }
  580. void serverTakeDmg(int damage)
  581. {
  582. health -= damage;
  583. if (health <= 0)
  584. {
  585. RpcDeath();
  586. death();
  587. }
  588. }
  589. float xpTimer = 0;
  590. public void ShowXP()
  591. {
  592. if (xpTimer > 0) { xpTimer -= Time.deltaTime; return; }
  593. xpTimer = 1;
  594. int xpInt = Mathf.RoundToInt(XP / 100f) * 100;
  595. xpText.text = $"+ {xpInt} XP";
  596. xpSlider.value = XpSliderVal;
  597. for (int i = 0; i < 10; i++)
  598. {
  599. float val = (float)i / 10f;
  600. xpSliderSlots[i].SetActive(xpSlider.value > val);
  601. }
  602. }
  603. public void ShowLevel()
  604. {
  605. lvlText.text = lvl.ToString();
  606. }
  607. public void OnEnemyKilled(int enemyLevel)
  608. {
  609. //disable take damage and disable healthbar going backwards
  610. int prevValue = lvl;
  611. // SavePlayerData();
  612. enemyKillCount++;
  613. // Use new exponential XP system
  614. int xpGained = enemyScript.CalculateExponentialXP(enemyLevel, lvl);
  615. XP += xpGained;
  616. // Debug log for XP gain
  617. Debug.Log($"Killed Level {enemyLevel} enemy! Gained {xpGained} XP (Player Level: {lvl})");
  618. }
  619. IEnumerator uiTxtDelay(float delayTime, int levelChange)
  620. {
  621. //enable
  622. xpEnableTxt.gameObject.SetActive(true);
  623. //int attackDamageChange= 5 * levelChange;
  624. //attackDmgEnableTxt.gameObject.SetActive(true);
  625. //attackDmgEnableTxt.text = "Attack Damage + " + attackDamageChange;
  626. yield return new WaitForSecondsRealtime(delayTime);
  627. //disable
  628. xpEnableTxt.gameObject.SetActive(false);
  629. //attackDmgEnableTxt.gameObject.SetActive(false);
  630. }
  631. // public void QuestComplete(){
  632. // //task completion logic
  633. // // Strikethrough the text
  634. // //questText.text = "<s>Kill 5 Enemies to claim 100Golds</s> Completed";
  635. // Debug.Log("First quest completed");
  636. // }
  637. public void AddCoin()
  638. {
  639. playerCoin += 100;
  640. coinText.text = playerCoin.ToString();
  641. }
  642. [ClientRpc]
  643. public void RpcDeath()
  644. {
  645. death();
  646. }
  647. public bool isDead = false;
  648. public void death()
  649. {
  650. Debug.Log("Death called");
  651. character.AnimationManager.Die();
  652. isDead = true;
  653. StartCoroutine(CouroutineWaitDeath());
  654. // throw new System.Exception();
  655. }
  656. IEnumerator CouroutineWaitDeath()
  657. {
  658. yield return new WaitForSecondsRealtime(3);
  659. isDead = false;
  660. playerRespawn();
  661. }
  662. public void OnAttack()
  663. {
  664. if (attackTimer > 0)
  665. {
  666. return;
  667. }
  668. //characterMan.SetActiveWeapon(78);
  669. attackTimer = ATTACK_COOLDOWN;
  670. if (isLocalPlayer)
  671. {
  672. PlayAttackAnim();
  673. playerAttack.Attack(false);
  674. if (isServer)
  675. {
  676. RpcPlayAttackAnim();
  677. }
  678. else
  679. {
  680. CmdPlayAttackAnim();
  681. }
  682. }
  683. }
  684. [SerializeField] public float arrowSpeed = 2.0f;
  685. [SerializeField] public float arrowShootOffset = 1;
  686. [SerializeField] public float arrowShootHeightOffset = 1;
  687. public void OnRangeAttack()
  688. {
  689. if (attackTimer > 0)
  690. {
  691. return;
  692. }
  693. if (closestEnemy == null) { return; }
  694. attackTimer = ATTACK_COOLDOWN;
  695. characterMan.EquipBow();
  696. PlayAttackAnim();
  697. StartCoroutine(ArrowShootDelay());
  698. // arrowRange.transform.position = startingPosition;
  699. //TODO: Deal Damage once it hits enemy
  700. }
  701. public float arrowDelay;
  702. IEnumerator ArrowShootDelay()
  703. {
  704. yield return new WaitForSeconds(arrowDelay);
  705. Vector3 startingPosition = transform.position;
  706. Vector3 destination = closestEnemy.transform.position;
  707. //TODO: Move attack projectile from startingPosition to destination
  708. Vector3 direction = (destination - startingPosition).normalized;
  709. startingPosition += (direction * arrowShootOffset);
  710. startingPosition += (Vector3.up * arrowShootHeightOffset);
  711. destination += (Vector3.up * arrowShootHeightOffset);
  712. // Quaternion rotation = Quaternion.LookRotation(direction);
  713. float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
  714. Quaternion rotation = Quaternion.Euler(0, 0, angle - 90f);
  715. GameObject newArrow = Instantiate(arrowRange, transform.position + (direction * arrowShootOffset), rotation);
  716. StartCoroutine(moveArrow(newArrow.transform, startingPosition, destination, closestEnemy));
  717. }
  718. public int RangeDmg = 10;
  719. IEnumerator moveArrow(Transform arrow, Vector3 start, Vector3 destination, enemyScript target)
  720. {
  721. float dist = Vector3.Distance(start, destination);
  722. float duration = dist / arrowSpeed;
  723. float timer = 0f;
  724. while (timer < duration)
  725. {
  726. arrow.position = Vector3.Lerp(start, destination, timer / duration);
  727. timer += Time.deltaTime;
  728. yield return null;
  729. }
  730. target.TakeDamage(RangeDmg, netId);
  731. Destroy(arrow.gameObject);
  732. }
  733. public int MagicAttackWeaponIndex = 52;
  734. public void OnMagicAttack()
  735. {
  736. if (attackTimer > 0)
  737. {
  738. return;
  739. }
  740. attackTimer = ATTACK_COOLDOWN;
  741. //characterMan.SetActiveWeapon(MagicAttackWeaponIndex);
  742. if (isLocalPlayer)
  743. {
  744. PlayAttackAnim();
  745. //?
  746. playerAttack.MagicalAttack();
  747. playerAttack.Attack(true);
  748. if (isServer)
  749. {
  750. RpcPlayAttackAnim();
  751. }
  752. else
  753. {
  754. CmdPlayAttackAnim();
  755. }
  756. }
  757. }
  758. [Command]
  759. void CmdPlayAttackAnim()
  760. {
  761. PlayAttackAnim();
  762. RpcPlayAttackAnim();
  763. }
  764. [ClientRpc]
  765. void RpcPlayAttackAnim()
  766. {
  767. if (isLocalPlayer) { return; }
  768. PlayAttackAnim();
  769. }
  770. void PlayAttackAnim()
  771. {
  772. switch (character.WeaponType)
  773. {
  774. case WeaponType.Melee1H:
  775. case WeaponType.Paired:
  776. character.AnimationManager.Slash(twoHanded: false);
  777. break;
  778. case WeaponType.Melee2H:
  779. character.AnimationManager.Slash(twoHanded: true);
  780. break;
  781. case WeaponType.Bow:
  782. character.AnimationManager.ShotBow();
  783. break;
  784. }
  785. }
  786. public void playerRespawn()
  787. {
  788. Debug.Log("Respawning");
  789. // healthBar.SetMaxHealth(statManager.GetEffectiveValue("health"));
  790. ResetHealthAndArmor();
  791. healthBar.value = health;
  792. character.AnimationManager.SetState(CharacterState.Idle);
  793. Transform newSpawnLocationPlayer = GameManager.instance.spawnPointsPlayer.GetChild(Random.Range(0, GameManager.instance.spawnPointsPlayer.childCount));
  794. transform.position = newSpawnLocationPlayer.position;
  795. }
  796. void ResetHealthAndArmor()
  797. {
  798. healthBar.maxValue = statManager.GetEffectiveValue("health");
  799. health = statManager.GetEffectiveValue("health") + statManager.GetEffectiveValue("defence");
  800. // Debug.Log($"Setting armor bar, maxVal:{health}, minVal:{healthBar.maxValue}, val:{health}");
  801. armorBar.maxValue = health;
  802. armorBar.minValue = healthBar.maxValue;
  803. armorBar.value = health;
  804. }
  805. void ConfigArmorHealthSliders()
  806. {
  807. healthBar.maxValue = statManager.GetEffectiveValue("health");
  808. float maxHealth = statManager.GetEffectiveValue("health") + statManager.GetEffectiveValue("defence");
  809. // Debug.Log($"Setting armor bar, maxVal:{health}, minVal:{healthBar.maxValue}, val:{health}");
  810. armorBar.maxValue = maxHealth;
  811. armorBar.minValue = healthBar.maxValue;
  812. armorBar.value = health;
  813. healthBar.value = health;
  814. }
  815. //Pickup
  816. public void PickupObject(pickup item)
  817. {
  818. if (!isServer) { Debug.LogError("Cant call command on client, 403"); return; }
  819. if (isLocalPlayer)
  820. {
  821. pickupObject(item.lootData.type);
  822. }
  823. else
  824. {
  825. RpcPickupObject(item.lootData.type);
  826. }
  827. }
  828. [ClientRpc]
  829. void RpcPickupObject(string type)
  830. {
  831. if (isLocalPlayer)
  832. {
  833. pickupObject(type);
  834. }
  835. }
  836. void pickupObject(string type)
  837. {
  838. inventory.AddItem(type);
  839. }
  840. public void DropPickup(string type)
  841. {
  842. if (isServer)
  843. {
  844. GameManager.instance.SpawnPickup(type, transform.position + new Vector3(0.85f, 0.6f));
  845. }
  846. else
  847. {
  848. CmdDropPickup(type);
  849. }
  850. }
  851. [Command]
  852. void CmdDropPickup(string type)
  853. {
  854. GameManager.instance.SpawnPickup(type, transform.position + new Vector3(4, 0));
  855. }
  856. int magicalDmg = 0;
  857. public void MagicalAttack(Vector3 direction, float magicalProjectileSpawnOffset, int dmg)
  858. {
  859. if (isServer)
  860. {
  861. magicalAttack(direction, magicalProjectileSpawnOffset, dmg);
  862. }
  863. else
  864. {
  865. CmdMagicalAttack(direction, magicalProjectileSpawnOffset, dmg);
  866. }
  867. }
  868. [Command]
  869. void CmdMagicalAttack(Vector3 direction, float magicalProjectileSpawnOffset, int dmg)
  870. {
  871. magicalAttack(direction, magicalProjectileSpawnOffset, dmg);
  872. }
  873. void magicalAttack(Vector3 direction, float magicalProjectileSpawnOffset, int dmg)
  874. {
  875. magicalDmg = dmg;
  876. GameObject projectileSpawned = Instantiate(projectile, transform.position + (direction * magicalProjectileSpawnOffset), Quaternion.identity);
  877. RangeProjectile _projectile = projectileSpawned.GetComponent<RangeProjectile>();
  878. _projectile.direction = direction;
  879. _projectile.OnHit.AddListener(OnMagicalHit);
  880. _projectile.shooterId = netId;
  881. NetworkServer.Spawn(projectileSpawned);
  882. }
  883. void OnMagicalHit(enemyScript victim)
  884. {
  885. //magical damage with intelligance stat ?
  886. //int damageamount = magicalDmg + (lvl * 5);
  887. int damageamount = magicalDmg + (statManager.GetEffectiveValue("intelligence") * 4) + 15; // Increased intelligence multiplier and added base bonus
  888. Debug.Log("magic damage amount " + damageamount);
  889. victim.TakeMagicalDamage(damageamount, netId);
  890. }
  891. public void GoBackMenu()
  892. {
  893. startClient.instance.networkManager.StopClient();
  894. SceneManager.LoadScene("GameLogin");
  895. #if UNITY_EDITOR || UNITY_SERVER || UNITY_STANDALONE_WIN
  896. #else
  897. PlayGamesPlatform.Instance.SignOut();
  898. Firebase.Auth.FirebaseAuth.DefaultInstance.SignOut();
  899. #endif
  900. }
  901. }