private void QueueRadio(FSMRunner fsmRunner, int soundId, int queueFlag, int owner) { bool endOfQueue; if (queueFlag == 1) { endOfQueue = false; } else if (queueFlag == 3) { endOfQueue = true; } else { endOfQueue = true; Debug.Log("Unknown value in cbPrior: " + queueFlag); } string soundName = fsmRunner.FSM.SoundClipTable[soundId]; RadioManager.Instance.QueueRadioMessage(soundName, endOfQueue, owner); }
public IEnumerator LoadLevel(string msnFilename) { _game.LevelName = msnFilename; string sceneName = SceneManager.GetActiveScene().name; if (sceneName != "Level") { AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(1, LoadSceneMode.Single); sceneLoad.allowSceneActivation = true; while (!sceneLoad.isDone) { yield return(null); } yield break; } Terrain[,] terrainPatches = new Terrain[80, 80]; MsnMissionParser.MissonDefinition mdef = MsnMissionParser.ReadMsnMission(msnFilename); _cacheManager.Palette = ActPaletteParser.ReadActPalette(mdef.PaletteFilePath); Texture2D surfaceTexture = TextureParser.ReadMapTexture(mdef.SurfaceTextureFilePath, _cacheManager.Palette, TextureFormat.RGB24, true, FilterMode.Point); GameObject.Find("Sky").GetComponent <Sky>().TextureFilename = mdef.SkyTextureFilePath; GameObject worldGameObject = GameObject.Find("World"); if (worldGameObject != null) { Object.Destroy(worldGameObject); } worldGameObject = new GameObject("World"); TerrainLayer[] terrainLayers = new[] { new TerrainLayer { diffuseTexture = surfaceTexture, tileSize = new Vector2(surfaceTexture.width, surfaceTexture.height) / 10.0f, metallic = 0, smoothness = 0 } }; for (int z = 0; z < 80; z++) { for (int x = 0; x < 80; x++) { if (mdef.TerrainPatches[x, z] == null) { continue; } GameObject patchGameObject = new GameObject("Ter " + x + ", " + z); patchGameObject.layer = LayerMask.NameToLayer("Terrain"); patchGameObject.transform.position = new Vector3(x * 640, 0, z * 640); patchGameObject.transform.parent = worldGameObject.transform; Terrain terrain = patchGameObject.AddComponent <Terrain>(); terrain.terrainData = mdef.TerrainPatches[x, z].TerrainData; terrain.terrainData.terrainLayers = terrainLayers; terrain.materialTemplate = _terrainMaterial; terrain.materialType = Terrain.MaterialType.Custom; TerrainCollider terrainCollider = patchGameObject.AddComponent <TerrainCollider>(); terrainCollider.terrainData = terrain.terrainData; foreach (MsnMissionParser.Odef odef in mdef.TerrainPatches[x, z].Objects) { GameObject go = null; if (odef.ClassId == MsnMissionParser.ClassId.Car) { string lblUpper = odef.Label.ToUpper(); // Training mission uses hardcoded VCF for player. string vcfName = odef.Label; if (msnFilename.ToLower() == "a01.msn" && vcfName == "vppirna1") { vcfName = "vppa01"; } switch (lblUpper) { case "SPAWN": go = Object.Instantiate(_spawnPrefab); go.tag = "Spawn"; break; case "REGEN": go = Object.Instantiate(_regenPrefab); go.tag = "Regen"; break; default: go = _cacheManager.ImportVcf(vcfName + ".vcf", odef.IsPlayer, out _); Car car = go.GetComponent <Car>(); car.TeamId = odef.TeamId; car.IsPlayer = odef.IsPlayer; break; } go.transform.parent = patchGameObject.transform; go.transform.localPosition = odef.LocalPosition; go.transform.localRotation = odef.LocalRotation; if (odef.IsPlayer) { CameraManager.Instance.MainCamera.GetComponent <SmoothFollow>().Target = go.transform; go.AddComponent <CarInput>(); } } else if (odef.ClassId != MsnMissionParser.ClassId.Special) { bool canWreck = odef.ClassId == MsnMissionParser.ClassId.Struct1 || odef.ClassId == MsnMissionParser.ClassId.Ramp || odef.ClassId == MsnMissionParser.ClassId.Struct2; go = _cacheManager.ImportSdf(odef.Label + ".sdf", patchGameObject.transform, odef.LocalPosition, odef.LocalRotation, canWreck, out Sdf sdf, out GameObject wreckedPart); if (odef.ClassId == MsnMissionParser.ClassId.Sign) { go.AddComponent <Sign>(); } else if (canWreck) { Building building = go.AddComponent <Building>(); building.Initialise(sdf, wreckedPart); } } if (go != null) { go.name = odef.Label + "_" + odef.Id; if (mdef.FSM != null) { FSMEntity[] entities = mdef.FSM.EntityTable; for (int i = 0; i < entities.Length; ++i) { if (entities[i].Value == odef.Label && entities[i].Id == odef.Id) { WorldEntity worldEntity = go.GetComponent <WorldEntity>(); if (worldEntity != null) { entities[i].WorldEntity = worldEntity; worldEntity.Id = i; } entities[i].Object = go; break; } } } } } terrainPatches[x, z] = terrain; } } RoadManager roadManager = RoadManager.Instance; foreach (MsnMissionParser.Road road in mdef.Roads) { roadManager.CreateRoadObject(road, mdef.Middle * 640); } foreach (MsnMissionParser.Ldef ldef in mdef.StringObjects) { GameObject sdfObj = _cacheManager.ImportSdf(ldef.Label + ".sdf", null, Vector3.zero, Quaternion.identity, false, out _, out _); for (int i = 0; i < ldef.StringPositions.Length; i++) { Vector3 pos = ldef.StringPositions[i]; Vector3 localPosition = new Vector3(pos.x % 640, pos.y, pos.z % 640); int patchPosX = (int)(pos.x / 640.0f); int patchPosZ = (int)(pos.z / 640.0f); sdfObj.name = ldef.Label + " " + i; sdfObj.transform.parent = terrainPatches[patchPosX, patchPosZ].transform; sdfObj.transform.localPosition = localPosition; if (i < ldef.StringPositions.Length - 1) { sdfObj.transform.LookAt(ldef.StringPositions[i + 1], Vector3.up); } else { sdfObj.transform.LookAt(ldef.StringPositions[i - 1], Vector3.up); sdfObj.transform.localRotation *= Quaternion.AngleAxis(180, Vector3.up); } if (i < ldef.StringPositions.Length - 1) { sdfObj = Object.Instantiate(sdfObj); } } } worldGameObject.transform.position = new Vector3(-mdef.Middle.x * 640, 0, -mdef.Middle.y * 640); Object.FindObjectOfType <Light>().color = _cacheManager.Palette[176]; UnityEngine.Camera.main.backgroundColor = _cacheManager.Palette[239]; RenderSettings.fogColor = _cacheManager.Palette[239]; RenderSettings.ambientLight = _cacheManager.Palette[247]; List <Car> cars = EntityManager.Instance.Cars; foreach (Car car in cars) { car.transform.parent = null; } if (mdef.FSM != null) { foreach (StackMachine machine in mdef.FSM.StackMachines) { machine.Reset(); machine.Constants = new IntRef[machine.InitialArguments.Length]; for (int i = 0; i < machine.Constants.Length; i++) { int stackValue = machine.InitialArguments[i]; machine.Constants[i] = mdef.FSM.Constants[stackValue]; } } FSMRunner fsmRunner = FSMRunner.Instance; fsmRunner.FSM = mdef.FSM; } }
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); }