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));
        }
예제 #2
0
        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));
        }
예제 #3
0
        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));
        }
예제 #4
0
        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));
        }
예제 #5
0
        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));
        }
예제 #7
0
        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
            }));
        }
예제 #9
0
        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);
        }
예제 #13
0
        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));
            }
            }
        }
예제 #15
0
        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));
            }
            }
        }
예제 #17
0
        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));
            }
            }
        }