Status icons, skill/character refactoring
This commit is contained in:
@@ -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;
|
||||
|
||||
142
Subsurface/Source/Characters/CharacterHUD.cs
Normal file
142
Subsurface/Source/Characters/CharacterHUD.cs
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
57
Subsurface/Source/Characters/Jobs/Skill.cs
Normal file
57
Subsurface/Source/Characters/Jobs/Skill.cs
Normal 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)];
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Subsurface/Source/Characters/Jobs/SkillPrefab.cs
Normal file
51
Subsurface/Source/Characters/Jobs/SkillPrefab.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user