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)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; ITES4StringValue argument0 = functionArguments[0]; TES5ObjectCallArguments functionArgs = new TES5ObjectCallArguments() { this.valueFactory.CreateValue(argument0, codeScope, globalScope, multipleScriptsScope), new TES5Bool(true) }; return(this.objectCallFactory.CreateObjectCall(calledOn, "SetAlpha", functionArgs)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { const string functionName = "SetActorOwner"; TES5LocalScope localScope = codeScope.LocalScope; ITES4StringValue tes4Cell = function.Arguments[0]; ITES5Referencer tes5Cell = this.referenceFactory.CreateReference(tes4Cell.StringValue, globalScope, multipleScriptsScope, localScope); TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { objectCallFactory.CreateGetActorBaseOfPlayer(multipleScriptsScope) }; return(this.objectCallFactory.CreateObjectCall(tes5Cell, functionName, multipleScriptsScope, arguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCallArguments methodArguments = new TES5ObjectCallArguments() { new TES5Bool(false)//override different behaviour }; ITES4StringValue lockAsOwner = functionArguments.GetOrNull(1); bool lockAsOwnerBool = lockAsOwner != null && (bool)lockAsOwner.Data; methodArguments.Add(new TES5Bool(lockAsOwnerBool)); return(this.objectCallFactory.CreateObjectCall(calledOn, "Lock", multipleScriptsScope, methodArguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; string xyz = functionArguments[0].StringValue; ITES4StringValue argument1 = functionArguments[1]; TES5ObjectCallArguments newArguments = new TES5ObjectCallArguments() { this.valueFactory.CreateValue(xyz == "x" ? argument1 : new TES4Integer(0), codeScope, globalScope, multipleScriptsScope), this.valueFactory.CreateValue(xyz == "y" ? argument1 : new TES4Integer(0), codeScope, globalScope, multipleScriptsScope), this.valueFactory.CreateValue(xyz == "z" ? argument1 : new TES4Integer(0), codeScope, globalScope, multipleScriptsScope) }; return(this.objectCallFactory.CreateObjectCall(calledOn, "SetAngle", newArguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; ITES4StringValue value = functionArguments[0]; TES5ObjectCallArguments newArguments = new TES5ObjectCallArguments() { this.valueFactory.CreateValue(new TES4ApiToken(calledOn.Name), codeScope, globalScope, multipleScriptsScope) }; ITES5Referencer newCalledOn = this.referenceFactory.CreateReadReference(value.StringValue, globalScope, multipleScriptsScope, localScope); const string functionName = "IsDetectedBy"; return(this.objectCallFactory.CreateObjectCall(newCalledOn, functionName, multipleScriptsScope, newArguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; string functionName = function.FunctionCall.FunctionName; TES5ObjectCallArguments methodArguments = new TES5ObjectCallArguments() { new TES5Bool(true)//override different behaviour }; ITES4StringValue lockAsOwnerBool = functionArguments.GetOrNull(1); bool newLockBool = lockAsOwnerBool != null && (int)lockAsOwnerBool.Data == 1; methodArguments.Add(new TES5Bool(newLockBool)); return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, methodArguments)); }
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 })); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5LocalScope localScope = codeScope.LocalScope; TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { calledOn }; ITES5Value argument1 = this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope); if (argument1.TES5Type != TES5BasicType.T_TOPIC) { TES5Castable argument1Castable = argument1 as TES5Reference; if (argument1Castable != null && TES5InheritanceGraphAnalyzer.IsExtending(TES5BasicType.T_TOPIC, argument1.TES5Type)) { argument1Castable.ManualCastTo = TES5BasicType.T_TOPIC; } } arguments.Add(argument1); ITES4StringValue optionalFlag = functionArguments.GetOrNull(2); if (optionalFlag != null) { string optionalFlagDataString = optionalFlag.StringValue; if (this.analyzer.GetFormTypeByEDID(optionalFlagDataString).Value != TES4RecordType.REFR.Name) { this.metadataLogService.WriteLine("ADD_SPEAK_AS_ACTOR", new string[] { optionalFlagDataString }); optionalFlag = new TES4ApiToken(optionalFlag.Data + "Ref"); } arguments.Add(this.valueFactory.CreateValue(optionalFlag, codeScope, globalScope, multipleScriptsScope)); } else { arguments.Add(new TES5None()); } arguments.Add(new TES5Bool(true)); ITES5Referencer timerReference = this.referenceFactory.CreateTimerReadReference(globalScope, multipleScriptsScope, localScope); return(this.objectCallFactory.CreateObjectCall(timerReference, "LegacySay", multipleScriptsScope, arguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { const string functionName = "playGamebryoAnimation"; TES4FunctionArguments functionArguments = function.Arguments; //this function does not use strings for the names, so i cant really understand what is it. //todo refactor TES5ObjectCallArguments convertedArguments = new TES5ObjectCallArguments(); ITES4StringValue firstArg = functionArguments[0]; convertedArguments.Add(new TES5String(firstArg.StringValue)); /* * secondArg = functionArguments.getValue(1); * * if (secondArg && secondArg.getData() != 0) { * convertedArguments.add(new TES5Integer(1)); * }*/ convertedArguments.Add(new TES5Bool(true)); return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, convertedArguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; string functionName = function.FunctionCall.FunctionName; TES4FunctionArguments functionArguments = function.Arguments; ITES4StringValue value = functionArguments[0]; ITES5Referencer toBeMethodArgument = calledOn; ITES5Referencer newCalledOn = this.referenceFactory.CreateReadReference(value.StringValue, globalScope, multipleScriptsScope, localScope); TES5ObjectCallArguments methodArguments = new TES5ObjectCallArguments() { toBeMethodArgument }; ITES4StringValue?target = functionArguments.GetOrNull(1); if (target != null) { methodArguments.Add(this.referenceFactory.CreateReadReference(target.StringValue, globalScope, multipleScriptsScope, localScope)); } return(this.objectCallFactory.CreateObjectCall(newCalledOn, functionName, methodArguments)); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCallArguments fameArguments = new TES5ObjectCallArguments(); ITES4StringValue argument0 = functionArguments[0]; Nullable <int> argument0Int = argument0.Data as Nullable <int>; ITES5Value newArgument; if (argument0Int != null) { newArgument = new TES5Integer(argument0Int.Value); } else { newArgument = this.valueFactory.CreateValue(argument0, codeScope, globalScope, multipleScriptsScope); } fameArguments.Add(newArgument); TES5ObjectCall newFunction = this.objectCallFactory.CreateObjectCall(this.referenceFactory.CreateReference("Infamy", globalScope, multipleScriptsScope, localScope), "SetValue", fameArguments); return(newFunction); }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { string functionName = function.FunctionCall.FunctionName; TES4FunctionArguments functionArguments = function.Arguments; if (functionArguments == null || !functionArguments.Any()) { TES5ObjectCallArguments constantArgumentForNoFunctionArguments = new TES5ObjectCallArguments(); TES5LocalVariable meaningVariable = codeScope.GetVariableWithMeaning(TES5LocalVariableParameterMeaning.ACTIVATOR); if (meaningVariable != null) { constantArgumentForNoFunctionArguments.Add(TES5ReferenceFactory.CreateReferenceToVariable(meaningVariable)); } else { constantArgumentForNoFunctionArguments.Add(TES5ReferenceFactory.CreateReferenceToPlayer()); } constantArgumentForNoFunctionArguments.Add(new TES5Bool(true)); //Since default in oblivion is ,,skip the OnActivateBlock", this defaults to ,,abDefaultProcessingOnly = true" in Skyrim return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, constantArgumentForNoFunctionArguments)); } TES5ObjectCallArguments constantArgument = new TES5ObjectCallArguments() { this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope) }; ITES4StringValue blockOnActivate = functionArguments.GetOrNull(1); if (blockOnActivate != null) { bool blockOnActivateVal = (int)blockOnActivate.Data == 1; constantArgument.Add(new TES5Bool(!blockOnActivateVal)); } return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, constantArgument)); }
public override ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; TES4FunctionArguments functionArguments = function.Arguments; TES5ObjectCallArguments convertedArguments = new TES5ObjectCallArguments(); Dictionary <string, string> actorValueMap = ActorValueMap.Map; ITES4StringValue firstArg = functionArguments[0]; string firstArgString = firstArg.StringValue; string firstArgStringLower = firstArgString.ToLower(); switch (firstArgStringLower) { case "strength": case "intelligence": case "willpower": case "agility": case "endurance": case "personality": case "luck": { if (!TES5PlayerReference.EqualsPlayer(calledOn.Name)) { //We can"t convert those.. and shouldn"t be any, too. throw new ConversionException("[" + TES4FunctionName + "] Cannot set attributes on non-player"); } const string functionName = "SetValue"; calledOn = this.referenceFactory.CreateReference(TES5ReferenceFactory.TES4Attr + PHPFunction.UCWords(firstArgStringLower), globalScope, multipleScriptsScope, localScope); ITES4StringValue secondArg = functionArguments[1]; convertedArguments.Add(this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope)); return(CreateObjectCall(calledOn, functionName, multipleScriptsScope, convertedArguments)); } case "speed": { const string functionName = "ForceMovementSpeed"; ITES4StringValue secondArg = functionArguments[1]; convertedArguments.Add(this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope)); return(CreateObjectCall(calledOn, functionName, multipleScriptsScope, convertedArguments)); } case "fatigue": case "armorer": case "security": case "acrobatics": case "mercantile": case "mysticism": //It doesn"t exist in Skyrim - defaulting to Illusion.. case "blade": case "blunt": case "encumbrance": case "spellabsorbchance": case "resistfire": case "resistfrost": case "resistdisease": case "resistmagic": case "resistpoison": case "resistshock": { convertedArguments.Add(new TES5String(actorValueMap[firstArgStringLower])); ITES4StringValue secondArg = functionArguments[1]; convertedArguments.Add(this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope)); return(CreateObjectCall(calledOn, TES5FunctionName, multipleScriptsScope, convertedArguments)); } case "aggression": { ITES4StringValue secondArg = functionArguments[1]; object secondArgObject = secondArg.Data; Nullable <int> secondArgNullableInt = secondArgObject as Nullable <int>; AST.Value.ITES5Value convertedArgument2; if (secondArgNullableInt != null) { //WTM: Change: This apparently went unnoticed in the PHP version. The second argument is not always an integer. Sometimes its a variable reference. //But the value of the variable will not be properly scaled to the values below, so the converted script may operate incorrectly. int secondArgInt = secondArgNullableInt.Value; float newValue; if (secondArgInt == 0) { newValue = 0; } else if (secondArgInt > 0 && secondArgInt < 50) { newValue = 1; } else if (secondArgInt >= 50 && secondArgInt < 80) { newValue = 2; } else { newValue = 3; } convertedArgument2 = new TES5Float(newValue); } else { convertedArgument2 = this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope); } convertedArguments.Add(new TES5String(firstArgString)); convertedArguments.Add(convertedArgument2); return(CreateObjectCall(calledOn, TES5FunctionName, multipleScriptsScope, convertedArguments)); } case "confidence": { ITES4StringValue secondArg = functionArguments[1]; int secondArgData = (int)secondArg.Data; float newValue; if (secondArgData == 0) { newValue = 0; } else if (secondArgData > 0 && secondArgData < 30) { newValue = 1; } else if (secondArgData >= 30 && secondArgData < 70) { newValue = 2; } else if (secondArgData >= 70 && secondArgData < 99) { newValue = 3; } else { newValue = 4; } convertedArguments.Add(new TES5String(firstArgString)); convertedArguments.Add(new TES5Float(newValue)); return(CreateObjectCall(calledOn, TES5FunctionName, multipleScriptsScope, convertedArguments)); } default: { convertedArguments.Add(new TES5String(firstArgString)); ITES4StringValue secondArg = functionArguments[1]; convertedArguments.Add(this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope)); return(CreateObjectCall(calledOn, TES5FunctionName, multipleScriptsScope, convertedArguments)); } } }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; string messageString = functionArguments[0].StringValue; MatchCollection messageMatches = Regex.Matches(messageString, @"%([ +-0]*[1-9]*\.[0-9]+[ef]|g)"); if (messageMatches.Cast <Match>().Any(m => m.Success)) { //Pack the printf syntax //TODO - Perhaps we can use sprintf? ITES4StringValue arg0 = functionArguments.Pop(0); if (!(arg0 is TES4String)) { //hacky throw new ConversionException("Cannot transform printf like syntax to concat on string loaded dynamically"); } int i = 0; int caret = 0; //Example call: You have %.2f apples and %g boxes in your inventory, applesCount, boxesCount ITES5Value[] variablesArray = functionArguments.Select(a => this.valueFactory.CreateValue(a, codeScope, globalScope, multipleScriptsScope)).ToArray(); List <TES5String> stringsList = new List <TES5String>(); //Target: "You have ", " apples and ", " boxes in your inventory" bool startWithVariable = false; //Pretty ugly. Basically, if we start with a vairable, it should be pushed first from the variable stack and then string comes, instead of string , variable , and so on [...] while (caret < messageString.Length) { int stringBeforeStart = caret; //Set the start on the caret. Match match = i < messageMatches.Count ? messageMatches[i] : null; if (match != null) { int stringBeforeEnd = match.Index; int length = stringBeforeEnd - stringBeforeStart; if (caret == 0 && length == 0) { startWithVariable = true; } if (length > 0) { stringsList.Add(new TES5String(messageString.Substring(stringBeforeStart, length))); caret += length; } caret += match.Length; } else { stringsList.Add(new TES5String(messageString.Substring(stringBeforeStart))); caret = messageString.Length; } ++i; } List <ITES5Value> combinedValues = new List <ITES5Value>(); Stack <TES5String> stringsStack = new Stack <TES5String>(stringsList.Select(kvp => kvp).Reverse()); Stack <ITES5Value> variablesStack = new Stack <ITES5Value>(variablesArray.Select(kvp => kvp).Reverse()); if (startWithVariable) { if (variablesStack.Any()) { combinedValues.Add(variablesStack.Pop()); } } while (stringsStack.Any()) { combinedValues.Add(stringsStack.Pop()); if (variablesStack.Any()) { combinedValues.Add(variablesStack.Pop()); } } calledOn = TES5StaticReference.Debug; TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { TES5PrimitiveValueFactory.createConcatenatedValue(combinedValues) }; return(this.objectCallFactory.CreateObjectCall(calledOn, "Notification", multipleScriptsScope, arguments)); } else { calledOn = TES5StaticReference.Debug; TES5ObjectCallArguments arguments = new TES5ObjectCallArguments() { this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope) }; return(this.objectCallFactory.CreateObjectCall(calledOn, "Notification", multipleScriptsScope, arguments)); } }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES4FunctionArguments functionArguments = function.Arguments; TES5LocalScope localScope = codeScope.LocalScope; if (function.FunctionCall.FunctionName.Equals("modpcskill", StringComparison.OrdinalIgnoreCase)) { /* * MODPCSkill means we will need to call upon the player object */ calledOn = TES5ReferenceFactory.CreateReferenceToPlayer(); } TES5ObjectCallArguments convertedArguments = new TES5ObjectCallArguments(); var actorValueMap = ActorValueMap.Map; string firstArgString = functionArguments[0].StringValue; string firstArgStringLower = firstArgString.ToLower(); switch (firstArgStringLower) { case "strength": case "intelligence": case "willpower": case "agility": case "speed": case "endurance": case "personality": case "luck": { if (!TES5PlayerReference.EqualsPlayer(calledOn.Name)) { //We can"t convert those.. and shouldn"t be any, too. throw new ConversionException(nameof(ModActorValueFactory) + ": Cannot set attributes on non-player. Name: " + calledOn.Name + ", Argument: " + firstArgString); } const string functionName = "SetValue"; string tes4AttrFirstArg = TES5ReferenceFactory.TES4Attr + PHPFunction.UCWords(firstArgStringLower); /* * Switch out callee with the reference to attr */ ITES5Referencer newCalledOn = this.referenceFactory.CreateReference(tes4AttrFirstArg, globalScope, multipleScriptsScope, localScope); ITES4StringValue secondArg = functionArguments[1]; ITES5Value addedValue = this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope); convertedArguments.Add(TES5ExpressionFactory.CreateArithmeticExpression(addedValue, TES5ArithmeticExpressionOperator.OPERATOR_ADD, this.referenceFactory.CreateReadReference(tes4AttrFirstArg, globalScope, multipleScriptsScope, localScope))); return(this.objectCallFactory.CreateObjectCall(newCalledOn, functionName, multipleScriptsScope, convertedArguments)); } case "fatigue": case "armorer": case "security": case "acrobatics": case "mercantile": case "mysticism": //It doesn"t exist in Skyrim - defaulting to Illusion.. case "blade": case "blunt": case "encumbrance": case "spellabsorbchance": case "resistfire": case "resistfrost": case "resistdisease": case "resistmagic": case "resistpoison": case "resistshock": { const string functionName = "ModActorValue"; convertedArguments.Add(new TES5String(actorValueMap[firstArgStringLower])); ITES4StringValue secondArg = functionArguments[1]; convertedArguments.Add(this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope)); return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, convertedArguments)); } case "aggression": { const string functionName = "ModActorValue"; ITES4StringValue secondArg = functionArguments[1]; int secondArgData = (int)secondArg.Data; int newValue; if (secondArgData < -80) { newValue = -3; } else if (secondArgData >= -80 && secondArgData < -50) { newValue = -2; } else if (secondArgData >= -50 && secondArgData < 0) { newValue = -1; } else if (secondArgData == 0) { newValue = 0; } else if (secondArgData > 0 && secondArgData < 50) { newValue = 1; } else if (secondArgData >= 50 && secondArgData < 80) { newValue = 2; } else { newValue = 3; } convertedArguments.Add(new TES5String(firstArgString)); convertedArguments.Add(new TES5Float(newValue)); return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, convertedArguments)); } case "confidence": { const string functionName = "ModActorValue"; ITES4StringValue secondArg = functionArguments[1]; int secondArgData = (int)secondArg.Data; int newValue; if (secondArgData == -100) { newValue = -4; } else if (secondArgData <= -70 && secondArgData > -100) { newValue = -3; } else if (secondArgData <= -30 && secondArgData > -70) { newValue = -2; } else if (secondArgData < 0 && secondArgData > -30) { newValue = -1; } else if (secondArgData == 0) { newValue = 0; } else if (secondArgData > 0 && secondArgData < 30) { newValue = 1; } else if (secondArgData >= 30 && secondArgData < 70) { newValue = 2; } else if (secondArgData >= 70 && secondArgData < 99) { newValue = 3; } else { newValue = 4; } convertedArguments.Add(new TES5String(firstArgString)); convertedArguments.Add(new TES5Float(newValue)); return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, convertedArguments)); } default: { const string functionName = "ModActorValue"; convertedArguments.Add(new TES5String(firstArgString)); ITES4StringValue secondArg = functionArguments[1]; convertedArguments.Add(this.valueFactory.CreateValue(secondArg, codeScope, globalScope, multipleScriptsScope)); return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, convertedArguments)); } } }
public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope) { TES5LocalScope localScope = codeScope.LocalScope; const string functionName = "GetActorValue"; TES4FunctionArguments functionArguments = function.Arguments; //@TODO - This should be fixed on expression-parsing level, with agression and confidence checks adjusted accordingly. There are no retail uses, so im not doing this for now ;) ITES4StringValue firstArg = functionArguments[0]; string firstArgString = firstArg.StringValue; string firstArgStringLower = firstArgString.ToLower(); switch (firstArgStringLower) { case "strength": case "intelligence": case "willpower": case "agility": case "speed": case "endurance": case "personality": case "luck": { if (!TES5PlayerReference.EqualsPlayer(calledOn.Name)) { if (calledOn.TES5Type.NativeType == TES5BasicType.T_ACTOR) //WTM: Change: I added this if branch. { TES5ObjectCallArguments convertedArguments = new TES5ObjectCallArguments() { new TES5String(firstArgString) }; return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, convertedArguments)); } //We can"t convert those.. and shouldn"t be any, too. throw new ConversionException(nameof(GetActorValueFactory) + ": Cannot get attributes on non-player. Name: " + calledOn.Name + ", Argument: " + firstArgString); } /* * Switch out callee with the reference to attr */ string tes4AttrFirstArg = TES5ReferenceFactory.GetTES4AttrPlusName(firstArgStringLower); return(this.referenceFactory.CreateReadReference(tes4AttrFirstArg, globalScope, multipleScriptsScope, localScope)); } case "fatigue": case "armorer": case "security": case "acrobatics": case "mercantile": case "mysticism": //It doesn"t exist in Skyrim - defaulting to Illusion.. case "blade": case "blunt": case "encumbrance": case "spellabsorbchance": case "resistfire": case "resistfrost": case "resistdisease": case "resistmagic": case "resistpoison": case "resistshock": { TES5ObjectCallArguments convertedArguments = new TES5ObjectCallArguments() { new TES5String(ActorValueMap.Map[firstArgStringLower]) }; return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, convertedArguments)); } default: { TES5ObjectCallArguments convertedArguments = new TES5ObjectCallArguments() { new TES5String(firstArgString) }; return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, convertedArguments)); } } }