public Spawner(World world, int snoId, TagMap tags) : base(world, snoId, tags) { this.Field2 = 8; this.Field7 = 0x00000000; //Actor.Data.TagMap contains: {66368 = 291072} //public static TagKeyInt Spawn2 = new TagKeyInt(291072); //TODO: Find why Tags is not the same as Actor.Data.TagMap if (Tags.ContainsKey(MarkerKeys.SpawnActor)) this.ActorToSpawnSNO = Tags[MarkerKeys.SpawnActor]; if (Tags.ContainsKey(MarkerKeys.OnActorSpawnedScript)) this.OnActorSpawnedScript = Tags[MarkerKeys.OnActorSpawnedScript]; }
//TODO: Move this out as loading actors can happen even after world was generated public static uint loadActor(SNOHandle actorHandle, PRTransform location, World world, TagMap tagMap) { var actor = Mooege.Core.GS.Actors.ActorFactory.Create(world, actorHandle.Id, tagMap); if (actor == null) { if (actorHandle.Id != -1) Logger.Warn("ActorFactory did not load actor {0}", actorHandle); return 0; } actor.RotationW = location.Quaternion.W; actor.RotationAxis = location.Quaternion.Vector3D; actor.EnterWorld(location.Vector3D); return actor.DynamicID; }
/// <summary> /// Loads content for level areas. Call this after scenes have been generated and after scenes have their GizmoLocations /// set (this is done in Scene.LoadActors right now) /// </summary> /// <param name="levelAreas">Dictionary that for every level area has the scenes it consists of</param> /// <param name="world">The world to which to add loaded actors</param> private static void loadLevelAreas(Dictionary<int, List<Scene>> levelAreas, World world) { /// Each Scene has one to four level areas assigned to it. I dont know if that means /// the scene belongs to both level areas or if the scene is split /// Scenes marker tags have generic GizmoLocationA to Z that are used /// to provide random spawning possibilities. /// For each of these 26 LocationGroups, the LevelArea has a entry in its SpawnType array that defines /// what type of actor/encounter/adventure could spawn there /// /// It could for example define, that for a level area X, out of the four spawning options /// two are randomly picked and have barrels placed there // Create an array of mobs, used with the loadActor in the load monster area loop // Each monster are created in Mooege.Core.GS.Actors.Implementations.Monsters // By Poluxxx //int[] aSNO = new int[] { // // 6652 // Zombie // 6443 // Ravenous // //, 136943 // Ghost //}; Dictionary<PRTransform, Mooege.Common.MPQ.FileFormats.Actor> dict = new Dictionary<PRTransform, Mooege.Common.MPQ.FileFormats.Actor>(); foreach (int la in levelAreas.Keys) { SNOHandle levelAreaHandle = new SNOHandle(SNOGroup.LevelArea, la); if (!levelAreaHandle.IsValid) { Logger.Warn("Level area {0} does not exist", la); continue; } var levelArea = levelAreaHandle.Target as LevelArea; for (int i = 0; i < 26; i++) { // Merge the gizmo starting locations from all scenes and // their subscenes into a single list for the whole level area List<PRTransform> gizmoLocations = new List<PRTransform>(); foreach (var scene in levelAreas[la]) { if (scene.GizmoSpawningLocations[i] != null) gizmoLocations.AddRange(scene.GizmoSpawningLocations[i]); foreach (Scene subScene in scene.Subscenes) { if (subScene.GizmoSpawningLocations[i] != null) gizmoLocations.AddRange(subScene.GizmoSpawningLocations[i]); } } // Load all spawns that are defined for that location group foreach (GizmoLocSpawnEntry spawnEntry in levelArea.LocSet.SpawnType[i].SpawnEntry) { // Get a random amount of spawns ... int amount = RandomHelper.Next(spawnEntry.Max, spawnEntry.Max); if (amount > gizmoLocations.Count) { Logger.Trace("Breaking after spawnEntry {0} for LevelArea {1} because there are less locations ({2}) than spawn amount ({3}, {4} min)", spawnEntry.SNOHandle, levelAreaHandle, gizmoLocations.Count, amount, spawnEntry.Min); break; } Logger.Trace("Spawning {0} ({3} - {4} {1} in {2}", amount, spawnEntry.SNOHandle, levelAreaHandle, spawnEntry.Min, spawnEntry.Max); // ...and place each one on a random position within the location group for (; amount > 0; amount--) { int location = RandomHelper.Next(gizmoLocations.Count - 1); switch (spawnEntry.SNOHandle.Group) { case SNOGroup.Actor: //TODO: Why to pass tagmap here and not load it inside Actor loadActor(spawnEntry.SNOHandle, gizmoLocations[location], world, ((Mooege.Common.MPQ.FileFormats.Actor)spawnEntry.SNOHandle.Target).TagMap); break; case SNOGroup.Encounter: var encounter = spawnEntry.SNOHandle.Target as Encounter; var actor = RandomHelper.RandomItem(encounter.Spawnoptions, x => x.Probability); var actorHandle = new SNOHandle(actor.SNOSpawn); loadActor(actorHandle, gizmoLocations[location], world, ((Mooege.Common.MPQ.FileFormats.Actor)actorHandle.Target).TagMap); break; case SNOGroup.Adventure: // Adventure are basically made up of a markerSet that has relative PRTransforms // it has some other fields that are always 0 and a reference to a symbol actor // no idea what they are used for - farmy var adventure = spawnEntry.SNOHandle.Target as Adventure; var markerSet = new SNOHandle(adventure.SNOMarkerSet).Target as MarkerSet; foreach (var marker in markerSet.Markers) { // relative marker set coordinates to absolute world coordinates var absolutePRTransform = new PRTransform { Vector3D = marker.PRTransform.Vector3D + gizmoLocations[location].Vector3D, Quaternion = new Quaternion { Vector3D = new Vector3D(marker.PRTransform.Quaternion.Vector3D.X, marker.PRTransform.Quaternion.Vector3D.Y, marker.PRTransform.Quaternion.Vector3D.Z), W = marker.PRTransform.Quaternion.W } }; switch (marker.Type) { case MarkerType.Actor: loadActor(marker.SNOHandle, absolutePRTransform, world, marker.TagMap); break; case MarkerType.Encounter: var encounter2 = marker.SNOHandle.Target as Encounter; var actor2 = RandomHelper.RandomItem(encounter2.Spawnoptions, x => x.Probability); loadActor(new SNOHandle(actor2.SNOSpawn), absolutePRTransform, world, marker.TagMap); break; default: Logger.Warn("Unhandled marker type {0} in actor loading", marker.Type); break; } } break; default: if (spawnEntry.SNOHandle.Id != -1) Logger.Warn("Unknown sno handle in LevelArea spawn entries: {0}", spawnEntry.SNOHandle); break; } // dont use that location again gizmoLocations.RemoveAt(location); } } } // Load monsters for level area foreach (var scene in levelAreas[la]) { // HACK: don't spawn monsters in tristram town scenes /mdz if (MPQStorage.Data.Assets[SNOGroup.Scene][scene.SceneSNO.Id].Name.StartsWith("trOut_Tristram_")) continue; // a little variety in monsters spawned int[] monsterActors = { 6652, 219725, 5346, 6356, 5393, 434, 4982 }; for (int i = 0; i < 100; i++) { if (RandomHelper.NextDouble() > 0.8) { // TODO Load correct spawn population // 2.5 is units per square, TODO: Find out how to calculate units per square. Is it F1 * V0.I1 / SquareCount? int x = RandomHelper.Next(scene.NavMesh.SquaresCountX); int y = RandomHelper.Next(scene.NavMesh.SquaresCountY); if ((scene.NavMesh.Squares[y * scene.NavMesh.SquaresCountX + x].Flags & Mooege.Common.MPQ.FileFormats.Scene.NavCellFlags.NoSpawn) == 0) { loadActor( new SNOHandle(monsterActors[RandomHelper.Next(monsterActors.Length)]), new PRTransform { Vector3D = new Vector3D { X = (float)(x * 2.5 + scene.Position.X), Y = (float)(y * 2.5 + scene.Position.Y), Z = scene.NavMesh.Squares[y * scene.NavMesh.SquaresCountX + x].Z + scene.Position.Z }, Quaternion = Quaternion.FacingRotation((float)(RandomHelper.NextDouble() * System.Math.PI * 2)) }, world, new TagMap() ); } } } } } }
public void Read(MpqFileStream stream) { ConditionType = (QuestStepFailureConditionType)stream.ReadValueS32(); I2 = stream.ReadValueS32(); I3 = stream.ReadValueS32(); SNOName1 = new SNOHandle(stream); SNOName2 = new SNOHandle(stream); GBID1 = stream.ReadValueS32(); GBID2 = stream.ReadValueS32(); Unknown1 = stream.ReadString(256, true); Unknown2 = stream.ReadString(256, true); }
public void Read(MpqFileStream stream) { I0 = stream.ReadValueS32(); ObjectiveType = (QuestStepObjectiveType)stream.ReadValueS32(); I2 = stream.ReadValueS32(); CounterTarget = stream.ReadValueS32(); SNOName1 = new SNOHandle(stream); SNOName2 = new SNOHandle(stream); GBID1 = stream.ReadValueS32(); GBID2 = stream.ReadValueS32(); Group1Name = stream.ReadString(256, true); Unknown2 = stream.ReadString(256, true); I4 = stream.ReadValueS32(); I5 = stream.ReadValueS32(); GBIDItemToShow = stream.ReadValueS32(); }
public Quest(Game game, int SNOQuest) { this.game = game; SNOHandle = new SNOHandle(SNOGroup.Quest, SNOQuest); asset = SNOHandle.Target as Mooege.Common.MPQ.FileFormats.Quest; CurrentStep = new QuestStep(asset.QuestUnassignedStep, this); //erekose foreach (var QCSasset in asset.QuestCompletionSteps) { if (QCSasset != null) { var nQCS = new QuestCompletionStep(QCSasset); QuestCompletionSteps.Add(nQCS); // Logger.Debug(" (quest ctor) adding a completion step {0}, {1}, {2} ", nQCS.Name, nQCS.StepId, nQCS.I2); } else { // Logger.Debug(" (quest ctor) asset null problem in QCS "); } } //foreach (var aQuestStep in asset.QuestSteps) //{ // Logger.Debug(" (quest ctor) steps ID contained in quest is : {0} ", aQuestStep.ID); //} // Logger.Debug(" (quest ctor) SNOHandle ID {0} Name {1} Group {2} isValid ?{3} ", SNOHandle.Id, SNOHandle.Name, SNOHandle.Group, SNOHandle.IsValid); // Logger.Debug(" (quest ctor) from assets numSteps {0}, SNO ID {1} num od completion step ", asset.NumberOfSteps, asset.Header.SNOId, asset.NumberOfCompletionSteps); // Logger.Debug(" (quest ctor) CurrentStep ID ", CurrentStep.QuestStepID); }
public override void Parse(GameBitBuffer buffer) { Name = new SNOHandle(); Name.Parse(buffer); }
private List<int> completedSteps = new List<int>(); // this list has to be saved if quest progress should be saved. It is required to keep track of questranges public Quest(Game game, int SNOQuest) { this.game = game; SNOHandle = new SNOHandle(SNOGroup.Quest, SNOQuest); asset = SNOHandle.Target as Mooege.Common.MPQ.FileFormats.Quest; CurrentStep = new QuestStep(asset.QuestUnassignedStep, this); }
private static void loadActor(SNOHandle actorHandle, PRTransform location, World world, TagMap tagMap) { var actor = Mooege.Core.GS.Actors.ActorFactory.Create(world, actorHandle.Id, tagMap); if (actor == null) { if(actorHandle.Id != -1) Logger.Warn("ActorFactory did not load actor {0}", actorHandle); return; } actor.FacingAngle = location.Quaternion.W; actor.RotationAxis = location.Quaternion.Vector3D; actor.EnterWorld(location.Vector3D); }
/// <summary> /// Loads content for level areas. Call this after scenes have been generated and after scenes have their GizmoLocations /// set (this is done in Scene.LoadActors right now) /// </summary> /// <param name="levelAreas">Dictionary that for every level area has the scenes it consists of</param> /// <param name="world">The world to which to add loaded actors</param> private static void loadLevelAreas(Dictionary<int, List<Scene>> levelAreas, World world) { /// Each Scene has one to four level areas assigned to it, so each level area consists of at /// least one scene. Scenes marker tags have generic GizmoLocationA to Z that are used /// to provide random spawning possibilities. /// For each of these 26 LocationGroups, the LevelArea has a entry in its SpawnType array that defines /// what type of actor/encounter/adventure could spawn there /// /// It could for example define, that for a level area X, out of the four spawning options /// two are randomly picked and have barrels placed there foreach (int la in levelAreas.Keys) { SNOHandle levelAreaHandle = new SNOHandle(SNOGroup.LevelArea, la); if (!levelAreaHandle.IsValid) { Logger.Warn("Level area {0} does not exist", la); continue; } var levelArea = levelAreaHandle.Target as LevelArea; for (int i = 0; i < 26; i++) { // Merge the gizmo starting locations from all scenes and // their subscenes into a single list for the whole level area List<PRTransform> gizmoLocations = new List<PRTransform>(); foreach (var scene in levelAreas[la]) { if (scene.GizmoSpawningLocations[i] != null) gizmoLocations.AddRange(scene.GizmoSpawningLocations[i]); foreach (Scene subScene in scene.Subscenes) { if (subScene.GizmoSpawningLocations[i] != null) gizmoLocations.AddRange(subScene.GizmoSpawningLocations[i]); } } // Load all spawns that are defined for that location group foreach (GizmoLocSpawnEntry spawnEntry in levelArea.LocSet.SpawnType[i].SpawnEntry) { // Get a random amount of spawns ... int amount = RandomHelper.Next(spawnEntry.Max, spawnEntry.Max); if (amount > gizmoLocations.Count) { Logger.Warn("Breaking after spawnEntry {0} for LevelArea {1} because there are less locations ({2}) than spawn amount ({3}, {4} min)", spawnEntry.SNOHandle, levelAreaHandle, gizmoLocations.Count, amount, spawnEntry.Min); break; } Logger.Trace("Spawning {0} ({3} - {4} {1} in {2}", amount, spawnEntry.SNOHandle, levelAreaHandle, spawnEntry.Min, spawnEntry.Max); // ...and place each one on a random position within the location group for (; amount > 0; amount--) { int location = RandomHelper.Next(gizmoLocations.Count - 1); switch (spawnEntry.SNOHandle.Group) { case SNOGroup.Actor: loadActor(spawnEntry.SNOHandle, gizmoLocations[location], world, new TagMap()); break; case SNOGroup.Encounter: var encounter = spawnEntry.SNOHandle.Target as Encounter; var actor = RandomHelper.RandomItem(encounter.Spawnoptions, x => x.Probability); loadActor(new SNOHandle(actor.SNOSpawn), gizmoLocations[location], world, new TagMap()); break; case SNOGroup.Adventure: // Adventure are basically made up of a markerSet that has relative PRTransforms // it has some other fields that are always 0 and a reference to a symbol actor // no idea what they are used for - farmy var adventure = spawnEntry.SNOHandle.Target as Adventure; var markerSet = new SNOHandle(adventure.SNOMarkerSet).Target as MarkerSet; foreach (var marker in markerSet.Markers) { // relative marker set coordinates to absolute world coordinates var absolutePRTransform = new PRTransform { Vector3D = marker.PRTransform.Vector3D + gizmoLocations[location].Vector3D, Quaternion = new Quaternion { Vector3D = new Vector3D(marker.PRTransform.Quaternion.Vector3D.X, marker.PRTransform.Quaternion.Vector3D.Y, marker.PRTransform.Quaternion.Vector3D.Z), W = marker.PRTransform.Quaternion.W } }; switch (marker.Type) { case MarkerType.Actor: loadActor(marker.SNOHandle, absolutePRTransform, world, marker.TagMap); break; case MarkerType.Encounter: var encounter2 = marker.SNOHandle.Target as Encounter; var actor2 = RandomHelper.RandomItem(encounter2.Spawnoptions, x => x.Probability); loadActor(new SNOHandle(actor2.SNOSpawn), absolutePRTransform, world, marker.TagMap); break; default: Logger.Warn("Unhandled marker type {0} in actor loading", marker.Type); break; } } break; default: if (spawnEntry.SNOHandle.Id != -1) Logger.Warn("Unknown sno handle in LevelArea spawn entries: {0}", spawnEntry.SNOHandle); break; } // dont use that location again gizmoLocations.RemoveAt(location); } } } } }
public TriggerEvent(MpqFileStream stream) { I0 = stream.ReadValueS32(); TriggerConditions = new TriggerConditions(stream); I1 = stream.ReadValueS32(); SNOHandle = new SNOHandle(stream); I2 = stream.ReadValueS32(); I3 = stream.ReadValueS32(); RuneType = stream.ReadValueS32(); UseRuneType = stream.ReadValueS32(); HardPointLinks = new HardPointLink[2]; HardPointLinks[0] = new HardPointLink(stream); HardPointLinks[1] = new HardPointLink(stream); this.LookLink = stream.ReadString(64, true); this.ConstraintLink = stream.ReadString(64, true); I4 = stream.ReadValueS32(); F0 = stream.ReadValueF32(); I5 = stream.ReadValueS32(); I6 = stream.ReadValueS32(); I7 = stream.ReadValueS32(); I8 = stream.ReadValueS32(); I9 = stream.ReadValueS32(); F1 = stream.ReadValueF32(); F2 = stream.ReadValueF32(); I10 = stream.ReadValueS32(); F3 = stream.ReadValueF32(); I11 = stream.ReadValueS32(); Velocity = stream.ReadValueF32(); I12 = stream.ReadValueS32(); Ticks1 = stream.ReadValueS32(); Color1 = new RGBAColor(stream); I14 = stream.ReadValueS32(); Color2 = new RGBAColor(stream); I15 = stream.ReadValueS32(); }
private List<int> completedSteps = new List<int>(); // this list has to be saved if quest progress should be saved. It is required to keep track of questranges public Quest(Game game, int SNOQuest) { this.game = game; //SNOId = SNOQuest; SNOHandle = new SNOHandle() { SNOId = SNOQuest, Group = SNOGroup.Quest }; asset = MPQStorage.Data.Assets[Common.Types.SNO.SNOGroup.Quest][SNOQuest].Data as Mooege.Common.MPQ.FileFormats.Quest; CurrentStep = new QuestStep(asset.QuestUnassignedStep, this); }
public void Read(MpqFileStream stream) { this.Min = stream.ReadValueS32(); this.Max = stream.ReadValueS32(); this.SNOHandle = new SNOHandle(stream); this.I2 = stream.ReadValueS32(); }