示例#1
0
        private void LateUpdate()
        {
            if (FSM == null)
            {
                return;
            }

            int currentMachineIndex = 0;

            while (currentMachineIndex < FSM.StackMachines.Length)
            {
                StackMachine machine = FSM.StackMachines[currentMachineIndex];
                if (machine.Halted || (Step(machine) == StepResult.DoNextMachine))
                {
                    currentMachineIndex++;
                }
            }
        }
示例#2
0
 private void LogUnhandledEntity(string actionName, int entityIndex, FSMEntity entity, StackMachine machine)
 {
     Debug.LogWarning("FSM action '" + actionName + "' not implemented for entity " + entityIndex + " (" + entity.Value + ") @ " + (machine.IP - 1));
 }
示例#3
0
        public int DoAction(string actionName, StackMachine machine, FSMRunner fsmRunner)
        {
            global::System.Collections.Generic.Queue <IntRef> args = machine.ArgumentQueue;
            switch (actionName)
            {
            case "null":
                // Do nothing?
                break;

            case "true":
                return(1);

            case "inc":
            {
                IntRef arg = args.Dequeue();
                ++arg.Value;
            }
            break;

            case "dec":
            {
                IntRef arg = args.Dequeue();
                --arg.Value;
            }
            break;

            case "set":
            {
                IntRef arg = args.Dequeue();
                IntRef val = args.Dequeue();
                arg.Value = val.Value;
            }
            break;

            case "isGreater":
            {
                IntRef val    = args.Dequeue();
                IntRef number = args.Dequeue();

                bool greater = val.Value > number.Value;
                return(greater ? 1 : 0);
            }

            case "isLesser":
            {
                IntRef val    = args.Dequeue();
                IntRef number = args.Dequeue();

                bool lesser = val.Value < number.Value;
                return(lesser ? 1 : 0);
            }

            case "isEqual":
            {
                IntRef val    = args.Dequeue();
                IntRef number = args.Dequeue();

                bool equal = val.Value == number.Value;
                return(equal ? 1 : 0);
            }

            case "pushCam":
                CameraManager.Instance.PushCamera();
                break;

            case "popCam":
                CameraManager.Instance.PopCamera();
                break;

            case "timeGreater":
                IntRef timerNo = args.Dequeue();
                IntRef seconds = args.Dequeue();

                float secondsElapsed = Time.unscaledTime - fsmRunner.Timers[timerNo.Value];
                return(secondsElapsed >= seconds.Value ? 1 : 0);

            case "isKeypress":
                return(Input.GetKeyDown(KeyCode.Space) ? 1 : 0);

            case "camObjDir":
            {
                if (CameraManager.Instance.IsMainCameraActive)
                {
                    break;
                }

                var        camera      = CameraManager.Instance.ActiveCamera;
                IntRef     whichEntity = args.Dequeue();
                FSMEntity  origoEntity = fsmRunner.FSM.EntityTable[whichEntity.Value];
                GameObject entity      = origoEntity.Object;

                Vector3 relativePos = new Vector3(args.Dequeue().Value, args.Dequeue().Value, args.Dequeue().Value) / 100.0f;

                int yaw   = args.Dequeue().Value;
                int roll  = args.Dequeue().Value;
                int pitch = args.Dequeue().Value;

                Vector3 rotation = new Vector3(yaw, pitch, roll) / 100.0f;

                Vector3 newPos = entity.transform.position + (entity.transform.rotation * relativePos);

                if (newPos.y < entity.transform.position.y + 1)
                {
                    newPos.y = entity.transform.position.y + 1;
                }

                camera.transform.position = newPos;
                camera.transform.rotation = entity.transform.rotation * Quaternion.Euler(rotation);
            }
            break;

            case "camPosObj":
            {
                if (CameraManager.Instance.IsMainCameraActive)
                {
                    break;
                }

                var camera      = CameraManager.Instance.ActiveCamera;
                int pathIndex   = args.Dequeue().Value;
                int height      = args.Dequeue().Value;
                int watchTarget = args.Dequeue().Value;

                FSMPath path = fsmRunner.FSM.Paths[pathIndex];

                Vector3 nodePos = path.GetWorldPosition(0);
                nodePos.y = Utils.GroundHeightAtPoint(nodePos.x, nodePos.z) + height * 0.01f;
                camera.transform.position = nodePos;

                GameObject entity = fsmRunner.FSM.EntityTable[watchTarget].Object;
                camera.transform.LookAt(entity.transform, Vector3.up);
            }
            break;

            case "camObjObj":
            {
                if (CameraManager.Instance.IsMainCameraActive)
                {
                    break;
                }

                int   objectIndex = args.Dequeue().Value;
                float xPos        = args.Dequeue().Value;
                float yPos        = args.Dequeue().Value;
                float zPos        = args.Dequeue().Value;
                int   watchTarget = args.Dequeue().Value;

                FSMEntity anchorEntity = fsmRunner.FSM.EntityTable[objectIndex];
                FSMEntity targetEntity = fsmRunner.FSM.EntityTable[watchTarget];

                var camera = CameraManager.Instance.ActiveCamera;
                camera.transform.SetParent(anchorEntity.Object.transform);
                camera.transform.localPosition = new Vector3(xPos * 0.01f, zPos * 0.01f, yPos * 0.01f);
                camera.transform.LookAt(targetEntity.Object.transform, Vector3.up);
            }
            break;

            case "camTransObj":
            {
                if (CameraManager.Instance.IsMainCameraActive)
                {
                    break;
                }

                var   camera      = CameraManager.Instance.ActiveCamera;
                int   pathIndex   = args.Dequeue().Value;
                int   targetSpeed = args.Dequeue().Value;
                float height      = args.Dequeue().Value * 0.01f;

                FSMPath path = fsmRunner.FSM.Paths[pathIndex];

                if (args.Count == 0)
                {
                    Vector3 nodePos = path.GetWorldPosition(0);
                    nodePos.y = Utils.GroundHeightAtPoint(nodePos.x, nodePos.z) + height;
                    camera.transform.position = nodePos;
                    break;
                }

                int        watchTarget = args.Dequeue().Value;
                GameObject entity      = fsmRunner.FSM.EntityTable[watchTarget].Object;
                camera.transform.LookAt(entity.transform, Vector3.up);
                camera.SetTargetPath(path, targetSpeed, height);
            }
            break;

            case "camIsArrived":
            {
                if (CameraManager.Instance.IsMainCameraActive)
                {
                    break;
                }

                var camera = CameraManager.Instance.ActiveCamera;
                if (camera.Arrived)
                {
                    camera.Arrived = false;
                    return(1);
                }
                return(0);
            }

            case "goto":
            {
                int entityIndex = args.Dequeue().Value;
                int pathIndex   = args.Dequeue().Value;
                int targetSpeed = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];
                FSMPath   path   = fsmRunner.FSM.Paths[pathIndex];

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    car.SetTargetPath(path, targetSpeed);
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isWithinNav":
            {
                int pathIndex   = args.Dequeue().Value;
                int entityIndex = args.Dequeue().Value;
                int distance    = args.Dequeue().Value;

                FSMPath   path   = fsmRunner.FSM.Paths[pathIndex];
                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    bool within = car.IsWithinNav(path, distance);
                    return(within ? 1 : 0);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isWithinSqNav":
            {
                int pathIndex   = args.Dequeue().Value;
                int entityIndex = args.Dequeue().Value;
                int distance    = args.Dequeue().Value;

                FSMPath   path   = fsmRunner.FSM.Paths[pathIndex];
                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    bool within = car.IsWithinNav(path, (int)Mathf.Sqrt(distance));
                    return(within ? 1 : 0);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "follow":
            {
                int entityIndex = args.Dequeue().Value;
                int targetIndex = args.Dequeue().Value;
                int unk1        = args.Dequeue().Value;
                int unk2        = args.Dequeue().Value;
                int xOffset     = args.Dequeue().Value;
                int targetSpeed = args.Dequeue().Value;

                FSMEntity entity       = fsmRunner.FSM.EntityTable[entityIndex];
                FSMEntity targetEntity = fsmRunner.FSM.EntityTable[targetIndex];

                Car car       = entity.Object.GetComponent <Car>();
                Car targetCar = targetEntity.Object.GetComponent <Car>();
                if (car != null && targetCar != null)
                {
                    car.SetFollowTarget(targetCar, xOffset, targetSpeed);
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isAtFollow":
            {
                int       entityIndex = args.Dequeue().Value;
                FSMEntity entity      = fsmRunner.FSM.EntityTable[entityIndex];

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    bool atFollow = car.AtFollowTarget();
                    return(atFollow ? 1 : 0);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "teleport":
            {
                int entityIndex = args.Dequeue().Value;
                int pathIndex   = args.Dequeue().Value;
                int targetSpeed = args.Dequeue().Value;
                int height      = args.Dequeue().Value;

                FSMPath path = fsmRunner.FSM.Paths[pathIndex];

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];

                Vector3 nodePos = path.GetWorldPosition(0);
                nodePos.y = Utils.GroundHeightAtPoint(nodePos.x, nodePos.z) + height * 0.01f;
                entity.Object.transform.position = nodePos;

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    car.SetSpeed(targetSpeed);
                    car.SetTargetPath(path, targetSpeed);
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "teleportOffset":
            {
                int entityIndex = args.Dequeue().Value;
                int pathIndex   = args.Dequeue().Value;
                int targetSpeed = args.Dequeue().Value;
                int height      = args.Dequeue().Value;
                var offsetX     = args.Dequeue().Value;
                var offsetZ     = args.Dequeue().Value;

                FSMPath path = fsmRunner.FSM.Paths[pathIndex];

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];

                Vector3 nodePos = path.GetWorldPosition(0) + new Vector3(offsetX, 0, offsetZ);
                nodePos.y = Utils.GroundHeightAtPoint(nodePos.x, nodePos.z) + height * 0.01f;
                entity.Object.transform.position = nodePos;

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    car.SetSpeed(targetSpeed);
                    car.SetTargetPath(path, targetSpeed);
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isArrived":
            {
                int        entityIndex = args.Dequeue().Value;
                FSMEntity  origoEntity = fsmRunner.FSM.EntityTable[entityIndex];
                GameObject entity      = origoEntity.Object;

                Car car = entity.GetComponent <Car>();
                if (car != null)
                {
                    if (car.Arrived)
                    {
                        car.Arrived = false;
                        return(1);
                    }

                    return(0);
                }

                LogUnhandledEntity(actionName, entityIndex, origoEntity, machine);
            }
            break;

            case "sit":
            {
                int       entityIndex = args.Dequeue().Value;
                FSMEntity entity      = fsmRunner.FSM.EntityTable[entityIndex];

                Car car = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    car.Sit();
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "setAvoid":
            {
                int entityIndex = args.Dequeue().Value;
                int avoidIndex  = args.Dequeue().Value;

                FSMEntity entity      = fsmRunner.FSM.EntityTable[entityIndex];
                FSMEntity avoidEntity = fsmRunner.FSM.EntityTable[avoidIndex];

                Car         car    = entity.Object.GetComponent <Car>();
                WorldEntity target = avoidEntity.WorldEntity;
                if (car != null && target != null)
                {
                    // TODO: Figure out 'avoid' logic - don't path near object?
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "setMaxAttackers":
            {
                int entityIndex  = args.Dequeue().Value;
                int maxAttackers = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];

                if (entity.WorldEntity != null)
                {
                    entity.WorldEntity.MaxAttackers = maxAttackers;
                    break;
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "setSkill":
            {
                int entityIndex = args.Dequeue().Value;
                int skill1      = args.Dequeue().Value;
                int skill2      = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];
                Car       car    = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    car.Skill1 = skill1;
                    car.Skill2 = skill2;
                    return(0);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "setAgg":
            {
                int entityIndex     = args.Dequeue().Value;
                int aggressionValue = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];
                Car       car    = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    car.Aggressiveness = aggressionValue;
                    return(0);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isAttacked":
            {
                int entityIndex = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];
                Car       car    = entity.Object.GetComponent <Car>();
                if (car != null)
                {
                    return(car.Attacked ? 1 : 0);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isDead":
            {
                int entityIndex = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];
                if (entity.WorldEntity != null)
                {
                    return(entity.WorldEntity.Alive ? 0 : 1);
                }

                LogUnhandledEntity(actionName, entityIndex, entity, machine);
            }
            break;

            case "isWithin":
            {
                int entityIndex = args.Dequeue().Value;
                int targetIndex = args.Dequeue().Value;
                int distance    = args.Dequeue().Value;

                FSMEntity entity = fsmRunner.FSM.EntityTable[entityIndex];
                FSMEntity target = fsmRunner.FSM.EntityTable[targetIndex];

                bool within = Vector3.Distance(entity.Object.transform.position, target.Object.transform.position) < distance;
                return(within ? 1 : 0);
            }

            case "cbFromPrior":
            {
                int soundId   = args.Dequeue().Value;
                int owner     = args.Dequeue().Value;
                int queueFlag = args.Dequeue().Value;
                QueueRadio(fsmRunner, soundId, queueFlag, owner);
            }
            break;

            case "cbPrior":
            {
                int soundId   = args.Dequeue().Value;
                int queueFlag = args.Dequeue().Value;
                QueueRadio(fsmRunner, soundId, queueFlag, -1);
            }
            break;

            case "rand":
            {
                IntRef arg = args.Dequeue();
                IntRef val = args.Dequeue();
                arg.Value = Random.Range(0, val.Value);
            }
            break;

            case "stopCB":
                RadioManager.Instance.Stop();
                break;

            case "isCBEmpty":
            {
                return(RadioManager.Instance.IsQueueEmpty() ? 1 : 0);
            }

            case "startTimer":
                int timerIndex = args.Dequeue().Value;
                fsmRunner.Timers[timerIndex] = Time.unscaledTime;
                break;

            default:
                Debug.LogWarning("FSM action not implemented: " + actionName + " @ " + (machine.IP - 1));
                break;
            }

            return(0);
        }
示例#4
0
        private StepResult Step(StackMachine machine)
        {
            ByteCode byteCode = FSM.ByteCode[machine.IP++];

            switch (byteCode.OpCode)
            {
            case OpCode.PUSH:
                machine.Stack.Push(new IntRef(byteCode.Value));
                break;

            case OpCode.ARGPUSH_S:
                IntRef sVal = machine.Stack[byteCode.Value - 1];

                machine.ArgumentQueue.Enqueue(sVal);
                break;

            case OpCode.ARGPUSH_B:
                int    idx  = machine.Constants.Length + (byteCode.Value + 1);
                IntRef bVal = machine.Constants[idx];
                machine.ArgumentQueue.Enqueue(bVal);
                break;

            case OpCode.ADJUST:
                int addToSP = byteCode.Value;

                if (addToSP < 1)
                {
                    throw new NotImplementedException("What to do when adjusting 0 or negative values?");
                }

                for (int i = 0; i < addToSP; i++)
                {
                    machine.Stack.Push(new IntRef(0));
                }
                break;

            case OpCode.DROP:
                int subFromSP = byteCode.Value;

                if (subFromSP < 0)
                {
                    throw new NotImplementedException("Expecting positive values");
                }

                for (int i = 0; i < subFromSP; i++)
                {
                    machine.Stack.Pop();
                }
                break;

            case OpCode.JMP:
                machine.IP = (uint)byteCode.Value;
                break;

            case OpCode.JZ:
                if (machine.ResultReg == 0)
                {
                    machine.IP = (uint)byteCode.Value;
                }
                break;

            case OpCode.JMP_I:
                machine.IP = (uint)byteCode.Value;
                return(StepResult.DoNextMachine);

            case OpCode.RST:
                machine.Halted = true;
                return(StepResult.DoNextMachine);

            case OpCode.ACTION:
                string actionName = FSM.ActionTable[byteCode.Value];
                machine.ResultReg = _actionDelegator.DoAction(actionName, machine, this);
                machine.ArgumentQueue.Clear();
                break;

            case OpCode.NEG:
                if (machine.ResultReg == 1)
                {
                    machine.ResultReg = 0;
                }
                else
                {
                    machine.ResultReg = 1;
                }
                break;

            default:
                throw new NotImplementedException("Unimplemented bytecode " + byteCode.OpCode);
            }

            return(StepResult.NotDone);
        }