public static void GenerateSubWaypoints(Submarine submarine) { if (!Hull.hullList.Any()) { DebugConsole.ThrowError("Couldn't generate waypoints: no hulls found."); return; } List <WayPoint> existingWaypoints = WayPointList.FindAll(wp => wp.spawnType == SpawnType.Path); foreach (WayPoint wayPoint in existingWaypoints) { wayPoint.Remove(); } //find all open doors and temporarily activate their bodies to prevent visibility checks //from ignoring the doors and generating waypoint connections that go straight through the door List <Door> openDoors = new List <Door>(); foreach (Item item in Item.ItemList) { var door = item.GetComponent <Door>(); if (door != null && !door.Body.Enabled) { openDoors.Add(door); door.Body.Enabled = true; } } float minDist = 150.0f; float heightFromFloor = 110.0f; foreach (Hull hull in Hull.hullList) { if (hull.Rect.Height < 150) { continue; } WayPoint prevWaypoint = null; if (hull.Rect.Width < minDist * 3.0f) { new WayPoint( new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, submarine); continue; } for (float x = hull.Rect.X + minDist; x <= hull.Rect.Right - minDist; x += minDist) { var wayPoint = new WayPoint(new Vector2(x, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, submarine); if (prevWaypoint != null) { wayPoint.ConnectTo(prevWaypoint); } prevWaypoint = wayPoint; } } float outSideWaypointInterval = 200.0f; int outsideWaypointDist = 100; Rectangle borders = Hull.GetBorders(); borders.X -= outsideWaypointDist; borders.Y += outsideWaypointDist; borders.Width += outsideWaypointDist * 2; borders.Height += outsideWaypointDist * 2; borders.Location -= MathUtils.ToPoint(submarine.HiddenSubPosition); if (borders.Width <= outSideWaypointInterval * 2) { borders.Inflate(outSideWaypointInterval * 2 - borders.Width, 0); } if (borders.Height <= outSideWaypointInterval * 2) { int inflateAmount = (int)(outSideWaypointInterval * 2) - borders.Height; borders.Y += inflateAmount / 2; borders.Height += inflateAmount; } WayPoint[,] cornerWaypoint = new WayPoint[2, 2]; for (int i = 0; i < 2; i++) { for (float x = borders.X + outSideWaypointInterval; x < borders.Right - outSideWaypointInterval; x += outSideWaypointInterval) { var wayPoint = new WayPoint( new Vector2(x, borders.Y - borders.Height * i) + submarine.HiddenSubPosition, SpawnType.Path, submarine); if (x == borders.X + outSideWaypointInterval) { cornerWaypoint[i, 0] = wayPoint; } else { wayPoint.ConnectTo(WayPointList[WayPointList.Count - 2]); } } cornerWaypoint[i, 1] = WayPointList[WayPointList.Count - 1]; } for (int i = 0; i < 2; i++) { WayPoint wayPoint = null; for (float y = borders.Y - borders.Height; y < borders.Y; y += outSideWaypointInterval) { wayPoint = new WayPoint( new Vector2(borders.X + borders.Width * i, y) + submarine.HiddenSubPosition, SpawnType.Path, submarine); if (y == borders.Y - borders.Height) { wayPoint.ConnectTo(cornerWaypoint[1, i]); } else { wayPoint.ConnectTo(WayPoint.WayPointList[WayPointList.Count - 2]); } } wayPoint.ConnectTo(cornerWaypoint[0, i]); } List <Structure> stairList = new List <Structure>(); foreach (MapEntity me in mapEntityList) { Structure stairs = me as Structure; if (stairs == null) { continue; } if (stairs.StairDirection != Direction.None) { stairList.Add(stairs); } } foreach (Structure stairs in stairList) { WayPoint[] stairPoints = new WayPoint[3]; stairPoints[0] = new WayPoint( new Vector2(stairs.Rect.X - 32.0f, stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? 80 : stairs.Rect.Height) + heightFromFloor), SpawnType.Path, submarine); stairPoints[1] = new WayPoint( new Vector2(stairs.Rect.Right + 32.0f, stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? stairs.Rect.Height : 80) + heightFromFloor), SpawnType.Path, submarine); for (int i = 0; i < 2; i++) { for (int dir = -1; dir <= 1; dir += 2) { WayPoint closest = stairPoints[i].FindClosest(dir, true, new Vector2(-30.0f, 30f)); if (closest == null) { continue; } stairPoints[i].ConnectTo(closest); } } stairPoints[2] = new WayPoint((stairPoints[0].Position + stairPoints[1].Position) / 2, SpawnType.Path, submarine); stairPoints[0].ConnectTo(stairPoints[2]); stairPoints[2].ConnectTo(stairPoints[1]); } foreach (Item item in Item.ItemList) { var ladders = item.GetComponent <Items.Components.Ladder>(); if (ladders == null) { continue; } List <WayPoint> ladderPoints = new List <WayPoint>(); ladderPoints.Add(new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height + heightFromFloor), SpawnType.Path, submarine)); WayPoint prevPoint = ladderPoints[0]; Vector2 prevPos = prevPoint.SimPosition; List <Body> ignoredBodies = new List <Body>(); for (float y = ladderPoints[0].Position.Y + 100.0f; y < item.Rect.Y - 100.0f; y += 100.0f) { var pickedBody = Submarine.PickBody( ConvertUnits.ToSimUnits(new Vector2(ladderPoints[0].Position.X, y)), prevPos, ignoredBodies, null, false); if (pickedBody == null) { prevPos = Submarine.LastPickedPosition; continue; } ignoredBodies.Add(pickedBody); if (pickedBody.UserData is Item && ((Item)pickedBody.UserData).GetComponent <Door>() != null) { var door = ((Item)pickedBody.UserData).GetComponent <Door>(); WayPoint newPoint = new WayPoint(door.Item.Position, SpawnType.Path, submarine); ladderPoints.Add(newPoint); newPoint.ConnectedGap = door.LinkedGap; newPoint.ConnectTo(prevPoint); prevPoint = newPoint; prevPos = new Vector2(prevPos.X, ConvertUnits.ToSimUnits(door.Item.Position.Y - door.Item.Rect.Height)); } else { WayPoint newPoint = new WayPoint(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition) + Vector2.UnitY * heightFromFloor, SpawnType.Path, submarine); ladderPoints.Add(newPoint); newPoint.ConnectTo(prevPoint); prevPoint = newPoint; prevPos = ConvertUnits.ToSimUnits(newPoint.Position); } } ladderPoints.Add(new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - 1.0f), SpawnType.Path, submarine)); prevPoint.ConnectTo(ladderPoints[ladderPoints.Count - 1]); for (int i = 0; i < ladderPoints.Count; i++) { ladderPoints[i].Ladders = ladders; for (int dir = -1; dir <= 1; dir += 2) { WayPoint closest = ladderPoints[i].FindClosest(dir, true, new Vector2(-150.0f, 10f)); if (closest == null) { continue; } ladderPoints[i].ConnectTo(closest); } if (i == ladderPoints.Count - 1 && ladderPoints.Count > 2) { for (int dir = -1; dir <= 1; dir += 2) { WayPoint closest = ladderPoints[i].FindClosest(dir, true, new Vector2(-150.0f, 10f)); if (closest == null) { continue; } ladderPoints[i].ConnectTo(closest); } } } } foreach (Gap gap in Gap.GapList) { if (!gap.IsHorizontal) { continue; } //too small to walk through if (gap.Rect.Height < 150.0f) { continue; } var wayPoint = new WayPoint( new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height + heightFromFloor), SpawnType.Path, submarine, gap); for (int dir = -1; dir <= 1; dir += 2) { float tolerance = gap.IsRoomToRoom ? 50.0f : outSideWaypointInterval / 2.0f; WayPoint closest = wayPoint.FindClosest( dir, true, new Vector2(-tolerance, tolerance), gap.ConnectedDoor == null ? null : gap.ConnectedDoor.Body.FarseerBody); if (closest != null) { wayPoint.ConnectTo(closest); } } } foreach (Gap gap in Gap.GapList) { if (gap.IsHorizontal || gap.IsRoomToRoom) { continue; } //too small to walk through if (gap.Rect.Width < 100.0f) { continue; } var wayPoint = new WayPoint( new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height / 2), SpawnType.Path, submarine, gap); } var orphans = WayPointList.FindAll(w => w.spawnType == SpawnType.Path && !w.linkedTo.Any()); foreach (WayPoint wp in orphans) { wp.Remove(); } //re-disable the bodies of the doors that are supposed to be open foreach (Door door in openDoors) { door.Body.Enabled = false; } }
/// <summary> /// Constructor for order instances /// </summary> public Order(Order prefab, Structure wall, int?sectionIndex, Character orderGiver = null) : this(prefab, targetEntity : wall, null, orderGiver : orderGiver) { WallSectionIndex = sectionIndex; TargetType = OrderTargetType.WallSection; }
private void ApplyImpact(float impact, Vector2 direction, Vector2 impactPos, bool applyDamage = true) { if (impact < MinCollisionImpact) { return; } Vector2 impulse = direction * impact * 0.5f; impulse = impulse.ClampLength(MaxCollisionImpact); if (!MathUtils.IsValid(impulse)) { string errorMsg = "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse + ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + "."; if (GameMain.NetworkMember != null) { errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server."; } if (GameSettings.VerboseLogging) { DebugConsole.ThrowError(errorMsg); } GameAnalyticsManager.AddErrorEventOnce( "SubmarineBody.ApplyImpact:InvalidImpulse", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } #if CLIENT if (Character.Controlled != null && Character.Controlled.Submarine == submarine) { GameMain.GameScreen.Cam.Shake = impact * 2.0f; if (submarine.Info.Type == SubmarineInfo.SubmarineType.Player && !submarine.DockedTo.Any(s => s.Info.Type != SubmarineInfo.SubmarineType.Player)) { float angularVelocity = (impactPos.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y - (impactPos.Y - Body.SimPosition.Y) / ConvertUnits.ToSimUnits(submarine.Borders.Height / 2) * impulse.X; GameMain.GameScreen.Cam.AngularVelocity = MathHelper.Clamp(angularVelocity * 0.1f, -1.0f, 1.0f); } } #endif foreach (Character c in Character.CharacterList) { if (c.Submarine != submarine) { continue; } foreach (Limb limb in c.AnimController.Limbs) { limb.body.ApplyLinearImpulse(limb.Mass * impulse, 10.0f); } c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 10.0f); bool holdingOntoSomething = false; if (c.SelectedConstruction != null) { var controller = c.SelectedConstruction.GetComponent <Items.Components.Controller>(); holdingOntoSomething = controller != null && controller.LimbPositions.Any(); } //stun for up to 1 second if the impact equal or higher to the maximum impact if (impact >= MaxCollisionImpact && !holdingOntoSomething) { c.SetStun(Math.Min(impulse.Length() * 0.2f, 1.0f)); } } foreach (Item item in Item.ItemList) { if (item.Submarine != submarine || item.CurrentHull == null || item.body == null || !item.body.Enabled) { continue; } item.body.ApplyLinearImpulse(item.body.Mass * impulse, 10.0f); } var damagedStructures = Explosion.RangedStructureDamage( ConvertUnits.ToDisplayUnits(impactPos), impact * 50.0f, applyDamage ? impact * ImpactDamageMultiplier : 0.0f); #if CLIENT //play a damage sound for the structure that took the most damage float maxDamage = 0.0f; Structure maxDamageStructure = null; foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures) { if (maxDamageStructure == null || structureDamage.Value > maxDamage) { maxDamage = structureDamage.Value; maxDamageStructure = structureDamage.Key; } } if (maxDamageStructure != null) { SoundPlayer.PlayDamageSound( "StructureBlunt", impact * 10.0f, ConvertUnits.ToDisplayUnits(impactPos), MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f), maxDamageStructure.Tags); } #endif }
private void ApplyImpact(float impact, Vector2 direction, Contact contact, bool applyDamage = true) { float minImpact = 3.0f; if (impact < minImpact) { return; } contact.GetWorldManifold(out Vector2 tempNormal, out FixedArray2 <Vector2> worldPoints); Vector2 lastContactPoint = worldPoints[0]; Vector2 impulse = direction * impact * 0.5f; impulse = impulse.ClampLength(5.0f); if (!MathUtils.IsValid(impulse)) { string errorMsg = "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse + ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + "."; if (GameMain.NetworkMember != null) { errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server."; } if (GameSettings.VerboseLogging) { DebugConsole.ThrowError(errorMsg); } GameAnalyticsManager.AddErrorEventOnce( "SubmarineBody.ApplyImpact:InvalidImpulse", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } #if CLIENT if (Character.Controlled != null && Character.Controlled.Submarine == submarine) { GameMain.GameScreen.Cam.Shake = impact * 2.0f; float angularVelocity = (lastContactPoint.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y - (lastContactPoint.Y - Body.SimPosition.Y) / ConvertUnits.ToSimUnits(submarine.Borders.Height / 2) * impulse.X; GameMain.GameScreen.Cam.AngularVelocity = MathHelper.Clamp(angularVelocity * 0.1f, -1.0f, 1.0f); } #endif foreach (Character c in Character.CharacterList) { if (c.Submarine != submarine) { continue; } if (impact > 2.0f) { c.SetStun((impact - 2.0f) * 0.1f); } foreach (Limb limb in c.AnimController.Limbs) { limb.body.ApplyLinearImpulse(limb.Mass * impulse, 20.0f); } c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 20.0f); } foreach (Item item in Item.ItemList) { if (item.Submarine != submarine || item.CurrentHull == null || item.body == null || !item.body.Enabled) { continue; } item.body.ApplyLinearImpulse(item.body.Mass * impulse, 20.0f); } var damagedStructures = Explosion.RangedStructureDamage( ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, applyDamage ? impact * ImpactDamageMultiplier : 0.0f); #if CLIENT //play a damage sound for the structure that took the most damage float maxDamage = 0.0f; Structure maxDamageStructure = null; foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures) { if (maxDamageStructure == null || structureDamage.Value > maxDamage) { maxDamage = structureDamage.Value; maxDamageStructure = structureDamage.Key; } } if (maxDamageStructure != null) { SoundPlayer.PlayDamageSound( "StructureBlunt", impact * 10.0f, ConvertUnits.ToDisplayUnits(lastContactPoint), MathHelper.Lerp(2000.0f, 10000.0f, (impact - minImpact) / 2.0f), maxDamageStructure.Tags); } #endif }
public override void UpdatePlacing(Camera cam) { if (PlayerInput.SecondaryMouseButtonClicked()) { selected = null; return; } Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); Vector2 size = ScaledSize; Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y); if (placePosition == Vector2.Zero) { if (PlayerInput.PrimaryMouseButtonHeld()) { placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); } newRect.X = (int)position.X; newRect.Y = (int)position.Y; } else { Vector2 placeSize = size; if (ResizeHorizontal) { placeSize.X = position.X - placePosition.X; } if (ResizeVertical) { placeSize.Y = placePosition.Y - position.Y; } //don't allow resizing width/height to less than the grid size if (ResizeHorizontal && Math.Abs(placeSize.X) < Submarine.GridSize.X) { placeSize.X = Submarine.GridSize.X; } if (ResizeVertical && Math.Abs(placeSize.Y) < Submarine.GridSize.Y) { placeSize.Y = Submarine.GridSize.Y; } newRect = Submarine.AbsRect(placePosition, placeSize); if (PlayerInput.PrimaryMouseButtonReleased()) { newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position); var structure = new Structure(newRect, this, Submarine.MainSub) { Submarine = Submarine.MainSub }; SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List <MapEntity> { structure }, false)); placePosition = Vector2.Zero; if (!PlayerInput.IsShiftDown()) { selected = null; } return; } } }
public void UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget) { float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition)); AttackTimer += deltaTime; body.ApplyTorque(Mass * character.AnimController.Dir * attack.Torque); bool wasHit = false; if (damageTarget != null) { switch (attack.HitDetectionType) { case HitDetection.Distance: wasHit = dist < attack.DamageRange; break; case HitDetection.Contact: List <Body> targetBodies = new List <Body>(); if (damageTarget is Character) { Character targetCharacter = (Character)damageTarget; foreach (Limb limb in targetCharacter.AnimController.Limbs) { if (!limb.IsSevered && limb.body?.FarseerBody != null) { targetBodies.Add(limb.body.FarseerBody); } } } else if (damageTarget is Structure) { Structure targetStructure = (Structure)damageTarget; if (character.Submarine == null && targetStructure.Submarine != null) { targetBodies.Add(targetStructure.Submarine.PhysicsBody.FarseerBody); } else { targetBodies.AddRange(targetStructure.Bodies); } } else if (damageTarget is Item) { Item targetItem = damageTarget as Item; if (targetItem.body?.FarseerBody != null) { targetBodies.Add(targetItem.body.FarseerBody); } } if (targetBodies != null) { ContactEdge contactEdge = body.FarseerBody.ContactList; while (contactEdge != null) { if (contactEdge.Contact != null && contactEdge.Contact.IsTouching && targetBodies.Any(b => b == contactEdge.Contact.FixtureA?.Body || b == contactEdge.Contact.FixtureB?.Body)) { wasHit = true; break; } contactEdge = contactEdge.Next; } } break; } } if (wasHit) { if (AttackTimer >= attack.Duration && damageTarget != null) { attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (SoundTimer <= 0.0f)); SoundTimer = SoundInterval; } } Vector2 diff = attackPosition - SimPosition; if (diff.LengthSquared() < 0.00001f) { return; } if (attack.ApplyForceOnLimbs != null) { foreach (int limbIndex in attack.ApplyForceOnLimbs) { if (limbIndex < 0 || limbIndex >= character.AnimController.Limbs.Length) { continue; } Limb limb = character.AnimController.Limbs[limbIndex]; Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA; limb.body.ApplyLinearImpulse( limb.Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos); } } else { Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA; body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos); } }
//goes through all the AItargets, evaluates how preferable it is to attack the target, //whether the Character can see/hear the target and chooses the most preferable target within //sight/hearing range public void UpdateTargets(Character character) { var prevAiTarget = selectedAiTarget; selectedAiTarget = null; selectedTargetMemory = null; targetValue = 0.0f; UpdateTargetMemories(); foreach (AITarget target in AITarget.List) { if (Level.Loaded != null && target.WorldPosition.Y > Level.Loaded.Size.Y) { continue; } float valueModifier = 0.0f; float dist = 0.0f; Character targetCharacter = target.Entity as Character; //ignore the aitarget if it is the Character itself if (targetCharacter == character) { continue; } if (targetCharacter != null) { if (targetCharacter.IsDead) { if (eatDeadPriority == 0.0f) { continue; } valueModifier = eatDeadPriority; } else if (targetCharacter.SpeciesName == "human") { if (attackHumans == 0.0f) { continue; } valueModifier = attackHumans; } else { EnemyAIController enemy = targetCharacter.AIController as EnemyAIController; if (enemy != null) { if (enemy.combatStrength > combatStrength) { valueModifier = attackStronger; } else if (enemy.combatStrength < combatStrength) { valueModifier = attackWeaker; } else { continue; } } } } else if (target.Entity != null && attackRooms != 0.0f) { IDamageable targetDamageable = target.Entity as IDamageable; if (targetDamageable != null && targetDamageable.Health <= 0.0f) { continue; } //skip the target if it's a room and the character is already inside a sub if (character.AnimController.CurrentHull != null && target.Entity is Hull) { continue; } valueModifier = attackRooms; } if (valueModifier == 0.0f) { continue; } dist = Vector2.Distance(character.WorldPosition, target.WorldPosition); //if the target has been within range earlier, the character will notice it more easily //(i.e. remember where the target was) if (targetMemories.ContainsKey(target)) { dist *= 0.5f; } //ignore target if it's too far to see or hear if (dist > target.SightRange * sight && dist > target.SoundRange * hearing) { continue; } AITargetMemory targetMemory = FindTargetMemory(target); valueModifier = valueModifier * targetMemory.Priority / dist; if (Math.Abs(valueModifier) > Math.Abs(targetValue)) { Vector2 rayStart = character.AnimController.Limbs[0].SimPosition; Vector2 rayEnd = target.SimPosition; if (target.Entity.Submarine != null && character.Submarine == null) { rayStart -= ConvertUnits.ToSimUnits(target.Entity.Submarine.Position); } Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure; if (selectedAiTarget == null || Math.Abs(valueModifier) > Math.Abs(targetValue)) { selectedAiTarget = target; selectedTargetMemory = targetMemory; targetValue = valueModifier; } } } if (selectedAiTarget != prevAiTarget) { wallAttackPos = Vector2.Zero; } }
public virtual bool IsAllowedToDamage(Structure structure) => false;
/// <summary> /// Control the Character according to player input /// </summary> public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true) { if (!DisableControls) { for (int i = 0; i < keys.Length; i++) { keys[i].SetState(); } } else { foreach (Key key in keys) { if (key == null) { continue; } key.Reset(); } } if (moveCam) { if (needsAir && pressureProtection < 80.0f && (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 50.0f)) { float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure; cam.Zoom = MathHelper.Lerp(cam.Zoom, (pressure / 50.0f) * Rand.Range(1.0f, 1.05f), (pressure - 50.0f) / 50.0f); } if (IsHumanoid) { cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime); } else { //increased visibility range when controlling large a non-humanoid cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, MathHelper.Clamp(Mass, 250.0f, 800.0f), deltaTime); } } cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition); if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null) { cursorPosition -= AnimController.CurrentHull.Submarine.Position; } Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition); if (moveCam) { if (DebugConsole.IsOpen || GUI.PauseMenuOpen || IsUnconscious || (GameMain.GameSession?.CrewManager?.CrewCommander != null && GameMain.GameSession.CrewManager.CrewCommander.IsOpen)) { if (deltaTime > 0.0f) { cam.OffsetAmount = 0.0f; } } else if (Lights.LightManager.ViewTarget == this && Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f) { Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos); Structure structure = body == null ? null : body.UserData as Structure; float sightDist = Submarine.LastPickedFraction; if (body?.UserData is Structure && !((Structure)body.UserData).CastShadow) { sightDist = 1.0f; } cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, Math.Max(250.0f, sightDist * 500.0f), 0.05f); } } DoInteractionUpdate(deltaTime, mouseSimPos); DisableControls = false; }
private void GetTargetEntity() { targetEntity = null; if (Character.AnimController.CurrentHull != null) { wallAttackPos = Vector2.Zero; return; } //check if there's a wall between the target and the Character Vector2 rayStart = Character.SimPosition; Vector2 rayEnd = selectedAiTarget.SimPosition; if (selectedAiTarget.Entity.Submarine != null && Character.Submarine == null) { rayStart -= ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position); } Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); if (Submarine.LastPickedFraction == 1.0f || closestBody == null) { wallAttackPos = Vector2.Zero; return; } Structure wall = closestBody.UserData as Structure; if (wall == null) { wallAttackPos = Submarine.LastPickedPosition; if (selectedAiTarget.Entity.Submarine != null && Character.Submarine == null) { wallAttackPos -= ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position); } } else { int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition)); float sectionDamage = wall.SectionDamage(sectionIndex); for (int i = sectionIndex - 2; i <= sectionIndex + 2; i++) { if (wall.SectionBodyDisabled(i)) { sectionIndex = i; break; } if (wall.SectionDamage(i) > sectionDamage) { sectionIndex = i; } } wallAttackPos = wall.SectionPosition(sectionIndex); //if (wall.Submarine != null) wallAttackPos += wall.Submarine.Position; wallAttackPos = ConvertUnits.ToSimUnits(wallAttackPos); } targetEntity = closestBody.UserData as IDamageable; }
private void ApplyImpact(float impact, Vector2 direction, Contact contact) { if (impact < 3.0f) { return; } Vector2 tempNormal; FarseerPhysics.Common.FixedArray2 <Vector2> worldPoints; contact.GetWorldManifold(out tempNormal, out worldPoints); Vector2 lastContactPoint = worldPoints[0]; if (Character.Controlled != null && Character.Controlled.Submarine == submarine) { GameMain.GameScreen.Cam.Shake = impact * 2.0f; } Vector2 impulse = direction * impact * 0.5f; float length = impulse.Length(); if (length > 5.0f) { impulse = (impulse / length) * 5.0f; } foreach (Character c in Character.CharacterList) { if (c.Submarine != submarine) { continue; } if (impact > 2.0f) { c.SetStun((impact - 2.0f) * 0.1f); } foreach (Limb limb in c.AnimController.Limbs) { limb.body.ApplyLinearImpulse(limb.Mass * impulse); } c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse); } foreach (Item item in Item.ItemList) { if (item.Submarine != submarine || item.CurrentHull == null || item.body == null || !item.body.Enabled) { continue; } item.body.ApplyLinearImpulse(item.body.Mass * impulse); } var damagedStructures = Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, impact * DamageMultiplier); //play a damage sound for the structure that took the most damage float maxDamage = 0.0f; Structure maxDamageStructure = null; foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures) { if (maxDamageStructure == null || structureDamage.Value > maxDamage) { maxDamage = structureDamage.Value; maxDamageStructure = structureDamage.Key; } } #if CLIENT if (maxDamageStructure != null) { SoundPlayer.PlayDamageSound( DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(lastContactPoint), MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f), maxDamageStructure.Tags); } #endif }
public static List <MapEntity> LoadAll(Submarine submarine, XElement parentElement, string filePath, int idOffset) { IdRemap idRemap = new IdRemap(parentElement, idOffset); List <MapEntity> entities = new List <MapEntity>(); foreach (XElement element in parentElement.Elements()) { string typeName = element.Name.ToString(); Type t; try { t = Type.GetType("Barotrauma." + typeName, true, true); if (t == null) { DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type \"" + typeName + "\"."); continue; } } catch (Exception e) { DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type \"" + typeName + "\".", e); continue; } if (t == typeof(Structure)) { string name = element.Attribute("name").Value; string identifier = element.GetAttributeString("identifier", ""); StructurePrefab structurePrefab = Structure.FindPrefab(name, identifier); if (structurePrefab == null) { ItemPrefab itemPrefab = ItemPrefab.Find(name, identifier); if (itemPrefab != null) { t = typeof(Item); } } } try { MethodInfo loadMethod = t.GetMethod("Load", new[] { typeof(XElement), typeof(Submarine), typeof(IdRemap) }); if (loadMethod == null) { DebugConsole.ThrowError("Could not find the method \"Load\" in " + t + "."); } else if (!loadMethod.ReturnType.IsSubclassOf(typeof(MapEntity))) { DebugConsole.ThrowError("Error loading entity of the type \"" + t.ToString() + "\" - load method does not return a valid map entity."); } else { object newEntity = loadMethod.Invoke(t, new object[] { element, submarine, idRemap }); if (newEntity != null) { entities.Add((MapEntity)newEntity); } } } catch (TargetInvocationException e) { DebugConsole.ThrowError("Error while loading entity of the type " + t + ".", e.InnerException); } catch (Exception e) { DebugConsole.ThrowError("Error while loading entity of the type " + t + ".", e); } } return(entities); }
public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List <Body> ignoredBodies = null, Category?collisionCategory = null, bool ignoreSensors = true) { if (Vector2.DistanceSquared(rayStart, rayEnd) < 0.00001f) { rayEnd += Vector2.UnitX * 0.001f; } float closestFraction = 1.0f; Vector2 closestNormal = Vector2.Zero; Body closestBody = null; GameMain.World.RayCast((fixture, point, normal, fraction) => { if (fixture == null || (ignoreSensors && fixture.IsSensor) || fixture.CollisionCategories == Category.None || fixture.CollisionCategories == Physics.CollisionItem) { return(-1); } if (collisionCategory != null && !fixture.CollisionCategories.HasFlag((Category)collisionCategory) && !((Category)collisionCategory).HasFlag(fixture.CollisionCategories)) { return(-1); } if (ignoredBodies != null && ignoredBodies.Contains(fixture.Body)) { return(-1); } Structure structure = fixture.Body.UserData as Structure; if (structure != null) { if (structure.IsPlatform && collisionCategory != null && !((Category)collisionCategory).HasFlag(Physics.CollisionPlatform)) { return(-1); } } if (fraction < closestFraction) { closestFraction = fraction; closestNormal = normal; if (fixture.Body != null) { closestBody = fixture.Body; } } return(fraction); } , rayStart, rayEnd); lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction; lastPickedFraction = closestFraction; lastPickedNormal = closestNormal; return(closestBody); }
/// <summary> /// Control the Character according to player input /// </summary> public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true) { if (!DisableControls) { for (int i = 0; i < keys.Length; i++) { keys[i].SetState(); } } else { foreach (Key key in keys) { if (key == null) { continue; } key.Reset(); } } if (moveCam) { if (needsAir && pressureProtection < 80.0f && (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 50.0f)) { float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure; cam.Zoom = MathHelper.Lerp(cam.Zoom, (pressure / 50.0f) * Rand.Range(1.0f, 1.05f), (pressure - 50.0f) / 50.0f); } if (IsHumanoid) { cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime); } else { //increased visibility range when controlling large a non-humanoid cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, MathHelper.Clamp(Mass, 250.0f, 800.0f), deltaTime); } } cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition); if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null) { cursorPosition -= AnimController.CurrentHull.Submarine.Position; } Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition); if (Lights.LightManager.ViewTarget == this && Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f) { Body body = Submarine.PickBody(AnimController.Limbs[0].SimPosition, mouseSimPos); Structure structure = null; if (body != null) { structure = body.UserData as Structure; } if (structure != null) { if (!structure.CastShadow && moveCam) { cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 500.0f, 0.05f); } } } DoInteractionUpdate(deltaTime, mouseSimPos); DisableControls = false; }
private void PlayDamageSound(Vector2 impactSimPos, float impact, string soundTag, Structure hitStructure = null) { if (impact < MinCollisionImpact) { return; } SoundPlayer.PlayDamageSound( soundTag, impact * 10.0f, ConvertUnits.ToDisplayUnits(impactSimPos), MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f), hitStructure?.Tags); }