169 lines
4.5 KiB
C#
169 lines
4.5 KiB
C#
|
using System.Linq;
|
||
|
using RoR2;
|
||
|
using RoR2.Projectile;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace EntityStates.MiniMushroom;
|
||
|
|
||
|
public class SporeGrenade : BaseState
|
||
|
{
|
||
|
public static GameObject chargeEffectPrefab;
|
||
|
|
||
|
public static string attackSoundString;
|
||
|
|
||
|
public static string chargeUpSoundString;
|
||
|
|
||
|
public static float recoilAmplitude = 1f;
|
||
|
|
||
|
public static GameObject projectilePrefab;
|
||
|
|
||
|
public static float baseDuration = 2f;
|
||
|
|
||
|
public static string muzzleString;
|
||
|
|
||
|
public static float damageCoefficient;
|
||
|
|
||
|
public static float timeToTarget = 3f;
|
||
|
|
||
|
public static float projectileVelocity = 55f;
|
||
|
|
||
|
public static float minimumDistance;
|
||
|
|
||
|
public static float maximumDistance;
|
||
|
|
||
|
public static float baseChargeTime = 2f;
|
||
|
|
||
|
private uint chargeupSoundID;
|
||
|
|
||
|
private Ray projectileRay;
|
||
|
|
||
|
private Transform modelTransform;
|
||
|
|
||
|
private float duration;
|
||
|
|
||
|
private float chargeTime;
|
||
|
|
||
|
private bool hasFired;
|
||
|
|
||
|
private Animator modelAnimator;
|
||
|
|
||
|
private GameObject chargeEffectInstance;
|
||
|
|
||
|
private static int ChargeStateHash = Animator.StringToHash("Charge");
|
||
|
|
||
|
private static int isChargedParamHash = Animator.StringToHash("isCharged");
|
||
|
|
||
|
private static int EmptyStateHash = Animator.StringToHash("Empty");
|
||
|
|
||
|
public override void OnEnter()
|
||
|
{
|
||
|
base.OnEnter();
|
||
|
duration = baseDuration / attackSpeedStat;
|
||
|
chargeTime = baseChargeTime / attackSpeedStat;
|
||
|
modelAnimator = GetModelAnimator();
|
||
|
if ((bool)modelAnimator)
|
||
|
{
|
||
|
modelAnimator.SetBool(isChargedParamHash, value: false);
|
||
|
PlayAnimation("Gesture, Additive", ChargeStateHash);
|
||
|
chargeupSoundID = Util.PlaySound(chargeUpSoundString, base.characterBody.modelLocator.modelTransform.gameObject);
|
||
|
}
|
||
|
Transform transform = FindModelChild("ChargeSpot");
|
||
|
if ((bool)transform)
|
||
|
{
|
||
|
chargeEffectInstance = Object.Instantiate(chargeEffectPrefab, transform);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void FixedUpdate()
|
||
|
{
|
||
|
base.FixedUpdate();
|
||
|
if (!(base.fixedAge >= chargeTime))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (!hasFired)
|
||
|
{
|
||
|
hasFired = true;
|
||
|
modelAnimator?.SetBool(isChargedParamHash, value: true);
|
||
|
if (base.isAuthority)
|
||
|
{
|
||
|
FireGrenade(muzzleString);
|
||
|
}
|
||
|
}
|
||
|
if (base.isAuthority && base.fixedAge >= duration)
|
||
|
{
|
||
|
outer.SetNextStateToMain();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void OnExit()
|
||
|
{
|
||
|
PlayAnimation("Gesture, Additive", EmptyStateHash);
|
||
|
AkSoundEngine.StopPlayingID(chargeupSoundID);
|
||
|
if ((bool)chargeEffectInstance)
|
||
|
{
|
||
|
EntityState.Destroy(chargeEffectInstance);
|
||
|
}
|
||
|
base.OnExit();
|
||
|
}
|
||
|
|
||
|
private void FireGrenade(string targetMuzzle)
|
||
|
{
|
||
|
Ray aimRay = GetAimRay();
|
||
|
Ray ray = new Ray(aimRay.origin, Vector3.up);
|
||
|
Transform transform = FindModelChild(targetMuzzle);
|
||
|
if ((bool)transform)
|
||
|
{
|
||
|
ray.origin = transform.position;
|
||
|
}
|
||
|
BullseyeSearch bullseyeSearch = new BullseyeSearch();
|
||
|
bullseyeSearch.searchOrigin = aimRay.origin;
|
||
|
bullseyeSearch.searchDirection = aimRay.direction;
|
||
|
bullseyeSearch.filterByLoS = false;
|
||
|
bullseyeSearch.teamMaskFilter = TeamMask.allButNeutral;
|
||
|
if ((bool)base.teamComponent)
|
||
|
{
|
||
|
bullseyeSearch.teamMaskFilter.RemoveTeam(base.teamComponent.teamIndex);
|
||
|
}
|
||
|
bullseyeSearch.sortMode = BullseyeSearch.SortMode.Angle;
|
||
|
bullseyeSearch.RefreshCandidates();
|
||
|
HurtBox hurtBox = bullseyeSearch.GetResults().FirstOrDefault();
|
||
|
bool flag = false;
|
||
|
Vector3 vector = Vector3.zero;
|
||
|
RaycastHit hitInfo;
|
||
|
if ((bool)hurtBox)
|
||
|
{
|
||
|
vector = hurtBox.transform.position;
|
||
|
flag = true;
|
||
|
}
|
||
|
else if (Physics.Raycast(aimRay, out hitInfo, 1000f, (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask, QueryTriggerInteraction.Ignore))
|
||
|
{
|
||
|
vector = hitInfo.point;
|
||
|
flag = true;
|
||
|
}
|
||
|
float magnitude = projectileVelocity;
|
||
|
if (flag)
|
||
|
{
|
||
|
Vector3 vector2 = vector - ray.origin;
|
||
|
Vector2 vector3 = new Vector2(vector2.x, vector2.z);
|
||
|
float magnitude2 = vector3.magnitude;
|
||
|
Vector2 vector4 = vector3 / magnitude2;
|
||
|
if (magnitude2 < minimumDistance)
|
||
|
{
|
||
|
magnitude2 = minimumDistance;
|
||
|
}
|
||
|
if (magnitude2 > maximumDistance)
|
||
|
{
|
||
|
magnitude2 = maximumDistance;
|
||
|
}
|
||
|
float y = Trajectory.CalculateInitialYSpeed(timeToTarget, vector2.y);
|
||
|
float num = magnitude2 / timeToTarget;
|
||
|
Vector3 direction = new Vector3(vector4.x * num, y, vector4.y * num);
|
||
|
magnitude = direction.magnitude;
|
||
|
ray.direction = direction;
|
||
|
}
|
||
|
Quaternion rotation = Util.QuaternionSafeLookRotation(ray.direction + Random.insideUnitSphere * 0.05f);
|
||
|
ProjectileManager.instance.FireProjectile(projectilePrefab, ray.origin, rotation, base.gameObject, damageStat * damageCoefficient, 0f, Util.CheckRoll(critStat, base.characterBody.master), DamageColorIndex.Default, null, magnitude);
|
||
|
}
|
||
|
}
|