public Node(int index, int indent, ScriptNode scriptNode, TranslatedScript ts) { this.index = index; this.indent = indent; this.scriptNode = scriptNode; this.children = new List <Node>(); this.ts = ts; }
public string ToString(Perso perso) { if (scriptNode != null) { string firstChildNode = (this.children.Count > 0 && this.children[0] != null) ? this.children[0].ToString() : "null"; string secondChildNode = (this.children.Count > 1 && this.children[1] != null) ? this.children[1].ToString() : "null"; string prefix = (ts.printAddresses ? "{" + scriptNode.offset.ToString() + "}" : ""); AITypes aiTypes = Settings.s.aiTypes; uint param = scriptNode.param; switch (scriptNode.nodeType) { case ScriptNode.NodeType.KeyWord: string keyword = param < aiTypes.keywordTable.Length ? aiTypes.keywordTable[param] : ""; switch (keyword) { // If keywords case "If": return(prefix + "if ({condition})".Replace("{condition}", firstChildNode)); case "IfNot": return(prefix + "if (!({condition}))".Replace("{condition}", firstChildNode)); case "If2": return(prefix + "if (globalRandomizer % 2 == 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "If4": return(prefix + "if (globalRandomizer % 4 == 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "If8": return(prefix + "if (globalRandomizer % 8 == 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "If16": return(prefix + "if (globalRandomizer % 16 == 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "If32": return(prefix + "if (globalRandomizer % 32 == 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "If64": return(prefix + "if (globalRandomizer % 64 == 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfNot2": return(prefix + "if (globalRandomizer % 2 != 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfNot4": return(prefix + "if (globalRandomizer % 4 != 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfNot8": return(prefix + "if (globalRandomizer % 8 != 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfNot16": return(prefix + "if (globalRandomizer % 16 != 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfNot32": return(prefix + "if (globalRandomizer % 32 != 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfNot64": return(prefix + "if (globalRandomizer % 64 != 0 && ({condition}))".Replace("{condition}", firstChildNode)); case "IfDebug": return(prefix + "if (debug && {condition})".Replace("{condition}", firstChildNode)); case "IfNotU64": return(prefix + "if (!u64)\n{\n{childNodes}\n}\n".Replace("{childNodes}", string.Join("\n", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())))); // Then case "Then": return(prefix + "{\n{childNodes}\n}\n".Replace("{childNodes}", string.Join("\n", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())))); // Else case "Else": return(prefix + "else\n{\n{childNodes}\n}\n".Replace("{childNodes}", string.Join("\n", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())))); default: return(prefix + scriptNode.ToString(perso, ts.settings)); } case ScriptNode.NodeType.Condition: string cond = param < aiTypes.conditionTable.Length ? aiTypes.conditionTable[param] : ""; switch (cond) { // Boolean conditions: case "Cond_And": return(prefix + firstChildNode + " && " + secondChildNode); case "Cond_Or": return(prefix + firstChildNode + " || " + secondChildNode); case "Cond_Not": return(prefix + "!" + "(" + firstChildNode + ")"); case "Cond_XOR": return(prefix + firstChildNode + " != " + secondChildNode); // XOR // Real (float) comparisons: case "Cond_Equal": return(prefix + firstChildNode + " == " + secondChildNode); case "Cond_Different": return(prefix + firstChildNode + " != " + secondChildNode); case "Cond_Lesser": return(prefix + firstChildNode + " < " + secondChildNode); case "Cond_Greater": return(prefix + firstChildNode + " > " + secondChildNode); case "Cond_LesserOrEqual": return(prefix + firstChildNode + " <= " + secondChildNode); case "Cond_GreaterOrEqual": return(prefix + firstChildNode + " >= " + secondChildNode); // Button condition: /*case 44: * case 45: * case 46: * case 47: * return prefix + firstChildNode;*/ default: if (firstChildNode != null) { return(prefix + scriptNode.ToString(perso, ts.settings) + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ")"); } else { return(prefix + scriptNode.ToString(perso, ts.settings) + "()"); } } case ScriptNode.NodeType.Function: string function = param < aiTypes.functionTable.Length ? aiTypes.functionTable[param] : ""; string ternaryCheck = ""; switch (function) { // Ternary real operators (e.g. x > y ? true : false) case "Func_TernInf": case "Func_TernSup": case "Func_TernEq": case "Func_TernInfEq": case "Func_TernSupEq": switch (function) { case "Func_TernInf": ternaryCheck = " < "; break; case "Func_TernSup": ternaryCheck = " > "; break; case "Func_TernEq": ternaryCheck = " == "; break; case "Func_TernInfEq": ternaryCheck = " <= "; break; case "Func_TernSupEq": ternaryCheck = " >= "; break; } if (this.children.Count >= 4) { return(prefix + "((" + this.children[0] + ternaryCheck + this.children[1] + ") ? " + this.children[2] + " : " + this.children[3] + ")"); } else { return("ERROR"); } case "Func_TernOp": // conditional ternary operator (cond ? true : false) string childCast1 = ""; string childCast2 = ""; if (this.children[1].scriptNode.nodeType == ScriptNode.NodeType.DsgVarRef && this.children[2].scriptNode.nodeType == ScriptNode.NodeType.Real) { childCast1 = "(float)"; } if (this.children[2].scriptNode.nodeType == ScriptNode.NodeType.DsgVarRef && this.children[1].scriptNode.nodeType == ScriptNode.NodeType.Real) { childCast2 = "(float)"; } return(prefix + "((" + this.children[0] + ") ? " + childCast1 + this.children[1] + " : " + childCast2 + this.children[2] + ")"); default: string func = scriptNode.ToString(perso, ts.settings); return(prefix + func + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ")"); } case ScriptNode.NodeType.Procedure: string procedure = param < aiTypes.procedureTable.Length ? aiTypes.procedureTable[param] : ""; switch (procedure) { case "Proc_Loop": return(prefix + "for(int i = 0; i < " + firstChildNode + "; i++)\n{"); case "Proc_EndLoop": return(prefix + "}\n"); case "Proc_Break": return(prefix + "break;\n"); default: string proc = scriptNode.ToString(perso, ts.settings); return(prefix + proc + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ");"); } case ScriptNode.NodeType.Operator: string op = param < aiTypes.operatorTable.Length ? aiTypes.operatorTable[param] : ""; Pointer persoPtr = null; switch (op) { // scalar: case "Operator_Plus": return("(" + firstChildNode + (children[1].scriptNode.param >= 0 ? " + " : "") + secondChildNode + ")"); case "Operator_Minus": case "Operator_UnaryMinus": if (children.Count > 1) { return("(" + firstChildNode + " - " + secondChildNode + ")"); } else { return("-" + firstChildNode); } case "Operator_Mul": return("(" + firstChildNode + " * " + secondChildNode + ")"); case "Operator_Div": return("(" + firstChildNode + " / " + secondChildNode + ")"); case "Operator_Mod": return("(" + firstChildNode + " % " + secondChildNode + ")"); // affect: case "Operator_PlusAffect": case "Operator_PlusPlusAffect": return(children.Count > 1 ? (firstChildNode + " += " + secondChildNode + ";") : firstChildNode + "++" + ";"); case "Operator_MinusAffect": case "Operator_MinusMinusAffect": return(children.Count > 1 ? (firstChildNode + " -= " + secondChildNode + ";") : firstChildNode + "--" + ";"); case "Operator_MulAffect": return(firstChildNode + " *= " + secondChildNode + ";"); case "Operator_DivAffect": return(firstChildNode + " /= " + secondChildNode + ";"); case "Operator_Affect": return(firstChildNode + " = " + secondChildNode + ";"); case "Operator_Dot": // dot operator persoPtr = this.children[0].scriptNode.param_ptr; if (persoPtr != null) { Perso firstNodePerso = Perso.FromOffset(persoPtr); /*if (firstNodePerso != null) { * string secondChildNodeWithDifferentContext = (this.children.Count > 1 && this.children[1] != null) ? this.children[1].ToString(firstNodePerso) : "null"; * return firstChildNode + "." + secondChildNodeWithDifferentContext; * } else {*/ return(firstChildNode + "." + this.children[1].ToString(null)); //} } return(firstChildNode + "." + secondChildNode); case ".X": return(firstChildNode + ".x"); // vector case ".Y": return(firstChildNode + ".y"); // vector case ".Z": return(firstChildNode + ".z"); // vector case "Operator_VectorPlusVector": return(firstChildNode + " + " + secondChildNode); case "Operator_VectorMinusVector": return(firstChildNode + " - " + secondChildNode); case "Operator_VectorMulScalar": return(firstChildNode + " * " + secondChildNode); case "Operator_VectorDivScalar": return(firstChildNode + " / " + secondChildNode); case "Operator_VectorUnaryMinus": return("-" + firstChildNode); case ".X:=": return(firstChildNode + ".x = " + secondChildNode + ";"); // vector case ".Y:=": return(firstChildNode + ".y = " + secondChildNode + ";"); // vector case ".Z:=": return(firstChildNode + ".z = " + secondChildNode + ";"); // vector case "Operator_Ultra": // Ultra operator (execute code for different object) return(firstChildNode + ".{code}".Replace("{code}", secondChildNode)); case "Operator_ModelCast": return("((" + firstChildNode + ")(" + secondChildNode + "))"); case "Operator_Array": return(firstChildNode + "[" + secondChildNode + "]"); default: string proc = "(" + scriptNode.param + ")" + scriptNode.ToString(perso, ts.settings); return(prefix + proc + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ");"); } case ScriptNode.NodeType.Field: if (firstChildNode != null) { return(prefix + scriptNode.ToString(perso, ts.settings) + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ")"); } else { return(prefix + scriptNode.ToString(perso, ts.settings)); } case ScriptNode.NodeType.Vector: case ScriptNode.NodeType.ConstantVector: return(prefix + scriptNode.ToString(perso, ts.settings) + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ")"); case ScriptNode.NodeType.MetaAction: return(prefix + scriptNode.ToString(perso, ts.settings) + "(" + string.Join(", ", Array.ConvertAll <Node, String>(this.children.ToArray(), x => x.ToString())) + ");"); case ScriptNode.NodeType.SubRoutine: if (ts.expandMacros) { Macro macro = MapLoader.Loader.FromOffset <Macro>(scriptNode.param_ptr); if (macro != null) { string macroString = "// evalMacro(" + macro.ShortName + ");"; macroString += Environment.NewLine; TranslatedScript macroScript = new TranslatedScript(macro.script, perso); macroScript.expandMacros = true; macroString += macroScript.ToString(); macroString += Environment.NewLine + "// end macro"; return(macroString); } } return(prefix + scriptNode.ToString(perso, ts.settings)); default: return(prefix + scriptNode.ToString(perso, ts.settings)); } } else // Root node returns all children concatenated { string result = ""; foreach (Node child in this.children) { result += child.ToString() + '\n'; } return(result); } }