Merge branch 'master' of https://bitbucket.org/Regalis11/repo
This commit is contained in:
@@ -380,27 +380,30 @@ namespace Subsurface
|
||||
Body closestBody = Map.CheckVisibility(rayStart, rayEnd);
|
||||
Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure;
|
||||
|
||||
if (targetCharacter != null)
|
||||
{
|
||||
//if target is a character that isn't visible, ignore
|
||||
if (closestStructure != null) continue;
|
||||
//if (targetCharacter != null)
|
||||
//{
|
||||
// //if target is a character that isn't visible, ignore
|
||||
// if (closestStructure != null) continue;
|
||||
|
||||
//prefer targets with low health
|
||||
valueModifier = valueModifier / targetCharacter.Health;
|
||||
}
|
||||
else
|
||||
{
|
||||
// //prefer targets with low health
|
||||
// valueModifier = valueModifier / targetCharacter.Health;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
if (targetDamageable != null)
|
||||
{
|
||||
valueModifier = valueModifier / targetDamageable.Health;
|
||||
|
||||
valueModifier = valueModifier / targetDamageable.Health;
|
||||
}
|
||||
else if (closestStructure!=null)
|
||||
{
|
||||
valueModifier = valueModifier / (closestStructure as IDamageable).Health;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueModifier = valueModifier / 1000.0f;
|
||||
}
|
||||
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,12 +8,26 @@ using System.Xml.Linq;
|
||||
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
|
||||
{
|
||||
|
||||
|
||||
public enum Type
|
||||
{
|
||||
None, PinchCW, PinchCCW
|
||||
@@ -67,7 +81,7 @@ namespace Subsurface
|
||||
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;
|
||||
//DamageSoundType damageSoundType = DamageSoundType.None;
|
||||
@@ -89,7 +103,14 @@ namespace Subsurface
|
||||
if (duration > 0.0f) damageAmount *= 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -675,7 +675,7 @@ namespace Subsurface
|
||||
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:
|
||||
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)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ namespace Subsurface
|
||||
if (onFloorTimer <= 0.0f)
|
||||
{
|
||||
onGround = false;
|
||||
|
||||
if (GetLimb(LimbType.Torso).inWater) inWater = true;
|
||||
//TODO: joku järkevämpi systeemi
|
||||
//if (!inWater && lastTimeOnFloor + 200 < gameTime.TotalGameTime.Milliseconds)
|
||||
// stunTimer = Math.Max(stunTimer, (float)gameTime.TotalGameTime.TotalMilliseconds + 100.0f);
|
||||
|
||||
@@ -257,11 +257,11 @@ namespace Subsurface
|
||||
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;
|
||||
|
||||
|
||||
bool hitArmor = false;
|
||||
if (armorSector != Vector2.Zero)
|
||||
{
|
||||
float rot = body.Rotation;
|
||||
@@ -273,7 +273,13 @@ namespace Subsurface
|
||||
|
||||
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)
|
||||
@@ -284,7 +290,7 @@ namespace Subsurface
|
||||
Bleeding += bleedingAmount;
|
||||
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)
|
||||
//{
|
||||
// bloodAmount *= 2;
|
||||
@@ -311,6 +317,8 @@ namespace Subsurface
|
||||
{
|
||||
Game1.particleManager.CreateParticle("waterblood", SimPosition, Vector2.Zero);
|
||||
}
|
||||
|
||||
return new AttackResult(amount, bleedingAmount, hitArmor);
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
|
||||
@@ -442,7 +442,7 @@ namespace Subsurface
|
||||
inWater = false;
|
||||
headInWater = false;
|
||||
|
||||
if (ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition)
|
||||
if (ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition*0.95f)
|
||||
inWater = true;
|
||||
|
||||
}
|
||||
|
||||
@@ -10,17 +10,17 @@
|
||||
flip="true">
|
||||
|
||||
<!-- 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"/>
|
||||
</limb>
|
||||
|
||||
<!-- 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"/>
|
||||
</limb>
|
||||
|
||||
<!-- 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"/>
|
||||
</limb>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<joint limb1="8" limb1anchor="0,-17" limb2="9" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190"/>
|
||||
</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"
|
||||
attackcooldown="5.0"/>
|
||||
</character>
|
||||
|
||||
BIN
Subsurface/Content/Sounds/Damage/HitArmor1.ogg
Normal file
BIN
Subsurface/Content/Sounds/Damage/HitArmor1.ogg
Normal file
Binary file not shown.
BIN
Subsurface/Content/Sounds/Damage/HitArmor2.ogg
Normal file
BIN
Subsurface/Content/Sounds/Damage/HitArmor2.ogg
Normal file
Binary file not shown.
BIN
Subsurface/Content/Sounds/Damage/HitArmor3.ogg
Normal file
BIN
Subsurface/Content/Sounds/Damage/HitArmor3.ogg
Normal file
Binary file not shown.
@@ -20,5 +20,9 @@
|
||||
<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/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"/>
|
||||
</sounds>
|
||||
@@ -209,11 +209,11 @@ namespace Subsurface
|
||||
Game1.lobbyScreen.Select();
|
||||
break;
|
||||
case "savemap":
|
||||
Map.Save("Content/SavedMaps/", commands[1]);
|
||||
Map.Loaded.SaveAs("Content/SavedMaps/" + commands[1]);
|
||||
NewMessage("map saved", Color.Green);
|
||||
break;
|
||||
case "loadmap":
|
||||
Map.Load("Content/SavedMaps/", commands[1]);
|
||||
Map.Load("Content/SavedMaps/" + commands[1]);
|
||||
break;
|
||||
case "debugdraw":
|
||||
Hull.DebugDraw = !Hull.DebugDraw;
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace Subsurface
|
||||
|
||||
AmbientSoundManager.Init("Content/Sounds/Sounds.xml");
|
||||
|
||||
Map.PreloadMaps("Content/SavedMaps");
|
||||
gameScreen = new GameScreen(graphics.GraphicsDevice);
|
||||
mainMenuScreen = new MainMenuScreen(this);
|
||||
lobbyScreen = new LobbyScreen();
|
||||
@@ -152,6 +153,7 @@ namespace Subsurface
|
||||
editMapScreen = new EditMapScreen();
|
||||
editCharacterScreen = new EditCharacterScreen();
|
||||
|
||||
|
||||
mainMenuScreen.Select();
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Subsurface
|
||||
{
|
||||
if (saveFile == null) return false;
|
||||
|
||||
Map.Save(Path.GetDirectoryName(saveFile) + "/", Path.GetFileName(saveFile));
|
||||
Map.Loaded.SaveAs(Path.GetDirectoryName(saveFile) + "/"+ Path.GetFileName(saveFile));
|
||||
|
||||
crewManager.EndShift();
|
||||
|
||||
|
||||
@@ -242,6 +242,8 @@ namespace Subsurface.Items.Components
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
if (itemIds == null) return;
|
||||
|
||||
for (int i = 0; i < itemIds.Length; i++)
|
||||
{
|
||||
Item item = MapEntity.FindEntityByID(itemIds[i]) as Item;
|
||||
|
||||
@@ -157,37 +157,18 @@ namespace Subsurface.Items.Components
|
||||
|
||||
//float damage = f1.Body.LinearVelocity.Length();
|
||||
|
||||
AttackResult attackResult = new AttackResult(0.0f, 0.0f);
|
||||
if (attack!=null)
|
||||
{
|
||||
Limb limb;
|
||||
Structure structure;
|
||||
if ((limb = (f2.Body.UserData as Limb)) != null)
|
||||
{
|
||||
attack.DoDamage(limb.character, item.SimPosition, 0.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);
|
||||
attackResult = attack.DoDamage(limb.character, item.SimPosition, 1.0f);
|
||||
}
|
||||
else if ((structure = (f2.Body.UserData as Structure)) != null)
|
||||
{
|
||||
attack.DoDamage(structure, item.SimPosition, 0.0f);
|
||||
|
||||
//AmbientSoundManager.PlayDamageSound(DamageType.StructureBlunt, damage, f2.Body);
|
||||
attackResult = attack.DoDamage(structure, item.SimPosition, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +181,11 @@ namespace Subsurface.Items.Components
|
||||
|
||||
ignoredBodies.Clear();
|
||||
|
||||
if (doesStick)
|
||||
if (attackResult.hitArmor)
|
||||
{
|
||||
item.body.LinearVelocity *= 0.5f;
|
||||
}
|
||||
else if (doesStick)
|
||||
{
|
||||
Vector2 normal = contact.Manifold.LocalNormal;
|
||||
Vector2 dir = new Vector2(
|
||||
|
||||
@@ -398,6 +398,13 @@ namespace Subsurface.Items.Components
|
||||
{
|
||||
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++ )
|
||||
{
|
||||
if (wires[i] == null) continue;
|
||||
@@ -406,7 +413,7 @@ namespace Subsurface.Items.Components
|
||||
|
||||
//int connectionIndex = recipient.item.Connections.FindIndex(x => x == recipient);
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
return new AttackResult(amount, 0.0f, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,6 @@ namespace Subsurface
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,36 @@ namespace Subsurface
|
||||
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 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
|
||||
{
|
||||
@@ -40,12 +58,31 @@ namespace Subsurface
|
||||
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; }
|
||||
}
|
||||
@@ -223,38 +260,51 @@ namespace Subsurface
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Save(string filePath, string fileName)
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (fileName==null)
|
||||
{
|
||||
DebugConsole.ThrowError("No save file selected");
|
||||
return;
|
||||
}
|
||||
SaveAs(filePath);
|
||||
}
|
||||
|
||||
public void SaveAs(string filePath)
|
||||
{
|
||||
//if (filePath=="")
|
||||
//{
|
||||
// DebugConsole.ThrowError("No save file selected");
|
||||
// return;
|
||||
//}
|
||||
XDocument doc = new XDocument(
|
||||
new XElement((XName)fileName));
|
||||
new XElement((XName)name));
|
||||
|
||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||
{
|
||||
e.Save(doc);
|
||||
}
|
||||
|
||||
mapHash = new MapHash(doc);
|
||||
doc.Root.Add(new XAttribute("md5hash", mapHash.MD5Hash));
|
||||
|
||||
try
|
||||
{
|
||||
string docString = doc.ToString();
|
||||
ToolBox.CompressStringToFile(filePath+fileName+".gz", doc.ToString());
|
||||
ToolBox.CompressStringToFile(filePath+".gz", doc.ToString());
|
||||
}
|
||||
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))
|
||||
{
|
||||
@@ -266,10 +316,12 @@ namespace Subsurface
|
||||
{
|
||||
|
||||
DebugConsole.ThrowError("Directory ''Content/SavedMaps'' not found and creating the directory failed.");
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string[] mapFilePaths;
|
||||
|
||||
try
|
||||
{
|
||||
mapFilePaths = Directory.GetFiles(MapFolder);
|
||||
@@ -277,21 +329,42 @@ namespace Subsurface
|
||||
catch (Exception 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;
|
||||
string extension = "";
|
||||
|
||||
@@ -302,16 +375,16 @@ namespace Subsurface
|
||||
catch
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (extension==".gz")
|
||||
if (extension == ".gz")
|
||||
{
|
||||
Stream stream = ToolBox.DecompressFiletoStream(file);
|
||||
if (stream == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -325,19 +398,37 @@ namespace Subsurface
|
||||
catch
|
||||
{
|
||||
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
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't load map ''"+file+"! (Unrecognized file extension)");
|
||||
return;
|
||||
DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)");
|
||||
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())
|
||||
{
|
||||
@@ -350,13 +441,13 @@ namespace Subsurface
|
||||
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -390,13 +481,29 @@ namespace Subsurface
|
||||
ic.OnMapLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
loaded = this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void Clear()
|
||||
public static void Load(string file)
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
65
Subsurface/Map/MapHash.cs
Normal file
65
Subsurface/Map/MapHash.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,12 +378,12 @@ namespace Subsurface
|
||||
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));
|
||||
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);
|
||||
|
||||
@@ -394,6 +394,8 @@ namespace Subsurface
|
||||
}
|
||||
|
||||
AddDamage(i, amount);
|
||||
|
||||
return new AttackResult(amount, 0.0f);
|
||||
}
|
||||
|
||||
private void SetDamage(int sectionIndex, float damage)
|
||||
|
||||
@@ -225,8 +225,15 @@ namespace Subsurface.Networking
|
||||
int seed = inc.ReadInt32();
|
||||
Game1.random = new Random(seed);
|
||||
|
||||
string mapFile = inc.ReadString();
|
||||
Map.Load(mapFile);
|
||||
string mapName = inc.ReadString();
|
||||
string mapHash = inc.ReadString();
|
||||
|
||||
Game1.netLobbyScreen.TrySelectMap(mapName, mapHash);
|
||||
|
||||
|
||||
//Map.Load(mapFile);
|
||||
|
||||
|
||||
|
||||
double durationMinutes = inc.ReadDouble();
|
||||
|
||||
@@ -316,7 +323,7 @@ namespace Subsurface.Networking
|
||||
|
||||
public void EndGame(string endMessage)
|
||||
{
|
||||
Map.Clear();
|
||||
Map.Unload();
|
||||
|
||||
Game1.netLobbyScreen.Select();
|
||||
|
||||
|
||||
@@ -271,7 +271,9 @@ namespace Subsurface.Networking
|
||||
int seed = DateTime.Now.Millisecond;
|
||||
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.StartShift(1);
|
||||
@@ -305,7 +307,9 @@ namespace Subsurface.Networking
|
||||
|
||||
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);
|
||||
|
||||
WriteCharacterData(msg, client.name, client.character);
|
||||
@@ -336,7 +340,7 @@ namespace Subsurface.Networking
|
||||
|
||||
public void EndGame(string endMessage)
|
||||
{
|
||||
Map.Clear();
|
||||
Map.Unload();
|
||||
|
||||
gameStarted = false;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Subsurface
|
||||
{
|
||||
base.Select();
|
||||
|
||||
Map.Clear();
|
||||
Map.Unload();
|
||||
|
||||
UpdateCharacterLists();
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace Subsurface
|
||||
|
||||
private bool StartShift(GUIButton button, object selection)
|
||||
{
|
||||
Map.Load("", Game1.gameSession.SaveFile);
|
||||
Map.Load(Game1.gameSession.SaveFile);
|
||||
|
||||
Game1.gameSession.StartShift();
|
||||
|
||||
|
||||
@@ -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]);
|
||||
mapList = new GUIListBox(new Rectangle(0, 60, 200, 400), Color.White, menuTabs[1]);
|
||||
|
||||
string[] mapFilePaths = Map.GetMapFilePaths();
|
||||
if (mapFilePaths!=null)
|
||||
{
|
||||
foreach (string s in mapFilePaths)
|
||||
//string[] mapFilePaths = Map.GetMapFilePaths();
|
||||
//if (mapFilePaths!=null)
|
||||
//{
|
||||
foreach (Map map in Map.SavedMaps)
|
||||
{
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25),
|
||||
Path.GetFileNameWithoutExtension(s),
|
||||
map.Name,
|
||||
GUI.style,
|
||||
Alignment.Left,
|
||||
Alignment.Left,
|
||||
mapList);
|
||||
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.OnClicked = StartGame;
|
||||
@@ -146,9 +146,12 @@ namespace Subsurface
|
||||
|
||||
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();
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace Subsurface
|
||||
|
||||
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.Enabled = (Game1.server!=null);
|
||||
|
||||
string[] mapFilePaths = Map.GetMapFilePaths();
|
||||
if (mapFilePaths != null)
|
||||
if (Map.SavedMaps.Count>0)
|
||||
{
|
||||
foreach (string s in mapFilePaths)
|
||||
foreach (Map map in Map.SavedMaps)
|
||||
{
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25),
|
||||
Path.GetFileNameWithoutExtension(s),
|
||||
map.Name,
|
||||
GUI.style,
|
||||
Alignment.Left,
|
||||
Alignment.Left,
|
||||
mapList);
|
||||
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
|
||||
textBlock.UserData = s;
|
||||
textBlock.UserData = map;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -194,7 +193,7 @@ namespace Subsurface
|
||||
modeList.OnSelected = 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]);
|
||||
}
|
||||
else
|
||||
@@ -245,8 +244,12 @@ namespace Subsurface
|
||||
{
|
||||
if (Game1.server != null) Game1.server.UpdateNetLobby(obj);
|
||||
|
||||
if ((string)obj == Map.FilePath) return true;
|
||||
Map.Load((string)obj);
|
||||
Map map = (Map)obj;
|
||||
|
||||
//map already loaded
|
||||
if (Map.Loaded!=null && map.FilePath == Map.Loaded.FilePath) return true;
|
||||
|
||||
map.Load();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -462,15 +465,60 @@ namespace Subsurface
|
||||
|
||||
public void WriteData(NetOutgoingMessage msg)
|
||||
{
|
||||
msg.Write(mapList.SelectedIndex);
|
||||
msg.Write(modeList.SelectedIndex);
|
||||
Map selectedMap = mapList.SelectedData as Map;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
mapList.Select(msg.ReadInt32());
|
||||
string mapName = msg.ReadString();
|
||||
string md5Hash = msg.ReadString();
|
||||
|
||||
TrySelectMap(mapName, md5Hash);
|
||||
|
||||
|
||||
//mapList.Select(msg.ReadInt32());
|
||||
modeList.Select(msg.ReadInt32());
|
||||
|
||||
durationBar.BarScroll = msg.ReadFloat();
|
||||
|
||||
@@ -9,7 +9,11 @@ using Subsurface.Sounds;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
public enum DamageSoundType { None, StructureBlunt, StructureSlash, LimbBlunt, LimbSlash, Implode }
|
||||
public enum DamageSoundType {
|
||||
None,
|
||||
StructureBlunt, StructureSlash,
|
||||
LimbBlunt, LimbSlash, LimbArmor,
|
||||
Implode }
|
||||
|
||||
public struct DamageSound
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user