protected override void Setup() { dfUnity = DaggerfallUnity.Instance; // Load native texture nativeTexture = DaggerfallUI.GetTextureFromImg(nativeImgName); if (!nativeTexture) throw new Exception("DaggerfallBookReaderWindow: Could not load native texture."); // Setup native panel background NativePanel.BackgroundTexture = nativeTexture; // Load default pixel font ChangeFont(4); // Add buttons DaggerfallUI.AddButton(new Vector2(181, 188), new Vector2(14, 8), DaggerfallUIMessages.dfuiBookReaderPreviousPage, NativePanel); DaggerfallUI.AddButton(new Vector2(208, 188), new Vector2(14, 8), DaggerfallUIMessages.dfuiBookReaderNextPage, NativePanel); //CreateButton(new Vector2(277, 187), new Vector2(32, 10), WindowMessages.wmCloseWindow); // Test book dfUnity.TextProvider.OpenBook("BOK00043.TXT"); // The Real Barenziah //dfUnity.TextProvider.OpenBook("BOK00101.TXT"); // Kind Edward, Part 2 //dfUnity.TextProvider.OpenBook("BOK00008.TXT"); // The Pig Children LayoutPage(); }
private bool ReadyCheck() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; // Must have a light component if (!myLight) return false; // Do nothing if DaggerfallUnity not ready if (!dfUnity.IsReady) { DaggerfallUnity.LogMessage("SunlightManager: DaggerfallUnity component is not ready. Have you set your Arena2 path?"); return false; } return true; }
void Awake() { dfUnity = DaggerfallUnity.Instance; audioSource = GetComponent<AudioSource>(); audioSource.spatialBlend = 0; dfAudioSource = GetComponent<DaggerfallAudioSource>(); dfPauseOptionsWindow = new DaggerfallPauseOptionsWindow(uiManager); dfPauseOptionsWindow.OnClose += PauseOptionsDialog_OnClose; dfCharacterSheetWindow = new DaggerfallCharacterSheetWindow(uiManager); dfCharacterSheetWindow.OnClose += CharacterSheetWindow_OnClose; dfInventoryWindow = new DaggerfallInventoryWindow(uiManager); dfInventoryWindow.OnClose += InventoryWindow_OnClose; dfTravelMapWindow = new DaggerfallTravelMapWindow(uiManager); SetupSingleton(); PostMessage(startupMessage); }
void Start() { dfUnity = DaggerfallUnity.Instance; dfAudioSource = GetComponent <DaggerfallAudioSource>(); StartCoroutine(AnimateWeapon()); }
void Start() { dfUnity = DaggerfallUnity.Instance; mainCamera = GameObject.FindGameObjectWithTag("MainCamera"); playerGPS = GetComponent<PlayerGPS>(); }
void Start() { dfUnity = DaggerfallUnity.Instance; playerEnterExit = GetComponent <PlayerEnterExit>(); }
private void UpdateWeapon() { // Do nothing if weapon not ready if (weaponAtlas == null || weaponAnims == null || weaponRects == null || weaponIndices == null) { return; } // Reset state if weapon not visible if (!ShowWeapon || WeaponType == WeaponTypes.None) { weaponState = WeaponStates.Idle; currentFrame = 0; } // Handle bow with no arrows if (!GameManager.Instance.WeaponManager.Sheathed && WeaponType == WeaponTypes.Bow && GameManager.Instance.PlayerEntity.Items.GetItem(Items.ItemGroups.Weapons, (int)Items.Weapons.Arrow) == null) { GameManager.Instance.WeaponManager.SheathWeapons(); DaggerfallUI.SetMidScreenText(UserInterfaceWindows.HardStrings.youHaveNoArrows); } // Store rect and anim int weaponAnimRecordIndex; if (WeaponType == WeaponTypes.Bow) { weaponAnimRecordIndex = 0; // Bow has only 1 animation } else { weaponAnimRecordIndex = (int)weaponState; } try { bool isImported = customTextures.TryGetValue(MaterialReader.MakeTextureKey(0, (byte)weaponState, (byte)currentFrame), out curCustomTexture); if (FlipHorizontal && (weaponState == WeaponStates.Idle || weaponState == WeaponStates.StrikeDown || weaponState == WeaponStates.StrikeUp)) { // Mirror weapon rect if (isImported) { curAnimRect = new Rect(0, 1, -1, 1); } else { Rect rect = weaponRects[weaponIndices[weaponAnimRecordIndex].startIndex + currentFrame]; curAnimRect = new Rect(rect.xMax, rect.yMin, -rect.width, rect.height); } } else { curAnimRect = isImported ? new Rect(0, 0, 1, 1) : weaponRects[weaponIndices[weaponAnimRecordIndex].startIndex + currentFrame]; } WeaponAnimation anim = weaponAnims[(int)weaponState]; // Get weapon dimensions int width = weaponIndices[weaponAnimRecordIndex].width; int height = weaponIndices[weaponAnimRecordIndex].height; // Get weapon scale weaponScaleX = (float)Screen.width / (float)nativeScreenWidth; weaponScaleY = (float)Screen.height / (float)nativeScreenHeight; // Adjust scale to be slightly larger when not using point filtering // This reduces the effect of filter shrink at edge of display if (dfUnity.MaterialReader.MainFilterMode != FilterMode.Point) { weaponScaleX *= 1.01f; weaponScaleY *= 1.01f; } // Source weapon images are designed to overlay a fixed 320x200 display. // Some weapons need to align with both top, bottom, and right of display. // This means they might be a little stretched on widescreen displays. switch (anim.Alignment) { case WeaponAlignment.Left: AlignLeft(anim, width, height); break; case WeaponAlignment.Center: AlignCenter(anim, width, height); break; case WeaponAlignment.Right: AlignRight(anim, width, height); break; } } catch (IndexOutOfRangeException) { DaggerfallUnity.LogMessage("Index out of range exception for weapon animation. Probably due to weapon breaking + being unequipped during animation."); } }
private static void AddProps( DaggerfallUnity dfUnity, ref DFBlock blockData, out List<StaticDoor> doorsOut, ModelCombiner combiner = null, Transform parent = null) { doorsOut = new List<StaticDoor>(); // Iterate through all misc records foreach (DFBlock.RmbBlock3dObjectRecord obj in blockData.RmbBlock.Misc3dObjectRecords) { // Get model transform Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos + propsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one); // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData); // Does this model have doors? if (modelData.Doors != null) doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix)); // Add or combine if (combiner == null) AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent); else combiner.Add(ref modelData, modelMatrix); } }
public static Material[] SetBaseMeshTextures(int[] textureKeys) { Material[] materials = new Material[1]; if (textureKeys.Length == 0) { Debug.Log("SetBaseMeshTextures - Texturekeys length is zero"); return(materials); } DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { Debug.Log("SetBaseMeshTextures - dfUnity isn't ready"); return(materials); } // Get new material array int archive, record, frame; materials = new Material[defaultTextures.Count]; int climateIndex = 0; for (int i = 0; i < defaultTextures.Count; i++) { MaterialReader.ReverseTextureKey(defaultTextures[i], out archive, out record, out frame); switch (archive) { case 119: archive = textureKeys[0]; break; case 120: archive = textureKeys[1]; break; case 122: archive = textureKeys[2]; break; case 123: archive = textureKeys[3]; break; case 124: archive = textureKeys[4]; break; case 168: archive = textureKeys[5]; break; case 74: archive += climateIndex; break; } materials[i] = dfUnity.MaterialReader.GetMaterial(archive, record); } return(materials); }
void Awake() { dfUnity = DaggerfallUnity.Instance; playerGPS = GetComponent <PlayerGPS>(); world = FindObjectOfType <StreamingWorld>(); }
public override void GenerateSamples(ref MapPixelData mapPixel) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Create samples arrays mapPixel.tilemapSamples = new TilemapSample[MapsFile.WorldMapTileDim, MapsFile.WorldMapTileDim]; mapPixel.heightmapSamples = new float[HeightmapDimension, HeightmapDimension]; // Divisor ensures continuous 0-1 range of tile samples float div = (float)(HeightmapDimension - 1) / 3f; // Read neighbouring height samples for this map pixel int mx = mapPixel.mapPixelX; int my = mapPixel.mapPixelY; byte[,] shm = dfUnity.ContentReader.WoodsFileReader.GetHeightMapValuesRange(mx - 2, my - 2, 4); byte[,] lhm = dfUnity.ContentReader.WoodsFileReader.GetLargeHeightMapValuesRange(mx - 1, my, 3); float[,] multiplierValue = new float[4, 4]; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { int mapPixelX = Math.Max(0, Math.Min(mx + x - 2, WoodsFile.mapWidthValue)); int mapPixelY = Math.Max(0, Math.Min(my + y - 2, WoodsFile.mapHeightValue)); multiplierValue[x, y] = ImprovedWorldTerrain.computeHeightMultiplier(mapPixelX, mapPixelY); } } // Extract height samples for all chunks float averageHeight = 0; float maxHeight = float.MinValue; float baseHeight, noiseHeight; float x1, x2, x3, x4; int dim = HeightmapDimension; //mapPixel.heightmapSamples = new float[dim, dim]; for (int y = 0; y < dim; y++) { for (int x = 0; x < dim; x++) { float rx = (float)x / div; float ry = (float)y / div; int ix = Mathf.FloorToInt(rx); int iy = Mathf.FloorToInt(ry); float sfracx = (float)x / (float)(dim - 1); float sfracy = (float)y / (float)(dim - 1); float fracx = (float)(x - ix * div) / div; float fracy = (float)(y - iy * div) / div; float scaledHeight = 0; // Bicubic sample small height map for base terrain elevation x1 = TerrainHelper.CubicInterpolator(shm[0, 3] * multiplierValue[0, 3], shm[1, 3] * multiplierValue[1, 3], shm[2, 3] * multiplierValue[2, 3], shm[3, 3] * multiplierValue[3, 3], sfracx); x2 = TerrainHelper.CubicInterpolator(shm[0, 2] * multiplierValue[0, 2], shm[1, 2] * multiplierValue[1, 2], shm[2, 2] * multiplierValue[2, 2], shm[3, 2] * multiplierValue[3, 2], sfracx); x3 = TerrainHelper.CubicInterpolator(shm[0, 1] * multiplierValue[0, 1], shm[1, 1] * multiplierValue[1, 1], shm[2, 1] * multiplierValue[2, 1], shm[3, 1] * multiplierValue[3, 1], sfracx); x4 = TerrainHelper.CubicInterpolator(shm[0, 0] * multiplierValue[0, 0], shm[1, 0] * multiplierValue[1, 0], shm[2, 0] * multiplierValue[2, 0], shm[3, 0] * multiplierValue[3, 0], sfracx); baseHeight = TerrainHelper.CubicInterpolator(x1, x2, x3, x4, sfracy); scaledHeight += baseHeight * baseHeightScale; // Bicubic sample large height map for noise mask over terrain features x1 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 0], lhm[ix + 1, iy + 0], lhm[ix + 2, iy + 0], lhm[ix + 3, iy + 0], fracx); x2 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 1], lhm[ix + 1, iy + 1], lhm[ix + 2, iy + 1], lhm[ix + 3, iy + 1], fracx); x3 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 2], lhm[ix + 1, iy + 2], lhm[ix + 2, iy + 2], lhm[ix + 3, iy + 2], fracx); x4 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 3], lhm[ix + 1, iy + 3], lhm[ix + 2, iy + 3], lhm[ix + 3, iy + 3], fracx); noiseHeight = TerrainHelper.CubicInterpolator(x1, x2, x3, x4, fracy); scaledHeight += noiseHeight * noiseMapScale; // Additional noise mask for small terrain features at ground level int noisex = mapPixel.mapPixelX * (HeightmapDimension - 1) + x; int noisey = (MapsFile.MaxMapPixelY - mapPixel.mapPixelY) * (HeightmapDimension - 1) + y; float lowFreq = TerrainHelper.GetNoise(noisex, noisey, 0.3f, 0.5f, 0.5f, 1); float highFreq = TerrainHelper.GetNoise(noisex, noisey, 0.9f, 0.5f, 0.5f, 1); scaledHeight += (lowFreq * highFreq) * extraNoiseScale; // Clamp lower values to ocean elevation if (scaledHeight < scaledOceanElevation) { scaledHeight = scaledOceanElevation; } // Accumulate average height averageHeight += scaledHeight; // Get max height if (scaledHeight > maxHeight) { maxHeight = scaledHeight; } // Set sample float height = Mathf.Clamp01(scaledHeight / MaxTerrainHeight); mapPixel.heightmapSamples[y, x] = height; } } // Average and max heights are passed back for locations mapPixel.averageHeight = (averageHeight /= (float)(dim * dim)) / MaxTerrainHeight; mapPixel.maxHeight = maxHeight / MaxTerrainHeight; }
/// <summary> /// Reads any Daggerfall image file to ImageData package. /// </summary> /// <param name="filename">Name of standalone file as it appears in arena2 folder.</param> /// <param name="record">Which image record to read for multi-image files.</param> /// <param name="frame">Which frame to read for multi-frame images.</param> /// <param name="hasAlpha">Enable this for image cutouts.</param> /// <param name="createTexture">Create a Texture2D.</param> /// <returns>ImageData. If result.type == ImageTypes.None then read failed.</returns> public static ImageData GetImageData(string filename, int record = 0, int frame = 0, bool hasAlpha = false, bool createTexture = true) { // Check API ready DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(new ImageData()); } // Parse image file type ImageTypes fileType; try { fileType = ParseFileType(filename); } catch { return(new ImageData()); } // Create base image data ImageData imageData = new ImageData(); imageData.type = fileType; imageData.filename = filename; imageData.record = record; imageData.frame = frame; imageData.hasAlpha = hasAlpha; // Read supported image files DFBitmap dfBitmap = null; switch (fileType) { case ImageTypes.TEXTURE: TextureFile textureFile = new TextureFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); textureFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, textureFile.PaletteName)); dfBitmap = textureFile.GetDFBitmap(record, frame); imageData.offset = textureFile.GetOffset(record); imageData.scale = textureFile.GetScale(record); imageData.size = textureFile.GetSize(record); break; case ImageTypes.IMG: ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName)); dfBitmap = imgFile.GetDFBitmap(); imageData.offset = imgFile.ImageOffset; imageData.scale = new DFSize(); imageData.size = imgFile.GetSize(0); // texture pack support if ((AssetInjection.TextureReplacement.CustomImageExist(filename)) && (createTexture)) { imageData.texture = AssetInjection.TextureReplacement.LoadCustomImage(filename); createTexture = false; } break; case ImageTypes.CIF: case ImageTypes.RCI: CifRciFile cifFile = new CifRciFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); cifFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, cifFile.PaletteName)); dfBitmap = cifFile.GetDFBitmap(record, frame); imageData.offset = cifFile.GetOffset(record); imageData.scale = new DFSize(); imageData.size = cifFile.GetSize(record); // texture pack support if ((AssetInjection.TextureReplacement.CustomCifExist(filename, record, frame)) && (createTexture)) { imageData.texture = AssetInjection.TextureReplacement.LoadCustomCif(filename, record, frame); createTexture = false; } break; default: return(new ImageData()); } // Store bitmap imageData.dfBitmap = dfBitmap; imageData.width = dfBitmap.Width; imageData.height = dfBitmap.Height; // Create Texture2D if (createTexture) { // Get colors array Color32[] colors = GetColors(imageData); if (colors == null) { return(new ImageData()); } // Create new Texture2D imageData.texture = GetTexture(colors, imageData.width, imageData.height); } return(imageData); }
/// <summary> /// Assigns player entity settings from a character document. /// </summary> public void AssignCharacter(CharacterDocument character, int level = 1, int maxHealth = 0, bool fillVitals = true) { if (character == null) { SetEntityDefaults(); return; } this.level = level; this.gender = character.gender; this.raceTemplate = character.raceTemplate; this.career = character.career; this.name = character.name; this.faceIndex = character.faceIndex; this.stats = character.workingStats; this.skills = character.workingSkills; this.reflexes = character.reflexes; this.maxHealth = character.maxHealth; this.currentHealth = character.currentHealth; this.currentMagicka = character.currentSpellPoints; this.sGroupReputations[0] = character.reputationCommoners; this.sGroupReputations[1] = character.reputationMerchants; this.sGroupReputations[2] = character.reputationNobility; this.sGroupReputations[3] = character.reputationScholars; this.sGroupReputations[4] = character.reputationUnderworld; this.currentFatigue = character.currentFatigue; this.skillUses = character.skillUses; this.startingLevelUpSkillSum = character.startingLevelUpSkillSum; this.minMetalToHit = (WeaponMaterialTypes)character.minMetalToHit; this.armorValues = character.armorValues; this.timeOfLastSkillTraining = character.lastTimePlayerBoughtTraining; this.timeForThievesGuildLetter = character.timeForThievesGuildLetter; this.timeForDarkBrotherhoodLetter = character.timeForDarkBrotherhoodLetter; this.darkBrotherhoodRequirementTally = character.darkBrotherhoodRequirementTally; this.thievesGuildRequirementTally = character.thievesGuildRequirementTally; SetCurrentLevelUpSkillSum(); if (startingLevelUpSkillSum <= 0) // new character { startingLevelUpSkillSum = currentLevelUpSkillSum; } if (maxHealth <= 0) { this.maxHealth = FormulaHelper.RollMaxHealth(level, career.HitPointsPerLevel); } else { this.maxHealth = maxHealth; } if (fillVitals) { FillVitalSigns(); } timeOfLastSkillIncreaseCheck = DaggerfallUnity.Instance.WorldTime.Now.ToClassicDaggerfallTime(); DaggerfallUnity.LogMessage("Assigned character " + this.name, true); }
/// <summary> /// Register a custom UI Window implementation class. Overwrites the previous class type. /// </summary> /// <param name="windowType">The type of ui window to be replaced</param> /// <param name="windowClassType">The c# class Type of the implementation class to replace with</param> public static void RegisterCustomUIWindow(UIWindowType windowType, Type windowClassType) { DaggerfallUnity.LogMessage("RegisterCustomUIWindow: " + windowType, true); uiWindowImplementations[windowType] = windowClassType; DaggerfallUI.Instance.ReinstantiatePersistentWindowInstances(); }
void Start() { dfUnity = DaggerfallUnity.Instance; }
void Start() { _dfUnity = DaggerfallUnity.Instance; _weatherTable = WeatherTable.ParseJsonTable(); }
void Start() { dfUnity = DaggerfallUnity.Instance; playerEnterExit = GetComponent<PlayerEnterExit>(); }
void Start() { // Store references dfUnity = DaggerfallUnity.Instance; dfAudioSource = GetComponent<DaggerfallAudioSource>(); playerMotor = GetComponent<PlayerMotor>(); playerEnterExit = GetComponent<PlayerEnterExit>(); // Add our own custom audio source at runtime as we need to change the pitch of footsteps. // We don't want that affecting to other sounds on this game object. customAudioSource = gameObject.AddComponent<AudioSource>(); customAudioSource.hideFlags = HideFlags.HideInInspector; customAudioSource.playOnAwake = false; customAudioSource.loop = false; customAudioSource.dopplerLevel = 0f; customAudioSource.spatialBlend = 0f; // Set start position lastPosition = GetHorizontalPosition(); // Set starting footsteps currentFootstepSound = FootstepSoundNormal; }
private static void AddLight(DaggerfallUnity dfUnity, DFBlock.RmbBlockFlatObjectRecord obj, Transform parent = null) { if (dfUnity.Option_CityLightPrefab == null) return; Vector2 size = dfUnity.MeshReader.GetScaledBillboardSize(210, obj.TextureRecord); Vector3 position = new Vector3( obj.XPos, -obj.YPos + size.y, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; GameObjectHelper.InstantiatePrefab(dfUnity.Option_CityLightPrefab.gameObject, string.Empty, parent, position); }
/// <summary> /// Adds models and their actions to scene. /// </summary> private static void AddModels( DaggerfallUnity dfUnity, ref DFBlock blockData, Dictionary<int, ActionLink> actionLinkDict, int[] textureTable, bool allowExitDoors, out List<StaticDoor> exitDoorsOut, bool serialize, ModelCombiner combiner = null, Transform modelsParent = null, Transform actionModelsParent = null) { exitDoorsOut = new List<StaticDoor>(); // Iterate object groups foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList) { // Skip empty object groups if (null == group.RdbObjects) { continue; } // Iterate objects in this group foreach (DFBlock.RdbObject obj in group.RdbObjects) { // Add models if (obj.Type == DFBlock.RdbResourceTypes.Model) { // Get model reference index and id int modelReference = obj.Resources.ModelResource.ModelIndex; uint modelId = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum; // Filter exit door models where flag not set if (modelId == exitDoorModelID && !allowExitDoors) continue; // Filter action door models // These must be added by AddActionDoors() if (IsActionDoor(ref blockData, obj, modelReference)) continue; // Get matrix Matrix4x4 modelMatrix = GetModelMatrix(obj); // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(modelId, out modelData); // Add to static doors exitDoorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix)); // Check if model has an action record bool hasAction = HasAction(obj); // Special handling for tapestries and banners // Some of these are so far out from wall player can become stuck behind them // Adding model invidually without collider to avoid problem // Not sure if these object ever actions, but bypass this hack if they do if (modelId >= minTapestryID && modelId <= maxTapestryID && !hasAction) { AddStandaloneModel(dfUnity, ref modelData, modelMatrix, modelsParent, hasAction, true); continue; } // Add or combine GameObject standaloneObject = null; Transform parent = (hasAction) ? actionModelsParent : modelsParent; if (combiner == null || hasAction) { standaloneObject = AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent, hasAction); standaloneObject.GetComponent<DaggerfallMesh>().SetDungeonTextures(textureTable); } else { combiner.Add(ref modelData, modelMatrix); } // Add action if (hasAction && standaloneObject != null) AddActionModelHelper(standaloneObject, actionLinkDict, obj, ref blockData, serialize); } } } }
void Start() { dfUnity = DaggerfallUnity.Instance; SetSunlightScale(); }
private void GetBuildingList() { listBuildings = new List <BuildingInfo>(); ContentReader.MapSummary mapSummary; DFPosition mapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; if (!DaggerfallUnity.Instance.ContentReader.HasLocation(mapPixel.X, mapPixel.Y, out mapSummary)) { // no location found return; // do nothing } DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex); if (!location.Loaded) { // Location not loaded, something went wrong DaggerfallUnity.LogMessage("error when loading location for in TalkManager.GetBuildingList", true); } DaggerfallExteriorAutomap.BlockLayout[] blockLayout = GameManager.Instance.ExteriorAutomap.ExteriorLayout; DFBlock[] blocks; RMBLayout.GetLocationBuildingData(location, out blocks); int width = location.Exterior.ExteriorData.Width; int height = location.Exterior.ExteriorData.Height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * width + x; BuildingSummary[] buildingsInBlock = RMBLayout.GetBuildingData(blocks[index], x, y); foreach (BuildingSummary buildingSummary in buildingsInBlock) { try { string locationName = BuildingNames.GetName(buildingSummary.NameSeed, buildingSummary.BuildingType, buildingSummary.FactionId, location.Name, location.RegionName); BuildingInfo item; item.buildingType = buildingSummary.BuildingType; item.name = locationName; item.buildingKey = buildingSummary.buildingKey; // compute building position in map coordinate system float xPosBuilding = blockLayout[index].rect.xpos + (int)(buildingSummary.Position.x / (BlocksFile.RMBDimension * MeshReader.GlobalScale) * DaggerfallExteriorAutomap.blockSizeWidth) - GameManager.Instance.ExteriorAutomap.LocationWidth * DaggerfallExteriorAutomap.blockSizeWidth * 0.5f; float yPosBuilding = blockLayout[index].rect.ypos + (int)(buildingSummary.Position.z / (BlocksFile.RMBDimension * MeshReader.GlobalScale) * DaggerfallExteriorAutomap.blockSizeHeight) - GameManager.Instance.ExteriorAutomap.LocationHeight * DaggerfallExteriorAutomap.blockSizeHeight * 0.5f; item.position = new Vector2(xPosBuilding, yPosBuilding); listBuildings.Add(item); } catch (Exception e) { string exceptionMessage = String.Format("exception occured in function BuildingNames.GetName (exception message: " + e.Message + @") with params: seed: {0}, type: {1}, factionID: {2}, locationName: {3}, regionName: {4}", buildingSummary.NameSeed, buildingSummary.BuildingType, buildingSummary.FactionId, location.Name, location.RegionName); DaggerfallUnity.LogMessage(exceptionMessage, true); } } } } }
/// <summary> /// Adds action door to scene. /// </summary> private static GameObject AddActionDoor(DaggerfallUnity dfUnity, uint modelId, DFBlock.RdbObject obj, Transform parent, long loadID = 0) { if (dfUnity.Option_DungeonDoorPrefab == null) return null; // Get model data and matrix ModelData modelData; dfUnity.MeshReader.GetModelData(modelId, out modelData); Matrix4x4 modelMatrix = GetModelMatrix(obj); // Instantiate door prefab and add model GameObject go = GameObjectHelper.InstantiatePrefab(dfUnity.Option_DungeonDoorPrefab.gameObject, string.Empty, parent, Vector3.zero); GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, parent, false, go, true); // Resize box collider to new mesh bounds BoxCollider boxCollider = go.GetComponent<BoxCollider>(); MeshRenderer meshRenderer = go.GetComponent<MeshRenderer>(); if (boxCollider != null && meshRenderer != null) { boxCollider.center = meshRenderer.bounds.center; boxCollider.size = meshRenderer.bounds.size; } // Get rotation angle for each axis float degreesX = -obj.Resources.ModelResource.XRotation / BlocksFile.RotationDivisor; float degreesY = -obj.Resources.ModelResource.YRotation / BlocksFile.RotationDivisor; float degreesZ = -obj.Resources.ModelResource.ZRotation / BlocksFile.RotationDivisor; // Apply transforms go.transform.Rotate(0, degreesY, 0, Space.World); go.transform.Rotate(degreesX, 0, 0, Space.World); go.transform.Rotate(0, 0, degreesZ, Space.World); go.transform.localPosition = modelMatrix.GetColumn(3); // Get action door script DaggerfallActionDoor actionDoor = go.GetComponent<DaggerfallActionDoor>(); // Set starting lock value if (obj.Resources.ModelResource.TriggerFlag_StartingLock >= 16) { actionDoor.StartingLockValue = (int)obj.Resources.ModelResource.TriggerFlag_StartingLock; } // Set LoadID actionDoor.LoadID = loadID; return go; }
/// <summary> /// Sets up enemy based on current settings. /// </summary> public void ApplyEnemySettings(MobileGender gender) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; Dictionary <int, MobileEnemy> enemyDict = GameObjectHelper.EnemyDict; MobileEnemy mobileEnemy = enemyDict[(int)EnemyType]; if (AlliedToPlayer) { mobileEnemy.Team = MobileTeams.PlayerAlly; } // Find mobile unit in children DaggerfallMobileUnit dfMobile = GetMobileBillboardChild(); if (dfMobile != null) { // Setup mobile billboard Vector2 size = Vector2.one; mobileEnemy.Gender = gender; dfMobile.SetEnemy(dfUnity, mobileEnemy, EnemyReaction, ClassicSpawnDistanceType); // Setup controller CharacterController controller = GetComponent <CharacterController>(); if (controller) { // Set base height from sprite size = dfMobile.Summary.RecordSizes[0]; controller.height = size.y; // Reduce height of flying creatures as their wing animation makes them taller than desired // This helps them get through doors while aiming for player eye height if (dfMobile.Summary.Enemy.Behaviour == MobileBehaviour.Flying) { // (in frame 0 wings are in high position, assume body is the lower half) AdjustControllerHeight(controller, controller.height / 2, ControllerJustification.BOTTOM); } // Limit minimum controller height // Stops very short characters like rats from being walked upon if (controller.height < 1.6f) { AdjustControllerHeight(controller, 1.6f, ControllerJustification.BOTTOM); } controller.gameObject.layer = LayerMask.NameToLayer("Enemies"); } // Setup sounds EnemySounds enemySounds = GetComponent <Game.EnemySounds>(); if (enemySounds) { enemySounds.MoveSound = (SoundClips)dfMobile.Summary.Enemy.MoveSound; enemySounds.BarkSound = (SoundClips)dfMobile.Summary.Enemy.BarkSound; enemySounds.AttackSound = (SoundClips)dfMobile.Summary.Enemy.AttackSound; } MeshRenderer meshRenderer = dfMobile.GetComponent <MeshRenderer>(); if (meshRenderer) { if (dfMobile.Summary.Enemy.NoShadow) { meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; } if (dfMobile.Summary.Enemy.GlowColor != null) { meshRenderer.receiveShadows = false; GameObject enemyLightGameObject = Instantiate(LightAura); enemyLightGameObject.transform.parent = dfMobile.transform; enemyLightGameObject.transform.localPosition = new Vector3(0, 0.3f, 0.2f); Light enemyLight = enemyLightGameObject.GetComponent <Light>(); enemyLight.color = (Color)dfMobile.Summary.Enemy.GlowColor; enemyLight.shadows = DaggerfallUnity.Settings.DungeonLightShadows ? LightShadows.Soft : LightShadows.None; } } // Setup entity if (entityBehaviour) { EnemyEntity entity = new EnemyEntity(entityBehaviour); entityBehaviour.Entity = entity; // Enemies are initially added to same world context as player entity.WorldContext = GameManager.Instance.PlayerEnterExit.WorldContext; int enemyIndex = (int)EnemyType; if (enemyIndex >= 0 && enemyIndex <= 42) { entityBehaviour.EntityType = EntityTypes.EnemyMonster; entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType); } else if (enemyIndex >= 128 && enemyIndex <= 146) { entityBehaviour.EntityType = EntityTypes.EnemyClass; entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType); } else { entityBehaviour.EntityType = EntityTypes.None; } } } }
/// <summary> /// Adds a single DaggerfallMesh game object to scene. /// </summary> /// <param name="modelID">ModelID of mesh to add.</param> /// <param name="parent">Optional parent of this object.</param> /// <param name="makeStatic">Flag to set object static flag.</param> /// <param name="useExistingObject">Add mesh to existing object rather than create new.</param> /// <param name="ignoreCollider">Force disable collider.</param> /// <returns>GameObject.</returns> public static GameObject CreateDaggerfallMeshGameObject( uint modelID, Transform parent, bool makeStatic = false, GameObject useExistingObject = null, bool ignoreCollider = false) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Create gameobject string name = string.Format("DaggerfallMesh [ID={0}]", modelID); GameObject go = (useExistingObject != null) ? useExistingObject : new GameObject(); if (parent != null) { go.transform.parent = parent; } go.name = name; // Add DaggerfallMesh component DaggerfallMesh dfMesh = go.GetComponent <DaggerfallMesh>(); if (dfMesh == null) { dfMesh = go.AddComponent <DaggerfallMesh>(); } // Get mesh filter and renderer components MeshFilter meshFilter = go.GetComponent <MeshFilter>(); MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>(); // Assign mesh and materials CachedMaterial[] cachedMaterials; int[] textureKeys; bool hasAnimations; Mesh mesh = dfUnity.MeshReader.GetMesh( dfUnity, modelID, out cachedMaterials, out textureKeys, out hasAnimations, dfUnity.MeshReader.AddMeshTangents, dfUnity.MeshReader.AddMeshLightmapUVs); // Assign animated materials component if required if (hasAnimations) { AssignAnimatedMaterialComponent(cachedMaterials, go); } // Assign mesh and materials if (mesh) { meshFilter.sharedMesh = mesh; meshRenderer.sharedMaterials = GetMaterialArray(cachedMaterials); dfMesh.SetDefaultTextures(textureKeys); } // Assign mesh to collider if (dfUnity.Option_AddMeshColliders && !ignoreCollider) { MeshCollider collider = go.GetComponent <MeshCollider>(); if (collider == null) { collider = go.AddComponent <MeshCollider>(); } collider.sharedMesh = mesh; } // Assign static if (makeStatic) { go.isStatic = true; } return(go); }
public void CreateDungeonBlock() { DungeonGenerator myGen = GetComponent <DungeonRecord>().MyGenerator; Debug.LogWarning("Creating dungeon block: " + blockIndex + " isStarting block: " + isStartBlock); DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { Debug.LogError("CreateDungeonBlock found dfUnity not ready; stopping"); return; } // Create base object DFBlock blockData = dfUnity.ContentReader.BlockFileReader.GetBlock(blockIndex); if (blockData.Type != DFBlock.BlockTypes.Rdb) { Debug.LogError(string.Format("Invalid block index : {0} | block name: {1} | block type: {2}, returning", blockIndex, blockData.Name, blockData.Type)); return; } GameObject go = RDBLayout.CreateBaseGameObject(blockData.Name, actLink, textureTable, true, cloneFrom); // Add exit doors if (isStartBlock) { StaticDoor[] doorsOut; RDBLayout.AddActionDoors(go, actLink, ref blockData, textureTable); } // Add action doors RDBLayout.AddActionDoors(go, actLink, ref blockData, textureTable); // Add lights RDBLayout.AddLights(go, ref blockData); // Add flats DFBlock.RdbObject[] editorObjectsOut = new DFBlock.RdbObject[0]; GameObject[] startMarkersOut = null; GameObject[] enterMarkersOut = null; if (myGen.GenerateTreasure) { RDBLayout.AddFlats(go, actLink, ref blockData, out editorObjectsOut, out startMarkersOut, out enterMarkersOut, dungeonType); } // Set start markers DaggerfallRDBBlock dfBlock = (cloneFrom != null) ? cloneFrom : go.GetComponent <DaggerfallRDBBlock>(); if (dfBlock != null) { dfBlock.SetMarkers(startMarkersOut, enterMarkersOut); } // Add enemies if (myGen.GenerateEnemies) { RDBLayout.AddRandomEnemies(go, editorObjectsOut, dungeonType, 0.5f, ref blockData, startMarkersOut); } go.transform.SetParent(this.transform); go.transform.localPosition = new Vector3(position.x, 0, position.y); }
/// <summary> /// Sets up enemy based on current settings. /// </summary> public void ApplyEnemySettings(MobileGender gender) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; Dictionary <int, MobileEnemy> enemyDict = GameObjectHelper.EnemyDict; MobileEnemy mobileEnemy = enemyDict[(int)EnemyType]; // Find mobile unit in children DaggerfallMobileUnit dfMobile = GetMobileBillboardChild(); if (dfMobile != null) { // Setup mobile billboard Vector2 size = Vector2.one; mobileEnemy.Gender = gender; dfMobile.SetEnemy(dfUnity, mobileEnemy, EnemyReaction); // Setup controller CharacterController controller = GetComponent <CharacterController>(); if (controller) { // Set base height from sprite size = dfMobile.Summary.RecordSizes[0]; controller.height = size.y; // Reduce height of flying creatures as their wing animation makes them taller than desired // This helps them get through doors while aiming for player eye height if (dfMobile.Summary.Enemy.Behaviour == MobileBehaviour.Flying) { controller.height /= 2f; } // Uncomment below lines to limit maximum controller height // Some particularly tall sprites (e.g. giants) require this hack to get through doors // However they will appear sunken into ground as a result //if (controller.height > 1.9f) // controller.height = 1.9f; controller.gameObject.layer = LayerMask.NameToLayer("Enemies"); } // Setup sounds EnemySounds enemySounds = GetComponent <Game.EnemySounds>(); if (enemySounds) { enemySounds.MoveSound = (SoundClips)dfMobile.Summary.Enemy.MoveSound; enemySounds.BarkSound = (SoundClips)dfMobile.Summary.Enemy.BarkSound; enemySounds.AttackSound = (SoundClips)dfMobile.Summary.Enemy.AttackSound; } // Setup entity if (entityBehaviour) { EnemyEntity entity = new EnemyEntity(); entityBehaviour.Entity = entity; int enemyIndex = (int)EnemyType; if (enemyIndex >= 0 && enemyIndex <= 42) { entityBehaviour.EntityType = EntityTypes.EnemyMonster; entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType); } else if (enemyIndex >= 128 && enemyIndex <= 146) { entityBehaviour.EntityType = EntityTypes.EnemyClass; entity.SetEnemyCareer(mobileEnemy, entityBehaviour.EntityType); } else { entityBehaviour.EntityType = EntityTypes.None; } } } }
void StartFromClassicSave() { NewCharacterCleanup(); // Save index must be in range if (classicSaveIndex < 0 || classicSaveIndex >= 6) { throw new IndexOutOfRangeException("classicSaveIndex out of range."); } // Open saves in parent path of Arena2 folder string path = SaveLoadManager.Instance.DaggerfallSavePath; SaveGames saveGames = new SaveGames(path); if (!saveGames.IsPathOpen) { throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path)); } // Open save index if (!saveGames.TryOpenSave(classicSaveIndex)) { string error = string.Format("Could not open classic save index {0}.", classicSaveIndex); DaggerfallUI.MessageBox(error); DaggerfallUnity.LogMessage(string.Format(error), true); return; } // Get required save data SaveTree saveTree = saveGames.SaveTree; SaveVars saveVars = saveGames.SaveVars; SaveTreeBaseRecord positionRecord = saveTree.FindRecord(RecordTypes.CharacterPositionRecord); if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Set player to world position playerEnterExit.EnableExteriorParent(); StreamingWorld streamingWorld = FindStreamingWorld(); int worldX = positionRecord.RecordRoot.Position.WorldX; int worldZ = positionRecord.RecordRoot.Position.WorldZ; streamingWorld.TeleportToWorldCoordinates(worldX, worldZ); streamingWorld.suppressWorld = false; } GameObject cameraObject = GameObject.FindGameObjectWithTag("MainCamera"); PlayerMouseLook mouseLook = cameraObject.GetComponent <PlayerMouseLook>(); if (mouseLook) { // Classic save value ranges from -256 (looking up) to 256 (looking down). // The maximum up and down range of view in classic is similar to 45 degrees up and down in DF Unity. float pitch = positionRecord.RecordRoot.Pitch; if (pitch != 0) { pitch = (pitch * 45 / 256); } mouseLook.Pitch = pitch; float yaw = positionRecord.RecordRoot.Yaw; // In classic saves 2048 units of yaw is 360 degrees. if (yaw != 0) { yaw = (yaw * 360 / 2048); } mouseLook.Yaw = yaw; } // Set whether the player's weapon is drawn WeaponManager weaponManager = GameManager.Instance.WeaponManager; weaponManager.Sheathed = (!saveVars.WeaponDrawn); // Set game time DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime); // Get character record List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character); if (records.Count != 1) { throw new Exception("SaveTree CharacterRecord not found."); } // Assign diseases and poisons to player entity LycanthropyTypes lycanthropyType; PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignDiseasesAndPoisons(saveTree, out lycanthropyType); // Get prototypical character document data CharacterRecord characterRecord = (CharacterRecord)records[0]; characterDocument = characterRecord.ToCharacterDocument(lycanthropyType); // Assign data to player entity playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.baseHealth, false); playerEntity.SetCurrentLevelUpSkillSum(); // Assign biography modifiers playerEntity.BiographyResistDiseaseMod = saveVars.BiographyResistDiseaseMod; playerEntity.BiographyResistMagicMod = saveVars.BiographyResistMagicMod; playerEntity.BiographyAvoidHitMod = saveVars.BiographyAvoidHitMod; playerEntity.BiographyResistPoisonMod = saveVars.BiographyResistPoisonMod; playerEntity.BiographyFatigueMod = saveVars.BiographyFatigueMod; // Assign faction data playerEntity.FactionData.ImportClassicReputation(saveVars); // Assign global variables playerEntity.GlobalVars.ImportClassicGlobalVars(saveVars); // Set time of last check for raising skills playerEntity.TimeOfLastSkillIncreaseCheck = saveVars.LastSkillCheckTime; // Assign classic items and spells to player entity playerEntity.AssignItemsAndSpells(saveTree); // Assign guild memberships playerEntity.AssignGuildMemberships(saveTree); // Assign gold pieces playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold; // Assign weapon hand being used weaponManager.UsingRightHand = !saveVars.UsingLeftHandWeapon; // GodMode setting playerEntity.GodMode = saveVars.GodMode; // Setup bank accounts var bankRecords = saveTree.FindRecord(RecordTypes.BankAccount); Banking.DaggerfallBankManager.ReadNativeBankData(bankRecords); // Ship ownership Banking.DaggerfallBankManager.AssignShipToPlayer(saveVars.PlayerOwnedShip); // Get regional data. playerEntity.RegionData = saveVars.RegionData; // Set time tracked by playerEntity for game minute-based updates playerEntity.LastGameMinutes = saveVars.GameTime; // Get breath remaining if player was submerged (0 if they were not in the water) playerEntity.CurrentBreath = saveVars.BreathRemaining; // Get last type of crime committed playerEntity.CrimeCommitted = (PlayerEntity.Crimes)saveVars.CrimeCommitted; // Get weather byte[] climateWeathers = saveVars.ClimateWeathers; // Enums for thunder and snow are reversed in classic and Unity, so they are converted here. for (int i = 0; i < climateWeathers.Length; i++) { // TODO: 0x80 flag can be set for snow or rain, to add fog to these weathers. This isn't in DF Unity yet, so // temporarily removing the flag. climateWeathers[i] &= 0x7f; if (climateWeathers[i] == 5) { climateWeathers[i] = 6; } else if (climateWeathers[i] == 6) { climateWeathers[i] = 5; } } GameManager.Instance.WeatherManager.PlayerWeather.ClimateWeathers = climateWeathers; // Load character biography text playerEntity.BackStory = saveGames.BioFile.Lines; // Validate spellbook item DaggerfallUnity.Instance.ItemHelper.ValidateSpellbookItem(playerEntity); // Restore old class specials RestoreOldClassSpecials(saveTree, characterDocument.classicTransformedRace, lycanthropyType); // Restore vampirism if classic character was a vampire if (characterDocument.classicTransformedRace == Races.Vampire) { // Restore effect Debug.Log("Restoring vampirism to classic character."); EntityEffectBundle bundle = GameManager.Instance.PlayerEffectManager.CreateVampirismCurse(); GameManager.Instance.PlayerEffectManager.AssignBundle(bundle, AssignBundleFlags.BypassSavingThrows); // Assign correct clan from classic save VampirismEffect vampireEffect = (VampirismEffect)GameManager.Instance.PlayerEffectManager.FindIncumbentEffect <VampirismEffect>(); if (vampireEffect != null) { Debug.LogFormat("Setting vampire clan to {0}", (VampireClans)characterDocument.vampireClan); vampireEffect.VampireClan = (VampireClans)characterDocument.vampireClan; } } // Restore lycanthropy if classic character was a werewolf/wereboar if (lycanthropyType != LycanthropyTypes.None) { // TODO: Restore lycanthropy effect switch (lycanthropyType) { case LycanthropyTypes.Werewolf: Debug.Log("Restoring lycanthropy (werewolf) to classic character."); break; case LycanthropyTypes.Wereboar: Debug.Log("Restoring lycanthropy (wereboar) to classic character."); break; } EntityEffectBundle bundle = GameManager.Instance.PlayerEffectManager.CreateLycanthropyCurse(); GameManager.Instance.PlayerEffectManager.AssignBundle(bundle, AssignBundleFlags.BypassSavingThrows); LycanthropyEffect lycanthropyEffect = (LycanthropyEffect)GameManager.Instance.PlayerEffectManager.FindIncumbentEffect <LycanthropyEffect>(); if (lycanthropyEffect != null) { lycanthropyEffect.InfectionType = lycanthropyType; GameManager.Instance.PlayerEntity.AssignPlayerLycanthropySpell(); } } // Start game DaggerfallUI.Instance.PopToHUD(); GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); lastStartMethod = StartMethods.LoadClassicSave; SaveIndex = -1; if (OnStartGame != null) { OnStartGame(this, null); } }
void AddControls() { saveImageButtons = new Button[saveImageButtonDims.Length]; saveTextButtons = new Button[saveTextButtonDims.Length]; for (int i = 0; i < saveImageButtonDims.Length; i++) { // Open save if (!saveGames.LazyOpenSave(i)) { DaggerfallUnity.LogMessage(string.Format("Could not lazy open save index {0}.", i), true); continue; } // Get save texture Texture2D saveTexture = TextureReader.CreateFromAPIImage(saveGames.SaveImage); saveTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode; // Setup image button saveImageButtons[i] = DaggerfallUI.AddButton(saveImageButtonDims[i], NativePanel); saveImageButtons[i].BackgroundTexture = saveTexture; saveImageButtons[i].BackgroundTextureLayout = BackgroundLayout.ScaleToFit; saveImageButtons[i].Tag = i; saveImageButtons[i].OnMouseClick += SaveGame_OnMouseClick; saveImageButtons[i].OnMouseDoubleClick += SaveGame_OnMouseDoubleClick; // Setup text button saveTextButtons[i] = DaggerfallUI.AddButton(saveTextButtonDims[i], NativePanel); saveTextButtons[i].Label.Text = saveGames.SaveName; saveTextButtons[i].Tag = i; saveTextButtons[i].OnMouseClick += SaveGame_OnMouseClick; saveTextButtons[i].OnMouseDoubleClick += SaveGame_OnMouseDoubleClick; // Select first valid save game if (selectedSaveGame == -1) { selectedSaveGame = i; } } // Setup outline outline = DaggerfallUI.AddOutline(outlineRects[0], DaggerfallUI.DaggerfallDefaultTextColor, NativePanel); if (selectedSaveGame == -1) { outline.Enabled = false; } else { SelectSaveGame(selectedSaveGame); } // Setup load game button if (selectedSaveGame >= 0) { Button loadGameButton = DaggerfallUI.AddButton(new Vector2(126, 5), new Vector2(68, 11), NativePanel); loadGameButton.OnMouseClick += LoadGameButton_OnMouseClick; } // Setup exit button DaggerfallUI.AddButton(new Vector2(133, 150), new Vector2(56, 19), WindowMessages.wmCloseWindow, NativePanel); //// TEMP: Look for quick save and add temp button //if (SaveLoadManager.Instance.HasQuickSave()) //{ // Button quickLoadButton = new Button(); // quickLoadButton.HorizontalAlignment = HorizontalAlignment.Center; // quickLoadButton.VerticalAlignment = VerticalAlignment.Middle; // quickLoadButton.BackgroundColor = Color.gray; // quickLoadButton.Label.Text = "Quick Load"; // quickLoadButton.Label.BackgroundColor = Color.gray; // quickLoadButton.OnMouseClick += QuickLoadButton_OnMouseClick; // quickLoadButton.Size = new Vector2(52, 10); // NativePanel.Components.Add(quickLoadButton); //} }
/// <summary> /// Reads any Daggerfall image file to ImageData package. /// </summary> /// <param name="filename">Name of standalone file as it appears in arena2 folder.</param> /// <param name="record">Which image record to read for multi-image files.</param> /// <param name="frame">Which frame to read for multi-frame images.</param> /// <param name="hasAlpha">Enable this for image cutouts.</param> /// <param name="createTexture">Create a Texture2D.</param> /// <param name="createAllFrameTextures">Creates a Texture2D for every frame in a TEXTURE file (if greater than 1 frames).</param> /// <param name="alphaIndex">Set palette index for alpha checks (default is 0).</param> /// <returns>ImageData. If result.type == ImageTypes.None then read failed.</returns> public static ImageData GetImageData(string filename, int record = 0, int frame = 0, bool hasAlpha = false, bool createTexture = true, bool createAllFrameTextures = false, int alphaIndex = 0) { // Check API ready DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(new ImageData()); } // Parse image file type ImageTypes fileType; try { fileType = ParseFileType(filename); } catch { return(new ImageData()); } // Create base image data ImageData imageData = new ImageData(); imageData.type = fileType; imageData.filename = filename; imageData.record = record; imageData.frame = frame; imageData.hasAlpha = hasAlpha; imageData.alphaIndex = alphaIndex; // Read supported image files DFBitmap dfBitmap = null; DFBitmap[] dfBitmapAllFrames = null; switch (fileType) { case ImageTypes.TEXTURE: TextureFile textureFile = new TextureFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); textureFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, textureFile.PaletteName)); dfBitmap = textureFile.GetDFBitmap(record, frame); int frameCount = textureFile.GetFrameCount(record); if (createAllFrameTextures && frameCount > 1) { dfBitmapAllFrames = new DFBitmap[frameCount]; for (int i = 0; i < frameCount; i++) { dfBitmapAllFrames[i] = textureFile.GetDFBitmap(record, i); } } imageData.offset = textureFile.GetOffset(record); imageData.scale = textureFile.GetScale(record); imageData.size = textureFile.GetSize(record); // Texture pack support int archive = AssetInjection.TextureReplacement.FileNameToArchive(filename); if (createTexture && AssetInjection.TextureReplacement.TryImportTexture(archive, record, frame, out imageData.texture)) { createTexture = false; } if (createAllFrameTextures && frameCount > 1 && AssetInjection.TextureReplacement.TryImportTexture(archive, record, out imageData.animatedTextures)) { createAllFrameTextures = false; } break; case ImageTypes.IMG: ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName)); dfBitmap = imgFile.GetDFBitmap(); imageData.offset = imgFile.ImageOffset; imageData.scale = new DFSize(); imageData.size = imgFile.GetSize(0); // Texture pack support if (createTexture && AssetInjection.TextureReplacement.TryImportImage(filename, false, out imageData.texture)) { createTexture = false; } break; case ImageTypes.CIF: case ImageTypes.RCI: CifRciFile cifFile = new CifRciFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); cifFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, cifFile.PaletteName)); dfBitmap = cifFile.GetDFBitmap(record, frame); imageData.offset = cifFile.GetOffset(record); imageData.scale = new DFSize(); imageData.size = cifFile.GetSize(record); // Texture pack support if (createTexture && AssetInjection.TextureReplacement.TryImportCifRci(filename, record, frame, false, out imageData.texture)) { createTexture = false; } break; case ImageTypes.CFA: CfaFile cfaFile = new CfaFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); cfaFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, cfaFile.PaletteName)); dfBitmap = cfaFile.GetDFBitmap(record, frame); imageData.offset = new DFPosition(0, 0); imageData.scale = new DFSize(); imageData.size = cfaFile.GetSize(record); // Texture pack support if (createTexture && AssetInjection.TextureReplacement.TryImportCifRci(filename, record, frame, false, out imageData.texture)) { createTexture = false; } break; case ImageTypes.BSS: BssFile bssFile = new BssFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); bssFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, bssFile.PaletteName)); dfBitmap = bssFile.GetDFBitmap(record, frame); imageData.offset = new DFPosition(0, 0); imageData.scale = new DFSize(); imageData.size = bssFile.GetSize(record); // Texture pack support if (createTexture && AssetInjection.TextureReplacement.TryImportCifRci(filename, record, frame, false, out imageData.texture)) { createTexture = false; } break; case ImageTypes.GFX: GfxFile gfxFile = new GfxFile(Path.Combine(dfUnity.Arena2Path, filename), FileUsage.UseMemory, true); gfxFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, gfxFile.PaletteName)); dfBitmap = gfxFile.GetDFBitmap(record, frame); imageData.offset = new DFPosition(0, 0); imageData.scale = new DFSize(); imageData.size = gfxFile.GetSize(record); // Texture pack support if (createTexture && AssetInjection.TextureReplacement.TryImportCifRci(filename, record, frame, false, out imageData.texture)) { createTexture = false; } break; default: return(new ImageData()); } // Store bitmap imageData.dfBitmap = dfBitmap; imageData.width = dfBitmap.Width; imageData.height = dfBitmap.Height; // Create Texture2D if (createTexture) { // Get colors array Color32[] colors = GetColors(imageData); if (colors == null) { return(new ImageData()); } // Create new Texture2D imageData.texture = GetTexture(colors, imageData.width, imageData.height); } // Create animated Texture2D frames if (createAllFrameTextures && dfBitmapAllFrames != null) { imageData.animatedTextures = new Texture2D[dfBitmapAllFrames.Length]; for (int i = 0; i < dfBitmapAllFrames.Length; i++) { ImageData curFrame = imageData; curFrame.dfBitmap = dfBitmapAllFrames[i]; Color32[] colors = GetColors(curFrame); imageData.animatedTextures[i] = GetTexture(colors, imageData.width, imageData.height); } } return(imageData); }
public override void Update() { // DaggerfallUnity must be ready if (dfUnity == null) dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) return; // Must be setup if (!isSetup) { Setup(); isSetup = true; return; } base.Update(); }
/// <summary> /// Instantiate base RMB block by DFBlock data. /// </summary> /// <param name="blockData">Block data.</param> /// <returns>Block GameObject.</returns> public static GameObject CreateBaseGameObject(ref DFBlock blockData, DaggerfallRMBBlock cloneFrom = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } // Create gameobject GameObject go; string name = string.Format("DaggerfallBlock [{0}]", blockData.Name); if (cloneFrom != null) { go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero); } else { go = new GameObject(name); go.AddComponent <DaggerfallRMBBlock>(); } // Setup combiner ModelCombiner combiner = null; if (dfUnity.Option_CombineRMB) { combiner = new ModelCombiner(); } // Lists to receive any doors found in this block List <StaticDoor> modelDoors; List <StaticDoor> propDoors; // Add models and static props GameObject modelsNode = new GameObject("Models"); modelsNode.transform.parent = go.transform; AddModels(dfUnity, ref blockData, out modelDoors, combiner, modelsNode.transform); AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform); // Add doors List <StaticDoor> allDoors = new List <StaticDoor>(); if (modelDoors.Count > 0) { allDoors.AddRange(modelDoors); } if (propDoors.Count > 0) { allDoors.AddRange(propDoors); } if (allDoors.Count > 0) { AddStaticDoors(allDoors.ToArray(), go); } // Apply combiner if (combiner != null) { if (combiner.VertexCount > 0) { combiner.Apply(); GameObjectHelper.CreateCombinedMeshGameObject( combiner, "CombinedModels", modelsNode.transform, dfUnity.Option_SetStaticFlags); } } return(go); }
void Start() { dfUnity = DaggerfallUnity.Instance; mainCamera = GameObject.FindGameObjectWithTag("MainCamera"); playerGPS = GetComponent <PlayerGPS>(); }
/// <summary> /// Add subrecord (building) exterior block flats. /// </summary> public static void AddExteriorBlockFlats( ref DFBlock blockData, Transform flatsParent, Transform lightsParent, int mapId, int locationIndex, ClimateNatureSets climateNature = ClimateNatureSets.TemperateWoodland, ClimateSeason climateSeason = ClimateSeason.Summer) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Get Nature Archive int natureArchive = ClimateSwaps.GetNatureArchive(climateNature, climateSeason); foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords) { Vector3 subRecordPosition = new Vector3(subRecord.XPos, 0, -subRecord.ZPos) * MeshReader.GlobalScale; foreach (DFBlock.RmbBlockFlatObjectRecord obj in subRecord.Exterior.BlockFlatObjectRecords) { // Don't add building exterior editor flats since they can't be used by any DFU systems int archive = obj.TextureArchive; if (archive == TextureReader.EditorFlatsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; billboardPosition += subRecordPosition; // Add natures using correct climate set archive if (archive >= (int)DFLocation.ClimateTextureSet.Nature_RainForest && archive <= (int)DFLocation.ClimateTextureSet.Nature_Mountains_Snow) { archive = natureArchive; billboardPosition.z = natureFlatsOffsetY; } // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(archive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } // Add standalone billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(archive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); // Add animal sound if (archive == TextureReader.AnimalsTextureArchive) { AddAnimalAudioSource(go); } // If flat record has a non-zero faction id, then it's an exterior NPC if (obj.FactionID != 0) { // Add RMB data to billboard DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); dfBillboard.SetRMBPeopleData(obj.FactionID, obj.Flags, obj.Position); // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, mapId, locationIndex); } // If this is a light flat, import light prefab if (archive == TextureReader.LightsTextureArchive) { if (dfUnity.Option_CityLightPrefab == null) { return; } Vector2 size = dfUnity.MeshReader.GetScaledBillboardSize(210, obj.TextureRecord); Vector3 position = new Vector3( obj.XPos, -obj.YPos + size.y, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; position += subRecordPosition; GameObjectHelper.InstantiatePrefab(dfUnity.Option_CityLightPrefab.gameObject, string.Empty, lightsParent, position); } } } }
void Awake() { dfUnity = DaggerfallUnity.Instance; //mainCamera = GameObject.FindGameObjectWithTag("MainCamera"); //playerMouseLook = GetComponent<PlayerMouseLook>(); playerGPS = GetComponent<PlayerGPS>(); world = FindObjectOfType<StreamingWorld>(); }
/// <summary> /// Instantiate base RMB block by DFBlock data. /// </summary> /// <param name="blockData">Block data.</param> /// <param name="layoutX">X coordinate in parent map layout.</param> /// /// <param name="layoutY">Y coordinate in parent map layout.</param> /// <param name="cloneFrom">Prefab to clone from.</param> /// <returns>Block GameObject.</returns> public static GameObject CreateBaseGameObject(ref DFBlock blockData, int layoutX, int layoutY, DaggerfallRMBBlock cloneFrom = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } // Create gameobject GameObject go; string name = string.Format("DaggerfallBlock [{0}]", blockData.Name); if (cloneFrom != null) { go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero); } else { go = new GameObject(name); } // Setup combiner ModelCombiner combiner = null; if (dfUnity.Option_CombineRMB) { combiner = new ModelCombiner(); } // Lists to receive any doors found in this block List <StaticDoor> modelDoors; List <StaticDoor> propDoors; List <StaticBuilding> modelBuildings; // Add models and static props GameObject modelsNode = new GameObject("Models"); modelsNode.transform.parent = go.transform; AddModels(dfUnity, layoutX, layoutY, ref blockData, out modelDoors, out modelBuildings, combiner, modelsNode.transform); AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform); // Combine list of doors found in models and props List <StaticDoor> allDoors = new List <StaticDoor>(); if (modelDoors.Count > 0) { allDoors.AddRange(modelDoors); } if (propDoors.Count > 0) { allDoors.AddRange(propDoors); } // Assign building key to each door for (int i = 0; i < allDoors.Count; i++) { StaticDoor door = allDoors[i]; door.buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)door.recordIndex); allDoors[i] = door; } // Assign building key to each building for (int i = 0; i < modelBuildings.Count; i++) { StaticBuilding building = modelBuildings[i]; building.buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)building.recordIndex); modelBuildings[i] = building; } // Add static doors component if (allDoors.Count > 0) { AddStaticDoors(allDoors.ToArray(), go); } // Add static buildings component if (modelBuildings.Count > 0) { AddStaticBuildings(modelBuildings.ToArray(), go); } // Apply combiner if (combiner != null) { if (combiner.VertexCount > 0) { combiner.Apply(); GameObjectHelper.CreateCombinedMeshGameObject( combiner, "CombinedModels", modelsNode.transform, dfUnity.Option_SetStaticFlags); } } return(go); }
private static void AddModels( DaggerfallUnity dfUnity, ref DFBlock blockData, out List<StaticDoor> doorsOut, ModelCombiner combiner = null, Transform parent = null) { doorsOut = new List<StaticDoor>(); // Iterate through all subrecords int recordCount = 0; foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords) { // Get subrecord transform Vector3 subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale; Vector3 subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 subRecordMatrix = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one); // Iterate through models in this subrecord foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords) { // Get model transform Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 modelMatrix = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one); // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData); // Does this model have doors? if (modelData.Doors != null) doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix)); // Add or combine if (combiner == null || IsCityGate(obj.ModelIdNum)) AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent); else combiner.Add(ref modelData, modelMatrix); } // Increment record count recordCount++; } }
/// <summary> /// Add misc block flats. /// Batching is conditionally supported. /// </summary> public static void AddMiscBlockFlats( ref DFBlock blockData, Transform flatsParent, DaggerfallBillboardBatch animalsBillboardBatch = null, TextureAtlasBuilder miscBillboardsAtlas = null, DaggerfallBillboardBatch miscBillboardsBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Add block flats foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Ignore lights as they are handled by AddLights() if (obj.TextureArchive == TextureReader.LightsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } //// Use misc billboard atlas where available //if (miscBillboardsAtlas != null && miscBillboardsBatch != null) //{ // TextureAtlasBuilder.AtlasItem item = miscBillboardsAtlas.GetAtlasItem(obj.TextureArchive, obj.TextureRecord); // if (item.key != -1) // { // miscBillboardsBatch.AddItem(item.rect, item.textureItem.size, item.textureItem.scale, billboardPosition); // continue; // } //} // Add to batch where available //if (obj.TextureArchive == TextureReader.AnimalsTextureArchive && animalsBillboardBatch != null) //{ // animalsBillboardBatch.AddItem(obj.TextureRecord, billboardPosition); // continue; //} // Add standalone billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); // Add animal sound if (obj.TextureArchive == TextureReader.AnimalsTextureArchive) { AddAnimalAudioSource(go); } // If flat record has a non-zero faction id, then it's an exterior NPC if (obj.FactionID != 0) { // Add RMB data to billboard DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); dfBillboard.SetRMBPeopleData(obj.FactionID, obj.Flags, obj.Position); // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj); } } }
private static GameObject AddStandaloneModel( DaggerfallUnity dfUnity, ref ModelData modelData, Matrix4x4 matrix, Transform parent) { uint modelID = (uint)modelData.DFMesh.ObjectId; // Add GameObject GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(modelID, parent, dfUnity.Option_SetStaticFlags); go.transform.position = matrix.GetColumn(3); go.transform.rotation = GameObjectHelper.QuaternionFromMatrix(matrix); // Is this a city gate? if (IsCityGate(modelID)) { DaggerfallCityGate gate = go.AddComponent<DaggerfallCityGate>(); gate.SetOpen(!dfUnity.Option_CloseCityGates); } return go; }
private static void AddModels( DaggerfallUnity dfUnity, int layoutX, int layoutY, ref DFBlock blockData, out List <StaticDoor> doorsOut, out List <StaticBuilding> buildingsOut, ModelCombiner combiner = null, Transform parent = null) { doorsOut = new List <StaticDoor>(); buildingsOut = new List <StaticBuilding>(); // Iterate through all subrecords int recordCount = 0; foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords) { // Get subrecord transform Vector3 subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale; Vector3 subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 subRecordMatrix = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one); // Iterate through models in this subrecord bool firstModel = true; foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords) { // Get model transform Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 modelMatrix = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one); // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData); // Does this model have doors? StaticDoor[] staticDoors = null; if (modelData.Doors != null) { staticDoors = GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix); doorsOut.AddRange(staticDoors); } // Store building information for first model of record // First model is main record structure, others are attachments like posts // Only main structure is needed to resolve building after hit-test //int buildingKey = 0; if (firstModel) { //// Example: Create building key for this record - considered experimental for now //buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)recordCount); StaticBuilding staticBuilding = new StaticBuilding(); staticBuilding.modelMatrix = modelMatrix; staticBuilding.recordIndex = recordCount; staticBuilding.centre = new Vector3(modelData.DFMesh.Centre.X, modelData.DFMesh.Centre.Y, modelData.DFMesh.Centre.Z) * MeshReader.GlobalScale; staticBuilding.size = new Vector3(modelData.DFMesh.Size.X, modelData.DFMesh.Size.Y, modelData.DFMesh.Size.Z) * MeshReader.GlobalScale; buildingsOut.Add(staticBuilding); firstModel = false; } // Example: Do stuff with buildingKey // if (buildingKey != 0) then this should be the building key for this record // if (staticDoors != null && staticDoors.Length > 0) then this should have all the initial door data (basically position stuff) for this building // Import custom GameObject if (MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, parent, modelMatrix) != null) { continue; } // Use Daggerfall Model // Add or combine if (combiner == null || IsCityGate(obj.ModelIdNum)) { AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent); } else { combiner.Add(ref modelData, modelMatrix); } } // Increment record count recordCount++; } }
void Start() { dfUnity = DaggerfallUnity.Instance; dfAudioSource = GetComponent<DaggerfallAudioSource>(); StartCoroutine(AnimateWeapon()); }
// Start new character to location specified in INI void StartNewCharacter() { DaggerfallUnity.ResetUID(); QuestMachine.Instance.ClearState(); RaiseOnNewGameEvent(); DaggerfallUI.Instance.PopToHUD(); ResetWeaponManager(); SaveLoadManager.ClearSceneCache(true); GameManager.Instance.GuildManager.ClearMembershipData(); // Must have a character document if (characterDocument == null) { characterDocument = new CharacterDocument(); } // Assign character sheet PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterDocument); // Set game time DaggerfallUnity.Instance.WorldTime.Now.SetClassicGameStartTime(); // Set time tracked in playerEntity playerEntity.LastGameMinutes = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToClassicDaggerfallTime(); // Get start parameters DFPosition mapPixel = new DFPosition(DaggerfallUnity.Settings.StartCellX, DaggerfallUnity.Settings.StartCellY); bool startInDungeon = DaggerfallUnity.Settings.StartInDungeon; // Read location if any DFLocation location = new DFLocation(); ContentReader.MapSummary mapSummary; bool hasLocation = DaggerfallUnity.Instance.ContentReader.HasLocation(mapPixel.X, mapPixel.Y, out mapSummary); if (hasLocation) { if (!DaggerfallUnity.Instance.ContentReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex, out location)) { hasLocation = false; } } if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Start at specified location StreamingWorld streamingWorld = FindStreamingWorld(); if (hasLocation && startInDungeon && location.HasDungeon) { if (streamingWorld) { streamingWorld.TeleportToCoordinates(mapPixel.X, mapPixel.Y); streamingWorld.suppressWorld = true; } playerEnterExit.EnableDungeonParent(); playerEnterExit.StartDungeonInterior(location); } else { playerEnterExit.EnableExteriorParent(); if (streamingWorld) { streamingWorld.SetAutoReposition(StreamingWorld.RepositionMethods.Origin, Vector3.zero); streamingWorld.suppressWorld = false; } } } // Assign starting gear to player entity DaggerfallUnity.Instance.ItemHelper.AssignStartingGear(playerEntity); // Setup bank accounts and houses Banking.DaggerfallBankManager.SetupAccounts(); Banking.DaggerfallBankManager.SetupHouses(); // Initialize region data playerEntity.InitializeRegionData(); // Randomize weathers GameManager.Instance.WeatherManager.SetClimateWeathers(); // Start game GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); lastStartMethod = StartMethods.NewCharacter; // Offer main quest during pre-alpha QuestMachine.Instance.InstantiateQuest("__MQSTAGE00"); // Launch startup optional quest if (!string.IsNullOrEmpty(LaunchQuest)) { QuestMachine.Instance.InstantiateQuest(LaunchQuest); LaunchQuest = string.Empty; } if (OnStartGame != null) { OnStartGame(this, null); } }
/// <summary> /// Add a standalone model when not combining. /// </summary> private static GameObject AddStandaloneModel( DaggerfallUnity dfUnity, ref ModelData modelData, Matrix4x4 matrix, Transform parent, bool overrideStatic = false, bool ignoreCollider = false) { // Determine static flag bool isStatic = (dfUnity.Option_SetStaticFlags && !overrideStatic) ? true : false; // Add GameObject uint modelID = (uint)modelData.DFMesh.ObjectId; GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(modelID, parent, isStatic, null, ignoreCollider); go.transform.position = matrix.GetColumn(3); go.transform.rotation = GameObjectHelper.QuaternionFromMatrix(matrix); return go; }
void StartFromClassicSave() { DaggerfallUnity.ResetUID(); QuestMachine.Instance.ClearState(); RaiseOnNewGameEvent(); ResetWeaponManager(); // Save index must be in range if (classicSaveIndex < 0 || classicSaveIndex >= 6) { throw new IndexOutOfRangeException("classicSaveIndex out of range."); } // Open saves in parent path of Arena2 folder string path = SaveLoadManager.Instance.DaggerfallSavePath; SaveGames saveGames = new SaveGames(path); if (!saveGames.IsPathOpen) { throw new Exception(string.Format("Could not open Daggerfall saves path {0}", path)); } // Open save index if (!saveGames.TryOpenSave(classicSaveIndex)) { string error = string.Format("Could not open classic save index {0}.", classicSaveIndex); DaggerfallUI.MessageBox(error); DaggerfallUnity.LogMessage(string.Format(error), true); return; } // Get required save data SaveTree saveTree = saveGames.SaveTree; SaveVars saveVars = saveGames.SaveVars; SaveTreeBaseRecord positionRecord = saveTree.FindRecord(RecordTypes.CharacterPositionRecord); if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Set player to world position playerEnterExit.EnableExteriorParent(); StreamingWorld streamingWorld = FindStreamingWorld(); int worldX = positionRecord.RecordRoot.Position.WorldX; int worldZ = positionRecord.RecordRoot.Position.WorldZ; streamingWorld.TeleportToWorldCoordinates(worldX, worldZ); streamingWorld.suppressWorld = false; } GameObject cameraObject = GameObject.FindGameObjectWithTag("MainCamera"); PlayerMouseLook mouseLook = cameraObject.GetComponent <PlayerMouseLook>(); if (mouseLook) { // Classic save value ranges from -256 (looking up) to 256 (looking down). // The maximum up and down range of view in classic is similar to 45 degrees up and down in DF Unity. float pitch = positionRecord.RecordRoot.Pitch; if (pitch != 0) { pitch = (pitch * 45 / 256); } mouseLook.Pitch = pitch; float yaw = positionRecord.RecordRoot.Yaw; // In classic saves 2048 units of yaw is 360 degrees. if (yaw != 0) { yaw = (yaw * 360 / 2048); } mouseLook.Yaw = yaw; } // Set whether the player's weapon is drawn GameManager.Instance.WeaponManager.Sheathed = (!saveVars.WeaponDrawn); // Set game time DaggerfallUnity.Instance.WorldTime.Now.FromClassicDaggerfallTime(saveVars.GameTime); // Get character record List <SaveTreeBaseRecord> records = saveTree.FindRecords(RecordTypes.Character); if (records.Count != 1) { throw new Exception("SaveTree CharacterRecord not found."); } // Get prototypical character document data CharacterRecord characterRecord = (CharacterRecord)records[0]; characterDocument = characterRecord.ToCharacterDocument(); // Assign data to player entity PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterDocument, characterRecord.ParsedData.level, characterRecord.ParsedData.maxHealth, false); // Assign biography modifiers playerEntity.BiographyResistDiseaseMod = saveVars.BiographyResistDiseaseMod; playerEntity.BiographyResistMagicMod = saveVars.BiographyResistMagicMod; playerEntity.BiographyAvoidHitMod = saveVars.BiographyAvoidHitMod; playerEntity.BiographyResistPoisonMod = saveVars.BiographyResistPoisonMod; playerEntity.BiographyFatigueMod = saveVars.BiographyFatigueMod; // Assign faction data playerEntity.FactionData.ImportClassicReputation(saveVars); // Assign global variables playerEntity.GlobalVars.ImportClassicGlobalVars(saveVars); // Set time of last check for raising skills playerEntity.TimeOfLastSkillIncreaseCheck = saveVars.LastSkillCheckTime; // Assign items to player entity playerEntity.AssignItems(saveTree); // Assign diseases and poisons to player entity playerEntity.AssignDiseasesAndPoisons(saveTree); // Assign gold pieces playerEntity.GoldPieces = (int)characterRecord.ParsedData.physicalGold; // GodMode setting playerEntity.GodMode = saveVars.GodMode; // Setup bank accounts var bankRecords = saveTree.FindRecord(RecordTypes.BankAccount); Banking.DaggerfallBankManager.ReadNativeBankData(bankRecords); // Get regional data. playerEntity.RegionData = saveVars.RegionData; // Set time tracked by playerEntity for game minute-based updates playerEntity.LastGameMinutes = saveVars.GameTime; // Get breath remaining if player was submerged (0 if they were not in the water) playerEntity.CurrentBreath = saveVars.BreathRemaining; // TODO: Import classic spellbook playerEntity.DeserializeSpellbook(null); // Get last type of crime committed playerEntity.CrimeCommitted = (PlayerEntity.Crimes)saveVars.CrimeCommitted; // Get weather byte[] climateWeathers = saveVars.ClimateWeathers; // Enums for thunder and snow are reversed in classic and Unity, so they are converted here. for (int i = 0; i < climateWeathers.Length; i++) { // TODO: 0x80 flag can be set for snow or rain, to add fog to these weathers. This isn't in DF Unity yet, so // temporarily removing the flag. climateWeathers[i] &= 0x7f; if (climateWeathers[i] == 5) { climateWeathers[i] = 6; } else if (climateWeathers[i] == 6) { climateWeathers[i] = 5; } } GameManager.Instance.WeatherManager.PlayerWeather.ClimateWeathers = climateWeathers; // Start game DaggerfallUI.Instance.PopToHUD(); GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); lastStartMethod = StartMethods.LoadClassicSave; SaveIndex = -1; if (OnStartGame != null) { OnStartGame(this, null); } }
private static GameObject AddLight(DaggerfallUnity dfUnity, DFBlock.RdbObject obj, Transform parent) { // Spawn light gameobject float range = obj.Resources.LightResource.Radius * MeshReader.GlobalScale; Vector3 position = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; GameObject go = GameObjectHelper.InstantiatePrefab(dfUnity.Option_DungeonLightPrefab.gameObject, string.Empty, parent, position); Light light = go.GetComponent<Light>(); if (light != null) { light.range = range * 3; } return go; }
IEnumerator Respawner(int worldX, int worldZ, bool insideDungeon, bool insideBuilding, bool forceReposition, bool importEnemies) { // Wait for end of frame so existing world data can be removed yield return(new WaitForEndOfFrame()); // Reset dungeon block on new spawn lastPlayerDungeonBlockIndex = -1; playerDungeonBlockData = new DFLocation.DungeonBlock(); // Reset inside state isPlayerInside = false; isPlayerInsideDungeon = false; isPlayerInsideDungeonCastle = false; blockWaterLevel = 10000; // Set player GPS coordinates playerGPS.WorldX = worldX; playerGPS.WorldZ = worldZ; // Set streaming world coordinates DFPosition pos = MapsFile.WorldCoordToMapPixel(worldX, worldZ); world.MapPixelX = pos.X; world.MapPixelY = pos.Y; // Get location at this position ContentReader.MapSummary summary; bool hasLocation = dfUnity.ContentReader.HasLocation(pos.X, pos.Y, out summary); if (!insideDungeon && !insideBuilding) { // Start outside EnableExteriorParent(); if (!forceReposition) { // Teleport to explicit world coordinates world.TeleportToWorldCoordinates(worldX, worldZ); } else { // Force reposition to closest start marker if available world.TeleportToCoordinates(pos.X, pos.Y, StreamingWorld.RepositionMethods.RandomStartMarker); } // Wait until world is ready while (world.IsInit) { yield return(new WaitForEndOfFrame()); } } else if (hasLocation && insideDungeon) { // Start in dungeon DFLocation location; world.TeleportToCoordinates(pos.X, pos.Y, StreamingWorld.RepositionMethods.None); dfUnity.ContentReader.GetLocation(summary.RegionIndex, summary.MapIndex, out location); StartDungeonInterior(location, true, importEnemies); world.suppressWorld = true; } else if (hasLocation && insideBuilding && exteriorDoors != null) { // Start in building DFLocation location; world.TeleportToCoordinates(pos.X, pos.Y, StreamingWorld.RepositionMethods.None); dfUnity.ContentReader.GetLocation(summary.RegionIndex, summary.MapIndex, out location); StartBuildingInterior(location, exteriorDoors[0]); world.suppressWorld = true; } else { // All else fails teleport to map pixel DaggerfallUnity.LogMessage("Something went wrong! Teleporting to origin of nearest map pixel."); EnableExteriorParent(); world.TeleportToCoordinates(pos.X, pos.Y); } // Lower respawn flag isRespawning = false; }
void Start() { dfUnity = DaggerfallUnity.Instance; streamingWorld = GameObject.FindObjectOfType<StreamingWorld>(); playerEnterExit = GetComponent<PlayerEnterExit>(); playerGPS = GetComponent<PlayerGPS>(); playerMotor = GetComponent<PlayerMotor>(); playerMouseLook = GameObject.FindObjectOfType<PlayerMouseLook>(); titleScreen = GameObject.FindObjectOfType<ShowTitleScreen>(); // Get starting run speed if (playerMotor) startRunSpeed = playerMotor.runSpeed; // Get starting torch range if (PlayerTorch != null) startTorchRange = PlayerTorch.range; }
/// <summary> /// Layout a complete RMB block game object. /// Can be used standalone or as part of a city build. /// </summary> public static GameObject CreateRMBBlockGameObject( string blockName, bool addGroundPlane = true, DaggerfallRMBBlock cloneFrom = null, DaggerfallBillboardBatch natureBillboardBatch = null, DaggerfallBillboardBatch lightsBillboardBatch = null, DaggerfallBillboardBatch animalsBillboardBatch = null, TextureAtlasBuilder miscBillboardAtlas = null, DaggerfallBillboardBatch miscBillboardBatch = null, ClimateNatureSets climateNature = ClimateNatureSets.TemperateWoodland, ClimateSeason climateSeason = ClimateSeason.Summer) { // Get DaggerfallUnity DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } // Create base object DFBlock blockData; GameObject go = RMBLayout.CreateBaseGameObject(blockName, out blockData, cloneFrom); // Create flats node GameObject flatsNode = new GameObject("Flats"); flatsNode.transform.parent = go.transform; // Create lights node GameObject lightsNode = new GameObject("Lights"); lightsNode.transform.parent = go.transform; // If billboard batching is enabled but user has not specified // a batch, then make our own auto batch for this block bool autoLightsBatch = false; bool autoNatureBatch = false; bool autoAnimalsBatch = false; if (dfUnity.Option_BatchBillboards) { if (natureBillboardBatch == null) { autoNatureBatch = true; int natureArchive = ClimateSwaps.GetNatureArchive(climateNature, climateSeason); natureBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(natureArchive, flatsNode.transform); } if (lightsBillboardBatch == null) { autoLightsBatch = true; lightsBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(TextureReader.LightsTextureArchive, flatsNode.transform); } if (animalsBillboardBatch == null) { autoAnimalsBatch = true; animalsBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(TextureReader.AnimalsTextureArchive, flatsNode.transform); } } // Layout light billboards and gameobjects RMBLayout.AddLights(ref blockData, flatsNode.transform, lightsNode.transform, lightsBillboardBatch); // Layout nature billboards RMBLayout.AddNatureFlats(ref blockData, flatsNode.transform, natureBillboardBatch, climateNature, climateSeason); // Layout all other flats RMBLayout.AddMiscBlockFlats(ref blockData, flatsNode.transform, animalsBillboardBatch, miscBillboardAtlas, miscBillboardBatch); // Add ground plane if (addGroundPlane) { RMBLayout.AddGroundPlane(ref blockData, go.transform); } // Apply auto batches if (autoNatureBatch) { natureBillboardBatch.Apply(); } if (autoLightsBatch) { lightsBillboardBatch.Apply(); } if (autoAnimalsBatch) { animalsBillboardBatch.Apply(); } return(go); }