38f1ddb...178a853: v0.8.9.1, removed content folder

This commit is contained in:
Joonas Rikkonen
2019-03-18 19:46:58 +02:00
parent 38f1ddb6fe
commit 6c0679c297
1054 changed files with 151673 additions and 144931 deletions
@@ -5,6 +5,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
#if CLIENT
using Barotrauma.Sounds;
#endif
namespace Barotrauma.Items.Components
{
@@ -37,7 +40,7 @@ namespace Barotrauma.Items.Components
public readonly Dictionary<ActionType, List<StatusEffect>> statusEffectLists;
public List<RelatedItem> requiredItems;
public Dictionary<RelatedItem.RelationType, List<RelatedItem>> requiredItems;
public List<Skill> requiredSkills;
@@ -53,7 +56,7 @@ namespace Barotrauma.Items.Components
public float PickingTime
{
get;
private set;
set;
}
public readonly Dictionary<string, SerializableProperty> properties;
@@ -73,7 +76,7 @@ namespace Barotrauma.Items.Components
StopSounds(ActionType.OnActive);
}
#endif
if (AITarget != null) AITarget.Enabled = value;
isActive = value;
}
}
@@ -88,7 +91,7 @@ namespace Barotrauma.Items.Components
if (value == drawable) return;
if (!(this is IDrawableComponent))
{
DebugConsole.ThrowError("Couldn't make \""+this+"\" drawable (the component doesn't implement the IDrawableComponent interface)");
DebugConsole.ThrowError("Couldn't make \"" + this + "\" drawable (the component doesn't implement the IDrawableComponent interface)");
return;
}
@@ -150,6 +153,14 @@ namespace Barotrauma.Items.Components
set { characterUsable = value; }
}
//Remove item if combination results in 0 condition
[Serialize(true, false), Editable(ToolTip = "Can the properties of the component be edited in-game (only applicable if the component has in-game editable properties).")]
public bool AllowInGameEditing
{
get;
set;
}
public InputType PickKey
{
get;
@@ -185,22 +196,19 @@ namespace Barotrauma.Items.Components
get { return msg; }
set { msg = value; }
}
public AITarget AITarget
{
get;
private set;
}
public ItemComponent(Item item, XElement element)
{
this.item = item;
name = element.Name.ToString();
properties = SerializableProperty.GetProperties(this);
//canBePicked = ToolBox.GetAttributeBool(element, "canbepicked", false);
//canBeSelected = ToolBox.GetAttributeBool(element, "canbeselected", false);
//msg = ToolBox.GetAttributeString(element, "msg", "");
requiredItems = new List<RelatedItem>();
properties = SerializableProperty.GetProperties(this);
requiredItems = new Dictionary<RelatedItem.RelationType, List<RelatedItem>>();
requiredSkills = new List<Skill>();
#if CLIENT
@@ -234,24 +242,50 @@ namespace Barotrauma.Items.Components
}
properties = SerializableProperty.DeserializeProperties(this, element);
#if CLIENT
string msg = TextManager.Get(Msg, true);
if (msg != null)
{
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
{
msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString());
}
Msg = msg;
}
#endif
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "requireditem":
case "requireditems":
RelatedItem ri = RelatedItem.Load(subElement);
if (ri != null) requiredItems.Add(ri);
RelatedItem ri = RelatedItem.Load(subElement, item.Name);
if (ri != null)
{
if (!requiredItems.ContainsKey(ri.Type))
{
requiredItems.Add(ri.Type, new List<RelatedItem>());
}
requiredItems[ri.Type].Add(ri);
}
else
{
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFile + "\" - component " + GetType().ToString() + " requires an item with no identifiers.");
}
break;
case "requiredskill":
case "requiredskills":
string skillName = subElement.GetAttributeString("name", "");
requiredSkills.Add(new Skill(skillName, subElement.GetAttributeInt("level", 0)));
if (subElement.Attribute("name") != null)
{
DebugConsole.ThrowError("Error in item config \"" + item.ConfigFile + "\" - skill requirement in component " + GetType().ToString() + " should use a skill identifier instead of the name of the skill.");
continue;
}
string skillIdentifier = subElement.GetAttributeString("identifier", "");
requiredSkills.Add(new Skill(skillIdentifier, subElement.GetAttributeInt("level", 0)));
break;
case "statuseffect":
var statusEffect = StatusEffect.Load(subElement);
var statusEffect = StatusEffect.Load(subElement, item.Name);
if (statusEffectLists == null) statusEffectLists = new Dictionary<ActionType, List<StatusEffect>>();
@@ -264,6 +298,12 @@ namespace Barotrauma.Items.Components
effectList.Add(statusEffect);
break;
case "aitarget":
AITarget = new AITarget(item, subElement)
{
Enabled = isActive
};
break;
default:
if (LoadElemProjSpecific(subElement)) break;
@@ -329,14 +369,14 @@ namespace Barotrauma.Items.Components
//called then the item is dropped or dragged out of a "limbslot"
public virtual void Unequip(Character character) { }
public virtual void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f)
{
public virtual void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
case "activate":
case "use":
case "trigger_in":
item.Use(1.0f);
break;
case "toggle":
@@ -394,10 +434,12 @@ namespace Barotrauma.Items.Components
public void Remove()
{
#if CLIENT
if (loopingSound != null)
if (loopingSoundChannel != null)
{
Sounds.SoundManager.Stop(loopingSoundIndex);
}
loopingSoundChannel.Dispose();
loopingSoundChannel = null;
}
if (GuiFrame != null) GUI.RemoveFromUpdateList(GuiFrame, true);
#endif
if (delayedCorrectionCoroutine != null)
@@ -406,6 +448,12 @@ namespace Barotrauma.Items.Components
delayedCorrectionCoroutine = null;
}
if (AITarget != null)
{
AITarget.Remove();
AITarget = null;
}
RemoveComponentSpecific();
}
@@ -416,11 +464,17 @@ namespace Barotrauma.Items.Components
public void ShallowRemove()
{
#if CLIENT
if (loopingSound != null)
if (loopingSoundChannel != null)
{
Sounds.SoundManager.Stop(loopingSoundIndex);
loopingSoundChannel.Dispose();
loopingSoundChannel = null;
}
#endif
if (AITarget != null)
{
AITarget.Remove();
AITarget = null;
}
ShallowRemoveComponentSpecific();
}
@@ -435,15 +489,14 @@ namespace Barotrauma.Items.Components
public bool HasRequiredSkills(Character character)
{
Skill temp;
return HasRequiredSkills(character, out temp);
return HasRequiredSkills(character, out Skill temp);
}
public bool HasRequiredSkills(Character character, out Skill insufficientSkill)
{
foreach (Skill skill in requiredSkills)
{
int characterLevel = character.GetSkillLevel(skill.Name);
float characterLevel = character.GetSkillLevel(skill.Identifier);
if (characterLevel < skill.Level)
{
insufficientSkill = skill;
@@ -458,39 +511,50 @@ namespace Barotrauma.Items.Components
/// Returns 0.0f-1.0f based on how well the Character can use the itemcomponent
/// </summary>
/// <returns>0.5f if all the skills meet the skill requirements exactly, 1.0f if they're way above and 0.0f if way less</returns>
protected float DegreeOfSuccess(Character character)
public float DegreeOfSuccess(Character character)
{
if (requiredSkills.Count == 0) return 100.0f;
float[] skillSuccess = new float[requiredSkills.Count];
for (int i = 0; i < requiredSkills.Count; i++)
{
int characterLevel = character.GetSkillLevel(requiredSkills[i].Name);
skillSuccess[i] = (characterLevel - requiredSkills[i].Level);
}
float average = skillSuccess.Average();
return (average + 100.0f) / 2.0f;
return DegreeOfSuccess(character, requiredSkills);
}
public virtual void FlipX() { }
/// <summary>
/// Returns 0.0f-1.0f based on how well the Character can use the itemcomponent
/// </summary>
/// <returns>0.5f if all the skills meet the skill requirements exactly, 1.0f if they're way above and 0.0f if way less</returns>
public float DegreeOfSuccess(Character character, List<Skill> requiredSkills)
{
if (requiredSkills.Count == 0) return 1.0f;
if (character == null)
{
string errorMsg = "ItemComponent.DegreeOfSuccess failed (character was null).\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return 0.0f;
}
float skillSuccessSum = 0.0f;
for (int i = 0; i < requiredSkills.Count; i++)
{
float characterLevel = character.GetSkillLevel(requiredSkills[i].Identifier);
skillSuccessSum += (characterLevel - requiredSkills[i].Level);
}
float average = skillSuccessSum / requiredSkills.Count;
return ((average + 100.0f) / 2.0f) / 100.0f;
}
public virtual void FlipX(bool relativeToSub) { }
public virtual void FlipY(bool relativeToSub) { }
public bool HasRequiredContainedItems(bool addMessage)
{
List<RelatedItem> requiredContained = requiredItems.FindAll(ri=> ri.Type == RelatedItem.RelationType.Contained);
if (!requiredContained.Any()) return true;
Item[] containedItems = item.ContainedItems;
if (containedItems == null || !containedItems.Any()) return false;
foreach (RelatedItem ri in requiredContained)
if (!requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) return true;
if (item.OwnInventory == null) return false;
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Contained])
{
Item containedItem = Array.Find(containedItems, x => x != null && x.Condition > 0.0f && ri.MatchesItem(x));
if (containedItem == null)
if (!item.OwnInventory.Items.Any(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)))
{
#if CLIENT
if (addMessage && !string.IsNullOrEmpty(ri.Msg)) GUI.AddMessage(ri.Msg, Color.Red);
@@ -507,57 +571,72 @@ namespace Barotrauma.Items.Components
if (!requiredItems.Any()) return true;
if (character.Inventory == null) return false;
foreach (RelatedItem ri in requiredItems)
if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped))
{
if (!ri.Type.HasFlag(RelatedItem.RelationType.Equipped) && !ri.Type.HasFlag(RelatedItem.RelationType.Picked)) continue;
bool hasItem = false;
if (ri.Type.HasFlag(RelatedItem.RelationType.Equipped))
{
if (character.SelectedItems.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) != null) hasItem = true;
}
if (!hasItem && ri.Type.HasFlag(RelatedItem.RelationType.Picked))
{
if (character.Inventory.Items.FirstOrDefault(x => x != null && x.Condition > 0.0f && ri.MatchesItem(x)) != null) hasItem = true;
}
if (!hasItem)
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Equipped])
{
if (character.SelectedItems.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null)
{
#if CLIENT
if (addMessage && !string.IsNullOrEmpty(ri.Msg)) GUI.AddMessage(ri.Msg, Color.Red);
#endif
return false;
return false;
}
}
}
if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked))
{
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked])
{
if (character.Inventory.Items.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null)
{
#if CLIENT
if (addMessage && !string.IsNullOrEmpty(ri.Msg)) GUI.AddMessage(ri.Msg, Color.Red);
#endif
return false;
}
}
}
return true;
}
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null)
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Character user = null)
{
if (statusEffectLists == null) return;
List<StatusEffect> statusEffects;
if (!statusEffectLists.TryGetValue(type, out statusEffects)) return;
if (!statusEffectLists.TryGetValue(type, out List<StatusEffect> statusEffects)) return;
bool broken = item.Condition <= 0.0f;
foreach (StatusEffect effect in statusEffects)
{
item.ApplyStatusEffect(effect, type, deltaTime, character);
if (broken && effect.type != ActionType.OnBroken) { continue; }
if (user != null) { effect.SetUser(user); }
item.ApplyStatusEffect(effect, type, deltaTime, character, targetLimb, false, false);
}
}
public virtual void Load(XElement componentElement)
{
if (componentElement == null) return;
if (componentElement == null) return;
foreach (XAttribute attribute in componentElement.Attributes())
{
SerializableProperty property = null;
if (!properties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out property)) continue;
if (!properties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
property.TrySetValue(attribute.Value);
}
List<RelatedItem> prevRequiredItems = new List<RelatedItem>(requiredItems);
#if CLIENT
string msg = TextManager.Get(Msg, true);
if (msg != null)
{
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
{
msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString());
}
Msg = msg;
}
#endif
var prevRequiredItems = new Dictionary<RelatedItem.RelationType, List<RelatedItem>>(requiredItems);
bool overrideRequiredItems = false;
foreach (XElement subElement in componentElement.Elements())
@@ -568,18 +647,22 @@ namespace Barotrauma.Items.Components
if (!overrideRequiredItems) requiredItems.Clear();
overrideRequiredItems = true;
RelatedItem newRequiredItem = RelatedItem.Load(subElement);
RelatedItem newRequiredItem = RelatedItem.Load(subElement, item.Name);
if (newRequiredItem == null) continue;
var prevRequiredItem = prevRequiredItems.Find(ri => ri.JoinedNames == newRequiredItem.JoinedNames);
if (prevRequiredItem!=null)
var prevRequiredItem = prevRequiredItems.ContainsKey(newRequiredItem.Type) ?
prevRequiredItems[newRequiredItem.Type].Find(ri => ri.JoinedIdentifiers == newRequiredItem.JoinedIdentifiers) : null;
if (prevRequiredItem != null)
{
newRequiredItem.statusEffects = prevRequiredItem.statusEffects;
newRequiredItem.Msg = prevRequiredItem.Msg;
}
requiredItems.Add(newRequiredItem);
if (!requiredItems.ContainsKey(newRequiredItem.Type))
{
requiredItems[newRequiredItem.Type] = new List<RelatedItem>();
}
requiredItems[newRequiredItem.Type].Add(newRequiredItem);
break;
}
}
@@ -594,7 +677,10 @@ namespace Barotrauma.Items.Components
/// Called when all the components of the item have been loaded. Use to initialize connections between components and such.
/// </summary>
public virtual void OnItemLoaded() { }
// TODO: Consider using generics, interfaces, or inheritance instead of reflection -> would be easier to debug when something changes/goes wrong.
// For example, currently we can edit the constructors but they will fail in runtime because the parameters are not changed here.
// It's also painful to find where the constructors are used, because the references exist only at runtime.
public static ItemComponent Load(XElement element, Item item, string file, bool errorMessages = true)
{
Type t;
@@ -604,7 +690,7 @@ namespace Barotrauma.Items.Components
// Get the type of a specified class.
t = Type.GetType("Barotrauma.Items.Components." + type + "", false, true);
if (t == null)
{
{
if (errorMessages) DebugConsole.ThrowError("Could not find the component \"" + type + "\" (" + file + ")");
return null;
}
@@ -631,13 +717,11 @@ namespace Barotrauma.Items.Components
DebugConsole.ThrowError("Could not find the constructor of the component \"" + type + "\" (" + file + ")", e);
return null;
}
ItemComponent ic = null;
try
{
object[] lobject = new object[] { item, element };
object component = constructor.Invoke(lobject);
ic = (ItemComponent)component;
ic.name = element.Name.ToString();
}
@@ -656,13 +740,17 @@ namespace Barotrauma.Items.Components
{
XElement componentElement = new XElement(name);
foreach (RelatedItem ri in requiredItems)
foreach (var kvp in requiredItems)
{
XElement newElement = new XElement("requireditem");
ri.Save(newElement);
componentElement.Add(newElement);
foreach (RelatedItem ri in kvp.Value)
{
XElement newElement = new XElement("requireditem");
ri.Save(newElement);
componentElement.Add(newElement);
}
}
SerializableProperty.SerializeProperties(this, componentElement);
parentElement.Add(componentElement);