public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; string arg0String = functionArguments[0].StringValue; ITES5Referencer targetReference = this.referenceFactory.CreateReadReference(arg0String, globalScope, multipleScriptsScope, localScope); var arg0Type = targetReference.TES5Type; string functionName; ITES5Referencer baseReference; if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(arg0Type, TES5BasicType.T_ACTORBASE)) { functionName = "GetActorOwner"; baseReference = targetReference; } else if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(arg0Type, TES5BasicType.T_ACTOR)) { functionName = "GetActorOwner"; baseReference = this.objectCallFactory.CreateGetActorBase(targetReference); } else if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(arg0Type, TES5BasicType.T_FACTION)) { functionName = "GetFactionOwner"; baseReference = targetReference; } else { throw new ConversionException(function.FunctionCall.FunctionName + " should be called with either an ActorBase or a Faction."); } TES5ObjectCall owner = this.objectCallFactory.CreateObjectCall(calledOn, functionName); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(owner, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, baseReference); return(expression); }
private void InferenceTypeOfCalledObject(TES5ObjectCall objectCall, TES5MultipleScriptsScope multipleScriptsScope) { ITES5Type inferencableType = objectCall.AccessedObject.TES5Type.NativeType; /* * Check if we have something to inference inside the code, not some static class or method call return */ if (objectCall.AccessedObject.ReferencesTo != null) { //this is not "exactly" nice solution, but its enough. For now. ITES5Type inferenceType = TES5InheritanceGraphAnalyzer.FindTypeByMethod(objectCall); if (inferencableType == null) { throw new ConversionException("Cannot inference a null type"); } if (inferencableType == inferenceType) { return; //We already have the good type. } if (this.InferenceType(objectCall.AccessedObject.ReferencesTo, inferenceType, multipleScriptsScope)) { return; } } }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; //todo Refactor - add floating point vars . if (functionArguments.Count == 1) { TES5StaticReference calledOnRef = TES5StaticReferenceFactory.Debug; return(this.objectCallFactory.CreateObjectCall(calledOnRef, "MessageBox", this.objectCallArgumentsFactory.CreateArgumentList(functionArguments, codeScope, globalScope, multipleScriptsScope))); } else { string[] stringArguments = functionArguments.Select(v => v.StringValue).ToArray(); string edid = messageBoxData.GetEDID(stringArguments); IEnumerable <string> messageArguments = (new string[] { edid }).Concat(functionArguments.Select(a => a.StringValue)); this.metadataLogService.WriteLine("ADD_MESSAGE", messageArguments); Nullable <int> tes5FormIDNullable = messageBoxData.GetTES5FormID(edid); TES5Property messageBoxProperty = TES5PropertyFactory.ConstructWithTES5FormID(edid, TES5BasicType.T_MESSAGE, edid, tes5FormIDNullable); globalScope.AddProperty(messageBoxProperty); ITES5Referencer messageBoxReference = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(messageBoxProperty); TES5ObjectCall messageBoxShow = this.objectCallFactory.CreateObjectCall(messageBoxReference, "Show"); ITES5Referencer messageBoxResult = this.referenceFactory.CreateReadReference(TES5ReferenceFactory.MESSAGEBOX_VARIABLE_CONST, globalScope, multipleScriptsScope, localScope); return(TES5VariableAssignationFactory.CreateAssignation(messageBoxResult, messageBoxShow)); } }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { //GetInCell checks if a cell name starts with the argument string: https://cs.elderscrolls.com/index.php?title=GetInCell //The below will probably not always work. TES4FunctionArguments functionArguments = function.Arguments; ITES4StringValue apiToken = functionArguments[0]; string cellName = apiToken.StringValue; TES5ObjectCall getParentCell = this.objectCallFactory.CreateObjectCall(calledOn, "GetParentCell", multipleScriptsScope); TES5ObjectCall getParentCellName = this.objectCallFactory.CreateObjectCall(getParentCell, "GetName", multipleScriptsScope); int length = cellName.Length; TES5ObjectCallArguments substringArguments = new TES5ObjectCallArguments() { getParentCellName, new TES5Integer(0), new TES5Integer(length) }; TES5ObjectCall substring = this.objectCallFactory.CreateObjectCall(TES5StaticReference.StringUtil, "Substring", multipleScriptsScope, substringArguments); TES4LoadedRecord cellRecord = ESMAnalyzer._instance().FindInTES4Collection(cellName, false); string cellNameWithSpaces = cellRecord.GetSubrecordTrim("FULL"); if (cellNameWithSpaces == null) { cellNameWithSpaces = cellName; } TES5String cellNameTES5String = new TES5String(cellNameWithSpaces); return(TES5ExpressionFactory.CreateComparisonExpression(substring, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, cellNameTES5String)); }
//WTM: Change: Added private static bool CanConvertGetItemCountSpecialCases(TES5ObjectCall value1ObjectCall, TES5ComparisonExpressionOperator op, TES5Integer value2Integer) { if (op == TES5ComparisonExpressionOperator.OPERATOR_EQUAL && value2Integer.IntValue == 1)//Special cases { //I checked the meaning of these scripts, and ContainsItem is a suitable replacement. if (value1ObjectCall.AccessedObject.Name == "MethredhelsChestRef_p" && ((TES5Reference)value1ObjectCall.Arguments[0]).Name == "TG01AmantiusDiary_p") { return(true); } //TES4methredhelscript.psc else if (value1ObjectCall.AccessedObject is TES5SelfReference) { if ( ((TES5Reference)value1ObjectCall.Arguments[0]).Name == "Dark07RoderickPoison_p" || //TES4dark07cabinetscript.psc ((TES5Reference)value1ObjectCall.Arguments[0]).Name == "Dark09Finger_p" //TES4dark09deskscript.psc ) { return(true); } } else if (value1ObjectCall.AccessedObject.Name == "TG03MyvrynasCupboardRef_p" && ((TES5Reference)value1ObjectCall.Arguments[0]).Name == "TG03LlathasasBust_p") { return(true); } //TES4hieronymuslexscript.psc and tif__010034a3.psc //TES4orumgangcourier1script.psc: functionality of fake Skooma rock explained here: https://en.uesp.net/wiki/Oblivion:Camonna_Tong_Thug //Skooma is added to the fake rock if the rock has zero or one Skooma bottles, reaching a maximum of two bottles. //If I use ContainsItem, the rock will only reach a maximum of one bottle. //If I use GetItemCount, the rock will apparently fill infinitely. //I'll need to check this later. @INCONSISTENCE } return(false); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; int arg; switch (((TES4Integer)functionArguments[1]).IntValue) { case 0: { arg = 0; break; } case 1: { arg = 1000; break; } default: { throw new ConversionException("SetPCFactionMurder/SetPCFactionAttack argument unknown"); } } TES5ObjectCallArguments constantArgument = new TES5ObjectCallArguments() { new TES5Integer(arg) }; ITES5Referencer faction = this.referenceFactory.CreateReadReference(functionArguments[0].StringValue, globalScope, multipleScriptsScope, localScope); TES5ObjectCall newFunction = this.objectCallFactory.CreateObjectCall(faction, "SetCrimeGoldViolent", constantArgument); return(newFunction); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCall functionThis = this.objectCallFactory.CreateObjectCall(this.objectCallFactory.CreateGetActorBase(calledOn, multipleScriptsScope), "GetSex", multipleScriptsScope); int operand; switch ((functionArguments[0].StringValue).ToLower()) { case "male": { operand = 0; break; } case "female": { operand = 1; break; } default: { throw new ConversionException("GetIsSex used with unknown gender."); } } TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(functionThis, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(operand)); return(expression); }
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); }
/* * Inference the type by analyzing the object call. * Please note: It is not able to analyze calls to another scripts, but those weren"t used in oblivion anyways */ public void InferenceObjectByMethodCall(TES5ObjectCall objectCall, TES5MultipleScriptsScope multipleScriptsScope) { this.InferenceTypeOfCalledObject(objectCall, multipleScriptsScope); if (objectCall.Arguments != null) { this.InferenceTypeOfMethodArguments(objectCall, multipleScriptsScope); } }
public List <ITES5CodeChunk> GenerateObjectiveHandling(ITES5CodeBlock codeBlock, TES5GlobalScope globalScope, List <int> stageMap) { TES5LocalVariable castedToQuest = new TES5LocalVariable("__temp", TES5BasicType.T_QUEST); TES5Reference referenceToTemp = TES5ReferenceFactory.CreateReferenceToVariable(castedToQuest); List <ITES5CodeChunk> result = new List <ITES5CodeChunk>() { TES5VariableAssignationFactory.CreateAssignation(referenceToTemp, TES5ReferenceFactory.CreateReferenceToSelf(globalScope)) }; TES5LocalScope localScope = codeBlock.CodeScope.LocalScope; localScope.AddVariable(castedToQuest); int i = 0; foreach (var stageTargetState in stageMap) { TES5Integer targetIndex = new TES5Integer(i); if (stageTargetState != 0) { //Should be visible TES5ObjectCallArguments displayedArguments = new TES5ObjectCallArguments() { targetIndex }; TES5ObjectCall isObjectiveDisplayed = new TES5ObjectCall(referenceToTemp, "IsObjectiveDisplayed", displayedArguments); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(isObjectiveDisplayed, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(0)); TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { targetIndex, new TES5Integer(1) }; TES5ObjectCall showTheObjective = new TES5ObjectCall(referenceToTemp, "SetObjectiveDisplayed", arguments); TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(expression, localScope); branch.MainBranch.CodeScope.AddChunk(showTheObjective); result.Add(branch); } else { TES5ObjectCallArguments displayedArguments = new TES5ObjectCallArguments() { targetIndex }; TES5ObjectCall isObjectiveDisplayed = new TES5ObjectCall(referenceToTemp, "IsObjectiveDisplayed", displayedArguments); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(isObjectiveDisplayed, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(1)); TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { targetIndex, new TES5Integer(1) }; TES5ObjectCall completeTheObjective = new TES5ObjectCall(referenceToTemp, "SetObjectiveCompleted", arguments); TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(expression, localScope); branch.MainBranch.CodeScope.AddChunk(completeTheObjective); result.Add(branch); } ++i; } return(result); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCallArguments callArguments = new TES5ObjectCallArguments(); TES5ObjectCall dummyX = this.objectCallFactory.CreateObjectCall(calledOn, "GetPositionX", multipleScriptsScope); TES5ObjectCall dummyY = this.objectCallFactory.CreateObjectCall(calledOn, "GetPositionY", multipleScriptsScope); TES5ObjectCall dummyZ = this.objectCallFactory.CreateObjectCall(calledOn, "GetPositionZ", multipleScriptsScope); ITES5Value[] argList; switch ((functionArguments[0].StringValue).ToLower()) { case "x": { argList = new ITES5Value[] { this.valueFactory.CreateValue(functionArguments[1], codeScope, globalScope, multipleScriptsScope), dummyY, dummyZ }; break; } case "y": { argList = new ITES5Value[] { dummyX, this.valueFactory.CreateValue(functionArguments[1], codeScope, globalScope, multipleScriptsScope), dummyZ }; break; } case "z": { argList = new ITES5Value[] { dummyX, dummyY, this.valueFactory.CreateValue(functionArguments[1], codeScope, globalScope, multipleScriptsScope) }; break; } default: { throw new ConversionException("setPos can handle only X,Y,Z parameters."); } } foreach (var argListC in argList) { callArguments.Add(argListC); } return(this.objectCallFactory.CreateObjectCall(calledOn, "SetPosition", multipleScriptsScope, callArguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCall functionThis = this.objectCallFactory.CreateObjectCall(calledOn, "GetWorldSpace"); ITES5Referencer argument = this.referenceFactory.CreateReadReference(functionArguments[0].StringValue, globalScope, multipleScriptsScope, localScope); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(functionThis, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, argument); return(expression); }
public TES5ObjectCall CreateObjectCall(ITES5Referencer callable, string functionName, TES5MultipleScriptsScope multipleScriptsScope, TES5ObjectCallArguments arguments = null, bool inference = true) { TES5ObjectCall objectCall = new TES5ObjectCall(callable, functionName, arguments); if (inference) { this.typeInferencer.InferenceObjectByMethodCall(objectCall, multipleScriptsScope); } return(objectCall); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES5ObjectCallArguments arguments = new TES5ObjectCallArguments(); ITES5Referencer loc = this.referenceFactory.CreateReadReference("SEWorldLocation", globalScope, multipleScriptsScope, localScope); arguments.Add(loc); TES5ObjectCall exp = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToPlayer(), "IsInLocation", multipleScriptsScope, arguments); return(exp); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; ITES5Referencer functionArgument0Reference = this.referenceFactory.CreateReadReference(functionArguments[0].StringValue, globalScope, multipleScriptsScope, localScope); TES5ObjectCall leftParentCell = this.objectCallFactory.CreateObjectCall(calledOn, "GetParentCell"); TES5ObjectCall rightParentCell = this.objectCallFactory.CreateObjectCall(functionArgument0Reference, "GetParentCell"); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(leftParentCell, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, rightParentCell); return(expression); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCallArguments constantArgument = new TES5ObjectCallArguments() { new TES5Bool(((TES4Integer)functionArguments[0]).IntValue == 1) }; TES5ObjectCall newFunction = this.objectCallFactory.CreateObjectCall(calledOn, "SetOpen", multipleScriptsScope, constantArgument); return(newFunction); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; //Made in post-analysis TES5ObjectCall race = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToPlayer(globalScope), "GetRace"); ITES5Referencer checkAgainst = this.referenceFactory.CreateReadReference(functionArguments[0].StringValue, globalScope, multipleScriptsScope, localScope); TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(race, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, checkAgainst); return(expression); }
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 ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; ITES5Referencer fameReference = this.referenceFactory.CreateReadReference("Infamy", globalScope, multipleScriptsScope, localScope); TES5ObjectCallArguments fameArguments = new TES5ObjectCallArguments(); TES5ArithmeticExpression arithmeticExpression = TES5ExpressionFactory.CreateArithmeticExpression(fameReference, TES5ArithmeticExpressionOperator.OPERATOR_ADD, new TES5Integer(((TES4Integer)functionArguments[0]).IntValue)); fameArguments.Add(arithmeticExpression); TES5ObjectCall newFunction = this.objectCallFactory.CreateObjectCall(this.referenceFactory.CreateReference("Infamy", globalScope, multipleScriptsScope, localScope), "SetValue", fameArguments); return(newFunction); }
private void InferenceTypeOfMethodArguments(TES5ObjectCall objectCall) { /* * Inference the arguments */ int argumentIndex = 0; foreach (ITES5Value argument in objectCall.Arguments) { InferenceTypeOfMethodArgument(objectCall, argument, argumentIndex); argumentIndex++; } }
private void InferenceTypeOfMethodArguments(TES5ObjectCall objectCall, TES5MultipleScriptsScope multipleScriptsScope) { /* * Inference the arguments */ int argumentIndex = 0; ITES5Type calledOnType = objectCall.AccessedObject.TES5Type.NativeType; foreach (ITES5Value argument in objectCall.Arguments) { /* * Get the argument type according to TES5Inheritance graph. */ ITES5Type argumentTargetType = TES5InheritanceGraphAnalyzer.FindTypeByMethodParameter(calledOnType, objectCall.FunctionName, argumentIndex); if (argument.TES5Type != argumentTargetType) { /* * todo - maybe we should move getReferencesTo() to TES5Value and make all of the rest TES5Values just have null references as they do not reference anything? :) */ ITES5Referencer referencerArgument = argument as ITES5Referencer; if (referencerArgument != null && TES5InheritanceGraphAnalyzer.IsExtending(argumentTargetType, argument.TES5Type.NativeType)) { //HACKY! this.InferenceType(referencerArgument.ReferencesTo, argumentTargetType, multipleScriptsScope); } else { //So there"s one , one special case where we actually have to cast a var from one to another even though they are not ,,inheriting" from themselves, because they are primitives. //Scenario: there"s an T_INT argument, and we feed it with a T_FLOAT variable reference. It won"t work :( //We need to cast it on call level ( NOT inference it ) to make it work and not break other possible scenarios ( more specifically, when a float would be inferenced to int and there"s a //float assigment somewhere in the code ) if (argumentTargetType == TES5BasicType.T_INT && argument.TES5Type == TES5BasicType.T_FLOAT) { TES5Castable argumentCastable = argument as TES5Castable; if (argumentCastable != null) { //HACKY! When we"ll clean up this interface, it will dissapear :) argumentCastable.ManualCastTo = argumentTargetType; } } else if ( !TES5InheritanceGraphAnalyzer.IsExtending(argument.TES5Type, argumentTargetType) && !TES5InheritanceGraphAnalyzer.IsNumberTypeOrBoolAndInt(argument.TES5Type, argumentTargetType) && !(argument is TES5None && TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(argumentTargetType, (new TES5None()).TES5Type))) { bool expected = objectCall.AccessedObject.TES5Type.OriginalName == "TES4TimerHelper" && objectCall.FunctionName == "LegacySay"; throw new ConversionException("Argument type mismatch at " + objectCall.FunctionName + " index " + argumentIndex + ". Expected " + argumentTargetType.OriginalName + ". Found " + argument.TES5Type.OriginalName + ".", expected: expected); } } } argumentIndex++; } }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { const string functionName = "SetCombatStyle"; TES4FunctionArguments functionArguments = function.Arguments; if (functionArguments.Count == 0) { return(logUnknownFunctionFactory.CreateLogCall(function)); } TES5ObjectCall getActorBase = this.objectCallFactory.CreateGetActorBase(calledOn); TES5ObjectCallArguments newArguments = this.objectCallArgumentsFactory.CreateArgumentList(functionArguments, codeScope, globalScope, multipleScriptsScope); return(this.objectCallFactory.CreateObjectCall(getActorBase, functionName, newArguments)); }
public TES5ObjectCall CreateObjectCall(ITES5Referencer callable, string functionName, TES5ObjectCallArguments?arguments = null, bool inference = true) { if (arguments == null) { arguments = new TES5ObjectCallArguments(); } TES5ObjectCall objectCall = new TES5ObjectCall(callable, functionName, arguments); if (inference) { this.typeInferencer.InferenceObjectByMethodCall(objectCall); } return(objectCall); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; //This has to be a write-action reference, not a read reference! ITES5Referencer fameReference = this.referenceFactory.CreateReference("Fame", globalScope, multipleScriptsScope, localScope); TES5ObjectCallArguments fameArguments = new TES5ObjectCallArguments() { this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope) }; TES5ObjectCall newFunction = this.objectCallFactory.CreateObjectCall(fameReference, "SetValue", fameArguments); return(newFunction); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { ITES5Referencer newCalledOn = TES5StaticReference.Game; const string functionName = "SetInChargen"; bool argumentBool = ((TES4Integer)function.Arguments[0]).IntValue == 1; ITES5Value argumentValue = new TES5Bool(argumentBool); TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { argumentValue, argumentValue, argumentValue }; TES5ObjectCall newFunction = this.objectCallFactory.CreateObjectCall(newCalledOn, functionName, multipleScriptsScope, arguments); return(newFunction); }
private TES5FunctionCodeBlock GetGetArmorRatingOfWornFormFunctionCodeBlock(ITES5Referencer calledOn, TES5CodeScope codeScope) { TES5FunctionCodeBlock functionCodeBlock = new TES5FunctionCodeBlock(new TES5FunctionScope(functionName), TES5CodeScopeFactory.CreateCodeScope(codeScope.LocalScope), TES5BasicType.T_INT, false, false); TES5SignatureParameter slotMaskParameter = new TES5SignatureParameter("slotMask", TES5BasicType.T_INT, true); functionCodeBlock.FunctionScope.AddParameter(slotMaskParameter); TES5ObjectCall getWornForm = GetGetWornFormObjectCall(calledOn, TES5ReferenceFactory.CreateReferenceToVariableOrProperty(slotMaskParameter)); TES5LocalVariable wornFormVariable = new TES5LocalVariable("wornForm", TES5BasicType.T_ARMOR); functionCodeBlock.CodeScope.AddVariable(wornFormVariable); TES5Reference wornFormVariableReference = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(wornFormVariable); functionCodeBlock.AddChunk(TES5VariableAssignationFactory.CreateAssignation(wornFormVariableReference, getWornForm)); functionCodeBlock.AddChunk(new TES5Return(objectCallFactory.CreateObjectCall(wornFormVariableReference, "GetArmorRating"))); return(functionCodeBlock); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCall startSneaking = this.objectCallFactory.CreateObjectCall(calledOn, "StartSneaking", multipleScriptsScope); if (((TES4Integer)functionArguments[0]).IntValue == 0) { //WTM: Change: Since StartSneaking toggles sneaking, we check if the TES4 code wants the user to stop sneaking. //If so, if the user is sneaking, call StartSneaking, which actually stops sneaking if already sneaking. TES5ObjectCall isSneaking = this.objectCallFactory.CreateObjectCall(calledOn, "IsSneaking", multipleScriptsScope); TES5ComparisonExpression playerIsNotSneaking = TES5ExpressionFactory.CreateComparisonExpression(isSneaking, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(true)); TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(playerIsNotSneaking, codeScope.LocalScope); branch.MainBranch.CodeScope.AddChunk(startSneaking); return(branch); } return(startSneaking); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { //WTM: Added: This is to prevent these Papyrus messages: /* * Actor is dead, cannot start combat. * Actor has no AI process, cannot start combat. [I might need to use Actor.IsAIEnabled or even Actor.EnableAI(True).] */ TES5ObjectCall isDeadCall = this.objectCallFactory.CreateObjectCall(calledOn, "IsDead"); TES5ComparisonExpression isNotDead = TES5ExpressionFactory.CreateComparisonExpression(isDeadCall, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(false)); TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCallArguments newArguments = this.objectCallArgumentsFactory.CreateArgumentList(functionArguments, codeScope, globalScope, multipleScriptsScope); TES5ObjectCall startCombatCall = this.objectCallFactory.CreateObjectCall(calledOn, "StartCombat", newArguments); TES5Branch ifNotDeadStartCombat = TES5BranchFactory.CreateSimpleBranch(isNotDead, codeScope.LocalScope); ifNotDeadStartCombat.MainBranch.CodeScope.AddChunk(startCombatCall); return(ifNotDeadStartCombat); }
public List <ITES5CodeChunk> GenerateObjectiveHandling(ITES5CodeBlock codeBlock, TES5GlobalScope globalScope, List <int> stageMap) { List <ITES5CodeChunk> result = new List <ITES5CodeChunk>(); //WTM: Change: if (!stageMap.Any()) { return(result); } TES5LocalVariable castedToQuest = new TES5LocalVariable("__temp", TES5BasicType.T_QUEST);//WTM: Note: Why is this variable even necessary? TES5Reference referenceToTemp = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(castedToQuest); TES5SelfReference questSelfReference = TES5ReferenceFactory.CreateReferenceToSelf(globalScope); TES5VariableAssignation tempQuestAssignation = TES5VariableAssignationFactory.CreateAssignation(referenceToTemp, questSelfReference); result.Add(tempQuestAssignation); TES5LocalScope localScope = codeBlock.CodeScope.LocalScope; localScope.AddVariable(castedToQuest); int i = 0; foreach (var stageTargetState in stageMap) { TES5Integer targetIndex = new TES5Integer(i); TES5ObjectCallArguments displayedArguments = new TES5ObjectCallArguments() { targetIndex }; TES5ObjectCall isObjectiveDisplayed = objectCallFactory.CreateObjectCall(referenceToTemp, "IsObjectiveDisplayed", displayedArguments, inference: false); int isObjectiveDisplayedArgument = stageTargetState != 0 ? 0 : 1; TES5ComparisonExpression expression = TES5ExpressionFactory.CreateComparisonExpression(isObjectiveDisplayed, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(isObjectiveDisplayedArgument)); TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { targetIndex, new TES5Integer(1) }; string setObjectiveFunction = stageTargetState != 0 ? "SetObjectiveDisplayed" : "SetObjectiveCompleted"; TES5ObjectCall setObjectiveObjectCall = objectCallFactory.CreateObjectCall(referenceToTemp, setObjectiveFunction, arguments, inference: false); TES5Branch branch = TES5BranchFactory.CreateSimpleBranch(expression, localScope); branch.MainBranch.CodeScope.AddChunk(setObjectiveObjectCall); result.Add(branch); ++i; } return(result); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; ITES4StringValue apiToken = functionArguments[0]; string cellEditorID = apiToken.StringValue; string locationPropertyNameWithoutSuffix = cellEditorID + "Location"; string locationPropertyNameWithSuffix = TES5Property.AddPropertyNameSuffix(locationPropertyNameWithoutSuffix); TES5Property?locationProperty = globalScope.TryGetPropertyByName(locationPropertyNameWithSuffix); if (locationProperty == null) { int tes5LocationFormID; if (cellToLocationFinder.TryGetLocationFormID(cellEditorID, out tes5LocationFormID)) { locationProperty = TES5PropertyFactory.ConstructWithTES5FormID(locationPropertyNameWithoutSuffix, TES5BasicType.T_LOCATION, null, tes5LocationFormID); globalScope.AddProperty(locationProperty); } else { TES5ObjectCall getParentCell = this.objectCallFactory.CreateObjectCall(calledOn, "GetParentCell"); TES5ObjectCall getParentCellName = this.objectCallFactory.CreateObjectCall(getParentCell, "GetName"); TES4Record cellRecord = this.esmAnalyzer.GetRecordByEDIDInTES4Collection(cellEditorID); string? cellNameWithSpaces = cellRecord.TryGetSubrecordTrim("FULL"); if (cellNameWithSpaces == null || cellNameWithSpaces.IndexOf("Dummy", StringComparison.OrdinalIgnoreCase) != -1) { cellNameWithSpaces = cellEditorID; } TES5String cellNameTES5String = new TES5String(cellNameWithSpaces); TES5ObjectCallArguments findArguments = new TES5ObjectCallArguments() { getParentCellName, cellNameTES5String }; TES5ObjectCall substring = this.objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.StringUtil, "Find", findArguments); return(TES5ExpressionFactory.CreateComparisonExpression(substring, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(0))); } } TES5Reference locationReference = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(locationProperty); return(this.objectCallFactory.CreateObjectCall(calledOn, "IsInLocation", new TES5ObjectCallArguments() { locationReference })); }