public AITypes(AITypes original) { keywordTable = original.keywordTable; operatorTable = original.operatorTable; functionTable = original.functionTable; procedureTable = original.procedureTable; conditionTable = original.conditionTable; dsgVarTypeTable = original.dsgVarTypeTable; fieldTable = original.fieldTable; metaActionTable = original.metaActionTable; nodeTypes = original.nodeTypes; }
public string ToString(Perso perso, TranslatedScript.TranslationSettings ts, bool advanced = false) { MapLoader l = MapLoader.Loader; short mask = 0; AITypes aiTypes = Settings.s.aiTypes; Vector3 vector3 = new Vector3 { x = 0, y = 0, z = 0 }; switch (nodeType) { case ScriptNode.NodeType.KeyWord: // KeyWordFunctionPtr if (param < aiTypes.keywordTable.Length) { if (ts.exportMode) { if (aiTypes.keywordTable[param] == "Me") { return("this"); } if (aiTypes.keywordTable[param] == "MainActor") { return("Controller.MainActor"); } if (aiTypes.keywordTable[param] == "Nobody" || aiTypes.keywordTable[param] == "NoInput" || aiTypes.keywordTable[param] == "Nowhere" || aiTypes.keywordTable[param] == "NoGraph" || aiTypes.keywordTable[param] == "NoAction" || aiTypes.keywordTable[param] == "CapsNull") { return("null"); } } return(aiTypes.keywordTable[param]); } return("UnknownKeyword_" + param); case ScriptNode.NodeType.Condition: // GetConditionFunctionPtr if (param < aiTypes.conditionTable.Length) { return(aiTypes.conditionTable[param]); } return("UnknownCondition_" + param); case ScriptNode.NodeType.Operator: // GetOperatorFunctionPtr if (advanced) { if (param < aiTypes.operatorTable.Length) { return(aiTypes.operatorTable[param] + " (" + param + ")"); } } if (param < aiTypes.operatorTable.Length) { return(aiTypes.operatorTable[param]); } return("UnknownOperator_" + param); case ScriptNode.NodeType.Function: // GetFunctionFunctionPtr if (param < aiTypes.functionTable.Length) { return(aiTypes.functionTable[param]); } return("UnknownFunction_" + param); case ScriptNode.NodeType.Procedure: // ProcedureFunctionReturn if (param < aiTypes.procedureTable.Length) { return(aiTypes.procedureTable[param]); } return("UnknownProcedure_" + param); case ScriptNode.NodeType.MetaAction: // meta action if (param < aiTypes.metaActionTable.Length) { return(aiTypes.metaActionTable[param]); } return("UnknownMetaAction_" + param); case ScriptNode.NodeType.BeginMacro: return("BeginMacro"); case ScriptNode.NodeType.EndMacro: return("EndMacro"); case ScriptNode.NodeType.Field: if (param < aiTypes.fieldTable.Length) { return(aiTypes.fieldTable[param]); } return("UnknownField_" + param); case ScriptNode.NodeType.DsgVarRef: // Dsg Var if (perso != null && perso.brain != null && perso.brain.mind != null) { Mind mind = perso.brain.mind; if (mind.dsgMem != null && mind.dsgMem.dsgVar != null) { if (param < mind.dsgMem.dsgVar.dsgVarInfos.Length) { return(mind.dsgMem.dsgVar.dsgVarInfos[param].NiceVariableName); } } else if (mind.AI_model != null && mind.AI_model.dsgVar != null) { if (param < mind.AI_model.dsgVar.dsgVarInfos.Length) { return(mind.AI_model.dsgVar.dsgVarInfos[param].NiceVariableName); } } } return("dsgVar_" + param); case ScriptNode.NodeType.Constant: if (advanced) { return("Constant: " + BitConverter.ToInt32(BitConverter.GetBytes(param), 0)); } return(BitConverter.ToInt32(BitConverter.GetBytes(param), 0).ToString()); case ScriptNode.NodeType.Real: NumberFormatInfo nfi = new NumberFormatInfo() { NumberDecimalSeparator = "." }; if (advanced) { return("Real: " + BitConverter.ToSingle(BitConverter.GetBytes(param), 0).ToString(nfi)); } return(BitConverter.ToSingle(BitConverter.GetBytes(param), 0).ToString(nfi) + "f"); case ScriptNode.NodeType.Button: // Button/entryaction EntryAction ea = EntryAction.FromOffset(param_ptr); if (ea == null) { return("ERR_ENTRYACTION_NOTFOUND"); } string eaName = (advanced ? ea.ToString() : ea.ToBasicString()); if (advanced) { return("Button: " + eaName + "(" + param_ptr + ")"); } if (!ts.expandEntryActions && ea != null) { return("\"" + ea.ExportName + "\""); } return(eaName); case ScriptNode.NodeType.ConstantVector: return("Constant Vector: " + "0x" + param.ToString("x8")); // TODO: get from address case ScriptNode.NodeType.Vector: return("new Vector3"); // TODO: same case ScriptNode.NodeType.Mask: mask = (short)param; // TODO: as short if (advanced) { return("Mask: " + (mask).ToString("x4")); } if (ts.exportMode) { return("\"" + (mask).ToString("x4") + "\""); } return("Mask(" + (mask).ToString("x4") + ")"); case ScriptNode.NodeType.ModuleRef: if (advanced) { return("ModuleRef: " + "0x" + (param).ToString("x8")); } return("GetModule(" + (int)param + ")"); case ScriptNode.NodeType.DsgVarId: if (advanced) { return("DsgVarId: " + "0x" + (param).ToString("x8")); } return("DsgVarId(" + param + ")"); case ScriptNode.NodeType.String: string str = "ERR_STRING_NOTFOUND"; if (l.strings.ContainsKey(param_ptr)) { str = l.strings[param_ptr]; } if (advanced) { return("String: " + param_ptr + " (" + str + ")"); } return("\"" + str + "\""); case ScriptNode.NodeType.LipsSynchroRef: return("LipsSynchroRef: " + param_ptr); case ScriptNode.NodeType.FamilyRef: if (advanced) { return("FamilyRef: " + param_ptr); } Family f = Family.FromOffset(param_ptr); if (f != null) { return("GetFamily(\"" + f.name + "\")"); } else { return("Family.FromOffset(\"" + param_ptr + "\")"); } case ScriptNode.NodeType.PersoRef: Perso argPerso = Perso.FromOffset(param_ptr); if (argPerso != null && perso != null && argPerso.offset == perso.offset) { if (advanced) { return("PersoRef: this"); } return("this"); } string persoName = argPerso == null ? "ERR_PERSO_NOTFOUND" : argPerso.fullName; if (advanced) { return("PersoRef: " + param_ptr + " (" + persoName + ")"); } if (argPerso?.brain?.mind?.AI_model != null) { AIModel aiModel = argPerso.brain.mind.AI_model; // Make sure to add a cast in case the AI Model is accessed return("((" + aiModel.name + ")GetPerso(\"" + argPerso.namePerso + "\"))"); } return("GetPerso(\"" + argPerso.namePerso + "\")"); case ScriptNode.NodeType.ActionRef: State state = State.FromOffset(param_ptr); string stateName = state == null ? "ERR_STATE_NOTFOUND" : state.ShortName; if (advanced) { return("ActionRef: " + param_ptr + " " + stateName); } if (ts.useStateIndex) { return("GetAction(" + state.index.ToString() + ")"); } return(stateName); case ScriptNode.NodeType.SuperObjectRef: if (advanced) { return("SuperObjectRef: " + param_ptr); } SuperObject so = SuperObject.FromOffset(param_ptr); if (so != null) { return("GetSuperObject(\"" + so.Gao.name + "\")"); } else { return("SuperObject.FromOffset(\"" + param_ptr + "\")"); } case ScriptNode.NodeType.WayPointRef: if (advanced) { return("WayPointRef: " + param_ptr); } return("WayPoint.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.TextRef: if (l.localization == null) { return("TextRef"); } if (advanced) { return("TextRef: " + param + " (" + l.localization.GetTextForHandleAndLanguageID((int)param, 0) + ")"); } if (ts.expandStrings) { return("\"" + l.localization.GetTextForHandleAndLanguageID((int)param, 0) + "\""); // Preview in english } else { return("new TextReference(" + (int)param + ")"); } case ScriptNode.NodeType.ComportRef: Behavior comportRef = Behavior.FromOffset(param_ptr); if (comportRef == null) { if (advanced) { return("ComportRef: " + param_ptr + " (null)"); } return("null"); } else { return(comportRef.ShortName); //string type = comportRef.type == Behavior.BehaviorType.Normal ? "normalBehavior" : "reflexBehavior"; //return type + "[" + script.behaviorOrMacro.aiModel.GetBehaviorIndex(comportRef) + "]"; } case ScriptNode.NodeType.SoundEventRef: if (advanced) { return("SoundEventRef: " + (int)param); } return("SoundEvent.FromID(0x" + ((int)param).ToString("X8") + ")"); case ScriptNode.NodeType.ObjectTableRef: if (advanced) { return("ObjectTableRef: " + param_ptr); } if (ts.useHashIdentifiers) { string objectListJson = ObjectList.FromOffset(param_ptr).ToJSON(); string objectListHash = HashUtils.MD5Hash(objectListJson); return("ObjectList.FromHash(\"" + objectListHash + "\")"); } return("ObjectTable.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.GameMaterialRef: if (advanced) { return("GameMaterialRef: " + param_ptr); } if (ts.useHashIdentifiers) { string gmtJson = GameMaterial.FromOffset(param_ptr).ToJSON(); string gmtHash = HashUtils.MD5Hash(gmtJson); return("GameMaterial.FromHash(\"" + gmtHash + "\")"); } return("GameMaterial.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.ParticleGenerator: return("ParticleGenerator: " + "0x" + (param).ToString("x8")); case ScriptNode.NodeType.VisualMaterial: if (advanced) { return("VisualMaterial: " + param_ptr); } if (ts.useHashIdentifiers) { string vmtJson = VisualMaterial.FromOffset(param_ptr).ToJSON(); string vmtHash = HashUtils.MD5Hash(vmtJson); return("VisualMaterial.FromHash(\"" + vmtHash + "\")"); } return("VisualMaterial.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.ModelRef: // ModelCast if (advanced) { return("AIModel: " + param_ptr); } AIModel model = AIModel.FromOffset(param_ptr); return(model != null ? model.name : "null"); case ScriptNode.NodeType.DataType42: if (advanced) { return("EvalDataType42: " + "0x" + (param).ToString("x8")); } return("EvalDataType42(" + "0x" + (param).ToString("x8") + ")"); case ScriptNode.NodeType.CustomBits: if (advanced) { return("CustomBits: " + "0x" + (param).ToString("x8")); } if (ts.exportMode) { return("0x" + (param).ToString("x8")); } return("CustomBits(" + "0x" + (param).ToString("x8") + ")"); case ScriptNode.NodeType.Caps: if (advanced) { return("Caps: " + "0x" + (param).ToString("x8")); } if (ts.exportMode) { return("0x" + (param).ToString("x8")); } return("Caps(" + "0x" + (param).ToString("x8") + ")"); case ScriptNode.NodeType.SubRoutine: if (advanced) { return("Eval SubRoutine: " + param_ptr); } Macro macro = Macro.FromOffset(param_ptr); if (macro == null) { return("null"); } return("evalMacro(" + macro.ShortName + ");"); case ScriptNode.NodeType.Null: return("null"); case ScriptNode.NodeType.GraphRef: if (advanced) { return("Graph: " + "0x" + (param).ToString("x8")); } return("Graph.FromOffset(\"" + param_ptr + "\")"); } return("unknown"); }
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); } }