private void ValidateDefinitionList(List <TR2Entities> modelEntities) { Dictionary <TR2Entities, List <TR2Entities> > detectedAliases = new Dictionary <TR2Entities, List <TR2Entities> >(); foreach (TR2Entities entity in modelEntities) { if (_entityAliases.ContainsKey(entity)) { TR2Entities masterEntity = _entityAliases[entity]; if (!detectedAliases.ContainsKey(masterEntity)) { detectedAliases[masterEntity] = new List <TR2Entities>(); } detectedAliases[_entityAliases[entity]].Add(entity); } } foreach (TR2Entities masterEntity in detectedAliases.Keys) { if (detectedAliases[masterEntity].Count > 1 && !_permittedAliasDuplicates.Contains(masterEntity)) { throw new TransportException(string.Format ( "Only one alias per entity can exist in the same level. [{0}] were found as aliases for {1}.", string.Join(", ", detectedAliases[masterEntity]), masterEntity.ToString() )); } } }
protected override void StartImpl() { // Make the outfit selection outwith the processing thread to ensure consistent RNG. // We select all potential Laras including the default for the level as there are // only 4 to choose from (there is also Assault Course Lara, but when holstering pistols // her trousers disappear, so she is excluded for the time being...). List <TR2Entities> allLaras = TR2EntityUtilities.GetLaraTypes(); List <TR2CombinedLevel> levels = new List <TR2CombinedLevel>(_outfitAllocations.Keys); foreach (TR2CombinedLevel level in levels) { // Add the persistent outfit first, but we will populate the candidate // list regardless in case a level cannot support this choice. if (_outer.PersistOutfits) { _outfitAllocations[level].Add(_outer._persistentOutfit); } while (_outfitAllocations[level].Count < allLaras.Count) { TR2Entities nextLara = allLaras[_outer._generator.Next(0, allLaras.Count)]; if (!_outfitAllocations[level].Contains(nextLara)) { _outfitAllocations[level].Add(nextLara); } } } }
private void DisguiseEntity(TR2CombinedLevel level, TR2Entities guiser, TR2Entities targetEntity) { List <TRModel> models = level.Data.Models.ToList(); int existingIndex = models.FindIndex(m => m.ID == (short)guiser); if (existingIndex != -1) { models.RemoveAt(existingIndex); } TRModel disguiseAsModel = models[models.FindIndex(m => m.ID == (short)targetEntity)]; if (targetEntity == TR2Entities.BirdMonster && level.Is(LevelNames.CHICKEN)) { // We have to keep the original model for the boss, so in // this instance we just clone the model for the guiser models.Add(new TRModel { Animation = disguiseAsModel.Animation, FrameOffset = disguiseAsModel.FrameOffset, ID = (uint)guiser, MeshTree = disguiseAsModel.MeshTree, NumMeshes = disguiseAsModel.NumMeshes, StartingMesh = disguiseAsModel.StartingMesh }); } else { disguiseAsModel.ID = (uint)guiser; } level.Data.Models = models.ToArray(); level.Data.NumModels = (uint)models.Count; }
public void AddEntity(TR2Entities entity) { if (!Entities.Contains(entity)) { Entities.Add(entity); } }
private TR2Entities GetWeaponAmmo(TR2Entities weapon) { switch (weapon) { case TR2Entities.Shotgun_S_P: return(TR2Entities.ShotgunAmmo_S_P); case TR2Entities.Automags_S_P: return(TR2Entities.AutoAmmo_S_P); case TR2Entities.Uzi_S_P: return(TR2Entities.UziAmmo_S_P); case TR2Entities.Harpoon_S_P: return(TR2Entities.HarpoonAmmo_S_P); case TR2Entities.M16_S_P: return(TR2Entities.M16Ammo_S_P); case TR2Entities.GrenadeLauncher_S_P: return(TR2Entities.Grenades_S_P); default: return(TR2Entities.PistolAmmo_S_P); } }
// roomNumber is specified if ONLY that room is to be populated private void PlaceAllItems(List <Location> locations, int roomNumber = -1, TR2Entities entityToAdd = TR2Entities.LargeMed_S_P, bool transformToLevelSpace = true) { List <TR2Entity> ents = _levelInstance.Data.Entities.ToList(); foreach (Location loc in locations) { Location copy = transformToLevelSpace ? SpatialConverters.TransformToLevelSpace(loc, _levelInstance.Data.Rooms[loc.Room].Info) : loc; if (roomNumber == -1 || roomNumber == copy.Room) { ents.Add(new TR2Entity { TypeID = (short)entityToAdd, Room = Convert.ToInt16(copy.Room), X = copy.X, Y = copy.Y, Z = copy.Z, Angle = 0, Intensity1 = -1, Intensity2 = -1, Flags = 0 }); } } _levelInstance.Data.NumEntities = (uint)ents.Count; _levelInstance.Data.Entities = ents.ToArray(); }
private void AdjustEntities() { // If an entity is marked to be removed but is also in the list // to import, don't remove it in the first place. List <TR2Entities> cleanedEntities = new List <TR2Entities>(); foreach (TR2Entities entity in EntitiesToRemove) { if (_aliasMap.ContainsKey(entity)) { // Check if we have another alias in the import list different from any // in the current level TR2Entities alias = TR2EntityUtilities.GetAliasForLevel(LevelName, entity); TR2Entities importAlias = TR2Entities.Lara; foreach (TR2Entities a in _aliasMap[entity]) { if (EntitiesToImport.Contains(a)) { importAlias = a; break; } } if (alias != importAlias) { cleanedEntities.Add(entity); } } else if (!EntitiesToImport.Contains(entity)) { cleanedEntities.Add(entity); } } EntitiesToRemove = cleanedEntities; }
public TRModelDefinition CreateModelDefinition(TR2Entities modelEntity) { Definition = new TRModelDefinition { Alias = modelEntity }; if (_entityAliases.ContainsKey(modelEntity)) { modelEntity = _entityAliases[modelEntity]; } _modelHandler.ModelEntity = modelEntity; _textureHandler.ExportIndividualSegments = ExportIndividualSegments; _textureHandler.SegmentsFolder = _segmentsFolder; _textureHandler.TextureClassifier = TextureClassifier; _modelHandler.Export(); _meshHandler.Export(); _colourHandler.Export(); _textureHandler.Export(); _animationHandler.Export(); _cinematicHandler.Export(); _soundHandler.Export(); ExportDependencies(); return(_definition); }
public static int GetRestrictedEnemyLevelCount(TR2Entities entity) { if (_restrictedEnemyLevelCounts.ContainsKey(entity)) { return(_restrictedEnemyLevelCounts[entity]); } return(-1); }
private void SetPersistentOutfit() { if (PersistOutfits) { List <TR2Entities> allLaras = TR2EntityUtilities.GetLaraTypes(); _persistentOutfit = allLaras[_generator.Next(0, allLaras.Count)]; } }
public static bool IsAmmoType(TR2Entities entity) { return(entity == TR2Entities.ShotgunAmmo_S_P || entity == TR2Entities.AutoAmmo_S_P || entity == TR2Entities.UziAmmo_S_P || entity == TR2Entities.HarpoonAmmo_S_P || entity == TR2Entities.M16Ammo_S_P || entity == TR2Entities.Grenades_S_P); }
private void PopulateVehicleLocation(TR2Entities entity, Dictionary <TR2Entities, Location> locationMap) { Location location = VehicleUtilities.GetRandomLocation(_levelInstance.Name, entity, _generator); if (location != null) { locationMap[entity] = location; } }
private void BuildDefinitionList(List <TRModelDefinition> standardModelDefinitions, List <TRModelDefinition> soundModelDefinitions, List <TR2Entities> modelEntities, TR2Entities nextEntity, bool isDependency) { if (modelEntities.Contains(nextEntity)) { // If the model already in the list is a dependency only, but the new one to add isn't, switch it TRModelDefinition definition = standardModelDefinitions.Find(m => m.Alias == nextEntity); if (definition != null && definition.IsDependencyOnly && !isDependency) { definition.IsDependencyOnly = false; } return; } TRModelDefinition nextDefinition = LoadDefinition(nextEntity); nextDefinition.IsDependencyOnly = isDependency; modelEntities.Add(nextEntity); // Add dependencies first foreach (TR2Entities dependency in nextDefinition.Dependencies) { // If it's a non-graphics dependency, but we are importing another alias // for it, or the level already contains the dependency, we don't need it. bool nonGraphics = _noGraphicsEntityDependencies.Contains(dependency); TR2Entities aliasFor = TR2EntityUtilities.TranslateEntityAlias(dependency); if (aliasFor != dependency && nonGraphics) { bool required = true; // #139 check entire model list for instances where alias and dependencies cause clashes foreach (TR2Entities entity in modelEntities) { // If this entity and the dependency are in the same family if (aliasFor == TR2EntityUtilities.TranslateEntityAlias(entity)) { // Skip it required = false; break; } } if (!required) { // We don't need the graphics, but do we need hardcoded sound? if (_soundOnlyDependencies.Contains(dependency) && standardModelDefinitions.Find(m => m.Alias == dependency) == null) { soundModelDefinitions.Add(LoadDefinition(dependency)); } continue; } } BuildDefinitionList(standardModelDefinitions, soundModelDefinitions, modelEntities, dependency, nonGraphics); } standardModelDefinitions.Add(nextDefinition); }
public static bool IsEnemySupported(string lvlName, TR2Entities entity) { if (_unsupportedEnemies.ContainsKey(lvlName)) { return(!_unsupportedEnemies[lvlName].Contains(TR2EntityUtilities.TranslateEntityAlias(entity))); } return(true); }
public static bool IsGunType(TR2Entities entity) { return(entity == TR2Entities.Shotgun_S_P || entity == TR2Entities.Automags_S_P || entity == TR2Entities.Uzi_S_P || entity == TR2Entities.Harpoon_S_P || entity == TR2Entities.M16_S_P || entity == TR2Entities.GrenadeLauncher_S_P); }
public static List <TR2Entities> GetEnemyGuisers(TR2Entities entity) { List <TR2Entities> entities = new List <TR2Entities>(); if (_enemyGuisers.ContainsKey(entity)) { entities.AddRange(_enemyGuisers[entity]); } return(entities); }
public static TRModel GetModel(TR2Level level, TR2Entities entity) { int i = level.Models.ToList().FindIndex(e => e.ID == (uint)entity); if (i != -1) { return(level.Models[i]); } return(null); }
public static TRMesh[] GetModelMeshes(TR2Level level, TR2Entities entity) { TRModel model = GetModel(level, entity); if (model != null) { return(GetModelMeshes(level, model)); } return(null); }
public void RemoveModelSegmentsChecked(IEnumerable <TR2Entities> modelEntitiesToRemove) { // Perform an exhaustive check against every other model in the level to find shared textures. Dictionary <TR2Entities, Dictionary <TexturedTile, List <TexturedTileSegment> > > candidateSegments = new Dictionary <TR2Entities, Dictionary <TexturedTile, List <TexturedTileSegment> > >(); // First cache each segment for the models we wish to remove foreach (TR2Entities modelEntity in modelEntitiesToRemove) { candidateSegments[modelEntity] = GetModelSegments(modelEntity); } // Load the segments for every other model in the level. For each, scan the segments of // the removal candidates. If any is used by any other model, the segment is no longer // a candidate. If the other model that shares it is in the list to remove, it will // remain a candidate. foreach (TRModel model in Level.Models) { TR2Entities otherEntity = (TR2Entities)model.ID; if (modelEntitiesToRemove.Contains(otherEntity)) { continue; } Dictionary <TexturedTile, List <TexturedTileSegment> > modelSegments = GetModelSegments(otherEntity); foreach (TR2Entities entityToRemove in modelEntitiesToRemove) { Dictionary <TexturedTile, List <TexturedTileSegment> > entityMap = candidateSegments[entityToRemove]; foreach (TexturedTile tile in entityMap.Keys) { if (modelSegments.ContainsKey(tile)) { int match = entityMap[tile].FindIndex(s1 => modelSegments[tile].Any(s2 => s1 == s2)); if (match != -1) { //System.Diagnostics.Debug.WriteLine("\t\t" + otherEntity + ", " + tile.Index + ": " + entityMap[tile][match].Bounds); entityMap[tile].RemoveAt(match); } } } } } // Tell each tile to remove the candidate segments foreach (Dictionary <TexturedTile, List <TexturedTileSegment> > segmentMap in candidateSegments.Values) { foreach (TexturedTile tile in segmentMap.Keys) { foreach (TexturedTileSegment segment in segmentMap[tile]) { tile.Remove(segment); } } } }
public static TR2Entities TranslateEntityAlias(TR2Entities entity) { foreach (TR2Entities parentEntity in EntityFamilies.Keys) { if (EntityFamilies[parentEntity].Contains(entity)) { return(parentEntity); } } return(entity); }
private void AdjustOutfit(TR2CombinedLevel level, TR2Entities lara) { if (level.Is(LevelNames.HOME) && lara != TR2Entities.LaraHome) { // This ensures that Lara's hips match the new outfit for the starting animation and shower cutscene, // otherwise the dressing gown hips are rendered, but the mesh is completely different for this, plus // its textures will have been removed. TRMesh laraMiscMesh = TR2LevelUtilities.GetModelFirstMesh(level.Data, TR2Entities.LaraMiscAnim_H); TRMesh laraHipsMesh = TR2LevelUtilities.GetModelFirstMesh(level.Data, TR2Entities.Lara); TR2LevelUtilities.DuplicateMesh(level.Data, laraMiscMesh, laraHipsMesh); } }
private void CleanAliases() { List <TR2Entities> cleanedEntities = new List <TR2Entities>(); // Do we have any aliases? foreach (TR2Entities importEntity in EntitiesToImport) { if (_aliasMap.ContainsKey(importEntity)) { throw new TransportException(string.Format ( "Cannot import ambiguous entity {0} - choose an alias from [{1}].", importEntity.ToString(), string.Join(", ", _aliasMap[importEntity]) )); } bool entityIsValid = true; if (_entityAliases.ContainsKey(importEntity)) { TR2Entities existingEntity = TR2EntityUtilities.GetAliasForLevel(LevelName, _entityAliases[importEntity]); // This entity is only valid if the alias it's for is not already there entityIsValid = importEntity != existingEntity; } if (entityIsValid) { cleanedEntities.Add(importEntity); } } // #139 Ensure that aliases are added last so to avoid dependency issues cleanedEntities.Sort(delegate(TR2Entities e1, TR2Entities e2) { return(((short)TR2EntityUtilities.TranslateEntityAlias(e1)).CompareTo((short)TR2EntityUtilities.TranslateEntityAlias(e2))); }); // For some reason, if the Barracuda is added before the shark, there is a slight animation // corruption on the shark's mouth. I can't find the reason. The patch is to ensure the // Barracuda is added last. // #137 Reason found - animated textures were not being reindexed following deduplication. See // TRModelExtensions.ReindexTextures and #137. /*int barracudaIndex = cleanedEntities.FindIndex(e => _aliasMap[TR2Entities.Barracuda].Contains(e)); * if (barracudaIndex != -1) * { * TR2Entities barracuda = cleanedEntities[barracudaIndex]; * cleanedEntities.RemoveAt(barracudaIndex); * cleanedEntities.Add(barracuda); * }*/ EntitiesToImport = cleanedEntities; }
public static bool IsUtilityType(TR2Entities entity) { return(entity == TR2Entities.ShotgunAmmo_S_P || entity == TR2Entities.AutoAmmo_S_P || entity == TR2Entities.UziAmmo_S_P || entity == TR2Entities.HarpoonAmmo_S_P || entity == TR2Entities.M16Ammo_S_P || entity == TR2Entities.Grenades_S_P || entity == TR2Entities.SmallMed_S_P || entity == TR2Entities.LargeMed_S_P || entity == TR2Entities.Flares_S_P); }
public StaticTextureSource[] GetStaticSource(TR2Entities entity) { List <StaticTextureSource> sources = new List <StaticTextureSource>(); if (_entityMap.ContainsKey(entity)) { foreach (string src in _entityMap[entity]) { sources.Add(GetStaticSource(src)); } } return(sources.ToArray()); }
private void CopyEntity(TR2Entity entity, TR2Entities newType) { List <TR2Entity> ents = _levelInstance.Data.Entities.ToList(); if (ents.Count < _levelInstance.GetMaximumEntityLimit()) { TR2Entity copy = entity.Clone(); copy.TypeID = (short)newType; ents.Add(copy); _levelInstance.Data.NumEntities++; _levelInstance.Data.Entities = ents.ToArray(); } }
private StaticTextureSource[] GetSources(TR2Entities entity) { List <StaticTextureSource> sources = new List <StaticTextureSource>(); foreach (StaticTextureSource source in _entitySources) { if (source.EntityTextureMap.ContainsKey(entity)) { sources.Add(source); } } return(sources.ToArray()); }
public static bool IsKeyItemType(TR2Entities entity) { return(entity == TR2Entities.Key1_S_P || entity == TR2Entities.Key2_S_P || entity == TR2Entities.Key3_S_P || entity == TR2Entities.Key4_S_P || entity == TR2Entities.Puzzle1_S_P || entity == TR2Entities.Puzzle2_S_P || entity == TR2Entities.Puzzle3_S_P || entity == TR2Entities.Puzzle4_S_P || entity == TR2Entities.Quest1_S_P || entity == TR2Entities.Quest2_S_P); }
public static TR2Entities GetAliasForLevel(string lvl, TR2Entities entity) { if (LevelEntityAliases.ContainsKey(entity)) { foreach (TR2Entities alias in LevelEntityAliases[entity].Keys) { if (LevelEntityAliases[entity][alias].Contains(lvl)) { return(alias); } } } return(entity); }
public static List <TR2Entities> GetEntityFamily(TR2Entities entity) { foreach (TR2Entities parentEntity in EntityFamilies.Keys) { if (EntityFamilies[parentEntity].Contains(entity)) { return(EntityFamilies[parentEntity]); } } return(new List <TR2Entities> { entity }); }
public static bool IsWaterEnemyRequired(TR2CombinedLevel level) { foreach (TR2Entity entityInstance in level.Data.Entities) { TR2Entities entity = (TR2Entities)entityInstance.TypeID; if (TR2EntityUtilities.IsWaterCreature(entity)) { if (!level.CanPerformDraining(entityInstance.Room)) { // Draining cannot be performed so we need to ensure we get at least one water enemy return(true); } } } return(false); }