Networking optimization/bugfixes (hull water volumes & wall damage are synced, more reliable inventory updates, AICharacter sync changes), proper particle collisions with walls

This commit is contained in:
Regalis
2015-09-25 18:56:39 +03:00
parent 3587b4a4bb
commit 53e729ea11
27 changed files with 50344 additions and 273 deletions

View File

@@ -68,7 +68,7 @@ namespace Subsurface
float cameraDist = Vector2.Distance(GameMain.GameScreen.Cam.Position, displayPosition)/2.0f;
GameMain.GameScreen.Cam.Shake = CameraShake * Math.Max((displayRange - cameraDist)/displayRange, 0.0f);
if (attack.StructureDamage > 0.0f)
if (attack.GetStructureDamage(1.0f) > 0.0f)
{
List<Structure> structureList = new List<Structure>();
@@ -91,11 +91,13 @@ namespace Subsurface
for (int i = 0; i < structure.SectionCount; i++)
{
float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i), displayPosition) / displayRange);
if (distFactor > 0.0f) structure.AddDamage(i, attack.StructureDamage*distFactor);
if (distFactor > 0.0f) structure.AddDamage(i, attack.GetStructureDamage(1.0f)*distFactor);
}
}
}
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);
@@ -109,7 +111,7 @@ namespace Subsurface
distFactor = 1.0f - Vector2.Distance(limb.SimPosition, simPosition)/attack.Range;
c.AddDamage(limb.SimPosition, DamageType.None,
attack.Damage / c.AnimController.Limbs.Length * distFactor, 0.0f, attack.Stun * distFactor, true);
attack.GetDamage(1.0f) / c.AnimController.Limbs.Length * distFactor, 0.0f, attack.Stun * distFactor, true);
if (force>0.0f)
{
limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.SimPosition - simPosition) * distFactor * force);

View File

@@ -10,6 +10,8 @@ namespace Subsurface
{
class Gap : MapEntity
{
public static List<Gap> GapList = new List<Gap>();
public bool isHorizontal;
//private Sound waterSound;
@@ -53,21 +55,8 @@ namespace Subsurface
}
public Gap(Rectangle newRect)
: this(newRect, (newRect.Width < newRect.Height))
{
rect = newRect;
linkedTo = new ObservableCollection<MapEntity>();
//waterSound = new Sound("waterstream", 0.0f);
flowForce = Vector2.Zero;
isHorizontal = (rect.Width < rect.Height);
open = 1.0f;
FindHulls();
mapEntityList.Add(this);
}
public Gap(Rectangle newRect, bool isHorizontal)
@@ -83,15 +72,15 @@ namespace Subsurface
FindHulls();
GapList.Add(this);
mapEntityList.Add(this);
}
public static void UpdateHulls()
{
foreach (MapEntity entity in mapEntityList)
foreach (Gap g in Gap.GapList)
{
Gap g = entity as Gap;
if (g != null) g.FindHulls();
g.FindHulls();
}
}
@@ -273,17 +262,19 @@ namespace Subsurface
Vector2 pos = Position;
if (isHorizontal)
{
pos.Y = MathHelper.Clamp(lowerSurface, rect.Y - rect.Height, rect.Y);
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));
var particle = GameMain.ParticleManager.CreateParticle("watersplash",
new Vector2(pos.X, pos.Y - Rand.Range(0.0f, 10.0f)),
new Vector2(
MathHelper.Clamp(flowForce.X, -5000.0f, 5000.0f) * Rand.Range(0.5f, 0.7f),
flowForce.Y * Rand.Range(0.5f, 0.7f)));
new Vector2(pos.X, pos.Y - Rand.Range(0.0f, 10.0f)), velocity);
if (particle != null)
{
particle.Size = particle.Size * Math.Abs(flowForce.X / 1000.0f);
}
pos.Y = Rand.Range(lowerSurface, rect.Y - rect.Height);
@@ -296,8 +287,13 @@ namespace Subsurface
for (int i = 0; i < rect.Width; i += (int)Rand.Range(80, 100))
{
pos.X = Rand.Range(rect.X, rect.X + rect.Width);
Subsurface.Particles.Particle splash = GameMain.ParticleManager.CreateParticle("watersplash", pos,
new Vector2(0, Math.Max(flowForce.Y * Rand.Range(0.5f, 0.8f), 0.0f)));
Vector2 velocity = new Vector2(
flowForce.X * Rand.Range(0.5f, 0.7f),
Math.Max(flowForce.Y,-100.0f) * Rand.Range(0.5f, 0.7f));
var splash = GameMain.ParticleManager.CreateParticle("watersplash", pos,
velocity);
if (splash != null) splash.Size = splash.Size * MathHelper.Clamp(rect.Width / 50.0f, 0.8f, 4.0f);
@@ -327,7 +323,7 @@ namespace Subsurface
//horizontal gap (such as a regular door)
if (isHorizontal)
{
//higherSurface = Math.Min(hull1.Surface,hull2.Surface);
higherSurface = Math.Max(hull1.Surface,hull2.Surface);
float delta=0.0f;
//water level is above the lower boundary of the gap
if (Math.Max(hull1.Surface+hull1.WaveY[hull1.WaveY.Length - 1], hull2.Surface+hull2.WaveY[0]) > rect.Y - size)
@@ -453,6 +449,8 @@ namespace Subsurface
flowForce = new Vector2(0.0f,-delta);
flowForce.X = hull1.WaveY[hull1.GetWaveIndex(rect.X)] - hull1.WaveY[hull1.GetWaveIndex(rect.Right)] * 10.0f;
//if (water2.Volume < water2.FullVolume - Hull.MaxCompress)
//{
// int posX = (int)((rect.X + size / 2.0f - water1.Rect.X) / Hull.WaveWidth);
@@ -569,6 +567,8 @@ namespace Subsurface
{
base.Remove();
GapList.Remove(this);
if (soundIndex > -1) Sounds.SoundManager.Stop(soundIndex);
}

View File

@@ -48,6 +48,8 @@ namespace Subsurface
float[] leftDelta;
float[] rightDelta;
float lastSentVolume;
public override bool IsLinkable
{
get { return true; }
@@ -73,7 +75,8 @@ namespace Subsurface
{
get { return volume; }
set
{
{
if (!MathUtils.IsValid(value)) return;
volume = MathHelper.Clamp(value, 0.0f, FullVolume + MaxCompress);
if (volume < FullVolume) Pressure = rect.Y - rect.Height + volume / rect.Width;
if (volume > 0.0f) update = true;
@@ -155,8 +158,13 @@ namespace Subsurface
public int GetWaveIndex(Vector2 position)
{
int index = (int)(position.X - rect.X) / WaveWidth;
index = (int)MathHelper.Clamp(index, 0, waveY.Length-1);
return GetWaveIndex(position.X);
}
public int GetWaveIndex(float xPos)
{
int index = (int)(xPos - rect.X) / WaveWidth;
index = (int)MathHelper.Clamp(index, 0, waveY.Length - 1);
return index;
}
@@ -202,6 +210,12 @@ namespace Subsurface
}
}
//update client hulls if the amount of water has changed by >10%
if (Math.Abs(lastSentVolume-volume)>FullVolume*0.1f)
{
new Networking.NetworkEvent(ID, false);
lastSentVolume = volume;
}
if (!update) return;
@@ -254,9 +268,9 @@ namespace Subsurface
}
}
if (volume<FullVolume)
if (volume < FullVolume)
{
LethalPressure -= 0.5f;
LethalPressure -= 10.0f * deltaTime;
if (Volume == 0.0f)
{
for (int i = 1; i < waveY.Length - 1; i++)
@@ -268,7 +282,7 @@ namespace Subsurface
}
else
{
LethalPressure += 1.0f;
LethalPressure += 10.0f * deltaTime;
}
@@ -402,12 +416,17 @@ namespace Subsurface
//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)
{
if (guess != null && hullList.Contains(guess))
return FindHull(position, hullList, guess);
}
public static Hull FindHull(Vector2 position, List<Hull> hulls, Hull guess = null)
{
if (guess != null && hulls.Contains(guess))
{
if (Submarine.RectContains(guess.rect, position)) return guess;
}
foreach (Hull w in hullList)
foreach (Hull w in hulls)
{
if (Submarine.RectContains(w.rect, position)) return w;
}
@@ -445,6 +464,28 @@ namespace Subsurface
h.ID = int.Parse(element.Attribute("ID").Value);
}
public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message, object data)
{
message.Write(volume);
}
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
{
float newVolume = this.volume;
try
{
newVolume = message.ReadFloat();
}
catch
{
return;
}
Volume = newVolume;
}
}

View File

@@ -19,6 +19,6 @@ namespace Subsurface
get;
}
AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound=true);
AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, float deltaTime, bool playSound=true);
}
}

View File

@@ -417,7 +417,7 @@ int currentTargetIndex = 1;
}
if (allowedEdges.Count==0)
{
edgeIndex = 0;
edgeIndex = rand.Next() % currentCell.edges.Count;
}
else
{

View File

@@ -21,6 +21,10 @@ namespace Subsurface
public float damage;
public Gap gap;
public float lastSentDamage;
public float lastUpdate;
public bool isHighLighted;
public WallSection(Rectangle rect)
@@ -412,7 +416,7 @@ namespace Subsurface
sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f);
}
public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = false)
public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, float deltaTime, bool playSound = false)
{
if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f);
@@ -421,23 +425,29 @@ namespace Subsurface
GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f);
float damageAmount = attack.GetStructureDamage(deltaTime);
if (playSound && !SectionHasHole(i))
{
DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
AmbientSoundManager.PlayDamageSound(damageSoundType, attack.Damage, position);
AmbientSoundManager.PlayDamageSound(damageSoundType, damageAmount, position);
}
AddDamage(i, attack.Damage);
AddDamage(i, damageAmount);
return new AttackResult(attack.Damage, 0.0f);
return new AttackResult(damageAmount, 0.0f);
}
private void SetDamage(int sectionIndex, float damage)
{
if (!prefab.HasBody) return;
if (damage != sections[sectionIndex].damage)
if (damage != sections[sectionIndex].damage && Math.Abs(sections[sectionIndex].lastSentDamage - damage)>5.0f)
{
new NetworkEvent(NetworkEventType.UpdateEntity, ID, false, sectionIndex);
sections[sectionIndex].lastSentDamage = damage;
}
if (damage < prefab.MaxHealth*0.5f)
{
@@ -637,6 +647,7 @@ namespace Subsurface
return;
}
message.Write((float)NetTime.Now);
message.Write(byteIndex);
message.Write(sections[sectionIndex].damage);
}
@@ -645,9 +656,11 @@ namespace Subsurface
{
int sectionIndex = 0;
float damage = 0.0f;
float updateTime = 0.0f;
try
{
updateTime = message.ReadFloat();
sectionIndex = message.ReadByte();
damage = message.ReadFloat();
}
@@ -656,6 +669,9 @@ namespace Subsurface
return;
}
if (sections[sectionIndex].lastUpdate != 0.0f && updateTime < sections[sectionIndex].lastUpdate) return;
sections[sectionIndex].lastUpdate = updateTime;
SetDamage(sectionIndex, damage);
}