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); }
public TES5CodeChunkCollection CreateCodeChunkCollection(TES5FunctionScope functionScope, TES5GlobalScope globalScope) { TES5CodeChunkCollection collection = new TES5CodeChunkCollection(); if (functionScope.BlockName == "OnUpdate") { TES5ObjectCall function = this.objectCallFactory.CreateRegisterForSingleUpdate(globalScope); collection.Add(function); } collection.Add(new TES5Return()); return(collection); }
public ITES5ValueCodeChunk CreateLogCall(TES4Function function, string?reason = null) { string message = "OBScript called " + function.FunctionCall.FunctionName + "(" + string.Join(", ", function.Arguments.Select(a => a.StringValue)) + "), but script converter didn't know a conversion." + (reason != null ? " " + reason : ""); TES5CodeChunkCollection codeChunks = new TES5CodeChunkCollection(); TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { new TES5String(message) }; codeChunks.Add(objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "Trace", arguments)); #if UNKNOWN_FUNCTIONS_MESSAGE_BOX codeChunks.Add(objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "MessageBox", arguments));//Debug.Notification might be a useful alternative. #endif return(codeChunks); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5CodeChunkCollection codeChunks = new TES5CodeChunkCollection(); if (functionArguments.Any()) { int oblivionLockLevel = (int)functionArguments[0].Data; int skyrimLockLevel; if (oblivionLockLevel == 0) { skyrimLockLevel = 1; } else if (oblivionLockLevel > 0 && oblivionLockLevel < 99) { skyrimLockLevel = oblivionLockLevel; } else if (oblivionLockLevel == 99) { skyrimLockLevel = 100; } else if (oblivionLockLevel == 100) { skyrimLockLevel = 255; } else { throw new ConversionException("Oblivion lock level out of range (0-100): " + oblivionLockLevel); } TES5ObjectCallArguments setLockLevelArguments = new TES5ObjectCallArguments() { new TES5Integer(skyrimLockLevel) }; codeChunks.Add(this.objectCallFactory.CreateObjectCall(calledOn, "SetLockLevel", setLockLevelArguments)); } ITES4StringValue? lockAsOwnerBool = functionArguments.GetOrNull(1); TES5ObjectCallArguments lockArguments = new TES5ObjectCallArguments() { new TES5Bool(true), //abLock new TES5Bool(lockAsOwnerBool != null && (int)lockAsOwnerBool.Data == 1) //abAsOwner }; codeChunks.Add(this.objectCallFactory.CreateObjectCall(calledOn, "Lock", lockArguments)); return(codeChunks); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; string questName = functionArguments.Pop(0).StringValue; ITES5Referencer newCalledOn = this.referenceFactory.CreateReadReference(questName, globalScope, multipleScriptsScope, localScope); /* * Basically, there are some ugly mechanics in Oblivion. * Two quests ( FGInterimConversation and Arena* quest group ) are repeadetely started and stopped * However, Skyrim does not support this - once 0x13A byte is marked in a TESQuest, it won"t allow * to be started again. Hence, we need to call a Papyrus endpoint to stop the quest and * reset this field, and be able to reset the quest completely. */ TES5CodeChunkCollection codeChunks = new TES5CodeChunkCollection(); codeChunks.Add(this.objectCallFactory.CreateObjectCall(newCalledOn, "Stop", this.objectCallArgumentsFactory.CreateArgumentList(functionArguments, codeScope, globalScope, multipleScriptsScope))); if (questName == "FGInterimConversation" || questName == "ArenaIC" || questName == "ArenaICGrandChampion" || questName == "ArenaAggression" || questName == "ArenaAnnouncer" || questName == "ArenaDisqualification" || questName == "Arena") { codeChunks.Add(this.objectCallFactory.CreateObjectCall(newCalledOn, "PrepareForReinitializing", new TES5ObjectCallArguments())); } return(codeChunks); }