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);
        }
コード例 #2
0
        private TES5CodeScope ConvertTES4CodeChunksToTES5CodeScope(TES4CodeChunks chunks, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES5CodeScope newCodeScope = TES5CodeScopeFactory.CreateCodeScope(codeScope.LocalScope);

            foreach (ITES4CodeChunk codeChunk in chunks)
            {
                TES5CodeChunkCollection codeChunks = this.codeChunkFactory.CreateCodeChunk(codeChunk, codeScope, globalScope, multipleScriptsScope);
                newCodeScope.AddChunk(codeChunks);
            }
            return(newCodeScope);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        public TES5FunctionCodeBlock CreateFragment(TES5FragmentType fragmentType, string fragmentName, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope, TES4CodeChunks chunks)
        {
            TES5FunctionScope     fragmentLocalScope = TES5FragmentFunctionScopeFactory.CreateFromFragmentType(fragmentName, fragmentType);
            TES5FunctionCodeBlock function           = new TES5FunctionCodeBlock(fragmentLocalScope, TES5CodeScopeFactory.CreateCodeScopeRoot(fragmentLocalScope), TES5VoidType.Instance, false, fragmentType == TES5FragmentType.T_QF || fragmentType == TES5FragmentType.T_TIF);

            foreach (var codeChunk in chunks)
            {
                TES5CodeChunkCollection codeChunks = this.codeChunkFactory.CreateCodeChunk(codeChunk, function.CodeScope, globalScope, multipleScriptsScope);
                foreach (var newCodeChunk in codeChunks)
                {
                    function.AddChunk(newCodeChunk);
                }
            }
            return(function);
        }
コード例 #5
0
        public ITES5ValueCodeChunk CreateLogCall(TES4Function function, string?reason = null)
        {
            string message = "OBScript called " + function.FunctionCall.FunctionName + "(" + string.Join(", ", function.Arguments.Select(a => a.StringValue)) + "), but script converter didn't know a conversion." + (reason != null ? "  " + reason : "");
            TES5CodeChunkCollection codeChunks = new TES5CodeChunkCollection();
            TES5ObjectCallArguments arguments  = new TES5ObjectCallArguments()
            {
                new TES5String(message)
            };

            codeChunks.Add(objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "Trace", arguments));
#if UNKNOWN_FUNCTIONS_MESSAGE_BOX
            codeChunks.Add(objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "MessageBox", arguments));//Debug.Notification might be a useful alternative.
#endif
            return(codeChunks);
        }
コード例 #6
0
        private void ConvertTES4CodeChunksToTES5EventCodeBlock(TES4CodeChunks chunks, TES5EventCodeBlock newBlock, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES5CodeScope conversionScope = this.initialBlockCodeFactory.AddInitialCode(multipleScriptsScope, globalScope, newBlock);

            foreach (ITES4CodeChunk codeChunk in chunks)
            {
                TES5CodeChunkCollection codeChunks = this.codeChunkFactory.createCodeChunk(codeChunk, newBlock.CodeScope, globalScope, multipleScriptsScope);
                if (codeChunks != null)
                {
                    foreach (ITES5CodeChunk newCodeChunk in codeChunks)
                    {
                        conversionScope.AddChunk(newCodeChunk);
                    }
                }
            }
        }
コード例 #7
0
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES4FunctionArguments   functionArguments = function.Arguments;
            TES5CodeChunkCollection codeChunks        = new TES5CodeChunkCollection();

            if (functionArguments.Any())
            {
                int oblivionLockLevel = (int)functionArguments[0].Data;
                int skyrimLockLevel;
                if (oblivionLockLevel == 0)
                {
                    skyrimLockLevel = 1;
                }
                else if (oblivionLockLevel > 0 && oblivionLockLevel < 99)
                {
                    skyrimLockLevel = oblivionLockLevel;
                }
                else if (oblivionLockLevel == 99)
                {
                    skyrimLockLevel = 100;
                }
                else if (oblivionLockLevel == 100)
                {
                    skyrimLockLevel = 255;
                }
                else
                {
                    throw new ConversionException("Oblivion lock level out of range (0-100):  " + oblivionLockLevel);
                }
                TES5ObjectCallArguments setLockLevelArguments = new TES5ObjectCallArguments()
                {
                    new TES5Integer(skyrimLockLevel)
                };
                codeChunks.Add(this.objectCallFactory.CreateObjectCall(calledOn, "SetLockLevel", setLockLevelArguments));
            }
            ITES4StringValue?       lockAsOwnerBool = functionArguments.GetOrNull(1);
            TES5ObjectCallArguments lockArguments   = new TES5ObjectCallArguments()
            {
                new TES5Bool(true),                                                     //abLock
                new TES5Bool(lockAsOwnerBool != null && (int)lockAsOwnerBool.Data == 1) //abAsOwner
            };

            codeChunks.Add(this.objectCallFactory.CreateObjectCall(calledOn, "Lock", lockArguments));
            return(codeChunks);
        }
コード例 #8
0
        private static TES5ElseSubBranch ConvertElseBranch(TES4ElseSubBranch branch, TES5CodeScope outerCodeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope, TES5ChainedCodeChunkFactory codeChunkFactory)
        {
            TES5CodeScope  newCodeScope = TES5CodeScopeFactory.CreateCodeScopeRecursive(outerCodeScope.LocalScope);
            TES4CodeChunks?branchChunks = branch.CodeChunks;

            if (branchChunks != null)
            {
                foreach (ITES4CodeChunk codeChunk in branchChunks)
                {
                    TES5CodeChunkCollection codeChunks = codeChunkFactory.CreateCodeChunk(codeChunk, newCodeScope, globalScope, multipleScriptsScope);
                    foreach (ITES5CodeChunk newCodeChunk in codeChunks)
                    {
                        newCodeScope.AddChunk(newCodeChunk);
                    }
                }
            }
            return(new TES5ElseSubBranch(newCodeScope));
        }
コード例 #9
0
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            //WTM:  @Inconsistence:
            //SKSE has Game.SetPlayerLevel(int level), but Oblivion calls this function on non-player actors.
            //Since we can't call SetLevel directly, we are instead modifying actor values.
            TES4FunctionArguments tes4Arguments = function.Arguments;
            int       newLevel = (int)tes4Arguments[0].Data;
            bool      levelToPC = tes4Arguments.Count > 1 ? (int)tes4Arguments[1].Data == 1 : false;//When false, newLevel should be evaluated absolutely.  When true, newLevel should be evaluated relative to the current level.
            string    newFunctionName = !levelToPC ? "SetActorValue" : "ModActorValue";
            int       attributeLevel = newLevel, skillLevel = newLevel;
            const int minAttributeValue = 25, minSkillLevel = 10;

            if (levelToPC)
            {//If levelToPC is true, increase or decrease attributes 10 times greater than the level change and skills 2 times greater than the level change.
                attributeLevel *= 10;
                skillLevel     *= 2;
            }
            else
            {//If levelToPC is false, ensure values are not set to values less than minimums.
                if (attributeLevel < minAttributeValue)
                {
                    attributeLevel = minAttributeValue;
                }
                if (skillLevel < minSkillLevel)
                {
                    skillLevel = minSkillLevel;
                }
            }
            TES5CodeChunkCollection codeChunks = new TES5CodeChunkCollection();

            string[] attributes = new string[] { "Health", "Magicka", "Stamina" };
            codeChunks.AddRange(attributes.Select(a => objectCallFactory.CreateObjectCall(calledOn, newFunctionName, multipleScriptsScope, new TES5ObjectCallArguments()
            {
                new TES5String(a), new TES5Float(attributeLevel)
            })));
            string[] skills = new string[] { "OneHanded", "TwoHanded", "Marksman", "Block", "Smithing", "HeavyArmor", "LightArmor", "Pickpocket", "Lockpicking", "Sneak", "Alchemy", "Speechcraft", "Alteration", "Conjuration", "Destruction", "Illusion", "Restoration", "Enchanting" };
            codeChunks.AddRange(skills.Select(s => objectCallFactory.CreateObjectCall(calledOn, newFunctionName, multipleScriptsScope, new TES5ObjectCallArguments()
            {
                new TES5String(s), new TES5Float(skillLevel)
            })));
            return(codeChunks);
        }
コード例 #10
0
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES5LocalScope        localScope        = codeScope.LocalScope;
            TES4FunctionArguments functionArguments = function.Arguments;
            string          questName   = functionArguments.Pop(0).StringValue;
            ITES5Referencer newCalledOn = this.referenceFactory.CreateReadReference(questName, globalScope, multipleScriptsScope, localScope);

            /*
             * Basically, there are some ugly mechanics in Oblivion.
             * Two quests ( FGInterimConversation and Arena* quest group ) are repeadetely started and stopped
             * However, Skyrim does not support this - once 0x13A byte is marked in a TESQuest, it won"t allow
             * to be started again. Hence, we need to call a Papyrus endpoint to stop the quest and
             * reset this field, and be able to reset the quest completely.
             */
            TES5CodeChunkCollection codeChunks = new TES5CodeChunkCollection();

            codeChunks.Add(this.objectCallFactory.CreateObjectCall(newCalledOn, "Stop", this.objectCallArgumentsFactory.CreateArgumentList(functionArguments, codeScope, globalScope, multipleScriptsScope)));
            if (questName == "FGInterimConversation" || questName == "ArenaIC" || questName == "ArenaICGrandChampion" || questName == "ArenaAggression" || questName == "ArenaAnnouncer" || questName == "ArenaDisqualification" || questName == "Arena")
            {
                codeChunks.Add(this.objectCallFactory.CreateObjectCall(newCalledOn, "PrepareForReinitializing", new TES5ObjectCallArguments()));
            }
            return(codeChunks);
        }
コード例 #11
0
        private static TES5SubBranch ConvertSubBranch(TES4SubBranch branch, TES5CodeScope outerCodeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope, TES5ChainedCodeChunkFactory codeChunkFactory, TES5ValueFactory valueFactory)
        {
            ITES5Value     expression   = valueFactory.CreateValue(branch.Expression, outerCodeScope, globalScope, multipleScriptsScope);
            TES5CodeScope  newCodeScope = TES5CodeScopeFactory.CreateCodeScopeRecursive(outerCodeScope.LocalScope);
            TES4CodeChunks branchChunks = branch.CodeChunks;

            if (branchChunks != null)
            {
                foreach (ITES4CodeChunk codeChunk in branchChunks)
                {
                    TES5CodeChunkCollection codeChunks = codeChunkFactory.createCodeChunk(codeChunk, newCodeScope, globalScope, multipleScriptsScope);
                    if (codeChunks != null)
                    {
                        foreach (ITES5CodeChunk newCodeChunk in codeChunks)
                        {
                            newCodeScope.AddChunk(newCodeChunk);
                        }
                    }
                }
            }

            return(new TES5SubBranch(expression, newCodeScope));
        }