Files
valheim/Assets/_Valheim/Scripts/Weapons/Bullet.cs
2025-07-04 14:16:14 +08:00

245 lines
6.0 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using DragonLi.Core;
using Mirror;
using UnityEngine;
using NaughtyAttributes;
using DragonLi.Frame;
using System;
public enum BulletType
{
Normal = 1,
Energy = 2,
Rocket = 3,
Shot = 4,
QY = 5,
RobotMesh = 6,
Super = 7,
Grenade = 8,
BossGrenadeBullet = 9,
BossNormal = 10,
Turret = 11,
}
public class Bullet : Entity
{
[Header("伤害")]
public float damage = 0;
[Header("击中删除时间")]
public float despawn_delay = 1f;
[Header("自动删除时间")]
public float auto_despawn_delay = 5f;
[Header("撞击预制体")]
public GameObject impact_prefab;
[Header("撞击删除时间")]
public float impact_despawn_time = 1f;
[Header("是否使用重力")]
public bool use_gravity = false;
public bool hit_trigger = false;
[Header("目标图层")]
public LayerMask HitLayer;
[SyncVar]
[NonSerialized]
public bool isHit = false;
[NonSerialized]
public bool isValid = true;
[NonSerialized]
public float despawnTime = 0f;
[NonSerialized]
public RaycastHit handlingHit;
public int ownerIndex;
public float GunDamage
{
get;
set;
}
public string SpawnPoolID
{
get;
set;
}
#region
public override void InitData()
{
Data.Add("despawn_delay", new DataRow(SupportDataType.Int)
{
Name = "despawn_delay",
FloatValue = despawn_delay
});
Data.Add("auto_despawn_delay", new DataRow(SupportDataType.Float)
{
Name = "auto_despawn_delay",
FloatValue = auto_despawn_delay
});
Data.Add("use_gravity", new DataRow(SupportDataType.Boolean)
{
Name = "use_gravity",
BooleanValue = use_gravity
});
Data.Add("hit_trigger", new DataRow(SupportDataType.Boolean)
{
Name = "hit_trigger",
BooleanValue = hit_trigger
});
Data.Add("impact_prefab", new DataRow(SupportDataType.UObject)
{
Name = "impact_prefab",
ObjectValue = impact_prefab
});
Data.Add("impact_despawn_time", new DataRow(SupportDataType.Float)
{
Name = "impact_despawn_time",
FloatValue = impact_despawn_time
});
base.InitData();
}
[Server]
public void Init(int ownerIndex)
{
this.ownerIndex = ownerIndex;
}
public override void Awake()
{
base.Awake();
RigidbodyComponent.useGravity = Data["use_gravity"].BooleanValue;
RigidbodyComponent.constraints = (RigidbodyConstraints)112;
}
public override void OnEnable()
{
isHit = false;
isValid = true;
despawnTime = Time.time + Data["auto_despawn_delay"].FloatValue;
base.OnEnable();
}
public override void Update()
{
if (isServer)
{
if (isValid)
{
if (isHit)
{
DespawnSelf();
return;
}
if (despawnTime < Time.time)
{
isValid = false;
NetworkServer.Destroy(transform.gameObject);
}
base.Update();
}
}
}
internal void FixedUpdate()
{
if (isServer && !isHit && HitCheck())
{
isHit = true;
SpawnImpact();
ApplyDamage();
HitTarget();
}
OnFixedUpdate();
}
/// <summary>
/// This will be called when fixedupdate called
/// </summary>
protected virtual void OnFixedUpdate()
{
}
#endregion
[Server]
public virtual void SpawnImpact()
{
GameObject impactPre = (GameObject)Data["impact_prefab"].ObjectValue;
if (impactPre != null)
{
GameObject impact = Instantiate(impactPre);
impact.transform.position = handlingHit.point;
//impact.transform.localEulerAngles
NetworkServer.Spawn(impact);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(impact);
}, Data["impact_despawn_time"].FloatValue);
// 碰撞点的法线方向
Vector3 normal = handlingHit.normal;
// 在这里处理特效的生成和方向
// 计算特效的旋转方向,使用法线信息
Quaternion rotation = Quaternion.LookRotation(normal);
// 将特效的旋转方向设置为法线方向
impact.transform.rotation = rotation;
}
}
[Server]
public void DespawnSelf()
{
isValid = false;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(transform.gameObject);
}, Data["despawn_delay"].FloatValue);
}
[Server]
public virtual bool HitCheck()
{
Vector3 position = transform.position;
Vector3 velocity = RigidbodyComponent.velocity * Time.deltaTime;
if (Physics.Raycast(position, velocity, out handlingHit, velocity.magnitude, HitLayer))
{
// Debug.Log("击中 - " + handlingHit.transform.name);
if (!Data["hit_trigger"].BooleanValue && handlingHit.collider.isTrigger)
{
return false;
}
return true;
}
return false;
}
[Server]
// todo
public virtual void ApplyDamage()
{
IDamagable component = handlingHit.transform.GetComponent<IDamagable>();
if (component != null)
{
OnApplyDamage(component);
}
}
[Server]
public virtual void HitTarget()
{
}
[Server]
public virtual void OnApplyDamage(IDamagable damagable) { }
[Server]
public virtual void OnHitTarget(RaycastHit hit) { }
}