private bool CanStartEventSet(EventSet eventSet) { ISpatialEntity refEntity = GetRefEntity(); float distFromStart = Vector2.Distance(refEntity.WorldPosition, level.StartPosition); float distFromEnd = Vector2.Distance(refEntity.WorldPosition, level.EndPosition); //don't create new events if within 50 meters of the start/end of the level if (!eventSet.AllowAtStart) { if (distanceTraveled <= 0.0f || distFromStart * Physics.DisplayToRealWorldRatio < 50.0f || distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f) { return(false); } } if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) && roundDuration < eventSet.MinMissionTime) { return(false); } if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity) { return(false); } return(true); }
private void LoadMonster(CharacterPrefab monsterPrefab, XElement element, Submarine submarine) { string[] moduleFlags = element.GetAttributeStringArray("moduleflags", null); string[] spawnPointTags = element.GetAttributeStringArray("spawnpointtags", null); ISpatialEntity spawnPos = SpawnAction.GetSpawnPos(SpawnAction.SpawnLocationType.Outpost, SpawnType.Enemy, moduleFlags, spawnPointTags, element.GetAttributeBool("asfaraspossible", false)); if (spawnPos == null) { spawnPos = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandom(); } Character spawnedCharacter = Character.Create(monsterPrefab.Identifier, spawnPos.WorldPosition, ToolBox.RandomSeed(8), createNetworkEvent: false); characters.Add(spawnedCharacter); if (element.GetAttributeBool("requirekill", false)) { requireKill.Add(spawnedCharacter); } if (spawnedCharacter.Inventory != null) { characterItems.Add(spawnedCharacter, spawnedCharacter.Inventory.FindAllItems(recursive: true)); } if (submarine != null && spawnedCharacter.AIController is EnemyAIController enemyAi) { enemyAi.UnattackableSubmarines.Add(submarine); enemyAi.UnattackableSubmarines.Add(Submarine.MainSub); foreach (Submarine sub in Submarine.MainSub.DockedTo) { enemyAi.UnattackableSubmarines.Add(sub); } } }
private IEnumerable <object> DoEndCampaignCameraTransition() { Character controlled = Character.Controlled; if (controlled != null) { controlled.AIController.Enabled = false; } GUI.DisableHUD = true; ISpatialEntity endObject = Level.Loaded.LevelObjectManager.GetAllObjects().FirstOrDefault(obj => obj.Prefab.SpawnPos == LevelObjectPrefab.SpawnPosType.LevelEnd); var transition = new CameraTransition(endObject ?? Submarine.MainSub, GameMain.GameScreen.Cam, null, Alignment.Center, fadeOut: true, duration: 10, startZoom: null, endZoom: 0.2f); while (transition.Running) { yield return(CoroutineStatus.Running); } GameMain.CampaignEndScreen.Select(); GUI.DisableHUD = false; yield return(CoroutineStatus.Success); }
bool TrySpawnCell(out Character cell, ISpatialEntity targetEntity = null) { cell = null; if (protectiveCells.Count >= MaxCellCount) { return(false); } if (targetEntity == null) { targetEntity = wayPoints.GetRandom(wp => wp.CurrentHull != null && populatedHulls.Count(h => h == wp.CurrentHull) < MaxCellsPerRoom && wp.CurrentHull.WaterPercentage >= MinWaterLevel) ?? hulls.GetRandom(h => populatedHulls.Count(h2 => h2 == h) < MaxCellsPerRoom && h.WaterPercentage >= MinWaterLevel) as ISpatialEntity; } if (targetEntity == null) { return(false); } if (targetEntity is Hull h) { populatedHulls.Add(h); } else if (targetEntity is WayPoint wp && wp.CurrentHull != null) { populatedHulls.Add(wp.CurrentHull); } // Don't add items in the list, because we want to be able to ignore the restrictions for spawner organs. cell = Character.Create(Config.DefensiveAgent, targetEntity.WorldPosition, ToolBox.RandomSeed(8), hasAi: true, createNetworkEvent: true); protectiveCells.Add(cell); cell.OnDeath += OnCellDeath; cellSpawnTimer = GetSpawnTime(); return(true); }
public AIObjectiveGetItem(Character character, Item targetItem, AIObjectiveManager objectiveManager, bool equip = true, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { currSearchIndex = -1; this.equip = equip; this.targetItem = targetItem; moveToTarget = targetItem?.GetRootInventoryOwner(); }
public OrderChatMessage(Order order, string orderOption, string text, ISpatialEntity targetEntity, Character targetCharacter, Character sender) : base(sender?.Name, text, ChatMessageType.Order, sender, GameMain.NetworkMember.ConnectedClients.Find(c => c.Character == sender)) { Order = order; OrderOption = orderOption; TargetCharacter = targetCharacter; TargetEntity = targetEntity; }
public AIObjectiveGoTo(ISpatialEntity target, Character character, AIObjectiveManager objectiveManager, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { this.Target = target; this.repeat = repeat; waitUntilPathUnreachable = 3.0f; this.getDivingGearIfNeeded = getDivingGearIfNeeded; CalculateCloseEnough(); }
public static ISpatialEntity FromWKT(string wkt, int srid) { SqlGeometry geometry = SqlGeometry.STGeomFromText(new SqlChars(wkt), srid); geometry = geometry.MakeValid(); ISpatialEntity retval = (ISpatialEntity)ToSharpMapGeometry(geometry); return(retval); }
public override void Reset() { base.Reset(); RemoveSubObjective(ref goToObjective); targetItem = null; moveToTarget = null; isDoneSeeking = false; currSearchIndex = 0; }
public void Attach(ISpatialEntity source, Item target) { System.Diagnostics.Debug.Assert(source != null); System.Diagnostics.Debug.Assert(target != null); this.source = source; this.target = target; ApplyStatusEffects(ActionType.OnUse, 1.0f, worldPosition: item.WorldPosition); IsActive = true; }
protected override void StartMissionSpecific(Level level) { items.Clear(); #if SERVER spawnedItems.Clear(); #endif if (!string.IsNullOrEmpty(itemTag)) { var itemsToDestroy = Item.ItemList.FindAll(it => it.Submarine?.Info.Type != SubmarineType.Player && it.HasTag(itemTag)); if (!itemsToDestroy.Any()) { DebugConsole.ThrowError($"Error in mission \"{Prefab.Identifier}\". Could not find an item with the tag \"{itemTag}\"."); } else { items.AddRange(itemsToDestroy); } } if (itemConfig != null && !IsClient) { foreach (XElement element in itemConfig.Elements()) { string itemIdentifier = element.GetAttributeString("identifier", ""); if (!(MapEntityPrefab.Find(null, itemIdentifier) is ItemPrefab itemPrefab)) { DebugConsole.ThrowError("Couldn't spawn item for outpost destroy mission: item prefab \"" + itemIdentifier + "\" not found"); continue; } string[] moduleFlags = element.GetAttributeStringArray("moduleflags", null); string[] spawnPointTags = element.GetAttributeStringArray("spawnpointtags", null); ISpatialEntity spawnPoint = SpawnAction.GetSpawnPos( SpawnAction.SpawnLocationType.Outpost, SpawnType.Human | SpawnType.Enemy, moduleFlags, spawnPointTags, element.GetAttributeBool("asfaraspossible", false)); if (spawnPoint == null) { var submarine = Submarine.Loaded.Find(s => s.Info.Type == SubmarineType.Outpost) ?? Submarine.MainSub; spawnPoint = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandom(); } Vector2 spawnPos = spawnPoint.WorldPosition; if (spawnPoint is WayPoint wp && wp.CurrentHull != null) { spawnPos = new Vector2( MathHelper.Clamp(wp.WorldPosition.X + Rand.Range(-200, 200), wp.CurrentHull.WorldRect.X, wp.CurrentHull.WorldRect.Right), wp.CurrentHull.WorldRect.Y - wp.CurrentHull.Rect.Height + 16.0f); } var item = new Item(itemPrefab, spawnPos, null); items.Add(item); #if SERVER spawnedItems.Add(item); #endif } } base.StartMissionSpecific(level); }
public AIObjectiveGoTo(ISpatialEntity target, Character character, AIObjectiveManager objectiveManager, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1, float closeEnough = 0) : base(character, objectiveManager, priorityModifier) { this.Target = target; this.repeat = repeat; waitUntilPathUnreachable = 3.0f; this.getDivingGearIfNeeded = getDivingGearIfNeeded; CloseEnough = closeEnough; if (Target is Item i) { CloseEnough = Math.Max(CloseEnough, i.InteractDistance + Math.Max(i.Rect.Width, i.Rect.Height) / 2); } }
private bool CheckInventory() { if (identifiersOrTags == null) { return(false); } var item = character.Inventory.FindItem(i => CheckItem(i), recursive: true); if (item != null) { targetItem = item; moveToTarget = item.GetRootInventoryOwner(); } return(item != null); }
public Feature(ISpatialEntity entity) { switch (entity.Geography.GeometryType) { case "MultiPolygon": Geometry = new MultiPolygon(entity.Geography as IMultiPolygon); break; case "Polygon": Geometry = new Polygon(entity.Geography as IPolygon); break; case "Point": Geometry = new Point(entity.Geography as IPoint); break; default: break; } Properties = entity.Properties as Dictionary<string, string>; }
public CameraTransition(ISpatialEntity targetEntity, Camera cam, Alignment?cameraStartPos, Alignment?cameraEndPos, bool fadeOut = true, float duration = 10.0f, float?startZoom = null, float?endZoom = null) { Duration = duration; FadeOut = fadeOut; this.cameraStartPos = cameraStartPos; this.cameraEndPos = cameraEndPos; this.startZoom = startZoom; this.endZoom = endZoom; AssignedCamera = cam; if (targetEntity == null) { return; } Running = true; CoroutineManager.StopCoroutines("CameraTransition"); updateCoroutine = CoroutineManager.StartCoroutine(Update(targetEntity, cam), "CameraTransition"); }
private void LoadHuman(HumanPrefab humanPrefab, XElement element, Submarine submarine) { string[] moduleFlags = element.GetAttributeStringArray("moduleflags", null); string[] spawnPointTags = element.GetAttributeStringArray("spawnpointtags", null); ISpatialEntity spawnPos = SpawnAction.GetSpawnPos( SpawnAction.SpawnLocationType.Outpost, SpawnType.Human, moduleFlags ?? humanPrefab.GetModuleFlags(), spawnPointTags ?? humanPrefab.GetSpawnPointTags(), element.GetAttributeBool("asfaraspossible", false)); if (spawnPos == null) { spawnPos = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandom(); } var characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: humanPrefab.GetJobPrefab(Rand.RandSync.Server), randSync: Rand.RandSync.Server); Character spawnedCharacter = Character.Create(characterInfo.SpeciesName, spawnPos.WorldPosition, ToolBox.RandomSeed(8), characterInfo, createNetworkEvent: false); if (element.GetAttributeBool("requirerescue", false)) { requireRescue.Add(spawnedCharacter); spawnedCharacter.TeamID = CharacterTeamType.FriendlyNPC; #if CLIENT GameMain.GameSession.CrewManager.AddCharacterToCrewList(spawnedCharacter); #endif } else { spawnedCharacter.TeamID = CharacterTeamType.None; } humanPrefab.InitializeCharacter(spawnedCharacter, spawnPos); humanPrefab.GiveItems(spawnedCharacter, Submarine.MainSub, Rand.RandSync.Server, createNetworkEvents: false); if (spawnPos is WayPoint wp) { spawnedCharacter.GiveIdCardTags(wp); } if (element.GetAttributeBool("requirekill", false)) { requireKill.Add(spawnedCharacter); } characters.Add(spawnedCharacter); characterItems.Add(spawnedCharacter, spawnedCharacter.Inventory.FindAllItems(recursive: true)); }
private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f) { if (order?.SymbolSprite == null) { return; } if (order.TargetAllCharacters) { if (order.OrderGiver != character && !order.HasAppropriateJob(character)) { return; } } ISpatialEntity target = order.ConnectedController != null ? order.ConnectedController.Item : order.TargetSpatialEntity; if (target == null) { return; } //don't show the indicator if far away and not inside the same sub //prevents exploiting the indicators in locating the sub if (character.Submarine != target.Submarine && Vector2.DistanceSquared(character.WorldPosition, target.WorldPosition) > 1000.0f * 1000.0f) { return; } if (!orderIndicatorCount.ContainsKey(target)) { orderIndicatorCount.Add(target, 0); } Vector2 drawPos = target is Entity ? (target as Entity).DrawPosition : target.Submarine == null ? target.Position : target.Position + target.Submarine.DrawPosition; drawPos += Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target]; GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha); orderIndicatorCount[target] = orderIndicatorCount[target] + 1; }
private void SpawnInitialCells() { int brainRoomCells = Rand.Range(MinCellsPerBrainRoom, MaxCellsPerRoom); if (brain.CurrentHull?.WaterPercentage >= MinWaterLevel) { for (int i = 0; i < brainRoomCells; i++) { if (!TrySpawnCell(out _, brain.CurrentHull)) { break; } } } int cellsInside = Rand.Range(MinCellsInside, MaxCellsInside); for (int i = 0; i < cellsInside; i++) { if (!TrySpawnCell(out _)) { break; } } int cellsOutside = Rand.Range(MinCellsOutside, MaxCellsOutside); // If we failed to spawn some of the cells in the brainroom/inside, spawn some extra cells outside. cellsOutside = Math.Clamp(cellsOutside + brainRoomCells + cellsInside - protectiveCells.Count, cellsOutside, MaxCellsOutside); for (int i = 0; i < cellsOutside; i++) { ISpatialEntity targetEntity = wayPoints.GetRandom(wp => wp.CurrentHull == null); if (targetEntity == null) { break; } if (!TrySpawnCell(out _, targetEntity)) { break; } } initialCellsSpawned = true; }
/// <summary> /// Get the entity that should be used in determining how far the player has progressed in the level. /// = The submarine or player character that has progressed the furthest. /// </summary> private ISpatialEntity GetRefEntity() { ISpatialEntity refEntity = Submarine.MainSub; #if CLIENT if (Character.Controlled != null) { if (Character.Controlled.Submarine != null && Character.Controlled.Submarine.Info.Type == SubmarineInfo.SubmarineType.Player) { refEntity = Character.Controlled.Submarine; } else { refEntity = Character.Controlled; } } #else foreach (Barotrauma.Networking.Client client in GameMain.Server.ConnectedClients) { if (client.Character == null) { continue; } //only take the players inside a player sub into account. //Otherwise the system could be abused by for example making a respawned player wait //close to the destination outpost if (client.Character.Submarine != null && client.Character.Submarine.Info.Type == SubmarineInfo.SubmarineType.Player) { if (client.Character.Submarine.WorldPosition.X > refEntity.WorldPosition.X) { refEntity = client.Character.Submarine; } } } #endif return(refEntity); }
private bool CanStartEventSet(EventSet eventSet) { ISpatialEntity refEntity = GetRefEntity(); float distFromStart = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.StartExitPosition.ToPoint(), level.StartPosition.ToPoint(), refEntity.WorldPosition.ToPoint())); float distFromEnd = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.EndExitPosition.ToPoint(), level.EndPosition.ToPoint(), refEntity.WorldPosition.ToPoint())); //don't create new events if within 50 meters of the start/end of the level if (!eventSet.AllowAtStart) { if (distanceTraveled <= 0.0f || distFromStart * Physics.DisplayToRealWorldRatio < 50.0f || distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f) { return(false); } } if (eventSet.DelayWhenCrewAway) { if ((isCrewAway && crewAwayDuration < settings.FreezeDurationWhenCrewAway) || crewAwayResetTimer > 0.0f) { return(false); } } if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) && roundDuration < eventSet.MinMissionTime) { return(false); } if (CurrentIntensity < eventSet.MinIntensity || CurrentIntensity > eventSet.MaxIntensity) { return(false); } return(true); }
private void LoadHuman(HumanPrefab humanPrefab, XElement element, Submarine submarine) { string[] moduleFlags = element.GetAttributeStringArray("moduleflags", null); string[] spawnPointTags = element.GetAttributeStringArray("spawnpointtags", null); ISpatialEntity spawnPos = SpawnAction.GetSpawnPos( SpawnAction.SpawnLocationType.Outpost, SpawnType.Human, moduleFlags ?? humanPrefab.GetModuleFlags(), spawnPointTags ?? humanPrefab.GetSpawnPointTags(), element.GetAttributeBool("asfaraspossible", false)); if (spawnPos == null) { spawnPos = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandom(); } bool requiresRescue = element.GetAttributeBool("requirerescue", false); Character spawnedCharacter = CreateHuman(humanPrefab, characters, characterItems, submarine, requiresRescue ? CharacterTeamType.FriendlyNPC : CharacterTeamType.None, spawnPos, giveTags: true); if (spawnPos is WayPoint wp) { spawnedCharacter.GiveIdCardTags(wp); } if (requiresRescue) { requireRescue.Add(spawnedCharacter); #if CLIENT GameMain.GameSession.CrewManager.AddCharacterToCrewList(spawnedCharacter); #endif } if (element.GetAttributeBool("requirekill", false)) { requireKill.Add(spawnedCharacter); } }
public void ThalamusOperate(WreckAI ai, float deltaTime, bool targetHumans, bool targetOtherCreatures, bool targetSubmarines, bool ignoreDelay) { if (ai == null) { return; } IsActive = true; if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (updatePending) { if (updateTimer < 0.0f) { #if SERVER item.CreateServerEvent(this); #endif prevTargetRotation = targetRotation; updateTimer = 0.25f; } updateTimer -= deltaTime; } if (!ignoreDelay && waitTimer > 0) { waitTimer -= deltaTime; return; } Submarine closestSub = null; float maxDistance = 10000.0f; float shootDistance = AIRange; ISpatialEntity target = null; float closestDist = shootDistance * shootDistance; if (targetHumans || targetOtherCreatures) { foreach (var character in Character.CharacterList) { if (character == null || character.Removed || character.IsDead) { continue; } if (character.Params.Group.Equals(ai.Config.Entity, StringComparison.OrdinalIgnoreCase)) { continue; } bool isHuman = character.IsHuman || character.Params.Group.Equals(CharacterPrefab.HumanSpeciesName, StringComparison.OrdinalIgnoreCase); if (isHuman) { if (!targetHumans) { // Don't target humans if not defined to. continue; } } else if (!targetOtherCreatures) { // Don't target other creatures if not defined to. continue; } float dist = Vector2.DistanceSquared(character.WorldPosition, item.WorldPosition); if (dist > closestDist) { continue; } target = character; closestDist = dist; } } if (targetSubmarines) { if (target == null || target.Submarine != null) { closestDist = maxDistance * maxDistance; foreach (Submarine sub in Submarine.Loaded) { if (sub.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; } float dist = Vector2.DistanceSquared(sub.WorldPosition, item.WorldPosition); if (dist > closestDist) { continue; } closestSub = sub; closestDist = dist; } closestDist = shootDistance * shootDistance; if (closestSub != null) { foreach (var hull in Hull.hullList) { if (!closestSub.IsEntityFoundOnThisSub(hull, true)) { continue; } float dist = Vector2.DistanceSquared(hull.WorldPosition, item.WorldPosition); if (dist > closestDist) { continue; } target = hull; closestDist = dist; } } } } if (!ignoreDelay) { if (target == null) { // Random movement waitTimer = Rand.Value(Rand.RandSync.Unsynced) < 0.98f ? 0f : Rand.Range(5f, 20f); targetRotation = Rand.Range(minRotation, maxRotation); updatePending = true; return; } if (disorderTimer < 0) { // Random disorder disorderTimer = Rand.Range(0f, 3f); waitTimer = Rand.Range(0.25f, 1f); targetRotation = MathUtils.WrapAngleTwoPi(targetRotation += Rand.Range(-1f, 1f)); updatePending = true; return; } else { disorderTimer -= deltaTime; } } if (target == null) { return; } float angle = -MathUtils.VectorToAngle(target.WorldPosition - item.WorldPosition); targetRotation = MathUtils.WrapAngleTwoPi(angle); if (Math.Abs(targetRotation - prevTargetRotation) > 0.1f) { updatePending = true; } if (target is Hull targetHull) { Vector2 barrelDir = new Vector2((float)Math.Cos(rotation), -(float)Math.Sin(rotation)); if (!MathUtils.GetLineRectangleIntersection(item.WorldPosition, item.WorldPosition + barrelDir * AIRange, targetHull.WorldRect, out _)) { return; } } else { float midRotation = (minRotation + maxRotation) / 2.0f; while (midRotation - angle < -MathHelper.Pi) { angle -= MathHelper.TwoPi; } while (midRotation - angle > MathHelper.Pi) { angle += MathHelper.TwoPi; } if (angle < minRotation || angle > maxRotation) { return; } float enemyAngle = MathUtils.VectorToAngle(target.WorldPosition - item.WorldPosition); float turretAngle = -rotation; if (Math.Abs(MathUtils.GetShortestAngle(enemyAngle, turretAngle)) > 0.15f) { return; } } Vector2 start = ConvertUnits.ToSimUnits(item.WorldPosition); Vector2 end = ConvertUnits.ToSimUnits(target.WorldPosition); if (target.Submarine != null) { start -= target.Submarine.SimPosition; end -= target.Submarine.SimPosition; } var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel; var pickedBody = Submarine.PickBody(start, end, null, collisionCategories, allowInsideFixture: true, customPredicate: (Fixture f) => { return(!item.StaticFixtures.Contains(f)); }); if (pickedBody == null) { return; } Character targetCharacter = null; if (pickedBody.UserData is Character c) { targetCharacter = c; } else if (pickedBody.UserData is Limb limb) { targetCharacter = limb.character; } if (targetCharacter != null) { if (targetCharacter.Params.Group.Equals(ai.Config.Entity, StringComparison.OrdinalIgnoreCase)) { // Don't shoot friendly characters return; } } else { if (pickedBody.UserData is ISpatialEntity e) { Submarine sub = e.Submarine; if (sub == null) { return; } if (!targetSubmarines) { return; } if (sub == Item.Submarine) { return; } // Don't shoot non-player submarines, i.e. wrecks or outposts. if (!sub.Info.IsPlayer) { return; } } else { // Hit something else, probably a level wall return; } } TryLaunch(deltaTime, ignorePower: true); }
private void FindTargetItem() { if (identifiersOrTags == null) { if (targetItem == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot find an item, because neither identifiers nor item was defined.", Color.Red); #endif Abandon = true; } return; } float priority = Math.Clamp(objectiveManager.GetCurrentPriority(), 10, 100); bool checkPath = priority >= AIObjectiveManager.LowestOrderPriority && (objectiveManager.IsCurrentOrder <AIObjectiveFixLeaks>() || objectiveManager.CurrentOrder is AIObjectiveGoTo gotoOrder && gotoOrder.isFollowOrderObjective); bool hasCalledPathFinder = false; int itemsPerFrame = (int)priority; for (int i = 0; i < itemsPerFrame && currSearchIndex < Item.ItemList.Count - 1; i++) { currSearchIndex++; var item = Item.ItemList[currSearchIndex]; Submarine itemSub = item.Submarine ?? item.ParentInventory?.Owner?.Submarine; if (itemSub == null) { continue; } Submarine mySub = character.Submarine; if (mySub == null) { continue; } if (!AllowStealing) { if (character.TeamID == CharacterTeamType.FriendlyNPC != item.SpawnedInOutpost) { continue; } } if (!CheckItem(item)) { continue; } if (item.Container != null) { if (item.Container.HasTag("donttakeitems")) { continue; } if (ignoredContainerIdentifiers != null) { if (ignoredContainerIdentifiers.Contains(item.ContainerIdentifier)) { continue; } } } // Don't allow going into another sub, unless it's connected and of the same team and type. if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { continue; } if (character.IsItemTakenBySomeoneElse(item)) { continue; } if (item.ParentInventory is ItemInventory itemInventory) { if (!itemInventory.Container.HasRequiredItems(character, addMessage: false)) { continue; } } float itemPriority = 1; if (GetItemPriority != null) { itemPriority = GetItemPriority(item); } Entity rootInventoryOwner = item.GetRootInventoryOwner(); if (rootInventoryOwner is Item ownerItem) { if (!ownerItem.IsInteractable(character)) { continue; } if (!(ownerItem.GetComponent <ItemContainer>()?.HasRequiredItems(character, addMessage: false) ?? true)) { continue; } } Vector2 itemPos = (rootInventoryOwner ?? item).WorldPosition; float yDist = Math.Abs(character.WorldPosition.Y - itemPos.Y); yDist = yDist > 100 ? yDist * 5 : 0; float dist = Math.Abs(character.WorldPosition.X - itemPos.X) + yDist; float distanceFactor = MathHelper.Lerp(1, 0, MathUtils.InverseLerp(0, 10000, dist)); itemPriority *= distanceFactor; itemPriority *= item.Condition / item.MaxCondition; // Ignore if the item has a lower priority than the currently selected one if (itemPriority < currItemPriority) { continue; } if (!hasCalledPathFinder && PathSteering != null && checkPath) { // While following the player, let's ensure that there's a valid path to the target before accepting it. // Otherwise it will take some time for us to find a valid item when there are multiple items that we can't reach and some that we can. // This is relatively expensive, so let's do this only when it significantly improves the behavior. // Only allow one path find call per frame. hasCalledPathFinder = true; var path = PathSteering.PathFinder.FindPath(character.SimPosition, item.SimPosition, character.Submarine, errorMsgStr: $"AIObjectiveGetItem {character.DisplayName}", nodeFilter: node => node.Waypoint.CurrentHull != null); if (path.Unreachable) { continue; } } currItemPriority = itemPriority; targetItem = item; moveToTarget = rootInventoryOwner ?? item; } if (currSearchIndex >= Item.ItemList.Count - 1) { isDoneSeeking = true; if (targetItem == null) { if (spawnItemIfNotFound) { if (!(MapEntityPrefab.List.FirstOrDefault(me => me is ItemPrefab ip && identifiersOrTags.Any(id => id == ip.Identifier || ip.Tags.Contains(id))) is ItemPrefab prefab)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot find an item with the following identifier(s) or tag(s): {string.Join(", ", identifiersOrTags)}, tried to spawn the item but no matching item prefabs were found.", Color.Yellow); #endif Abandon = true; } else { Entity.Spawner.AddToSpawnQueue(prefab, character.Inventory, onSpawned: (Item spawnedItem) => { targetItem = spawnedItem; if (character.TeamID == CharacterTeamType.FriendlyNPC && (character.Submarine?.Info.IsOutpost ?? false)) { spawnedItem.SpawnedInOutpost = true; } }); } } else { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot find an item with the following identifier(s) or tag(s): {string.Join(", ", identifiersOrTags)}", Color.Yellow); #endif SpeakCannotFind(); Abandon = true; } } }
protected override void Act(float deltaTime) { if (character.LockHands) { Abandon = true; return; } if (character.Submarine == null) { Abandon = true; return; } if (identifiersOrTags != null && !isDoneSeeking) { if (checkInventory) { if (CheckInventory()) { isDoneSeeking = true; } } if (!isDoneSeeking) { if (!AllowDangerousPressure) { bool dangerousPressure = character.CurrentHull == null || character.CurrentHull.LethalPressure > 0 && character.PressureProtection <= 0; if (dangerousPressure) { #if DEBUG string itemName = targetItem != null ? targetItem.Name : identifiersOrTags.FirstOrDefault(); DebugConsole.NewMessage($"{character.Name}: Seeking item ({itemName}) aborted, because the pressure is dangerous.", Color.Yellow); #endif Abandon = true; return; } } FindTargetItem(); if (!objectiveManager.IsCurrentOrder <AIObjectiveGoTo>()) { objectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime); } return; } } if (targetItem == null || targetItem.Removed) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target null or removed. Aborting.", Color.Red); #endif Abandon = true; return; } else if (isDoneSeeking && moveToTarget == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Move target null. Aborting.", Color.Red); #endif Abandon = true; return; } if (character.IsItemTakenBySomeoneElse(targetItem)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Found an item, but it's already equipped by someone else.", Color.Yellow); #endif if (originalTarget == null) { // Try again ignoredItems.Add(targetItem); ResetInternal(); } else { Abandon = true; } return; } bool canInteract = false; if (moveToTarget is Character c) { if (character == c) { canInteract = true; moveToTarget = null; } else { character.SelectCharacter(c); canInteract = character.CanInteractWith(c, maxDist: DefaultReach); character.DeselectCharacter(); } } else if (moveToTarget is Item parentItem) { canInteract = character.CanInteractWith(parentItem, checkLinked: false); } if (canInteract) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target not pickable. Aborting.", Color.Yellow); #endif Abandon = true; return; } Inventory itemInventory = targetItem.ParentInventory; var slots = itemInventory?.FindIndices(targetItem); if (HumanAIController.TakeItem(targetItem, character.Inventory, Equip, Wear, storeUnequipped: true)) { if (TakeWholeStack && slots != null) { foreach (int slot in slots) { foreach (Item item in itemInventory.GetItemsAt(slot).ToList()) { HumanAIController.TakeItem(item, character.Inventory, equip: false, storeUnequipped: true); } } } IsCompleted = true; } else { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif Abandon = true; } } else if (moveToTarget != null) { TryAddSubObjective(ref goToObjective, constructor: () => { return(new AIObjectiveGoTo(moveToTarget, character, objectiveManager, repeat: false, getDivingGearIfNeeded: AllowToFindDivingGear, closeEnough: DefaultReach) { // If the root container changes, the item is no longer where it was (taken by someone -> need to find another item) AbortCondition = obj => targetItem == null || targetItem.GetRootInventoryOwner() != moveToTarget, SpeakIfFails = false }); }, onAbandon: () => { if (originalTarget == null) { // Try again ignoredItems.Add(targetItem); ResetInternal(); } else { Abandon = true; } }, onCompleted: () => RemoveSubObjective(ref goToObjective)); } }
protected override void Act(float deltaTime) { if (character.LockHands) { Abandon = true; return; } if (itemIdentifiers != null && !isDoneSeeking) { if (checkInventory) { if (CheckInventory()) { isDoneSeeking = true; } } if (!isDoneSeeking) { bool dangerousPressure = character.CurrentHull == null || character.CurrentHull.LethalPressure > 0; if (dangerousPressure) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Seeking item aborted, because the pressure is dangerous.", Color.Yellow); #endif Abandon = true; return; } FindTargetItem(); objectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime); return; } } if (targetItem == null || targetItem.Removed) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target null or removed. Aborting.", Color.Red); #endif Abandon = true; return; } if (character.IsItemTakenBySomeoneElse(targetItem)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Found an item, but it's already equipped by someone else.", Color.Yellow); #endif // Try again Reset(); return; } bool canInteract = false; if (moveToTarget is Character c) { if (character == c) { canInteract = true; moveToTarget = null; } else { character.SelectCharacter(c); canInteract = character.CanInteractWith(c, maxDist: DefaultReach); character.DeselectCharacter(); } } else if (moveToTarget is Item parentItem) { canInteract = character.CanInteractWith(parentItem, out _, checkLinked: false); } if (canInteract) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target not pickable. Aborting.", Color.Yellow); #endif Abandon = true; return; } if (equip) { int targetSlot = -1; //check if all the slots required by the item are free foreach (InvSlotType slots in pickable.AllowedSlots) { if (slots.HasFlag(InvSlotType.Any)) { continue; } for (int i = 0; i < character.Inventory.Items.Length; i++) { //slot not needed by the item, continue if (!slots.HasFlag(character.Inventory.SlotTypes[i])) { continue; } targetSlot = i; //slot free, continue var otherItem = character.Inventory.Items[i]; if (otherItem == null) { continue; } //try to move the existing item to LimbSlot.Any and continue if successful if (otherItem.AllowedSlots.Contains(InvSlotType.Any) && character.Inventory.TryPutItem(otherItem, character, new List <InvSlotType>() { InvSlotType.Any })) { continue; } //if everything else fails, simply drop the existing item otherItem.Drop(character); } } if (character.Inventory.TryPutItem(targetItem, targetSlot, false, false, character)) { targetItem.Equip(character); IsCompleted = true; } else { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif Abandon = true; } } else { if (character.Inventory.TryPutItem(targetItem, null, new List <InvSlotType>() { InvSlotType.Any })) { IsCompleted = true; } else { Abandon = true; #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif } } } else if (moveToTarget != null) { TryAddSubObjective(ref goToObjective, constructor: () => { return(new AIObjectiveGoTo(moveToTarget, character, objectiveManager, repeat: false, getDivingGearIfNeeded: AllowToFindDivingGear, closeEnough: DefaultReach) { // If the root container changes, the item is no longer where it was (taken by someone -> need to find another item) abortCondition = () => targetItem == null || targetItem.GetRootInventoryOwner() != moveToTarget, DialogueIdentifier = "dialogcannotreachtarget", TargetName = (moveToTarget as MapEntity)?.Name ?? (moveToTarget as Character)?.Name ?? moveToTarget.ToString() }); }, onAbandon: () => { ignoredItems.Add(targetItem); Reset(); }, onCompleted: () => RemoveSubObjective(ref goToObjective)); } }
protected override void Act(float deltaTime) { if (followControlledCharacter) { if (Character.Controlled == null) { Abandon = true; return; } Target = Character.Controlled; } if (Target == character) { // Wait character.AIController.SteeringManager.Reset(); return; } waitUntilPathUnreachable -= deltaTime; if (!character.IsClimbing) { character.SelectedConstruction = null; } if (Target is Entity e) { if (e.Removed) { Abandon = true; } else { character.AIController.SelectTarget(e.AiTarget); } } var targetHull = Target is Hull h ? h : Target is Item i ? i.CurrentHull : Target is Character c ? c.CurrentHull : character.CurrentHull; if (!followControlledCharacter) { // Abandon if going through unsafe paths. Note ignores unsafe nodes when following an order or when the objective is set to ignore unsafe hulls. bool containsUnsafeNodes = HumanAIController.CurrentOrder == null && !HumanAIController.ObjectiveManager.CurrentObjective.IgnoreUnsafeHulls && PathSteering != null && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull)); if (containsUnsafeNodes || HumanAIController.UnreachableHulls.Contains(targetHull)) { Abandon = true; SteeringManager.Reset(); return; } } bool insideSteering = SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.IsPathDirty; bool isInside = character.CurrentHull != null; bool targetIsOutside = (Target != null && targetHull == null) || (insideSteering && PathSteering.CurrentPath.HasOutdoorsNodes); if (isInside && targetIsOutside && !AllowGoingOutside) { Abandon = true; } else if (waitUntilPathUnreachable < 0) { if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Unreachable && !PathSteering.IsPathDirty) { if (repeat) { SteeringManager.Reset(); } else { Abandon = true; } } } if (Abandon) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {Target.ToString()}", Color.Yellow); #endif if (objectiveManager.CurrentOrder != null && objectiveManager.CurrentOrder.ReportFailures) { character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f); } SteeringManager.Reset(); } else { if (getDivingGearIfNeeded && !character.LockHands) { Character followTarget = Target as Character; bool needsDivingSuit = targetIsOutside; bool needsDivingGear = needsDivingSuit || HumanAIController.NeedsDivingGear(character, targetHull, out needsDivingSuit); if (!needsDivingGear && mimic) { if (HumanAIController.HasDivingSuit(followTarget)) { needsDivingGear = true; needsDivingSuit = true; } else if (HumanAIController.HasDivingMask(followTarget)) { needsDivingGear = true; } } bool needsEquipment = false; if (needsDivingSuit) { needsEquipment = !HumanAIController.HasDivingSuit(character, AIObjectiveFindDivingGear.lowOxygenThreshold); } else if (needsDivingGear) { needsEquipment = !HumanAIController.HasDivingGear(character, AIObjectiveFindDivingGear.lowOxygenThreshold); } if (needsEquipment) { TryAddSubObjective(ref findDivingGear, () => new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager), onAbandon: () => Abandon = true, onCompleted: () => RemoveSubObjective(ref findDivingGear)); return; } } if (repeat && IsCloseEnough) { OnCompleted(); return; } if (SteeringManager == PathSteering) { Func <PathNode, bool> nodeFilter = null; if (isInside && !AllowGoingOutside) { nodeFilter = node => node.Waypoint.CurrentHull != null; } PathSteering.SteeringSeek(character.GetRelativeSimPosition(Target), 1, startNodeFilter, endNodeFilter, nodeFilter); } else { SteeringManager.SteeringSeek(character.GetRelativeSimPosition(Target), 10); } if (!insideSteering) { SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1); } } }
private void FindTargetItem() { if (identifiersOrTags == null) { if (targetItem == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot find the item, because neither identifiers nor item was defined.", Color.Red); #endif Abandon = true; } return; } for (int i = 0; i < 10 && currSearchIndex < Item.ItemList.Count - 1; i++) { currSearchIndex++; var item = Item.ItemList[currSearchIndex]; Submarine itemSub = item.Submarine ?? item.ParentInventory?.Owner?.Submarine; Submarine mySub = character.Submarine; if (itemSub == null) { continue; } if (mySub == null) { continue; } if (!CheckItem(item)) { continue; } if (ignoredContainerIdentifiers != null && item.Container != null) { if (ignoredContainerIdentifiers.Contains(item.ContainerIdentifier)) { continue; } } // Don't allow going into another sub, unless it's connected and of the same team and type. if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { continue; } if (character.IsItemTakenBySomeoneElse(item)) { continue; } if (item.ParentInventory is ItemInventory itemInventory) { if (!itemInventory.Container.HasRequiredItems(character, addMessage: false)) { continue; } } float itemPriority = 1; if (GetItemPriority != null) { itemPriority = GetItemPriority(item); } Entity rootInventoryOwner = item.GetRootInventoryOwner(); Vector2 itemPos = (rootInventoryOwner ?? item).WorldPosition; float yDist = Math.Abs(character.WorldPosition.Y - itemPos.Y); yDist = yDist > 100 ? yDist * 5 : 0; float dist = Math.Abs(character.WorldPosition.X - itemPos.X) + yDist; float distanceFactor = MathHelper.Lerp(1, 0, MathUtils.InverseLerp(0, 10000, dist)); itemPriority *= distanceFactor; itemPriority *= item.Condition / item.MaxCondition; //ignore if the item has a lower priority than the currently selected one if (itemPriority < currItemPriority) { continue; } currItemPriority = itemPriority; targetItem = item; moveToTarget = rootInventoryOwner ?? item; } if (currSearchIndex >= Item.ItemList.Count - 1) { isDoneSeeking = true; if (targetItem == null) { if (spawnItemIfNotFound) { if (!(MapEntityPrefab.List.FirstOrDefault(me => me is ItemPrefab ip && identifiersOrTags.Any(id => id == ip.Identifier || ip.Tags.Contains(id))) is ItemPrefab prefab)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot find the item with the following identifier(s) or tag(s): {string.Join(", ", identifiersOrTags)}, tried to spawn the item but no matching item prefabs were found.", Color.Yellow); #endif Abandon = true; } else { Entity.Spawner.AddToSpawnQueue(prefab, character.Inventory, onSpawned: (Item spawnedItem) => { targetItem = spawnedItem; if (character.TeamID == Character.TeamType.FriendlyNPC && (character.Submarine?.Info.IsOutpost ?? false)) { spawnedItem.SpawnedInOutpost = true; } }); } } else { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot find the item with the following identifier(s) or tag(s): {string.Join(", ", identifiersOrTags)}", Color.Yellow); #endif Abandon = true; } } }
protected override void Act(float deltaTime) { if (followControlledCharacter) { if (Character.Controlled == null) { abandon = true; return; } Target = Character.Controlled; } if (Target == character) { character.AIController.SteeringManager.Reset(); abandon = true; return; } waitUntilPathUnreachable -= deltaTime; if (!character.IsClimbing) { character.SelectedConstruction = null; } if (Target is Entity e) { if (e.Removed) { abandon = true; } else { character.AIController.SelectTarget(e.AiTarget); } } bool isInside = character.CurrentHull != null; bool insideSteering = SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.IsPathDirty; var targetHull = Target is Hull h ? h : Target is Item i ? i.CurrentHull : Target is Character c ? c.CurrentHull : character.CurrentHull; bool targetIsOutside = (Target != null && targetHull == null) || (insideSteering && PathSteering.CurrentPath.HasOutdoorsNodes); if (isInside && targetIsOutside && !AllowGoingOutside) { abandon = true; } else if (waitUntilPathUnreachable < 0) { if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Unreachable) { if (repeat) { SteeringManager.Reset(); } else { abandon = true; } } } if (abandon) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {Target.ToString()}", Color.Yellow); #endif if (objectiveManager.CurrentOrder != null) { character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f); } character.AIController.SteeringManager.Reset(); } else { Vector2 currTargetSimPos = Vector2.Zero; currTargetSimPos = Target.SimPosition; // Take the sub position into account in the sim pos if (SteeringManager != PathSteering && character.Submarine == null && Target.Submarine != null) { currTargetSimPos += Target.Submarine.SimPosition; } else if (character.Submarine != null && Target.Submarine == null) { currTargetSimPos -= character.Submarine.SimPosition; } else if (character.Submarine != Target.Submarine) { if (character.Submarine != null && Target.Submarine != null) { Vector2 diff = character.Submarine.SimPosition - Target.Submarine.SimPosition; currTargetSimPos -= diff; } } character.AIController.SteeringManager.SteeringSeek(currTargetSimPos); if (SteeringManager != PathSteering) { SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1, heading: VectorExtensions.Forward(character.AnimController.Collider.Rotation)); } if (getDivingGearIfNeeded) { Character followTarget = Target as Character; bool needsDivingGear = HumanAIController.NeedsDivingGear(targetHull) || mimic && HumanAIController.HasDivingMask(followTarget); bool needsDivingSuit = needsDivingGear && (targetHull == null || targetIsOutside || targetHull.WaterPercentage > 90) || mimic && HumanAIController.HasDivingSuit(followTarget); bool needsEquipment = false; if (needsDivingSuit) { needsEquipment = !HumanAIController.HasDivingSuit(character); } else if (needsDivingGear) { needsEquipment = !HumanAIController.HasDivingMask(character); } if (needsEquipment) { TryAddSubObjective(ref findDivingGear, () => new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager)); } } } }
protected override void Act(float deltaTime) { var extinguisherItem = character.Inventory.FindItemByTag("fireextinguisher"); if (extinguisherItem == null || extinguisherItem.Condition <= 0.0f || !character.HasEquippedItem(extinguisherItem)) { TryAddSubObjective(ref getExtinguisherObjective, () => { if (character.IsOnPlayerTeam && !character.HasEquippedItem("fireextinguisher", allowBroken: false)) { character.Speak(TextManager.Get("DialogFindExtinguisher"), null, 2.0f, "findextinguisher", 30.0f); } var getItemObjective = new AIObjectiveGetItem(character, "fireextinguisher", objectiveManager, equip: true) { AllowStealing = true, // If the item is inside an unsafe hull, decrease the priority GetItemPriority = i => HumanAIController.UnsafeHulls.Contains(i.CurrentHull) ? 0.1f : 1 }; if (objectiveManager.HasOrder <AIObjectiveExtinguishFires>()) { getItemObjective.Abandoned += () => character.Speak(TextManager.Get("dialogcannotfindfireextinguisher"), null, 0.0f, "dialogcannotfindfireextinguisher", 10.0f); } ; return(getItemObjective); }); } else { var extinguisher = extinguisherItem.GetComponent <RepairTool>(); if (extinguisher == null) { #if DEBUG DebugConsole.ThrowError($"{character.Name}: AIObjectiveExtinguishFire failed - the item \"" + extinguisherItem + "\" has no RepairTool component but is tagged as an extinguisher"); #endif Abandon = true; return; } foreach (FireSource fs in targetHull.FireSources) { float xDist = Math.Abs(character.WorldPosition.X - fs.WorldPosition.X) - fs.DamageRange; float yDist = Math.Abs(character.WorldPosition.Y - fs.WorldPosition.Y); bool inRange = xDist + yDist < extinguisher.Range; // Use the hull position, because the fire x pos is sometimes inside a wall -> the bot can't ever see it and continues running towards the wall. ISpatialEntity lookTarget = character.CurrentHull == targetHull || character.CurrentHull.linkedTo.Contains(targetHull) ? targetHull : fs as ISpatialEntity; bool move = !inRange || !character.CanSeeTarget(lookTarget); if ((inRange && character.CanSeeTarget(lookTarget)) || useExtinquisherTimer > 0) { useExtinquisherTimer += deltaTime; if (useExtinquisherTimer > 2.0f) { useExtinquisherTimer = 0.0f; } // Aim character.CursorPosition = fs.Position; Vector2 fromCharacterToFireSource = fs.WorldPosition - character.WorldPosition; float dist = fromCharacterToFireSource.Length(); character.CursorPosition += VectorExtensions.Forward(extinguisherItem.body.TransformedRotation + (float)Math.Sin(sinTime) / 2, dist / 2); if (extinguisherItem.RequireAimToUse) { character.SetInput(InputType.Aim, false, true); sinTime += deltaTime * 10; } character.SetInput(extinguisherItem.IsShootable ? InputType.Shoot : InputType.Use, false, true); extinguisher.Use(deltaTime, character); if (!targetHull.FireSources.Contains(fs)) { character.Speak(TextManager.GetWithVariable("DialogPutOutFire", "[roomname]", targetHull.DisplayName, true), null, 0, "putoutfire", 10.0f); } } if (move) { //go to the first firesource if (TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(fs, character, objectiveManager, closeEnough: Math.Max(fs.DamageRange, extinguisher.Range * 0.7f)) { DialogueIdentifier = "dialogcannotreachfire", TargetName = fs.Hull.DisplayName }, onAbandon: () => Abandon = true, onCompleted: () => RemoveSubObjective(ref gotoObjective))) { gotoObjective.requiredCondition = () => targetHull == null || character.CanSeeTarget(targetHull); } } else { character.AIController.SteeringManager.Reset(); } break; } } }
public void Resize(ISpatialEntity entity, IShape shape, MovementDelegate movementDelegate) { // TODO: Check if shape > cellsize if (gpuActive) gpuActiveWait.WaitOne(); Interlocked.Increment(ref m_ActiveOperationCount); long objId = spatialObjIdMap[entity]; var newEnt = entity; newEnt.Shape = shape; spatialObjIdMap.Remove(entity); spatialObjIdMap.Add(newEnt, objId); objIdSpatialMap[(int)objId].Shape = shape; shapeList.Remove(objIdClShapeMap[(int)objId]); m_MoveDelegates.Add(new Tuple<long, MovementDelegate>(objId, movementDelegate)); clShapeObject act; clPoint center; center.x = (float)entity.Shape.Bounds.Position.X; center.y = (float)entity.Shape.Bounds.Position.Y; center.z = (float)entity.Shape.Bounds.Position.Z; clPoint front; front.x = (float)entity.Shape.Bounds.LeftBottomFront.X; front.y = (float)entity.Shape.Bounds.LeftBottomFront.Y; front.z = (float)entity.Shape.Bounds.LeftBottomFront.Z; clPoint rear; rear.x = (float)entity.Shape.Bounds.RightTopRear.X; rear.y = (float)entity.Shape.Bounds.RightTopRear.Y; rear.z = (float)entity.Shape.Bounds.RightTopRear.Z; act.center = center; act.leftBottomFront = front; act.rigthTopRear = rear; shapeList.Add(act); objIdClShapeMap[(int)objId] = act; Interlocked.Decrement(ref m_ActiveOperationCount); }
public void Remove(ISpatialEntity entity) { if (gpuActive) gpuActiveWait.WaitOne(); long objId = spatialObjIdMap[entity]; envActEnvObjs.Remove(objId); objIdList.Remove(objId); spatialObjIdMap.Remove(entity); objIdSpatialMap.Remove((int)objId); objIdClShapeMap.Remove((int)objId); shapeList.Remove(objIdClShapeMap[(int)objId]); }
public void Move(ISpatialEntity entity, Vector3 movementVector, Direction rotation, MovementDelegate movementDelegate) { if (gpuActive) gpuActiveWait.WaitOne(); Interlocked.Increment(ref m_ActiveOperationCount); var objId = spatialObjIdMap[entity]; objId &= (~(0xFFFFFFFF << 32)); objId |= FLAG_MOVE; var newEnt = entity; var newShape = newEnt.Shape.Transform(movementVector, rotation); newEnt.Shape = newShape; spatialObjIdMap.Remove(entity); spatialObjIdMap.Add(newEnt, objId); objIdSpatialMap[(int)objId].Shape = newShape; //shapeList.Remove(objIdClShapeMap[objId]); envActEnvObjs.Remove(objId); // TODO Testen ob es auch mit Konstruktoren funktioniert clShapeObject act; clPoint center; center.x = (float)entity.Shape.Bounds.Position.X; center.y = (float)entity.Shape.Bounds.Position.Y; center.z = (float)entity.Shape.Bounds.Position.Z; clPoint front; front.x = (float)entity.Shape.Bounds.LeftBottomFront.X; front.y = (float)entity.Shape.Bounds.LeftBottomFront.Y; front.z = (float)entity.Shape.Bounds.LeftBottomFront.Z; clPoint rear; rear.x = (float)entity.Shape.Bounds.RightTopRear.X; rear.y = (float)entity.Shape.Bounds.RightTopRear.Y; rear.z = (float)entity.Shape.Bounds.RightTopRear.Z; act.center = center; act.leftBottomFront = front; act.rigthTopRear = rear; envActEnvObjs[objId] = act; //shapeList.Add(act); objIdClShapeMap[(int)objId] = act; Interlocked.Decrement(ref m_ActiveOperationCount); }
protected Character CreateHuman(HumanPrefab humanPrefab, List <Character> characters, Dictionary <Character, List <Item> > characterItems, Submarine submarine, CharacterTeamType teamType, ISpatialEntity positionToStayIn = null, Rand.RandSync humanPrefabRandSync = Rand.RandSync.Server, bool giveTags = true) { var characterInfo = humanPrefab.GetCharacterInfo(Rand.RandSync.Server) ?? new CharacterInfo(CharacterPrefab.HumanSpeciesName, npcIdentifier: humanPrefab.Identifier, jobPrefab: humanPrefab.GetJobPrefab(humanPrefabRandSync), randSync: humanPrefabRandSync); characterInfo.TeamID = teamType; if (positionToStayIn == null) { positionToStayIn = WayPoint.GetRandom(SpawnType.Human, characterInfo.Job?.Prefab, submarine) ?? WayPoint.GetRandom(SpawnType.Human, null, submarine); } Character spawnedCharacter = Character.Create(characterInfo.SpeciesName, positionToStayIn.WorldPosition, ToolBox.RandomSeed(8), characterInfo, createNetworkEvent: false); spawnedCharacter.Prefab = humanPrefab; humanPrefab.InitializeCharacter(spawnedCharacter, positionToStayIn); humanPrefab.GiveItems(spawnedCharacter, submarine, Rand.RandSync.Server, createNetworkEvents: false); characters.Add(spawnedCharacter); characterItems.Add(spawnedCharacter, spawnedCharacter.Inventory.FindAllItems(recursive: true)); return(spawnedCharacter); }
private static void Main(string[] args) { if (File.Exists(Path.Combine(System.Environment.CurrentDirectory, @"..\..\log.txt"))) { File.Delete(Path.Combine(System.Environment.CurrentDirectory, @"..\..\log.txt")); } if (File.Exists(Path.Combine(System.Environment.CurrentDirectory, @"..\..\sortLog.txt"))) { File.Delete(Path.Combine(System.Environment.CurrentDirectory, @"..\..\sortLog.txt")); } if (File.Exists(Path.Combine(System.Environment.CurrentDirectory, @"..\..\OpenCLDebugLog.txt"))) { File.Delete(Path.Combine(System.Environment.CurrentDirectory, @"..\..\OpenCLDebugLog.txt")); } numElements--; numElements |= numElements >> 1; numElements |= numElements >> 2; numElements |= numElements >> 4; numElements |= numElements >> 8; numElements |= numElements >> 16; numElements++; Random generator = new Random(); Console.SetWindowSize(Console.LargestWindowWidth/2,Console.LargestWindowHeight/2); /* ISpatialEntity[] testSpatials = new ISpatialEntity[numElements]; for (int i = 2; i < testSpatials.Length; i++) { testSpatials[i] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[i].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(generator.Next(1,100), generator.Next(1,100), generator.Next(1,100)), null); Console.WriteLine("GUID = "+ testSpatials[i].AgentGuid); Console.WriteLine(string.Format("Pos: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.Position.X, testSpatials[i].Shape.Bounds.Position.Y, testSpatials[i].Shape.Bounds.Position.Z)); Console.WriteLine(string.Format("Min: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.LeftBottomFront.X, testSpatials[i].Shape.Bounds.LeftBottomFront.Y, testSpatials[i].Shape.Bounds.LeftBottomFront.Z, testSpatials[i].AgentGuid)); Console.WriteLine(string.Format("Max: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.RightTopRear.X, testSpatials[i].Shape.Bounds.RightTopRear.Y, testSpatials[i].Shape.Bounds.RightTopRear.Z, testSpatials[i].AgentGuid)); Console.WriteLine(); // Console.Write(" " + testData[i]);#3##2# } testSpatials[0] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[0].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(3, 3, 2), null); testSpatials[1] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[1].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(3, 2.5, 2), null); testSpatials[0] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[0].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(2,2,2), null); testSpatials[1] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[1].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(2,2,2), null); testSpatials[2] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[2].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(4,4,2), null); testSpatials[3] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[3].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(4, 4, 2), null);#1# for (int i = 0; i < numElements; i++) { Console.WriteLine("GUID = " + testSpatials[i].AgentGuid); Console.WriteLine(string.Format("Pos: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.Position.X, testSpatials[i].Shape.Bounds.Position.Y, testSpatials[i].Shape.Bounds.Position.Z)); Console.WriteLine(string.Format("Min: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.LeftBottomFront.X, testSpatials[i].Shape.Bounds.LeftBottomFront.Y, testSpatials[i].Shape.Bounds.LeftBottomFront.Z)); Console.WriteLine(string.Format("Max: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.RightTopRear.X, testSpatials[i].Shape.Bounds.RightTopRear.Y, testSpatials[i].Shape.Bounds.RightTopRear.Z)); Console.WriteLine(); } #1# // compute the next highest power of 2 of 32-bit v /* #1# int[] testData = new int[numElements]; int[] testResult = new int[numElements]; for (int i = 0; i < testData.Length; i++) { testData[i] = generator.Next(1000000); // Console.Write(" " + testData[i]);#3# } Console.WriteLine(); Program ins = new Program(); ins.Setup(); var radix = new GPURadixSort(cqCommandQueue, cxGPUContext, _device); Event eve; ErrorCode error; IMem inputBuff = Cl.CreateBuffer(cxGPUContext, MemFlags.ReadWrite, (IntPtr)(numElements * 4), testData, out error); ins.CheckErr(error, "Createbuffer"); IMem outputBuff = Cl.CreateBuffer(cxGPUContext, MemFlags.ReadWrite, (IntPtr)(numElements * 4), out error); ins.CheckErr(error, "Createbuffer"); error = Cl.EnqueueWriteBuffer(cqCommandQueue, inputBuff, Bool.True, IntPtr.Zero, (IntPtr)(numElements * 4), testData, 0, null, out eve); ins.CheckErr(error, "EnqBuffer"); error = Cl.Finish(cqCommandQueue); ins.CheckErr(error, "Cl.Finish"); */ #region RadixSortTest /* DateTime before = DateTime.Now; radix.sortKeysOnly(inputBuff, outputBuff, numElements); error = Cl.EnqueueWriteBuffer(cqCommandQueue, inputBuff, Bool.True, IntPtr.Zero, (IntPtr)(numElements * 4), testData, 0, null, out eve); ins.CheckErr(error, "EnqBuffer"); radix.sortKeysOnly(inputBuff, outputBuff, numElements);*/ //Collision Detection tests /* CollisionDetection detec = new CollisionDetection(cqCommandQueue,cxGPUContext,_device,radix,new Point3D(150,150,150),new Vector3(2,2,2) ); IMem inp; IMem outp; detec.CreateCellIdArray(testSpatials,out inp, out outp); #1# */ #endregion /* radix.sortKeysOnly(inputBuff, outputBuff, numElements); #1# error = Cl.EnqueueReadBuffer(cqCommandQueue, outputBuff, Bool.True, IntPtr.Zero, (IntPtr)(numElements * 4), testResult, 0, null, out eve); ins.CheckErr(error, "Cl.EnqueueReadBuffer"); //Execute our kernel (OpenCL code) error = Cl.Finish(cqCommandQueue); ins.CheckErr(error, "Cl.Finish"); Console.WriteLine("Execution time Gpu ="+( DateTime.Now- before ).TotalMilliseconds); /* for (int i = 0; i < numElements; i++) { Console.Write(" " + testResult[i]); }#1# before = DateTime.Now; Array.Sort(testData); Console.WriteLine("Execution time CPU =" + (DateTime.Now - before).TotalMilliseconds); int r = 0; */ MovementDelegate moveDel = new MovementDelegate(dele1); ExploreDelegate expDel = new ExploreDelegate(dele2); generator = new Random(); Console.SetWindowSize(Console.LargestWindowWidth / 2, Console.LargestWindowHeight / 2); ISpatialEntity[] testSpatials = new ISpatialEntity[numElements]; GpuESC esc = new GpuESC(new Vector3(2, 2, 2), new Vector3(2000000, 8, 8)); for (int i = 2; i < testSpatials.Length; i++) { testSpatials[i] = new TestSpatialEntity(new Vector3(0.5, 0.5, 0.5)); Vector3 actos = new Vector3(i + 0.1, 1.5, 1.5); testSpatials[i].Shape = new Cuboid(new Vector3(0.5, 0.5, 0.5), actos, null); /*Console.WriteLine("GUID = " + testSpatials[i].AgentGuid); Console.WriteLine(string.Format("Pos: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.Position.X, testSpatials[i].Shape.Bounds.Position.Y, testSpatials[i].Shape.Bounds.Position.Z)); Console.WriteLine(string.Format("Min: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.LeftBottomFront.X, testSpatials[i].Shape.Bounds.LeftBottomFront.Y, testSpatials[i].Shape.Bounds.LeftBottomFront.Z, testSpatials[i].AgentGuid)); Console.WriteLine(string.Format("Max: x={0} , y ={1}, z={2} ", testSpatials[i].Shape.Bounds.RightTopRear.X, testSpatials[i].Shape.Bounds.RightTopRear.Y, testSpatials[i].Shape.Bounds.RightTopRear.Z, testSpatials[i].AgentGuid)); */ // Console.WriteLine(); // Console.Write(" " + testData[i]);#3##2#*/ esc.Add(testSpatials[i], actos, null, moveDel); } testSpatials[0] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[0].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(3, 3, 2), null); esc.Add(testSpatials[0], testSpatials[0].Shape.Position, null, moveDel); testSpatials[1] = new TestSpatialEntity(new Vector3(1, 1, 1)); testSpatials[1].Shape = new Cuboid(new Vector3(1, 1, 1), new Vector3(3, 3, 2), null); Console.WriteLine(testSpatials[0].AgentGuid); Console.WriteLine(testSpatials[1].AgentGuid); esc.Add(testSpatials[1], testSpatials[1].Shape.Position, null, moveDel); var before = DateTime.Now; for (int i = 0; i <10; i++) { esc.Commit(); } Console.WriteLine("Execution time Total =" + (DateTime.Now - before).TotalMilliseconds); Console.WriteLine(collisionCount); int asdcyxcsa = 2; }
protected override void Act(float deltaTime) { if (character.LockHands) { Abandon = true; return; } if (itemIdentifiers != null && !isDoneSeeking) { if (checkInventory) { if (CheckInventory()) { isDoneSeeking = true; } } if (!isDoneSeeking) { bool dangerousPressure = character.CurrentHull == null || character.CurrentHull.LethalPressure > 0; if (dangerousPressure) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Seeking item aborted, because the pressure is dangerous.", Color.Yellow); #endif Abandon = true; return; } FindTargetItem(); objectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime); return; } } if (targetItem == null || targetItem.Removed) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target null or removed. Aborting.", Color.Red); #endif Abandon = true; return; } else if (isDoneSeeking && moveToTarget == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Move target null. Aborting.", Color.Red); #endif Abandon = true; return; } if (character.IsItemTakenBySomeoneElse(targetItem)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Found an item, but it's already equipped by someone else.", Color.Yellow); #endif if (originalTarget == null) { // Try again Reset(); } else { Abandon = true; } return; } bool canInteract = false; if (moveToTarget is Character c) { if (character == c) { canInteract = true; moveToTarget = null; } else { character.SelectCharacter(c); canInteract = character.CanInteractWith(c, maxDist: DefaultReach); character.DeselectCharacter(); } } else if (moveToTarget is Item parentItem) { canInteract = character.CanInteractWith(parentItem, out _, checkLinked: false); } if (canInteract) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target not pickable. Aborting.", Color.Yellow); #endif Abandon = true; return; } if (equip) { if (HumanAIController.TryToMoveItem(targetItem, character.Inventory)) { targetItem.Equip(character); IsCompleted = true; } else { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif Abandon = true; } } else { if (character.Inventory.TryPutItem(targetItem, character, new List <InvSlotType>() { InvSlotType.Any })) { IsCompleted = true; } else { Abandon = true; #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif } } } else if (moveToTarget != null) { TryAddSubObjective(ref goToObjective, constructor: () => { return(new AIObjectiveGoTo(moveToTarget, character, objectiveManager, repeat: false, getDivingGearIfNeeded: AllowToFindDivingGear, closeEnough: DefaultReach) { // If the root container changes, the item is no longer where it was (taken by someone -> need to find another item) abortCondition = () => targetItem == null || targetItem.GetRootInventoryOwner() != moveToTarget, DialogueIdentifier = "dialogcannotreachtarget", TargetName = (moveToTarget as MapEntity)?.Name ?? (moveToTarget as Character)?.Name ?? moveToTarget.ToString() }); }, onAbandon: () => { ignoredItems.Add(targetItem); Reset(); }, onCompleted: () => RemoveSubObjective(ref goToObjective)); } }
public void AddWithRandomPosition(ISpatialEntity entity, Vector3 min, Vector3 max, bool grid, MovementDelegate movementDelegate) { //Evaluate dimesions var shapeTmp = new Vector3(entity.Shape.Bounds.Length / 2, entity.Shape.Bounds.Height / 2, entity.Shape.Bounds.Width / 2); if (!checkBoundarys(min - shapeTmp, max + shapeTmp)) { movementDelegate.Invoke(new MovementResult()); return; } if (gpuActive) gpuActiveWait.WaitOne(); Interlocked.Increment(ref m_ActiveOperationCount); Vector3 freepos = GetNextFreeCell(min, max); if (freepos == Vector3.Null) { var rnd = new Random(); freepos = new Vector3((double)rnd.Next((int)min.X, (int)max.X), (double)rnd.Next((int)min.Y, (int)max.Y), (double)rnd.Next((int)min.Z, (int)max.Z)); } var objId = getNextObjId(); var objData = objId | FLAG_NEW; m_AddDelegates.Add(new Tuple<long, MovementDelegate>(objData, movementDelegate)); objIdList.Add(objId); spatialObjIdMap.Add(entity, objId); objIdSpatialMap.Add(objId, entity); entity.Shape = new Cuboid(entity.Shape.Bounds.Dimension, freepos); clShapeObject act; clPoint center; center.x = (float)entity.Shape.Bounds.Position.X; center.y = (float)entity.Shape.Bounds.Position.Y; center.z = (float)entity.Shape.Bounds.Position.Z; clPoint front; front.x = (float)entity.Shape.Bounds.LeftBottomFront.X; front.y = (float)entity.Shape.Bounds.LeftBottomFront.Y; front.z = (float)entity.Shape.Bounds.LeftBottomFront.Z; clPoint rear; rear.x = (float)entity.Shape.Bounds.RightTopRear.X; rear.y = (float)entity.Shape.Bounds.RightTopRear.Y; rear.z = (float)entity.Shape.Bounds.RightTopRear.Z; act.center = center; act.leftBottomFront = front; act.rigthTopRear = rear; envFreshAddedObjs.Add(objData, act); /* shapeList.Add(act); objIdClShapeMap.Add(objId, act); */ // Added Element -> Now wait until the CollisionDetection did its work at the LayerTick Interlocked.Decrement(ref m_ActiveOperationCount); // envActEnvObjs.Add(objId, act); // We need the list with free positions first }
public void Add(ISpatialEntity entity, Vector3 position, Direction rotation, MovementDelegate movementDelegate) { entity.Shape.Transform(position - entity.Shape.Position, null); // First check boundarys if (!checkBoundarys(entity.Shape.Bounds.LeftBottomFront,entity.Shape.Bounds.RightTopRear)) { movementDelegate.Invoke(new MovementResult()); return; } bool res; if (gpuActive) gpuActiveWait.WaitOne(); Interlocked.Increment(ref m_ActiveOperationCount); int objId = getNextObjId(); long objData = objId | FLAG_NEW; m_AddDelegates.Add(new Tuple<long,MovementDelegate>(objData,movementDelegate)); objIdList.Add(objId); spatialObjIdMap.Add(entity, objId); objIdSpatialMap.Add(objId, entity); clShapeObject act; clPoint center; center.x = (float)entity.Shape.Bounds.Position.X; center.y = (float)entity.Shape.Bounds.Position.Y; center.z = (float)entity.Shape.Bounds.Position.Z; clPoint front; front.x = (float)entity.Shape.Bounds.LeftBottomFront.X; front.y = (float)entity.Shape.Bounds.LeftBottomFront.Y; front.z = (float)entity.Shape.Bounds.LeftBottomFront.Z; clPoint rear; rear.x = (float)entity.Shape.Bounds.RightTopRear.X; rear.y = (float)entity.Shape.Bounds.RightTopRear.Y; rear.z = (float)entity.Shape.Bounds.RightTopRear.Z; act.center = center; act.leftBottomFront = front; act.rigthTopRear = rear; objIdClShapeMap.Add(objId, act); envFreshAddedObjs.Add(objData, act); /* shapeList.Add(act); objIdClShapeMap.Add(objId, act); */ Interlocked.Decrement(ref m_ActiveOperationCount); }