public static DialogueResponse getResponses(int day, List<int> ChoiceChildren, Character.Player player) { string childrenString = ""; int childCounter = 0; int id = 0; List<int> children = new List<int>(); int responseDay = 0; List<Condition> conditions = new List<Condition>(); List<effect> effects = new List<effect>(); string text = ""; int ResponseCounter = 0; List<DialogueResponse> UnparsedResponses = new List<DialogueResponse>(); foreach (int child in ChoiceChildren) { childCounter += 1; if (childCounter < ChoiceChildren.Count) { childrenString = childrenString + "id = " + child + " or "; } else { childrenString = childrenString + "id = " + child; } } string strExpression = "/dialogue/dialogueResponse[(" + childrenString + ") and @day='" + day.ToString() + "']/*"; XPathDocument dialogueFile = new XPathDocument(DialogueFileLocation); XPathNavigator nav = dialogueFile.CreateNavigator(); XPathNodeIterator nodeIter = nav.Select(strExpression); //we've selected all the child dialogue choices. Now we need to read them into dialogueChoice objects. while (nodeIter.MoveNext()) { switch (nodeIter.Current.Name) { case "children": //read and parse this comma delimited string, turn it into a List<int> object String ChildrenString = nodeIter.Current.Value; string[] childrenArray = ChildrenString.Split(','); foreach (string s in childrenArray) { children.Add(Convert.ToInt32(s)); } break; case "condition": //create condition and add it to condition list. Condition condition = new Condition(); //go through condition attribute values and populate the condition object with them. String subject = nodeIter.Current.GetAttribute("subject", ""); condition.Subject = subject; String attribute = nodeIter.Current.GetAttribute("attribute", ""); condition.Attribute = attribute; String upperLimit = nodeIter.Current.GetAttribute("upperLimit", ""); if (upperLimit != "") condition.UpperLimit = Convert.ToInt32(upperLimit); String lowerLimit = nodeIter.Current.GetAttribute("lowerLimit", ""); if (lowerLimit != "") condition.LowerLimit = Convert.ToInt32(lowerLimit); String value = nodeIter.Current.Value; if (value != "") condition.Value = Convert.ToInt32(value); String type = nodeIter.Current.GetAttribute("type", ""); condition.Type = type; String decisionID = nodeIter.Current.GetAttribute("id", ""); if (decisionID != "") condition.DecisionID = Convert.ToInt32(decisionID); conditions.Add(condition); break; case "effect": effect effect = new effect(); String effectType = nodeIter.Current.GetAttribute("type", ""); effect.type = effectType; String effectSubject = nodeIter.Current.GetAttribute("subject", ""); effect.Subject = effectSubject; String effectAttribute = nodeIter.Current.GetAttribute("attribute", ""); effect.Attribute = effectAttribute; String effectChange = nodeIter.Current.GetAttribute("change", ""); if (effectChange != "") effect.change = Convert.ToInt32(effectChange); String effectDecisionId = nodeIter.Current.GetAttribute("id", ""); if (effectDecisionId != "") effect.DecisionID = Convert.ToInt32(effectDecisionId); String decisionValue = nodeIter.Current.Value; int n; if (Int32.TryParse(decisionValue, out n)) effect.DecisionValue = Convert.ToInt32(decisionValue); String effectDescription = nodeIter.Current.GetAttribute("desc", ""); effect.Description = effectDescription; effects.Add(effect); break; case "text": text = nodeIter.Current.Value; break; case "id": //add one to the response counter - we got a new response! ResponseCounter += 1; id = Convert.ToInt32(nodeIter.Current.Value); //Now we can create a new response object and fill it. DialogueResponse Response = new DialogueResponse(); Response.Day = day; Response.ID = id; Response.Text = text; Response.children = children; Response.Conditions = conditions; Response.Effects = effects; //Add new response to response list UnparsedResponses.Add(Response); //reset values to default for the next dialogue id = 0; text = ""; children = new List<int>(); conditions = new List<Condition>(); break; } } DialogueResponse parsedResponses = ParseResponses(UnparsedResponses, player); return parsedResponses; }
public static DialogueResponse ParseResponses(List<DialogueResponse> responses, Character.Player player) { DialogueResponse finalResponse = new DialogueResponse(); bool saveResponse = true; foreach (DialogueResponse response in responses) { saveResponse = true; //cycle through each condition, and see if it applies. for (int i = 0; i < response.Conditions.Count; i++) { Condition currentCondition = response.Conditions[i]; //there are two types of conditions, ones based on decisions, and ones based relationships. They have different requirnments to be valid. switch (currentCondition.Type) { case ("rel"): //check if this condition has all the necessary attributes. If not, throw an error. if (currentCondition.Subject == null || currentCondition.Attribute == null || currentCondition.UpperLimit == null || currentCondition.LowerLimit == null) { throw new System.InvalidOperationException("This condition is a type 'rel' but doesnt have the necessary attributes: Subject, Attribute, Compare, Value"); } else { //test condition if (currentCondition.Subject != "player") { Character.NPC npcSubject = (Quarantine.NPCs.Find(npc => npc.Name == currentCondition.Subject)); //we found the NPC who is the subject of this condition var property = typeof(Character.NPC).GetProperty(currentCondition.Attribute); var propValue = Convert.ToInt32(property.GetValue(npcSubject, null)); Console.WriteLine(String.Format("{0} is the subject; his/her {1} attribute has a value of {2}", npcSubject.Name, property.Name, propValue)); //find out if this condition is met. If not, remove its parent response from the list if (propValue <= currentCondition.UpperLimit && propValue >= currentCondition.LowerLimit) { Console.WriteLine("Response Condition Accepted!, {0} is between the lower limit {1} and the upper limit {2}", property.Name, currentCondition.LowerLimit, currentCondition.UpperLimit); finalResponse = response; } else { saveResponse = false; } } else { // subject of this condition is the player. } //Let's set a value //property.SetValue(npcSubject, 99, null); //var newPropValue = property.GetValue(npcSubject, null); //Console.WriteLine(String.Format("{0} has a value of {1}", property.Name, newPropValue)); } break; case ("dec"): //check if this condition has all the necessary attributes If not, throw an error. if (currentCondition.DecisionID == 0 || currentCondition.Value == 0) { throw new System.InvalidOperationException("This condition is a type 'dec' but doesnt have the necessary attributes: DecisionID, Value"); } else { //see if the given value matches the player's given value for this decision, if it exists. Character.Player currentPlayer = Quarantine.Player; if ((player.decisions.FindIndex(decision => decision.id == currentCondition.DecisionID)) != null) { //the player has made this decision int index = (player.decisions.FindIndex(decision => decision.id == currentCondition.DecisionID)); if (player.decisions[index].value == currentCondition.Value) { } else { saveResponse = false; } } else { //the player has not made this choice, or their choice doesnt match the condition. saveResponse = false; } } break; } } //remove it from the list of responses if necessary if (saveResponse == true) { finalResponse = response; } } return finalResponse; }
public static List<DialogueResponse> getDialogueRoot(int day, Character.Player player) { int id = 0; List<int> children = new List<int>(); int Rday = 0; List<Condition> conditions = new List<Condition>(); List<effect> effects = new List<effect>(); string text = ""; int ResponseCounter = 0; List<DialogueResponse> RootResponses = new List<DialogueResponse>(); //select all dialogueResponse elements with attribute root=1, on a day which matches the current day, and the players current location. string strExpression = "/dialogue/dialogueResponse[@root='1' and @day='" + day.ToString() + "' and @location='" + player.Location.ToString() + "']/*"; XPathDocument dialogueFile = new XPathDocument(DialogueFileLocation); XPathNavigator nav = dialogueFile.CreateNavigator(); XPathNodeIterator nodeIter = nav.Select(strExpression); while (nodeIter.MoveNext()) { //we've located the dialogueResponses we're interested in. Now we need to read and assign their child elements. switch (nodeIter.Current.Name) { case "children": //read and parse this comma delimited string, turn it into a List<int> object String ChildrenString = nodeIter.Current.Value; string[] childrenArray = ChildrenString.Split(','); foreach (string s in childrenArray) { children.Add(Convert.ToInt32(s)); } break; case "condition": //create condition and add it to condition list. Condition condition = new Condition(); //go through condition attribute values and populate the condition object with them. String subject = nodeIter.Current.GetAttribute("subject",""); condition.Subject = subject; String attribute = nodeIter.Current.GetAttribute("attribute", ""); condition.Attribute = attribute; String upperLimit = nodeIter.Current.GetAttribute("upperLimit", ""); if (upperLimit != "") condition.UpperLimit = Convert.ToInt32(upperLimit); String lowerLimit = nodeIter.Current.GetAttribute("lowerLimit", ""); if (lowerLimit != "") condition.LowerLimit = Convert.ToInt32(lowerLimit); String value = nodeIter.Current.Value; if (value !="") condition.Value = Convert.ToInt32(value); String type = nodeIter.Current.GetAttribute("type", ""); condition.Type = type; String decisionID = nodeIter.Current.GetAttribute("id", ""); if (decisionID != "") condition.DecisionID = Convert.ToInt32(decisionID); conditions.Add(condition); break; case "effect": effect effect = new effect(); String effectType = nodeIter.Current.GetAttribute("type",""); effect.type = effectType; String effectSubject = nodeIter.Current.GetAttribute("subject", ""); effect.Subject = effectSubject; String effectAttribute = nodeIter.Current.GetAttribute("attribute", ""); effect.Attribute = effectAttribute; String effectChange = nodeIter.Current.GetAttribute("change", ""); if(effectChange != "") effect.change = Convert.ToInt32(effectChange); String effectDecisionId = nodeIter.Current.GetAttribute("id", ""); if (effectDecisionId != "") effect.DecisionID = Convert.ToInt32(effectDecisionId); String decisionValue = nodeIter.Current.Value; int n; if (Int32.TryParse(decisionValue, out n)) effect.DecisionValue = Convert.ToInt32(decisionValue); String effectDescription = nodeIter.Current.GetAttribute("desc", ""); effect.Description = effectDescription; effects.Add(effect); break; case "text": text = nodeIter.Current.Value; break; case "id": //add one to the response counter - we got a new response! ResponseCounter += 1; id = Convert.ToInt32(nodeIter.Current.Value); //Now we can create a new response object and fill it. DialogueResponse Response = new DialogueResponse(); Response.ID = id; Response.Text = text; Response.children = children; Response.Conditions = conditions; Response.Effects = effects; //Add new response to response list RootResponses.Add(Response); //reset values to default for the next dialogue id = 0; text = ""; children = new List<int>(); conditions = new List<Condition>(); break; } //throw new System.InvalidOperationException("No Root Dialogue was found!"); } ParseResponses(RootResponses, player); return RootResponses; }