public TES4ToTES5ASTConverter(ESMAnalyzer ESMAnalyzer, TES5BlockFactory blockFactory, TES5ObjectCallFactory objectCallFactory, TES5ReferenceFactory referenceFactory) { this.esmAnalyzer = ESMAnalyzer; this.blockFactory = blockFactory; this.objectCallFactory = objectCallFactory; this.referenceFactory = referenceFactory; }
protected static void GetFactories(MetadataLogService metadataLogService, out ESMAnalyzer analyzer, out TES5ObjectCallFactory objectCallFactory, out TES5ReferenceFactory referenceFactory, out TES5BlockFactory blockFactory) { TES5ChainedCodeChunkFactory chainedCodeChunkFactory; TES5AdditionalBlockChangesPass additionalBlockChangesPass; GetFactories(metadataLogService, out analyzer, out objectCallFactory, out referenceFactory, out _, out chainedCodeChunkFactory, out additionalBlockChangesPass); TES5InitialBlockCodeFactory initialBlockCodeFactory = new TES5InitialBlockCodeFactory(referenceFactory, objectCallFactory); blockFactory = new TES5BlockFactory(chainedCodeChunkFactory, additionalBlockChangesPass, initialBlockCodeFactory, objectCallFactory); }
public void Modify(TES4CodeBlock block, TES5BlockList blockList, TES5EventCodeBlock newBlock, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5FunctionScope blockFunctionScope = newBlock.FunctionScope; switch (block.BlockType.ToLower()) { case "gamemode": case "scripteffectupdate": { TES5ObjectCall function = this.objectCallFactory.CreateRegisterForSingleUpdate(globalScope, multipleScriptsScope); newBlock.AddChunk(function); if (globalScope.ScriptHeader.BasicScriptType == TES5BasicType.T_QUEST) { TES5EventCodeBlock onInitBlock = TES5BlockFactory.CreateOnInit(); onInitBlock.AddChunk(function); blockList.Add(onInitBlock); } break; } case "onactivate": { TES5EventCodeBlock onInitBlock = TES5BlockFactory.CreateOnInit(); TES5ObjectCall function = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "BlockActivation", multipleScriptsScope); onInitBlock.AddChunk(function); blockList.Add(onInitBlock); break; } case "onactorequip": { SetUpBranch(block, newBlock, blockFunctionScope, TES5LocalVariableParameterMeaning.CONTAINER, globalScope, multipleScriptsScope); break; } case "ontriggeractor": { TES4BlockParameterList parameterList = block.BlockParameterList; TES5LocalScope localScope = newBlock.CodeScope.LocalScope; TES5LocalVariable activator = localScope.GetVariableWithMeaning(TES5LocalVariableParameterMeaning.ACTIVATOR); TES5LocalVariable castedToActor = new TES5LocalVariable("akAsActor", TES5BasicType.T_ACTOR); TES5Reference referenceToCastedVariable = TES5ReferenceFactory.CreateReferenceToVariable(castedToActor); TES5Reference referenceToNonCastedVariable = TES5ReferenceFactory.CreateReferenceToVariable(activator); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(referenceToCastedVariable, TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL, new TES5None()); TES5CodeScope newCodeScope = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope); newCodeScope.LocalScope.AddVariable(castedToActor); newCodeScope.AddChunk(TES5VariableAssignationFactory.CreateAssignation(referenceToCastedVariable, referenceToNonCastedVariable)); TES5CodeScope outerBranchCode; if (parameterList != null) { //NOT TESTED List <TES4BlockParameter> parameterListVariableList = parameterList.Parameters; ITES5Referencer targetActor = this.referenceFactory.CreateReadReference(parameterListVariableList[0].BlockParameter, globalScope, multipleScriptsScope, localScope); TES5ComparisonExpression interExpression = TES5ExpressionFactory.CreateComparisonExpression(TES5ReferenceFactory.CreateReferenceToVariable(activator), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, targetActor); //TES5CodeScope interBranchCode = PHPFunction.Deserialize<TES5CodeScope>(PHPFunction.Serialize(newBlock.CodeScope));//WTM: Change: Why serialize and then deserialize? TES5CodeScope interBranchCode = newBlock.CodeScope; outerBranchCode = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope); interBranchCode.LocalScope.ParentScope = outerBranchCode.LocalScope; outerBranchCode.AddChunk(new TES5Branch(new TES5SubBranch(interExpression, interBranchCode))); } else { //outerBranchCode = PHPFunction.Deserialize<TES5CodeScope>(PHPFunction.Serialize(newBlock.CodeScope));//WTM: Change: Why serialize and then deserialize? outerBranchCode = newBlock.CodeScope; outerBranchCode.LocalScope.ParentScope = newCodeScope.LocalScope; } newCodeScope.AddChunk(new TES5Branch(new TES5SubBranch(expression, outerBranchCode))); newBlock.CodeScope = newCodeScope; break; } case "onadd": { SetUpBranch(block, newBlock, blockFunctionScope, "akNewContainer", globalScope, multipleScriptsScope); break; } case "ondrop": { SetUpBranch(block, newBlock, blockFunctionScope, "akOldContainer", globalScope, multipleScriptsScope); break; } case "onpackagestart": { SetUpBranch(block, newBlock, blockFunctionScope, "akNewPackage", globalScope, multipleScriptsScope); break; } case "onpackagedone": case "onpackagechange": case "onpackageend": { SetUpBranch(block, newBlock, blockFunctionScope, "akOldPackage", globalScope, multipleScriptsScope); break; } case "onalarm": { //@INCONSISTENCE - We don"t account for alarm type. TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "IsAlarmed", multipleScriptsScope), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(true)); SetUpBranch(blockFunctionScope, newBlock, expression); break; } /* * * case "onalarm": * { * * this.skyrimGroupEventName = "onhit"; * * if (this.eventArgs[1] != 3) { * //Nothing eelse is supported really.. * this.omit = true; * break; * } * * branch = new TES4ConditionalBranch(); * expression = new TES4Expression(); * leftConstant = new TES4Constant("akAggressor", "ObjectReference"); * //actionConstant = new TES4Constant(this.eventArgs[1],"Package"); * actionConstant = TES4Factories.createReference(this.eventArgs[2], this); * * expression.left_side = leftConstant; * expression.right_side = actionConstant; * expression.comparision_operator = TES4Expression.COMPARISION_OPERATOR_EQUAL; * * codeBlock = new TES4CodeBlock(); * codeBlock.chunks = this.chunks; * * branch.ifs[] = array( * "rawExpression" => "SCRIPT_GENERATED", * "expression" => expression, * "codeBlock" => codeBlock * ); * this.chunks = new TES4ChunkContainer(); * this.chunks.parent = this; * this.chunks.addChunk(branch); * * break; * } */ case "onequip": case "onunequip": { SetUpBranch(block, newBlock, blockFunctionScope, "akActor", globalScope, multipleScriptsScope); break; } } }
/* * The script to be converted * The script"s global scope * The scope under which we"re converting * * @throws ConversionException */ public TES5Target Convert(TES4Target target, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4Script script = target.Script; TES5BlockList blockList = new TES5BlockList(); TES4BlockList parsedBlockList = script.BlockList; Dictionary <string, List <ITES5CodeBlock> > createdBlocks = new Dictionary <string, List <ITES5CodeBlock> >(); if (parsedBlockList != null) { foreach (TES4CodeBlock block in parsedBlockList.Blocks) { TES5BlockList newBlockList = this.blockFactory.CreateBlock(block, globalScope, multipleScriptsScope); foreach (ITES5CodeBlock newBlock in newBlockList.Blocks) { createdBlocks.AddNewListIfNotContainsKeyAndAddValueToList(newBlock.BlockName, newBlock); } } } //todo encapsulate it to a different class. bool isStandalone = target.OutputPath.Contains(Path.DirectorySeparatorChar + "Standalone" + Path.DirectorySeparatorChar); foreach (var createdBlock in createdBlocks) { var blockType = createdBlock.Key; var blocks = createdBlock.Value; if (blocks.Count > 1) { List <TES5FunctionCodeBlock> functions = new List <TES5FunctionCodeBlock>(); int i = 1; TES5ObjectCallArguments localScopeArguments = null; foreach (TES5CodeBlock block in blocks) { TES5FunctionScope newFunctionScope = new TES5FunctionScope(blockType + "_" + i.ToString()); foreach (var variable in block.FunctionScope.Variables.Values) { newFunctionScope.AddVariable(variable); } TES5FunctionCodeBlock function = new TES5FunctionCodeBlock(newFunctionScope, block.CodeScope, new TES5VoidType(), isStandalone); functions.Add(function); if (localScopeArguments == null) { localScopeArguments = new TES5ObjectCallArguments(); foreach (var variable in block.FunctionScope.Variables.Values) { localScopeArguments.Add(TES5ReferenceFactory.CreateReferenceToVariable(variable)); } } ++i; } //Create the proxy block. ITES5CodeBlock lastBlock = blocks.Last(); TES5EventCodeBlock proxyBlock = TES5BlockFactory.CreateEventCodeBlock(blockType, /* * //WTM: Change: block was used below, but block is out of scope. The PHP must have been using the last defined block from above. * //WTM: Change: PHP called "clone" below, but I'm not sure if this is necessary or would even operate the same in C#. */ lastBlock.FunctionScope); foreach (var function in functions) { blockList.Add(function); TES5ObjectCall functionCall = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), function.BlockName, multipleScriptsScope, localScopeArguments, false // hacky. ); proxyBlock.AddChunk(functionCall); } blockList.Add(proxyBlock); } else { ITES5CodeBlock block = blocks[0]; blockList.Add(block); } } TES5Target result = new TES5Target(new TES5Script(globalScope, blockList), target.OutputPath); return(result); }
public TES5CodeScope Modify(TES4CodeBlock block, TES5BlockList blockList, TES5FunctionScope blockFunctionScope, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { //https://cs.elderscrolls.com/index.php?title=Begin //WTM: Change: Added: I reorganized this method and forced each event to account for the first Oblivion parameter. bool accountedForParameter = false; switch (block.BlockType.ToLower()) { case "gamemode": case "scripteffectupdate": { TES5ObjectCall function = this.objectCallFactory.CreateRegisterForSingleUpdate(globalScope); codeScope.AddChunk(function); if (globalScope.ScriptHeader.ScriptType.NativeType == TES5BasicType.T_QUEST) { TES5EventCodeBlock onInitBlock = TES5BlockFactory.CreateOnInit(); onInitBlock.AddChunk(function); blockList.Add(onInitBlock); } break; } case "menumode": { TES5ComparisonExpression isInMenuModeComparisonExpression = GetIsInMenuModeComparisonExpression(); codeScope = SetUpBranch(blockFunctionScope, codeScope, isInMenuModeComparisonExpression); accountedForParameter = true; //Skyrim handles menus differently than Oblivion's MenuType. break; } case "onactivate": { TES5EventCodeBlock onInitBlock = TES5BlockFactory.CreateOnInit(); TES5ObjectCall function = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "BlockActivation"); onInitBlock.AddChunk(function); blockList.Add(onInitBlock); //WTM: Change: Added: The following scripts erroneously add a parameter to their OnActivate block: //MS11BradonCorpse, SE01WaitingRoomScript, SE02LoveLetterScript, SE08Xeddefen03DoorSCRIPT, SE08Xeddefen05DoorSCRIPT, SE32TombEpitaph01SCRIPT, SEHillofSuicidesSCRIPT, SEXidPuzButton1, SEXidPuzButton2, SEXidPuzButton3, SEXidPuzButton4, SEXidPuzButtonSCRIPT, SEXidPuzHungerSCRIPT, XPEbroccaCrematorySCRIPT //But OnActivate does not take a parameter. I'm trying to use the author's intended parameter instead of just ignoring it. codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akActivateRef", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onactorequip": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, TES5LocalVariableParameterMeaning.CONTAINER, globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onadd": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akNewContainer", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onalarm": { //@INCONSISTENCE - We don"t account for CrimeType or Criminal. codeScope.AddChunk(this.objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "Trace", new TES5ObjectCallArguments() { new TES5String("This function does not account for OnAlarm's CrimeType or Criminal.") })); ITES5Value isAlarmed = TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "IsAlarmed"), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(true)); codeScope = SetUpBranch(blockFunctionScope, codeScope, isAlarmed); accountedForParameter = true; break; } /* * case "onalarm": * { * * this.skyrimGroupEventName = "onhit"; * * if (this.eventArgs[1] != 3) { * //Nothing eelse is supported really.. * this.omit = true; * break; * } * * branch = new TES4ConditionalBranch(); * expression = new TES4Expression(); * leftConstant = new TES4Constant("akAggressor", "ObjectReference"); * //actionConstant = new TES4Constant(this.eventArgs[1],"Package"); * actionConstant = TES4Factories.createReference(this.eventArgs[2], this); * * expression.left_side = leftConstant; * expression.right_side = actionConstant; * expression.comparision_operator = TES4Expression.COMPARISION_OPERATOR_EQUAL; * * codeBlock = new TES4CodeBlock(); * codeBlock.chunks = this.chunks; * * branch.ifs[] = array( * "rawExpression" => "SCRIPT_GENERATED", * "expression" => expression, * "codeBlock" => codeBlock * ); * this.chunks = new TES4ChunkContainer(); * this.chunks.parent = this; * this.chunks.addChunk(branch); * * break; * } */ case "ondeath": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akKiller", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "ondrop": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akOldContainer", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onequip": case "onunequip": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akActor", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onhit": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akAggressor", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onhitwith": { TES4BlockParameterList?parameterList = block.BlockParameterList; if (parameterList != null) { TES5LocalScope localScope = codeScope.LocalScope; ITES5Referencer hitWithCriteria = this.referenceFactory.CreateReadReference(parameterList.Parameters[0].BlockParameter, globalScope, multipleScriptsScope, localScope); TES5SignatureParameter akSource = localScope.FunctionScope.GetParameter("akSource"); TES5ComparisonExpression hitWithEqualsSource = TES5ExpressionFactory.CreateComparisonExpression(TES5ReferenceFactory.CreateReferenceToVariableOrProperty(akSource), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, hitWithCriteria); TES5CodeScope newCodeScope = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope); if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(TES5BasicType.T_AMMO, hitWithCriteria.TES5Type)) { newCodeScope.AddChunk(this.objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "Trace", new TES5ObjectCallArguments() { new TES5String("OBScript called OnHitWith using Ammo, but it's unlikely Papyrus will handle it properly. When arrows are used, " + akSource.Name + " will be a bow.") })); } newCodeScope.AddChunk(new TES5Branch(new TES5SubBranch(hitWithEqualsSource, codeScope))); codeScope = newCodeScope; } accountedForParameter = true; break; } case "onmagiceffecthit": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akEffect", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onpackagestart": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akNewPackage", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onpackagechange": case "onpackagedone": case "onpackageend": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akOldPackage", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onsell": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akSeller", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "onstartcombat": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akTarget", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "ontrigger": { codeScope = SetUpBranch(block, codeScope, blockFunctionScope, "akActivateRef", globalScope, multipleScriptsScope); accountedForParameter = true; break; } case "ontriggeractor": { TES4BlockParameterList? parameterList = block.BlockParameterList; TES5LocalScope localScope = codeScope.LocalScope; ITES5VariableOrProperty activator = localScope.GetVariableWithMeaning(TES5LocalVariableParameterMeaning.ACTIVATOR); TES5LocalVariable castedToActor = new TES5LocalVariable("akAsActor", TES5BasicType.T_ACTOR); TES5Reference referenceToCastedVariable = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(castedToActor); TES5Reference referenceToNonCastedVariable = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(activator); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(referenceToCastedVariable, TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL, new TES5None()); TES5CodeScope newCodeScope = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope); newCodeScope.AddVariable(castedToActor); newCodeScope.AddChunk(TES5VariableAssignationFactory.CreateAssignation(referenceToCastedVariable, referenceToNonCastedVariable)); TES5CodeScope outerBranchCode = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope); outerBranchCode.LocalScope.CopyVariablesFrom(codeScope.LocalScope); if (parameterList != null) { ITES5Referencer targetActor = this.referenceFactory.CreateReadReference(parameterList.Parameters[0].BlockParameter, globalScope, multipleScriptsScope, localScope); TES5ComparisonExpression interExpression = TES5ExpressionFactory.CreateComparisonExpression(TES5ReferenceFactory.CreateReferenceToVariableOrProperty(activator), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, targetActor); outerBranchCode.AddChunk(new TES5Branch(new TES5SubBranch(interExpression, codeScope))); } else { outerBranchCode.AddChunks(codeScope.CodeChunks); } newCodeScope.AddChunk(new TES5Branch(new TES5SubBranch(expression, outerBranchCode))); codeScope = newCodeScope; accountedForParameter = true; break; } case "onload": case "onreset": case "ontriggermob": case "scripteffectstart": case "scripteffectfinish": { break; } default: { throw new InvalidOperationException(block.BlockType + " not found."); } } if (!accountedForParameter) { TES4BlockParameterList?parameterList = block.BlockParameterList; if (parameterList != null && parameterList.Parameters.Any()) { throw new ConversionException("Parameter not accounted for in " + block.BlockType + ": " + parameterList.Parameters[0].BlockParameter); } } return(codeScope); }
private IEnumerable <TES5CodeBlock> CombineRepeatedEventCodeBlockNames(List <ITES5CodeBlock> blocks, string blockType, bool isStandalone, TES5GlobalScope globalScope) { ITES5CodeBlock[] nonEvents = blocks.Where(b => !(b is TES5EventCodeBlock)).ToArray(); if (nonEvents.Any()) { throw new ConversionException("Some non-event code blocks were present in " + nameof(CombineRepeatedEventCodeBlockNames) + ": " + string.Join("; ", nonEvents.Select(b => b.GetType().FullName))); } TES5EventCodeBlock[] eventBlocks = blocks.Cast <TES5EventCodeBlock>().ToArray(); List <TES5FunctionCodeBlock> functions = new List <TES5FunctionCodeBlock>(); TES5ObjectCallArguments? localScopeArguments = null; for (int i = 0; i < eventBlocks.Length; i++) { ITES5CodeBlock block = eventBlocks[i]; TES5FunctionScope newFunctionScope = new TES5FunctionScope(blockType + "_" + (i + 1).ToString()); foreach (var parameter in block.FunctionScope.GetParameters()) { newFunctionScope.AddParameter(parameter); } TES5FunctionCodeBlock function = new TES5FunctionCodeBlock(newFunctionScope, block.CodeScope, TES5VoidType.Instance, isStandalone, false); functions.Add(function); if (localScopeArguments == null) { localScopeArguments = new TES5ObjectCallArguments(); foreach (var parameter in block.FunctionScope.GetParameters()) { localScopeArguments.Add(TES5ReferenceFactory.CreateReferenceToVariableOrProperty(parameter)); } } } if (functions.Any()) { //Create the proxy block. ITES5CodeBlock lastBlock = blocks.Last(); TES5EventCodeBlock proxyBlock = TES5BlockFactory.CreateEventCodeBlock( //WTM: Change: block was used below, but block is out of scope. The PHP must have been using the last defined block from above. //WTM: Change: PHP called "clone" below, but I'm not sure if this is necessary or would even operate the same in C#. lastBlock.FunctionScope, globalScope); foreach (var function in functions) { yield return(function); TES5ObjectCall functionCall = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), function.BlockName, localScopeArguments, false// hacky. ); proxyBlock.AddChunk(functionCall); } yield return(proxyBlock); } /* * //This was not ultimately necessary. * IGrouping<string, TES5StateCodeBlock>[] states = blocks.OfType<TES5StateCodeBlock>().ToLookup(b => b.BlockName).ToArray(); * List<TES5CodeBlock> consolidatedStateCodeBlocks = states.Where(b => b.Count() == 1).SelectMany(b => b.Select(b2 => (TES5CodeBlock)b2).ToArray()).ToList(); * IGrouping<string, TES5StateCodeBlock>[] repeatedStateCodeBlocks = states.Where(b => b.Count() > 1).ToArray(); * for (int i = 0; i < repeatedStateCodeBlocks.Length; i++) * { * IGrouping<string, TES5StateCodeBlock> groupsWithSameName = repeatedStateCodeBlocks[i]; * TES5StateCodeBlock firstGroup = groupsWithSameName.First(); * foreach (var otherGroup in groupsWithSameName.Skip(1)) * { * foreach (ITES5CodeChunk chunk in otherGroup.CodeScope.CodeChunks) * { * firstGroup.AddChunk(chunk); * } * } * if (firstGroup.CodeBlocks.Blocks.Any()) * { * TES5CodeBlock[] reducedBlocks = CombineRepeatedCodeBlockNames(firstGroup.CodeBlocks.Blocks, blockType, isStandalone, globalScope, multipleScriptsScope).ToArray(); * firstGroup.CodeBlocks.Blocks.Clear(); * firstGroup.CodeBlocks.Blocks.AddRange(reducedBlocks); * } * consolidatedStateCodeBlocks.Add(firstGroup); * } * foreach(TES5CodeBlock codeBlock in consolidatedStateCodeBlocks) * { * yield return codeBlock; * } */ }
public TES4ToTES5ASTConverter(TES5BlockFactory blockFactory, TES5ObjectCallFactory objectCallFactory) { this.blockFactory = blockFactory; this.objectCallFactory = objectCallFactory; }