private void AssignStatusContext(HaJSElement parent, HashSet <int> currContext) { // Set this element statusContext currContext.ToList().ForEach(x => parent.statusContext.Add(x)); // If we are a context switcher, update context now (in cases like OptionsMessageElement children need to be cast at the final context) if (parent.ControlFlowBreaker) { currContext.Clear(); currContext.Add(((MessageBaseElement)parent).NextStatus); } // Handle children (forking) if (parent.HasChildren) { if (parent.Parallel) // Parallel fork { HashSet <int> resultContext = new HashSet <int>(); foreach (HaJSElement element in parent.Children) { HashSet <int> elementExitContext = new HashSet <int>(currContext); AssignStatusContext(element, elementExitContext); elementExitContext.ToList().ForEach(x => resultContext.Add(x)); } currContext.Clear(); resultContext.ToList().ForEach(x => currContext.Add(x)); } else // Serial fork { parent.Children.ForEach(x => AssignStatusContext(x, currContext)); } } }
public override string PostCompile(HaJSCompiler compiler, HaJSElement parent) { StringBuilder sb = new StringBuilder(); sb.AppendLine("if (mode == 0)"); sb.AppendLine("{"); sb.AppendLine(IndentedStringBuilder.Indent + compiler.GetFeature("dlg_Ok").Compile(compiler, Stringify(noText))); sb.AppendLine(IndentedStringBuilder.Indent + compiler.GetFeature("special_End").Compile(compiler)); sb.AppendLine(IndentedStringBuilder.Indent + "return;"); sb.AppendLine("}"); return(sb.ToString()); }
public override string PostCompile(HaJSCompiler compiler, HaJSElement parent) { StringBuilder sb = new StringBuilder(); sb.AppendLine("if (mode == 0)"); sb.AppendLine("{"); sb.AppendLine(IndentedStringBuilder.Indent + "status = " + GetPreviousStatus(parent).ToString()); sb.AppendLine(IndentedStringBuilder.Indent + "action(1,0,0);"); sb.AppendLine(IndentedStringBuilder.Indent + "return;"); sb.AppendLine("}"); return(sb.ToString()); }
private int GetPreviousStatus(HaJSElement parent) { MessageBaseElement prev = null; foreach (HaJSElement child in parent.Children) { if (!(child is MessageBaseElement)) { continue; } if (child == this) { return(prev == null ? -1 : prev.statusContext.ElementAt(0)); } else { prev = (MessageBaseElement)child; } } throw new ArgumentException("Internal error - element is not a child of the parent supplied"); }
private string CompileInternal(XmlElement element) { switch (element.Name) { case "npc": manager = "cm"; break; case "quest": manager = "qm"; break; default: throw new ArgumentException("Unknown script type \"" + element.Name + "\""); } resources = new Dictionary <string, string>(); deps = new HashSet <string>(); messages = new List <MessageBaseElement>(); sbl = new Dictionary <HashSet <int>, IndentedStringBuilder>(); contexts = new List <HashSet <int> >(); bool hasRsrc = element.GetElementsByTagName("resources").Count > 0; if (hasRsrc) { foreach (XmlElement rsrcElement in element.GetElementsByTagName("resources")[0]) { resources.Add(rsrcElement.GetAttribute("name"), rsrcElement.GetAttribute("text")); } } List <HaJSElement> mainList = new List <HaJSElement>(); BuildElementRecursive((XmlElement)element.ChildNodes[hasRsrc ? 1 : 0], ref mainList); HaJSElement mainElement = mainList[0]; HashSet <int> startingContext = new HashSet <int>(); startingContext.Add(-1); AssignStatusContext(mainElement, startingContext); CompileJSRecursive(mainElement, null); StringBuilder sb = new StringBuilder(); sb.AppendLine("/* This script was automatically generated by HaJS on " + DateTime.Today.ToShortDateString() + " */"); foreach (string dep in deps) { sb.AppendLine("importPackage(" + dep + ");"); } if (manager == "cm") { sb.AppendLine("var status = 0;"); sb.AppendLine("function start() {"); sb.AppendLine(" status = -1;"); sb.AppendLine(" action(1, 0, 0);"); sb.AppendLine("}"); sb.AppendLine("function action(mode, type, selection) {"); sb.AppendLine(" if (mode == -1) {"); sb.AppendLine(" cm.dispose();"); sb.AppendLine(" } else {"); } else if (manager == "qm") { sb.AppendLine("var status = -1;"); sb.AppendLine("function start(mode, type, selection) {"); sb.AppendLine(" if (mode == -1) {"); sb.AppendLine(" qm.dispose();"); sb.AppendLine(" } else {"); } foreach (HashSet <int> context in contexts) { sb.AppendLine(" if (" + context.ToList().Select(x => "status == " + x.ToString()).Aggregate((x, y) => x + " || " + y) + ")"); sb.AppendLine(" {"); sb.Append(sbl[context].ToString()); sb.AppendLine(" }"); } sb.AppendLine(" }"); sb.AppendLine("}"); return(sb.ToString()); }
private void CompileJSRecursive(HaJSElement root, HaJSElement parent) { IndentedStringBuilder sb = GetStringBuilderByContext(root.statusContext); if (root is SwitchElement) { SwitchElement se = (SwitchElement)root; for (int i = 0; i < se.Children.Count; i++) { CaseElement ce = (CaseElement)se.Children[i]; sb.AppendLine(ce.Compile(this, se.Type, i == 0)); sb.Enter(); CompileJSRecursive(ce, root); sb.Leave(); } } else if (root.HasChildren && !root.Parallel) { root.Children.ForEach(x => CompileJSRecursive(x, root)); } else if (root is CommandElement) { CommandElement ce = (CommandElement)root; sb.AppendLine(ce.Compile(this)); } else if (root is MessageBaseElement) { MessageBaseElement mbe = (MessageBaseElement)root; if (mbe.ControlFlowBreaker) { WriteStatusChange(sb, mbe.NextStatus); } sb.AppendLine(mbe.Compile(this)); if (mbe is OkMessageElement) { sb.AppendLine(GetFeature("special_End").Compile(this)); } sb.AppendLine("return;"); string postCompileData = mbe.PostCompile(this, parent); if (root is OptionsMessageElement) { // Special case handled here because OptionMessages are complicated OptionsMessageElement ome = (OptionsMessageElement)root; sb = GetStringBuilderByContext(new HashSet <int>() { ome.NextStatus }); for (int i = 0; i < ome.Children.Count; i++) { OptionElement oe = (OptionElement)ome.Children[i]; sb.AppendLine((i == 0 ? "if" : "else if") + " (selection == " + i.ToString() + ")"); sb.Enter(); CompileJSRecursive(oe, root); sb.Leave(); } } else if (postCompileData != null) { GetStringBuilderByContext(new HashSet <int>() { mbe.NextStatus }).Append(postCompileData); } } }
public virtual string PostCompile(HaJSCompiler compiler, HaJSElement parent) { return(null); }