Progress on tutorial, gap tweaking (water flows faster from room to room), UPnP error messages, input keys in array, underwater aiming tweaking, tons of misc stuff commit more often ffs

This commit is contained in:
Regalis
2015-08-31 19:57:49 +03:00
parent 1e990784b2
commit f739808520
150 changed files with 15933 additions and 588 deletions
+13
View File
@@ -0,0 +1,13 @@
#----------------------------- Global Properties ----------------------------#
/outputDir:bin/$(Platform)
/intermediateDir:obj/$(Platform)
/platform:Windows
/config:
/profile:Reach
/compress:False
#-------------------------------- References --------------------------------#
#---------------------------------- Content ---------------------------------#
Binary file not shown.
+4 -4
View File
@@ -1,7 +1,7 @@
<locationtypes>
<None
commonness="3"
symbol="Content\Map\beaconSymbol.png">
symbol="Content/Map/beaconSymbol.png">
<nameformats
f0="[name]"
f1="[name]"
@@ -12,7 +12,7 @@
<City
commonness="3"
hireablecharacters="true"
symbol="Content\Map\citySymbol.png">
symbol="Content/Map/citySymbol.png">
<nameformats
f0="The City of [name]"
f1="[name] City"
@@ -23,7 +23,7 @@
<Military
commonness="1"
hireablecharacters="true"
symbol="Content\Map\militarySymbol.png">
symbol="Content/Map/militarySymbol.png">
<nameformats
f0="[name] Outpost"
f1="[name] Facility"
@@ -34,7 +34,7 @@
<Research
commonness="1"
hireablecharacters="true"
symbol="Content\Map\researchSymbol.png">
symbol="Content/Map/researchSymbol.png">
<nameformats
f0="[name] Research Facility"
f1="[name] Research Center"
@@ -42,7 +42,7 @@
colorchange="0.0, 0.0, 0.0, -0.5"
lifetime="3"
deleteonhit="true"
inwater="true"
drawtarget="water"
velocitychange="0.0, 0.1">
<sprite texture="Content/Particles/bubbles.png"/>
</bubbles>
@@ -67,7 +67,7 @@
startcolor="0.5, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="5.0"
inwater="true"
drawtarget="water"
velocitychange="0.0, 0.0">
<sprite texture="Content/Particles/spatter.png"/>
</waterblood>
@@ -79,7 +79,7 @@
startcolor="1.0, 1.0, 1.0" startalpha="1.0"
colorchange="-0.4, -0.4, -0.4, -0.3"
lifetime="5.0"
inwater="false"
drawtarget="air"
deleteonhit="true"
velocitychange="0.0, 0.5">
<sprite texture="Content/Particles/explosion.png"/>
@@ -91,7 +91,7 @@
startcolor="1.0, 1.0, 1.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -4.0"
lifetime="0.25"
inwater="false"
drawtarget="both"
velocitychange="0.0, 0.0">
<sprite texture="Content/Particles/flames.png" sourcerect="0,0,128,64" origin="0.15,0.5"/>
</weld>
@@ -102,7 +102,7 @@
startcolor="1.0, 1.0, 1.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -4.0"
lifetime="0.25"
inwater="false"
drawtarget="both"
velocitychange="0.0, 0.0">
<sprite texture="Content/Particles/flames.png" sourcerect="0,64,128,64" origin="0.15,0.5"/>
</plasma>
+3 -3
View File
@@ -29,7 +29,7 @@
<damagesound file="Content/Sounds/Damage/implode.ogg" damagerange="0.0,100.0" damagesoundtype="Implode"/>
<music file="Content\Sounds\Music\Simplex.ogg" type="default"/>
<music file="Content\Sounds\Music\Enter The Maze.ogg" type="repair" priorityrange="40,100"/>
<music file="Content\Sounds\Music\Unseen Horrors.ogg" type="monster" priorityrange="40,100"/>
<music file="Content/Sounds/Music/Simplex.ogg" type="default"/>
<music file="Content/Sounds/Music/Enter the Maze.ogg" type="repair" priorityrange="40,100"/>
<music file="Content/Sounds/Music/Unseen Horrors.ogg" type="monster" priorityrange="40,100"/>
</sounds>
+9 -9
View File
@@ -11,8 +11,8 @@
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
</GUIFrame>
<GUIButton
@@ -34,8 +34,8 @@
textcolor="1.0, 1.0, 1.0, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
</GUIListBox>
<GUIScrollBar
@@ -43,7 +43,7 @@
textcolor="1.0, 1.0, 1.0, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 0.0"/>
</GUIScrollBar>
<GUITextBox
@@ -51,14 +51,14 @@
textcolor="1.0, 1.0, 1.0, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
</GUITextBox>
<GUITickBox
color="0.5, 0.5, 0.5, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
</GUITickBox>
<GUIMessageBox
@@ -72,8 +72,8 @@
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content/UI/uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
</GUIMessageBox>
</style>
Binary file not shown.
+1 -4
View File
@@ -1,24 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<Randomevents>
<MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/Crawler/Crawler.xml"
characterfile="Content/Characters/Crawler/crawler.xml"
commonness="10"
difficulty="15"
minamount="2" maxamount="3"
starttimemin="15" starttimemax="20"
musictype="monster"/>
<MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/TigerThresher/tigerthresher.xml"
commonness="10"
difficulty="30"
starttimemin="15" starttimemax="20"
musictype="monster"/>
<MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/Moloch/moloch.xml"
commonness="10"
difficulty="50"
starttimemin="15" starttimemax="20"
musictype="monster"/>
</Randomevents>
@@ -34,6 +34,7 @@ namespace Subsurface
public AiState State
{
get { return state; }
set { state = value; }
}
public AIController (Character c)
@@ -469,8 +469,8 @@ namespace Subsurface
public override void FillNetworkData(NetOutgoingMessage message)
{
message.Write((byte)state);
bool wallAttack = (wallAttackPos!=Vector2.Zero && state == AiState.Attack);
bool wallAttack = (wallAttackPos != Vector2.Zero && state == AiState.Attack);
message.Write(wallAttack);
+185 -148
View File
@@ -46,9 +46,11 @@ namespace Subsurface
get { return Properties; }
}
protected Key selectKeyHit;
protected Key actionKeyHit, actionKeyDown;
protected Key secondaryKeyHit, secondaryKeyDown;
protected Key[] keys;
//protected Key selectKeyHit;
//protected Key actionKeyHit, actionKeyDown;
//protected Key secondaryKeyHit, secondaryKeyDown;
private Item selectedConstruction;
private Item[] selectedItems;
@@ -123,10 +125,10 @@ namespace Subsurface
get { return cursorPosition; }
}
public AITarget AiTarget
{
get { return aiTarget; }
}
//public AITarget AiTarget
//{
// get { return aiTarget; }
//}
public float SoundRange
{
@@ -244,31 +246,6 @@ namespace Subsurface
get { return closestItem; }
}
public Key SelectKeyHit
{
get { return selectKeyHit; }
}
public Key ActionKeyHit
{
get { return actionKeyHit; }
}
public Key ActionKeyDown
{
get { return actionKeyDown; }
}
public Key SecondaryKeyHit
{
get { return secondaryKeyHit; }
}
public Key SecondaryKeyDown
{
get { return secondaryKeyDown; }
}
public AIController AIController
{
get { return aiController; }
@@ -311,11 +288,19 @@ namespace Subsurface
public Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
{
selectKeyHit = new Key(false);
actionKeyDown = new Key(true);
actionKeyHit = new Key(false);
secondaryKeyHit = new Key(false);
secondaryKeyDown = new Key(true);
keys = new Key[Enum.GetNames(typeof(InputType)).Length];
keys[(int)InputType.Select] = new Key(false);
keys[(int)InputType.ActionHeld] = new Key(true);
keys[(int)InputType.ActionHit] = new Key(false);
keys[(int)InputType.SecondaryHit] = new Key(false);
keys[(int)InputType.SecondaryHeld] = new Key(true);
keys[(int)InputType.Left] = new Key(true);
keys[(int)InputType.Right] = new Key(true);
keys[(int)InputType.Up] = new Key(true);
keys[(int)InputType.Down] = new Key(true);
keys[(int)InputType.Run] = new Key(true);
selectedItems = new Item[2];
@@ -426,6 +411,19 @@ namespace Subsurface
}
}
public bool GetInputState(InputType inputType)
{
return keys[(int)inputType].State;
}
public void ClearInputs()
{
foreach (Key key in keys)
{
key.State = false;
}
}
public override string ToString()
{
return (info != null && !string.IsNullOrWhiteSpace(info.Name)) ? info.Name : SpeciesName;
@@ -477,6 +475,42 @@ namespace Subsurface
{
if (isDead) return;
Vector2 targetMovement = Vector2.Zero;
if (GetInputState(InputType.Left)) targetMovement.X -= 1.0f;
if (GetInputState(InputType.Right)) targetMovement.X += 1.0f;
if (GetInputState(InputType.Up)) targetMovement.Y += 1.0f;
if (GetInputState(InputType.Down)) targetMovement.Y -= 1.0f;
//the vertical component is only used for falling through platforms and climbing ladders when not in water,
//so the movement can't be normalized or the character would walk slower when pressing down/up
if (AnimController.InWater)
{
float length = targetMovement.Length();
if (length > 0.0f) targetMovement = targetMovement / length;
}
if (Math.Sign(targetMovement.X) == Math.Sign(AnimController.Dir) && GetInputState(InputType.Run))
targetMovement *= 3.0f;
AnimController.TargetMovement = targetMovement;
AnimController.IsStanding = true;
if (AnimController.onGround &&
!AnimController.InWater &&
AnimController.Anim != AnimController.Animation.UsingConstruction)
{
Limb head = AnimController.GetLimb(LimbType.Head);
if (cursorPosition.X < head.Position.X - 10.0f)
{
AnimController.TargetDir = Direction.Left;
}
else if (cursorPosition.X > head.Position.X + 10.0f)
{
AnimController.TargetDir = Direction.Right;
}
}
//find the closest item if selectkey has been hit, or if the character is being
//controlled by the player (in order to highlight it)
if (controlled == this)
@@ -487,7 +521,7 @@ namespace Subsurface
if (closestItem != null)
{
closestItem.IsHighlighted = true;
if (selectKeyHit.State && closestItem.Pick(this, forcePick))
if (GetInputState(InputType.Select) && closestItem.Pick(this, forcePick))
{
new NetworkEvent(NetworkEventType.PickItem, ID, true, closestItem.ID);
}
@@ -497,7 +531,7 @@ namespace Subsurface
if (closestCharacter != selectedCharacter) selectedCharacter = null;
if (closestCharacter!=null)
{
if (selectKeyHit.State) selectedCharacter = (selectedCharacter==null) ? closestCharacter : null;
if (GetInputState(InputType.Select)) selectedCharacter = (selectedCharacter == null) ? closestCharacter : null;
}
}
@@ -506,23 +540,22 @@ namespace Subsurface
if (selectedItems[i] == null) continue;
if (i == 1 && selectedItems[0] == selectedItems[1]) continue;
if (actionKeyDown.State) selectedItems[i].Use(deltaTime, this);
if (secondaryKeyDown.State && selectedItems[i] != null) selectedItems[i].SecondaryUse(deltaTime, this);
if (GetInputState(InputType.ActionHeld)) selectedItems[i].Use(deltaTime, this);
if (GetInputState(InputType.SecondaryHeld) && selectedItems[i] != null) selectedItems[i].SecondaryUse(deltaTime, this);
}
if (selectedConstruction != null)
{
if (actionKeyDown.State) selectedConstruction.Use(deltaTime, this);
if (secondaryKeyDown.State) selectedConstruction.SecondaryUse(deltaTime, this);
if (GetInputState(InputType.ActionHeld)) selectedConstruction.Use(deltaTime, this);
if (GetInputState(InputType.SecondaryHeld)) selectedConstruction.SecondaryUse(deltaTime, this);
}
if (IsNetworkPlayer)
{
selectKeyHit.Reset();
actionKeyHit.Reset();
actionKeyDown.Reset();
secondaryKeyHit.Reset();
secondaryKeyDown.Reset();
foreach (Key key in keys)
{
key.Reset();
}
}
}
@@ -574,44 +607,29 @@ namespace Subsurface
Lights.LightManager.ViewPos = ConvertUnits.ToDisplayUnits(head.SimPosition);
Vector2 targetMovement = Vector2.Zero;
if (!DisableControls)
{
if (PlayerInput.KeyDown(Keys.W)) targetMovement.Y += 1.0f;
if (PlayerInput.KeyDown(Keys.S)) targetMovement.Y -= 1.0f;
if (PlayerInput.KeyDown(Keys.A)) targetMovement.X -= 1.0f;
if (PlayerInput.KeyDown(Keys.D)) targetMovement.X += 1.0f;
keys[(int)InputType.Left].SetState(PlayerInput.KeyDown(Keys.A));
keys[(int)InputType.Right].SetState(PlayerInput.KeyDown(Keys.D));
keys[(int)InputType.Up].SetState(PlayerInput.KeyDown(Keys.W));
keys[(int)InputType.Down].SetState(PlayerInput.KeyDown(Keys.S));
//the vertical component is only used for falling through platforms and climbing ladders when not in water,
//so the movement can't be normalized or the character would walk slower when pressing down/up
if (AnimController.InWater)
{
float length = targetMovement.Length();
if (length > 0.0f) targetMovement = targetMovement / length;
}
keys[(int)InputType.Select].SetState(PlayerInput.KeyHit(Keys.E));
keys[(int)InputType.ActionHit].SetState(PlayerInput.LeftButtonClicked());
keys[(int)InputType.ActionHeld].SetState(PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed);
keys[(int)InputType.SecondaryHit].SetState(PlayerInput.RightButtonClicked());
keys[(int)InputType.SecondaryHeld].SetState(PlayerInput.GetMouseState.RightButton == ButtonState.Pressed);
if (Keyboard.GetState().IsKeyDown(Keys.LeftShift) && Math.Sign(targetMovement.X) == Math.Sign(AnimController.Dir))
targetMovement *= 3.0f;
selectKeyHit.SetState(PlayerInput.KeyHit(Keys.E));
actionKeyHit.SetState(PlayerInput.LeftButtonClicked());
actionKeyDown.SetState(PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed);
secondaryKeyHit.SetState(PlayerInput.RightButtonClicked());
secondaryKeyDown.SetState(PlayerInput.GetMouseState.RightButton == ButtonState.Pressed);
keys[(int)InputType.Run].SetState(PlayerInput.KeyDown(Keys.LeftShift));
}
else
{
selectKeyHit.SetState(false);
actionKeyHit.SetState(false);
actionKeyDown.SetState(false);
secondaryKeyHit.SetState(false);
secondaryKeyDown.SetState(false);
foreach (Key key in keys)
{
key.SetState(false);
}
}
AnimController.TargetMovement = targetMovement;
AnimController.IsStanding = true;
if (moveCam)
{
cam.TargetPos = ConvertUnits.ToDisplayUnits(AnimController.limbs[0].SimPosition);
@@ -634,20 +652,6 @@ namespace Subsurface
}
}
if (AnimController.onGround &&
!AnimController.InWater &&
AnimController.Anim != AnimController.Animation.UsingConstruction)
{
if (mouseSimPos.X < head.SimPosition.X-1.0f)
{
AnimController.TargetDir = Direction.Left;
}
else if (mouseSimPos.X > head.SimPosition.X + 1.0f)
{
AnimController.TargetDir = Direction.Right;
}
}
DisableControls = false;
}
@@ -810,7 +814,7 @@ namespace Subsurface
Color color = Color.Orange;
if (closestCharacter != null && closestCharacter.isDead)
if (closestCharacter != null && closestCharacter.isDead && closestCharacter.isHumanoid)
{
Vector2 startPos = Position + (closestCharacter.Position - Position) * 0.7f;
startPos = cam.WorldToScreen(startPos);
@@ -840,10 +844,10 @@ namespace Subsurface
textPos.Y += 50.0f;
foreach (ColoredText coloredText in closestItem.GetHUDTexts(Controlled))
{
textPos.X = startPos.X - GUI.Font.MeasureString(coloredText.text).X / 2;
textPos.X = startPos.X - GUI.Font.MeasureString(coloredText.Text).X / 2;
spriteBatch.DrawString(GUI.Font, coloredText.text, textPos, Color.Black);
spriteBatch.DrawString(GUI.Font, coloredText.text, textPos + new Vector2(1, -1), coloredText.color);
spriteBatch.DrawString(GUI.Font, coloredText.Text, textPos, Color.Black);
spriteBatch.DrawString(GUI.Font, coloredText.Text, textPos + new Vector2(1, -1), coloredText.Color);
textPos.Y += 25;
}
@@ -919,13 +923,7 @@ namespace Subsurface
Limb torso= AnimController.GetLimb(LimbType.Torso);
if (torso == null) torso = AnimController.GetLimb(LimbType.Head);
Vector2 centerOfMass = Vector2.Zero;
foreach (Limb limb in AnimController.limbs)
{
centerOfMass += limb.Mass * limb.SimPosition;
}
centerOfMass /= AnimController.Mass;
Vector2 centerOfMass = AnimController.GetCenterOfMass();
health = 0.0f;
@@ -1022,34 +1020,44 @@ namespace Subsurface
}
else if (type == NetworkEventType.KillCharacter)
{
return;
}
else if (type== NetworkEventType.NotMoving)
{
return;
return;
}
var hasInputs = (GetInputState(InputType.Left) ||
GetInputState(InputType.Right) ||
GetInputState(InputType.Up) ||
GetInputState(InputType.Down) ||
GetInputState(InputType.ActionHeld) ||
GetInputState(InputType.SecondaryHeld));
//if (type == Networking.NetworkEventType.KeyHit)
//{
// message.Write(selectKeyHit.Dequeue);
message.Write(actionKeyDown.Dequeue);
message.Write(secondaryKeyDown.Dequeue);
//}
message.Write(hasInputs || LargeUpdateTimer <= 0);
message.Write((float)NetTime.Now);
// Write byte = move direction
message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -10.0f, 10.0f), -10.0f, 10.0f, 8);
message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -10.0f, 10.0f), -10.0f, 10.0f, 8);
message.Write(keys[(int)InputType.ActionHeld].Dequeue);
message.Write(keys[(int)InputType.SecondaryHeld].Dequeue);
message.Write(keys[(int)InputType.Left].Dequeue);
message.Write(keys[(int)InputType.Right].Dequeue);
message.Write(AnimController.TargetDir==Direction.Right);
message.Write(keys[(int)InputType.Up].Dequeue);
message.Write(keys[(int)InputType.Down].Dequeue);
message.Write(keys[(int)InputType.Run].Dequeue);
// Write byte = move direction
//message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -10.0f, 10.0f), -10.0f, 10.0f, 8);
//message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -10.0f, 10.0f), -10.0f, 10.0f, 8);
if (aiController==null)
{
message.Write(cursorPosition.X);
message.Write(cursorPosition.Y);
}
else
{
message.Write(AnimController.TargetDir == Direction.Right);
}
message.Write(LargeUpdateTimer <= 0);
@@ -1070,7 +1078,7 @@ namespace Subsurface
}
message.WriteRangedSingle(MathHelper.Clamp(AnimController.StunTimer,0.0f,60.0f), 0.0f, 60.0f, 8);
message.Write((byte)health);
message.Write((byte)((health/maxHealth)*255.0f));
if (aiController != null) aiController.FillNetworkData(message);
@@ -1122,40 +1130,39 @@ namespace Subsurface
}
return;
}
else if (type == NetworkEventType.NotMoving)
{
AnimController.TargetMovement = Vector2.Zero;
actionKeyDown.State = false;
secondaryKeyDown.State = false;
return;
}
bool actionKeyState = false;
bool secondaryKeyState = false;
float sendingTime = 0.0f;
Vector2 targetMovement = Vector2.Zero;
float sendingTime = 0.0f;
//Vector2 targetMovement = Vector2.Zero;
bool targetDir = false;
Vector2 cursorPos = Vector2.Zero;
bool leftKeyState = false, rightKeyState = false;
bool upKeyState = false, downKeyState = false;
bool runState = false;
try
{
bool hasInputs = message.ReadBoolean();
if (!hasInputs)
{
ClearInputs();
return;
}
sendingTime = message.ReadFloat();
actionKeyState = message.ReadBoolean();
secondaryKeyState = message.ReadBoolean();
sendingTime = message.ReadFloat();
leftKeyState = message.ReadBoolean();
rightKeyState = message.ReadBoolean();
upKeyState = message.ReadBoolean();
downKeyState = message.ReadBoolean();
targetMovement = new Vector2(message.ReadRangedSingle(-10.0f, 10.0f, 8), message.ReadRangedSingle(-10.0f, 10.0f, 8));
targetMovement.X = MathUtils.Round(targetMovement.X, 0.1f);
targetMovement.Y = MathUtils.Round(targetMovement.Y, 0.1f);
targetDir = message.ReadBoolean();
if (aiController==null)
{
cursorPos = new Vector2(
message.ReadFloat(),
message.ReadFloat());
}
runState = message.ReadBoolean();
}
catch
@@ -1165,22 +1172,52 @@ namespace Subsurface
AnimController.IsStanding = true;
actionKeyDown.State = actionKeyState;
secondaryKeyDown.State = secondaryKeyState;
keys[(int)InputType.ActionHeld].State = actionKeyState;
keys[(int)InputType.SecondaryHeld].State = secondaryKeyState;
if (sendingTime <= LastNetworkUpdate) return;
cursorPosition = cursorPos;
AnimController.TargetMovement= targetMovement;
AnimController.TargetDir = (targetDir) ? Direction.Right : Direction.Left;
keys[(int)InputType.Left].State = leftKeyState;
keys[(int)InputType.Right].State = rightKeyState;
keys[(int)InputType.Up].State = upKeyState;
keys[(int)InputType.Down].State = downKeyState;
keys[(int)InputType.Run].State = runState;
try
{
if (aiController == null)
{
cursorPos = new Vector2(
message.ReadFloat(),
message.ReadFloat());
}
else
{
targetDir = message.ReadBoolean();
}
}
catch
{
return;
}
if (aiController == null)
{
cursorPosition = cursorPos;
}
else
{
AnimController.TargetDir = (targetDir) ? Direction.Right : Direction.Left;
}
if (message.ReadBoolean())
{
foreach (Limb limb in AnimController.limbs)
{
Vector2 pos = Vector2.Zero, vel = Vector2.Zero;
float rotation = 0.0f, angularVel = 0.0f;
float rotation = 0.0f;
try
{
@@ -1213,7 +1250,7 @@ namespace Subsurface
try
{
newStunTimer = message.ReadRangedSingle(0.0f, 60.0f, 8);
newHealth = message.ReadByte();
newHealth = (message.ReadByte() / 255.0f) * maxHealth;
}
catch { return; }
@@ -368,7 +368,7 @@ namespace Subsurface
}
}
float midX = (leftX + rightX) / 2.0f;
float midX = GetCenterOfMass().X;
foreach (Limb l in limbs)
{
@@ -9,6 +9,8 @@ namespace Subsurface
{
class HumanoidAnimController : AnimController
{
private bool aiming;
public HumanoidAnimController(Character character, XElement element)
: base(character, element)
{
@@ -144,6 +146,7 @@ namespace Subsurface
limb.Disabled = false;
}
aiming = false;
}
void UpdateStanding()
@@ -398,7 +401,7 @@ namespace Subsurface
rotation = MathHelper.ToDegrees(rotation);
if (rotation < 0.0f) rotation += 360;
if (!character.IsNetworkPlayer)
if (!character.IsNetworkPlayer && !aiming)
{
if (rotation > 20 && rotation < 170)
TargetDir = Direction.Left;
@@ -413,12 +416,17 @@ namespace Subsurface
//if trying to head to the opposite direction, apply torque
//to the torso to flip the ragdoll around
if (Math.Sign(TargetMovement.X) != Dir && TargetMovement.X != 0.0f)
{
float torque = torso.Mass * 10.0f;
torque *= (rotation > 90 && rotation < 270) ? -Dir : Dir;
//if (Math.Sign(TargetMovement.X) != Dir && TargetMovement.X != 0.0f)
//{
// float torque = torso.Mass * 10.0f;
// torque *= (rotation > 90 && rotation < 270) ? -Dir : Dir;
torso.body.ApplyTorque(torque);
// torso.body.ApplyTorque(torque);
//}
if (targetSpeed > 0.1f && !aiming)
{
torso.body.SmoothRotate(MathUtils.VectorToAngle(TargetMovement)-MathHelper.PiOver2);
}
movement = MathUtils.SmoothStep(movement, TargetMovement, 0.3f);
@@ -578,7 +586,7 @@ namespace Subsurface
handPos = new Vector2(
ladderSimPos.X,
head.SimPosition.Y + 0.5f + movement.Y * 0.1f - ladderSimPos.Y);
head.SimPosition.Y + 0.0f + movement.Y * 0.1f - ladderSimPos.Y);
MoveLimb(leftHand,
new Vector2(handPos.X,
@@ -595,7 +603,7 @@ namespace Subsurface
footPos = new Vector2(
handPos.X - Dir*0.05f,
head.SimPosition.Y - stepHeight * 2.7f - ladderSimPos.Y);
head.SimPosition.Y - stepHeight * 2.7f - ladderSimPos.Y - 0.7f);
//if (movement.Y < 0) footPos.Y += 0.05f;
@@ -679,10 +687,10 @@ namespace Subsurface
Limb rightHand = GetLimb(LimbType.RightHand);
Limb rightArm = GetLimb(LimbType.RightArm);
Vector2 itemPos = character.SecondaryKeyDown.State ? aimPos : holdPos;
Vector2 itemPos = character.GetInputState(InputType.SecondaryHeld) ? aimPos : holdPos;
float itemAngle;
if (character.SecondaryKeyDown.State && itemPos != Vector2.Zero)
if (character.GetInputState(InputType.SecondaryHeld) && itemPos != Vector2.Zero)
{
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
@@ -697,9 +705,11 @@ namespace Subsurface
if (TargetMovement == Vector2.Zero && inWater)
{
torso.body.SmoothRotate(0.2f * Dir);
torso.body.AngularVelocity -= torso.body.AngularVelocity * 0.1f;
torso.body.ApplyForce(torso.body.LinearVelocity * -0.5f);
}
aiming = true;
}
else
{
+25 -15
View File
@@ -8,6 +8,7 @@ using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Subsurface.Networking;
namespace Subsurface
{
@@ -39,7 +40,7 @@ namespace Subsurface
//a movement vector that overrides targetmovement if trying to steer
//a character to the position sent by server in multiplayer mode
public Vector2 correctionMovement;
private Vector2 correctionMovement;
protected float floorY;
protected float surfaceY;
@@ -73,11 +74,7 @@ namespace Subsurface
}
set
{
if (float.IsNaN(value.X) || float.IsNaN(value.Y))
{
targetMovement = Vector2.Zero;
return;
}
if (!MathUtils.IsValid(value)) return;
targetMovement.X = MathHelper.Clamp(value.X, -3.0f, 3.0f);
targetMovement.Y = MathHelper.Clamp(value.Y, -3.0f, 3.0f);
}
@@ -408,10 +405,24 @@ namespace Subsurface
new Vector2(
-limbs[i].pullJoint.LocalAnchorA.X,
limbs[i].pullJoint.LocalAnchorA.Y);
}
}
}
public Vector2 GetCenterOfMass()
{
Vector2 centerOfMass = Vector2.Zero;
foreach (Limb limb in limbs)
{
centerOfMass += limb.Mass * limb.SimPosition;
}
centerOfMass /= Mass;
return centerOfMass;
}
/// <summary>
///
/// </summary>
@@ -567,10 +578,10 @@ namespace Subsurface
if (refLimb.body.TargetPosition == Vector2.Zero) return;
//if the limb is further away than resetdistance, all limbs are immediately snapped to their targetpositions
float resetDistance = 1.5f;
float resetDistance = NetConfig.ResetRagdollDistance;
//if the limb is closer than alloweddistance, limb positions aren't updated
float allowedDistance = 0.1f;
//if the limb is closer than alloweddistance, just ignore the difference
float allowedDistance = NetConfig.AllowedRagdollDistance;
float dist = Vector2.Distance(limbs[0].body.Position, refLimb.body.TargetPosition);
bool resetAll = (dist > resetDistance && character.LargeUpdateTimer == 1);
@@ -596,8 +607,7 @@ namespace Subsurface
}
else
{
correctionMovement = Vector2.Normalize(newMovement) * ((targetMovement == Vector2.Zero) ? 1.0f : targetMovement.Length());
correctionMovement = Vector2.Normalize(newMovement) * Math.Min(1.0f + dist, 3.0f);
}
}
@@ -627,13 +637,13 @@ namespace Subsurface
foreach (MapEntity e in MapEntity.mapEntityList)
{
Gap gap = e as Gap;
if (gap == null || gap.FlowTargetHull!=currentHull ||gap.FlowForce == Vector2.Zero) continue;
if (gap == null || gap.FlowTargetHull != currentHull || gap.FlowForce == Vector2.Zero) continue;
Vector2 gapPos = gap.SimPosition;
float dist = Vector2.Distance(limbPos, gapPos);
force += Vector2.Normalize(gap.FlowForce)*(Math.Max(gap.FlowForce.Length() - dist, 0.0f)/1000.0f);
force += Vector2.Normalize(gap.FlowForce) * (Math.Max(gap.FlowForce.Length() - dist, 0.0f) / 500.0f);
}
if (force.Length() > 20.0f) return force;
+3 -4
View File
@@ -57,13 +57,14 @@ namespace Subsurface
{
XDocument doc = ToolBox.TryLoadXml(filePath);
Path = filePath;
if (doc==null)
{
DebugConsole.ThrowError("Couldn't load content package ''"+filePath+"''!");
return;
}
Path = filePath;
name = ToolBox.GetAttributeString(doc.Root, "name", "");
@@ -81,7 +82,7 @@ namespace Subsurface
public static ContentPackage CreatePackage(string name)
{
ContentPackage newPackage = new ContentPackage();
ContentPackage newPackage = new ContentPackage("Content/Data/"+name);
newPackage.name = name;
newPackage.Path = Folder + name;
list.Add(newPackage);
@@ -150,8 +151,6 @@ namespace Subsurface
}
}
//string str = sb.ToString();
byte[] bytes = new byte[hashes.Count()*16];
for (int i = 0; i < hashes.Count; i++ )
+11 -4
View File
@@ -6,7 +6,7 @@ using System.Text;
namespace Subsurface
{
enum Status
enum CoroutineStatus
{
Running, Success, Failure
}
@@ -24,6 +24,13 @@ namespace Subsurface
Coroutines.Add(func.GetEnumerator());
}
public static void StopCoroutine(string name)
{
IEnumerator<object> coroutine = Coroutines.FirstOrDefault(c => c.ToString().Contains(name));
if (coroutine != null) Coroutines.Remove(coroutine);
}
// Updating just means stepping through all the coroutines
public static void Update(float deltaTime)
{
@@ -39,12 +46,12 @@ namespace Subsurface
}
else
{
switch ((Status)Coroutines[i].Current)
switch ((CoroutineStatus)Coroutines[i].Current)
{
case Status.Success:
case CoroutineStatus.Success:
Coroutines.RemoveAt(i);
continue;
case Status.Failure:
case CoroutineStatus.Failure:
DebugConsole.ThrowError("Coroutine ''" + Coroutines[i]+ "'' has failed");
break;
}
+20 -6
View File
@@ -10,13 +10,17 @@ namespace Subsurface
{
struct ColoredText
{
public string text;
public Color color;
public string Text;
public Color Color;
public readonly string Time;
public ColoredText(string text, Color color)
{
this.text = text;
this.color = color;
this.Text = text;
this.Color = color;
Time = DateTime.Now.ToString();
}
}
@@ -96,7 +100,7 @@ namespace Subsurface
if (selectedIndex < 0) selectedIndex = messageCount - 1;
selectedIndex = selectedIndex % messageCount;
textBox.Text = messages[selectedIndex].text;
textBox.Text = messages[selectedIndex].Text;
}
public static void Draw(SpriteBatch spriteBatch)
@@ -127,7 +131,7 @@ namespace Subsurface
Vector2 messagePos = new Vector2(x + margin * 2, y + height - 70 - messages.Count()*20);
foreach (ColoredText message in messages)
{
spriteBatch.DrawString(GUI.Font, message.text, messagePos, message.color);
spriteBatch.DrawString(GUI.Font, message.Text, messagePos, message.Color);
messagePos.Y += 20;
}
@@ -227,6 +231,16 @@ namespace Subsurface
it.Condition = 100.0f;
}
break;
case "fixhull":
case "fixwalls":
foreach (Structure w in Structure.wallList)
{
for (int i = 0 ; i < w.SectionCount; i++)
{
w.AddDamage(i, -100000.0f);
}
}
break;
case "shake":
Game1.GameScreen.Cam.Shake = 10.0f;
break;
+10 -4
View File
@@ -157,16 +157,19 @@ namespace EventInput
throw new InvalidOperationException("TextInput.Initialize can only be called once!");
hookProcDelegate = HookProc;
prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC,
(int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate));
#if WINDOWS
prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC,
(int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate));
hIMC = ImmGetContext(window.Handle);
#endif
hIMC = ImmGetContext(window.Handle);
initialized = true;
}
static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
switch (msg)
{
@@ -200,7 +203,10 @@ namespace EventInput
break;
}
return returnCode;
}
}
+18 -14
View File
@@ -18,10 +18,10 @@ namespace Subsurface
characterFile = ToolBox.GetAttributeString(element, "characterfile", "");
minAmount = ToolBox.GetAttributeInt(element, "minamount", 1);
maxAmount = Math.Max(ToolBox.GetAttributeInt(element, "maxamount", 1),minAmount);
maxAmount = Math.Max(ToolBox.GetAttributeInt(element, "maxamount", 1), minAmount);
}
protected override void Start()
private void SpawnMonsters()
{
WayPoint randomWayPoint = WayPoint.GetRandom(SpawnType.Enemy);
@@ -40,22 +40,26 @@ namespace Subsurface
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (monsters == null) SpawnMonsters();
if (!isStarted) return;
if (!isFinished)
//base.Update(deltaTime);
//if (!isStarted) return;
if (isFinished) return;
bool monstersDead = true;
for (int i = 0; i < monsters.Length; i++)
{
bool monstersDead = true;
for (int i = 0; i < monsters.Length; i++)
{
if (monsters[i].IsDead) continue;
if (monsters[i].IsDead) continue;
if (!isStarted && monsters[i].SimPosition != Vector2.Zero && monsters[i].SimPosition.Length() < 20.0) isStarted = true;
monstersDead = false;
break;
}
if (monstersDead) Finished();
monstersDead = false;
break;
}
if (monstersDead) Finished();
}
}
}
@@ -32,7 +32,7 @@ namespace Subsurface
public override void Start(Level level)
{
Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count)];
Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count, false)];
monster = new Character(monsterFile, ConvertUnits.ToSimUnits(position+level.Position));
}
+1 -1
View File
@@ -104,7 +104,7 @@ namespace Subsurface
try
{
t = Type.GetType("Subsurface." + type + ", Subsurface", true, true);
t = Type.GetType("Subsurface." + type, true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + configFile + "! Could not find a quest class of the type ''" + type + "''.");
+1 -1
View File
@@ -137,7 +137,7 @@ namespace Subsurface
try
{
t = Type.GetType("Subsurface." + type + ", Subsurface", true, true);
t = Type.GetType("Subsurface." + type, true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + configFile + "! Could not find an event class of the type ''" + type + "''.");
+5
View File
@@ -6,6 +6,11 @@
private bool prevStarted;
public override bool IsStarted
{
get { return scriptedEvent.IsStarted; }
}
public ScriptedTask(ScriptedEvent scriptedEvent)
: base(scriptedEvent.Difficulty, scriptedEvent.Name)
{
+5
View File
@@ -34,6 +34,11 @@ namespace Subsurface
get { return isFinished; }
}
public virtual bool IsStarted
{
get { return true; }
}
public Task(float priority, string name)
{
if (Game1.GameSession==null || Game1.GameSession.taskManager == null) return;
+38 -43
View File
@@ -11,7 +11,7 @@ namespace Subsurface
private List<Task> tasks;
private GUIListBox taskListBox;
//private GUIListBox taskListBox;
public List<Task> Tasks
{
@@ -34,7 +34,7 @@ namespace Subsurface
{
tasks = new List<Task>();
taskListBox = new GUIListBox(new Rectangle(Game1.GraphicsWidth - 250, 50, 250, 500), Color.Transparent);
//taskListBox = new GUIListBox(new Rectangle(Game1.GraphicsWidth - 250, 50, 250, 500), Color.Transparent);
//taskListBox.ScrollBarEnabled = false;
//taskListBox.Padding = GUI.style.smallPadding;
}
@@ -50,24 +50,24 @@ namespace Subsurface
{
CreateScriptedEvents(level);
taskListBox.ClearChildren();
//taskListBox.ClearChildren();
}
public void EndShift()
{
taskListBox.ClearChildren();
//taskListBox.ClearChildren();
tasks.Clear();
}
private void CreateScriptedEvents(Level level)
{
Random rand = new Random(level.Seed.GetHashCode());
Random rand = new Random(ToolBox.StringToInt(level.Seed));
float totalDifficulty = level.Difficulty;
int tries = 0;
do
while (tries < 5)
{
ScriptedEvent scriptedEvent = ScriptedEvent.LoadRandom(rand);
if (scriptedEvent==null || scriptedEvent.Difficulty > totalDifficulty)
@@ -79,36 +79,36 @@ namespace Subsurface
AddTask(new ScriptedTask(scriptedEvent));
totalDifficulty -= scriptedEvent.Difficulty;
tries = 0;
} while (tries < 5);
}
}
public void TaskStarted(Task task)
{
Color color = Color.Red;
int width = 250;
if (task.Priority < 30.0f)
{
width = 200;
color = Color.Yellow;
}
else if (task.Priority < 60)
{
width = 220;
color = Color.Orange;
}
//Color color = Color.Red;
//int width = 250;
//if (task.Priority < 30.0f)
//{
// width = 200;
// color = Color.Yellow;
//}
//else if (task.Priority < 60)
//{
// width = 220;
// color = Color.Orange;
//}
GUIFrame frame = new GUIFrame(new Rectangle(0,0,width,40), Color.Transparent, Alignment.Right, null, taskListBox);
frame.UserData = task;
frame.Padding = new Vector4(0.0f, 5.0f, 5.0f, 5.0f);
//GUIFrame frame = new GUIFrame(new Rectangle(0,0,width,40), Color.Transparent, Alignment.Right, null, taskListBox);
//frame.UserData = task;
//frame.Padding = new Vector4(0.0f, 5.0f, 5.0f, 5.0f);
GUIFrame colorFrame = new GUIFrame(new Rectangle(0, 0, 0, 0), color * 0.5f, Alignment.Right, null, frame);
GUITextBlock textBlock = new GUITextBlock(new Rectangle(5, 5, 0, 20), task.Name, Color.Transparent, Color.Black, Alignment.Right, null, colorFrame);
//GUIFrame colorFrame = new GUIFrame(new Rectangle(0, 0, 0, 0), color * 0.5f, Alignment.Right, null, frame);
//GUITextBlock textBlock = new GUITextBlock(new Rectangle(5, 5, 0, 20), task.Name, Color.Transparent, Color.Black, Alignment.Right, null, colorFrame);
//textBlock.Padding = new Vector4(10.0f, 10.0f, 0.0f, 0.0f);
//colorFrame.AddChild(textBlock);
taskListBox.children.Sort((x, y) => ((Task)y.UserData).Priority.CompareTo(((Task)x.UserData).Priority));
//taskListBox.children.Sort((x, y) => ((Task)y.UserData).Priority.CompareTo(((Task)x.UserData).Priority));
}
public void TaskFinished(Task task)
@@ -121,23 +121,22 @@ namespace Subsurface
public void Update(float deltaTime)
{
Task removeTask = null;
GUIComponent removeComponent = null;
foreach (Task task in tasks)
{
if (task.IsFinished)
{
foreach (GUIComponent comp in taskListBox.children)
{
if (comp.UserData as Task != task) continue;
comp.Rect = new Rectangle(comp.Rect.X, comp.Rect.Y, comp.Rect.Width, comp.Rect.Height - 1);
comp.children[0].ClearChildren();
if (comp.Rect.Height < 1)
{
removeComponent = comp;
//foreach (GUIComponent comp in taskListBox.children)
//{
// if (comp.UserData as Task != task) continue;
// comp.Rect = new Rectangle(comp.Rect.X, comp.Rect.Y, comp.Rect.Width, comp.Rect.Height - 1);
// comp.children[0].ClearChildren();
// if (comp.Rect.Height < 1)
// {
// removeComponent = comp;
removeTask = task;
}
break;
}
// }
// break;
//}
}
else
@@ -146,18 +145,14 @@ namespace Subsurface
}
}
if (removeComponent!= null)
if (removeTask!= null)
{
taskListBox.RemoveChild(removeComponent);
//taskListBox.RemoveChild(removeComponent);
tasks.Remove(removeTask);
}
//endShiftButton.Enabled = finished || Game1.server!=null;
}
public void Draw(SpriteBatch spriteBatch)
{
taskListBox.Draw(spriteBatch);
}
}
}
+2 -2
View File
@@ -18,12 +18,12 @@ namespace Subsurface
public string Text
{
get { return coloredText.text; }
get { return coloredText.Text; }
}
public Color Color
{
get { return coloredText.color; }
get { return coloredText.Color; }
}
public Vector2 Pos
+6 -1
View File
@@ -15,6 +15,11 @@ namespace Subsurface
//GUIFrame frame;
public GUIButton[] Buttons;
public static GUIMessageBox VisibleBox
{
get { return MessageBoxes.Count==0 ? null : MessageBoxes.Peek(); }
}
public string Text
{
get { return (children[1] as GUITextBlock).Text; }
@@ -63,8 +68,8 @@ namespace Subsurface
public bool Close(GUIButton button, object obj)
{
if (parent != null) parent.RemoveChild(this);
if (MessageBoxes.Contains(this)) MessageBoxes.Dequeue();
MessageBoxes.Dequeue();
return true;
}
}
+14 -14
View File
@@ -174,42 +174,42 @@ namespace Subsurface
Hull.renderer = new WaterRenderer(GraphicsDevice);
loadState = 1.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
GUI.LoadContent(GraphicsDevice);
loadState = 2.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
MapEntityPrefab.Init();
loadState = 10.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
JobPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Jobs));
loadState = 15.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
StructurePrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Structure));
loadState = 25.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
ItemPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Item));
loadState = 40.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
Debug.WriteLine("sounds");
CoroutineManager.StartCoroutine(AmbientSoundManager.Init());
loadState = 70.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
GameModePreset.Init();
Submarine.Preload("Content/SavedMaps");
loadState = 80.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
GameScreen = new GameScreen(Graphics.GraphicsDevice);
loadState = 90.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
MainMenuScreen = new MainMenuScreen(this);
LobbyScreen = new LobbyScreen();
@@ -220,21 +220,21 @@ namespace Subsurface
EditMapScreen = new EditMapScreen();
EditCharacterScreen = new EditCharacterScreen();
yield return Status.Running;
yield return CoroutineStatus.Running;
ParticleManager = new ParticleManager("Content/Particles/ParticlePrefabs.xml", Cam);
yield return Status.Running;
yield return CoroutineStatus.Running;
GUIComponent.Init(Window);
DebugConsole.Init(Window);
yield return Status.Running;
yield return CoroutineStatus.Running;
LocationType.Init("Content/Map/locationTypes.xml");
MainMenuScreen.Select();
yield return Status.Running;
yield return CoroutineStatus.Running;
loadState = 100.0f;
yield return Status.Success;
yield return CoroutineStatus.Success;
}
/// <summary>
@@ -23,7 +23,7 @@ namespace Subsurface
{
Location[] locations = new Location[2];
Random rand = new Random(Game1.NetLobbyScreen.LevelSeed.GetHashCode());
Random rand = new Random(ToolBox.StringToInt(Game1.NetLobbyScreen.LevelSeed));
for (int i = 0; i < 2; i++)
{
@@ -69,7 +69,17 @@ namespace Subsurface
{
base.Update(deltaTime);
if (Character.Controlled!=null && Character.Controlled.IsDead)
{
Character.Controlled = null;
CoroutineManager.StopCoroutine("TutorialMode.UpdateState");
infoBox = null;
CoroutineManager.StartCoroutine(Dead());
}
CrewManager.Update(deltaTime);
if (infoBox!=null) infoBox.Update(deltaTime);
}
@@ -90,7 +100,7 @@ namespace Subsurface
while (!tutorialDoor.IsOpen)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(2.0f);
@@ -103,14 +113,14 @@ namespace Subsurface
while (Vector2.Distance(Character.Controlled.Position, reactor.Item.Position)>200.0f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Select the reactor by walking next to it and pressing E.");
while (Character.Controlled.SelectedConstruction != reactor.Item)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(0.5f);
@@ -118,7 +128,7 @@ namespace Subsurface
while (reactor.FissionRate <= 0.0f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(0.5f);
@@ -128,7 +138,7 @@ namespace Subsurface
while (Math.Abs(reactor.ShutDownTemp-5000.0f) > 400.0f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(0.5f);
@@ -138,7 +148,7 @@ namespace Subsurface
while (!reactor.AutoTemp)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(0.5f);
@@ -150,14 +160,14 @@ namespace Subsurface
while (Vector2.Distance(Character.Controlled.Position, steering.Item.Position) > 150.0f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Select the navigation terminal by walking next to it and pressing E.");
while (Character.Controlled.SelectedConstruction != steering.Item)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(0.5f);
@@ -168,7 +178,7 @@ namespace Subsurface
while (Character.Controlled.SelectedConstruction == steering.Item)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(1.0f);
@@ -178,7 +188,7 @@ namespace Subsurface
while (Character.Controlled.SelectedConstruction != steering.Item ||
Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.Name == "Screwdriver") == null)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
@@ -188,7 +198,7 @@ namespace Subsurface
while (!HasItem("Wire"))
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Head back to the navigation terminal to fix the wiring.");
@@ -199,7 +209,7 @@ namespace Subsurface
Character.Controlled.SelectedConstruction != steering.Item) ||
Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.Name == "Screwdriver") == null)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
if (Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.GetComponent<Wire>()!=null) == null)
@@ -208,7 +218,7 @@ namespace Subsurface
while (Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.GetComponent<Wire>() != null) == null)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
}
@@ -219,7 +229,7 @@ namespace Subsurface
while (steeringConnection.Wires.FirstOrDefault(w => w != null) == null)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
@@ -228,7 +238,7 @@ namespace Subsurface
while (Character.Controlled.SelectedConstruction!=null)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(2.0f);
@@ -239,7 +249,7 @@ namespace Subsurface
while (radar.Voltage<0.1f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Great! Now we should be able to get moving.");
@@ -247,23 +257,23 @@ namespace Subsurface
while (Character.Controlled.SelectedConstruction != steering.Item)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("You can take a look at the area around the sub by pressing ''Activate Radar''.");
while (!radar.IsActive)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(0.5f);
infoBox = CreateInfoFrame("The white box in the middle is the submarine, and the white lines outside it are the walls of an underwater cavern. "
+ "Try moving the submarine by clicking somewhere inside the rectangle and draggind the pointer to the direction you want to go to.");
while (steering.CurrTargetVelocity == Vector2.Zero && steering.CurrTargetVelocity.Length() < 40.0f)
while (steering.CurrTargetVelocity == Vector2.Zero && steering.CurrTargetVelocity.Length() < 50.0f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(4.0f);
@@ -276,12 +286,14 @@ namespace Subsurface
while (Submarine.Loaded.Position.Y > 31000.0f)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
var moloch = new Character("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 15.0f);
var moloch = new Character("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 25.0f);
moloch.PlaySound(AIController.AiState.Attack);
yield return new WaitForSeconds(1.0f);
infoBox = CreateInfoFrame("Uh-oh... Something enormous just appeared on the radar.");
List<Structure> windows = new List<Structure>();
@@ -295,13 +307,15 @@ namespace Subsurface
bool broken = false;
do
{
Submarine.Loaded.Speed = Vector2.Zero;
moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget);
Vector2 steeringDir = windows[0].Position - moloch.Position;
if (steeringDir != Vector2.Zero) steeringDir = Vector2.Normalize(steeringDir);
foreach (Limb limb in moloch.AnimController.limbs)
{
limb.body.LinearVelocity = new Vector2(limb.LinearVelocity.X, limb.LinearVelocity.Y + steeringDir.Y*0.01f);
limb.body.LinearVelocity = new Vector2(limb.LinearVelocity.X, limb.LinearVelocity.Y + steeringDir.Y*10.0f);
}
moloch.AIController.Steering = steeringDir;
@@ -310,7 +324,7 @@ namespace Subsurface
{
for (int i = 0; i < window.SectionCount; i++)
{
if (!window.SectionHasHole(i)) continue;
if (!window.SectionIsLeaking(i)) continue;
broken = true;
break;
}
@@ -336,17 +350,17 @@ namespace Subsurface
Door commandDoor2 = Item.itemList.Find(i => i.HasTag("commanddoor2")).GetComponent<Door>();
Door commandDoor3 = Item.itemList.Find(i => i.HasTag("commanddoor3")).GetComponent<Door>();
while (commandDoor1.IsOpen && (commandDoor2.IsOpen || commandDoor3.IsOpen))
while (commandDoor1.IsOpen || (commandDoor2.IsOpen || commandDoor3.IsOpen))
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Great! You should find yourself an diving mask or a diving suit, in case the creature causes more damage. "+
infoBox = CreateInfoFrame("You should find yourself an diving mask or a diving suit, in case the creature causes more damage. "+
"There are some in the room next to the airlock.");
while (!HasItem("Diving Mask") && !HasItem("Diving Suit"))
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
if (HasItem("Diving Mask"))
@@ -364,7 +378,7 @@ namespace Subsurface
while (!HasItem("Oxygen Tank"))
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return new WaitForSeconds(5.0f);
@@ -393,23 +407,153 @@ namespace Subsurface
var loader = Item.itemList.Find(i => i.Name == "Railgun Loader").GetComponent<ItemContainer>();
while (Math.Abs(Character.Controlled.Position.Y - loader.Item.Position.Y)>50)
while (Math.Abs(Character.Controlled.Position.Y - loader.Item.Position.Y)>80)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Grab one of the shells. You can load it by selecting the railgun loader and dragging the shell to. "
+"one of the free slots.");
+"one of the free slots. You need two hands to carry a shell, so make sure you don't have anything else in either hand.");
while (loader.Item.ContainedItems.FirstOrDefault(i => i != null) != null)
while (loader.Item.ContainedItems.FirstOrDefault(i => i != null && i.Name == "Railgun Shell") == null)
{
capacitor1.Charge += 1.0f;
capacitor2.Charge += 1.0f;
yield return Status.Running;
moloch.Health = 50.0f;
capacitor1.Charge += 5.0f;
capacitor2.Charge += 5.0f;
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Now we're ready to shoot! Select the railgun controller.");
yield return Status.Success;
while (Character.Controlled.SelectedConstruction == null || Character.Controlled.SelectedConstruction.Name != "Railgun Controller")
{
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("Use the right mouse button to aim and left to shoot.");
while (!moloch.IsDead)
{
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("The creature has died. Now you should fix the damages in the control room: "+
"Grab a welding tool from the closet in the railgun room.");
while (!HasItem("Welding Tool"))
{
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("The welding tool requires fuel to work. Grab a welding fuel tank and attach it to the tool "+
"by dragging it into the same slot.");
do
{
var weldingTool = Character.Controlled.Inventory.items.FirstOrDefault(i => i != null && i.Name == "Welding Tool");
if (weldingTool != null &&
weldingTool.ContainedItems.FirstOrDefault(contained => contained != null && contained.Name == "Welding Fuel Tank") != null) break;
yield return CoroutineStatus.Running;
} while (true);
infoBox = CreateInfoFrame("You can aim with the tool using the right mouse button and weld using the left button. "+
"Head to the command room to fix the leaks there.");
do
{
broken = false;
foreach (Structure window in windows)
{
for (int i = 0; i < window.SectionCount; i++)
{
if (!window.SectionIsLeaking(i)) continue;
broken = true;
break;
}
if (broken) break;
}
yield return new WaitForSeconds(1.0f);
} while (broken);
infoBox = CreateInfoFrame("Great! However, there's still quite a bit of water inside the sub. It should be pumped out "
+"using the pump in the room at the bottom of the submarine.");
Pump pump = Item.itemList.Find(i => i.HasTag("tutorialpump")).GetComponent<Pump>();
while (Vector2.Distance(Character.Controlled.Position, pump.Item.Position) > 100.0f)
{
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("The two pumps inside the ballast tanks "
+"are connected straight to the navigation terminal and can't be manually controlled unless you mess with their wiring, "+
"so you should only use the pump in the middle room to pump out the water. Select it, turn it on and adjust the pumping speed "+
"to start pumping water out.");
while (pump.Item.CurrentHull.Volume>1000.0f)
{
yield return CoroutineStatus.Running;
}
infoBox = CreateInfoFrame("That was all there is to this tutorial! Now you should be able to handle "+
"most of the basic tasks on board the submarine.");
yield return new WaitForSeconds(4.0f);
float endPreviewLength = 10.0f;
DateTime endTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, (int)(1000.0f * endPreviewLength));
float secondsLeft = endPreviewLength;
Character.Controlled = null;
do
{
secondsLeft = (float)(endTime - DateTime.Now).TotalSeconds;
float camAngle = (float)((DateTime.Now - endTime).TotalSeconds / endPreviewLength) * MathHelper.TwoPi;
Vector2 offset = (new Vector2(
(float)Math.Cos(camAngle) * (Submarine.Borders.Width / 2.0f),
(float)Math.Sin(camAngle) * (Submarine.Borders.Height / 2.0f)));
Game1.GameScreen.Cam.TargetPos = offset * 0.8f;
//Game1.GameScreen.Cam.MoveCamera((float)deltaTime);
yield return CoroutineStatus.Running;
} while (secondsLeft > 0.0f);
Submarine.Unload();
Game1.MainMenuScreen.Select();
yield return CoroutineStatus.Success;
}
private IEnumerable<object> Dead()
{
yield return new WaitForSeconds(3.0f);
var messageBox = new GUIMessageBox("You have died", "Do you want to try again?", new string[] { "Yes", "No" });
messageBox.Buttons[0].OnClicked += Restart;
messageBox.Buttons[0].OnClicked += messageBox.Close;
messageBox.Buttons[1].UserData = MainMenuScreen.Tabs.Main;
messageBox.Buttons[1].OnClicked = Game1.MainMenuScreen.SelectTab;
messageBox.Buttons[1].OnClicked += messageBox.Close;
yield return CoroutineStatus.Success;
}
private bool Restart(GUIButton button, object obj)
{
TutorialMode.Start();
return true;
}
private bool HasItem(string itemName)
@@ -425,6 +569,10 @@ namespace Subsurface
{
do
{
enemy.Health = 50.0f;
enemy.AIController.State = AIController.AiState.None;
Vector2 targetPos = Character.Controlled.Position + new Vector2(0.0f, 3000.0f);
Vector2 steering = targetPos - enemy.Position;
@@ -432,10 +580,10 @@ namespace Subsurface
enemy.AIController.Steering = steering*2.0f;
yield return Status.Running;
yield return CoroutineStatus.Running;
} while (capacitors.FirstOrDefault(c => c.Charge > 0.4f) == null);
yield return Status.Success;
yield return CoroutineStatus.Success;
}
public override void Draw(SpriteBatch spriteBatch)
+1 -2
View File
@@ -175,8 +175,7 @@ namespace Subsurface
public void Draw(SpriteBatch spriteBatch)
{
guiRoot.Draw(spriteBatch);
taskManager.Draw(spriteBatch);
if (gameMode != null) gameMode.Draw(spriteBatch);
}
+27 -24
View File
@@ -45,38 +45,41 @@ namespace Subsurface
public void Load(string filePath)
{
XDocument doc = ToolBox.TryLoadXml(filePath);
try
if (doc == null)
{
XElement graphicsMode = doc.Root.Element("graphicsmode");
GraphicsWidth = int.Parse(graphicsMode.Attribute("width").Value);
GraphicsHeight = int.Parse(graphicsMode.Attribute("height").Value);
FullScreenEnabled = graphicsMode.Attribute("fullscreen").Value == "true";
DebugConsole.ThrowError("No config file found");
MasterServerUrl = ToolBox.GetAttributeString(doc.Root, "masterserverurl", "");
foreach (XElement subElement in doc.Root.Elements())
{
switch (subElement.Name.ToString().ToLower())
{
case "contentpackage":
string path = ToolBox.GetAttributeString(subElement, "path", "");
SelectedContentPackage = ContentPackage.list.Find(cp => cp.Path == path);
if (SelectedContentPackage == null) SelectedContentPackage = new ContentPackage(path);
break;
}
}
}
catch
{
GraphicsWidth = 1024;
GraphicsHeight = 768;
GraphicsHeight = 678;
MasterServerUrl = "";
SelectedContentPackage = new ContentPackage("");
return;
}
XElement graphicsMode = doc.Root.Element("graphicsmode");
GraphicsWidth = int.Parse(graphicsMode.Attribute("width").Value);
GraphicsHeight = int.Parse(graphicsMode.Attribute("height").Value);
FullScreenEnabled = graphicsMode.Attribute("fullscreen").Value == "true";
MasterServerUrl = ToolBox.GetAttributeString(doc.Root, "masterserverurl", "");
foreach (XElement subElement in doc.Root.Elements())
{
switch (subElement.Name.ToString().ToLower())
{
case "contentpackage":
string path = ToolBox.GetAttributeString(subElement, "path", "");
SelectedContentPackage = ContentPackage.list.Find(cp => cp.Path == path);
if (SelectedContentPackage == null) SelectedContentPackage = new ContentPackage(path);
break;
}
}
}
public void Save(string filePath)
@@ -53,7 +53,7 @@ namespace Subsurface.Items.Components
public override bool Use(float deltaTime, Character character = null)
{
if (character == null) return false;
if (!character.SecondaryKeyDown.State || reload > 0.0f) return false;
if (!character.GetInputState(InputType.SecondaryHeld) || reload > 0.0f) return false;
isActive = true;
reload = 1.0f;
@@ -102,7 +102,7 @@ namespace Subsurface.Items.Components
public override bool Use(float deltaTime, Character character = null)
{
if (character == null) return false;
if (!character.SecondaryKeyDown.State) return false;
if (!character.GetInputState(InputType.SecondaryHeld)) return false;
if (DoesUseFail(character)) return false;
@@ -126,9 +126,6 @@ namespace Subsurface.Items.Components
if (targetBody == null || targetBody.UserData == null) return true;
//ApplyStatusEffects(ActionType.OnUse, 1.0f, character);
Structure targetStructure;
Limb targetLimb;
Item targetItem;
@@ -143,10 +140,19 @@ namespace Subsurface.Items.Components
targetStructure.AddDamage(sectionIndex, -structureFixAmount);
//if the next section is small enough, apply the effect to it as well
//(to make it easier to fix a small "left-over" section)
int nextSectionLength = targetStructure.SectionLength(sectionIndex + 1);
if (nextSectionLength > 0 && nextSectionLength < Structure.wallSectionSize * 0.3f)
{
targetStructure.HighLightSection(sectionIndex + 1);
targetStructure.AddDamage(sectionIndex + 1, -structureFixAmount);
}
}
else if ((targetLimb = (targetBody.UserData as Limb)) != null)
{
if (character.SecondaryKeyDown.State)
if (character.GetInputState(InputType.SecondaryHeld))
{
targetLimb.character.Health += limbFixAmount;
//isActive = true;
@@ -28,7 +28,7 @@ namespace Subsurface.Items.Components
public override bool Use(float deltaTime, Character character = null)
{
if (character == null) return false;
if (!character.SecondaryKeyDown.State || throwing) return false;
if (!character.GetInputState(InputType.SecondaryHeld) || throwing) return false;
throwing = true;
@@ -60,7 +60,7 @@ namespace Subsurface.Items.Components
if (!item.body.Enabled) return;
if (!picker.HasSelectedItem(item)) isActive = false;
if (!picker.SecondaryKeyDown.State && !throwing) throwPos = 0.0f;
if (!picker.GetInputState(InputType.SecondaryHeld) && !throwing) throwPos = 0.0f;
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
@@ -223,7 +223,7 @@ namespace Subsurface.Items.Components
case "sound":
string filePath = ToolBox.GetAttributeString(subElement, "file", "");
if (filePath=="") continue;
if (!filePath.Contains("\\")) filePath = Path.GetDirectoryName(item.Prefab.ConfigFile)+"\\"+filePath;
if (!filePath.Contains("/")) filePath = Path.GetDirectoryName(item.Prefab.ConfigFile)+"/"+filePath;
ActionType type;
@@ -594,7 +594,7 @@ namespace Subsurface.Items.Components
try
{
// Get the type of a specified class.
t = Type.GetType("Subsurface.Items.Components." + type + ", Subsurface", false, true);
t = Type.GetType("Subsurface.Items.Components." + type + "", false, true);
if (t == null)
{
if (errorMessages) DebugConsole.ThrowError("Could not find the component ''" + type + "'' (" + file + ")");
@@ -67,17 +67,17 @@ namespace Subsurface.Items.Components
GUI.DrawRectangle(spriteBatch, hullRect, Color.White);
}
foreach (Character c in Character.CharacterList)
{
if (c.AnimController.CurrentHull!=null) continue;
//foreach (Character c in Character.CharacterList)
//{
// if (c.AnimController.CurrentHull!=null) continue;
Rectangle characterRect = new Rectangle(
miniMap.X + (int)((c.Position.X - Submarine.Borders.X) * size),
miniMap.Y - (int)((c.Position.Y - Submarine.Borders.Y) * size),
5, 5);
// Rectangle characterRect = new Rectangle(
// miniMap.X + (int)((c.Position.X - Submarine.Borders.X) * size),
// miniMap.Y - (int)((c.Position.Y - Submarine.Borders.Y) * size),
// 5, 5);
GUI.DrawRectangle(spriteBatch, characterRect, Color.White, true);
}
// GUI.DrawRectangle(spriteBatch, characterRect, Color.White, true);
//}
}
}
@@ -17,7 +17,7 @@ namespace Subsurface.Items.Components
Hull hull1, hull2;
[HasDefaultValue(0.0f, true)]
private float FlowPercentage
public float FlowPercentage
{
get { return flowPercentage; }
set
@@ -116,21 +116,18 @@ namespace Subsurface.Items.Components
item.NewComponentEvent(this, true);
}
spriteBatch.DrawString(GUI.Font, "Flow percentage: " + (int)flowPercentage + " %", new Vector2(x + 20, y + 80), Color.White);
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 200, y + 70, 40, 40), "+", false))
{
FlowPercentage += 10.0f;
item.NewComponentEvent(this, true);
}
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 250, y + 70, 40, 40), "-", false))
spriteBatch.DrawString(GUI.Font, "Pumping speed: " + (int)flowPercentage + " %", new Vector2(x + 20, y + 80), Color.White);
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 200, y + 70, 40, 40), "OUT", false))
{
FlowPercentage -= 10.0f;
item.NewComponentEvent(this, true);
}
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 250, y + 70, 40, 40), "IN", false))
{
FlowPercentage += 10.0f;
item.NewComponentEvent(this, true);
}
}
public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f)
@@ -10,7 +10,7 @@ using System.Xml.Linq;
namespace Subsurface.Items.Components
{
class Steering : ItemComponent
class Steering : Powered
{
private Vector2 currVelocity;
private Vector2 targetVelocity;
@@ -67,7 +67,9 @@ namespace Subsurface.Items.Components
public override void Update(float deltaTime, Camera cam)
{
base.Update(deltaTime, cam);
//base.Update(deltaTime, cam);
//if (voltage < minVoltage) return;
if (autoPilot)
{
@@ -112,6 +114,8 @@ namespace Subsurface.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
//if (voltage < minVoltage) return;
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
+1 -18
View File
@@ -75,7 +75,7 @@ namespace Subsurface.Items.Components
{
isActive = true;
barrelSprite = new Sprite(Path.GetDirectoryName(item.Prefab.ConfigFile) + "\\" +element.Attribute("barrelsprite").Value,
barrelSprite = new Sprite(Path.GetDirectoryName(item.Prefab.ConfigFile) + "/" +element.Attribute("barrelsprite").Value,
ToolBox.GetAttributeVector2(element, "origin", Vector2.Zero));
}
@@ -99,23 +99,8 @@ namespace Subsurface.Items.Components
}
rotation = MathUtils.CurveAngle(rotation, targetRotation, 0.05f);
}
//public override void SecondaryUse(float deltaTime, Character character = null)
//{
// if (character == null) return;
// Vector2 centerPos = new Vector2(item.Rect.X + barrelPos.X, item.Rect.Y - barrelPos.Y);
// if (character == Character.Controlled && cam!=null)
// {
// Lights.LightManager.ViewPos = centerPos;
// cam.TargetPos = new Vector2(item.Rect.X + barrelPos.X, item.Rect.Y - barrelPos.Y);
// }
//}
public override bool Use(float deltaTime, Character character = null)
{
if (reload > 0.0f) return false;
@@ -174,8 +159,6 @@ namespace Subsurface.Items.Components
projectile.body.Enabled = true;
projectile.SetTransform(ConvertUnits.ToSimUnits(new Vector2(item.Rect.X + barrelPos.X, item.Rect.Y - barrelPos.Y)), -rotation);
//if (useSounds.Count() > 0) useSounds[Game1.localRandom.Next(useSounds.Count())].Play(1.0f, 800.0f, item.body.FarseerBody);
projectileComponent.Use(deltaTime);
item.RemoveContained(projectile);
@@ -50,7 +50,7 @@ namespace Subsurface.Items.Components
}
string spritePath = subElement.Attribute("texture").Value;
spritePath = Path.GetDirectoryName( item.Prefab.ConfigFile)+"\\"+spritePath;
spritePath = Path.GetDirectoryName( item.Prefab.ConfigFile)+"/"+spritePath;
var sprite = new Sprite(subElement, "", spritePath);
wearableSprite[i] = new WearableSprite(sprite, ToolBox.GetAttributeBool(subElement, "hidelimb", false));
+4 -4
View File
@@ -126,10 +126,10 @@ namespace Subsurface
}
}
public AITarget AiTarget
{
get { return aiTarget; }
}
//public override AITarget AiTarget
//{
// get { return aiTarget; }
//}
public bool Updated
{
+2 -2
View File
@@ -129,12 +129,12 @@ namespace Subsurface
currBrightness -= 0.1f;
yield return Status.Running;
yield return CoroutineStatus.Running;
}
light.Remove();
yield return Status.Success;
yield return CoroutineStatus.Success;
}
}
}
+14 -6
View File
@@ -249,12 +249,20 @@ namespace Subsurface
{
pos.Y = ConvertUnits.ToSimUnits(MathHelper.Clamp(lowerSurface, rect.Y-rect.Height, rect.Y));
Game1.ParticleManager.CreateParticle("watersplash",
var particle = Game1.ParticleManager.CreateParticle("watersplash",
new Vector2(pos.X, pos.Y - Rand.Range(0.0f, 0.1f)),
new Vector2(flowForce.X * Rand.Range(0.005f, 0.007f), flowForce.Y * Rand.Range(0.005f, 0.007f)));
new Vector2(
MathHelper.Clamp(flowForce.X, -5000.0f, 5000.0f) * Rand.Range(0.005f, 0.007f),
flowForce.Y * Rand.Range(0.005f, 0.007f)));
if (particle!=null)
{
particle.Size = particle.Size * Math.Abs(flowForce.X / 1000.0f);
}
pos.Y = ConvertUnits.ToSimUnits(Rand.Range(lowerSurface, rect.Y - rect.Height));
Game1.ParticleManager.CreateParticle("bubbles", pos, flowForce / 200.0f);
Game1.ParticleManager.CreateParticle("bubbles", pos, flowForce / 200.0f);
}
else
{
@@ -312,7 +320,7 @@ namespace Subsurface
flowTargetHull = hull1;
//make sure not to move more than what the room contains
delta = Math.Min((hull2.Pressure - hull1.Pressure) * sizeModifier, Math.Min(hull2.Volume, hull2.FullVolume));
delta = Math.Min((hull2.Pressure - hull1.Pressure) * 5.0f * sizeModifier, Math.Min(hull2.Volume, hull2.FullVolume));
//make sure not to place more water to the target room than it can hold
delta = Math.Min(delta, hull1.FullVolume + Hull.MaxCompress - (hull1.Volume));
@@ -331,7 +339,7 @@ namespace Subsurface
flowTargetHull = hull2;
//make sure not to move more than what the room contains
delta = Math.Min((hull1.Pressure - hull2.Pressure) * sizeModifier, Math.Min(hull1.Volume, hull1.FullVolume));
delta = Math.Min((hull1.Pressure - hull2.Pressure) * 5.0f * sizeModifier, Math.Min(hull1.Volume, hull1.FullVolume));
//make sure not to place more water to the target room than it can hold
delta = Math.Min(delta, hull2.FullVolume + Hull.MaxCompress - (hull2.Volume));
@@ -405,7 +413,7 @@ namespace Subsurface
flowTargetHull = hull2;
//make sure the amount of water moved isn't more than what the room contains
float delta = Math.Min(hull1.Volume, deltaTime * 10000f * sizeModifier);
float delta = Math.Min(hull1.Volume, deltaTime * 25000f * sizeModifier);
//make sure not to place more water to the target room than it can hold
delta = Math.Min(delta, (hull2.FullVolume + Math.Max(hull1.Volume - hull1.FullVolume, 0.0f)) - hull2.Volume + Hull.MaxCompress / 4.0f);
+3 -3
View File
@@ -122,8 +122,8 @@ namespace Subsurface
public static Level CreateRandom(LocationConnection locationConnection)
{
int seed = locationConnection.Locations[0].GetHashCode() | locationConnection.Locations[1].GetHashCode();
return new Level(seed.ToString(), locationConnection.Difficulty, 100000, 40000, 2000);
string seed = locationConnection.Locations[0].Name + locationConnection.Locations[1].Name;
return new Level(seed, locationConnection.Difficulty, 100000, 40000, 2000);
}
public static Level CreateRandom(string seed = "")
@@ -153,7 +153,7 @@ namespace Subsurface
bodies = new List<Body>();
Random rand = new Random(seed.GetHashCode());
Random rand = new Random(ToolBox.StringToInt(seed));
float siteVariance = siteInterval * 0.8f;
for (int x = siteInterval / 2; x < borders.Width; x += siteInterval)
+1 -1
View File
@@ -119,7 +119,7 @@ namespace Subsurface.Lights
shadowEffect.TextureEnabled = true;
//shadowEffect.VertexColorEnabled = true;
shadowEffect.LightingEnabled = false;
shadowEffect.Texture = Game1.TextureLoader.FromFile("Content/lights/penumbra.png");
shadowEffect.Texture = Game1.TextureLoader.FromFile("Content/Lights/penumbra.png");
}
//compute facing of each edge, using N*L
+2 -2
View File
@@ -72,7 +72,7 @@ namespace Subsurface
if (iceCraters == null) iceCraters = Game1.TextureLoader.FromFile("Content/Map/iceCraters.png");
if (iceCrack == null) iceCrack = Game1.TextureLoader.FromFile("Content/Map/iceCrack.png");
Rand.SetSyncedSeed(this.seed.GetHashCode());
Rand.SetSyncedSeed(ToolBox.StringToInt(this.seed));
GenerateLocations();
@@ -126,7 +126,7 @@ namespace Subsurface
newLocations[i] = Location.CreateRandom(position);
locations.Add(newLocations[i]);
}
int seed = (newLocations[0].GetHashCode() | newLocations[1].GetHashCode());
//int seed = (newLocations[0].GetHashCode() | newLocations[1].GetHashCode());
connections.Add(new LocationConnection(newLocations[0], newLocations[1]));
}
+5
View File
@@ -59,6 +59,11 @@ namespace Subsurface
shortHash = GetShortHash(hash);
}
public override string ToString()
{
return hash;
}
private string CalculateHash(FileStream stream)
{
MD5 md5 = MD5.Create();
+43 -13
View File
@@ -38,7 +38,7 @@ namespace Subsurface
class Structure : MapEntity, IDamageable
{
static int wallSectionSize = 100;
public static int wallSectionSize = 100;
public static List<Structure> wallList = new List<Structure>();
ConvexHull convexHull;
@@ -97,12 +97,7 @@ namespace Subsurface
{
get { return prefab.MaxHealth; }
}
public AITarget AiTarget
{
get { return null;}
}
public override void Move(Vector2 amount)
{
base.Move(amount);
@@ -368,6 +363,20 @@ namespace Subsurface
return (sections[sectionIndex].damage>=prefab.MaxHealth);
}
public bool SectionIsLeaking(int sectionIndex)
{
if (sectionIndex < 0 || sectionIndex >= sections.Length) return false;
return (sections[sectionIndex].damage >= prefab.MaxHealth*0.5f);
}
public int SectionLength(int sectionIndex)
{
if (sectionIndex < 0 || sectionIndex >= sections.Length) return 0;
return (isHorizontal ? sections[sectionIndex].rect.Width : sections[sectionIndex].rect.Height);
}
public void AddDamage(int sectionIndex, float damage)
{
if (!prefab.HasBody || prefab.IsPlatform) return;
@@ -428,7 +437,7 @@ namespace Subsurface
if (!prefab.HasBody) return;
if (damage != sections[sectionIndex].damage)
new NetworkEvent(ID, false);
new NetworkEvent(NetworkEventType.UpdateEntity, ID, false, sectionIndex);
if (damage < prefab.MaxHealth*0.5f)
{
@@ -615,19 +624,40 @@ namespace Subsurface
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
{
for (int i = 0; i < sections.Length; i++ )
int sectionIndex = 0;
byte byteIndex = 0;
try
{
message.Write(sections[i].damage);
sectionIndex = (int)data;
byteIndex = (byte)sectionIndex;
}
catch
{
return;
}
message.Write(byteIndex);
message.Write(sections[sectionIndex].damage);
}
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
{
for (int i = 0; i < sections.Length; i++)
int sectionIndex = 0;
float damage = 0.0f;
try
{
float damage = message.ReadFloat();
if (damage != sections[i].damage) SetDamage(i, damage);
sectionIndex = message.ReadByte();
damage = message.ReadFloat();
}
catch
{
return;
}
SetDamage(sectionIndex, damage);
}
}
+7 -2
View File
@@ -76,7 +76,7 @@ namespace Subsurface
private set;
}
public Md5Hash Hash
public Md5Hash MD5Hash
{
get
{
@@ -115,6 +115,11 @@ namespace Subsurface
public Vector2 Speed
{
get { return speed; }
set
{
if (!MathUtils.IsValid(value)) return;
speed = value;
}
}
public string FilePath
@@ -773,7 +778,7 @@ namespace Subsurface
try
{
// Get the type of a specified class.
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
t = Type.GetType("Subsurface." + typeName, true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.");
+6 -1
View File
@@ -56,8 +56,13 @@ namespace Subsurface
//vertexBuffer.SetData(vertices);
//effect = Game1.game.Content.Load<Effect>("effects");
#if WINDOWS
byte[] bytecode = File.ReadAllBytes("Content/effects.mgfx");
#endif
#if LINUX
byte[] bytecode = File.ReadAllBytes("Content/effects_linux.mgfx");
#endif
byte[] bytecode = File.ReadAllBytes("Content/effects.mgfx");
effect = new Effect(graphicsDevice, bytecode);
//Texture2D waterBumpMap = Game1.textureLoader.FromFile("Content/waterbump.jpg");
+12 -36
View File
@@ -10,9 +10,6 @@ namespace Subsurface.Networking
{
private NetClient client;
private Character myCharacter;
private CharacterInfo characterInfo;
private GUIMessageBox reconnectBox;
private bool connected;
@@ -23,17 +20,6 @@ namespace Subsurface.Networking
private string serverIP;
public Character Character
{
get { return myCharacter; }
set { myCharacter = value; }
}
public CharacterInfo CharacterInfo
{
get { return characterInfo; }
}
public int ID
{
get { return myID; }
@@ -56,7 +42,7 @@ namespace Subsurface.Networking
if (address.Length==1)
{
serverIP = hostIP;
Port = DefaultPort;
Port = NetConfig.DefaultPort;
}
else
{
@@ -65,7 +51,7 @@ namespace Subsurface.Networking
if (!int.TryParse(address[1], out Port))
{
DebugConsole.ThrowError("Invalid port: "+address[1]+"!");
Port = DefaultPort;
Port = NetConfig.DefaultPort;
}
}
@@ -151,10 +137,10 @@ namespace Subsurface.Networking
DateTime timeOut = DateTime.Now + new TimeSpan(0,0,15);
// Loop untill we are approved
// Loop until we are approved
while (!CanStart)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
if (DateTime.Now > timeOut) break;
@@ -171,7 +157,7 @@ namespace Subsurface.Networking
if (packetType == (byte)PacketTypes.LoggedIn)
{
myID = inc.ReadInt32();
if (inc.ReadBoolean())
if (inc.ReadBoolean() && Screen.Selected != Game1.GameScreen)
{
new GUIMessageBox("Please wait", "A round is already running. You will have to wait for a new round to start.");
}
@@ -234,11 +220,11 @@ namespace Subsurface.Networking
}
else
{
if (Screen.Selected == Game1.MainMenuScreen) Game1.NetLobbyScreen.Select();
if (Screen.Selected != Game1.GameScreen) Game1.NetLobbyScreen.Select();
connected = true;
}
yield return Status.Success;
yield return CoroutineStatus.Success;
}
public override void Update(float deltaTime)
@@ -274,17 +260,7 @@ namespace Subsurface.Networking
}
else if (gameStarted)
{
Vector2 charMovement = myCharacter.AnimController.TargetMovement;
if ((charMovement==Vector2.Zero || charMovement.Length()<0.001f) &&
!myCharacter.ActionKeyDown.State && !myCharacter.SecondaryKeyDown.State)
{
new NetworkEvent(NetworkEventType.NotMoving, myCharacter.ID, true);
}
else
{
new NetworkEvent(myCharacter.ID, true);
}
new NetworkEvent(myCharacter.ID, true);
}
}
@@ -335,7 +311,7 @@ namespace Subsurface.Networking
if (this.Character != null) Character.Remove();
int seed = inc.ReadInt32();
Rand.SetSyncedSeed(seed);
string levelSeed = inc.ReadString();
@@ -347,7 +323,7 @@ namespace Subsurface.Networking
double durationMinutes = inc.ReadDouble();
TimeSpan duration = new TimeSpan(0,(int)durationMinutes,0);
Rand.SetSyncedSeed(seed);
//int gameModeIndex = inc.ReadInt32();
Game1.GameSession = new GameSession(Submarine.Loaded, "", Game1.NetLobbyScreen.SelectedMode);
Game1.GameSession.StartShift(duration, levelSeed);
@@ -456,7 +432,7 @@ namespace Subsurface.Networking
//Game1.GameScreen.Cam.MoveCamera((float)deltaTime);
messageBox.Text = endMessage + "\nReturning to lobby in " + (int)secondsLeft + " s";
yield return Status.Running;
yield return CoroutineStatus.Running;
} while (secondsLeft > 0.0f);
messageBox.Text = endMessage;
@@ -469,7 +445,7 @@ namespace Subsurface.Networking
myCharacter = null;
yield return Status.Success;
yield return CoroutineStatus.Success;
}
+63 -38
View File
@@ -13,10 +13,12 @@ namespace Subsurface.Networking
public List<Client> connectedClients = new List<Client>();
bool started;
private NetServer server;
private NetPeerConfiguration config;
private TimeSpan SparseUpdateInterval = new TimeSpan(0, 0, 0, 1);
private TimeSpan SparseUpdateInterval = new TimeSpan(0, 0, 0, 3);
private DateTime sparseUpdateTimer;
private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 40);
@@ -36,7 +38,6 @@ namespace Subsurface.Networking
endRoundButton.OnClicked = EndButtonHit;
this.name = name;
this.password = password;
config = new NetPeerConfiguration("subsurface");
@@ -45,7 +46,6 @@ namespace Subsurface.Networking
config.SimulatedLoss = 0.2f;
config.SimulatedMinimumLatency = 0.3f;
#endif
config.Port = port;
Port = port;
@@ -56,25 +56,52 @@ namespace Subsurface.Networking
config.MaximumConnections = maxPlayers;
config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
| NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);
config.DisableMessageType(NetIncomingMessageType.DebugMessage |
NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt |
NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
CoroutineManager.StartCoroutine(StartServer(isPublic));
}
private IEnumerable<object> StartServer(bool isPublic)
{
try
{
server = new NetServer(config);
server = new NetServer(config);
server.Start();
if (attemptUPnP)
{
server.UPnP.ForwardPort(port, "subsurface");
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't start the server", e);
DebugConsole.ThrowError("Couldn't start the server", e);
}
if (config.EnableUPnP)
{
server.UPnP.ForwardPort(config.Port, "subsurface");
GUIMessageBox upnpBox = new GUIMessageBox("Please wait...", "Attempting UPnP port forwarding", new string[] {"Cancel"} );
upnpBox.Buttons[0].OnClicked = upnpBox.Close;
DateTime upnpTimeout = DateTime.Now + new TimeSpan(0,0,5);
while (server.UPnP.Status == UPnPStatus.Discovering
&& GUIMessageBox.VisibleBox == upnpBox)// && upnpTimeout>DateTime.Now)
{
yield return null;
}
upnpBox.Close(null,null);
if (server.UPnP.Status == UPnPStatus.NotAvailable)
{
new GUIMessageBox("Error", "UPnP not available");
}
else if (server.UPnP.Status == UPnPStatus.Discovering)
{
new GUIMessageBox("Error", "UPnP discovery timed out");
}
}
if (isPublic)
@@ -86,11 +113,15 @@ namespace Subsurface.Networking
updateInterval = new TimeSpan(0, 0, 0, 0, 30);
DebugConsole.NewMessage("Server started", Color.Green);
Game1.NetLobbyScreen.Select();
started = true;
yield return CoroutineStatus.Success;
}
private void RegisterToMasterServer()
{
var client = new RestClient(NetworkMember.MasterServerUrl);
var client = new RestClient(NetConfig.MasterServerUrl);
var request = new RestRequest("masterserver.php", Method.GET);
request.AddParameter("action", "addserver");
@@ -120,7 +151,7 @@ namespace Subsurface.Networking
private IEnumerable<object> RefreshMaster()
{
var client = new RestClient(NetworkMember.MasterServerUrl);
var client = new RestClient(NetConfig.MasterServerUrl);
var request = new RestRequest("masterserver.php", Method.GET);
request.AddParameter("action", "refreshserver");
@@ -146,10 +177,10 @@ namespace Subsurface.Networking
}
System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms");
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return Status.Success;
yield return CoroutineStatus.Success;
}
private void MasterServerCallBack(IRestResponse response)
@@ -173,6 +204,8 @@ namespace Subsurface.Networking
public override void Update(float deltaTime)
{
if (!started) return;
base.Update(deltaTime);
if (gameStarted) inGameHUD.Update((float)Physics.step);
@@ -298,7 +331,7 @@ namespace Subsurface.Networking
}
int id = 1;
while (connectedClients.Find(c=>c.ID==id)!=null)
while (connectedClients.Find(c => c.ID==id)!=null)
{
id++;
}
@@ -458,26 +491,17 @@ namespace Subsurface.Networking
List<NetConnection> recipients = new List<NetConnection>();
if (!networkEvent.IsImportant)
{
Entity e = Entity.FindEntityByID(networkEvent.ID);
foreach (Client c in connectedClients)
{
if (c.character==null) continue;
if (Vector2.Distance(e.SimPosition, c.character.SimPosition) > 2000.0f) continue;
recipients.Add(c.Connection);
}
}
else
{
foreach (Client c in connectedClients)
{
if (c.character == null) continue;
//if (networkEvent.Type == NetworkEventType.UpdateEntity &&
// Vector2.Distance(e.SimPosition, c.character.SimPosition) > NetConfig.UpdateEntityDistance) continue;
recipients.Add(c.Connection);
}
}
if (recipients.Count == 0) return;
@@ -510,13 +534,14 @@ namespace Subsurface.Networking
return false;
}
int seed = DateTime.Now.Millisecond;
Rand.SetSyncedSeed(seed);
AssignJobs();
//selectedMap.Load();
int seed = DateTime.Now.Millisecond;
Rand.SetSyncedSeed(seed);
Game1.GameSession = new GameSession(selectedMap, "", Game1.NetLobbyScreen.SelectedMode);
Game1.GameSession.StartShift(Game1.NetLobbyScreen.GameDuration, Game1.NetLobbyScreen.LevelSeed);
//EventManager.SelectEvent(Game1.netLobbyScreen.SelectedEvent);
@@ -570,7 +595,7 @@ namespace Subsurface.Networking
msg.Write(Game1.NetLobbyScreen.LevelSeed);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Name);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Hash.Hash);
msg.Write(Game1.NetLobbyScreen.SelectedMap.MD5Hash.Hash);
msg.Write(Game1.NetLobbyScreen.GameDuration.TotalMinutes);
@@ -651,7 +676,7 @@ namespace Subsurface.Networking
Game1.GameScreen.Cam.TargetPos = offset * 0.8f;
//Game1.GameScreen.Cam.MoveCamera((float)deltaTime);
yield return Status.Running;
yield return CoroutineStatus.Running;
} while (secondsLeft > 0.0f);
Submarine.Unload();
@@ -660,7 +685,7 @@ namespace Subsurface.Networking
DebugConsole.ThrowError(endMessage);
yield return Status.Success;
yield return CoroutineStatus.Success;
}
@@ -674,7 +699,7 @@ namespace Subsurface.Networking
{
if (client == null) return;
if (gameStarted && client.character != null) client.character.Kill(true);
if (gameStarted && client.character != null) client.character.ClearInputs();
if (msg == "") msg = client.name + " has left the server";
if (targetmsg == "") targetmsg = "You have left the server";
@@ -742,7 +767,7 @@ namespace Subsurface.Networking
GUI.DrawRectangle(spriteBatch, new Rectangle(x,y,width,height), Color.Black*0.7f, true);
spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x+10, y+10), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + server.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
+24
View File
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Subsurface.Networking
{
static class NetConfig
{
public const int DefaultPort = 14242;
//UpdateEntity networkevents aren't sent to clients if they're further than this from the entity
public const float UpdateEntityDistance = 2500.0f;
public static string MasterServerUrl = Game1.Config.MasterServerUrl;
//if a ragdoll is further than this from the correct position, teleport it there
//(in sim units)
public const float ResetRagdollDistance = 2.0f;
//if the ragdoll is closer than this, don't try to correct its position
public const float AllowedRagdollDistance = 0.1f;
}
}
+8 -4
View File
@@ -11,8 +11,7 @@ namespace Subsurface.Networking
DropItem = 3,
InventoryUpdate = 4,
PickItem = 5,
UpdateProperty = 6,
NotMoving = 7
UpdateProperty = 6
}
class NetworkEvent
@@ -46,6 +45,11 @@ namespace Subsurface.Networking
get { return isImportant[(int)eventType]; }
}
public NetworkEventType Type
{
get { return eventType; }
}
public NetworkEvent(int id, bool isClient)
: this(NetworkEventType.UpdateEntity, id, isClient)
{
@@ -64,9 +68,9 @@ namespace Subsurface.Networking
eventType = type;
foreach (NetworkEvent e in events)
if (!isImportant[(int)type])
{
if (!isImportant[(int)type] && e.id == id && e.eventType == type) return;
if (events.Find(e => e.id == id && e.eventType == type) != null) return;
}
this.id = id;
+15 -3
View File
@@ -31,9 +31,6 @@ namespace Subsurface.Networking
class NetworkMember
{
public const int DefaultPort = 14242;
public static string MasterServerUrl = Game1.Config.MasterServerUrl;
protected static Color[] messageColor = { Color.White, Color.Red, Color.LightBlue, Color.LightGreen };
@@ -54,6 +51,21 @@ namespace Subsurface.Networking
protected bool gameStarted;
protected Character myCharacter;
protected CharacterInfo characterInfo;
public Character Character
{
get { return myCharacter; }
set { myCharacter = value; }
}
public CharacterInfo CharacterInfo
{
get { return characterInfo; }
set { characterInfo = value; }
}
public string Name
{
get { return name; }
+2 -2
View File
@@ -32,9 +32,9 @@ namespace Subsurface.Particles
private float checkCollisionTimer;
public bool InWater
public ParticlePrefab.DrawTargetType DrawTarget
{
get { return prefab.inWater; }
get { return prefab.DrawTarget; }
}
public Vector2 yLimits
@@ -95,14 +95,15 @@ namespace Subsurface.Particles
public void Draw(SpriteBatch spriteBatch, bool inWater)
{
ParticlePrefab.DrawTargetType drawTarget = inWater ? ParticlePrefab.DrawTargetType.Water : ParticlePrefab.DrawTargetType.Air;
for (int i = 0; i < particleCount; i++)
{
if (particles[i].InWater != inWater) continue;
if (!particles[i].DrawTarget.HasFlag(drawTarget)) continue;
particles[i].Draw(spriteBatch);
}
}
}
}
+17 -3
View File
@@ -5,6 +5,8 @@ namespace Subsurface.Particles
{
class ParticlePrefab
{
public enum DrawTargetType { Air = 1, Water = 2, Both = 3 }
public readonly string name;
public readonly Sprite sprite;
@@ -27,7 +29,7 @@ namespace Subsurface.Particles
public readonly Vector2 velocityChange;
public readonly bool inWater;
public readonly DrawTargetType DrawTarget;
public readonly bool rotateToDirection;
@@ -67,8 +69,20 @@ namespace Subsurface.Particles
rotateToDirection = ToolBox.GetAttributeBool(element, "rotatetodirection", false);
inWater = ToolBox.GetAttributeBool(element, "inwater", false);
switch (ToolBox.GetAttributeString(element, "drawtarget", "air").ToLower())
{
case "air":
default:
DrawTarget = DrawTargetType.Air;
break;
case "water":
DrawTarget = DrawTargetType.Water;
break;
case "both":
DrawTarget = DrawTargetType.Both;
break;
}
}
}
}
+4 -4
View File
@@ -49,7 +49,7 @@ namespace Subsurface
get { return targetPosition; }
set
{
if (float.IsNaN(value.X) || float.IsNaN(value.Y)) return;
if (!MathUtils.IsValid(value)) return;
targetPosition.X = MathHelper.Clamp(value.X, -10000.0f, 10000.0f);
targetPosition.Y = MathHelper.Clamp(value.Y, -10000.0f, 10000.0f);
}
@@ -60,7 +60,7 @@ namespace Subsurface
get { return targetVelocity; }
set
{
if (float.IsNaN(value.X) || float.IsNaN(value.Y)) return;
if (!MathUtils.IsValid(value)) return;
targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f);
targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f);
}
@@ -71,7 +71,7 @@ namespace Subsurface
get { return targetRotation; }
set
{
if (float.IsNaN(value) || float.IsInfinity(value)) return;
if (!MathUtils.IsValid(value)) return;
targetRotation = value;
}
}
@@ -81,7 +81,7 @@ namespace Subsurface
get { return targetAngularVelocity; }
set
{
if (float.IsNaN(value) || float.IsInfinity(value)) return;
if (!MathUtils.IsValid(value)) return;
targetAngularVelocity = value;
}
}
+15
View File
@@ -3,10 +3,25 @@ using Microsoft.Xna.Framework.Input;
namespace Subsurface
{
public enum InputType
{
Select,
ActionHit, ActionHeld,
SecondaryHit, SecondaryHeld,
Left, Right, Up, Down,
Run
}
class Key
{
private bool state, stateQueue;
private bool canBeHeld;
public bool CanBeHeld
{
get { return canBeHeld; }
}
public Key(bool canBeHeld)
{
+73 -1
View File
@@ -1,6 +1,12 @@
#region Using Statements
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Management;
using System.Windows.Forms;
#endregion
@@ -19,7 +25,73 @@ namespace Subsurface
static void Main()
{
using (var game = new Game1())
game.Run();
{
#if !DEBUG
try
{
#endif
game.Run();
#if !DEBUG
}
catch (Exception e)
{
CrashDump(game, "crashreport.txt", e);
}
#endif
}
}
static void CrashDump(Game1 game, string filePath, Exception exception)
{
StreamWriter sw = new StreamWriter(filePath);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Subsurface crash report (generated on " + DateTime.Now + ")");
sb.AppendLine("\n");
sb.AppendLine("Subsurface seems to have crashed. Sorry for the inconvenience! ");
sb.AppendLine("If you'd like to help fix the bug that caused the crash, please send this file to the developers on the Undertow Games forums.");
sb.AppendLine("\n");
sb.AppendLine("Subsurface version " + Game1.Version);
sb.AppendLine("Selected content package: "+Game1.SelectedPackage.Name);
sb.AppendLine("Level seed: "+ ((Level.Loaded == null) ? "no level loaded" : Level.Loaded.Seed));
sb.AppendLine("Loaded submarine: " + ((Submarine.Loaded == null) ? "none" : Submarine.Loaded.Name +" ("+Submarine.Loaded.MD5Hash+")"));
sb.AppendLine("Selected screen: " + Screen.Selected.ToString());
if (Game1.Server != null)
{
sb.AppendLine("Server (" +(Game1.Server.GameStarted ? "Round had started" : "Round hand't been started"));
}
else if (Game1.Client != null)
{
sb.AppendLine("Server (" +(Game1.Client.GameStarted ? "Round had started" : "Round hand't been started"));
}
sb.AppendLine("\n");
sb.AppendLine("System info:");
sb.AppendLine(" Operating system: " + System.Environment.OSVersion + (System.Environment.Is64BitOperatingSystem ? " 64 bit" : " x86"));
sb.AppendLine(" Graphics device handle: " + game.GraphicsDevice.Handle.ToString());
sb.AppendLine("\n");
sb.AppendLine("Exception: "+exception.Message);
sb.AppendLine("Target site: " +exception.TargetSite.ToString());
sb.AppendLine("Stack trace: ");
sb.AppendLine(exception.StackTrace);
sb.AppendLine("\n");
sb.AppendLine("Last debug messages:");
for (int i = DebugConsole.messages.Count - 1; i > 0 && i > DebugConsole.messages.Count - 10; i-- )
{
sb.AppendLine(" "+DebugConsole.messages[i].Time+" - "+DebugConsole.messages[i].Text);
}
sw.WriteLine(sb.ToString());
MessageBox.Show( "A crash report (''crashreport.txt'') was saved in the root folder of the game."+
" If you'd like to help fix this bug, please make a bug report on the Undertow Games forum with the report attached.",
"Oops! Subsurface just crashed.", MessageBoxButtons.OK, MessageBoxIcon.Error);
sw.Close();
}
}
#endif
+4 -4
View File
@@ -118,7 +118,7 @@ namespace Subsurface
new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server port:", GUI.style, Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tabs.HostServer]);
portBox = new GUITextBox(new Rectangle(160, 100, 200, 30), null, null, Alignment.TopLeft, Alignment.Left, GUI.style, menuTabs[(int)Tabs.HostServer]);
portBox.Text = NetworkMember.DefaultPort.ToString();
portBox.Text = NetConfig.DefaultPort.ToString();
portBox.ToolTip = "Server port";
new GUITextBlock(new Rectangle(0, 150, 100, 30), "Max players:", GUI.style, Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tabs.HostServer]);
@@ -210,7 +210,7 @@ namespace Subsurface
int port;
if (!int.TryParse(portBox.Text, out port) || port < 0 || port > 65535)
{
portBox.Text = NetworkMember.DefaultPort.ToString();
portBox.Text = NetConfig.DefaultPort.ToString();
portBox.Flash();
return false;
@@ -219,7 +219,7 @@ namespace Subsurface
Game1.NetworkMember = new GameServer(name, port, isPublicBox.Selected, passwordBox.Text, useUpnpBox.Selected, int.Parse(maxPlayersBox.Text));
Game1.NetLobbyScreen.IsServer = true;
Game1.NetLobbyScreen.Select();
//Game1.NetLobbyScreen.Select();
return true;
}
@@ -320,7 +320,7 @@ namespace Subsurface
}
private void RemoveSaveFrame()
{
{
GUIComponent prevFrame = null;
foreach (GUIComponent child in menuTabs[(int)Tabs.LoadGame].children)
{
+52 -12
View File
@@ -279,23 +279,44 @@ namespace Subsurface
durationBar.OnMoved = Game1.Server.UpdateNetLobby;
if (subList.CountChildren > 0) subList.Select(-1);
if (GameModePreset.list.Count > 0) modeList.Select(0);
if (GameModePreset.list.Count > 0) modeList.Select(0);
var playYourself = new GUITickBox(new Rectangle(0, -20, 20, 20), "Play yourself", Alignment.TopLeft, playerFrame);
playYourself.OnSelected = TogglePlayYourself;
}
else if (playerFrame.children.Count==0)
{
else
{
UpdatePlayerFrame(Game1.Client.CharacterInfo);
}
base.Select();
}
private void UpdatePlayerFrame(CharacterInfo characterInfo)
{
if (playerFrame.children.Count <= 1)
{
playerFrame.ClearChildren();
if (IsServer && Game1.Server != null)
{
var playYourself = new GUITickBox(new Rectangle(0, -20, 200, 30), "Play yourself", Alignment.TopLeft, playerFrame);
playYourself.OnSelected = TogglePlayYourself;
}
new GUITextBlock(new Rectangle(60, 0, 200, 30), "Name: ", GUI.style, playerFrame);
GUITextBox playerName = new GUITextBox(new Rectangle(60, 30, 0, 20),
Alignment.TopLeft, GUI.style, playerFrame);
playerName.Text = Game1.Client.CharacterInfo.Name;
playerName.Text = characterInfo.Name;
playerName.OnEnter += ChangeCharacterName;
new GUITextBlock(new Rectangle(0, 70, 200, 30), "Gender: ", GUI.style, playerFrame);
GUIButton maleButton = new GUIButton(new Rectangle(0, 100, 70, 20), "Male",
Alignment.TopLeft, GUI.style,playerFrame);
GUIButton maleButton = new GUIButton(new Rectangle(0, 100, 70, 20), "Male",
Alignment.TopLeft, GUI.style, playerFrame);
maleButton.UserData = Gender.Male;
maleButton.OnClicked += SwitchGender;
@@ -313,7 +334,7 @@ namespace Subsurface
int i = 1;
foreach (JobPrefab job in JobPrefab.List)
{
GUITextBlock jobText = new GUITextBlock(new Rectangle(0,0,0,20), i+". "+job.Name, GUI.style, Alignment.Left, Alignment.Right, jobList);
GUITextBlock jobText = new GUITextBlock(new Rectangle(0, 0, 0, 20), i + ". " + job.Name, GUI.style, Alignment.Left, Alignment.Right, jobList);
jobText.UserData = job;
GUIButton upButton = new GUIButton(new Rectangle(0, 0, 15, 15), "u", GUI.style, jobText);
@@ -329,10 +350,29 @@ namespace Subsurface
//UpdatePreviewPlayer(Game1.Client.CharacterInfo);
UpdatePreviewPlayer(Game1.Client.CharacterInfo);
UpdatePreviewPlayer(characterInfo);
}
}
base.Select();
private bool TogglePlayYourself(object obj)
{
GUITickBox tickBox = obj as GUITickBox;
if (tickBox.Selected)
{
Game1.Server.CharacterInfo = new CharacterInfo(Character.HumanConfigFile, Game1.Server.Name);
UpdatePlayerFrame(Game1.Server.CharacterInfo);
}
else
{
playerFrame.ClearChildren();
if (IsServer && Game1.Server != null)
{
var playYourself = new GUITickBox(new Rectangle(0, -20, 200, 30), "Play yourself", Alignment.TopLeft, playerFrame);
playYourself.OnSelected = TogglePlayYourself;
}
}
return false;
}
private bool SelectMap(object obj)
@@ -590,10 +630,10 @@ namespace Subsurface
}
else
{
if (map.Hash.Hash != md5Hash)
if (map.MD5Hash.Hash != 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.Hash.Hash + ")");
DebugConsole.ThrowError("Your file: " + map.Name + "(MD5 hash : " + map.MD5Hash.Hash + ")");
DebugConsole.ThrowError("Server's file: " + mapName + "(MD5 hash : " + md5Hash + ")");
return false;
}
@@ -618,7 +658,7 @@ namespace Subsurface
else
{
msg.Write(Path.GetFileName(selectedMap.Name));
msg.Write(selectedMap.Hash.Hash);
msg.Write(selectedMap.MD5Hash.Hash);
}
msg.Write(ServerName);
@@ -130,7 +130,7 @@ namespace Subsurface
refreshDisableTimer = DateTime.Now + AllowedRefreshInterval;
yield return Status.Success;
yield return CoroutineStatus.Success;
}
private void UpdateServerList(string masterServerData)
@@ -197,14 +197,14 @@ namespace Subsurface
RestClient client = null;
try
{
client = new RestClient(NetworkMember.MasterServerUrl);
client = new RestClient(NetConfig.MasterServerUrl);
}
catch (Exception e)
{
DebugConsole.ThrowError("Error while connecting to master server", e);
}
if (client == null) yield return Status.Success;
if (client == null) yield return CoroutineStatus.Success;
var request = new RestRequest("masterserver.php", Method.GET);
@@ -231,10 +231,10 @@ namespace Subsurface
restRequestHandle.Abort();
DebugConsole.ThrowError("Couldn't connect to master server (request timed out)");
}
yield return Status.Running;
yield return CoroutineStatus.Running;
}
yield return Status.Success;
yield return CoroutineStatus.Success;
}
@@ -296,7 +296,7 @@ namespace Subsurface
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
{
okButton.Enabled = !string.IsNullOrWhiteSpace(passwordBox.Text);
yield return Status.Running;
yield return CoroutineStatus.Running;
}
selectedPassword = passwordBox.Text;
@@ -305,9 +305,7 @@ namespace Subsurface
Game1.NetworkMember = new GameClient(clientNameBox.Text);
Game1.Client.ConnectToServer(ip, selectedPassword);
Game1.NetLobbyScreen.Select();
yield return Status.Success;
yield return CoroutineStatus.Success;
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
+13 -12
View File
@@ -75,22 +75,22 @@ namespace Subsurface
startDrone.Play();
yield return Status.Running;
yield return CoroutineStatus.Running;
waterAmbience = Sound.Load("Content/Sounds/Water/WaterAmbience.ogg");
yield return Status.Running;
yield return CoroutineStatus.Running;
flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg");
yield return Status.Running;
yield return CoroutineStatus.Running;
flowSounds[1] = Sound.Load("Content/Sounds/Water/FlowMedium.ogg");
yield return Status.Running;
yield return CoroutineStatus.Running;
flowSounds[2] = Sound.Load("Content/Sounds/Water/FlowLarge.ogg");
yield return Status.Running;
yield return CoroutineStatus.Running;
XDocument doc = ToolBox.TryLoadXml("Content/Sounds/Sounds.xml");
if (doc == null) yield return Status.Failure;
XDocument doc = ToolBox.TryLoadXml("Content/Sounds/sounds.xml");
if (doc == null) yield return CoroutineStatus.Failure;
yield return Status.Running;
yield return CoroutineStatus.Running;
var xMusic = doc.Root.Elements("music").ToList();
@@ -100,13 +100,13 @@ namespace Subsurface
int i = 0;
foreach (XElement element in xMusic)
{
string file = ToolBox.GetAttributeString(element, "file", "").ToLower();
string file = ToolBox.GetAttributeString(element, "file", "");
string type = ToolBox.GetAttributeString(element, "type", "").ToLower();
Vector2 priority = ToolBox.GetAttributeVector2(element, "priorityrange", new Vector2(0.0f, 100.0f));
musicClips[i] = new BackgroundMusic(file, type, priority);
yield return Status.Running;
yield return CoroutineStatus.Running;
i++;
}
@@ -120,7 +120,7 @@ namespace Subsurface
int i = 0;
foreach (XElement element in xDamageSounds)
{
yield return Status.Running;
yield return CoroutineStatus.Running;
Sound sound = Sound.Load(ToolBox.GetAttributeString(element, "file", ""));
if (sound == null) continue;
@@ -144,7 +144,7 @@ namespace Subsurface
}
}
yield return Status.Success;
yield return CoroutineStatus.Success;
}
@@ -189,6 +189,7 @@ namespace Subsurface
{
foreach (Task task in Game1.GameSession.taskManager.Tasks)
{
if (!task.IsStarted) continue;
if (criticalTask == null || task.Priority > criticalTask.Priority)
{
criticalTask = task;
-2
View File
@@ -1,9 +1,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework;
#if WINDOWS
using OpenTK.Audio.OpenAL;
#endif
using OpenTK.Audio;
using System;
+1 -1
View File
@@ -77,7 +77,7 @@ namespace Subsurface
if (!string.IsNullOrEmpty(path))
{
if (!path.EndsWith("\\")) path += "\\";
if (!path.EndsWith("/")) path += "/";
}
file = path + file;
+1 -1
View File
@@ -51,7 +51,7 @@ namespace Subsurface
#endif
#if LINUX
using (Stream fileStream = File.OpenRead(path))
return Texture2D.FromFile(_graphicsDevice, fileStream);// .FromStream(fileStream, preMultiplyAlpha);
return Texture2D.FromStream(_graphicsDevice, fileStream);// .FromStream(fileStream, preMultiplyAlpha);
#endif
}
+9
View File
@@ -270,6 +270,15 @@ namespace Subsurface
.Select(s => s[Rand.Int(s.Length)])
.ToArray());
}
public static int StringToInt(string str)
{
str = str.Substring(0, Math.Min(str.Length, 32));
byte[] asciiBytes = Encoding.ASCII.GetBytes(str);
return BitConverter.ToInt32(asciiBytes, 0);
}
public static string WrapText(string text, float lineLength, SpriteFont font)
{
+6 -4
View File
@@ -82,6 +82,7 @@
<Compile Include="Source\Items\FixRequirement.cs" />
<Compile Include="Source\Map\Lights\Light.cs" />
<Compile Include="Source\Map\LocationType.cs" />
<Compile Include="Source\Networking\NetConfig.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Utils\Rand.cs" />
<Compile Include="Source\Events\PropertyTask.cs" />
@@ -218,10 +219,6 @@
<Compile Include="Source\Map\Hull.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Lidgren.Network, Version=3.3.0.2069, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\Lidgren.Network.dll</HintPath>
</Reference>
<Reference Include="MonoGame.Framework">
<HintPath>$(MSBuildProgramFiles32)\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll</HintPath>
</Reference>
@@ -238,6 +235,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
@@ -943,6 +941,10 @@
<Project>{0aad36e3-51a5-4a07-ab60-5c8a66bd38b7}</Project>
<Name>Farseer Physics MonoGame</Name>
</ProjectReference>
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj">
<Project>{49ba1c69-6104-41ac-a5d8-b54fa9f696e8}</Project>
<Name>Lidgren.Network</Name>
</ProjectReference>
<ProjectReference Include="..\Subsurface_content\Subsurface_content\Subsurface_content.csproj">
<Project>{1e6bf44d-6e31-40cc-8321-3d5958c983e7}</Project>
<Name>Subsurface_content</Name>