コード例 #1
0
    private void OnActorAiState(SocketAsyncEventArgs args, byte[] bytes)
    {
        ActorAiState input = ActorAiState.Parser.ParseFrom(bytes);

        if (input.RoomId != RoomId)
        {
            return; // 不是自己房间的消息,略过
        }
        if (input.AiCellIndexFrom == 0)
        {
            string msg = $"Actor position is lost!";
            ServerRoomManager.Instance.Log("RoomLogic OnActorAiState Error - " + msg);
            ActorAiStateReply output2 = new ActorAiStateReply()
            {
                RoomId  = input.RoomId,
                OwnerId = input.OwnerId,
                ActorId = input.ActorId,
                Ret     = false,
                ErrMsg  = msg,
            };

            ServerRoomManager.Instance.SendMsg(args, ROOM_REPLY.ActorAiStateReply, output2.ToByteArray());
            return;
        }

        // 更新单元Ai信息,在服务器的ActorBehaviour里保存一份
        var ab = ActorManager.GetActor(input.ActorId);

        if (ab != null)
        {
            ab.AiState        = input.AiState;
            ab.CellIndex      = input.AiCellIndexFrom;
            ab.AiCellIndexTo  = input.AiCellIndexTo;
            ab.AiTargetId     = input.AiTargetId;
            ab.Orientation    = input.Orientation;
            ab.AiDurationTime = input.AiDurationTime;
            ab.AiTotalTime    = input.AiTotalTime;
            ab.AiStartTime    = DateTime.Now; // 记录得到当前状态的时间, 在存盘的时候再记录一下时间, 把剩余时间保存起来
        }

        // 注意: 有一种情况, 可能是ab并不存在,但是这条消息还是有用的,因为ActorRemoveReply消息里, 服务器已经把本单元删掉了,
        // 但是服务器仍然需要转发一条将单位状态设置为StateEnum.DIE的消息
        ActorAiStateReply output = new ActorAiStateReply()
        {
            RoomId          = input.RoomId,
            OwnerId         = input.OwnerId,
            ActorId         = input.ActorId,
            AiState         = input.AiState,
            AiCellIndexFrom = input.AiCellIndexFrom,
            AiCellIndexTo   = input.AiCellIndexTo,
            AiTargetId      = input.AiTargetId,
            Orientation     = input.Orientation,
            AiDurationTime  = input.AiDurationTime,
            AiTotalTime     = input.AiTotalTime,
            Ret             = true,
        };

        BroadcastMsg(ROOM_REPLY.ActorAiStateReply, output.ToByteArray());
    }
コード例 #2
0
        public void ForceEnterState(ActorAiState newState)
        {
            //disgusting hack, need to rework how this is handled
            bool oldLockAiState = LockAiState;

            LockAiState = false;
            EnterState(newState);
            LockAiState = oldLockAiState;
        }
コード例 #3
0
        public override void RestoreEntityData(Dictionary <string, object> data)
        {
            base.RestoreEntityData(data);

            if (data.ContainsKey("Actor"))
            {
                ActorExtraData actorData = data["Actor"] as ActorExtraData;
                if (actorData != null)
                {
                    //restore!

                    CurrentAiState = actorData.CurrentAiState;
                    LastAiState    = actorData.LastAiState;
                    LockAiState    = actorData.LockAiState;
                    if (AnimationComponent != null)
                    {
                        AnimationComponent.CurrentAnimState = actorData.CurrentAnimState;
                        AnimationComponent.LockAnimState    = actorData.LockAnimState;
                    }
                    SavedTarget = actorData.SavedTarget;
                    TimeInState = actorData.TimeInState;

                    Health  = actorData.Health;
                    BeenHit = actorData.BeenHit;

                    LastHit         = actorData.LastHit;
                    LastHitDamage   = actorData.LastHitDamage;
                    WasExtremeDeath = actorData.WasExtremeDeath;

                    MovementComponent.BeforeRestore(data);
                    MovementComponent.MovementTarget = actorData.AltTarget;
                    MovementComponent.IsRunning      = actorData.IsRunning;
                    if (CurrentAiState == ActorAiState.Dead)
                    {
                        MovementComponent.HandleDeath();
                    }

                    if (InteractionComponent != null)
                    {
                        InteractionComponent.InteractionDisabledByHit = actorData.InteractionForceDisabled;

                        if (data.ContainsKey("Container"))
                        {
                            InteractionComponent.CorpseContainer = SerializableContainerModel.MakeContainerModel((SerializableContainerModel)data["Container"]);
                        }
                    }
                }
                else
                {
                    CDebug.LogEx(string.Format("Invalid actor data for {0} found on restore!", this.name), LogLevel.Error, this);
                }
            }
            else
            {
                CDebug.LogEx(string.Format("No actor data for {0} found on restore!", this.name), LogLevel.Error, this);
            }
        }
コード例 #4
0
    public void TriggerTransition(StateEnum newState, int cellIndex = 0, long actorId = 0, float durationTime = 0, float totalTime = 0)
    {
        if (IsValidTransition(newState))
        {
            SetTarget(cellIndex, actorId);
            var          ab     = _actorBehaviour;
            ActorAiState output = new ActorAiState()
            {
                RoomId          = ab.RoomId,
                OwnerId         = ab.OwnerId,
                ActorId         = ab.ActorId,
                AiState         = (int)newState,
                AiCellIndexFrom = ab.CellIndex,
                AiCellIndexTo   = TargetCellIndex,
                AiTargetId      = TargetActorId,
                Orientation     = ab.Orientation,
                AiDurationTime  = durationTime,
                AiTotalTime     = totalTime,
            };
            GameRoomManager.Instance.SendMsg(ROOM.ActorAiState, output.ToByteArray());

            var oldState = CurrentAiState;
            CurrentAiState = newState;

            TransitionTo(newState);

            _startTime    = Time.time;  // 必须放在后面,因为这个数值大多在Tick()和Exit()里进行判定,而在Enter()里是没用的
            _durationTime = durationTime;
            _totalTime    = totalTime;

            if (logChanges)
            {
                Debug.Log(
                    $"ActorStateMachine: <{ab.ActorId}> State changed from<{oldState}> to<{newState}> - TargetPosition:<{TargetPosX},{TargetPosZ}> DurationTime:<{output.AiDurationTime}> -Time:{DateTime.Now.ToLongTimeString()}");
            }
        }
        else
        {
            Debug.LogErrorFormat("ActorStateMachine: Invalid transition from {0} to {1} detected.",
                                 CurrentAiState, newState);
        }
    }
コード例 #5
0
ファイル: ActorController.cs プロジェクト: HXWY/commoncore
        private void ExitState(ActorAiState oldState)
        {
            if (LockAiState)
            {
                return;
            }

            //TODO we may need this at some point
            switch (oldState)
            {
            case ActorAiState.Idle:
                break;

            case ActorAiState.Dead:
                break;

            case ActorAiState.Wandering:
                MovementComponent.AbortMove();
                AudioComponent.Ref()?.StopMoveSound();
                break;

            case ActorAiState.Chasing:
                MovementComponent.AbortMove();
                AudioComponent.Ref()?.StopMoveSound();
                break;

            case ActorAiState.Attacking:
                AttackComponent.Ref()?.EndAttack();
                break;

            case ActorAiState.Covering:
                break;

            case ActorAiState.Fleeing:
                MovementComponent.AbortMove();
                AudioComponent.Ref()?.StopMoveSound();
                break;

            default:
                break;
            }
        }
コード例 #6
0
        public void EnterState(ActorAiState newState)
        {
            if (LockAiState)
            {
                return;
            }

            LastAiState = CurrentAiState;

            ExitState(CurrentAiState); //good place or no?

            TimeInState = 0;

            switch (newState)
            {
            case ActorAiState.Idle:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Idle);
                MovementComponent.AbortMove();
                break;

            case ActorAiState.Dead:
                if (CurrentAiState == ActorAiState.Dead)     //fix for glitchy looking behaviour
                {
                    break;
                }

                MovementComponent.AbortMove();
                MovementComponent.HandleDeath();
                if (DieImmediately)
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dead);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dying);
                }

                if (InteractionComponent != null)
                {
                    InteractionComponent.InteractionDisabledByHit = false;
                }

                if (DestroyOnDeath)
                {
                    this.gameObject.SetActive(false);     //actually destroying the object breaks saving
                }
                if (OnDeathSpecial != null)
                {
                    OnDeathSpecial.Execute(new ActionInvokerData {
                        Activator = this
                    });
                }

                if (Target != null && Target.GetComponent <PlayerController>() && GrantXpOnDeath > 0)
                {
                    GameState.Instance.PlayerRpgState.GrantXPScaled(GrantXpOnDeath);
                }
                break;

            case ActorAiState.Wandering:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                //set initial destination
                Vector2 newpos = VectorUtils.GetRandomVector2(InitialPosition.GetFlatVector(), WanderRadius);
                MovementComponent.SetDestination(newpos.GetSpaceVector());
                break;

            case ActorAiState.Chasing:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                }
                {
                    //set target

                    if (Target == null)
                    {
                        GetSwizzledTarget();     //fix for loading saves
                    }
                    var d = Target.position;     //FIXME what if Target is null?
                    MovementComponent.SetDestination(d);
                }
                break;

            case ActorAiState.ScriptedMoveTo:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                }
                MovementComponent.SetDestination(MovementComponent.MovementTarget);
                break;

            case ActorAiState.Attacking:
                if (AttackComponent == null)
                {
                    Debug.LogError($"{name} tried to attack, but has no attack component!");
                    EnterState(ActorAiState.Idle);
                    return;
                }

                if (Target == null)
                {
                    GetSwizzledTarget();     //fix for loading saves
                }
                //set animation, fire projectile, set timer
                AttackComponent.BeginAttack();
                break;

            case ActorAiState.Covering:
                break;

            case ActorAiState.Hurting:
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Hurting);
                break;

            case ActorAiState.Fleeing:
                if (RunOnFlee)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                }
                {
                    //set target
                    var d = transform.position + ((Target.position - transform.position).normalized * -1);
                    MovementComponent.SetDestination(d);
                }
                break;

            default:
                break;
            }

            CurrentAiState = newState;
        }
コード例 #7
0
        public void EnterState(ActorAiState newState)
        {
            if (LockAiState)
            {
                return;
            }

            if (newState != CurrentAiState)
            {
                LastAiState = CurrentAiState;
            }

            ExitState(CurrentAiState); //good place or no?

            TimeInState = 0;

            switch (newState)
            {
            case ActorAiState.Idle:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Idle);
                MovementComponent.AbortMove();
                break;

            case ActorAiState.Dead:
            {
                if (CurrentAiState == ActorAiState.Dead)         //fix for glitchy looking behaviour
                {
                    break;
                }

                MovementComponent.AbortMove();
                MovementComponent.HandleDeath();
                var deathStateArgs = new DeathStateActorAnimationArgs()
                {
                    DamageEffector = LastHit?.DamageEffector ?? 0, DamageType = LastHit?.DamageType ?? 0, ExtremeDeath = WasExtremeDeath, HitLocation = LastHit?.HitLocation ?? 0, HitMaterial = LastHit?.HitMaterial ?? 0
                };
                if (DieImmediately)
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dead, deathStateArgs);
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Dying, deathStateArgs);
                }

                AudioComponent.Ref()?.StopLivingSounds();
                if (WasExtremeDeath)
                {
                    AudioComponent.Ref()?.PlayExtremeDeathSound();
                }
                else
                {
                    AudioComponent.Ref()?.PlayDeathSound();
                }

                if (InteractionComponent != null)
                {
                    InteractionComponent.InteractionDisabledByHit = false;
                }

                if (DestroyOnDeath)
                {
                    this.gameObject.SetActive(false);         //actually destroying the object breaks saving
                }
                if (OnDeathSpecial != null)
                {
                    OnDeathSpecial.Execute(new ActionInvokerData {
                            Activator = this
                        });
                }

                if (DisableHitboxesOnDeath)
                {
                    var hitboxComponents = GetComponentsInChildren <IHitboxComponent>(true);
                    foreach (var hitboxComponent in hitboxComponents)
                    {
                        if (hitboxComponent is MonoBehaviour mb)         //IHitboxComponent does not actually imply MonoBehaviour
                        {
                            mb.gameObject.SetActive(false);
                        }
                    }
                }

                if (DisableCollidersOnDeath)
                {
                    var colliders = GetComponentsInChildren <Collider>(true);
                    foreach (var collider in colliders)
                    {
                        collider.enabled = false;
                    }
                }

                if (
                    ((LastHit != null && LastHit.Value.Originator != null && LastHit.Value.Originator is PlayerController) ||
                     (Target != null && Target.GetComponent <PlayerController>())
                    ) &&
                    GrantXpOnDeath > 0
                    )
                {
                    GameState.Instance.PlayerRpgState.GrantXPScaled(GrantXpOnDeath);
                }
            }
            break;

            case ActorAiState.Wandering:
                Target = null;
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                //set initial destination
                Vector2 newpos = VectorUtils.GetRandomVector2(InitialPosition.GetFlatVector(), WanderRadius);
                MovementComponent.SetDestination(newpos.GetSpaceVector());
                AudioComponent.Ref()?.StartWalkSound();
                break;

            case ActorAiState.Chasing:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }

                {
                    //set target

                    if (Target == null)
                    {
                        GetSwizzledTarget();     //fix for loading saves
                    }
                    SetChaseDestination();
                }
                break;

            case ActorAiState.ScriptedMoveTo:
                if (RunOnChase)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }
                MovementComponent.SetDestination(MovementComponent.MovementTarget);
                break;

            case ActorAiState.Attacking:
                if (AttackComponent == null)
                {
                    Debug.LogError($"{name} tried to attack, but has no attack component!");
                    EnterState(ActorAiState.Idle);
                    return;
                }

                if (Target == null)
                {
                    GetSwizzledTarget();     //fix for loading saves
                }
                //set animation, fire projectile, set timer
                AttackComponent.BeginAttack();
                break;

            case ActorAiState.Covering:
                break;

            case ActorAiState.Hurting:
                AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Hurting);
                AudioComponent.Ref()?.PlayPainSound();
                break;

            case ActorAiState.Fleeing:
                if (RunOnFlee)
                {
                    MovementComponent.IsRunning = true;
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Running);
                    AudioComponent.Ref()?.StartRunSound();
                }
                else
                {
                    AnimationComponent.Ref()?.SetAnimation(ActorAnimState.Walking);
                    AudioComponent.Ref()?.StartWalkSound();
                }

                {
                    //set target
                    var d = transform.position + ((Target.position - transform.position).normalized * -(1 + Mathf.Abs(MovementComponent.TargetThreshold)));
                    MovementComponent.SetDestination(d);
                }
                break;

            case ActorAiState.ScriptedAction:
                //nop
                break;

            default:
                break;
            }

            CurrentAiState = newState;
        }