234 lines
6.3 KiB
C#
234 lines
6.3 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
namespace FORGE3D
|
|
{
|
|
[RequireComponent(typeof(LineRenderer))]
|
|
public class F3DBeam : MonoBehaviour
|
|
{
|
|
public LayerMask layerMask;
|
|
|
|
[Tooltip("The amount of damage this projectil inflicts generally.")]
|
|
public float Damage = 1f;
|
|
[Tooltip("The magnitude of the blast when hitting something.")]
|
|
public float BlastMagnitude = 0.1f;
|
|
|
|
[HideInInspector]
|
|
public int OwnerId = 0;
|
|
|
|
public WeaponEffect fxType; // Weapon type
|
|
public bool OneShot; // Constant or single beam?
|
|
|
|
public Texture[] BeamFrames; // Animation frame sequence
|
|
public float FrameStep; // Animation time
|
|
|
|
public float beamScale; // Default beam scale to be kept over distance
|
|
public float MaxBeamLength; // Maximum beam length
|
|
|
|
public bool AnimateUV; // UV Animation
|
|
public float UVTime; // UV Animation speed
|
|
|
|
public Transform rayImpact; // Impact transform
|
|
public Transform rayMuzzle; // Muzzle flash transform
|
|
|
|
LineRenderer lineRenderer; // Line rendered component
|
|
RaycastHit hitPoint; // Raycast structure
|
|
RaycastHit2D hitPoint2D; // Raycasthit in 2d
|
|
|
|
int frameNo; // Frame counter
|
|
int FrameTimerID; // Frame timer reference
|
|
float beamLength; // Current beam length
|
|
float initialBeamOffset; // Initial UV offset
|
|
public float fxOffset; // Fx offset from bullet's touch point
|
|
|
|
void Awake()
|
|
{
|
|
// Get line renderer component
|
|
lineRenderer = GetComponent<LineRenderer>();
|
|
|
|
// Assign first frame texture
|
|
if (!AnimateUV && BeamFrames.Length > 0)
|
|
lineRenderer.material.mainTexture = BeamFrames[0];
|
|
|
|
// Randomize uv offset
|
|
initialBeamOffset = Random.Range(0f, 5f);
|
|
}
|
|
|
|
// OnSpawned called by pool manager
|
|
void OnSpawned()
|
|
{
|
|
// Do one time raycast in case of one shot flag
|
|
if (OneShot)
|
|
Raycast();
|
|
|
|
// Start animation sequence if beam frames array has more than 2 elements
|
|
if (BeamFrames.Length > 1)
|
|
Animate();
|
|
}
|
|
|
|
// OnDespawned called by pool manager
|
|
void OnDespawned()
|
|
{
|
|
// Reset frame counter
|
|
frameNo = 0;
|
|
|
|
// Clear timer
|
|
if (FrameTimerID != -1)
|
|
{
|
|
F3DTime.time.RemoveTimer(FrameTimerID);
|
|
FrameTimerID = -1;
|
|
}
|
|
}
|
|
|
|
// Hit point calculation
|
|
void Raycast()
|
|
{
|
|
// Prepare structure and create ray
|
|
hitPoint = new RaycastHit();
|
|
Ray ray = new Ray(transform.position, transform.forward);
|
|
// Calculate default beam proportion multiplier based on default scale and maximum length
|
|
float propMult = MaxBeamLength * (beamScale / 10f);
|
|
|
|
// Raycast
|
|
if (Physics.Raycast(ray, out hitPoint, MaxBeamLength, layerMask)
|
|
&& DetectorCollision(hitPoint) != OwnerId)
|
|
{
|
|
// Get current beam length and update line renderer accordingly
|
|
beamLength = Vector3.Distance(transform.position, hitPoint.point);
|
|
lineRenderer.SetPosition(1, new Vector3(0f, 0f, beamLength));
|
|
|
|
// Calculate default beam proportion multiplier based on default scale and current length
|
|
propMult = beamLength * (beamScale / 10f);
|
|
// Spawn prefabs and apply force
|
|
switch (fxType)
|
|
{
|
|
case WeaponEffect.Sniper:
|
|
F3DFXController.instance.SniperImpact(hitPoint.point + hitPoint.normal * fxOffset);
|
|
break;
|
|
|
|
case WeaponEffect.RailGun:
|
|
F3DFXController.instance.RailgunImpact(hitPoint.point + hitPoint.normal * fxOffset);
|
|
break;
|
|
|
|
case WeaponEffect.PlasmaBeam:
|
|
break;
|
|
|
|
case WeaponEffect.PlasmaBeamHeavy:
|
|
break;
|
|
}
|
|
|
|
// Adjust impact effect position
|
|
if (rayImpact)
|
|
rayImpact.position = hitPoint.point - transform.forward * 0.5f;
|
|
}
|
|
else
|
|
{
|
|
// Set beam to maximum length
|
|
beamLength = MaxBeamLength;
|
|
lineRenderer.SetPosition(1, new Vector3(0f, 0f, beamLength));
|
|
|
|
// Adjust impact effect position
|
|
if (rayImpact)
|
|
rayImpact.position = transform.position + transform.forward * beamLength;
|
|
}
|
|
|
|
// Adjust muzzle position
|
|
if (rayMuzzle)
|
|
rayMuzzle.position = transform.position + transform.forward * 0.1f;
|
|
|
|
// Set beam scaling according to its length
|
|
lineRenderer.material.SetTextureScale("_BaseMap", new Vector2(propMult, 1f));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if a HitDetector was hit and registers a hit
|
|
/// on it if so.
|
|
/// </summary>
|
|
/// <param name="hitPoint"></param>
|
|
/// <returns>OwnerId of the hit detector (-1 on none)</returns>
|
|
int DetectorCollision(RaycastHit hitPoint)
|
|
{
|
|
if (hitPoint.collider.gameObject.TryGetComponent(out HitDetection detector))
|
|
{
|
|
// Check if the one firing was hit
|
|
if (detector.OwnerId == OwnerId)
|
|
{
|
|
return OwnerId;
|
|
}
|
|
|
|
ProjectileDamage inflictling = new()
|
|
{
|
|
DamageValue = Damage,
|
|
ImpactMagnitude = BlastMagnitude,
|
|
ImpactPoint = hitPoint.point,
|
|
ImpactDirection = transform.forward
|
|
};
|
|
detector.RegisterHit(inflictling);
|
|
return detector.OwnerId;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// Advance texture frame
|
|
void OnFrameStep()
|
|
{
|
|
// Set current texture frame based on frame counter
|
|
lineRenderer.material.mainTexture = BeamFrames[frameNo];
|
|
frameNo++;
|
|
|
|
// Reset frame counter
|
|
if (frameNo == BeamFrames.Length)
|
|
frameNo = 0;
|
|
}
|
|
|
|
// Initialize frame animation
|
|
void Animate()
|
|
{
|
|
if (BeamFrames.Length > 1)
|
|
{
|
|
// Set current frame
|
|
frameNo = 0;
|
|
lineRenderer.material.mainTexture = BeamFrames[frameNo];
|
|
|
|
// Add timer
|
|
FrameTimerID = F3DTime.time.AddTimer(FrameStep, BeamFrames.Length - 1, OnFrameStep);
|
|
|
|
frameNo = 1;
|
|
}
|
|
}
|
|
|
|
// Apply force to last hit object
|
|
void ApplyForce(float force)
|
|
{
|
|
if (hitPoint.rigidbody != null)
|
|
hitPoint.rigidbody.AddForceAtPosition(transform.forward * force, hitPoint.point,
|
|
ForceMode.VelocityChange);
|
|
}
|
|
|
|
// Set offset of impact
|
|
public void SetOffset(float offset)
|
|
{
|
|
fxOffset = offset;
|
|
}
|
|
|
|
private float animateUVTime;
|
|
|
|
void Update()
|
|
{
|
|
// Animate texture UV
|
|
if (AnimateUV)
|
|
{
|
|
animateUVTime += Time.deltaTime;
|
|
|
|
if (animateUVTime > 1.0f)
|
|
animateUVTime = 0f;
|
|
var v = animateUVTime * UVTime + initialBeamOffset;
|
|
lineRenderer.material.SetVector("_Offset", new Vector2(v, 0));
|
|
}
|
|
|
|
// Raycast for laser beams
|
|
if (!OneShot)
|
|
Raycast();
|
|
}
|
|
}
|
|
} |