Status icons, skill/character refactoring

This commit is contained in:
Regalis
2015-09-25 12:42:42 +03:00
parent bf7619bcc4
commit 3587b4a4bb
20 changed files with 483 additions and 188 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<character name ="tigerthresher" humanoid="false">
<character name ="tigerthresher" humanoid="false" health="300.0">
<sound file="Content/Characters/Scorpion/scorpionattack1.ogg" state="Attack" />
<sound file="Content/Characters/Scorpion/scorpionidle1.ogg" state="None" />

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<Jobs>
<Captain description="The Commanding Officer with authority over the entire crew." minnumber="1" maxnumber="1">
<Job name="Captain" description="The Commanding Officer with authority over the entire crew. The captain is responsible for commanding the rest of the crew and trying to keep everything running smoothly." minnumber="1" maxnumber="1">
<Item name="ID Card"/>
<Item name="Captain's Cap" equip="true"/>
<Item name="Captain's Jacket" equip="true"/>
@@ -11,9 +11,9 @@
<Skill name="Construction" level="10,20"/>
<Skill name="Electrical Engineering" level="10,20"/>
</Skills>
</Captain>
</Job>
<Engineer minnumber="1">
<Job name="Engineer" description="Engineers have above-average construction and mechanic skills, but fixing complex mechanical devices is still usually out of their skill set. They are competent at fixing electrical devices however, and are the ones to turn to when the power grid starts failing." minnumber="1">
<Skills>
<Skill name="Weapons" level="10,30"/>
<Skill name="Construction" level="30,40"/>
@@ -22,9 +22,9 @@
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
</Engineer>
</Job>
<Mechanic minnumber="1">
<Job name="Mechanic" description="Mechanics have high construction and mechanic skills. They can use welders and plasma cutters safely, and are usually the only ones who can fix broken mechanical devices." minnumber="1">
<Skills>
<Skill name="Weapons" level="10,30"/>
<Skill name="Construction" level="50,60"/>
@@ -33,9 +33,20 @@
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
</Mechanic>
</Job>
<Assistant allowalways="true">
<Job name="Security Officer" description="Security officers are are responsible for keeping the submarine safe from potential attackers. The creatures inhabiting the subsurface ocean aren't the only threat they need to worry about, as several of the renegade groups opposing the Europa Coalition are known to have sent infiltrators on board our vessels.">
<Skills>
<Skill name="Weapons" level="10,30"/>
<Skill name="Construction" level="50,60"/>
<Skill name="Electrical Engineering" level="30,40"/>
</Skills>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
</Job>
<Job name="Assistant" description="Assistants don't have any specific responsibilities or areas of expertise. This job is a good choice for newcomers who want to get a hang of working on board a submarine without taking up tasks that they aren't qualified for." allowalways="true">
<Skills>
<Skill name="Weapons" level="0,10"/>
<Skill name="Construction" level="0,10"/>
@@ -44,5 +55,5 @@
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
</Assistant>
</Job>
</Jobs>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -124,6 +124,16 @@ namespace Subsurface
get { return cursorPosition; }
}
public Character ClosestCharacter
{
get { return closestCharacter; }
}
public Character SelectedCharacter
{
get { return selectedCharacter; }
}
//public AITarget AiTarget
//{
// get { return aiTarget; }
@@ -152,7 +162,7 @@ namespace Subsurface
{
get { return oxygen; }
set
{
{
oxygen = MathHelper.Clamp(value, 0.0f, 100.0f);
if (oxygen == 0.0f) Kill();
}
@@ -163,27 +173,25 @@ namespace Subsurface
get
{
return health;
//float totalHealth = 0.0f;
//foreach (Limb l in animController.limbs)
//{
// totalHealth += (l.MaxHealth - l.Damage);
//}
//return totalHealth/animController.limbs.Count();
}
set
{
health = MathHelper.Clamp(value, 0.0f, maxHealth);
if (health==0.0f) Kill();
if (health == 0.0f) Kill();
}
}
public float MaxHealth
{
get { return maxHealth; }
}
public float Bleeding
{
get { return bleeding; }
set
{
if (float.IsNaN(value) || float.IsInfinity(value)) return;
if (MathUtils.IsValid(value)) return;
bleeding = Math.Max(value, 0.0f);
}
}
@@ -287,6 +295,8 @@ namespace Subsurface
public Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
{
keys = new Key[Enum.GetNames(typeof(InputType)).Length];
keys[(int)InputType.Select] = new Key(false);
keys[(int)InputType.ActionHeld] = new Key(true);
@@ -513,22 +523,55 @@ namespace Subsurface
if (controlled == this)
{
Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cam.ScreenToWorld(PlayerInput.MousePosition));
closestItem = FindClosestItem(mouseSimPos);
if (closestItem != null)
closestCharacter = FindClosestCharacter(mouseSimPos);
if (closestCharacter != null)
{
closestItem.IsHighlighted = true;
if (GetInputState(InputType.Select) && closestItem.Pick(this, forcePick))
if (closestCharacter != selectedCharacter) selectedCharacter = null;
if (!closestCharacter.isHumanoid) closestCharacter = null;
}
closestItem = FindClosestItem(mouseSimPos);
if (closestCharacter != null && closestItem != null)
{
if (Vector2.Distance(closestCharacter.SimPosition, mouseSimPos) < Vector2.Distance(closestItem.SimPosition, mouseSimPos))
{
new NetworkEvent(NetworkEventType.PickItem, ID, true, closestItem.ID);
if (selectedConstruction!=closestItem) closestItem = null;
}
else
{
closestCharacter = null;
}
}
closestCharacter = FindClosestCharacter(mouseSimPos);
if (closestCharacter != selectedCharacter) selectedCharacter = null;
if (closestCharacter!=null)
if (selectedCharacter==null)
{
if (closestItem != null)
{
closestItem.IsHighlighted = true;
if (GetInputState(InputType.Select) && closestItem.Pick(this, forcePick))
{
new NetworkEvent(NetworkEventType.PickItem, ID, true, closestItem.ID);
}
}
}
else
{
if (GetInputState(InputType.Select)) selectedCharacter = (selectedCharacter == null) ? closestCharacter : null;
if (Vector2.Distance(selectedCharacter.SimPosition, SimPosition) > 2.0f) selectedCharacter = null;
}
if (GetInputState(InputType.Select))
{
if (selectedCharacter!=null)
{
selectedCharacter = null;
}
else if (closestCharacter!=null && closestCharacter.isDead && closestCharacter.isHumanoid)
{
selectedCharacter = closestCharacter;
}
}
}
@@ -686,7 +729,11 @@ namespace Subsurface
return;
}
if (controlled == this) ControlLocalPlayer(cam);
if (controlled == this)
{
CharacterHUD.Update(deltaTime,this);
ControlLocalPlayer(cam);
}
Control(deltaTime, cam);
@@ -711,15 +758,11 @@ namespace Subsurface
PressureProtection -= deltaTime*100.0f;
}
//foreach (Limb limb in animController.limbs)
//{
Health = health - bleeding * deltaTime;
//}
Health = health - bleeding * deltaTime;
}
private void UpdateSightRange()
{
aiTarget.SightRange = 0.0f;
@@ -747,6 +790,11 @@ namespace Subsurface
// ConvertUnits.ToDisplayUnits(animController.targetMovement.X, animController.targetMovement.Y), Color.Green);
}
public void DrawHUD(SpriteBatch spriteBatch, Camera cam)
{
CharacterHUD.Draw(spriteBatch, this, cam);
}
public void DrawFront(SpriteBatch spriteBatch)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(AnimController.Limbs[0].SimPosition);
@@ -772,67 +820,7 @@ namespace Subsurface
}
private static GUIProgressBar drowningBar, healthBar;
public void DrawHud(SpriteBatch spriteBatch, Camera cam)
{
if (drowningBar == null)
{
int width = 100, height = 20;
drowningBar = new GUIProgressBar(new Rectangle(20, GameMain.GraphicsHeight / 2, width, height), Color.Blue, 1.0f);
healthBar = new GUIProgressBar(new Rectangle(20, GameMain.GraphicsHeight / 2 + 30, width, height), Color.Red, 1.0f);
}
drowningBar.BarSize = Controlled.Oxygen / 100.0f;
if (drowningBar.BarSize < 0.95f) drowningBar.Draw(spriteBatch);
healthBar.BarSize = health / maxHealth;
if (healthBar.BarSize < 1.0f) healthBar.Draw(spriteBatch);
if (Controlled.Inventory != null) Controlled.Inventory.DrawOwn(spriteBatch);
Color color = Color.Orange;
if (closestCharacter != null && closestCharacter.isDead && closestCharacter.isHumanoid)
{
Vector2 startPos = Position + (closestCharacter.Position - Position) * 0.7f;
startPos = cam.WorldToScreen(startPos);
Vector2 textPos = startPos;
float stringWidth = GUI.Font.MeasureString(closestCharacter.Info.Name).X;
textPos -= new Vector2(stringWidth / 2, 20);
spriteBatch.DrawString(GUI.Font, closestCharacter.Info.Name, textPos, Color.Black);
spriteBatch.DrawString(GUI.Font, closestCharacter.Info.Name, textPos + new Vector2(1, -1), Color.Orange);
if (selectedCharacter==closestCharacter) closestCharacter.inventory.Draw(spriteBatch);
}
else if (closestItem != null && selectedConstruction==null)
{
Vector2 startPos = Position + (closestItem.Position - Position) * 0.7f;
startPos = cam.WorldToScreen(startPos);
Vector2 textPos = startPos;
float stringWidth = GUI.Font.MeasureString(closestItem.Prefab.Name).X;
textPos -= new Vector2(stringWidth / 2, 20);
spriteBatch.DrawString(GUI.Font, closestItem.Prefab.Name, textPos, Color.Black);
spriteBatch.DrawString(GUI.Font, closestItem.Prefab.Name, textPos + new Vector2(1, -1), Color.Orange);
textPos.Y += 50.0f;
foreach (ColoredText coloredText in closestItem.GetHUDTexts(Controlled))
{
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);
textPos.Y += 25;
}
}
}
public void PlaySound(AIController.AiState state)
{
@@ -856,20 +844,23 @@ namespace Subsurface
}
}
public virtual AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = false)
public virtual AttackResult AddDamage(IDamageable attacker, Vector2 simPosition, Attack attack, bool playSound = false)
{
return AddDamage(position, attack.DamageType, attack.Damage, attack.BleedingDamage, attack.Stun, playSound);
return AddDamage(simPosition, attack.DamageType, attack.Damage, attack.BleedingDamage, attack.Stun, playSound);
}
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound)
public AttackResult AddDamage(Vector2 simPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound)
{
AnimController.StunTimer = Math.Max(AnimController.StunTimer, stun);
if (controlled == this) CharacterHUD.TakeDamage();
Limb closestLimb = null;
float closestDistance = 0.0f;
foreach (Limb limb in AnimController.Limbs)
{
float distance = Vector2.Distance(position, limb.SimPosition);
float distance = Vector2.Distance(simPosition, limb.SimPosition);
if (closestLimb == null || distance < closestDistance)
{
closestLimb = limb;
@@ -877,12 +868,12 @@ namespace Subsurface
}
}
Vector2 pull = position - closestLimb.SimPosition;
Vector2 pull = simPosition - closestLimb.SimPosition;
if (pull != Vector2.Zero) pull = Vector2.Normalize(pull);
closestLimb.body.ApplyForce(pull*Math.Min(amount*100.0f, 100.0f));
AttackResult attackResult = closestLimb.AddDamage(position, damageType, amount, bleedingAmount, playSound);
AttackResult attackResult = closestLimb.AddDamage(simPosition, damageType, amount, bleedingAmount, playSound);
health -= attackResult.Damage;
bleeding += attackResult.Bleeding;
@@ -938,6 +929,8 @@ namespace Subsurface
private IEnumerable<object> DeathAnim(Camera cam)
{
if (controlled != this) yield return CoroutineStatus.Success;
float dimDuration = 8.0f;
float timer = 0.0f;
@@ -967,9 +960,9 @@ namespace Subsurface
}
float lerpLightBack = 0.0f;
while (lerpLightBack<1.0f)
while (lerpLightBack < 1.0f)
{
lerpLightBack = Math.Min(lerpLightBack+0.05f,1.0f);
lerpLightBack = Math.Min(lerpLightBack + 0.05f, 1.0f);
GameMain.LightManager.AmbientLight = Color.Lerp(Color.DarkGray, prevAmbientLight, lerpLightBack);
yield return CoroutineStatus.Running;

View File

@@ -0,0 +1,142 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Subsurface
{
class CharacterHUD
{
private static Sprite statusIcons;
private static GUIProgressBar drowningBar, healthBar;
private static float pressureTimer;
public static void TakeDamage()
{
healthBar.Flash();
}
public static void Update(float deltaTime, Character character)
{
if (drowningBar != null)
{
drowningBar.Update(deltaTime);
if (character.Oxygen < 10.0f) drowningBar.Flash();
}
if (healthBar != null) healthBar.Update(deltaTime);
pressureTimer += ((character.AnimController.CurrentHull == null) ?
100.0f : character.AnimController.CurrentHull.LethalPressure)*deltaTime;
}
public static void Draw(SpriteBatch spriteBatch, Character character, Camera cam)
{
if (statusIcons==null)
{
statusIcons = new Sprite("Content/UI/statusIcons.png", Vector2.Zero);
}
DrawStatusIcons(spriteBatch, character);
if (character.Inventory != null) character.Inventory.DrawOwn(spriteBatch);
Color color = Color.Orange;
if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory!=null)
{
character.SelectedCharacter.Inventory.Draw(spriteBatch);
//if (Vector2.Distance(selectedCharacter.SimPosition, SimPosition) > 2.0f) selectedCharacter = null;
}
if (character.ClosestCharacter != null && character.ClosestCharacter.IsDead)
{
Vector2 startPos = character.Position + (character.ClosestCharacter.Position - character.Position) * 0.7f;
startPos = cam.WorldToScreen(startPos);
Vector2 textPos = startPos;
float stringWidth = GUI.Font.MeasureString(character.ClosestCharacter.Info.Name).X;
textPos -= new Vector2(stringWidth / 2, 20);
spriteBatch.DrawString(GUI.Font, character.ClosestCharacter.Info.Name, textPos, Color.Black);
spriteBatch.DrawString(GUI.Font, character.ClosestCharacter.Info.Name, textPos + new Vector2(1, -1), Color.Orange);
}
else if (character.SelectedCharacter == null && character.ClosestItem != null && character.SelectedConstruction == null)
{
Vector2 startPos = character.Position + (character.ClosestItem.Position - character.Position) * 0.7f;
startPos = cam.WorldToScreen(startPos);
Vector2 textPos = startPos;
float stringWidth = GUI.Font.MeasureString(character.ClosestItem.Prefab.Name).X;
textPos -= new Vector2(stringWidth / 2, 20);
spriteBatch.DrawString(GUI.Font, character.ClosestItem.Prefab.Name, textPos, Color.Black);
spriteBatch.DrawString(GUI.Font, character.ClosestItem.Prefab.Name, textPos + new Vector2(1, -1), Color.Orange);
textPos.Y += 50.0f;
foreach (ColoredText coloredText in character.ClosestItem.GetHUDTexts(character))
{
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);
textPos.Y += 25;
}
}
}
private static void DrawStatusIcons(SpriteBatch spriteBatch, Character character)
{
if (drowningBar == null)
{
int width = 100, height = 20;
drowningBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 200, width, height), Color.Blue, 1.0f);
new GUIImage(new Rectangle(-27, -7, 20, 20), new Rectangle(17, 0, 20, 24), statusIcons, Alignment.TopLeft, drowningBar);
healthBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 230, width, height), Color.Red, 1.0f);
new GUIImage(new Rectangle(-26, -7, 20, 20), new Rectangle(0, 0, 13, 24), statusIcons, Alignment.TopLeft, healthBar);
}
drowningBar.BarSize = character.Oxygen / 100.0f;
if (drowningBar.BarSize < 0.99f)
{
drowningBar.Draw(spriteBatch);
}
healthBar.BarSize = character.Health / character.MaxHealth;
if (healthBar.BarSize < 1.0f)
{
healthBar.Draw(spriteBatch);
}
int bloodDropCount = (int)Math.Floor(character.Bleeding);
bloodDropCount = MathHelper.Clamp(bloodDropCount, 0, 5);
for (int i = 1; i < bloodDropCount; i++)
{
spriteBatch.Draw(statusIcons.Texture, new Vector2(5.0f + 20 * i, healthBar.Rect.Y - 20.0f), new Rectangle(39, 3, 15, 19), Color.White * 0.8f);
}
float pressureFactor = (character.AnimController.CurrentHull == null) ?
100.0f : Math.Min(character.AnimController.CurrentHull.LethalPressure,100.0f);
if (character.PressureProtection > 0.0f) pressureFactor = 0.0f;
if (pressureFactor>0.0f)
{
float indicatorAlpha = ((float)Math.Sin(pressureTimer * 0.1f) + 1.0f) * 0.5f;
indicatorAlpha = MathHelper.Clamp(indicatorAlpha, 0.1f, pressureFactor/100.0f);
spriteBatch.Draw(statusIcons.Texture, new Vector2(10.0f, healthBar.Rect.Y - 60.0f), new Rectangle(0, 24, 24, 25), Color.White * indicatorAlpha);
}
}
}
}

View File

@@ -7,28 +7,6 @@ using System.Xml.Linq;
namespace Subsurface
{
class Skill
{
string name;
int level;
public string Name
{
get { return name; }
}
public int Level
{
get { return level; }
}
public Skill(string name, int level)
{
this.name = name;
this.level = level;
}
}
class Job
{
@@ -76,11 +54,9 @@ namespace Subsurface
prefab = jobPrefab;
skills = new Dictionary<string, Skill>();
foreach (KeyValuePair<string, Vector2> skill in prefab.Skills)
foreach (SkillPrefab skillPrefab in prefab.Skills)
{
skills.Add(
skill.Key,
new Skill( skill.Key, (int)Rand.Range(skill.Value.X, skill.Value.Y, false)));
skills.Add(skillPrefab.Name, new Skill(skillPrefab));
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
using System.Linq;
namespace Subsurface
{
@@ -30,7 +31,7 @@ namespace Subsurface
public List<string> ItemNames;
public List<bool> EquipItem;
public Dictionary<string, Vector2> Skills;
public List<SkillPrefab> Skills;
public string Name
{
@@ -54,7 +55,7 @@ namespace Subsurface
public JobPrefab(XElement element)
{
name = element.Name.ToString();
name = ToolBox.GetAttributeString(element, "name", "name not found");
description = ToolBox.GetAttributeString(element, "description", "");
@@ -66,7 +67,7 @@ namespace Subsurface
ItemNames = new List<string>();
EquipItem = new List<bool>();
Skills = new Dictionary<string, Vector2>();
Skills = new List<SkillPrefab>();
foreach (XElement subElement in element.Elements())
{
@@ -82,10 +83,15 @@ namespace Subsurface
}
break;
case "skills":
LoadSkills(subElement);
foreach (XElement skillElement in subElement.Elements())
{
Skills.Add(new SkillPrefab(skillElement));
}
break;
}
}
Skills.Sort((x,y) => y.LevelRange.X.CompareTo(x.LevelRange.X));
}
public static JobPrefab Random()
@@ -93,28 +99,51 @@ namespace Subsurface
return List[Rand.Int(List.Count)];
}
private void LoadSkills(XElement element)
public GUIFrame CreateInfoFrame()
{
foreach (XElement subElement in element.Elements())
int width = 500, height = 400;
GUIFrame frame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), GUI.Style);
frame.Padding = new Vector4(30.0f, 30.0f, 30.0f, 30.0f);
new GUITextBlock(new Rectangle(0,0,100,20), name, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), description, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont);
new GUITextBlock(new Rectangle(0, 40 + descriptionBlock.Rect.Height + 20, 100, 20), "Skills: ", GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
int y = 40 + descriptionBlock.Rect.Height + 50;
foreach (SkillPrefab skill in Skills)
{
string skillName = ToolBox.GetAttributeString(subElement, "name", "");
string skillDescription = Skill.GetLevelName((int)skill.LevelRange.X);
string skillDescription2 = Skill.GetLevelName((int)skill.LevelRange.Y);
if (string.IsNullOrEmpty(skillName) || Skills.ContainsKey(skillName)) continue;
var levelString = ToolBox.GetAttributeString(subElement, "level", "");
if (levelString.Contains(","))
if (skillDescription2!= skillDescription)
{
Skills.Add(skillName, ToolBox.ParseToVector2(levelString, false));
}
else
{
float skillLevel = float.Parse(levelString, CultureInfo.InvariantCulture);
Skills.Add(skillName, new Vector2(skillLevel, skillLevel));
skillDescription += "/"+skillDescription2;
}
new GUITextBlock(new Rectangle(0, y, 100, 20),
" - " + skill.Name + ": " + skillDescription, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont);
y += 20;
}
}
new GUITextBlock(new Rectangle(250, 40 + descriptionBlock.Rect.Height + 20, 0, 20), "Items: ", GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
y = 40 + descriptionBlock.Rect.Height + 50;
foreach (string itemName in ItemNames)
{
new GUITextBlock(new Rectangle(250, y, 100, 20),
" - " + itemName, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont);
y += 20;
}
return frame;
}
public static void LoadAll(List<string> filePaths)
{

View File

@@ -0,0 +1,57 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Subsurface
{
class Skill
{
SkillPrefab prefab;
string name;
int level;
static string[] levelNames = new string[] {
"Untrained", "Incompetent", "Novice",
"Adequate", "Competent", "Proficient",
"Professional", "Master", "Legendary" };
public string Name
{
get { return name; }
}
public int Level
{
get { return level; }
}
public Skill(SkillPrefab prefab)
{
this.prefab = prefab;
this.name = prefab.Name;
this.level = (int)Rand.Range(prefab.LevelRange.X, prefab.LevelRange.Y);
}
public Skill(string name, int level)
{
this.name = name;
this.level = level;
}
/// <summary>
/// returns the "name" of some skill level (0-10 -> untrained, etc)
/// </summary>
public static string GetLevelName(int level)
{
level = MathHelper.Clamp(level, 0, 100);
int scaledLevel = (int)Math.Floor((level / 100.0f) * levelNames.Length);
return levelNames[Math.Min(scaledLevel, levelNames.Length - 1)];
}
}
}

View File

@@ -0,0 +1,51 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Subsurface
{
class SkillPrefab
{
string name;
string description;
private Vector2 levelRange;
public string Name
{
get { return name; }
}
public string Description
{
get { return description; }
}
public Vector2 LevelRange
{
get { return levelRange; }
}
public SkillPrefab(XElement element)
{
name = ToolBox.GetAttributeString(element, "name", "");
var levelString = ToolBox.GetAttributeString(element, "level", "");
if (levelString.Contains(","))
{
levelRange = ToolBox.ParseToVector2(levelString, false);
}
else
{
float skillLevel = float.Parse(levelString, System.Globalization.CultureInfo.InvariantCulture);
levelRange = new Vector2(skillLevel, skillLevel);
}
}
}
}

View File

@@ -285,7 +285,7 @@ namespace Subsurface
body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, pullPos);
}
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound)
public AttackResult AddDamage(Vector2 simPosition, DamageType damageType, float amount, float bleedingAmount, bool playSound)
{
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;
@@ -299,7 +299,7 @@ namespace Subsurface
float mid = (armorLimits.X + armorLimits.Y) / 2.0f;
float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(position - SimPosition), mid);
float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(simPosition - SimPosition), mid);
if (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f)
{
@@ -310,9 +310,9 @@ namespace Subsurface
}
}
if (playSound)
if (playSound && amount>0.0f)
{
AmbientSoundManager.PlayDamageSound(damageSoundType, amount, position);
AmbientSoundManager.PlayDamageSound(damageSoundType, amount, ConvertUnits.ToDisplayUnits(simPosition));
}
//Bleeding += bleedingAmount;
@@ -322,7 +322,7 @@ namespace Subsurface
for (int i = 0; i < bloodAmount; i++)
{
Vector2 particleVel = SimPosition - position;
Vector2 particleVel = SimPosition - simPosition;
if (particleVel != Vector2.Zero) particleVel = Vector2.Normalize(particleVel);
GameMain.ParticleManager.CreateParticle("blood",

View File

@@ -320,7 +320,7 @@ namespace Subsurface
}
}
if (Character.Controlled != null && cam!=null) Character.Controlled.DrawHud(spriteBatch, cam);
if (Character.Controlled != null && cam!=null) Character.Controlled.DrawHUD(spriteBatch, cam);
if (GameMain.NetworkMember != null) GameMain.NetworkMember.Draw(spriteBatch);
DrawMessages(spriteBatch, (float)deltaTime);

View File

@@ -47,6 +47,11 @@ namespace Subsurface
}
public GUIImage(Rectangle rect, Sprite sprite, Alignment alignment, GUIComponent parent = null)
: this(rect, sprite.SourceRect, sprite, alignment, parent)
{
}
public GUIImage(Rectangle rect, Rectangle sourceRect, Sprite sprite, Alignment alignment, GUIComponent parent = null)
: base(null)
{
this.rect = rect;
@@ -60,12 +65,12 @@ namespace Subsurface
Scale = 1.0f;
this.sprite = sprite;
if (rect.Width == 0) this.rect.Width = (int)sprite.size.X;
if (rect.Height == 0) this.rect.Height = (int)Math.Min(sprite.size.Y, sprite.size.Y * (this.rect.Width / sprite.size.X));
sourceRect = sprite.SourceRect;
this.sourceRect = sourceRect;
if (parent != null)
parent.AddChild(this);
}

View File

@@ -131,13 +131,11 @@ namespace Subsurface.Items.Components
public override bool Use(float deltaTime, Character activator = null)
{
//character = activator;
//foreach (MapEntity e in item.linkedTo)
//{
// Item linkedItem = e as Item;
// if (linkedItem == null) continue;
// linkedItem.Use(deltaTime, activator);
//}
if (character.SelectedConstruction != item)
{
character = null;
return false;
}
item.SendSignal("1", "trigger_out");
@@ -149,6 +147,11 @@ namespace Subsurface.Items.Components
public override void SecondaryUse(float deltaTime, Character character = null)
{
if (character == null) return;
if (character.SelectedConstruction!=item)
{
character = null;
return;
}
foreach (Connection c in item.Connections)
{

View File

@@ -420,7 +420,7 @@ namespace Subsurface
{
foreach (Item containedItem in containedItems)
{
if (containedItem == null || containedItem.condition==0.0f) continue;
if (containedItem == null) continue;
if (effect.TargetNames != null && !effect.TargetNames.Contains(containedItem.Name)) continue;
hasTargets = true;
@@ -719,7 +719,7 @@ namespace Subsurface
return;
}
if (!HasInGameEditableProperties)
if (HasInGameEditableProperties)
{
if (editingHUD == null || editingHUD.UserData as Item != this)
{

View File

@@ -60,8 +60,6 @@ namespace Subsurface
Rand.Vector(Rand.Range(50f, 100.0f)), 0.0f);
}
float displayRange = ConvertUnits.ToDisplayUnits(attack.Range);
light = new LightSource(displayPosition, displayRange, Color.LightYellow);

View File

@@ -239,7 +239,6 @@ namespace Subsurface
public override void Update(Camera cam, float deltaTime)
{
soundVolume = soundVolume + ((flowForce.Length() < 100.0f) ? -deltaTime * 0.5f : deltaTime * 0.5f);
soundVolume = MathHelper.Clamp(soundVolume, 0.0f, 1.0f);
@@ -254,7 +253,6 @@ namespace Subsurface
UpdateOxygen();
if (linkedTo.Count == 1)
{
//gap leading from a room to outside
@@ -266,7 +264,7 @@ namespace Subsurface
UpdateRoomToRoom(deltaTime);
}
lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, 0.1f);
lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, 0.05f);
if (FlowForce.Length() > 150.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume)
{

View File

@@ -147,7 +147,7 @@ namespace Subsurface
+ " However, UPnP isn't supported by all routers, so you may need to setup port forwards manually"
+" if players are unable to join the server (see the readme for instructions).";
GUIButton hostButton = new GUIButton(new Rectangle(0, 0, 200, 30), "Start", Alignment.BottomRight, GUI.Style, menuTabs[(int)Tabs.HostServer]);
GUIButton hostButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", Alignment.BottomRight, GUI.Style, menuTabs[(int)Tabs.HostServer]);
hostButton.OnClicked = HostServerClicked;
this.game = game;

View File

@@ -27,6 +27,8 @@ namespace Subsurface
private GUIFrame playerFrame;
private GUIFrame jobInfoFrame;
private float camAngle;
public bool IsServer;
@@ -305,7 +307,7 @@ namespace Subsurface
if (IsServer && GameMain.Server != null)
{
var playYourself = new GUITickBox(new Rectangle(0, -20, 20, 20), "Play yourself", Alignment.TopLeft, playerFrame);
var playYourself = new GUITickBox(new Rectangle(-30, -30, 20, 20), "Play yourself", Alignment.TopLeft, playerFrame);
playYourself.Selected = GameMain.Server.CharacterInfo != null;
playYourself.OnSelected = TogglePlayYourself;
playYourself.UserData = "playyourself";
@@ -332,21 +334,25 @@ namespace Subsurface
new GUITextBlock(new Rectangle(0, 150, 200, 30), "Job preferences:", GUI.Style, playerFrame);
jobList = new GUIListBox(new Rectangle(0, 180, 180, 0), GUI.Style, playerFrame);
jobList = new GUIListBox(new Rectangle(0, 180, 250, 0), GUI.Style, playerFrame);
jobList.Enabled = false;
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);
GUIButton infoButton = new GUIButton(new Rectangle(0, 0, 15, 15), "?", GUI.Style, jobText);
infoButton.UserData = -1;
infoButton.OnClicked += ViewJobInfo;
GUIButton upButton = new GUIButton(new Rectangle(30, 0, 15, 15), "^", GUI.Style, jobText);
upButton.UserData = -1;
upButton.OnClicked += ChangeJobPreference;
GUIButton downButton = new GUIButton(new Rectangle(25, 0, 15, 15), "d", GUI.Style, jobText);
GUIButton downButton = new GUIButton(new Rectangle(50, 0, 15, 15), "˅", GUI.Style, jobText);
downButton.UserData = 1;
downButton.OnClicked += ChangeJobPreference;
}
@@ -460,6 +466,8 @@ namespace Subsurface
GameMain.GameScreen.Cam.MoveCamera((float)deltaTime);
menu.Update((float)deltaTime);
if (jobInfoFrame != null) jobInfoFrame.Update((float)deltaTime);
//durationBar.BarScroll = Math.Max(durationBar.BarScroll, 1.0f / 60.0f);
}
@@ -474,6 +482,8 @@ namespace Subsurface
menu.Draw(spriteBatch);
if (jobInfoFrame != null) jobInfoFrame.Draw(spriteBatch);
//if (previewPlayer!=null) previewPlayer.Draw(spriteBatch);
GUI.Draw((float)deltaTime, spriteBatch, null);
@@ -531,17 +541,14 @@ namespace Subsurface
private bool SwitchGender(GUIButton button, object obj)
{
try
{
Gender gender = (Gender)obj;
GameMain.Client.CharacterInfo.Gender = gender;
GameMain.Client.SendCharacterData();
Gender gender = (Gender)obj;
GameMain.NetworkMember.CharacterInfo.Gender = gender;
GameMain.Client.SendCharacterData();
//CreatePreviewCharacter();
}
catch {}
//CreatePreviewCharacter();
UpdatePreviewPlayer(GameMain.Client.CharacterInfo);
UpdatePreviewPlayer(GameMain.NetworkMember.CharacterInfo);
return true;
}
@@ -594,6 +601,25 @@ namespace Subsurface
return true;
}
private bool ViewJobInfo(GUIButton button, object obj)
{
GUIComponent jobText = button.Parent;
JobPrefab jobPrefab = jobText.UserData as JobPrefab;
if (jobPrefab == null) return false;
jobInfoFrame = jobPrefab.CreateInfoFrame();
GUIButton closeButton = new GUIButton(new Rectangle(0,0,100,20), "Close", Alignment.BottomRight, GUI.Style, jobInfoFrame);
closeButton.OnClicked = CloseJobInfo;
return true;
}
private bool CloseJobInfo(GUIButton button, object obj)
{
jobInfoFrame = null;
return true;
}
private bool ChangeJobPreference(GUIButton button, object obj)
{
GUIComponent jobText = button.Parent;

View File

@@ -67,6 +67,7 @@
<Compile Include="Source\Characters\BackgroundSprite\BackgroundSpriteManager.cs" />
<Compile Include="Source\Characters\BackgroundSprite\BackgroundSpritePrefab.cs" />
<Compile Include="Source\Characters\Character.cs" />
<Compile Include="Source\Characters\CharacterHUD.cs" />
<Compile Include="Source\Characters\CharacterInfo.cs" />
<Compile Include="Source\Characters\AI\ISteerable.cs" />
<Compile Include="Source\Characters\DelayedEffect.cs" />
@@ -74,6 +75,8 @@
<Compile Include="Source\Characters\Jobs\JobPrefab.cs" />
<Compile Include="Source\Characters\AI\SteeringManager.cs" />
<Compile Include="Source\Characters\AI\SteeringPath.cs" />
<Compile Include="Source\Characters\Jobs\Skill.cs" />
<Compile Include="Source\Characters\Jobs\SkillPrefab.cs" />
<Compile Include="Source\ContentPackage.cs" />
<Compile Include="Source\CoroutineManager.cs" />
<Compile Include="Source\Events\Quests\Quest.cs" />
@@ -217,7 +220,7 @@
<Compile Include="Source\Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Source\Screens\LobbyScreen.cs" />
<Compile Include="Source\Screens\MainMenu.cs" />
<Compile Include="Source\Screens\MainMenuScreen.cs" />
<Compile Include="Source\Screens\NetLobbyScreen.cs" />
<Compile Include="Source\Screens\SettingsScreen.cs" />
<Compile Include="Source\Screens\Screen.cs" />
@@ -530,6 +533,9 @@
<Content Include="Content\UI\inventoryIcons.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\UI\statusIcons.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\UI\style.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>

Binary file not shown.