using System.Xml; using System.Xml.Linq; using UnityEngine; /// /// /// Changes the target's relationship with the specified faction, and all the specified related /// factions (if any), according to the relationships between the faction and the related factions. /// /// /// Supported tag attributes: /// /// /// target /// /// The entity target(s), to change relationships with the factions. /// Valid target values: "self", "other", "selfAOE", "otherAOE", "positionAOE". /// In most cases you should use "self" (the player). /// Required. /// /// /// /// range /// /// Maximum range (distance in meters) to include entities as targets. /// Used only when the target is one of the AOE (Area Of Effect) values. /// Optional. /// /// /// /// target_tags /// /// Adds entities with these tags, to the list of entity targets. /// Special tag values: "party", "ally", "enemy". /// Optional. /// /// /// /// faction /// /// The primary faction whose relationship will change with the target. /// Required. /// /// /// /// value /// /// The amount to add to the relationship between the target and "primary" faction. /// Positive numbers represent amity, negative numbers represent antagonism. /// It takes 200 points to change a faction relationship entirely /// (e.g. from "neutral" to "like"). /// Required. /// /// /// /// related /// /// One or more related factions, whose relationships will change with the target /// according to each one's relationship with the primary faction. /// It should be a comma-separated list of faction names (without spaces). /// You can not include either the target's faction, nor the "primary" faction. /// Optional; if not specified, no faction relationships are affected, other than the /// one between the target and primary faction. /// In this case, it behaves exactly like the ModifyFactionSDX action. /// /// /// /// scale /// /// A ratio by which to scale the target relationship to related factions. /// Suggested values are between 0 and 1 (exclusive). /// Optional; defaults to 1. /// (Ignored if "related" is not specified.) /// /// /// /// /// /// Default multiplier, to determine the relationship value betwen the target and each related /// faction, by related faction's relationship with the primary faction. /// These multipliers are then multiplied by the "scale" property (if specified). /// /// /// Relationship to primary faction /// Value multiplier /// /// /// Hate /// -0.6666667 /// /// /// Dislike /// -0.3333333 /// /// /// Neutral /// 0 (no effect) /// /// /// Like /// 0.3333333 /// /// /// Love /// 0.6666667 /// /// /// Leader /// 1.0 /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public class MinEventActionModifyRelatedFactionsSDX : MinEventActionTargetedBase { private readonly bool debug = false; // for logging when testing private string faction = ""; private string[] relatedFactions; private float scale = 1f; private float value; public override void Execute(MinEventParams _params) { if (debug) Debug.Log("MinEventActionModifyRelatedFactionsSDX.Execute..."); for (var i = 0; i < targets.Count; i++) { var entity = targets[i]; if (entity != null) { var otherFaction = FactionManager.Instance.GetFactionByName(faction); if (otherFaction != null) { otherFaction.ModifyRelationship(entity.factionId, value); if (debug) Debug.Log(string.Format("relationship to {0} modified by {1}", faction, value)); ModifyRelatedFactionRelationships(entity.factionId, otherFaction); } } } } private void ModifyRelatedFactionRelationships(byte targetEntityFactionId, Faction otherFaction) { if (relatedFactions == null) return; for (var i = 0; i < relatedFactions.Length; i++) { var relatedFaction = FactionManager.Instance.GetFactionByName(relatedFactions[i]); // Guard against users entering a related faction name that doesn't exist, is the // name of a target entity's faction, or is the same as the "faction" attribute if (relatedFaction != null && relatedFaction.ID != otherFaction.ID && relatedFaction.ID != targetEntityFactionId) { var modifier = CalculateRelatedFactionModifier( relatedFaction.GetRelationship(otherFaction.ID)); relatedFaction.ModifyRelationship(targetEntityFactionId, modifier); if (debug) Debug.Log(string.Format("relationship to {0} modified by {1}", relatedFactions[i], modifier)); } } } private float CalculateRelatedFactionModifier(float relationshipToFaction) { float ratio = 1; // default to Leader if (relationshipToFaction < 200f) // Hate ratio = -0.6666667f; else if (relationshipToFaction < 400f) // Dislike ratio = -0.3333333f; else if (relationshipToFaction < 600f) // Neutral ratio = 0f; else if (relationshipToFaction < 800f) // Like ratio = 0.3333333f; else if (relationshipToFaction < 1001f) // Love ratio = 0.6666667f; var relationshipToTarget = ratio * value * scale; // The value 255f has a special meaning in TFP code, so avoid it return relationshipToTarget == 255f ? relationshipToTarget + 1 : relationshipToTarget; } public override bool ParseXmlAttribute(XAttribute _attribute) { if (base.ParseXmlAttribute(_attribute)) return true; var name = _attribute.Name.LocalName; if (name == "faction") { faction = _attribute.Value.Trim(); return true; } if (name == "value") { value = StringParsers.ParseFloat(_attribute.Value); return true; } if (name == "related") { relatedFactions = ParseArray(_attribute.Value); return true; } if (name == "scale") { scale = StringParsers.ParseFloat(_attribute.Value); return true; } return false; } private static string[] ParseArray(string str) { var subs = str.Split(','); for (var i = 0; i < subs.Length; i++) subs[i] = subs[i].Trim(); return subs; } }