protected override void FSMUpdate() { if (CurrentState != null && isServer) { CurrentState.Reason(); CurrentState.Act(); // If we don't have a target, do nothing if (Target == null) { return; } // If the target is NOT in front of us if (EnemyUtilities.GetAngle(transform, Target) > 1) { // We want to slowly increase out rotation speed multiplier RotationMultiplier = Mathf.Lerp(RotationMultiplier, 2.5f, Time.deltaTime * 0.5f); } else { // Else we are looking at the target RotationMultiplier = Mathf.Lerp(RotationMultiplier, 1f, Time.deltaTime * 0.5f); } // Look at the target float rotSpeed = RotationSpeed * RotationMultiplier; Quaternion neededRotation = Quaternion.LookRotation(Target.position - transform.position, transform.up); transform.rotation = Quaternion.Slerp(transform.rotation, neededRotation, Time.deltaTime * rotSpeed); // Move forward transform.position += transform.forward * MoveSpeed * Time.deltaTime; } }
void OnTriggerEnter2D(Collider2D other) { //Entra al collider other.gameObject.GetComponent <genericEnemy>().inField = true; //Calcular el resultado del enemigo. other.gameObject.GetComponent <genericEnemy>().enemyResult = EnemyUtilities.getEnemyResult(other.gameObject.GetComponent <genericEnemy>().enemyType, other.gameObject); //Emitir el sonido other.gameObject.GetComponent <AudioSource>().Play(); }
// Use this for initialization protected void Start() { //Set the rigidbodys mass _rb = gameObject.GetComponent <Rigidbody2D>(); _rb.mass = _mass; _controller = gameObject.GetComponent <Controller>(); _getUpTicker = _getUpDelay; _enemyUtilites = gameObject.GetComponent <EnemyUtilities>(); _attackTicker = _attackDelay; _animator = gameObject.GetComponentInChildren <Animator>(); }
/*public genericEnemy(int numBalls, float speed, string iniPos){ * enemyElements = numBalls; * enemySpeed = speed; * enemySpawnPos = EnemyUtilities.setEnemyIniPos(iniPos); * enemySpawnPosS = iniPos; * }*/ // Use this for initialization void Start() { //Obtener el objeto controlador para determinar el tiempo y con ello la velocidad. gameController = GameObject.Find("GameController"); //Desactivar las pelotas de alrededor de la central EnemyUtilities.deActiveEnemyElements(gameObject); //Establecer el tipo de enemigo enemyType = "sumEnemy"; //Establecer el numero de elementos del enemigo segun el tiempo de juego. enemyElements = EnemyUtilities.setEnemyBalls(gameController.GetComponent <gameController>().gameTime); //Activar en pantalla el numero de elementos del enemigo EnemyUtilities.activeEnemyElements(gameObject, enemyElements); //Obtener el resultado del enemigo, a partir de su tipo. //Dependiendo del tipo es como se calculca el resultado. enemyResult = EnemyUtilities.getEnemyResult(enemyType, gameObject); //Obtener la posicicion en la que se emite el enmigo //Obtener la posicion inicial de donde se emite el enemigo. enemySpawnPos.x = gameObject.transform.position.x; enemySpawnPos.y = gameObject.transform.position.y; enemySpawnPosS = EnemyUtilities.setEnemyIniPos(enemySpawnPos.x, enemySpawnPos.y); //Establecer la velocidad del enemigo, segun el tipo y la posicion en que se emite enemySpeed = EnemyUtilities.setEnemySpeed(enemyElements, enemySpawnPosS); //Establecer los puntos que se generar por eliminar al enemigo enemyPoints = EnemyUtilities.setEnemyPoints(enemyElements, enemyType); randomType = 0; randomDisType = Random.Range(0, 2); randomDis = Random.Range(-2.0f, 2.0f); invert = Random.Range(0, 99); inField = false; //Si es una funcion exponencial, disminuir la velocidad. //Cuadrado if (randomType == 1) { enemySpeed = 1.0f; } //Cubo if (randomType == 2) { enemySpeed = 0.75f; } }
//Checar el resultado IEnumerator checkResult() { if (EnemyUtilities.getResultBox() == enemyResult) { //Detener al enemigo enemySpeed = 0.0f; //Animación destrucción. EnemyUtilities.enemyDestruction(gameObject); //Borrar la caja de resultados yield return(new WaitForSeconds(0.1f)); EnemyUtilities.eraseResultBox(); //Actualizar el score yield return(new WaitForSeconds(0.3f)); EnemyUtilities.updateScore(20); Destroy(gameObject); } }
private void Start() { enemyUtilities = GetComponent <EnemyUtilities>(); }
// Start is called before the first frame update void Start() { util = this.GetComponent <EnemyUtilities>(); pacing = this.GetComponent <EnemyPacing>(); combat = this.GetComponent <EnemyCombat>(); }
private void RandomizeEnemiesCrossLevel() { MaxPackingAttempts = Math.Max(1, MaxPackingAttempts); SetMessage("Randomizing enemies - loading levels"); List <EnemyProcessor> processors = new List <EnemyProcessor>(); for (int i = 0; i < _maxThreads; i++) { processors.Add(new EnemyProcessor(this)); } List <TR2CombinedLevel> levels = new List <TR2CombinedLevel>(Levels.Count); foreach (TR23ScriptedLevel lvl in Levels) { levels.Add(LoadCombinedLevel(lvl)); if (!TriggerProgress()) { return; } } // Sort the levels so each thread has a fairly equal weight in terms of import cost/time levels.Sort(new TR2LevelTextureWeightComparer()); int processorIndex = 0; foreach (TR2CombinedLevel level in levels) { processors[processorIndex].AddLevel(level); processorIndex = processorIndex == _maxThreads - 1 ? 0 : processorIndex + 1; } // Track enemies whose counts across the game are restricted _gameEnemyTracker = EnemyUtilities.PrepareEnemyGameTracker(DocileBirdMonsters); SetMessage("Randomizing enemies - importing models"); foreach (EnemyProcessor processor in processors) { processor.Start(); } foreach (EnemyProcessor processor in processors) { processor.Join(); } if (!SaveMonitor.IsCancelled && _processingException == null) { SetMessage("Randomizing enemies - saving levels"); foreach (EnemyProcessor processor in processors) { processor.ApplyRandomization(); } } if (_processingException != null) { throw _processingException; } }
private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollection enemies) { bool shotgunGoonSeen = level.Is(LevelNames.HOME); // 1 ShotgunGoon in HSH only bool dragonSeen = level.Is(LevelNames.LAIR); // 1 Marco in DL only // Get a list of current enemy entities List <TR2Entity> enemyEntities = level.GetEnemyEntities(); // Keep track of any new entities added (e.g. Skidoo) List <TR2Entity> newEntities = new List <TR2Entity>(); // #148 If it's HSH and we have been able to import cross-level, we will add 15 // dogs outside the gate to ensure the kill counter works. Dogs, Goon1 and // StickGoons will have been excluded from the cross-level pool for simplicity // Their textures will have been removed but they won't spawn anyway as we aren't // defining triggers - the game only needs them to be present in the entity list. if (level.Is(LevelNames.HOME) && !enemies.Available.Contains(TR2Entities.Doberman)) { for (int i = 0; i < 15; i++) { newEntities.Add(new TR2Entity { TypeID = (short)TR2Entities.Doberman, Room = 85, X = 61919, Y = 2560, Z = 74222, Angle = 16384, Flags = 0, Intensity1 = -1, Intensity2 = -1 }); } } // First iterate through any enemies that are restricted by room Dictionary <TR2Entities, List <int> > enemyRooms = EnemyUtilities.GetRestrictedEnemyRooms(level.Name); if (enemyRooms != null) { foreach (TR2Entities entity in enemyRooms.Keys) { if (!enemies.Available.Contains(entity)) { continue; } List <int> rooms = enemyRooms[entity]; int maxEntityCount = EnemyUtilities.GetRestrictedEnemyLevelCount(entity); if (maxEntityCount == -1) { // We are allowed any number, but this can't be more than the number of unique rooms, // so we will assume 1 per room as these restricted enemies are likely to be tanky. maxEntityCount = rooms.Count; } else { maxEntityCount = Math.Min(maxEntityCount, rooms.Count); } // Pick an actual count int enemyCount = _generator.Next(1, maxEntityCount + 1); for (int i = 0; i < enemyCount; i++) { // Find an entity in one of the rooms that the new enemy is restricted to TR2Entity targetEntity = null; do { int room = enemyRooms[entity][_generator.Next(0, enemyRooms[entity].Count)]; targetEntity = enemyEntities.Find(e => e.Room == room); }while (targetEntity == null); targetEntity.TypeID = (short)TR2EntityUtilities.TranslateEntityAlias(entity); // #146 Ensure OneShot triggers are set for this enemy if needed EnemyUtilities.SetEntityTriggers(level.Data, targetEntity); // Remove the target entity so it doesn't get replaced enemyEntities.Remove(targetEntity); } // Remove this entity type from the available rando pool enemies.Available.Remove(entity); } } foreach (TR2Entity currentEntity in enemyEntities) { TR2Entities currentEntityType = (TR2Entities)currentEntity.TypeID; TR2Entities newEntityType = currentEntityType; // If it's an existing enemy that has to remain in the same spot, skip it if (EnemyUtilities.IsEnemyRequired(level.Name, currentEntityType)) { continue; } //#45 - Check to see if any items are at the same location as the enemy. //If there are we need to ensure that the new random enemy type is one that can drop items. List <TR2Entity> sharedItems = new List <TR2Entity>(Array.FindAll ( level.Data.Entities, e => ( e.X == currentEntity.X && e.Y == currentEntity.Y && e.Z == currentEntity.Z ) )); //Do multiple entities share one location? bool isPickupItem = false; if (sharedItems.Count > 1 && enemies.Droppable.Count != 0) { //Are any entities sharing a location a droppable pickup? foreach (TR2Entity ent in sharedItems) { TR2Entities entType = (TR2Entities)ent.TypeID; isPickupItem = TR2EntityUtilities.IsUtilityType(entType) || TR2EntityUtilities.IsGunType(entType) || TR2EntityUtilities.IsKeyItemType(entType); if (isPickupItem) { break; } } //Generate a new type newEntityType = enemies.Available[_generator.Next(0, enemies.Available.Count)]; //Do we need to ensure the enemy can drop the item on the same tile? if (!TR2EntityUtilities.CanDropPickups(newEntityType, !ProtectMonks) && isPickupItem) { //Ensure the new random entity can drop pickups newEntityType = enemies.Droppable[_generator.Next(0, enemies.Droppable.Count)]; } } else { //Generate a new type newEntityType = enemies.Available[_generator.Next(0, enemies.Available.Count)]; } short roomIndex = currentEntity.Room; TR2Room room = level.Data.Rooms[roomIndex]; if (level.Is(LevelNames.DA) && roomIndex == 77) { // Make sure the end level trigger isn't blocked by an unkillable enemy while (TR2EntityUtilities.IsHazardCreature(newEntityType) || (ProtectMonks && TR2EntityUtilities.IsMonk(newEntityType))) { newEntityType = enemies.Available[_generator.Next(0, enemies.Available.Count)]; } } if (TR2EntityUtilities.IsWaterCreature(currentEntityType) && !TR2EntityUtilities.IsWaterCreature(newEntityType)) { // Check alternate rooms too - e.g. rooms 74/48 in 40 Fathoms short roomDrainIndex = -1; if (room.ContainsWater) { roomDrainIndex = roomIndex; } else if (room.AlternateRoom != -1 && level.Data.Rooms[room.AlternateRoom].ContainsWater) { roomDrainIndex = room.AlternateRoom; } if (roomDrainIndex != -1 && !level.PerformDraining(roomDrainIndex)) { // Draining cannot be performed so make the entity a water creature. // The list of provided water creatures will either be those native // to this level, or if randomizing cross-level, a pre-check will // have already been performed on draining so if it's not possible, // at least one water creature will be available. newEntityType = enemies.Water[_generator.Next(0, enemies.Water.Count)]; } } // Ensure that if we have to pick a different enemy at this point that we still // honour any pickups in the same spot. List <TR2Entities> enemyPool = isPickupItem ? enemies.Droppable : enemies.Available; if (newEntityType == TR2Entities.ShotgunGoon && shotgunGoonSeen) // HSH only { while (newEntityType == TR2Entities.ShotgunGoon) { newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; } } if (newEntityType == TR2Entities.MarcoBartoli && dragonSeen) // DL only, other levels use quasi-zoning for the dragon { while (newEntityType == TR2Entities.MarcoBartoli) { newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; } } // If we are restricting count per level for this enemy and have reached that count, pick // someting else. This applies when we are restricting by in-level count, but not by room // (e.g. Winston). int maxEntityCount = EnemyUtilities.GetRestrictedEnemyLevelCount(newEntityType); if (maxEntityCount != -1) { if (level.Data.Entities.ToList().FindAll(e => e.TypeID == (short)newEntityType).Count == maxEntityCount) { TR2Entities tmp = newEntityType; while (newEntityType == tmp) { newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; } } } // #158 Several entity freezing issues have been found with various enemy // combinations in Barkhang, so for now all Mercenary1 and MonkWithLongStick // entities must remain in place, and no additional ones should be added. if (level.Is(LevelNames.MONASTERY)) { while (EnemyUtilities.IsEnemyRequired(level.Name, newEntityType)) { newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; } } // #144 Disguise something as the Chicken. Pre-checks will have been done to ensure // the guiser is suitable for the level. if (DocileBirdMonsters && newEntityType == TR2Entities.BirdMonster) { newEntityType = enemies.BirdMonsterGuiser; } // Make sure to convert BengalTiger, StickWieldingGoonBandana etc back to their actual types currentEntity.TypeID = (short)TR2EntityUtilities.TranslateEntityAlias(newEntityType); // #146 Ensure OneShot triggers are set for this enemy if needed. This currently only applies // to the dragon, which will be handled above in defined rooms, but the check should be made // here in case this needs to be extended later. EnemyUtilities.SetEntityTriggers(level.Data, currentEntity); } // MercSnowMobDriver relies on RedSnowmobile so it will be available in the model list if (!level.Is(LevelNames.TIBET)) { TR2Entity mercDriver = level.Data.Entities.ToList().Find(e => e.TypeID == (short)TR2Entities.MercSnowmobDriver); if (mercDriver != null) { short room, angle; int x, y, z; // we will only spawn one skidoo, so only need one random location Location randomLocation = VehicleUtilities.GetRandomLocation(level.Name, TR2Entities.RedSnowmobile, _generator); if (randomLocation != null) { room = (short)randomLocation.Room; x = randomLocation.X; y = randomLocation.Y; z = randomLocation.Z; angle = randomLocation.Angle; } else { // if the level does not have skidoo locations for some reason, just spawn it on the MercSnowMobDriver room = mercDriver.Room; x = mercDriver.X; y = mercDriver.Y; z = mercDriver.Z; angle = mercDriver.Angle; } newEntities.Add(new TR2Entity { TypeID = (short)TR2Entities.RedSnowmobile, Room = room, X = x, Y = y, Z = z, Angle = angle, Flags = 0, Intensity1 = -1, Intensity2 = -1 }); } } // Did we add any new entities? if (newEntities.Count > 0) { List <TR2Entity> levelEntities = level.Data.Entities.ToList(); levelEntities.AddRange(newEntities); level.Data.Entities = levelEntities.ToArray(); level.Data.NumEntities = (uint)levelEntities.Count; } }
private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, int reduceEnemyCountBy = 0) { // For the assault course, nothing will be imported for the time being if (level.IsAssault) { return(null); } // Get the list of enemy types currently in the level List <TR2Entities> oldEntities = TR2EntityUtilities.GetEnemyTypeDictionary()[level.Name]; // Work out how many we can support int enemyCount = oldEntities.Count - reduceEnemyCountBy + EnemyUtilities.GetEnemyAdjustmentCount(level.Name); List <TR2Entities> newEntities = new List <TR2Entities>(enemyCount); List <TR2Entities> chickenGuisers = EnemyUtilities.GetEnemyGuisers(TR2Entities.BirdMonster); TR2Entities chickenGuiser = TR2Entities.BirdMonster; // #148 For HSH, we lock the enemies that are required for the kill counter to work outside // the gate, which means the game still has the correct target kill count, while allowing // us to randomize the ones inside the gate (except the final shotgun goon). // If however, we are on the final packing attempt, we will just change the stick goon // alias and add docile bird monsters (if selected) as this is known to be supported. if (level.Is(LevelNames.HOME) && reduceEnemyCountBy > 0) { TR2Entities newGoon = TR2Entities.StickWieldingGoon1BlackJacket; List <TR2Entities> goonies = TR2EntityUtilities.GetEntityFamily(newGoon); do { newGoon = goonies[_generator.Next(0, goonies.Count)]; }while (newGoon == TR2Entities.StickWieldingGoon1BlackJacket); newEntities.AddRange(oldEntities); newEntities.Remove(TR2Entities.StickWieldingGoon1); newEntities.Add(newGoon); if (DocileBirdMonsters) { newEntities.Remove(TR2Entities.MaskedGoon1); newEntities.Add(TR2Entities.BirdMonster); chickenGuiser = TR2Entities.MaskedGoon1; } } else { // Do we need at least one water creature? bool waterEnemyRequired = EnemyUtilities.IsWaterEnemyRequired(level); // Do we need at least one enemy that can drop? bool droppableEnemyRequired = EnemyUtilities.IsDroppableEnemyRequired(level); // Let's try to populate the list. Start by adding one water enemy // and one droppable enemy if they are needed. if (waterEnemyRequired) { List <TR2Entities> waterEnemies = TR2EntityUtilities.KillableWaterCreatures(); TR2Entities entity; do { entity = waterEnemies[_generator.Next(0, waterEnemies.Count)]; }while (!EnemyUtilities.IsEnemySupported(level.Name, entity)); newEntities.Add(entity); } if (droppableEnemyRequired) { List <TR2Entities> droppableEnemies = TR2EntityUtilities.GetCrossLevelDroppableEnemies(!ProtectMonks); TR2Entities entity; do { entity = droppableEnemies[_generator.Next(0, droppableEnemies.Count)]; }while (!EnemyUtilities.IsEnemySupported(level.Name, entity)); newEntities.Add(entity); } // Are there any other types we need to retain? foreach (TR2Entities entity in EnemyUtilities.GetRequiredEnemies(level.Name)) { if (!newEntities.Contains(entity)) { newEntities.Add(entity); } } // Get all other candidate enemies and fill the list List <TR2Entities> allEnemies = TR2EntityUtilities.GetCandidateCrossLevelEnemies(); while (newEntities.Count < newEntities.Capacity) { TR2Entities entity = allEnemies[_generator.Next(0, allEnemies.Count)]; // Make sure this isn't known to be unsupported in the level if (!EnemyUtilities.IsEnemySupported(level.Name, entity)) { continue; } // If it's the chicken in HSH but we're not using docile, we don't want it ending the level if (!DocileBirdMonsters && entity == TR2Entities.BirdMonster && level.Is(LevelNames.HOME)) { continue; } // If it's a docile chicken in Barkhang, it won't work because we can't disguise monks in this level. if (DocileBirdMonsters && entity == TR2Entities.BirdMonster && level.Is(LevelNames.MONASTERY)) { continue; } // If this is a tracked enemy throughout the game, we only allow it if the number // of unique levels is within the limit. Bear in mind we are collecting more than // one group of enemies per level. if (_gameEnemyTracker.ContainsKey(entity) && !_gameEnemyTracker[entity].Contains(level.Name)) { if (_gameEnemyTracker[entity].Count < _gameEnemyTracker[entity].Capacity) { // The entity is allowed, so store the fact that this level will have it _gameEnemyTracker[entity].Add(level.Name); } else { // Otherwise, pick something else continue; } } // GetEntityFamily returns all aliases for the likes of the tigers, but if an entity // doesn't have any, the returned list just contains the entity itself. This means // we can avoid duplicating standard enemies as well as avoiding alias-clashing. List <TR2Entities> family = TR2EntityUtilities.GetEntityFamily(entity); if (!newEntities.Any(e1 => family.Any(e2 => e1 == e2))) { // #144 We can include docile chickens provided we aren't including everything // that can be disguised as a chicken. if (DocileBirdMonsters) { bool guisersAvailable = !chickenGuisers.All(g => newEntities.Contains(g)); // If the selected entity is the chicken, it can be added provided there are // available guisers. if (!guisersAvailable && entity == TR2Entities.BirdMonster) { continue; } // If the selected entity is a potential guiser, it can only be added if it's not // the last available guiser. Otherwise, it will become the guiser. if (chickenGuisers.Contains(entity) && newEntities.Contains(TR2Entities.BirdMonster)) { if (newEntities.FindAll(e => chickenGuisers.Contains(e)).Count == chickenGuisers.Count - 1) { continue; } } } newEntities.Add(entity); } } } // #144 Decide at this point who will be guising unless it has already been decided above (e.g. HSH) if (DocileBirdMonsters && newEntities.Contains(TR2Entities.BirdMonster) && chickenGuiser == TR2Entities.BirdMonster) { int guiserIndex = chickenGuisers.FindIndex(g => !newEntities.Contains(g)); if (guiserIndex != -1) { chickenGuiser = chickenGuisers[guiserIndex]; } } return(new EnemyTransportCollection { EntitiesToImport = newEntities, EntitiesToRemove = oldEntities, BirdMonsterGuiser = chickenGuiser }); }
private void RandomizeORPistol() { //Is there something in the unarmed level pistol location? if (_unarmedLevelPistolIndex != -1) { List <TR2Entities> ReplacementWeapons = TR2EntityUtilities.GetListOfGunTypes(); ReplacementWeapons.Add(TR2Entities.Pistols_S_P); TR2Entities Weap = ReplacementWeapons[_generator.Next(0, ReplacementWeapons.Count)]; if (_levelInstance.Is(LevelNames.CHICKEN)) { // Grenade Launcher and Harpoon cannot trigger the bells in Ice Palace while (Weap.Equals(TR2Entities.GrenadeLauncher_S_P) || Weap.Equals(TR2Entities.Harpoon_S_P)) { Weap = ReplacementWeapons[_generator.Next(0, ReplacementWeapons.Count)]; } } TR2Entity unarmedLevelWeapons = _levelInstance.Data.Entities[_unarmedLevelPistolIndex]; uint ammoToGive = 0; bool addPistols = false; uint smallMediToGive = 0; uint largeMediToGive = 0; if (_startingAmmoToGive.ContainsKey(Weap)) { ammoToGive = _startingAmmoToGive[Weap]; if (PerformEnemyWeighting) { // Create a score based on each type of enemy in this level and increase the ammo count based on this EnemyDifficulty difficulty = EnemyUtilities.GetEnemyDifficulty(_levelInstance.GetEnemyEntities()); ammoToGive *= (uint)difficulty; // Depending on how difficult the enemy combination is, allocate some extra helpers. addPistols = difficulty > EnemyDifficulty.Easy; if (difficulty == EnemyDifficulty.Medium || difficulty == EnemyDifficulty.Hard) { smallMediToGive++; } if (difficulty > EnemyDifficulty.Medium) { largeMediToGive++; } if (difficulty == EnemyDifficulty.VeryHard) { largeMediToGive++; } } else if (_levelInstance.Is(LevelNames.LAIR)) { ammoToGive *= 6; } } //#68 - Provide some additional ammo for a weapon if not pistols if (Weap != TR2Entities.Pistols_S_P) { AddORAmmo(GetWeaponAmmo(Weap), ammoToGive, unarmedLevelWeapons); } unarmedLevelWeapons.TypeID = (short)Weap; if (Weap != TR2Entities.Pistols_S_P) { // If we haven't decided to add the pistols (i.e. for enemy difficulty) // add a 1/3 chance of getting them anyway. #149 If the harpoon is being // given, the pistols will be included. if (addPistols || Weap == TR2Entities.Harpoon_S_P || _generator.Next(0, 3) == 0) { CopyEntity(unarmedLevelWeapons, TR2Entities.Pistols_S_P); } } for (int i = 0; i < smallMediToGive; i++) { CopyEntity(unarmedLevelWeapons, TR2Entities.SmallMed_S_P); } for (int i = 0; i < largeMediToGive; i++) { CopyEntity(unarmedLevelWeapons, TR2Entities.LargeMed_S_P); } } }
private void Start() { util = GetComponent <EnemyUtilities>(); ogHorzSpeed = util.horzSpeed; }