From 78bccca4af373b69bdfc6f27107d7a2552e19b36 Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 9 Dec 2015 19:29:53 +0200 Subject: [PATCH] Moar progress, fixed shadow/los/submarine misalignment issues --- .../Content/Characters/Coelanth/coelanth.xml | 2 +- Subsurface/Source/Characters/AI/AITarget.cs | 5 + .../Source/Characters/AI/EnemyAIController.cs | 61 ++-- .../Source/Characters/AI/HumanAIController.cs | 4 +- .../AI/Objectives/AIObjectiveIdle.cs | 4 +- .../Source/Characters/Animation/Ragdoll.cs | 26 +- Subsurface/Source/Characters/Attack.cs | 2 +- .../BackgroundSprite/BackgroundSprite.cs | 6 +- .../BackgroundSpriteManager.cs | 5 +- Subsurface/Source/Characters/Character.cs | 20 +- Subsurface/Source/Characters/Limb.cs | 9 +- Subsurface/Source/Characters/StatusEffect.cs | 2 +- Subsurface/Source/DebugConsole.cs | 4 +- Subsurface/Source/GameSession/CargoManager.cs | 2 +- .../GameSession/GameModes/TutorialMode.cs | 2 +- Subsurface/Source/Items/Components/Door.cs | 2 +- .../Items/Components/Holdable/RepairTool.cs | 22 +- .../Items/Components/Machines/Engine.cs | 2 +- .../Source/Items/Components/Machines/Pump.cs | 2 +- .../Items/Components/Machines/Reactor.cs | 2 +- .../Items/Components/Machines/Steering.cs | 2 +- .../Items/Components/Power/PowerTransfer.cs | 2 +- .../Items/Components/Signal/OxygenDetector.cs | 20 +- .../Source/Items/Components/Signal/Wire.cs | 21 +- Subsurface/Source/Items/Components/Turret.cs | 6 +- Subsurface/Source/Items/Item.cs | 5 +- Subsurface/Source/Map/Explosion.cs | 50 ++- Subsurface/Source/Map/FireSource.cs | 8 +- Subsurface/Source/Map/Gap.cs | 2 +- Subsurface/Source/Map/Hull.cs | 17 +- Subsurface/Source/Map/IDamageable.cs | 5 + Subsurface/Source/Map/Levels/LevelRenderer.cs | 6 +- Subsurface/Source/Map/Lights/ConvexHull.cs | 32 +- Subsurface/Source/Map/Lights/LightManager.cs | 2 +- Subsurface/Source/Map/MapEntity.cs | 19 +- Subsurface/Source/Map/Structure.cs | 23 +- Subsurface/Source/Map/Submarine.cs | 37 ++- Subsurface/Source/Map/SubmarineBody.cs | 290 ++++++++---------- Subsurface/Source/Map/WayPoint.cs | 2 +- Subsurface/Source/Particles/Particle.cs | 39 ++- Subsurface/Source/Screens/GameScreen.cs | 5 +- Subsurface/Source/Sounds/SoundPlayer.cs | 2 +- Subsurface_Solution.v12.suo | Bin 810496 -> 812544 bytes 43 files changed, 396 insertions(+), 383 deletions(-) diff --git a/Subsurface/Content/Characters/Coelanth/coelanth.xml b/Subsurface/Content/Characters/Coelanth/coelanth.xml index 1f9407652..66786ce8e 100644 --- a/Subsurface/Content/Characters/Coelanth/coelanth.xml +++ b/Subsurface/Content/Characters/Coelanth/coelanth.xml @@ -15,7 +15,7 @@ - + diff --git a/Subsurface/Source/Characters/AI/AITarget.cs b/Subsurface/Source/Characters/AI/AITarget.cs index b4f0f3af6..868468704 100644 --- a/Subsurface/Source/Characters/AI/AITarget.cs +++ b/Subsurface/Source/Characters/AI/AITarget.cs @@ -27,6 +27,11 @@ namespace Barotrauma set { sightRange = value; } } + public Vector2 WorldPosition + { + get { return Entity.WorldPosition; } + } + public Vector2 SimPosition { get { return Entity.SimPosition; } diff --git a/Subsurface/Source/Characters/AI/EnemyAIController.cs b/Subsurface/Source/Characters/AI/EnemyAIController.cs index 3c6d2c4b4..1c1b00e1a 100644 --- a/Subsurface/Source/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Source/Characters/AI/EnemyAIController.cs @@ -167,12 +167,17 @@ namespace Barotrauma selectedTargetMemory.Priority -= deltaTime; - Vector2 attackPosition = selectedAiTarget.SimPosition; - if (wallAttackPos != Vector2.Zero) attackPosition = wallAttackPos; + Vector2 attackSimPosition = Character.Submarine==null ? ConvertUnits.ToSimUnits(selectedAiTarget.WorldPosition) : selectedAiTarget.SimPosition; + if (wallAttackPos != Vector2.Zero) + { + attackSimPosition = wallAttackPos; + + if (selectedAiTarget.Entity != null && Character.Submarine==null && selectedAiTarget.Entity.Submarine != null) attackSimPosition += ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position); + } if (coolDownTimer>0.0f) { - UpdateCoolDown(attackPosition, deltaTime); + UpdateCoolDown(attackSimPosition, deltaTime); return; } @@ -187,7 +192,7 @@ namespace Barotrauma raycastTimer = RaycastInterval; } - steeringManager.SteeringSeek(attackPosition); + steeringManager.SteeringSeek(attackSimPosition); //check if any of the limbs is close enough to attack the target if (attackingLimb == null) @@ -195,7 +200,7 @@ namespace Barotrauma foreach (Limb limb in Character.AnimController.Limbs) { if (limb.attack==null || limb.attack.Type == AttackType.None) continue; - if (Vector2.Distance(limb.SimPosition, attackPosition) > limb.attack.Range) continue; + if (ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackSimPosition)) > limb.attack.Range) continue; attackingLimb = limb; break; @@ -203,7 +208,7 @@ namespace Barotrauma return; } - UpdateLimbAttack(deltaTime, attackingLimb, attackPosition); + UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition); } @@ -230,9 +235,19 @@ namespace Barotrauma private void GetTargetEntity() { targetEntity = null; + + + + //check if there's a wall between the target and the Character - Vector2 rayStart = Character.AnimController.Limbs[0].SimPosition; + 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) @@ -245,6 +260,8 @@ namespace Barotrauma if (wall == null) { wallAttackPos = Submarine.LastPickedPosition; + if (selectedAiTarget.Entity.Submarine!=null) wallAttackPos -= ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position); + } else { @@ -261,6 +278,7 @@ namespace Barotrauma if (wall.SectionDamage(i) > sectionDamage) sectionIndex = i; } wallAttackPos = wall.SectionPosition(sectionIndex); + //if (wall.Submarine != null) wallAttackPos += wall.Submarine.Position; wallAttackPos = ConvertUnits.ToSimUnits(wallAttackPos); } @@ -288,15 +306,8 @@ namespace Barotrauma float dir = (limb.attack.Type == AttackType.PinchCW) ? 1.0f : -1.0f; - if (wallAttackPos != Vector2.Zero && targetEntity != null) - { - damageTarget = targetEntity as IDamageable; - } - else - { - damageTarget = selectedAiTarget.Entity as IDamageable; - } - + damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable; + attackTimer += deltaTime*0.05f; if (damageTarget == null) @@ -305,12 +316,12 @@ namespace Barotrauma break; } - float dist = Vector2.Distance(limb.SimPosition, damageTarget.SimPosition); + float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackPosition)); if (dist < limb.attack.Range * 0.5f) { attackTimer += deltaTime; limb.body.ApplyTorque(limb.Mass * 50.0f * Character.AnimController.Dir * dir); - + limb.attack.DoDamage(Character, damageTarget, limb.SimPosition, deltaTime, (limb.soundTimer <= 0.0f)); limb.soundTimer = Limb.SoundInterval; @@ -392,9 +403,8 @@ namespace Barotrauma } dist = Vector2.Distance( - character.AnimController.Limbs[0].SimPosition, - target.SimPosition); - dist = ConvertUnits.ToDisplayUnits(dist); + character.WorldPosition, + target.WorldPosition); AITargetMemory targetMemory = FindTargetMemory(target); @@ -406,6 +416,11 @@ namespace Barotrauma 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; @@ -490,12 +505,12 @@ namespace Barotrauma { if (Character.IsDead) return; - Vector2 pos = Character.Position; + Vector2 pos = Character.WorldPosition; pos.Y = -pos.Y; if (selectedAiTarget!=null) { - GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(new Vector2(selectedAiTarget.SimPosition.X, -selectedAiTarget.SimPosition.Y)), Color.Red); + GUI.DrawLine(spriteBatch, pos, new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red); if (wallAttackPos!=Vector2.Zero) { diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index 6ab49fa46..8a8b5c8af 100644 --- a/Subsurface/Source/Characters/AI/HumanAIController.cs +++ b/Subsurface/Source/Characters/AI/HumanAIController.cs @@ -87,7 +87,9 @@ namespace Barotrauma { if (selectedAiTarget != null) { - GUI.DrawLine(spriteBatch, new Vector2(Character.Position.X, -Character.Position.Y), ConvertUnits.ToDisplayUnits(new Vector2(selectedAiTarget.SimPosition.X, -selectedAiTarget.SimPosition.Y)), Color.Red); + GUI.DrawLine(spriteBatch, + new Vector2(Character.WorldPosition.X, -Character.WorldPosition.Y), + new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red); } IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager; diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs index 9bd5f267f..0017385fe 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -89,8 +89,8 @@ namespace Barotrauma foreach (WayPoint wp in WayPoint.WayPointList) { - if (wp.SpawnType != SpawnType.Human) continue; - + if (wp.SpawnType != SpawnType.Human || wp.CurrentHull==null) continue; + foreach (string tag in wp.IdCardTags) { if (idCard.HasTag(tag)) return wp.CurrentHull.AiTarget; diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index b92ce3d2a..0f5432c86 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -536,11 +536,11 @@ namespace Barotrauma } } - public void FindHull(bool setSubmarine = true) + public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true) { - Hull newHull = Hull.FindHull( - ConvertUnits.ToDisplayUnits(refLimb.SimPosition), - currentHull); + Vector2 findPos = worldPosition==null ? refLimb.WorldPosition : (Vector2)worldPosition; + + Hull newHull = Hull.FindHull(findPos, currentHull); if (newHull == currentHull) return; @@ -619,11 +619,9 @@ namespace Barotrauma foreach (Limb limb in Limbs) { - Vector2 limbPosition = ConvertUnits.ToDisplayUnits(limb.SimPosition); - //find the room which the limb is in //the room where the ragdoll is in is used as the "guess", meaning that it's checked first - Hull limbHull = Hull.FindHull(limbPosition, currentHull); + Hull limbHull = Hull.FindHull(limb.WorldPosition, currentHull); bool prevInWater = limb.inWater; limb.inWater = false; @@ -633,9 +631,9 @@ namespace Barotrauma //limb isn't in any room -> it's in the water limb.inWater = true; } - else if (limbHull.Volume > 0.0f && Submarine.RectContains(limbHull.Rect, limbPosition)) - { - if (limbPosition.Y < limbHull.Surface) + else if (limbHull.Volume > 0.0f && Submarine.RectContains(limbHull.Rect, limb.Position)) + { + if (limb.Position.Y < limbHull.Surface) { limb.inWater = true; @@ -659,12 +657,12 @@ namespace Barotrauma //create a splash particle GameMain.ParticleManager.CreateParticle("watersplash", - new Vector2(limb.Position.X, limbHull.Surface), + new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position, new Vector2(0.0f, Math.Abs(-limb.LinearVelocity.Y * 10.0f)), 0.0f, limbHull); - + GameMain.ParticleManager.CreateParticle("bubbles", - new Vector2(limb.Position.X, limbHull.Surface), + new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position, limb.LinearVelocity*0.001f, 0.0f, limbHull); @@ -678,7 +676,7 @@ namespace Barotrauma float parallel = (float)Math.Abs(Math.Sin(limb.Rotation)); Vector2 impulse = Vector2.Multiply(limb.LinearVelocity, -parallel * limb.Mass); //limb.body.ApplyLinearImpulse(impulse); - int n = (int)((limbPosition.X - limbHull.Rect.X) / Hull.WaveWidth); + int n = (int)((limb.Position.X - limbHull.Rect.X) / Hull.WaveWidth); limbHull.WaveVel[n] = Math.Min(impulse.Y * 1.0f, 5.0f); StrongestImpact = ((impulse.Length() * 0.5f) - limb.impactTolerance); } diff --git a/Subsurface/Source/Characters/Attack.cs b/Subsurface/Source/Characters/Attack.cs index fd7f06ce2..bd59c5923 100644 --- a/Subsurface/Source/Characters/Attack.cs +++ b/Subsurface/Source/Characters/Attack.cs @@ -109,7 +109,7 @@ namespace Barotrauma sound = Sound.Load(soundPath); } - Range = FarseerPhysics.ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "range", 0.0f)); + Range = ToolBox.GetAttributeFloat(element, "range", 0.0f); Duration = ToolBox.GetAttributeFloat(element, "duration", 0.0f); diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs index dead2e808..49a5be9c9 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs @@ -153,15 +153,15 @@ namespace Barotrauma if (velocity.X < 0.0f) rotation -= MathHelper.Pi; } - if (Level.Loaded != null) drawPosition = position;// +Level.Loaded.Position; + drawPosition = position;// +Level.Loaded.Position; if (depth > 0.0f) { Vector2 camOffset = drawPosition - GameMain.GameScreen.Cam.WorldViewCenter; - drawPosition = drawPosition - camOffset * (depth / MaxDepth) * 0.05f; + drawPosition -= camOffset * (depth / MaxDepth) * 0.05f; } - + prefab.Sprite.Draw(spriteBatch, new Vector2(drawPosition.X, -drawPosition.Y), Color.Lerp(Color.White, Color.DarkBlue, (depth/MaxDepth)*0.3f), rotation, 1.0f - (depth / MaxDepth) * 0.2f, velocity.X > 0.0f ? SpriteEffects.None : SpriteEffects.FlipHorizontally, (depth / MaxDepth)); } diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs index 410b119c2..b08753e8c 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs @@ -47,9 +47,10 @@ namespace Barotrauma if (position == null) { - if (WayPoint.WayPointList.Count>0) + var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null); + if (wayPoints.Any()) { - WayPoint wp = WayPoint.WayPointList[Rand.Int(WayPoint.WayPointList.Count)]; + WayPoint wp = wayPoints[Rand.Int(wayPoints.Count)]; pos = new Vector2(wp.Rect.X, wp.Rect.Y); pos += Rand.Vector(200.0f); diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 7744f2b37..e2cf4a5b7 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -138,6 +138,11 @@ namespace Barotrauma } } + public Vector2 CursorWorldPosition + { + get { return Submarine == null ? cursorPosition : cursorPosition + Submarine.Position; } + } + public Character ClosestCharacter { get { return closestCharacter; } @@ -295,7 +300,7 @@ namespace Barotrauma public static Character Create(CharacterInfo characterInfo, WayPoint spawnPoint, bool isNetworkPlayer = false) { - return Create(characterInfo.File, spawnPoint.SimPosition, characterInfo, isNetworkPlayer); + return Create(characterInfo.File, spawnPoint.WorldPosition, characterInfo, isNetworkPlayer); } @@ -393,7 +398,7 @@ namespace Barotrauma foreach (Limb limb in AnimController.Limbs) { - limb.body.SetTransform(position+limb.SimPosition, 0.0f); + limb.body.SetTransform(ConvertUnits.ToSimUnits(position)+limb.SimPosition, 0.0f); //limb.prevPosition = ConvertUnits.ToDisplayUnits(position); } @@ -443,7 +448,8 @@ namespace Barotrauma } } - AnimController.FindHull(false); + AnimController.FindHull(null, false); + if (AnimController.CurrentHull != null) Submarine = AnimController.CurrentHull.Submarine; CharacterList.Add(this); @@ -735,7 +741,7 @@ namespace Barotrauma { Limb head = AnimController.GetLimb(LimbType.Head); - Lights.LightManager.ViewPos = ConvertUnits.ToDisplayUnits(WorldPosition); + Lights.LightManager.ViewPos = WorldPosition; if (!DisableControls) { @@ -1004,7 +1010,7 @@ namespace Barotrauma AnimController.DebugDraw(spriteBatch); } - Vector2 healthBarPos = new Vector2(Position.X - 50, -Position.Y - 100.0f); + Vector2 healthBarPos = new Vector2(WorldPosition.X - 50, -WorldPosition.Y - 100.0f); GUI.DrawRectangle(spriteBatch, new Rectangle((int)healthBarPos.X - 2, (int)healthBarPos.Y - 2, 100 + 4, 15 + 4), Color.Black, false); GUI.DrawRectangle(spriteBatch, new Rectangle((int)healthBarPos.X, (int)healthBarPos.Y, (int)(100.0f * (health / maxHealth)), 15), Color.Red, true); } @@ -1102,12 +1108,12 @@ namespace Barotrauma for (int i = 0; i < 10; i++) { Particle p = GameMain.ParticleManager.CreateParticle("waterblood", - centerOfMass + Rand.Vector(50.0f), + ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(50.0f), Vector2.Zero); if (p!=null) p.Size *= 2.0f; GameMain.ParticleManager.CreateParticle("bubbles", - centerOfMass + Rand.Vector(50.0f), + ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(50.0f), new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f,50f))); } diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index f3e20b861..15ae58311 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -79,6 +79,11 @@ namespace Barotrauma get { return doesFlip; } } + public Vector2 WorldPosition + { + get { return character.Submarine == null ? Position : Position + character.Submarine.Position; } + } + public Vector2 Position { get { return ConvertUnits.ToDisplayUnits(body.SimPosition); } @@ -352,13 +357,13 @@ namespace Barotrauma if (particleVel != Vector2.Zero) particleVel = Vector2.Normalize(particleVel); GameMain.ParticleManager.CreateParticle("blood", - Position, + WorldPosition, particleVel * Rand.Range(100.0f, 300.0f), 0.0f, character.AnimController.CurrentHull); } for (int i = 0; i < bloodAmount / 2; i++) { - GameMain.ParticleManager.CreateParticle("waterblood", Position, Vector2.Zero, 0.0f, character.AnimController.CurrentHull); + GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull); } damage += Math.Max(amount,bleedingAmount) / character.MaxHealth * 100.0f; diff --git a/Subsurface/Source/Characters/StatusEffect.cs b/Subsurface/Source/Characters/StatusEffect.cs index da6786d54..a8826ac87 100644 --- a/Subsurface/Source/Characters/StatusEffect.cs +++ b/Subsurface/Source/Characters/StatusEffect.cs @@ -212,7 +212,7 @@ namespace Barotrauma protected virtual void Apply(float deltaTime, Entity entity, List targets) { - if (explosion != null) explosion.Explode(entity.SimPosition); + if (explosion != null) explosion.Explode(entity.WorldPosition); if (Fire) new FireSource(ConvertUnits.ToDisplayUnits(entity.SimPosition)); if (sound != null) sound.Play(1.0f, 1000.0f, ConvertUnits.ToDisplayUnits(entity.SimPosition)); diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 54e6a579d..b0d7d1ec3 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -225,7 +225,7 @@ namespace Barotrauma if (commands[1].ToLower()=="human") { WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Human); - Character.Controlled = Character.Create(Character.HumanConfigFile, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition); + Character.Controlled = Character.Create(Character.HumanConfigFile, (spawnPoint == null) ? Vector2.Zero : spawnPoint.WorldPosition); if (GameMain.GameSession != null) { SinglePlayerMode mode = GameMain.GameSession.gameMode as SinglePlayerMode; @@ -237,7 +237,7 @@ namespace Barotrauma else { WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Enemy); - Character.Create("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition); + Character.Create("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", (spawnPoint == null) ? Vector2.Zero : spawnPoint.WorldPosition); } break; diff --git a/Subsurface/Source/GameSession/CargoManager.cs b/Subsurface/Source/GameSession/CargoManager.cs index 8d0226448..0f6dea546 100644 --- a/Subsurface/Source/GameSession/CargoManager.cs +++ b/Subsurface/Source/GameSession/CargoManager.cs @@ -30,7 +30,7 @@ namespace Barotrauma return; } - Hull cargoRoom = Hull.FindHull(wp.Position); + Hull cargoRoom = Hull.FindHull(wp.WorldPosition); if (cargoRoom == null) { diff --git a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs index b9854f2ff..2c64e0bfe 100644 --- a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs +++ b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs @@ -343,7 +343,7 @@ namespace Barotrauma bool broken = false; do { - Submarine.Loaded.Speed = Vector2.Zero; + Submarine.Loaded.Velocity = Vector2.Zero; moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget); Vector2 steeringDir = windows[0].Position - moloch.Position; diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 6933fb1cc..fb23a0644 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -318,7 +318,7 @@ namespace Barotrauma.Items.Components } Vector2 pos = new Vector2(item.Rect.Center.X, item.Rect.Y); - if (item.Submarine != null) pos += item.Submarine.Position; + if (item.Submarine != null) pos += item.Submarine.DrawPosition; pos.Y = -pos.Y; spriteBatch.Draw(doorSprite.Texture, pos, diff --git a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs index cdcbaac48..47a36bb99 100644 --- a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs +++ b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs @@ -24,8 +24,8 @@ namespace Barotrauma.Items.Components [HasDefaultValue(0.0f, false)] public float Range { - get { return ConvertUnits.ToDisplayUnits(range); } - set { range = ConvertUnits.ToSimUnits(value); } + get { return range; } + set { range = value; } } [HasDefaultValue(0.0f, false)] @@ -61,8 +61,8 @@ namespace Barotrauma.Items.Components [HasDefaultValue("0.0,0.0", false)] public string BarrelPos { - get { return ToolBox.Vector2ToString(ConvertUnits.ToDisplayUnits(barrelPos)); } - set { barrelPos = ConvertUnits.ToSimUnits(ToolBox.ParseToVector2(value)); } + get { return ToolBox.Vector2ToString(barrelPos); } + set { barrelPos = ToolBox.ParseToVector2(value); } } public Vector2 TransformedBarrelPos @@ -72,7 +72,7 @@ namespace Barotrauma.Items.Components Matrix bodyTransform = Matrix.CreateRotationZ(item.body.Rotation); Vector2 flippedPos = barrelPos; if (item.body.Dir < 0.0f) flippedPos.X = -flippedPos.X; - return (Vector2.Transform(flippedPos, bodyTransform) + item.body.SimPosition); + return (Vector2.Transform(flippedPos, bodyTransform)); } } @@ -115,7 +115,6 @@ namespace Barotrauma.Items.Components IsActive = true; - Vector2 targetPosition = item.body.SimPosition; //targetPosition = targetPosition.X, -targetPosition.Y); float degreeOfSuccess = DegreeOfSuccess(character)/100.0f; @@ -126,6 +125,7 @@ namespace Barotrauma.Items.Components return false; } + Vector2 targetPosition = item.WorldPosition; targetPosition += new Vector2( (float)Math.Cos(item.body.Rotation), (float)Math.Sin(item.body.Rotation)) * range * item.body.Dir; @@ -137,14 +137,18 @@ namespace Barotrauma.Items.Components ignoredBodies.Add(limb.body.FarseerBody); } + Vector2 rayStart = item.WorldPosition + TransformedBarrelPos; + Vector2 rayEnd = targetPosition; + Body targetBody = Submarine.PickBody( + ConvertUnits.ToSimUnits(rayStart - Submarine.Loaded.Position), + ConvertUnits.ToSimUnits(rayEnd - Submarine.Loaded.Position), ignoredBodies); - Body targetBody = Submarine.PickBody(TransformedBarrelPos, targetPosition, ignoredBodies); pickedPosition = Submarine.LastPickedPosition; if (ExtinquishAmount > 0.0f) { - Vector2 displayPos = ConvertUnits.ToDisplayUnits(TransformedBarrelPos + (targetPosition-TransformedBarrelPos)*Submarine.LastPickedFraction*0.9f); + Vector2 displayPos = rayStart + (rayEnd-rayStart)*Submarine.LastPickedFraction*0.9f; Hull hull = Hull.FindHull(displayPos, item.CurrentHull); if (hull != null) hull.Extinquish(deltaTime, ExtinquishAmount, displayPos); } @@ -224,7 +228,7 @@ namespace Barotrauma.Items.Components if (!string.IsNullOrWhiteSpace(particles)) { - GameMain.ParticleManager.CreateParticle(particles, ConvertUnits.ToDisplayUnits(TransformedBarrelPos), + GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition+TransformedBarrelPos, -item.body.Rotation + ((item.body.Dir>0.0f) ? 0.0f : MathHelper.Pi), ParticleSpeed); } diff --git a/Subsurface/Source/Items/Components/Machines/Engine.cs b/Subsurface/Source/Items/Components/Machines/Engine.cs index d86d955fc..238d92a38 100644 --- a/Subsurface/Source/Items/Components/Machines/Engine.cs +++ b/Subsurface/Source/Items/Components/Machines/Engine.cs @@ -74,7 +74,7 @@ namespace Barotrauma.Items.Components for (int i = 0; i < 5; i++) { - GameMain.ParticleManager.CreateParticle("bubbles", item.Position, + GameMain.ParticleManager.CreateParticle("bubbles", item.WorldPosition, -currForce / 5.0f + new Vector2(Rand.Range(-100.0f, 100.0f), Rand.Range(-50f, 50f)), 0.0f, item.CurrentHull); } diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index bce4c90ae..d58a9c465 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -103,7 +103,7 @@ namespace Barotrauma.Items.Components private void GetHull() { - hull1 = Hull.FindHull(item.Position, item.CurrentHull); + hull1 = Hull.FindHull(item.WorldPosition, item.CurrentHull); } public override void DrawHUD(SpriteBatch spriteBatch, Character character) diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 1f3ee98fa..78355ed1e 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -163,7 +163,7 @@ namespace Barotrauma.Items.Components Vector2 baseVel = Rand.Vector(300.0f); for (int i = 0; i < 10; i++) { - var particle = GameMain.ParticleManager.CreateParticle("spark", item.Position, + var particle = GameMain.ParticleManager.CreateParticle("spark", item.WorldPosition, baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull); if (particle != null) particle.Size *= Rand.Range(0.5f, 1.0f); diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index d938a96b9..fff87c0d5 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -193,7 +193,7 @@ namespace Barotrauma.Items.Components { float prediction = 5.0f; - Vector2 futurePosition = Submarine.Loaded.Speed * prediction; + Vector2 futurePosition = ConvertUnits.ToDisplayUnits(Submarine.Loaded.Velocity) * prediction; Vector2 targetSpeed = ((steeringPath.CurrentNode.Position - Submarine.Loaded.Position) - futurePosition); targetSpeed = Vector2.Normalize(targetSpeed); diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index 62c650871..c777e3a0f 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -67,7 +67,7 @@ namespace Barotrauma.Items.Components Vector2 baseVel = Rand.Vector(300.0f); for (int i = 0; i < 10; i++) { - var particle = GameMain.ParticleManager.CreateParticle("spark", pt.item.Position, + var particle = GameMain.ParticleManager.CreateParticle("spark", pt.item.WorldPosition, baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull); if (particle != null) particle.Size *= Rand.Range(0.5f, 1.0f); diff --git a/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs b/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs index 918d64241..1a06ccf46 100644 --- a/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs +++ b/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs @@ -4,31 +4,17 @@ namespace Barotrauma.Items.Components { class OxygenDetector : ItemComponent { - private Hull hull; - public OxygenDetector(Item item, XElement element) : base (item, element) { - hull = Hull.FindHull(item.Position); - IsActive = true; } - public override void OnMapLoaded() - { - hull = Hull.FindHull(item.Position); - } - - public override void Move(Microsoft.Xna.Framework.Vector2 amount) - { - hull = Hull.FindHull(item.Position); - } - public override void Update(float deltaTime, Camera cam) { - if (hull == null) return; - - item.SendSignal(((int)hull.OxygenPercentage).ToString(), "signal_out"); + if (item.CurrentHull == null) return; + + item.SendSignal(((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out"); } diff --git a/Subsurface/Source/Items/Components/Signal/Wire.cs b/Subsurface/Source/Items/Components/Signal/Wire.cs index 771b2e4ee..a338b94f1 100644 --- a/Subsurface/Source/Items/Components/Signal/Wire.cs +++ b/Subsurface/Source/Items/Components/Signal/Wire.cs @@ -41,11 +41,10 @@ namespace Barotrauma.Items.Components public override void Move(Vector2 amount) { - //amount = FarseerPhysics.ConvertUnits.ToDisplayUnits(amount); - //for (int i = 0; i 0.0f) { - RangedStructureDamage(displayPosition, displayRange, attack.GetStructureDamage(1.0f)); + RangedStructureDamage(worldPosition, displayRange, attack.GetStructureDamage(1.0f)); } if (force == 0.0f && attack.Stun == 0.0f && attack.GetDamage(1.0f) == 0.0f) return; foreach (Character c in Character.CharacterList) { - float dist = Vector2.Distance(c.SimPosition, simPosition); + float dist = Vector2.Distance(c.WorldPosition, worldPosition); if (dist > attack.Range) continue; @@ -91,14 +83,14 @@ namespace Barotrauma foreach (Limb limb in c.AnimController.Limbs) { - if (limb.SimPosition == simPosition) continue; - distFactor = 1.0f - Vector2.Distance(limb.SimPosition, simPosition)/attack.Range; + if (limb.WorldPosition == worldPosition) continue; + distFactor = 1.0f - Vector2.Distance(limb.WorldPosition, worldPosition)/attack.Range; c.AddDamage(limb.SimPosition, DamageType.None, attack.GetDamage(1.0f) / c.AnimController.Limbs.Length * distFactor, 0.0f, attack.Stun * distFactor, false); - if (force>0.0f) + if (force > 0.0f) { - limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.SimPosition - simPosition) * distFactor * force); + limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force); } } } @@ -124,7 +116,7 @@ namespace Barotrauma yield return CoroutineStatus.Success; } - public static void RangedStructureDamage(Vector2 displayPosition, float displayRange, float damage) + public static void RangedStructureDamage(Vector2 worldPosition, float worldRange, float damage) { List structureList = new List(); @@ -137,7 +129,7 @@ namespace Barotrauma if (structure.HasBody && !structure.IsPlatform && - Vector2.Distance(structure.Position, displayPosition) < dist * 3.0f) + Vector2.Distance(structure.WorldPosition, worldPosition) < dist * 3.0f) { structureList.Add(structure); } @@ -147,7 +139,7 @@ namespace Barotrauma { for (int i = 0; i < structure.SectionCount; i++) { - float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i), displayPosition) / displayRange); + float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i, true), worldPosition) / worldRange); if (distFactor > 0.0f) structure.AddDamage(i, damage * distFactor); } } diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs index ae2fd58be..2bba83534 100644 --- a/Subsurface/Source/Map/FireSource.cs +++ b/Subsurface/Source/Map/FireSource.cs @@ -39,9 +39,9 @@ namespace Barotrauma get { return size; } } - public FireSource(Vector2 position, Hull spawningHull = null, bool networkEvent=false) + public FireSource(Vector2 worldPosition, Hull spawningHull = null, bool networkEvent=false) { - hull = Hull.FindHull(position, spawningHull); + hull = Hull.FindHull(worldPosition, spawningHull); if (hull == null || (!networkEvent && GameMain.Client!=null)) return; if (fireSoundBasic==null) @@ -50,11 +50,11 @@ namespace Barotrauma fireSoundLarge = Sound.Load("Content/Sounds/firelarge.ogg"); } - lightSource = new LightSource(position, 50.0f, new Color(1.0f, 0.9f, 0.6f), hull == null ? null : hull.Submarine); + lightSource = new LightSource(worldPosition, 50.0f, new Color(1.0f, 0.9f, 0.6f), hull == null ? null : hull.Submarine); hull.AddFireSource(this, !networkEvent); - this.position = position - new Vector2(-5.0f, 5.0f); + this.position = worldPosition - new Vector2(-5.0f, 5.0f); //this.position.Y = hull.Rect.Y - hull.Rect.Height; diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index 5fe9e32ba..de315a9df 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -229,7 +229,7 @@ namespace Barotrauma { pos.X += Math.Sign(flowForce.X); pos.Y = MathHelper.Clamp((higherSurface+lowerSurface)/2.0f, rect.Y - rect.Height, rect.Y); - + Vector2 velocity = new Vector2( MathHelper.Clamp(flowForce.X, -5000.0f, 5000.0f) * Rand.Range(0.5f, 0.7f), flowForce.Y * Rand.Range(0.5f, 0.7f)); diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index 22f0f9f69..6c5e52e89 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -270,8 +270,11 @@ namespace Barotrauma float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i])); if (maxDelta > Rand.Range(1.0f,10.0f)) { + Vector2 particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]); + if (Submarine != null) particlePos += Submarine.Position; + GameMain.ParticleManager.CreateParticle("mist", - new Vector2(rect.X + WaveWidth * i,surface + waveY[i]), + particlePos, new Vector2(0.0f, -50.0f), 0.0f, this); } @@ -473,21 +476,21 @@ namespace Barotrauma } //returns the water block which contains the point (or null if it isn't inside any) - public static Hull FindHull(Vector2 position, Hull guess = null) + public static Hull FindHull(Vector2 worldPosition, Hull guess = null) { - return FindHull(position, hullList, guess); + return FindHull(worldPosition, hullList, guess); } - public static Hull FindHull(Vector2 position, List hulls, Hull guess = null) + public static Hull FindHull(Vector2 worldPosition, List hulls, Hull guess = null) { if (guess != null && hulls.Contains(guess)) { - if (Submarine.RectContains(guess.rect, position)) return guess; + if (Submarine.RectContains(guess.WorldRect, worldPosition)) return guess; } - foreach (Hull w in hulls) + foreach (Hull hull in hulls) { - if (Submarine.RectContains(w.rect, position)) return w; + if (Submarine.RectContains(hull.WorldRect, worldPosition)) return hull; } return null; diff --git a/Subsurface/Source/Map/IDamageable.cs b/Subsurface/Source/Map/IDamageable.cs index 995c3121f..9b56fc410 100644 --- a/Subsurface/Source/Map/IDamageable.cs +++ b/Subsurface/Source/Map/IDamageable.cs @@ -9,6 +9,11 @@ namespace Barotrauma get; } + Vector2 WorldPosition + { + get; + } + float Health { get; diff --git a/Subsurface/Source/Map/Levels/LevelRenderer.cs b/Subsurface/Source/Map/Levels/LevelRenderer.cs index 0938c9a45..3ae18a0ac 100644 --- a/Subsurface/Source/Map/Levels/LevelRenderer.cs +++ b/Subsurface/Source/Map/Levels/LevelRenderer.cs @@ -35,18 +35,18 @@ namespace Barotrauma public void Draw(SpriteBatch spriteBatch) { - Vector2 pos = Vector2.Zero;// level.EndPosition; + Vector2 pos = new Vector2(0.0f, -level.StartPosition.Y);// level.EndPosition; //pos.Y = -pos.Y - level.Position.Y; if (GameMain.GameScreen.Cam.WorldView.Y < -pos.Y - 512) return; - pos.X = GameMain.GameScreen.Cam.WorldView.X - 512.0f; + pos.X = GameMain.GameScreen.Cam.WorldView.X -512.0f; //pos.X += Position.X % 512; int width = (int)(Math.Ceiling(GameMain.GameScreen.Cam.WorldView.Width / 512.0f + 2.0f) * 512.0f); spriteBatch.Draw(shaftTexture, - new Rectangle((int)(MathUtils.Round(pos.X, 512.0f) - Submarine.Loaded.Position.X % 512), (int)pos.Y, width, 512), + new Rectangle((int)(MathUtils.Round(pos.X, 512.0f)), (int)pos.Y, width, 512), new Rectangle(0, 0, width, 256), Color.White, 0.0f, Vector2.Zero, diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs index 20c72fdf3..2e2133d85 100644 --- a/Subsurface/Source/Map/Lights/ConvexHull.cs +++ b/Subsurface/Source/Map/Lights/ConvexHull.cs @@ -30,7 +30,6 @@ namespace Barotrauma.Lights private Dictionary cachedShadows; - private Vector2[] worldVertices; private Vector2[] vertices; private int primitiveCount; @@ -75,7 +74,6 @@ namespace Barotrauma.Lights cachedShadows = new Dictionary(); vertices = points; - worldVertices = new Vector2[vertices.Length]; primitiveCount = vertices.Length; CalculateDimensions(); @@ -115,7 +113,6 @@ namespace Barotrauma.Lights for (int i = 0; i < vertices.Count(); i++) { vertices[i] += amount; - worldVertices[i] += amount; } CalculateDimensions(); @@ -125,26 +122,17 @@ namespace Barotrauma.Lights { cachedShadows.Clear(); - worldVertices = points; vertices = points; } private void CalculateShadowVertices(Vector2 lightSourcePos, bool los = true) { - for (int i = 0; i < vertices.Length; i++) - { - worldVertices[i] = vertices[i]; - if (parentEntity != null && parentEntity.Submarine != null) - { - worldVertices[i] += parentEntity.Submarine.Position; - } - } //compute facing of each edge, using N*L for (int i = 0; i < primitiveCount; i++) { - Vector2 firstVertex = new Vector2(worldVertices[i].X, worldVertices[i].Y); + Vector2 firstVertex = new Vector2(vertices[i].X, vertices[i].Y); int secondIndex = (i + 1) % primitiveCount; - Vector2 secondVertex = new Vector2(worldVertices[secondIndex].X, worldVertices[secondIndex].Y); + Vector2 secondVertex = new Vector2(vertices[secondIndex].X, vertices[secondIndex].Y); Vector2 middle = (firstVertex + secondVertex) / 2; Vector2 L = lightSourcePos - middle; @@ -187,7 +175,7 @@ namespace Barotrauma.Lights int svCount = 0; while (svCount != shadowVertexCount * 2) { - Vector3 vertexPos = new Vector3(worldVertices[currentIndex], 0.0f); + Vector3 vertexPos = new Vector3(vertices[currentIndex], 0.0f); //one vertex on the hull shadowVertices[svCount] = new VertexPositionColor(); @@ -217,7 +205,7 @@ namespace Barotrauma.Lights for (int n = 0; n < 4; n += 3) { - Vector3 penumbraStart = new Vector3((n == 0) ? worldVertices[startingIndex] : worldVertices[endingIndex], 0.0f); + Vector3 penumbraStart = new Vector3((n == 0) ? vertices[startingIndex] : vertices[endingIndex], 0.0f); penumbraVertices[n] = new VertexPositionTexture(); penumbraVertices[n].Position = penumbraStart; @@ -293,6 +281,8 @@ namespace Barotrauma.Lights { if (!Enabled) return; + if (parentEntity != null && parentEntity.Submarine != null) lightSourcePos -= parentEntity.Submarine.Position; + CalculateShadowVertices(lightSourcePos, los); DrawShadows(graphicsDevice, cam, transform, los); @@ -300,7 +290,15 @@ namespace Barotrauma.Lights private void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, Matrix transform, bool los = true) { - shadowEffect.World = transform; + + Vector3 offset = Vector3.Zero; + if (parentEntity != null && parentEntity.Submarine != null) + { + offset = new Vector3(parentEntity.Submarine.DrawPosition.X, parentEntity.Submarine.DrawPosition.Y, 0.0f); + } + + + shadowEffect.World = Matrix.CreateTranslation(offset) * transform; shadowEffect.CurrentTechnique.Passes[0].Apply(); graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, shadowVertices, 0, shadowVertices.Length - 2); diff --git a/Subsurface/Source/Map/Lights/LightManager.cs b/Subsurface/Source/Map/Lights/LightManager.cs index 6248090e1..4cc6b6d3d 100644 --- a/Subsurface/Source/Map/Lights/LightManager.cs +++ b/Subsurface/Source/Map/Lights/LightManager.cs @@ -128,7 +128,7 @@ namespace Barotrauma.Lights //draw the light shape //where Alpha is 0, nothing will be written - spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, Matrix.CreateTranslation(new Vector3(Submarine.Loaded.Position.X, -Submarine.Loaded.Position.Y, 0.0f)) * cam.Transform); + spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, Matrix.CreateTranslation(new Vector3(Submarine.Loaded.DrawPosition.X, -Submarine.Loaded.DrawPosition.Y, 0.0f)) * cam.Transform); light.Draw(spriteBatch); spriteBatch.End(); } diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index 05e282a27..b1842622d 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -70,7 +70,12 @@ namespace Barotrauma public virtual Rectangle Rect { get { return rect; } set { rect = value; } - } + } + + public Rectangle WorldRect + { + get { return Submarine == null ? rect : new Rectangle((int)(Submarine.Position.X + rect.X), (int)(Submarine.Position.Y + rect.Y), rect.Width, rect.Height); } + } public virtual Sprite Sprite { @@ -505,12 +510,16 @@ namespace Barotrauma foreach (MapEntity e in mapEntityList) { e.OnMapLoaded(); + + if (e.Submarine != null) e.Move(Submarine.HiddenSubPosition); } - //mapEntityList.Sort((x, y) => - //{ - // return x.Name.CompareTo(y.Name); - //}); + + + mapEntityList.Sort((x, y) => + { + return x.Name.CompareTo(y.Name); + }); } diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 313509faa..dc9902dd1 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -292,16 +292,16 @@ namespace Barotrauma Color color = (isHighlighted) ? Color.Green : Color.White; if (isSelected && editing) color = Color.Red; - Vector2 drawPos = Submarine == null ? new Vector2(rect.X, -rect.Y) : new Vector2(rect.X + Submarine.DrawPosition.X, -(rect.Y + Submarine.DrawPosition.Y)); - - prefab.sprite.DrawTiled(spriteBatch, drawPos, new Vector2(rect.Width, rect.Height), Vector2.Zero, color); + Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition; + prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), Vector2.Zero, color); foreach (WallSection s in sections) { + if (s.isHighLighted) { GUI.DrawRectangle(spriteBatch, - drawPos, new Vector2(rect.Width, rect.Height), + new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), new Color((s.damage / prefab.MaxHealth), 1.0f - (s.damage / prefab.MaxHealth), 0.0f, 1.0f), true); } @@ -310,7 +310,7 @@ namespace Barotrauma if (s.damage < 0.01f) continue; GUI.DrawRectangle(spriteBatch, - drawPos, new Vector2(rect.Width, rect.Height), + new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), Color.Black * (s.damage / prefab.MaxHealth), true); } @@ -413,13 +413,17 @@ namespace Barotrauma return sections[sectionIndex].damage; } - public Vector2 SectionPosition(int sectionIndex) + public Vector2 SectionPosition(int sectionIndex, bool world = false) { if (sectionIndex < 0 || sectionIndex >= sections.Length) return Vector2.Zero; - return new Vector2( + Vector2 sectionPos = new Vector2( sections[sectionIndex].rect.X + sections[sectionIndex].rect.Width / 2.0f, sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f); + + if (world && Submarine != null) sectionPos += Submarine.Position; + + return sectionPos; } public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, float deltaTime, bool playSound = false) @@ -427,7 +431,10 @@ namespace Barotrauma if (Submarine.Loaded != null && Submarine.Loaded.GodMode) return new AttackResult(0.0f, 0.0f); if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f); - int i = FindSectionIndex(ConvertUnits.ToDisplayUnits(position)); + Vector2 transformedPos = ConvertUnits.ToDisplayUnits(position); + if (Submarine != null) transformedPos -= Submarine.Position; + + int i = FindSectionIndex(transformedPos); if (i == -1) return new AttackResult(0.0f, 0.0f); GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f); diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 6c0d41534..d5d4d6f2f 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -25,6 +25,10 @@ namespace Barotrauma { public static string SavePath = "Data" + System.IO.Path.DirectorySeparatorChar + "SavedSubs"; + //position of the "actual submarine" which is rendered wherever the SubmarineBody is + //should be in an unreachable place + public static readonly Vector2 HiddenSubPosition = new Vector2(0.0f, 50000.0f); + public static List SavedSubmarines = new List(); public static readonly Vector2 GridSize = new Vector2(16.0f, 16.0f); @@ -97,7 +101,7 @@ namespace Barotrauma public override Vector2 Position { - get { return subBody.Position; } + get { return subBody.Position - HiddenSubPosition; } } public new Vector2 DrawPosition @@ -106,13 +110,13 @@ namespace Barotrauma private set; } - public Vector2 Speed + public Vector2 Velocity { - get { return subBody==null ? Vector2.Zero : subBody.Speed; } - set + get { return subBody==null ? Vector2.Zero : subBody.Velocity; } + set { if (subBody == null) return; - subBody.Speed = value; + subBody.Velocity = value; } } @@ -185,10 +189,6 @@ namespace Barotrauma MapEntity.mapEntityList[i].Draw(spriteBatch, editing); } - if (Submarine.Loaded!=null) - { - Submarine.Loaded.DrawPosition = Physics.Interpolate(Submarine.Loaded.prevPosition, Submarine.Loaded.Position); - } if (loaded == null) return; @@ -214,6 +214,11 @@ namespace Barotrauma } } + public void UpdateTransform() + { + DrawPosition = Physics.Interpolate(prevPosition, Position); + } + //math/physics stuff ---------------------------------------------------- public static Vector2 MouseToWorldGrid(Camera cam) @@ -414,8 +419,8 @@ namespace Barotrauma message.Write(Position.X); message.Write(Position.Y); - message.Write(Speed.X); - message.Write(Speed.Y); + message.Write(Velocity.X); + message.Write(Velocity.Y); return true; } @@ -446,7 +451,7 @@ namespace Barotrauma //newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime); subBody.TargetPosition = newTargetPosition; - subBody.Speed = newSpeed; + subBody.Velocity = newSpeed; lastNetworkUpdate = sendingTime; } @@ -611,6 +616,8 @@ namespace Barotrauma XDocument doc = OpenDoc(filePath); if (doc == null) return; + subBody = new SubmarineBody(this); + foreach (XElement element in doc.Root.Elements()) { string typeName = element.Name.ToString(); @@ -643,7 +650,7 @@ namespace Barotrauma } - subBody = new SubmarineBody(this); + subBody.SetPosition(HiddenSubPosition); loaded = this; @@ -694,10 +701,10 @@ namespace Barotrauma { if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; - subBody = null; - Entity.RemoveAll(); + subBody = null; + PhysicsBody.list.Clear(); Ragdoll.list.Clear(); diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 4c5b32f16..14e34f442 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -35,14 +35,12 @@ namespace Barotrauma private Body body; - private Vector2 speed; - private Vector2 targetPosition; float mass = 10000.0f; - private Vector2? lastContactPoint; - private VoronoiCell lastContactCell; + //private Vector2? lastContactPoint; + //private VoronoiCell lastContactCell; public Rectangle Borders { @@ -50,13 +48,13 @@ namespace Barotrauma private set; } - public Vector2 Speed + public Vector2 Velocity { - get { return speed; } - set + get { return body.LinearVelocity; } + set { if (!MathUtils.IsValid(value)) return; - speed = value; + body.LinearVelocity = value; } } @@ -117,15 +115,16 @@ namespace Barotrauma body = BodyFactory.CreateCompoundPolygon(GameMain.World, triangulatedVertices, 5.0f); body.BodyType = BodyType.Dynamic; - body.CollisionCategories = Physics.CollisionMisc; + body.CollisionCategories = Physics.CollisionMisc | Physics.CollisionWall; body.CollidesWith = Physics.CollisionLevel | Physics.CollisionCharacter; - body.Restitution = 0.0f; + body.Restitution = Restitution; + body.Friction = Friction; body.FixedRotation = true; + body.Mass = mass; body.Awake = true; body.SleepingAllowed = false; body.IgnoreGravity = true; body.OnCollision += OnCollision; - body.OnSeparation += OnSeparation; body.UserData = this; } @@ -224,14 +223,14 @@ namespace Barotrauma Vector2 totalForce = CalculateBuoyancy(); - if (speed.LengthSquared() > 0.000001f) + if (body.LinearVelocity.LengthSquared() > 0.000001f) { float dragCoefficient = 0.00001f; - float speedLength = (speed == Vector2.Zero) ? 0.0f : speed.Length(); + float speedLength = (body.LinearVelocity == Vector2.Zero) ? 0.0f : body.LinearVelocity.Length(); float drag = speedLength * speedLength * dragCoefficient * mass; - totalForce += -Vector2.Normalize(speed) * drag; + totalForce += -Vector2.Normalize(body.LinearVelocity) * drag; } ApplyForce(totalForce); @@ -267,7 +266,7 @@ namespace Barotrauma public void ApplyForce(Vector2 force) { - body.ApplyForce(force/100.0f); + body.ApplyForce(force); } public void SetPosition(Vector2 position) @@ -317,31 +316,121 @@ namespace Barotrauma depthDamageTimer = 10.0f; } - private void UpdateColliding() + //private void UpdateColliding() + //{ + + // return; + + // if (body.Position.LengthSquared()<0.00001f) return; + + // Vector2 normal = Vector2.Normalize(body.Position); + // Vector2 simSpeed = ConvertUnits.ToSimUnits(body.LinearVelocity); + + // float impact = Vector2.Dot(simSpeed, -normal); + + // if (impact < 0.0f) return; + + // Vector2 u = Vector2.Dot(simSpeed, -normal) * normal; + // Vector2 w = (simSpeed + u); + + // //speed = ConvertUnits.ToDisplayUnits(w * (1.0f - Friction) + u * Restitution); + + // if (lastContactPoint == null || lastContactCell==null || impact < 3.0f) return; + + // SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits((Vector2)lastContactPoint)); + // GameMain.GameScreen.Cam.Shake = impact * 2.0f; + + // Vector2 limbForce = -normal * impact*0.5f; + + // float length = limbForce.Length(); + // if (length > 10.0f) limbForce = (limbForce / length) * 10.0f; + + // foreach (Character c in Character.CharacterList) + // { + // if (c.AnimController.CurrentHull == null) continue; + + // if (impact > 2.0f) c.AnimController.StunTimer = (impact - 2.0f) * 0.1f; + + // foreach (Limb limb in c.AnimController.Limbs) + // { + // if (c.AnimController.LowestLimb == limb) continue; + // limb.body.ApplyLinearImpulse(limb.Mass * limbForce); + // } + // } + + // Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits((Vector2)lastContactPoint), impact*50.0f, impact*DamageMultiplier); + + // //Body wallBody = Submarine.PickBody( + // // (Vector2)lastContactPoint - body.Position, + // // (Vector2)lastContactPoint + body.Position * 10.0f, + // // new List() { lastContactCell.body }); + + // //if (wallBody == null || wallBody.UserData == null) return; + + // //var damageable = wallBody.UserData as IDamageable; + // //Structure structure = wallBody.UserData as Structure; + + // //if (structure == null) return; + + // //int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition)); + + // //for (int i = sectionIndex - (int)(impact / 5.0f); i < sectionIndex + (int)(impact / 5.0f); i++) + // //{ + // // structure.AddDamage(i, impact * DamageMultiplier); + // //} + //} + + public bool OnCollision(Fixture f1, Fixture f2, Contact contact) { - return; - if (body.Position.LengthSquared()<0.00001f) return; - - Vector2 normal = Vector2.Normalize(body.Position); - Vector2 simSpeed = ConvertUnits.ToSimUnits(speed); - - float impact = Vector2.Dot(simSpeed, -normal); - - if (impact < 0.0f) return; - - Vector2 u = Vector2.Dot(simSpeed, -normal) * normal; - Vector2 w = (simSpeed + u); - - speed = ConvertUnits.ToDisplayUnits(w * (1.0f - Friction) + u * Restitution); + VoronoiCell cell = f2.Body.UserData as VoronoiCell; - if (lastContactPoint == null || lastContactCell==null || impact < 3.0f) return; - - SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits((Vector2)lastContactPoint)); + if (cell == null) + { + Limb limb = f2.Body.UserData as Limb; + if (limb!=null && limb.character.Submarine==null) + { + Vector2 normal2; + FixedArray2 points; + contact.GetWorldManifold(out normal2, out points); + + if (Submarine.PickBody(points[0] - ConvertUnits.ToSimUnits(submarine.Position) + normal2, points[0] - ConvertUnits.ToSimUnits(submarine.Position) - normal2, null, Physics.CollisionWall) != null) + { + + return true; + } + + var ragdoll = limb.character.AnimController; + ragdoll.FindHull(); + + return false; + + } + + return true; + } + + Vector2 normal; + FarseerPhysics.Common.FixedArray2 worldPoints; + contact.GetWorldManifold(out normal, out worldPoints); + + Vector2 lastContactPoint = worldPoints[0]; + + + float impact = Vector2.Dot(Velocity, -normal); + + //Vector2 u = Vector2.Dot(Velocity, -normal) * normal; + //Vector2 w = (Velocity + u); + + //speed = ConvertUnits.ToDisplayUnits(w * (1.0f - Friction) + u * Restitution); + + if (impact < 3.0f) return true; + + SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(lastContactPoint)); GameMain.GameScreen.Cam.Shake = impact * 2.0f; - Vector2 limbForce = -normal * impact*0.5f; + Vector2 limbForce = -normal * impact * 0.5f; float length = limbForce.Length(); if (length > 10.0f) limbForce = (limbForce / length) * 10.0f; @@ -359,141 +448,10 @@ namespace Barotrauma } } - Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits((Vector2)lastContactPoint), impact*50.0f, impact*DamageMultiplier); - - //Body wallBody = Submarine.PickBody( - // (Vector2)lastContactPoint - body.Position, - // (Vector2)lastContactPoint + body.Position * 10.0f, - // new List() { lastContactCell.body }); - - //if (wallBody == null || wallBody.UserData == null) return; - - //var damageable = wallBody.UserData as IDamageable; - //Structure structure = wallBody.UserData as Structure; - - //if (structure == null) return; - - //int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition)); - - //for (int i = sectionIndex - (int)(impact / 5.0f); i < sectionIndex + (int)(impact / 5.0f); i++) - //{ - // structure.AddDamage(i, impact * DamageMultiplier); - //} - } - - public bool OnCollision(Fixture f1, Fixture f2, Contact contact) - { - VoronoiCell cell = f2.Body.UserData as VoronoiCell; - if (cell == null) - { - Limb limb = f2.Body.UserData as Limb; - if (limb!=null && limb.character.Submarine==null) - { - Vector2 normal2; - FixedArray2 points; - contact.GetWorldManifold(out normal2, out points); - - if (Submarine.PickBody(points[0] - ConvertUnits.ToSimUnits(submarine.Position), points[0] - ConvertUnits.ToSimUnits(submarine.Position) - normal2, null, Physics.CollisionWall) != null) - { - return true; - } - - return false; - //var ragdoll = limb.character.AnimController; - //ragdoll.SetPosition(ragdoll.RefLimb.Position - body.Position); - //limb.character.Submarine = submarine; - } - - return true; - } - - lastContactCell = cell; - - Vector2 normal; - FarseerPhysics.Common.FixedArray2 worldPoints; - contact.GetWorldManifold(out normal, out worldPoints); - - lastContactPoint = worldPoints[0]; + Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, impact * DamageMultiplier); return true; - - //Vector2 normal = contact.Manifold.LocalNormal; - //Vector2 simSpeed = ConvertUnits.ToSimUnits(speed); - //float impact = Vector2.Dot(-simSpeed, normal); - - ////Vector2 u = Vector2.Dot(simSpeed, -normal) * -normal; - ////Vector2 w = simSpeed - u; - - //Vector2 limbForce = normal * impact; - - ////float length = limbForce.Length(); - ////if (length > 10.0f) limbForce = (limbForce / length) * 10.0f; - - ////foreach (Character c in Character.CharacterList) - ////{ - //// if (c.AnimController.CurrentHull == null) continue; - - //// if (impact > 2.0f) c.AnimController.StunTimer = (impact - 2.0f) * 0.1f; - - //// foreach (Limb limb in c.AnimController.Limbs) - //// { - //// if (c.AnimController.LowestLimb == limb) continue; - //// limb.body.ApplyLinearImpulse(limb.Mass * limbForce); - //// } - ////} - - //System.Diagnostics.Debug.WriteLine("IMPACT: " + impact + " normal: " + normal + " simspeed: " + simSpeed); - //if (impact > 1.0f) - //{ - - // contact.GetWorldManifold(out normal, out worldPoints); - - // lastContactPoint = worldPoints[0]; - - // AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(worldPoints[0])); - - // GameMain.GameScreen.Cam.Shake = impact * 2.0f; - - // //speed = ConvertUnits.ToDisplayUnits(w * 0.9f + u * 0.5f); - - // //FixedArray2 worldPoints; - // //contact.GetWorldManifold(out normal, out worldPoints); - - // //if (contact.Manifold.PointCount >= 1) - // //{ - // // Vector2 contactPoint = worldPoints[0]; - - // // Body wallBody = Submarine.PickBody(contactPoint, contactPoint + normal, new List() { cell.body }); - - // // if (wallBody!=null && wallBody.UserData!=null) - // // { - // // Structure s = wallBody.UserData as Structure; - // // } - // //} - - // //foreach (GraphEdge ge in cell.edges) - // //{ - // // Body wallBody = Submarine.PickBody( - // // ConvertUnits.ToSimUnits(ge.point1 + GameMain.GameSession.Level.Position + normal), - // // ConvertUnits.ToSimUnits(ge.point2 + GameMain.GameSession.Level.Position + normal), new List() { cell.body }); - // // if (wallBody == null || wallBody.UserData == null) continue; - - // // Structure structure = wallBody.UserData as Structure; - // // if (structure == null) continue; - // // structure.AddDamage( - // // structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition)), impact*50.0f); - // //} - //} - - - //collisionRigidness = 0.8f; - - //return true; } - public void OnSeparation(Fixture f1, Fixture f2) - { - lastContactPoint = null; - } } } diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index 7ed2808f5..6de856274 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -403,7 +403,7 @@ namespace Barotrauma public override void OnMapLoaded() { - currentHull = Hull.FindHull(this.Position); + currentHull = Hull.FindHull(WorldPosition); } public override XElement Save(XDocument doc) diff --git a/Subsurface/Source/Particles/Particle.cs b/Subsurface/Source/Particles/Particle.cs index 9cacf2284..0c07c275b 100644 --- a/Subsurface/Source/Particles/Particle.cs +++ b/Subsurface/Source/Particles/Particle.cs @@ -74,7 +74,7 @@ namespace Barotrauma.Particles spriteIndex = Rand.Int(prefab.Sprites.Count); currentHull = Hull.FindHull(position, hullGuess); - if (currentHull == null) position = Submarine.Loaded == null ? position : position + Submarine.Loaded.Position; + //if (currentHull == null) position = Submarine.Loaded == null ? position : position + Submarine.Loaded.Position; this.position = position; prevPosition = position; @@ -164,8 +164,8 @@ namespace Barotrauma.Particles if ((prefab.DeleteOnCollision || prefab.CollidesWithWalls) && currentHull!=null) { Vector2 edgePos = position + prefab.CollisionRadius * Vector2.Normalize(velocity) * size.X; - - if (!Submarine.RectContains(currentHull.Rect, edgePos)) + + if (!Submarine.RectContains(currentHull.WorldRect, edgePos)) { if (prefab.DeleteOnCollision) return false; @@ -174,13 +174,13 @@ namespace Barotrauma.Particles { if (!gap.isHorizontal) { - if (gap.Rect.X > position.X || gap.Rect.Right < position.X) continue; - if (Math.Sign(velocity.Y) != Math.Sign(gap.Rect.Y - (currentHull.Rect.Y-currentHull.Rect.Height))) continue; + if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X) continue; + if (Math.Sign(velocity.Y) != Math.Sign(gap.WorldRect.Y - (currentHull.WorldRect.Y - currentHull.WorldRect.Height))) continue; } else { - if (gap.Rect.Y < position.Y || gap.Rect.Y - gap.Rect.Height > position.Y) continue; - if (Math.Sign(velocity.X) != Math.Sign(gap.Rect.Center.X - currentHull.Rect.Center.X)) continue; + if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y) continue; + if (Math.Sign(velocity.X) != Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X)) continue; } //Rectangle enlargedRect = new Rectangle(gap.Rect.X - 10, gap.Rect.Y + 10, gap.Rect.Width + 20, gap.Rect.Height + 20); @@ -224,27 +224,29 @@ namespace Barotrauma.Particles } private void OnWallCollision(Hull prevHull, Vector2 position) - { - if (position.Y < prevHull.Rect.Y - prevHull.Rect.Height) + { + Rectangle prevHullRect = prevHull.WorldRect; + + if (position.Y < prevHullRect.Y - prevHullRect.Height) { - position.Y = prevHull.Rect.Y - prevHull.Rect.Height + 1.0f; + position.Y = prevHullRect.Y - prevHullRect.Height + 1.0f; velocity.Y = -velocity.Y; } - else if (position.Y > prevHull.Rect.Y) + else if (position.Y > prevHullRect.Y) { - position.Y = prevHull.Rect.Y - 1.0f; + position.Y = prevHullRect.Y - 1.0f; velocity.X = Math.Abs(velocity.Y) * Math.Sign(velocity.X); velocity.Y = -velocity.Y*0.1f; } - if (position.X < prevHull.Rect.X) + if (position.X < prevHullRect.X) { - position.X = prevHull.Rect.X + 1.0f; + position.X = prevHullRect.X + 1.0f; velocity.X = -velocity.X; } - else if (position.X > prevHull.Rect.X + prevHull.Rect.Width) + else if (position.X > prevHullRect.X + prevHullRect.Width) { - position.X = prevHull.Rect.X + prevHull.Rect.Width - 1.0f; + position.X = prevHullRect.X + prevHullRect.Width - 1.0f; velocity.X = -velocity.X; } @@ -265,11 +267,8 @@ namespace Barotrauma.Particles drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime); } - Vector2 screenSpacePos = currentHull == null && Submarine.Loaded != null ? drawPosition - Submarine.Loaded.Position : drawPosition; - screenSpacePos.Y = -screenSpacePos.Y; - prefab.Sprites[spriteIndex].Draw(spriteBatch, - screenSpacePos, + new Vector2(drawPosition.X, -drawPosition.Y), color * alpha, prefab.Sprites[spriteIndex].origin, drawRotation, drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index 75f9f334e..1c5900610 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -166,11 +166,14 @@ namespace Barotrauma public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch) { + + if (Submarine.Loaded != null) Submarine.Loaded.UpdateTransform(); + GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision; GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam); GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, - Character.Controlled==null ? LightManager.ViewPos : Character.Controlled.CursorPosition); + Character.Controlled==null ? LightManager.ViewPos : Character.Controlled.CursorWorldPosition); //---------------------------------------------------------------------------------------- //1. draw the background, characters and the parts of the submarine that are behind them diff --git a/Subsurface/Source/Sounds/SoundPlayer.cs b/Subsurface/Source/Sounds/SoundPlayer.cs index 48878cc98..96255625a 100644 --- a/Subsurface/Source/Sounds/SoundPlayer.cs +++ b/Subsurface/Source/Sounds/SoundPlayer.cs @@ -201,7 +201,7 @@ namespace Barotrauma float movementFactor = 0.0f; if (Submarine.Loaded != null) { - movementFactor = (Submarine.Loaded.Speed == Vector2.Zero) ? 0.0f : Submarine.Loaded.Speed.Length() / 500.0f; + movementFactor = (Submarine.Loaded.Velocity == Vector2.Zero) ? 0.0f : Submarine.Loaded.Velocity.Length() / 5.0f; movementFactor = MathHelper.Clamp(movementFactor, 0.0f, 1.0f); } diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index ba8cfe073c394c80a55ddf98e84108da6e351715..2bde0e29a7539466782408071d29101c26abad2d 100644 GIT binary patch delta 11941 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 delta 13010 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