/* * Add initial code to the blocks and return the scope in which conversion should occur * Sometimes, we want to add a bit of code before the converted code, or want to encapsulate whole converted code * with a branch or so - this is a place to do it. * * * * Scope in which we want for conversion to happen */ public TES5CodeScope AddInitialCode(TES5MultipleScriptsScope multipleScriptsScope, TES5GlobalScope globalScope, TES5EventCodeBlock eventCodeBlock) { switch (eventCodeBlock.BlockName) { case "OnUpdate": { if (globalScope.ScriptHeader.BasicScriptType == TES5BasicType.T_QUEST) { TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "IsRunning", multipleScriptsScope, new TES5ObjectCallArguments()), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(false)), eventCodeBlock.CodeScope.LocalScope); //Even though we"d like this script to not do anything at this time, it seems like sometimes condition races, so we"re putting it into a loop anyways but with early return bailout branch.MainBranch.CodeScope.AddChunk(this.objectCallFactory.CreateRegisterForSingleUpdate(globalScope, multipleScriptsScope)); branch.MainBranch.CodeScope.AddChunk(new TES5Return()); eventCodeBlock.AddChunk(branch); return(eventCodeBlock.CodeScope); } /*else if (globalScope.ScriptHeader.BasicScriptType== TES5BasicType.T_OBJECTREFERENCE) * { * TES5LocalScope localScope = eventCodeBlock.CodeScope.LocalScope; * TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "GetParentCell", multipleScriptsScope, new TES5ObjectCallArguments()), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToPlayer(), "GetParentCell", multipleScriptsScope, new TES5ObjectCallArguments())), localScope); * eventCodeBlock.AddChunk(branch); * return branch.MainBranch.CodeScope; * }*/ else { return(eventCodeBlock.CodeScope); } } default: { return(eventCodeBlock.CodeScope); } } }
/* * Add initial code to the blocks and return the scope in which conversion should occur * Sometimes, we want to add a bit of code before the converted code, or want to encapsulate whole converted code * with a branch or so - this is a place to do it. * * * * Scope in which we want for conversion to happen */ public TES5CodeScope AddInitialCode(TES5GlobalScope globalScope, TES5EventCodeBlock eventCodeBlock) { if (eventCodeBlock.BlockName == "OnUpdate") { if (globalScope.ScriptHeader.ScriptType.NativeType == TES5BasicType.T_QUEST) { //Even though we"d like this script to not do anything at this time, it seems like sometimes condition races, so we"re putting it into a loop anyways but with early return bailout TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "IsRunning", new TES5ObjectCallArguments()), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(false)), eventCodeBlock.CodeScope.LocalScope); if (!globalScope.QuestHasOnUpdateRegisterForSingleUpdate)//WTM: Change: Added { //If quest has RegisterForSingleUpdate already, preventing adding it again. //Previously, RegisterForSingleUpdate was being called multiple times in OnUpdate because of how CombineRepeatedEventCodeBlockNames splits multiple OnUpdate methods into separate functions. //See TES4tutorialscript.psc for an example. globalScope.QuestHasOnUpdateRegisterForSingleUpdate = true; branch.MainBranch.CodeScope.AddChunk(this.objectCallFactory.CreateRegisterForSingleUpdate(globalScope)); } branch.MainBranch.CodeScope.AddChunk(new TES5Return()); eventCodeBlock.AddChunk(branch); return(eventCodeBlock.CodeScope); } /*else if (globalScope.ScriptHeader.BasicScriptType == TES5BasicType.T_OBJECTREFERENCE) * { * TES5LocalScope localScope = eventCodeBlock.CodeScope.LocalScope; * TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "GetParentCell", multipleScriptsScope, new TES5ObjectCallArguments()), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToPlayer(), "GetParentCell", multipleScriptsScope, new TES5ObjectCallArguments())), localScope); * eventCodeBlock.AddChunk(branch); * return branch.MainBranch.CodeScope; * }*/ } return(eventCodeBlock.CodeScope); }
public TES5CodeChunkCollection CreateCodeChunk(TES4VariableAssignation chunk, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5CodeChunkCollection codeChunkCollection = new TES5CodeChunkCollection(); string referenceName = chunk.Reference.StringValue; ITES5Referencer reference = this.referenceFactory.CreateReference(referenceName, globalScope, multipleScriptsScope, codeScope.LocalScope); ITES5Value value = this.valueFactory.CreateValue(chunk.Value, codeScope, globalScope, multipleScriptsScope); if (reference.TES5Type == TES5BasicType.T_GLOBALVARIABLE) { //if the reference is in reality a global variable, we will need to convert it by creating a Reference.SetValue(value); call //Object call creation TES5ObjectCallArguments objectCallArguments = new TES5ObjectCallArguments() { value }; TES5ObjectCall objectCall = this.objectCallFactory.CreateObjectCall(reference, "SetValue", objectCallArguments); codeChunkCollection.Add(objectCall); } else { if (reference.ReferencesTo == null) { throw new NullableException(nameof(reference.ReferencesTo)); } if (!reference.ReferencesTo.TES5Type.IsPrimitive && value.TES5Type.IsPrimitive) { //Hacky! TES5IntegerOrFloat?valueNumber = value as TES5IntegerOrFloat; if (valueNumber != null && valueNumber.ConvertedIntValue == 0) { value = new TES5None(); } } TES5VariableAssignation assignation = TES5VariableAssignationFactory.CreateAssignation(reference, value); this.typeInferencer.InferenceObjectByAssignation(reference, value); codeChunkCollection.Add(assignation); //post analysis. //Todo - rethink the prefix here ITES5Referencer?referencerValue = value as ITES5Referencer; if (referencerValue != null && referencerValue.Name == TES5Property.AddPropertyNameSuffix(TES5ReferenceFactory.MESSAGEBOX_VARIABLE_CONST)) { /* * Create block: * variable = this.TES4_MESSAGEBOX_RESULT; ; assignation * if(variable != -1) ; branch, expression * this.TES4_MESSAGEBOX_RESULT = -1; ; reassignation * endIf */ TES5Integer negativeOne = new TES5Integer(-1); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(reference, TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL, negativeOne); TES5VariableAssignation reassignation = TES5VariableAssignationFactory.CreateAssignation(referencerValue, negativeOne); TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(expression, codeScope.LocalScope); branch.MainBranch.CodeScope.AddChunk(reassignation); codeChunkCollection.Add(branch); } } return(codeChunkCollection); }