|
@@ -15,6 +15,11 @@ public class enemyScript : NetworkBehaviour
|
|
public int health;
|
|
public int health;
|
|
[SyncVar(hook = nameof(OnMagicalHealthChange))]
|
|
[SyncVar(hook = nameof(OnMagicalHealthChange))]
|
|
public int magicalHealth;
|
|
public int magicalHealth;
|
|
|
|
+
|
|
|
|
+ // NEW: Shield break boolean
|
|
|
|
+ [SyncVar]
|
|
|
|
+ public bool shieldBreak = false;
|
|
|
|
+
|
|
public SpriteHealthBar healthBar;
|
|
public SpriteHealthBar healthBar;
|
|
public SpriteHealthBar MagicalhealthBar;
|
|
public SpriteHealthBar MagicalhealthBar;
|
|
public float speed;
|
|
public float speed;
|
|
@@ -40,63 +45,73 @@ public class enemyScript : NetworkBehaviour
|
|
|
|
|
|
MeshRenderer meshRenderer;
|
|
MeshRenderer meshRenderer;
|
|
public GameObject hitVfx;
|
|
public GameObject hitVfx;
|
|
- void Awake(){
|
|
|
|
|
|
+ void Awake()
|
|
|
|
+ {
|
|
meshRenderer = GetComponent<MeshRenderer>();
|
|
meshRenderer = GetComponent<MeshRenderer>();
|
|
scanCooldown = Random.Range(0.5f, 1.5f);
|
|
scanCooldown = Random.Range(0.5f, 1.5f);
|
|
}
|
|
}
|
|
- private void Start(){
|
|
|
|
- rb2 = GetComponent<Rigidbody2D>();
|
|
|
|
|
|
+ private void Start()
|
|
|
|
+ {
|
|
|
|
+ rb2 = GetComponent<Rigidbody2D>();
|
|
//target = GameObject.FindWithTag("Player").transform;
|
|
//target = GameObject.FindWithTag("Player").transform;
|
|
- UpdateAnimation(directionString,animationString);
|
|
|
|
- defaultPos = transform.position;
|
|
|
|
|
|
+ UpdateAnimation(directionString, animationString);
|
|
|
|
+ defaultPos = transform.position;
|
|
|
|
|
|
}
|
|
}
|
|
- [SyncVar(hook =nameof(OnLevelChanged))]
|
|
|
|
|
|
+ [SyncVar(hook = nameof(OnLevelChanged))]
|
|
public int level;
|
|
public int level;
|
|
- void OnLevelChanged(int oldVal, int newVal){
|
|
|
|
- if(isServer){return;}
|
|
|
|
|
|
+ void OnLevelChanged(int oldVal, int newVal)
|
|
|
|
+ {
|
|
|
|
+ if (isServer) { return; }
|
|
|
|
|
|
SetLevel(newVal);
|
|
SetLevel(newVal);
|
|
}
|
|
}
|
|
- public void SetLevel(int _level){
|
|
|
|
|
|
+ public void SetLevel(int _level)
|
|
|
|
+ {
|
|
|
|
|
|
- if(enemyLevel != null){
|
|
|
|
- enemyLevel.text = _level.ToString();
|
|
|
|
|
|
+ if (enemyLevel != null)
|
|
|
|
+ {
|
|
|
|
+ enemyLevel.text = _level.ToString();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
level = _level;
|
|
level = _level;
|
|
- int healthIncrement =level * HEALTH_INC;
|
|
|
|
|
|
+ int healthIncrement = level * HEALTH_INC;
|
|
maxHealth = 100 + healthIncrement;
|
|
maxHealth = 100 + healthIncrement;
|
|
|
|
|
|
health = (int)maxHealth;
|
|
health = (int)maxHealth;
|
|
magicalHealth = (int)maxHealth;
|
|
magicalHealth = (int)maxHealth;
|
|
enemyAttackDamage += (int)(level * DAMAGE_INC);
|
|
enemyAttackDamage += (int)(level * DAMAGE_INC);
|
|
|
|
|
|
|
|
+ // MODIFIED: Reset shield break when level is set
|
|
|
|
+ shieldBreak = false;
|
|
|
|
+
|
|
// Debug.Log($"{health}/{maxHealth}");
|
|
// Debug.Log($"{health}/{maxHealth}");
|
|
-
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
public Vector3 defScale;
|
|
public Vector3 defScale;
|
|
Vector3 defaultPos;
|
|
Vector3 defaultPos;
|
|
|
|
|
|
-
|
|
|
|
- float playerDistCheckTimer=0f;
|
|
|
|
- void LateUpdate(){
|
|
|
|
|
|
+ float playerDistCheckTimer = 0f;
|
|
|
|
+ void LateUpdate()
|
|
|
|
+ {
|
|
LOD();
|
|
LOD();
|
|
}
|
|
}
|
|
public const float disappearDistFromPlayer = 15f;
|
|
public const float disappearDistFromPlayer = 15f;
|
|
- void LOD(){
|
|
|
|
- if(playerDistCheckTimer > 0){playerDistCheckTimer -= Time.deltaTime;return;}
|
|
|
|
|
|
+ void LOD()
|
|
|
|
+ {
|
|
|
|
+ if (playerDistCheckTimer > 0) { playerDistCheckTimer -= Time.deltaTime; return; }
|
|
|
|
|
|
- playerDistCheckTimer = Random.Range(1.5f,2.5f);
|
|
|
|
- if(playerNetwork.localPlayerTransform == null){return;}
|
|
|
|
|
|
+ playerDistCheckTimer = Random.Range(1.5f, 2.5f);
|
|
|
|
+ if (playerNetwork.localPlayerTransform == null) { return; }
|
|
float distToPlayer = Vector3.Distance(playerNetwork.localPlayerTransform.position, transform.position);
|
|
float distToPlayer = Vector3.Distance(playerNetwork.localPlayerTransform.position, transform.position);
|
|
meshRenderer.enabled = distToPlayer < disappearDistFromPlayer;
|
|
meshRenderer.enabled = distToPlayer < disappearDistFromPlayer;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- #if UNITY_SERVER || UNITY_EDITOR
|
|
|
|
|
|
+#if UNITY_SERVER || UNITY_EDITOR
|
|
[Server]
|
|
[Server]
|
|
- private void Update(){
|
|
|
|
|
|
+ private void Update()
|
|
|
|
+ {
|
|
|
|
|
|
// animator.skeleton.SetSkin
|
|
// animator.skeleton.SetSkin
|
|
// set animation state to running if in chase Range
|
|
// set animation state to running if in chase Range
|
|
@@ -104,54 +119,67 @@ public class enemyScript : NetworkBehaviour
|
|
|
|
|
|
// isInChaseRange = Physics2D.OverlapCircle(transform.position, chaseRadius , layerMask);
|
|
// isInChaseRange = Physics2D.OverlapCircle(transform.position, chaseRadius , layerMask);
|
|
// isInAttackRange = Physics2D.OverlapCircle(transform.position, attackRadius, layerMask);
|
|
// isInAttackRange = Physics2D.OverlapCircle(transform.position, attackRadius, layerMask);
|
|
- if (health <= 0 ){
|
|
|
|
|
|
+
|
|
|
|
+ // MODIFIED: Check both health and magicalHealth for death condition
|
|
|
|
+ if (health <= 0 || (shieldBreak && magicalHealth <= 0))
|
|
|
|
+ {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- if(target != null){
|
|
|
|
|
|
+
|
|
|
|
+ if (target != null)
|
|
|
|
+ {
|
|
isInChaseRange = Vector3.Distance(transform.position, target.transform.position) < chaseRadius;
|
|
isInChaseRange = Vector3.Distance(transform.position, target.transform.position) < chaseRadius;
|
|
- isInAttackRange = Vector3.Distance(transform.position, target.transform.position) < attackRadius;
|
|
|
|
- }else{
|
|
|
|
|
|
+ isInAttackRange = Vector3.Distance(transform.position, target.transform.position) < attackRadius;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
isInChaseRange = false;
|
|
isInChaseRange = false;
|
|
isInAttackRange = false;
|
|
isInAttackRange = false;
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
ScanPlayers();
|
|
ScanPlayers();
|
|
- if(target !=null){
|
|
|
|
|
|
+ if (target != null)
|
|
|
|
+ {
|
|
enemyFollow();
|
|
enemyFollow();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- #endif
|
|
|
|
- float scanTimer =0;
|
|
|
|
|
|
+#endif
|
|
|
|
+ float scanTimer = 0;
|
|
float scanCooldown;
|
|
float scanCooldown;
|
|
- public void ScanPlayers(){
|
|
|
|
-
|
|
|
|
- if(scanTimer >0){scanTimer-=Time.deltaTime; return;}
|
|
|
|
|
|
+ public void ScanPlayers()
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ if (scanTimer > 0) { scanTimer -= Time.deltaTime; return; }
|
|
|
|
|
|
scanTimer = scanCooldown;
|
|
scanTimer = scanCooldown;
|
|
playerNetwork[] playersinNetwork = FindObjectsOfType<playerNetwork>();
|
|
playerNetwork[] playersinNetwork = FindObjectsOfType<playerNetwork>();
|
|
float closestDist = float.MaxValue;
|
|
float closestDist = float.MaxValue;
|
|
playerNetwork closestPlayer = null;
|
|
playerNetwork closestPlayer = null;
|
|
|
|
|
|
- foreach(playerNetwork player in playersinNetwork ){
|
|
|
|
- if(player.health <= 0 ){continue;}
|
|
|
|
|
|
+ foreach (playerNetwork player in playersinNetwork)
|
|
|
|
+ {
|
|
|
|
+ if (player.health <= 0) { continue; }
|
|
float dist = Vector3.Distance(transform.position, player.transform.position);
|
|
float dist = Vector3.Distance(transform.position, player.transform.position);
|
|
- if(dist < closestDist){
|
|
|
|
|
|
+ if (dist < closestDist)
|
|
|
|
+ {
|
|
closestPlayer = player;
|
|
closestPlayer = player;
|
|
closestDist = dist;
|
|
closestDist = dist;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- if(closestDist < chaseRadius){
|
|
|
|
- target = closestPlayer ;
|
|
|
|
|
|
+ if (closestDist < chaseRadius)
|
|
|
|
+ {
|
|
|
|
+ target = closestPlayer;
|
|
|
|
|
|
}
|
|
}
|
|
- else {
|
|
|
|
|
|
+ else
|
|
|
|
+ {
|
|
target = null;
|
|
target = null;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
//if(target == null) {return;}
|
|
//if(target == null) {return;}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -160,79 +188,99 @@ public class enemyScript : NetworkBehaviour
|
|
// void RpcUpdateAnim(string animDir , string animName, bool isLoop){
|
|
// void RpcUpdateAnim(string animDir , string animName, bool isLoop){
|
|
// UpdateAnimation(animDir , animName, isLoop);
|
|
// UpdateAnimation(animDir , animName, isLoop);
|
|
// }
|
|
// }
|
|
- [SyncVar(hook =nameof(OnFlipped))]
|
|
|
|
- bool isFlipped= false;
|
|
|
|
|
|
+ [SyncVar(hook = nameof(OnFlipped))]
|
|
|
|
+ bool isFlipped = false;
|
|
|
|
|
|
- void OnFlipped(bool oldVal, bool newVal){
|
|
|
|
- if(isServer){return;}
|
|
|
|
- transform.localScale = new Vector3(defScale.x * (newVal ? -1 : 1),defScale.y,defScale.z);
|
|
|
|
|
|
+ void OnFlipped(bool oldVal, bool newVal)
|
|
|
|
+ {
|
|
|
|
+ if (isServer) { return; }
|
|
|
|
+ transform.localScale = new Vector3(defScale.x * (newVal ? -1 : 1), defScale.y, defScale.z);
|
|
HandleFlip();
|
|
HandleFlip();
|
|
}
|
|
}
|
|
|
|
|
|
- void HandleFlip(){
|
|
|
|
- if(uiEnemy == null){
|
|
|
|
- return;
|
|
|
|
|
|
+ void HandleFlip()
|
|
|
|
+ {
|
|
|
|
+ if (uiEnemy == null)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- if(transform.localScale.x < 0 ){
|
|
|
|
- uiEnemy.localScale = new Vector3(-1,1,1);
|
|
|
|
|
|
+ if (transform.localScale.x < 0)
|
|
|
|
+ {
|
|
|
|
+ uiEnemy.localScale = new Vector3(-1, 1, 1);
|
|
}
|
|
}
|
|
- else{
|
|
|
|
- uiEnemy.localScale = new Vector3(1,1,1);
|
|
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ uiEnemy.localScale = new Vector3(1, 1, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private void enemyFollow(){
|
|
|
|
-
|
|
|
|
- if(Mathf.Abs(dir.y) > Mathf.Abs(dir.x)){
|
|
|
|
- if(dir.y < 0){
|
|
|
|
|
|
+ private void enemyFollow()
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ if (Mathf.Abs(dir.y) > Mathf.Abs(dir.x))
|
|
|
|
+ {
|
|
|
|
+ if (dir.y < 0)
|
|
|
|
+ {
|
|
directionString = "Back";
|
|
directionString = "Back";
|
|
- }else{
|
|
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
directionString = "Front";
|
|
directionString = "Front";
|
|
}
|
|
}
|
|
- }else{
|
|
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
directionString = "Side";
|
|
directionString = "Side";
|
|
|
|
|
|
- if(dir.x < 0){
|
|
|
|
- transform.localScale = new Vector3(defScale.x,defScale.y,0);
|
|
|
|
- isFlipped=false;
|
|
|
|
- }else{
|
|
|
|
- transform.localScale = new Vector3(-defScale.x,defScale.y,0);
|
|
|
|
|
|
+ if (dir.x < 0)
|
|
|
|
+ {
|
|
|
|
+ transform.localScale = new Vector3(defScale.x, defScale.y, 0);
|
|
|
|
+ isFlipped = false;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ transform.localScale = new Vector3(-defScale.x, defScale.y, 0);
|
|
isFlipped = true;
|
|
isFlipped = true;
|
|
}
|
|
}
|
|
HandleFlip();
|
|
HandleFlip();
|
|
}
|
|
}
|
|
- if(animationHistory != directionString + animationString){
|
|
|
|
|
|
+ if (animationHistory != directionString + animationString)
|
|
|
|
+ {
|
|
UpdateAnimation(directionString, animationString);
|
|
UpdateAnimation(directionString, animationString);
|
|
// RpcUpdateAnim(directionString, animationString,true);
|
|
// RpcUpdateAnim(directionString, animationString,true);
|
|
}
|
|
}
|
|
- animationHistory=directionString + animationString;
|
|
|
|
|
|
+ animationHistory = directionString + animationString;
|
|
|
|
|
|
- if(target != null){
|
|
|
|
|
|
+ if (target != null)
|
|
|
|
+ {
|
|
dir = transform.position - target.transform.position;
|
|
dir = transform.position - target.transform.position;
|
|
}
|
|
}
|
|
-
|
|
|
|
- float angle = Mathf.Atan2(dir.y , dir.x ) * Mathf.Rad2Deg;
|
|
|
|
|
|
+
|
|
|
|
+ float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
|
|
dir.Normalize();
|
|
dir.Normalize();
|
|
|
|
|
|
movement = dir;
|
|
movement = dir;
|
|
|
|
|
|
- if(rotate){
|
|
|
|
|
|
+ if (rotate)
|
|
|
|
+ {
|
|
//set anim direction x, y dir
|
|
//set anim direction x, y dir
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
- string animationHistory ="";
|
|
|
|
- [SyncVar(hook =nameof(OnAnimationDirectionChanged))]
|
|
|
|
|
|
+ string animationHistory = "";
|
|
|
|
+ [SyncVar(hook = nameof(OnAnimationDirectionChanged))]
|
|
public string directionString = "Side";
|
|
public string directionString = "Side";
|
|
- [SyncVar(hook =nameof(OnAnimationNameChanged))]
|
|
|
|
|
|
+ [SyncVar(hook = nameof(OnAnimationNameChanged))]
|
|
public string animationString = "Idle";
|
|
public string animationString = "Idle";
|
|
|
|
|
|
- void OnAnimationDirectionChanged(string oldVal, string newVal){
|
|
|
|
|
|
+ void OnAnimationDirectionChanged(string oldVal, string newVal)
|
|
|
|
+ {
|
|
UpdateAnimation(newVal, animationString);
|
|
UpdateAnimation(newVal, animationString);
|
|
}
|
|
}
|
|
|
|
|
|
- void OnAnimationNameChanged(string oldVal, string newVal){
|
|
|
|
|
|
+ void OnAnimationNameChanged(string oldVal, string newVal)
|
|
|
|
+ {
|
|
UpdateAnimation(directionString, newVal);
|
|
UpdateAnimation(directionString, newVal);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -241,67 +289,85 @@ public class enemyScript : NetworkBehaviour
|
|
|
|
|
|
[SyncVar]
|
|
[SyncVar]
|
|
public float maxHealth;
|
|
public float maxHealth;
|
|
-
|
|
|
|
- #if UNITY_SERVER || UNITY_EDITOR
|
|
|
|
|
|
+
|
|
|
|
+#if UNITY_SERVER || UNITY_EDITOR
|
|
[Server]
|
|
[Server]
|
|
- private void FixedUpdate() {
|
|
|
|
- if (health <= 0 || magicalHealth <= 0){
|
|
|
|
|
|
+ private void FixedUpdate()
|
|
|
|
+ {
|
|
|
|
+ // MODIFIED: Updated death condition
|
|
|
|
+ if (health <= 0 || (shieldBreak && magicalHealth <= 0))
|
|
|
|
+ {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
healthBar.SetHealth(health, maxHealth);
|
|
healthBar.SetHealth(health, maxHealth);
|
|
- MagicalhealthBar.SetHealth(magicalHealth, maxHealth); //magical health maxout err
|
|
|
|
- if(isInChaseRange && !isInAttackRange ){
|
|
|
|
|
|
+ MagicalhealthBar.SetHealth(magicalHealth, maxHealth);
|
|
|
|
+
|
|
|
|
+ if (isInChaseRange && !isInAttackRange)
|
|
|
|
+ {
|
|
MoveEnemy(movement);
|
|
MoveEnemy(movement);
|
|
//Set animation to moving
|
|
//Set animation to moving
|
|
animationString = "Walk";
|
|
animationString = "Walk";
|
|
}
|
|
}
|
|
- if(isInAttackRange){
|
|
|
|
|
|
+ if (isInAttackRange)
|
|
|
|
+ {
|
|
rb2.velocity = Vector2.zero;
|
|
rb2.velocity = Vector2.zero;
|
|
//Set animation to attack
|
|
//Set animation to attack
|
|
animationString = "Attack";
|
|
animationString = "Attack";
|
|
|
|
|
|
- if(attackTimer < attackDuration){
|
|
|
|
|
|
+ if (attackTimer < attackDuration)
|
|
|
|
+ {
|
|
attackTimer += Time.deltaTime;
|
|
attackTimer += Time.deltaTime;
|
|
|
|
|
|
- }else{
|
|
|
|
- attackTimer = 0 ;
|
|
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ attackTimer = 0;
|
|
Attack();
|
|
Attack();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
//TODO: ATTACK HERE
|
|
//TODO: ATTACK HERE
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- if(!isInAttackRange && !isInChaseRange){
|
|
|
|
|
|
+ if (!isInAttackRange && !isInChaseRange)
|
|
|
|
+ {
|
|
//SetAnimation to idle
|
|
//SetAnimation to idle
|
|
animationString = "Idle";
|
|
animationString = "Idle";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- #endif
|
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
- public void Attack(){
|
|
|
|
|
|
+ public void Attack()
|
|
|
|
+ {
|
|
target.TakeDamage(enemyAttackDamage);
|
|
target.TakeDamage(enemyAttackDamage);
|
|
}
|
|
}
|
|
- private void MoveEnemy(Vector2 dir){
|
|
|
|
|
|
+ private void MoveEnemy(Vector2 dir)
|
|
|
|
+ {
|
|
rb2.MovePosition((Vector2)transform.position + (dir * speed * Time.deltaTime));
|
|
rb2.MovePosition((Vector2)transform.position + (dir * speed * Time.deltaTime));
|
|
}
|
|
}
|
|
- void UpdateAnimation(string direction, string animationName){
|
|
|
|
|
|
+ void UpdateAnimation(string direction, string animationName)
|
|
|
|
+ {
|
|
// try{
|
|
// try{
|
|
StartCoroutine(CoroutineUpdateAnim(direction, animationName));
|
|
StartCoroutine(CoroutineUpdateAnim(direction, animationName));
|
|
}
|
|
}
|
|
|
|
|
|
- IEnumerator CoroutineUpdateAnim(string direction, string animationName){
|
|
|
|
- while(animator == null){
|
|
|
|
|
|
+ IEnumerator CoroutineUpdateAnim(string direction, string animationName)
|
|
|
|
+ {
|
|
|
|
+ while (animator == null)
|
|
|
|
+ {
|
|
yield return new WaitForSeconds(0.1f);
|
|
yield return new WaitForSeconds(0.1f);
|
|
Debug.LogError("animator is null!");
|
|
Debug.LogError("animator is null!");
|
|
}
|
|
}
|
|
- while(animator.skeleton == null){
|
|
|
|
|
|
+ while (animator.skeleton == null)
|
|
|
|
+ {
|
|
yield return new WaitForSeconds(0.1f);
|
|
yield return new WaitForSeconds(0.1f);
|
|
Debug.LogError("animator skelton is null!");
|
|
Debug.LogError("animator skelton is null!");
|
|
|
|
|
|
}
|
|
}
|
|
- while(animator.AnimationState == null){
|
|
|
|
|
|
+ while (animator.AnimationState == null)
|
|
|
|
+ {
|
|
yield return new WaitForSeconds(0.1f);
|
|
yield return new WaitForSeconds(0.1f);
|
|
Debug.LogError("animator state is null!");
|
|
Debug.LogError("animator state is null!");
|
|
|
|
|
|
@@ -316,90 +382,150 @@ public class enemyScript : NetworkBehaviour
|
|
Debug.Log($"Updating enemy animation {direction}_{animationName}");
|
|
Debug.Log($"Updating enemy animation {direction}_{animationName}");
|
|
}
|
|
}
|
|
|
|
|
|
- [Command(requiresAuthority =false)]
|
|
|
|
- void CmdTakeDamage(int damage,uint id){
|
|
|
|
- takedmg(damage,id);
|
|
|
|
|
|
+ [Command(requiresAuthority = false)]
|
|
|
|
+ void CmdTakeDamage(int damage, uint id)
|
|
|
|
+ {
|
|
|
|
+ takedmg(damage, id);
|
|
Debug.Log("Enemy Attack Recieved ");
|
|
Debug.Log("Enemy Attack Recieved ");
|
|
}
|
|
}
|
|
- public void TakeDamage(int damage, uint id){
|
|
|
|
- if(isServer){
|
|
|
|
- takedmg(damage,id);
|
|
|
|
|
|
+
|
|
|
|
+ public void TakeDamage(int damage, uint id)
|
|
|
|
+ {
|
|
|
|
+ if (isServer)
|
|
|
|
+ {
|
|
|
|
+ takedmg(damage, id);
|
|
}
|
|
}
|
|
- else{
|
|
|
|
- CmdTakeDamage(damage,id);
|
|
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ CmdTakeDamage(damage, id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- void takedmg(int damage,uint id){
|
|
|
|
- if(health<=0){return;}
|
|
|
|
- health -= damage;
|
|
|
|
- //hit vfx
|
|
|
|
- // GameObject newObject = Instantiate(hitVfx , transform.position , Quaternion.identity );
|
|
|
|
- // newObject.transform.localPosition = Vector3.zero;
|
|
|
|
- // newObject.transform.parent = transform;
|
|
|
|
- if(health<= 0 ){
|
|
|
|
- StartCoroutine(couroutineDeath());
|
|
|
|
|
|
+ // MODIFIED: Completely rewritten damage system
|
|
|
|
+ void takedmg(int damage, uint id)
|
|
|
|
+ {
|
|
|
|
+ if (health <= 0) { return; }
|
|
|
|
+
|
|
|
|
+ int finalDamage = damage;
|
|
|
|
+
|
|
|
|
+ // If shield is not broken, reduce damage by half and damage magical health
|
|
|
|
+ if (!shieldBreak && magicalHealth > 0)
|
|
|
|
+ {
|
|
|
|
+ finalDamage = damage / 2;
|
|
|
|
+
|
|
|
|
+ // Calculate magical health damage based on player attack damage + enemy level
|
|
|
|
+ int magicalDamage = damage + level;
|
|
|
|
+ magicalHealth -= magicalDamage;
|
|
|
|
+
|
|
|
|
+ // Check if shield breaks
|
|
|
|
+ if (magicalHealth <= 0)
|
|
|
|
+ {
|
|
|
|
+ shieldBreak = true;
|
|
|
|
+ magicalHealth = 0;
|
|
|
|
+ Debug.Log("Shield Broken!");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- foreach(playerNetwork player in FindObjectsOfType<playerNetwork>()){
|
|
|
|
- if(player.netId == id){
|
|
|
|
|
|
+ // Apply damage to health
|
|
|
|
+ health -= finalDamage;
|
|
|
|
|
|
- //This one attacked me
|
|
|
|
|
|
+ // Check for death
|
|
|
|
+ if (health <= 0)
|
|
|
|
+ {
|
|
|
|
+ StartCoroutine(couroutineDeath());
|
|
|
|
+
|
|
|
|
+ foreach (playerNetwork player in FindObjectsOfType<playerNetwork>())
|
|
|
|
+ {
|
|
|
|
+ if (player.netId == id)
|
|
|
|
+ {
|
|
player.OnEnemyKilled(level);
|
|
player.OnEnemyKilled(level);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- Debug.Log("Enemy Takes Damage ***");
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ Debug.Log($"Enemy Takes Damage: {finalDamage} | Shield Broken: {shieldBreak} | Health: {health} | Magical Health: {magicalHealth}");
|
|
}
|
|
}
|
|
|
|
|
|
- [Command(requiresAuthority =false)]
|
|
|
|
- void CmdTakeMagicalDamage(int damage,uint id){
|
|
|
|
- takeMagicalDmg(damage,id);
|
|
|
|
- Debug.Log("Enemy Attack Recieved ");
|
|
|
|
|
|
+ [Command(requiresAuthority = false)]
|
|
|
|
+ void CmdTakeMagicalDamage(int damage, uint id)
|
|
|
|
+ {
|
|
|
|
+ takeMagicalDmg(damage, id);
|
|
|
|
+ Debug.Log("Enemy Magical Attack Recieved ");
|
|
}
|
|
}
|
|
- public void TakeMagicalDamage(int damage, uint id){
|
|
|
|
- if(isServer){
|
|
|
|
- takeMagicalDmg(damage,id);
|
|
|
|
|
|
+
|
|
|
|
+ public void TakeMagicalDamage(int damage, uint id)
|
|
|
|
+ {
|
|
|
|
+ if (isServer)
|
|
|
|
+ {
|
|
|
|
+ takeMagicalDmg(damage, id);
|
|
}
|
|
}
|
|
- else{
|
|
|
|
- CmdTakeMagicalDamage(damage,id);
|
|
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ CmdTakeMagicalDamage(damage, id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- void takeMagicalDmg(int damage,uint id){
|
|
|
|
- if(magicalHealth<=0){return;}
|
|
|
|
- magicalHealth -= damage;
|
|
|
|
- if(magicalHealth<= 0 ){
|
|
|
|
- StartCoroutine(couroutineDeath());
|
|
|
|
|
|
+ // MODIFIED: Updated magical damage to use same system
|
|
|
|
+ void takeMagicalDmg(int damage, uint id)
|
|
|
|
+ {
|
|
|
|
+ if (magicalHealth <= 0 && shieldBreak) { return; }
|
|
|
|
|
|
- foreach(playerNetwork player in FindObjectsOfType<playerNetwork>()){
|
|
|
|
- if(player.netId == id){
|
|
|
|
|
|
+ int finalDamage = damage;
|
|
|
|
+
|
|
|
|
+ // If shield is not broken, reduce damage by half and damage magical health
|
|
|
|
+ if (!shieldBreak && magicalHealth > 0)
|
|
|
|
+ {
|
|
|
|
+ finalDamage = damage / 2;
|
|
|
|
+
|
|
|
|
+ // Calculate magical health damage based on player attack damage + enemy level
|
|
|
|
+ int magicalDamage = damage + level;
|
|
|
|
+ magicalHealth -= magicalDamage;
|
|
|
|
+
|
|
|
|
+ // Check if shield breaks
|
|
|
|
+ if (magicalHealth <= 0)
|
|
|
|
+ {
|
|
|
|
+ shieldBreak = true;
|
|
|
|
+ magicalHealth = 0;
|
|
|
|
+ Debug.Log("Shield Broken!");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- //This one attacked me
|
|
|
|
|
|
+ // Apply damage to health
|
|
|
|
+ health -= finalDamage;
|
|
|
|
+
|
|
|
|
+ // Check for death
|
|
|
|
+ if (health <= 0)
|
|
|
|
+ {
|
|
|
|
+ StartCoroutine(couroutineDeath());
|
|
|
|
+
|
|
|
|
+ foreach (playerNetwork player in FindObjectsOfType<playerNetwork>())
|
|
|
|
+ {
|
|
|
|
+ if (player.netId == id)
|
|
|
|
+ {
|
|
player.OnEnemyKilled(level);
|
|
player.OnEnemyKilled(level);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- Debug.Log("Enemy Takes Damage ***");
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ Debug.Log($"Enemy Takes Magical Damage: {finalDamage} | Shield Broken: {shieldBreak} | Health: {health} | Magical Health: {magicalHealth}");
|
|
}
|
|
}
|
|
|
|
|
|
- IEnumerator couroutineDeath(){
|
|
|
|
-
|
|
|
|
|
|
+ IEnumerator couroutineDeath()
|
|
|
|
+ {
|
|
|
|
+
|
|
animationString = "Death";
|
|
animationString = "Death";
|
|
StartCoroutine(PopDisappearUI());
|
|
StartCoroutine(PopDisappearUI());
|
|
- UpdateAnimation(directionString , animationString);
|
|
|
|
|
|
+ UpdateAnimation(directionString, animationString);
|
|
// RpcUpdateAnim(directionString, animationString,false);
|
|
// RpcUpdateAnim(directionString, animationString,false);
|
|
Vector3 lootSpawnPos = transform.position;
|
|
Vector3 lootSpawnPos = transform.position;
|
|
lootSpawnPos.z = GameManager.instance.LootSpawnPointsParent.GetChild(0).position.z;
|
|
lootSpawnPos.z = GameManager.instance.LootSpawnPointsParent.GetChild(0).position.z;
|
|
//instantiate loot item
|
|
//instantiate loot item
|
|
GameObject newLoot = Instantiate(GameManager.instance.GetRandomLoot(), lootSpawnPos, Quaternion.identity);
|
|
GameObject newLoot = Instantiate(GameManager.instance.GetRandomLoot(), lootSpawnPos, Quaternion.identity);
|
|
-
|
|
|
|
|
|
+
|
|
NetworkServer.Spawn(newLoot);
|
|
NetworkServer.Spawn(newLoot);
|
|
|
|
|
|
yield return new WaitForSecondsRealtime(7);// dead corpse delay
|
|
yield return new WaitForSecondsRealtime(7);// dead corpse delay
|
|
|
|
|
|
-
|
|
|
|
if (!isServer)
|
|
if (!isServer)
|
|
{
|
|
{
|
|
CmdDie();
|
|
CmdDie();
|
|
@@ -408,66 +534,57 @@ public class enemyScript : NetworkBehaviour
|
|
{
|
|
{
|
|
GameManager.OnEnemyDeath(this, defaultPos);
|
|
GameManager.OnEnemyDeath(this, defaultPos);
|
|
}
|
|
}
|
|
-
|
|
|
|
- /* transform.position = defaultPos;
|
|
|
|
- health = (int)maxHealth;
|
|
|
|
- magicalHealth = (int)maxHealth;*/
|
|
|
|
-
|
|
|
|
- //animationString = "Idle";
|
|
|
|
-
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
[Command]
|
|
[Command]
|
|
void CmdDie()
|
|
void CmdDie()
|
|
{
|
|
{
|
|
- GameManager.OnEnemyDeath(this,defaultPos);
|
|
|
|
|
|
+ GameManager.OnEnemyDeath(this, defaultPos);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- public void OnHealthChange(int oldVlaue, int newValue){
|
|
|
|
- healthBar.SetHealth(newValue,maxHealth);
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- public void OnMagicalHealthChange(int oldVlaue, int newValue){
|
|
|
|
- MagicalhealthBar.SetHealth(newValue,maxHealth);
|
|
|
|
|
|
+ public void OnHealthChange(int oldVlaue, int newValue)
|
|
|
|
+ {
|
|
|
|
+ healthBar.SetHealth(newValue, maxHealth);
|
|
}
|
|
}
|
|
|
|
|
|
- //etc for ui Disspear coroutine
|
|
|
|
- IEnumerator PopDisappearUI(){
|
|
|
|
- Vector3 originalScale = uiEnemy.localScale;
|
|
|
|
-
|
|
|
|
- // First, scale up slightly
|
|
|
|
- float popDuration = 0.15f;
|
|
|
|
- float elapsedTime = 0f;
|
|
|
|
- Vector3 popScale = originalScale * 1.2f;
|
|
|
|
-
|
|
|
|
- while(elapsedTime < popDuration)
|
|
|
|
|
|
+ public void OnMagicalHealthChange(int oldVlaue, int newValue)
|
|
{
|
|
{
|
|
- float t = elapsedTime / popDuration;
|
|
|
|
- uiEnemy.localScale = Vector3.Lerp(originalScale, popScale, t);
|
|
|
|
- elapsedTime += Time.deltaTime;
|
|
|
|
- yield return null;
|
|
|
|
|
|
+ MagicalhealthBar.SetHealth(newValue, maxHealth);
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Then scale down to zero quickly
|
|
|
|
- float shrinkDuration = 0.3f;
|
|
|
|
- elapsedTime = 0f;
|
|
|
|
-
|
|
|
|
- while(elapsedTime < shrinkDuration)
|
|
|
|
|
|
+
|
|
|
|
+ //etc for ui Disspear coroutine
|
|
|
|
+ IEnumerator PopDisappearUI()
|
|
{
|
|
{
|
|
- float t = elapsedTime / shrinkDuration;
|
|
|
|
- // Use ease-in curve for faster shrinking
|
|
|
|
- float easedT = t * t;
|
|
|
|
- uiEnemy.localScale = Vector3.Lerp(popScale, Vector3.zero, easedT);
|
|
|
|
- elapsedTime += Time.deltaTime;
|
|
|
|
- yield return null;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- uiEnemy.localScale = Vector3.zero;
|
|
|
|
- uiEnemy.gameObject.SetActive(false);
|
|
|
|
-}
|
|
|
|
|
|
+ Vector3 originalScale = uiEnemy.localScale;
|
|
|
|
+
|
|
|
|
+ // First, scale up slightly
|
|
|
|
+ float popDuration = 0.15f;
|
|
|
|
+ float elapsedTime = 0f;
|
|
|
|
+ Vector3 popScale = originalScale * 1.2f;
|
|
|
|
|
|
|
|
+ while (elapsedTime < popDuration)
|
|
|
|
+ {
|
|
|
|
+ float t = elapsedTime / popDuration;
|
|
|
|
+ uiEnemy.localScale = Vector3.Lerp(originalScale, popScale, t);
|
|
|
|
+ elapsedTime += Time.deltaTime;
|
|
|
|
+ yield return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Then scale down to zero quickly
|
|
|
|
+ float shrinkDuration = 0.3f;
|
|
|
|
+ elapsedTime = 0f;
|
|
|
|
+
|
|
|
|
+ while (elapsedTime < shrinkDuration)
|
|
|
|
+ {
|
|
|
|
+ float t = elapsedTime / shrinkDuration;
|
|
|
|
+ // Use ease-in curve for faster shrinking
|
|
|
|
+ float easedT = t * t;
|
|
|
|
+ uiEnemy.localScale = Vector3.Lerp(popScale, Vector3.zero, easedT);
|
|
|
|
+ elapsedTime += Time.deltaTime;
|
|
|
|
+ yield return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ uiEnemy.localScale = Vector3.zero;
|
|
|
|
+ uiEnemy.gameObject.SetActive(false);
|
|
|
|
+ }
|
|
}
|
|
}
|