void AttractableSystem::Update(double DeltaTime)
{
    for (auto actor : mScene.GetActorsFromMap( GetType_static() ))
    {
        auto attractableC( actor->Get<IAttractableComponent>() );
        auto accelerationC( actor->Get<IAccelerationComponent>() );
        auto targetHolderC( actor->Get<ITargetHolderComponent>() );
        auto moveC( actor->Get<IMoveComponent>() );
        if (!attractableC.IsValid() || !accelerationC.IsValid() || !targetHolderC.IsValid() || !moveC.IsValid())
        {
            continue;
        }

        auto const accel = accelerationC->GetAcceleration();
        auto currentTarget( mScene.GetActor( targetHolderC->GetTargetGUID() ) );
        targetHolderC->SetTargetGUID( -1 );
        accelerationC->SetAcceleration( -1 * attractableC->GetDeceleration() );

        if (currentTarget.IsValid())
        {
            auto healthC( currentTarget->Get<IHealthComponent>() );
            if (healthC.IsValid() && healthC->IsAlive())
            {
                accelerationC->SetAcceleration( accel );
                targetHolderC->SetTargetGUID( currentTarget->GetGUID() );
                moveC->SetMoving( true );
                attractableC->GetTurnToTargetAct().Update( *actor, DeltaTime );
            }
        }
    }
}
void GuardControllerSubSystem::Update(Actor& actor, double DeltaTime)
{
    Opt<GuardControllerComponent> guardCC=actor.Get<IControllerComponent>();
    if (!guardCC.IsValid()||!guardCC->IsEnabled())
    {
        return;
    }
    if (mProgramState.mMode == core::ProgramState::Client)
    {
        return;
    }
    auto targetHolderC = actor.Get<ITargetHolderComponent>();
    if (!targetHolderC.IsValid())
    {
        return;
    }
    auto healthC = actor.Get<IHealthComponent>();
    if (!healthC.IsValid() || !healthC->IsAlive())
    {
        return;
    }
    UpdateTarget( actor, targetHolderC );
    Opt<Actor> currentTarget( mScene.GetActor( targetHolderC->GetTargetGUID() ) );
    auto moveC( actor.Get<IMoveComponent>() );
    guardCC->SetNextMoveTimer( guardCC->GetNextMoveTimer() - DeltaTime );
    if (currentTarget.IsValid())
    {
        auto positionC( actor.Get<IPositionComponent>() );
        auto targetPositionC( currentTarget->Get<IPositionComponent>() );
        auto const distSqr = GetDistanceSqr( positionC, targetPositionC );
        glm::vec2 const distV( (targetPositionC->GetX() - positionC->GetX()), (targetPositionC->GetY() - positionC->GetY()) );
        double const Rot = atan2( distV.y, distV.x );
        positionC->SetOrientation( Rot );
        auto inventoryC = actor.Get<IInventoryComponent>();
        if (inventoryC.IsValid())
        {
            Opt<Weapon> weapon = inventoryC->GetSelectedWeapon();
            if (weapon.IsValid())
            {
                int32_t const aggroAltDistSqr = guardCC->GetAggroAltDist() * guardCC->GetAggroAltDist();
                if (distSqr < aggroAltDistSqr)
                {
                    weapon->SetShoot( false );
                    weapon->SetShootAlt( true );
                }
                else
                {
                    weapon->SetShoot( true );
                    weapon->SetShootAlt( false );
                }
            }
        }




        if (guardCC->GetNextMoveTimer() <= 0.0)
        {
            const int32_t ran = RandomGenerator::global()() % 3;
            if (ran == 0)
            {
                guardCC->SetMoveDirection( GuardControllerComponent::Left );
            }
            else if (ran == 1)
            {
                guardCC->SetMoveDirection( GuardControllerComponent::Right );
            }
            else
            {
                guardCC->SetMoveDirection( GuardControllerComponent::None );
            }
            guardCC->SetNextMoveTimer(guardCC->GetNextMoveTimerMax() 
                + (RandomGenerator::global()() % 100*0.02*- 1)*guardCC->GetNextMoveTimerVariance() );
        }
        int32_t const tooCloseDistSqr = guardCC->GetCloseDist() * guardCC->GetCloseDist();
        int32_t const walkAwayDistSqr = guardCC->GetWalkAwayDist() * guardCC->GetWalkAwayDist();
        double heading = 0.0;
        static const double pi = boost::math::constants::pi<double>();
        if (distSqr > tooCloseDistSqr)
        {
            heading = Rot;
            if (guardCC->GetMoveDirection() == GuardControllerComponent::Left)
            {
                heading -= pi / 4;
            }
            else if (guardCC->GetMoveDirection() == GuardControllerComponent::Right)
            {
                heading += pi / 4;
            }
            moveC->SetMoving( true );
        }
        else if (distSqr < walkAwayDistSqr)
        {
            heading = Rot-pi;
            if (guardCC->GetMoveDirection() == GuardControllerComponent::Left)
            {
                heading += pi / 4;
            }
            else if (guardCC->GetMoveDirection() == GuardControllerComponent::Right)
            {
                heading -= pi / 4;
            }
            moveC->SetMoving( true );
        }
        else
        {
            heading = Rot;
            if (guardCC->GetMoveDirection() == GuardControllerComponent::Left)
            {
                heading -= pi / 2;
                moveC->SetMoving( true );
            }
            else if (guardCC->GetMoveDirection() == GuardControllerComponent::Right)
            {
                heading += pi / 2;
                moveC->SetMoving( true );
            }
            else
            {
                moveC->SetMoving( false );
            }
        }
        moveC->SetHeading( heading );
    }
    else
    {
        moveC->SetMoving( false );
        Opt<IInventoryComponent> inventoryC = actor.Get<IInventoryComponent>();
        if (inventoryC.IsValid())
        {
            Opt<Weapon> weapon = inventoryC->GetSelectedWeapon();
            if (weapon.IsValid())
            {
                weapon->SetShoot( false );
                weapon->SetShootAlt( false );
            }
        }
    }
}