Partial Boss enemy component handling its sword-summoning attack. Initializes timing parameters, checks distance to trigger a prepare state, broadcasts RPCs to play animations and SFX, and spawns "sword" enemies at computed target positions over a timed sequence.
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++;
}
}