This commit is contained in:
Regalis11
2015-06-06 16:03:47 +03:00
28 changed files with 411 additions and 137 deletions
+15 -12
View File
@@ -380,27 +380,30 @@ namespace Subsurface
Body closestBody = Map.CheckVisibility(rayStart, rayEnd); Body closestBody = Map.CheckVisibility(rayStart, rayEnd);
Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure; Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure;
if (targetCharacter != null) //if (targetCharacter != null)
{ //{
//if target is a character that isn't visible, ignore // //if target is a character that isn't visible, ignore
if (closestStructure != null) continue; // if (closestStructure != null) continue;
//prefer targets with low health // //prefer targets with low health
valueModifier = valueModifier / targetCharacter.Health; // valueModifier = valueModifier / targetCharacter.Health;
} //}
else //else
{ //{
if (targetDamageable != null) if (targetDamageable != null)
{ {
valueModifier = valueModifier / targetDamageable.Health; valueModifier = valueModifier / targetDamageable.Health;
} }
else if (closestStructure!=null) else if (closestStructure!=null)
{ {
valueModifier = valueModifier / (closestStructure as IDamageable).Health; valueModifier = valueModifier / (closestStructure as IDamageable).Health;
} }
else
{
valueModifier = valueModifier / 1000.0f;
}
} //}
@@ -8,12 +8,26 @@ using System.Xml.Linq;
namespace Subsurface namespace Subsurface
{ {
public enum DamageType { None, Blunt, Slash }; public enum DamageType { None, Blunt, Slash };
struct AttackResult
{
public readonly float damage;
public readonly float bleeding;
public readonly bool hitArmor;
public AttackResult(float damage, float bleeding, bool hitArmor=false)
{
this.damage = damage;
this.bleeding = bleeding;
this.hitArmor = hitArmor;
}
}
class Attack class Attack
{ {
public enum Type public enum Type
{ {
None, PinchCW, PinchCCW None, PinchCW, PinchCCW
@@ -67,7 +81,7 @@ namespace Subsurface
priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f); priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f);
} }
public void DoDamage(IDamageable target, Vector2 position, float deltaTime, bool playSound=true) public AttackResult DoDamage(IDamageable target, Vector2 position, float deltaTime, bool playSound=true)
{ {
float damageAmount = 0.0f; float damageAmount = 0.0f;
//DamageSoundType damageSoundType = DamageSoundType.None; //DamageSoundType damageSoundType = DamageSoundType.None;
@@ -89,7 +103,14 @@ namespace Subsurface
if (duration > 0.0f) damageAmount *= deltaTime; if (duration > 0.0f) damageAmount *= deltaTime;
float bleedingAmount = (duration == 0.0f) ? bleedingDamage : bleedingDamage * deltaTime; float bleedingAmount = (duration == 0.0f) ? bleedingDamage : bleedingDamage * deltaTime;
if (damageAmount>0.0f) target.AddDamage(position, damageType, damageAmount, bleedingAmount, stun, playSound); if (damageAmount > 0.0f)
{
return target.AddDamage(position, damageType, damageAmount, bleedingAmount, stun, playSound);
}
else
{
return new AttackResult(0.0f, 0.0f);
}
} }
} }
} }
+2 -2
View File
@@ -654,7 +654,7 @@ namespace Subsurface
} }
} }
public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false) public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false)
{ {
animController.StunTimer = Math.Max(animController.StunTimer, stun); animController.StunTimer = Math.Max(animController.StunTimer, stun);
@@ -675,7 +675,7 @@ namespace Subsurface
closestLimb.body.ApplyForce(pull*Math.Min(amount*100.0f, 100.0f)); closestLimb.body.ApplyForce(pull*Math.Min(amount*100.0f, 100.0f));
closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound); return closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound);
} }
@@ -33,7 +33,7 @@ namespace Subsurface
{ {
case Physics.CollisionStairs: case Physics.CollisionStairs:
Structure structure = fixture.Body.UserData as Structure; Structure structure = fixture.Body.UserData as Structure;
if (stairs == null) if (stairs == null && (!inWater || TargetMovement.Y>0.0f))
{ {
if (LowestLimb.SimPosition.Y<structure.SimPosition.Y) if (LowestLimb.SimPosition.Y<structure.SimPosition.Y)
{ {
@@ -80,7 +80,7 @@ namespace Subsurface
if (onFloorTimer <= 0.0f) if (onFloorTimer <= 0.0f)
{ {
onGround = false; onGround = false;
if (GetLimb(LimbType.Torso).inWater) inWater = true;
//TODO: joku järkevämpi systeemi //TODO: joku järkevämpi systeemi
//if (!inWater && lastTimeOnFloor + 200 < gameTime.TotalGameTime.Milliseconds) //if (!inWater && lastTimeOnFloor + 200 < gameTime.TotalGameTime.Milliseconds)
// stunTimer = Math.Max(stunTimer, (float)gameTime.TotalGameTime.TotalMilliseconds + 100.0f); // stunTimer = Math.Max(stunTimer, (float)gameTime.TotalGameTime.TotalMilliseconds + 100.0f);
+12 -4
View File
@@ -257,11 +257,11 @@ namespace Subsurface
body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, pullPos); body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, pullPos);
} }
public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound) public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound)
{ {
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash; DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;
bool hitArmor = false;
if (armorSector != Vector2.Zero) if (armorSector != Vector2.Zero)
{ {
float rot = body.Rotation; float rot = body.Rotation;
@@ -273,7 +273,13 @@ namespace Subsurface
float angleDiff = ToolBox.GetShortestAngle(ToolBox.VectorToAngle(position - SimPosition), mid); float angleDiff = ToolBox.GetShortestAngle(ToolBox.VectorToAngle(position - SimPosition), mid);
if (Math.Abs(angleDiff) < (armorSector.Y-armorSector.X) / 2.0f) return; if (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f)
{
hitArmor = true;
damageSoundType = DamageSoundType.LimbArmor;
damage /= armorValue;
bleedingAmount /= armorValue;
}
} }
if (playSound) if (playSound)
@@ -284,7 +290,7 @@ namespace Subsurface
Bleeding += bleedingAmount; Bleeding += bleedingAmount;
Damage += amount; Damage += amount;
float bloodAmount = (int)Math.Min((int)(amount * 2.0f), 20); float bloodAmount = hitArmor ? 0 : (int)Math.Min((int)(amount * 2.0f), 20);
//if (closestLimb.Damage>=100.0f) //if (closestLimb.Damage>=100.0f)
//{ //{
// bloodAmount *= 2; // bloodAmount *= 2;
@@ -311,6 +317,8 @@ namespace Subsurface
{ {
Game1.particleManager.CreateParticle("waterblood", SimPosition, Vector2.Zero); Game1.particleManager.CreateParticle("waterblood", SimPosition, Vector2.Zero);
} }
return new AttackResult(amount, bleedingAmount, hitArmor);
} }
public void Update(float deltaTime) public void Update(float deltaTime)
+1 -1
View File
@@ -442,7 +442,7 @@ namespace Subsurface
inWater = false; inWater = false;
headInWater = false; headInWater = false;
if (ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition) if (ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition*0.95f)
inWater = true; inWater = true;
} }
@@ -10,17 +10,17 @@
flip="true"> flip="true">
<!-- head --> <!-- head -->
<limb id = "0" radius="22" height="45" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0"> <limb id = "0" radius="22" height="45" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="5.0f">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="0,0,51,121" depth="0.02" origin="0.45,0.63"/> <sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="0,0,51,121" depth="0.02" origin="0.45,0.63"/>
</limb> </limb>
<!-- middle part --> <!-- middle part -->
<limb id = "1" width="36" height="40" mass = "6" flip="true"> <limb id = "1" width="36" height="40" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="57,7,59,57" depth="0.021" origin="0.3,0.65"/> <sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="57,7,59,57" depth="0.021" origin="0.3,0.65"/>
</limb> </limb>
<!-- tail --> <!-- tail -->
<limb id = "2" width="41" height="63" mass = "6" type="Tail" flip="true"> <limb id = "2" width="41" height="63" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="6,141,60,95" depth="0.022" origin="0.37,0.43"/> <sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="6,141,60,95" depth="0.022" origin="0.37,0.43"/>
</limb> </limb>
@@ -70,7 +70,7 @@
<joint limb1="8" limb1anchor="0,-17" limb2="9" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190"/> <joint limb1="8" limb1anchor="0,-17" limb2="9" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190"/>
</ragdoll> </ragdoll>
<ai attackhumans="100" attackrooms="50.0" attackweaker="50" attackstronger="-30" <ai attackhumans="500" attackrooms="50.0" attackweaker="50" attackstronger="-30"
sight="0.5" hearing="1.0" sight="0.5" hearing="1.0"
attackcooldown="5.0"/> attackcooldown="5.0"/>
</character> </character>
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -20,5 +20,9 @@
<damagesound file="Content/Sounds/Damage/LimbSlash2.ogg" damagerange="10.0,80.0" damagesoundtype="LimbSlash"/> <damagesound file="Content/Sounds/Damage/LimbSlash2.ogg" damagerange="10.0,80.0" damagesoundtype="LimbSlash"/>
<damagesound file="Content/Sounds/Damage/LimbSlash3.ogg" damagerange="40.0,100.0" damagesoundtype="LimbSlash"/> <damagesound file="Content/Sounds/Damage/LimbSlash3.ogg" damagerange="40.0,100.0" damagesoundtype="LimbSlash"/>
<damagesound file="Content/Sounds/Damage/HitArmor1.ogg" damagerange="5.0,80.0" damagesoundtype="LimbArmor"/>
<damagesound file="Content/Sounds/Damage/HitArmor2.ogg" damagerange="5.0,80.0" damagesoundtype="LimbArmor"/>
<damagesound file="Content/Sounds/Damage/HitArmor3.ogg" damagerange="40.0,100.0" damagesoundtype="LimbArmor"/>
<damagesound file="Content/Sounds/Damage/implode.ogg" damagerange="0.0,100.0" damagesoundtype="Implode"/> <damagesound file="Content/Sounds/Damage/implode.ogg" damagerange="0.0,100.0" damagesoundtype="Implode"/>
</sounds> </sounds>
+2 -2
View File
@@ -209,11 +209,11 @@ namespace Subsurface
Game1.lobbyScreen.Select(); Game1.lobbyScreen.Select();
break; break;
case "savemap": case "savemap":
Map.Save("Content/SavedMaps/", commands[1]); Map.Loaded.SaveAs("Content/SavedMaps/" + commands[1]);
NewMessage("map saved", Color.Green); NewMessage("map saved", Color.Green);
break; break;
case "loadmap": case "loadmap":
Map.Load("Content/SavedMaps/", commands[1]); Map.Load("Content/SavedMaps/" + commands[1]);
break; break;
case "debugdraw": case "debugdraw":
Hull.DebugDraw = !Hull.DebugDraw; Hull.DebugDraw = !Hull.DebugDraw;
+2
View File
@@ -145,6 +145,7 @@ namespace Subsurface
AmbientSoundManager.Init("Content/Sounds/Sounds.xml"); AmbientSoundManager.Init("Content/Sounds/Sounds.xml");
Map.PreloadMaps("Content/SavedMaps");
gameScreen = new GameScreen(graphics.GraphicsDevice); gameScreen = new GameScreen(graphics.GraphicsDevice);
mainMenuScreen = new MainMenuScreen(this); mainMenuScreen = new MainMenuScreen(this);
lobbyScreen = new LobbyScreen(); lobbyScreen = new LobbyScreen();
@@ -152,6 +153,7 @@ namespace Subsurface
editMapScreen = new EditMapScreen(); editMapScreen = new EditMapScreen();
editCharacterScreen = new EditCharacterScreen(); editCharacterScreen = new EditCharacterScreen();
mainMenuScreen.Select(); mainMenuScreen.Select();
} }
+1 -1
View File
@@ -116,7 +116,7 @@ namespace Subsurface
{ {
if (saveFile == null) return false; if (saveFile == null) return false;
Map.Save(Path.GetDirectoryName(saveFile) + "/", Path.GetFileName(saveFile)); Map.Loaded.SaveAs(Path.GetDirectoryName(saveFile) + "/"+ Path.GetFileName(saveFile));
crewManager.EndShift(); crewManager.EndShift();
+2
View File
@@ -242,6 +242,8 @@ namespace Subsurface.Items.Components
public override void OnMapLoaded() public override void OnMapLoaded()
{ {
if (itemIds == null) return;
for (int i = 0; i < itemIds.Length; i++) for (int i = 0; i < itemIds.Length; i++)
{ {
Item item = MapEntity.FindEntityByID(itemIds[i]) as Item; Item item = MapEntity.FindEntityByID(itemIds[i]) as Item;
+8 -23
View File
@@ -157,37 +157,18 @@ namespace Subsurface.Items.Components
//float damage = f1.Body.LinearVelocity.Length(); //float damage = f1.Body.LinearVelocity.Length();
AttackResult attackResult = new AttackResult(0.0f, 0.0f);
if (attack!=null) if (attack!=null)
{ {
Limb limb; Limb limb;
Structure structure; Structure structure;
if ((limb = (f2.Body.UserData as Limb)) != null) if ((limb = (f2.Body.UserData as Limb)) != null)
{ {
attack.DoDamage(limb.character, item.SimPosition, 0.0f); attackResult = attack.DoDamage(limb.character, item.SimPosition, 1.0f);
//limb.Damage += damage;
//limb.Bleeding += bleedingDamage;
//if (bleedingDamage>0.0f)
//{
// for (int i = 0; i < 5; i++ )
// {
// Game1.particleManager.CreateParticle(limb.SimPosition,
// ToolBox.VectorToAngle(-f1.Body.LinearVelocity*0.5f) + ToolBox.RandomFloat(-0.5f, 0.5f),
// ToolBox.RandomFloat(1.0f, 3.0f), "blood");
// }
// Game1.particleManager.CreateParticle(limb.SimPosition,
// 0.0f,
// Vector2.Zero, "waterblood");
//}
//AmbientSoundManager.PlayDamageSound(DamageType.LimbBlunt, damage, limb.body.FarseerBody);
} }
else if ((structure = (f2.Body.UserData as Structure)) != null) else if ((structure = (f2.Body.UserData as Structure)) != null)
{ {
attack.DoDamage(structure, item.SimPosition, 0.0f); attackResult = attack.DoDamage(structure, item.SimPosition, 1.0f);
//AmbientSoundManager.PlayDamageSound(DamageType.StructureBlunt, damage, f2.Body);
} }
} }
@@ -200,7 +181,11 @@ namespace Subsurface.Items.Components
ignoredBodies.Clear(); ignoredBodies.Clear();
if (doesStick) if (attackResult.hitArmor)
{
item.body.LinearVelocity *= 0.5f;
}
else if (doesStick)
{ {
Vector2 normal = contact.Manifold.LocalNormal; Vector2 normal = contact.Manifold.LocalNormal;
Vector2 dir = new Vector2( Vector2 dir = new Vector2(
@@ -398,6 +398,13 @@ namespace Subsurface.Items.Components
{ {
XElement newElement = new XElement(isOutput ? "output" : "input", new XAttribute("name", name)); XElement newElement = new XElement(isOutput ? "output" : "input", new XAttribute("name", name));
Array.Sort(wires, delegate(Wire wire1, Wire wire2)
{
if (wire1 == null) return 1;
if (wire2 == null) return -1;
return wire1.Item.ID.CompareTo(wire2.Item.ID);
});
for (int i = 0; i < MaxLinked; i++ ) for (int i = 0; i < MaxLinked; i++ )
{ {
if (wires[i] == null) continue; if (wires[i] == null) continue;
@@ -406,7 +413,7 @@ namespace Subsurface.Items.Components
//int connectionIndex = recipient.item.Connections.FindIndex(x => x == recipient); //int connectionIndex = recipient.item.Connections.FindIndex(x => x == recipient);
newElement.Add(new XElement("link", newElement.Add(new XElement("link",
new XAttribute("w", (wires[i] == null) ? "-1" : wires[i].Item.ID.ToString()))); new XAttribute("w", wires[i].Item.ID.ToString())));
} }
parentElement.Add(newElement); parentElement.Add(newElement);
+3 -1
View File
@@ -370,9 +370,11 @@ namespace Subsurface
} }
public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = true) public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = true)
{ {
Condition -= amount; Condition -= amount;
return new AttackResult(amount, 0.0f, false);
} }
+1 -1
View File
@@ -14,6 +14,6 @@ namespace Subsurface
get; get;
} }
void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true); AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true);
} }
} }
+150 -43
View File
@@ -17,18 +17,36 @@ namespace Subsurface
None = 0, Left = 1, Right = 2 None = 0, Left = 1, Right = 2
} }
static class Map class Map
{ {
static string MapFolder = "Content/SavedMaps"; static string MapFolder;
MapHash mapHash;
public static Vector2 gridSize = new Vector2(16.0f, 16.0f); public static List<Map> SavedMaps = new List<Map>();
private static Map loaded;
//public static Map Loaded
//{
// get { return loaded; }
// set { loaded = value; }
//}
public static readonly Vector2 gridSize = new Vector2(16.0f, 16.0f);
private static Vector2 lastPickedPosition; private static Vector2 lastPickedPosition;
private static float lastPickedFraction; private static float lastPickedFraction;
private static Rectangle borders; private Rectangle borders;
private static string filePath; private string filePath;
private string name;
public string Name
{
get { return name; }
}
public static Vector2 LastPickedPosition public static Vector2 LastPickedPosition
{ {
@@ -40,12 +58,31 @@ namespace Subsurface
get { return lastPickedFraction; } get { return lastPickedFraction; }
} }
public static Rectangle Borders public MapHash MapHash
{ {
get { return borders; } get
{
XDocument doc = OpenDoc(filePath);
mapHash = new MapHash(doc);
return mapHash;
}
} }
public static string FilePath public static Map Loaded
{
get { return loaded; }
}
public static Rectangle Borders
{
get
{
return (loaded==null) ? Rectangle.Empty : loaded.borders;
}
}
public string FilePath
{ {
get { return filePath; } get { return filePath; }
} }
@@ -223,38 +260,51 @@ namespace Subsurface
return true; return true;
} }
public static void Save(string filePath, string fileName)
public void Save()
{ {
if (fileName==null) SaveAs(filePath);
{ }
DebugConsole.ThrowError("No save file selected");
return; public void SaveAs(string filePath)
} {
//if (filePath=="")
//{
// DebugConsole.ThrowError("No save file selected");
// return;
//}
XDocument doc = new XDocument( XDocument doc = new XDocument(
new XElement((XName)fileName)); new XElement((XName)name));
foreach (MapEntity e in MapEntity.mapEntityList) foreach (MapEntity e in MapEntity.mapEntityList)
{ {
e.Save(doc); e.Save(doc);
} }
mapHash = new MapHash(doc);
doc.Root.Add(new XAttribute("md5hash", mapHash.MD5Hash));
try try
{ {
string docString = doc.ToString(); string docString = doc.ToString();
ToolBox.CompressStringToFile(filePath+fileName+".gz", doc.ToString()); ToolBox.CompressStringToFile(filePath+".gz", doc.ToString());
} }
catch catch
{ {
DebugConsole.ThrowError("Saving map ''" + filePath + fileName + "'' failed!"); DebugConsole.ThrowError("Saving map ''" + filePath + "'' failed!");
} }
//doc.Save(filePath + fileName); doc.Save(filePath);
} }
public static string[] GetMapFilePaths() public static void PreloadMaps(string mapFolder)
{ {
string[] mapFilePaths; MapFolder = mapFolder;
//string[] mapFilePaths;
Unload();
SavedMaps.Clear();
if (!Directory.Exists(MapFolder)) if (!Directory.Exists(MapFolder))
{ {
@@ -266,10 +316,12 @@ namespace Subsurface
{ {
DebugConsole.ThrowError("Directory ''Content/SavedMaps'' not found and creating the directory failed."); DebugConsole.ThrowError("Directory ''Content/SavedMaps'' not found and creating the directory failed.");
return null; return;
} }
} }
string[] mapFilePaths;
try try
{ {
mapFilePaths = Directory.GetFiles(MapFolder); mapFilePaths = Directory.GetFiles(MapFolder);
@@ -277,21 +329,42 @@ namespace Subsurface
catch (Exception e) catch (Exception e)
{ {
DebugConsole.ThrowError("Couldn't open directory ''Content/SavedMaps''!", e); DebugConsole.ThrowError("Couldn't open directory ''Content/SavedMaps''!", e);
return null; return;
} }
return mapFilePaths; foreach (string mapPath in mapFilePaths)
{
//Map savedMap = new Map(mapPath);
SavedMaps.Add(new Map(mapPath));
}
} }
public static void Load(string filePath, string fileName) public Map(string filePath, string mapHash="")
{ {
Load(filePath + fileName); this.filePath = filePath;
this.name = Path.GetFileNameWithoutExtension(filePath);
if (mapHash != "")
{
this.mapHash = new MapHash(mapHash);
}
else
{
//XDocument doc = OpenDoc(filePath);
//string md5Hash = ToolBox.GetAttributeString(doc.Root, "md5hash", "");
//if (md5Hash == "" || md5Hash.Length < 16)
//{
// DebugConsole.ThrowError("Couldn't find a valid MD5 hash in the map file");
//}
//this.mapHash = new MapHash(md5Hash);
}
} }
public static void Load(string file) private XDocument OpenDoc(string file)
{ {
Clear();
filePath = file;
XDocument doc = null; XDocument doc = null;
string extension = ""; string extension = "";
@@ -302,16 +375,16 @@ namespace Subsurface
catch catch
{ {
DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)"); DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)");
return; return null;
} }
if (extension==".gz") if (extension == ".gz")
{ {
Stream stream = ToolBox.DecompressFiletoStream(file); Stream stream = ToolBox.DecompressFiletoStream(file);
if (stream == null) if (stream == null)
{ {
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!"); DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return; return null;
} }
try try
@@ -325,19 +398,37 @@ namespace Subsurface
catch catch
{ {
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!"); DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return; return null;
} }
} }
else if (extension ==".xml") else if (extension == ".xml")
{ {
doc = XDocument.Load(file); try
{
doc = XDocument.Load(file);
}
catch
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return null;
}
} }
else else
{ {
DebugConsole.ThrowError("Couldn't load map ''"+file+"! (Unrecognized file extension)"); DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)");
return; return null;
} }
return doc;
}
public void Load()
{
//string file = filePath;
XDocument doc = OpenDoc(filePath);
if (doc == null) return;
foreach (XElement element in doc.Root.Elements()) foreach (XElement element in doc.Root.Elements())
{ {
@@ -350,13 +441,13 @@ namespace Subsurface
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true); t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
if (t == null) if (t == null)
{ {
DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''."); DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.");
continue; continue;
} }
} }
catch (Exception e) catch (Exception e)
{ {
DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''.", e); DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.", e);
continue; continue;
} }
@@ -390,13 +481,29 @@ namespace Subsurface
ic.OnMapLoaded(); ic.OnMapLoaded();
} }
} }
loaded = this;
} }
public static void Load(string file)
public static void Clear()
{ {
Map.filePath = ""; Unload();
Map map = new Map(file);
map.Load();
}
public static void Unload()
{
if (loaded==null)return;
loaded.Clear();
loaded = null;
}
private void Clear()
{
filePath = "";
if (Game1.gameScreen.Cam != null) Game1.gameScreen.Cam.TargetPos = Vector2.Zero; if (Game1.gameScreen.Cam != null) Game1.gameScreen.Cam.TargetPos = Vector2.Zero;
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace Subsurface
{
class MapHash
{
private string md5Hash;
private string shortHash;
public string MD5Hash
{
get
{
return md5Hash;
}
}
public string ShortHash
{
get
{
return shortHash;
}
}
public MapHash(string md5Hash)
{
this.md5Hash = md5Hash;
shortHash = GetShortHash(md5Hash);
}
public MapHash(XDocument doc)
{
string docString = Regex.Replace(doc.ToString(), @"\s+", "");
// step 1, calculate MD5 hash from input
MD5 md5 = MD5.Create();
byte[] inputBytes = Encoding.ASCII.GetBytes(docString);
byte[] hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
md5Hash = sb.ToString();
shortHash = GetShortHash(md5Hash);
}
private string GetShortHash(string fullHash)
{
return fullHash;
}
}
}
+5 -3
View File
@@ -378,12 +378,12 @@ namespace Subsurface
sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f); sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f);
} }
public void AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false) public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false)
{ {
if (!prefab.HasBody || prefab.IsPlatform) return; if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f);
int i = FindSectionIndex(ConvertUnits.ToDisplayUnits(position)); int i = FindSectionIndex(ConvertUnits.ToDisplayUnits(position));
if (i == -1) return; if (i == -1) return new AttackResult(0.0f, 0.0f);
Game1.particleManager.CreateParticle("dustcloud", ConvertUnits.ToSimUnits(SectionPosition(i)), 0.0f, 0.0f); Game1.particleManager.CreateParticle("dustcloud", ConvertUnits.ToSimUnits(SectionPosition(i)), 0.0f, 0.0f);
@@ -394,6 +394,8 @@ namespace Subsurface
} }
AddDamage(i, amount); AddDamage(i, amount);
return new AttackResult(amount, 0.0f);
} }
private void SetDamage(int sectionIndex, float damage) private void SetDamage(int sectionIndex, float damage)
+10 -3
View File
@@ -225,8 +225,15 @@ namespace Subsurface.Networking
int seed = inc.ReadInt32(); int seed = inc.ReadInt32();
Game1.random = new Random(seed); Game1.random = new Random(seed);
string mapFile = inc.ReadString(); string mapName = inc.ReadString();
Map.Load(mapFile); string mapHash = inc.ReadString();
Game1.netLobbyScreen.TrySelectMap(mapName, mapHash);
//Map.Load(mapFile);
double durationMinutes = inc.ReadDouble(); double durationMinutes = inc.ReadDouble();
@@ -316,7 +323,7 @@ namespace Subsurface.Networking
public void EndGame(string endMessage) public void EndGame(string endMessage)
{ {
Map.Clear(); Map.Unload();
Game1.netLobbyScreen.Select(); Game1.netLobbyScreen.Select();
+7 -3
View File
@@ -271,7 +271,9 @@ namespace Subsurface.Networking
int seed = DateTime.Now.Millisecond; int seed = DateTime.Now.Millisecond;
Game1.random = new Random(seed); Game1.random = new Random(seed);
Map.Load(Game1.netLobbyScreen.SelectedMap); Map selectedMap = Game1.netLobbyScreen.SelectedMap as Map;
selectedMap.Load();
Game1.gameSession = new GameSession("", false, Game1.netLobbyScreen.GameDuration, Game1.netLobbyScreen.SelectedMode); Game1.gameSession = new GameSession("", false, Game1.netLobbyScreen.GameDuration, Game1.netLobbyScreen.SelectedMode);
Game1.gameSession.StartShift(1); Game1.gameSession.StartShift(1);
@@ -305,7 +307,9 @@ namespace Subsurface.Networking
msg.Write(seed); msg.Write(seed);
msg.Write(Game1.netLobbyScreen.SelectedMap); msg.Write(Game1.netLobbyScreen.SelectedMap.Name);
msg.Write(Game1.netLobbyScreen.SelectedMap.MapHash.MD5Hash);
msg.Write(Game1.netLobbyScreen.GameDuration.TotalMinutes); msg.Write(Game1.netLobbyScreen.GameDuration.TotalMinutes);
WriteCharacterData(msg, client.name, client.character); WriteCharacterData(msg, client.name, client.character);
@@ -336,7 +340,7 @@ namespace Subsurface.Networking
public void EndGame(string endMessage) public void EndGame(string endMessage)
{ {
Map.Clear(); Map.Unload();
gameStarted = false; gameStarted = false;
+2 -2
View File
@@ -96,7 +96,7 @@ namespace Subsurface
{ {
base.Select(); base.Select();
Map.Clear(); Map.Unload();
UpdateCharacterLists(); UpdateCharacterLists();
@@ -213,7 +213,7 @@ namespace Subsurface
private bool StartShift(GUIButton button, object selection) private bool StartShift(GUIButton button, object selection)
{ {
Map.Load("", Game1.gameSession.SaveFile); Map.Load(Game1.gameSession.SaveFile);
Game1.gameSession.StartShift(); Game1.gameSession.StartShift();
+13 -10
View File
@@ -56,23 +56,23 @@ namespace Subsurface
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, menuTabs[(int)Tabs.NewGame]); new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, menuTabs[(int)Tabs.NewGame]);
mapList = new GUIListBox(new Rectangle(0, 60, 200, 400), Color.White, menuTabs[1]); mapList = new GUIListBox(new Rectangle(0, 60, 200, 400), Color.White, menuTabs[1]);
string[] mapFilePaths = Map.GetMapFilePaths(); //string[] mapFilePaths = Map.GetMapFilePaths();
if (mapFilePaths!=null) //if (mapFilePaths!=null)
{ //{
foreach (string s in mapFilePaths) foreach (Map map in Map.SavedMaps)
{ {
GUITextBlock textBlock = new GUITextBlock( GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25), new Rectangle(0, 0, 0, 25),
Path.GetFileNameWithoutExtension(s), map.Name,
GUI.style, GUI.style,
Alignment.Left, Alignment.Left,
Alignment.Left, Alignment.Left,
mapList); mapList);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = s; textBlock.UserData = map;
} }
if (mapFilePaths.Length > 0) mapList.Select(mapFilePaths[0]); if (Map.SavedMaps.Count > 0) mapList.Select(Map.SavedMaps[0]);
} //}
button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", GUI.style, Alignment.Right | Alignment.Bottom, menuTabs[(int)Tabs.NewGame]); button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", GUI.style, Alignment.Right | Alignment.Bottom, menuTabs[(int)Tabs.NewGame]);
button.OnClicked = StartGame; button.OnClicked = StartGame;
@@ -146,9 +146,12 @@ namespace Subsurface
private bool StartGame(GUIButton button, object obj) private bool StartGame(GUIButton button, object obj)
{ {
if (mapList.SelectedData == null) return false;
Game1.gameSession = new GameSession(mapList.SelectedData.ToString(), true, TimeSpan.Zero); Map selectedMap = mapList.SelectedData as Map;
if (selectedMap == null) return false;
Game1.gameSession = new GameSession(selectedMap.FilePath, true, TimeSpan.Zero);
Game1.lobbyScreen.Select(); Game1.lobbyScreen.Select();
+61 -13
View File
@@ -31,9 +31,9 @@ namespace Subsurface
public bool isServer; public bool isServer;
public string SelectedMap public Map SelectedMap
{ {
get { return mapList.SelectedData.ToString(); } get { return mapList.SelectedData as Map; }
} }
@@ -136,20 +136,19 @@ namespace Subsurface
mapList.OnSelected = SelectMap; mapList.OnSelected = SelectMap;
mapList.Enabled = (Game1.server!=null); mapList.Enabled = (Game1.server!=null);
string[] mapFilePaths = Map.GetMapFilePaths(); if (Map.SavedMaps.Count>0)
if (mapFilePaths != null)
{ {
foreach (string s in mapFilePaths) foreach (Map map in Map.SavedMaps)
{ {
GUITextBlock textBlock = new GUITextBlock( GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25), new Rectangle(0, 0, 0, 25),
Path.GetFileNameWithoutExtension(s), map.Name,
GUI.style, GUI.style,
Alignment.Left, Alignment.Left,
Alignment.Left, Alignment.Left,
mapList); mapList);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = s; textBlock.UserData = map;
} }
} }
else else
@@ -194,7 +193,7 @@ namespace Subsurface
modeList.OnSelected = Game1.server.UpdateNetLobby; modeList.OnSelected = Game1.server.UpdateNetLobby;
durationBar.OnMoved = Game1.server.UpdateNetLobby; durationBar.OnMoved = Game1.server.UpdateNetLobby;
if (mapFilePaths.Length > 0) mapList.Select(mapFilePaths[oldMapIndex]); if (mapList.CountChildren > 0) mapList.Select(Map.SavedMaps[0]);
if (GameMode.list.Count > 0) modeList.Select(GameMode.list[0]); if (GameMode.list.Count > 0) modeList.Select(GameMode.list[0]);
} }
else else
@@ -245,8 +244,12 @@ namespace Subsurface
{ {
if (Game1.server != null) Game1.server.UpdateNetLobby(obj); if (Game1.server != null) Game1.server.UpdateNetLobby(obj);
if ((string)obj == Map.FilePath) return true; Map map = (Map)obj;
Map.Load((string)obj);
//map already loaded
if (Map.Loaded!=null && map.FilePath == Map.Loaded.FilePath) return true;
map.Load();
return true; return true;
} }
@@ -462,15 +465,60 @@ namespace Subsurface
public void WriteData(NetOutgoingMessage msg) public void WriteData(NetOutgoingMessage msg)
{ {
msg.Write(mapList.SelectedIndex); Map selectedMap = mapList.SelectedData as Map;
msg.Write(modeList.SelectedIndex);
if (selectedMap==null)
{
msg.Write(" ");
msg.Write(" ");
}
else
{
msg.Write(selectedMap.Name);
msg.Write(selectedMap.MapHash.MD5Hash);
}
msg.Write(modeList.SelectedIndex);
msg.Write(durationBar.BarScroll); msg.Write(durationBar.BarScroll);
} }
public bool TrySelectMap(string mapName, string md5Hash)
{
Map map = Map.SavedMaps.Find(m => m.Name == mapName);
if (map==null)
{
DebugConsole.ThrowError("The map ''" + mapName + "'' has been selected by the server.");
DebugConsole.ThrowError("Matching map not found in your map folder.");
return false;
}
else
{
if (map.MapHash.MD5Hash!=md5Hash)
{
DebugConsole.ThrowError("Your version of the map file ''"+map.Name+"'' doesn't match the server's version!");
DebugConsole.ThrowError("Your file: "+map.Name+"(MD5 hash : "+map.MapHash.MD5Hash+")");
DebugConsole.ThrowError("Server's file: " + mapName + "(MD5 hash : " + md5Hash + ")");
return false;
}
else
{
mapList.Select(map);
map.Load();
return true;
}
}
}
public void ReadData(NetIncomingMessage msg) public void ReadData(NetIncomingMessage msg)
{ {
mapList.Select(msg.ReadInt32()); string mapName = msg.ReadString();
string md5Hash = msg.ReadString();
TrySelectMap(mapName, md5Hash);
//mapList.Select(msg.ReadInt32());
modeList.Select(msg.ReadInt32()); modeList.Select(msg.ReadInt32());
durationBar.BarScroll = msg.ReadFloat(); durationBar.BarScroll = msg.ReadFloat();
+5 -1
View File
@@ -9,7 +9,11 @@ using Subsurface.Sounds;
namespace Subsurface namespace Subsurface
{ {
public enum DamageSoundType { None, StructureBlunt, StructureSlash, LimbBlunt, LimbSlash, Implode } public enum DamageSoundType {
None,
StructureBlunt, StructureSlash,
LimbBlunt, LimbSlash, LimbArmor,
Implode }
public struct DamageSound public struct DamageSound
{ {