126 lines
3.7 KiB
C#
126 lines
3.7 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using OTGIntegrated.Core;
|
||
|
|
using OTGIntegrated.Items;
|
||
|
|
using OTGIntegrated.Stats;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
namespace OTGIntegrated.Combat
|
||
|
|
{
|
||
|
|
[Serializable]
|
||
|
|
public sealed class EnemyDrop
|
||
|
|
{
|
||
|
|
public ItemData item;
|
||
|
|
[Min(1)] public int amount = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed class Enemy : Damageable
|
||
|
|
{
|
||
|
|
public string enemyId = "Goblin";
|
||
|
|
public float damage = 5f;
|
||
|
|
public int expReward = 20;
|
||
|
|
public List<EnemyDrop> dropItems = new List<EnemyDrop>();
|
||
|
|
public float aggroRange = 8f;
|
||
|
|
public float attackRange = 1.8f;
|
||
|
|
public float attackCooldown = 1.4f;
|
||
|
|
public float moveSpeed = 2.2f;
|
||
|
|
|
||
|
|
private Transform player;
|
||
|
|
private PlayerStats playerStats;
|
||
|
|
private float nextAttackTime;
|
||
|
|
private bool dead;
|
||
|
|
|
||
|
|
protected override void Awake()
|
||
|
|
{
|
||
|
|
base.Awake();
|
||
|
|
currentHealth = maxHealth;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Start()
|
||
|
|
{
|
||
|
|
if (GameManager.Instance != null && GameManager.Instance.playerStats != null)
|
||
|
|
{
|
||
|
|
playerStats = GameManager.Instance.playerStats;
|
||
|
|
player = playerStats.transform;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
PlayerStats stats = FindObjectOfType<PlayerStats>();
|
||
|
|
if (stats != null)
|
||
|
|
{
|
||
|
|
playerStats = stats;
|
||
|
|
player = stats.transform;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Update()
|
||
|
|
{
|
||
|
|
if (!IsAlive || player == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Vector3 toPlayer = player.position - transform.position;
|
||
|
|
toPlayer.y = 0f;
|
||
|
|
float distance = toPlayer.magnitude;
|
||
|
|
|
||
|
|
if (distance <= aggroRange && distance > attackRange)
|
||
|
|
{
|
||
|
|
Vector3 direction = toPlayer.normalized;
|
||
|
|
transform.position += direction * moveSpeed * Time.deltaTime;
|
||
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 8f * Time.deltaTime);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (distance <= attackRange && Time.time >= nextAttackTime)
|
||
|
|
{
|
||
|
|
nextAttackTime = Time.time + attackCooldown;
|
||
|
|
if (playerStats != null)
|
||
|
|
{
|
||
|
|
playerStats.TakeDamage(damage);
|
||
|
|
GameEvents.RaiseNotification($"{displayName} наносит {Mathf.RoundToInt(damage)} урона");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void HandleDeath(GameObject source)
|
||
|
|
{
|
||
|
|
if (dead)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
dead = true;
|
||
|
|
DropRewards();
|
||
|
|
|
||
|
|
if (GameManager.Instance != null && GameManager.Instance.levelSystem != null && expReward > 0)
|
||
|
|
{
|
||
|
|
GameManager.Instance.levelSystem.AddExperience(expReward);
|
||
|
|
}
|
||
|
|
|
||
|
|
GameEvents.RaiseEnemyKilled(enemyId);
|
||
|
|
GameEvents.RaiseNotification($"{displayName} повержен");
|
||
|
|
base.HandleDeath(source);
|
||
|
|
Destroy(gameObject, 0.15f);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void DropRewards()
|
||
|
|
{
|
||
|
|
OTGIntegrated.Inventory.Inventory inventory = GameManager.Instance != null ? GameManager.Instance.inventory : null;
|
||
|
|
if (inventory == null || dropItems == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < dropItems.Count; i++)
|
||
|
|
{
|
||
|
|
EnemyDrop drop = dropItems[i];
|
||
|
|
if (drop != null && drop.item != null && drop.amount > 0)
|
||
|
|
{
|
||
|
|
inventory.AddItem(drop.item, drop.amount);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|