Boss partial class methods for the Sword attack. Initializes timing, checks range to start the attack, broadcasts RPCs to play animations and SFX, and spawns "sword" enemies toward the target with randomized delays and positions.
using Sandbox;
using Sandbox.Citizen;
using System;
using System.Xml.Linq;
public partial class Boss
{
protected float _swordDelayTimer;
protected float _swordDelayMin;
protected float _swordDelayMax;
private TimeSince _timeSinceSwordShoot;
private float _swordEmitDelay;
private float _swordEmitDelayMin;
private float _swordEmitDelayMax;
private int _swordEmitNum;
private float _swordTotalTime;
void InitSword()
{
if ( IsProxy )
return;
_swordDelayMin = 15f;
_swordDelayMax = 34f;
_swordDelayTimer = Game.Random.Float( _swordDelayMin, _swordDelayMax ) * Utils.Select( Manager.Instance.Difficulty, 1.35f, 1f, 0.925f );
//_swordDelayTimer = 0.6f;
_swordEmitDelayMin = 1.2f;
_swordEmitDelayMax = 1.6f;
}
void HandleSword()
{
if ( !IsReadyForAction || !TargetUnit.IsValid() )
return;
var targetDistSqr = (TargetUnit.Position2D - Position2D).LengthSquared;
if ( targetDistSqr < MathF.Pow( 800f, 2f ) )
{
_swordDelayTimer -= Time.Delta * TimeScale;
if ( _swordDelayTimer < 0f )
SetState( BossState.SwordPrepare );
}
}
[Rpc.Broadcast]
protected void StartSwordRpc()
{
SetAnim( "SummonPrepare" );
//AnimationHelper.HoldType = CitizenAnimationHelper.HoldTypes.RPG;
//AnimationHelper.WithLook( Vector3.Up );
Manager.Instance.PlaySfxNearby( "boss.prepare", Position2D, pitch: Game.Random.Float( 0.75f, 0.85f ), volume: 1.4f, maxDist: 500f );
if ( IsProxy )
return;
_swordEmitNum = 0;
_swordEmitDelay = Game.Random.Float( _swordEmitDelayMin, _swordEmitDelayMax ) * Utils.Map( HpPercent, 1f, 0f, 1f, 0.75f );
_swordTotalTime = Game.Random.Float( 7f, 9f ) * Utils.Map( HpPercent, 1f, 0f, 1f, 1.33f, EasingType.Linear );
_timeSinceSwordShoot = _swordEmitDelay - Game.Random.Float( 0.1f, 0.2f );
}
[Rpc.Broadcast]
protected void SwordRpc()
{
//AnimationHelper.Target.Set( "b_attack", true );
if ( IsProxy )
return;
}
[Rpc.Broadcast]
protected void SwordEmitRpc()
{
SetAnim( "Summon" );
// todo: better sfx
//Manager.Instance.PlaySfxNearby( "boss.shoot", Position2D, pitch: Utils.Map( _swordEmitNum, 0, 10, 0.3f, 0.4f, EasingType.SineOut), volume: 0.8f, maxDist: 600f );
//AnimationHelper.Target.Set( "b_attack", true );
if ( IsProxy )
return;
var targetPos = (HasTarget && !TargetUnit.IsDying)
? TargetUnit.Position2D + TargetUnit.Velocity * Game.Random.Float( 0.5f, 3f ) + TargetUnit.Velocity.Normal * Game.Random.Float( 0f, 60f ) + Utils.GetRandomVector() * Game.Random.Float( 30f, 90f )
: Position2D + Utils.GetRandomVector() * Game.Random.Float( 100f, 400f );
Manager.Instance.SpawnEnemy( "sword", targetPos, spawnInstantly: false, rotAngle: 90f + Game.Random.Float( -40f, 40f ) + (Game.Random.Int( 0, 1 ) == 0 ? 180f : 0f) );
_swordEmitNum++;
}
}