private static void AddEnemy( DFBlock.RdbObject obj, MobileTypes type, Transform parent = null, DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold) { // Get default reaction MobileReactions reaction = MobileReactions.Hostile; if (obj.Resources.FlatResource.FlatData.Reaction == (int)DFBlock.EnemyReactionTypes.Passive) { reaction = MobileReactions.Passive; } // Just setup demo enemies at this time string name = string.Format("DaggerfallEnemy [{0}]", type.ToString()); Vector3 position = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; GameObject go = GameObjectHelper.InstantiatePrefab(DaggerfallUnity.Instance.Option_EnemyPrefab.gameObject, name, parent, position); SetupDemoEnemy setupEnemy = go.GetComponent <SetupDemoEnemy>(); if (setupEnemy != null) { // Configure enemy setupEnemy.ApplyEnemySettings(type, reaction); // Align non-flying units with ground DaggerfallMobileUnit mobileUnit = setupEnemy.GetMobileBillboardChild(); if (mobileUnit.Summary.Enemy.Behaviour != MobileBehaviour.Flying) { GameObjectHelper.AlignControllerToGround(go.GetComponent <CharacterController>()); } } }
public void SetupDungeon ( Vector3 rootPos, Quaternion rootRot, string name = "", int[] textureTable = null, DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold, int creationSeed = 0 ) { if (textureTable == null) { this.textureTable = defaultTextureTable; } else { this.textureTable = textureTable; } this.rootPosition = rootPos; this.rootRotation = rootRot; this.creationSeed = creationSeed; this.name = name; this.dungeonType = dungeonType; this.blocks = new List <BlockRecord>(); }
private static void AddRandomRDBEnemy( DFBlock.RdbObject obj, DFRegion.DungeonTypes dungeonType, float monsterPower, int monsterVariance, Transform parent, ref DFBlock blockData, bool serialize) { // Must have a dungeon type if (dungeonType == DFRegion.DungeonTypes.NoDungeon) { return; } // Get dungeon type index int dungeonIndex = (int)dungeonType >> 8; if (dungeonIndex < RandomEncounters.EncounterTables.Length) { // Get encounter table RandomEncounterTable table = RandomEncounters.EncounterTables[dungeonIndex]; // Get base monster index into table int baseMonsterIndex = (int)((float)table.Enemies.Length * monsterPower); // Set min index int minMonsterIndex = baseMonsterIndex - monsterVariance; if (minMonsterIndex < 0) { minMonsterIndex = 0; } // Set max index int maxMonsterIndex = baseMonsterIndex + monsterVariance; if (maxMonsterIndex >= table.Enemies.Length) { maxMonsterIndex = table.Enemies.Length; } // Get random monster from table MobileTypes type = table.Enemies[UnityEngine.Random.Range(minMonsterIndex, maxMonsterIndex)]; // Create unique LoadID for save sytem long loadID = 0; if (serialize) { loadID = (blockData.Index << 24) + obj.This; } // Add enemy AddEnemy(obj, type, parent, loadID); } else { DaggerfallUnity.LogMessage(string.Format("RDBLayout: Dungeon type {0} is out of range or unknown.", dungeonType), true); } }
/// <summary> /// Layout a complete RDB block game object. /// </summary> /// <param name="blockName">Name of block to create.</param> /// <param name="textureTable">Optional texture table for dungeon.</param> /// <param name="allowExitDoors">Add exit doors to block (for start blocks).</param> /// <param name="dungeonType">Dungeon type for random encounters.</param> /// <param name="seed">Seed for random encounters.</param> /// <param name="cloneFrom">Clone and build on a prefab object template.</param> public static GameObject CreateRDBBlockGameObject( string blockName, int[] textureTable = null, bool allowExitDoors = true, DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold, float monsterPower = 0.5f, int monsterVariance = 4, int seed = 0, DaggerfallRDBBlock cloneFrom = null) { // Get DaggerfallUnity DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } Dictionary <int, RDBLayout.ActionLink> actionLinkDict = new Dictionary <int, RDBLayout.ActionLink>(); // Create base object DFBlock blockData; GameObject go = RDBLayout.CreateBaseGameObject(blockName, actionLinkDict, out blockData, textureTable, allowExitDoors, cloneFrom); // Add action doors RDBLayout.AddActionDoors(go, actionLinkDict, ref blockData, textureTable); // Add lights RDBLayout.AddLights(go, ref blockData); // Add flats DFBlock.RdbObject[] editorObjects; GameObject[] startMarkers; GameObject[] enterMarkers; RDBLayout.AddFlats(go, actionLinkDict, ref blockData, out editorObjects, out startMarkers, out enterMarkers); // Set start and enter markers DaggerfallRDBBlock dfBlock = go.GetComponent <DaggerfallRDBBlock>(); if (dfBlock != null) { dfBlock.SetMarkers(startMarkers, enterMarkers); } // Add treasure RDBLayout.AddTreasure(go, editorObjects, ref blockData); // Add enemies RDBLayout.AddFixedEnemies(go, editorObjects, ref blockData); RDBLayout.AddRandomEnemies(go, editorObjects, dungeonType, monsterPower, ref blockData, monsterVariance, seed); // Link action nodes RDBLayout.LinkActionNodes(actionLinkDict); return(go); }
/// <summary> /// Add random enemies from encounter tables based on dungeon type, monster power, and seed. /// </summary> /// <param name="go">GameObject to add monsters to.</param> /// <param name="editorObjects">Editor objects containing flats.</param> /// <param name="dungeonType">Dungeon type selects the encounter table.</param> /// <param name="monsterPower">Value between 0-1 for lowest monster power to highest.</param> /// <param name="monsterVariance">Adjust final index +/- this value in encounter table.</param> /// <param name="seed">Random seed for encounters.</param> /// <param name="serialize">Allow for serialization when available.</param> public static void AddRandomEnemies( GameObject go, DFBlock.RdbObject[] editorObjects, DFRegion.DungeonTypes dungeonType, float monsterPower, ref DFBlock blockData, int monsterVariance = 4, int seed = 0, bool serialize = true) { const int randomMonsterFlatIndex = 15; DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Must have import enabled and prefab set if (!dfUnity.Option_ImportEnemyPrefabs || dfUnity.Option_EnemyPrefab == null) { return; } // Editor objects array must be populated if (editorObjects == null || editorObjects.Length == 0) { return; } // Add parent node GameObject randomEnemiesNode = new GameObject("Random Enemies"); randomEnemiesNode.transform.parent = go.transform; // Seed random generator UnityEngine.Random.seed = seed; // Iterate editor flats for enemies for (int i = 0; i < editorObjects.Length; i++) { // Add random enemy objects if (editorObjects[i].Resources.FlatResource.TextureRecord == randomMonsterFlatIndex) { AddRandomRDBEnemy(editorObjects[i], dungeonType, monsterPower, monsterVariance, randomEnemiesNode.transform, ref blockData, serialize); } } }
public void SetupDungeonBlock ( int index, bool isStartBlock, int[] textureTable, DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold, int seed = 0, DaggerfallRDBBlock cloneFrom = null ) { this.blockIndex = index; this.isStartBlock = isStartBlock; this.textureTable = textureTable; this.dungeonType = dungeonType; this.cloneFrom = cloneFrom; CreateDungeonBlock(); }
public void SetupDungeonBlock ( BlockRecord record, bool isStartBlock, int[] textureTable, DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold, int seed = 0, DaggerfallRDBBlock cloneFrom = null ) { this.blockIndex = record.index; actLink = new System.Collections.Generic.Dictionary <int, RDBLayout.ActionLink>(); this.isStartBlock = isStartBlock; this.textureTable = textureTable; this.dungeonType = dungeonType; this.cloneFrom = cloneFrom; this.position = record.position; CreateDungeonBlock(); }
/// <summary> /// Creates a new RDB GameObject and performs block layout. /// Can pass information about dungeon for texture swaps and random enemies. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="blockName">Name of RDB block to build.</param> /// <param name="isStartingBlock">True if this is the starting block. Controls exit doors.</param> /// <param name="textureTable">Dungeon texture table.</param> /// <param name="dungeonType">Type of dungeon for random encounter tables.</param> /// <param name="seed">Seed for random encounters.</param> /// <returns>GameObject.</returns> public static GameObject CreateGameObject( string blockName, bool isStartingBlock, int[] textureTable = null, DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold, int seed = 0) { // Validate if (string.IsNullOrEmpty(blockName)) { return(null); } if (!blockName.ToUpper().EndsWith(".RDB")) { return(null); } DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } // Create gameobject GameObject go = new GameObject(string.Format("DaggerfallBlock [Name={0}]", blockName)); DaggerfallRDBBlock dfBlock = go.AddComponent <DaggerfallRDBBlock>(); // Start new layout RDBLayout layout = new RDBLayout(blockName); layout.isStartingBlock = isStartingBlock; layout.textureTable = textureTable; layout.dungeonType = dungeonType; layout.staticModelsNode = new GameObject("Static Models"); layout.actionModelsNode = new GameObject("Action Models"); layout.doorsNode = new GameObject("Doors"); layout.flatsNode = new GameObject("Flats"); layout.lightsNode = new GameObject("Lights"); layout.enemiesNode = new GameObject("Enemies"); // Parent child game objects layout.staticModelsNode.transform.parent = go.transform; layout.actionModelsNode.transform.parent = go.transform; layout.doorsNode.transform.parent = go.transform; layout.flatsNode.transform.parent = go.transform; layout.lightsNode.transform.parent = go.transform; layout.enemiesNode.transform.parent = go.transform; // List to receive any exit doors found List <StaticDoor> allDoors = new List <StaticDoor>(); // Seed random generator UnityEngine.Random.seed = seed; // Iterate object groups layout.groupIndex = 0; DFBlock blockData = dfUnity.ContentReader.BlockFileReader.GetBlock(blockName); foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList) { // Skip empty object groups if (null == group.RdbObjects) { layout.groupIndex++; continue; } // Iterate objects in this group List <StaticDoor> modelDoors; foreach (DFBlock.RdbObject obj in group.RdbObjects) { // Handle by object type switch (obj.Type) { case DFBlock.RdbResourceTypes.Model: layout.AddRDBModel(obj, out modelDoors, layout.staticModelsNode.transform); if (modelDoors.Count > 0) { allDoors.AddRange(modelDoors); } break; case DFBlock.RdbResourceTypes.Flat: layout.AddRDBFlat(obj, layout.flatsNode.transform); break; case DFBlock.RdbResourceTypes.Light: layout.AddRDBLight(obj, layout.lightsNode.transform); break; default: break; } } // Increment group index layout.groupIndex++; } // Link action nodes layout.LinkActionNodes(); // Combine meshes if (dfUnity.Option_CombineRDB) { layout.combiner.Apply(); GameObject cgo = GameObjectHelper.CreateCombinedMeshGameObject(layout.combiner, "CombinedMeshes", layout.staticModelsNode.transform, dfUnity.Option_SetStaticFlags); cgo.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable); } // Fix enemy standing positions for this block // Some enemies are floating in air or sunk into ground // Can only adjust this after geometry instantiated layout.FixEnemyStanding(go); // Store start markers in block dfBlock.SetStartMarkers(layout.startMarkers.ToArray()); // Add doors if (allDoors.Count > 0) { layout.AddDoors(allDoors.ToArray(), go); } return(go); }