Beispiel #1
0
 public void InferenceObjectByAssignation(ITES5Referencer reference, ITES5Value value)
 {
     if (reference.ReferencesTo != null && !reference.TES5Type.IsPrimitive)
     {
         this.InferenceType(reference.ReferencesTo, value.TES5Type.NativeType);
     }
 }
Beispiel #2
0
 private TES5ObjectCall GetGetWornFormObjectCall(ITES5Referencer calledOn, ITES5Value slotMask)
 {
     return(objectCallFactory.CreateObjectCall(calledOn, "GetWornForm", new TES5ObjectCallArguments()
     {
         slotMask
     }));
 }
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES4FunctionArguments functionArguments = function.Arguments;
            //Simple implementation without looking.
            TES5ObjectCallArguments arguments = new TES5ObjectCallArguments();

            //if (calledOn.TES5Type != TES5BasicType.T_OBJECTREFERENCE)
            //{
            //    TES5Castable calledOnCastable = calledOn as TES5Reference;
            //    if (calledOn != null && TES5InheritanceGraphAnalyzer.IsExtending(TES5BasicType.T_ACTOR, calledOn.TES5Type))
            //    {
            //        calledOnCastable.ManualCastTo = TES5BasicType.T_OBJECTREFERENCE;
            //    }
            //}
            //arguments.Add(calledOn);
            arguments.Add(this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope));
            ITES5Value argument1 = this.valueFactory.CreateValue(functionArguments[1], codeScope, globalScope, multipleScriptsScope);

            //WTM:  Change:  Why is the below necessary?

            /*if (argument1.TES5Type != TES5BasicType.T_TOPIC)
             * {
             *  TES5Reference? argument1Reference = argument1 as TES5Reference;
             *  if (argument1Reference != null && TES5InheritanceGraphAnalyzer.IsExtending(TES5BasicType.T_TOPIC, argument1.TES5Type))
             *  {
             *      argument1Reference.ManualCastTo = TES5BasicType.T_TOPIC;
             *  }
             * }*/
            arguments.Add(argument1);
            arguments.Add(new TES5Bool(true));

            //TES5LocalScope localScope = codeScope.LocalScope;
            //ITES5Referencer timerReference = this.referenceFactory.CreateTimerReadReference(globalScope, multipleScriptsScope, localScope);
            return(this.objectCallFactory.CreateObjectCall(calledOn, "LegacySayTo", arguments));
        }
        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);
        }
Beispiel #5
0
        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)
        {
            TES4FunctionArguments   functionArguments = function.Arguments;
            TES5ObjectCallArguments arguments         = new TES5ObjectCallArguments();

            //if (calledOn.TES5Type != TES5BasicType.T_OBJECTREFERENCE)
            //{
            //    TES5Castable calledOnCastable = calledOn as TES5Reference;
            //    if (calledOn != null && TES5InheritanceGraphAnalyzer.IsExtending(TES5BasicType.T_ACTOR, calledOn.TES5Type))
            //    {
            //        calledOnCastable.ManualCastTo = TES5BasicType.Tl_OBJECTREFERENCE;
            //    }
            //}
            //arguments.Add(calledOn);

            ITES5Value argument0 = this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope);

            //WTM:  Change:  Why is the below necessary?

            /*if (argument0.TES5Type != TES5BasicType.T_TOPIC)
             * {
             *  TES5Reference? argument0Reference = argument0 as TES5Reference;
             *  if (argument0Reference != null && TES5InheritanceGraphAnalyzer.IsExtending(TES5BasicType.T_TOPIC, argument0.TES5Type))
             *  {
             *      argument0Reference.ManualCastTo = TES5BasicType.T_TOPIC;
             *  }
             * }*/
            arguments.Add(argument0);

            //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));

            //TES5LocalScope localScope = codeScope.LocalScope;
            //ITES5Referencer timerReference = this.referenceFactory.CreateTimerReadReference(globalScope, multipleScriptsScope, localScope);
            //return this.objectCallFactory.CreateObjectCall(timerReference, "LegacySay", multipleScriptsScope, arguments);
            return(this.objectCallFactory.CreateObjectCall(calledOn, "LegacySay", arguments));
        }
Beispiel #7
0
 public TES5VariableAssignation(ITES5Value reference, ITES5Value value)
 {
     this.Reference = reference;
     this.value     = value;
     //If value is going to be casted but actually can't be casted, throw an exception.
     if (ReferenceAndValueDifferentTypesAndValueIsNonNone() && !ReferenceIsIntAndValueExtendsForm() &&
         //Oblivion stores boolean-like values in short ints.  Exclude such cases.
         !(reference.TES5Type == TES5BasicType.T_INT && value.TES5Type == TES5BasicType.T_BOOL) &&
         !TES5InheritanceGraphAnalyzer.IsTypeOrExtendsTypeOrIsNumberType(value.TES5Type, reference.TES5Type, true))
     {
         throw new ConversionTypeMismatchException(value.TES5Type.OriginalName + " : " + value.TES5Type.NativeType.Name + " cannot be assigned to " + reference.TES5Type.OriginalName + " : " + reference.TES5Type.NativeType.Name);
     }
 }
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            string functionName = function.FunctionCall.FunctionName;
            TES4FunctionArguments   functionArguments      = function.Arguments;
            TES5ObjectCallArguments newObjectCallArguments = this.objectCallArgumentsFactory.CreateArgumentList(functionArguments, codeScope, globalScope, multipleScriptsScope);
            ITES5Value firstArg = newObjectCallArguments[0];

            if (firstArg.TES5Type == TES5BasicType.T_STRING)
            {
                newObjectCallArguments[0] = valueFactory.CreateValue(new TES4ApiToken(((TES5String)firstArg).StringValue.Trim('"')), codeScope, globalScope, multipleScriptsScope);
            }
            return(this.objectCallFactory.CreateObjectCall(calledOn, functionName, multipleScriptsScope, newObjectCallArguments));
        }
Beispiel #9
0
        private void InferenceTypeOfMethodArgument(TES5ObjectCall objectCall, ITES5Value argument, int argumentIndex)
        {
            ITES5Type calledOnType = objectCall.AccessedObject.TES5Type.NativeType;

            /*
             * Get the argument type according to TES5Inheritance graph.
             */
            TES5BasicType argumentTargetType = TES5InheritanceGraphAnalyzer.FindTypeByMethodParameter(calledOnType.NativeType, 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!
                    if (referencerArgument.ReferencesTo == null)
                    {
                        throw new NullableException(nameof(referencerArgument.ReferencesTo));
                    }
                    this.InferenceType(referencerArgument.ReferencesTo, argumentTargetType);
                }
                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, TES5None.TES5TypeStatic)))
                    {
                        throw new ConversionTypeMismatchException("Argument type mismatch at " + objectCall.FunctionName + " index " + argumentIndex + ".  Expected " + argumentTargetType.Name + ".  Found " + argument.TES5Type.OriginalName + " : " + argument.TES5Type.NativeType.OriginalName + ".");
                    }
                }
            }
        }
Beispiel #10
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);
                    foreach (ITES5CodeChunk newCodeChunk in codeChunks)
                    {
                        newCodeScope.AddChunk(newCodeChunk);
                    }
                }
            }
            return(new TES5SubBranch(expression, newCodeScope));
        }
Beispiel #11
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));
        }
Beispiel #12
0
 public static TES5BoolCastedExpression CreateBoolCastedExpression(ITES5Value value)
 {
     return(new TES5BoolCastedExpression(value));
 }
Beispiel #13
0
 public static TES5ArithmeticExpression CreateArithmeticExpression(ITES5Value left, TES5ArithmeticExpressionOperator op, ITES5Value right)
 {
     return(new TES5ArithmeticExpression(left, op, right));
 }
Beispiel #14
0
 public static TES5ComparisonExpression CreateComparisonExpression(ITES5Value left, TES5ComparisonExpressionOperator op, ITES5Value right)
 {
     return(new TES5ComparisonExpression(left, op, right));
 }
Beispiel #15
0
 public static TES5TrueBooleanExpression CreateTrueBooleanExpression(ITES5Value valueToBeTrue)
 {
     return(new TES5TrueBooleanExpression(valueToBeTrue));
 }
Beispiel #16
0
 public TES5BinaryExpression(ITES5Value leftValue, T op, ITES5Value rightValue)
 {
     this.LeftValue  = leftValue;
     this.op         = op;
     this.RightValue = rightValue;
 }
 public static TES5VariableAssignation CreateAssignation(ITES5Value reference, ITES5Value value)
 {
     return(new TES5VariableAssignation(reference, value));
 }
Beispiel #18
0
        private ITES5Value ConvertComparisonExpression(ITES4BinaryExpression expression, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            Tuple <ITES4Value, ITES4Value>[] tes4ValueTuples = new Tuple <ITES4Value, ITES4Value>[]
            {
                new Tuple <ITES4Value, ITES4Value>(expression.LeftValue, expression.RightValue),
                new Tuple <ITES4Value, ITES4Value>(expression.RightValue, expression.LeftValue)
            };

            /*
             * Scenario 1 - Special functions converted on expression level
             */
            foreach (Tuple <ITES4Value, ITES4Value> tes4ValueTuple in tes4ValueTuples)
            {
                ITES4Callable?valueTupleItem1 = tes4ValueTuple.Item1 as ITES4Callable;
                if (valueTupleItem1 == null)
                {
                    continue;
                }

                TES4Function function = valueTupleItem1.Function;

                switch (function.FunctionCall.FunctionName.ToLower())
                {
                case "getweaponanimtype":
                {
                    ITES5Referencer calledOn = this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope);
                    TES5ObjectCall  equippedWeaponLeftValue = this.objectCallFactory.CreateObjectCall(this.objectCallFactory.CreateObjectCall(calledOn, "GetEquippedWeapon"), "GetWeaponType");

                    int[] targetedWeaponTypes;
                    switch ((int)tes4ValueTuple.Item2.Data)
                    {
                    case 0:
                    {
                        targetedWeaponTypes = new int[] { 0 };
                        break;
                    }

                    case 1:
                    {
                        targetedWeaponTypes = new int[] { 1, 2, 3, 4 };
                        break;
                    }

                    case 2:
                    {
                        targetedWeaponTypes = new int[] { 5, 6, 8 };
                        break;
                    }

                    case 3:
                    {
                        targetedWeaponTypes = new int[] { 7, 9 };
                        break;
                    }

                    default:
                    {
                        throw new ConversionException("GetWeaponAnimType() - Unknown weapon type in expression");
                    }
                    }

                    List <TES5ComparisonExpression> expressions = new List <TES5ComparisonExpression>();

                    foreach (var targetedWeaponType in targetedWeaponTypes)
                    {
                        expressions.Add(TES5ExpressionFactory.CreateComparisonExpression(equippedWeaponLeftValue, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(targetedWeaponType)));
                    }

                    ITES5Expression resultExpression = expressions[0];

                    expressions.RemoveAt(0);

                    while (expressions.Any())
                    {
                        resultExpression = TES5ExpressionFactory.CreateLogicalExpression(resultExpression, TES5LogicalExpressionOperator.OPERATOR_OR, expressions.Last());
                        expressions.RemoveAt(expressions.Count - 1);
                    }

                    return(resultExpression);
                }

                case "getdetected":
                {
                    TES5ObjectCallArguments inversedArgument = new TES5ObjectCallArguments()
                    {
                        this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope)
                    };
                    TES5ObjectCall getDetectedLeftValue  = this.objectCallFactory.CreateObjectCall(this.referenceFactory.CreateReadReference(function.Arguments[0].StringValue, globalScope, multipleScriptsScope, codeScope.LocalScope), "isDetectedBy", inversedArgument);
                    TES5Integer    getDetectedRightValue = new TES5Integer(((int)tes4ValueTuple.Item2.Data == 0) ? 0 : 1);
                    return(TES5ExpressionFactory.CreateComparisonExpression(getDetectedLeftValue, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, getDetectedRightValue));
                }

                case "getdetectionlevel":
                {
                    if (!tes4ValueTuple.Item2.HasFixedValue)
                    {
                        throw new ConversionException("Cannot convert getDetectionLevel calls with dynamic comparision");
                    }

                    TES5Bool tes5Bool = new TES5Bool(((int)tes4ValueTuple.Item2.Data) == 3);         //true only if the compared value was 3

                    TES5ObjectCallArguments inversedArgument = new TES5ObjectCallArguments()
                    {
                        this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope)
                    };

                    return(TES5ExpressionFactory.CreateComparisonExpression
                           (
                               this.objectCallFactory.CreateObjectCall(this.referenceFactory.CreateReadReference(function.Arguments[0].StringValue, globalScope, multipleScriptsScope, codeScope.LocalScope), "isDetectedBy", inversedArgument),
                               TES5ComparisonExpressionOperator.OPERATOR_EQUAL,
                               tes5Bool
                           ));
                }

                case "getcurrentaiprocedure":
                {
                    if (!tes4ValueTuple.Item2.HasFixedValue)
                    {
                        throw new ConversionException("Cannot convert getCurrentAIProcedure() calls with dynamic comparision");
                    }

                    switch ((int)tes4ValueTuple.Item2.Data)
                    {
                    case 4:
                    {
                        return(TES5ExpressionFactory.CreateComparisonExpression(
                                   this.objectCallFactory.CreateObjectCall(this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope), "IsInDialogueWithPlayer"),
                                   TES5ComparisonExpressionOperator.OPERATOR_EQUAL,
                                   new TES5Bool(expression.Operator == TES4ComparisonExpressionOperator.OPERATOR_EQUAL)          //cast to true if the original op was ==, false otherwise.
                                   ));
                    }

                    case 8:
                    {
                        //ref.getSleepState() == 3
                        return(TES5ExpressionFactory.CreateComparisonExpression(
                                   this.objectCallFactory.CreateObjectCall(this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope), "getSleepState"),
                                   TES5ComparisonExpressionOperator.OPERATOR_EQUAL,
                                   new TES5Integer(3)          //SLEEPSTATE_SLEEP
                                   ));
                    }

                    case 13:
                    {
                        return(TES5ExpressionFactory.CreateComparisonExpression(
                                   this.objectCallFactory.CreateObjectCall(this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope), "IsInCombat"),
                                   TES5ComparisonExpressionOperator.OPERATOR_EQUAL,
                                   new TES5Bool(expression.Operator == TES4ComparisonExpressionOperator.OPERATOR_EQUAL)          //cast to true if the original op was ==, false otherwise.
                                   ));
                    }

                    case 0:            //Travel
                    case 7:            //Wander
                    case 15:           //Pursue
                    case 17:           //Done
                    {
                        //@INCONSISTENCE idk how to check it tbh. We return always true. Think about better representation
                        return(new TES5Bool(expression.Operator == TES4ComparisonExpressionOperator.OPERATOR_EQUAL));
                    }

                    default:
                    {
                        throw new ConversionException("Cannot convert GetCurrentAiProcedure - unknown TES4 procedure number arg " + ((int)tes4ValueTuple.Item2.Data).ToString());
                    }
                    }
                }

                case "isidleplaying":
                case "getknockedstate":
                case "gettalkedtopc":
                {
                    return(new TES5Bool(true));        //This is so unimportant that i think it"s not worth to find a good alternative and waste time.
                }

                case "getsitting":
                {
                    //WARNING: Needs to implement Horse sittings, too.
                    //SEE: http://www.gameskyrim.com/papyrus-isridinghorse-function-t255012.html
                    int goTo;
                    switch ((int)tes4ValueTuple.Item2.Data)
                    {
                    case 0:
                    {
                        goTo = 0;
                        break;
                    }

                    case 1:
                    case 2:
                    case 11:
                    case 12:
                    {
                        goTo = 2;
                        break;
                    }

                    case 3:
                    case 13:
                    {
                        goTo = 3;
                        break;
                    }

                    case 4:
                    case 14:
                    {
                        goTo = 4;
                        break;
                    }

                    default:
                    {
                        throw new ConversionException("GetSitting - unknown state found");
                    }
                    }

                    //ref.getSleepState() == 3
                    return(TES5ExpressionFactory.CreateComparisonExpression
                           (
                               this.objectCallFactory.CreateObjectCall(this.CreateCalledOnReferenceOfCalledFunction(valueTupleItem1, codeScope, globalScope, multipleScriptsScope), "GetSitState"),
                               TES5ComparisonExpressionOperator.GetFirst(expression.Operator.Name),
                               new TES5Integer(goTo)
                           ));
                }
                }
            }

            ITES5Value leftValue  = this.CreateValue(expression.LeftValue, codeScope, globalScope, multipleScriptsScope);
            ITES5Value rightValue = this.CreateValue(expression.RightValue, codeScope, globalScope, multipleScriptsScope);

            Tuple <ITES5Value, ITES5Value>[] tes5ValueTuples = new Tuple <ITES5Value, ITES5Value>[]
            {
                new Tuple <ITES5Value, ITES5Value>(leftValue, rightValue),
                new Tuple <ITES5Value, ITES5Value>(rightValue, leftValue)
            };

            TES5BasicType objectReferenceType   = TES5BasicType.T_FORM; //used just to make sure.
            TES5ComparisonExpressionOperator op = TES5ComparisonExpressionOperator.GetFirst(expression.Operator.Name);

            /*
             * Scenario 2: Comparision of ObjectReferences to integers ( quick formid check )
             */
            bool flipOperator = false;

            foreach (var valueTuple in tes5ValueTuples)
            {
                TES5ComparisonExpressionOperator newOp = !flipOperator ? op : op.Flip();
                if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(valueTuple.Item1.TES5Type, objectReferenceType) || TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(valueTuple.Item1.TES5Type.NativeType, objectReferenceType))
                {
                    if (valueTuple.Item2.TES5Type == TES5BasicType.T_INT)
                    {
                        //Perhaps we should allow to try to cast upwards for primitives, .asPrimitive() or similar
                        //In case we do know at compile time that we"re comparing against zero, then we can assume
                        //we can compare against None, which allows us not call GetFormID() on most probably None object
                        TES5Integer tes5SetItem2Integer = (TES5Integer)valueTuple.Item2;
                        if (tes5SetItem2Integer.IntValue == 0)
                        {
                            newOp = op == TES5ComparisonExpressionOperator.OPERATOR_EQUAL ? op : TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL;
                            return(TES5ExpressionFactory.CreateComparisonExpression(valueTuple.Item1, newOp, new TES5None()));
                        }
                        else
                        {
                            ITES5Referencer callable        = (ITES5Referencer)valueTuple.Item1;
                            TES5ObjectCall  tes5setNewItem1 = this.objectCallFactory.CreateObjectCall(callable, "GetFormID");
                            return(TES5ExpressionFactory.CreateComparisonExpression(tes5setNewItem1, newOp, valueTuple.Item2));
                        }
                    }
                }
                else if (valueTuple.Item1.TES5Type.OriginalName == TES5VoidType.OriginalNameConst)
                {
#if PHP_COMPAT
                    TES5IntegerOrFloat tes5SetItem2Number = tes5set.Item2 as TES5IntegerOrFloat;
                    if (tes5SetItem2Number != null && tes5SetItem2Number.ConvertedIntValue == 0)
                    {
                        return(TES5ExpressionFactory.createArithmeticExpression(tes5set.Item1, newOp, new TES5None()));
                    }
#else
                    throw new ConversionException("Type was void.");//This shouldn't happen anymore.
#endif
                }
                if (!TES5InheritanceGraphAnalyzer.IsTypeOrExtendsTypeOrIsNumberType(valueTuple.Item1.TES5Type, valueTuple.Item2.TES5Type, true))//WTM:  Change:  Added entire if branch
                {
                    if (valueTuple.Item1.TES5Type.NativeType == TES5BasicType.T_QUEST && valueTuple.Item2.TES5Type == TES5BasicType.T_INT)
                    {
                        TES5ObjectCall getStage = this.objectCallFactory.CreateObjectCall((ITES5Referencer)valueTuple.Item1, "GetStage");
                        return(TES5ExpressionFactory.CreateComparisonExpression(getStage, newOp, valueTuple.Item2));
                    }
                    if (valueTuple.Item1.TES5Type == TES5BasicType.T_BOOL && valueTuple.Item2.TES5Type == TES5BasicType.T_INT)
                    {
                        int item2Value = ((TES5Integer)valueTuple.Item2).IntValue;
                        if (item2Value != 0 && item2Value != 1)
                        {
                            throw new ConversionException("Unexpected Value:  " + item2Value.ToString());
                        }
                        ITES5Value newItem2 = new TES5Bool(item2Value == 1);
                        newOp = op == TES5ComparisonExpressionOperator.OPERATOR_EQUAL ? op : TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL;
                        return(TES5ExpressionFactory.CreateComparisonExpression(valueTuple.Item1, newOp, newItem2));
                    }
                    if (valueTuple.Item1.TES5Type == TES5BasicType.T_ACTOR && valueTuple.Item2.TES5Type == TES5BasicType.T_ACTORBASE)
                    {
                        return(TES5ExpressionFactory.CreateComparisonExpression(objectCallFactory.CreateGetActorBase((TES5ObjectCall)valueTuple.Item1), newOp, valueTuple.Item2));
                    }
                    //WTM:  Change:  Added for se08barriertriggerscript
                    if (newOp == TES5ComparisonExpressionOperator.OPERATOR_EQUAL && TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(valueTuple.Item1.TES5Type, TES5BasicType.T_FORM) && TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(valueTuple.Item2.TES5Type, TES5BasicType.T_FORM))
                    {
                        TES5Reference reference1 = (TES5Reference)valueTuple.Item1;
                        TES5Reference reference2 = (TES5Reference)valueTuple.Item2;
                        reference1.ManualCastTo = TES5BasicType.T_FORM;
                        reference2.ManualCastTo = TES5BasicType.T_FORM;
                        return(TES5ExpressionFactory.CreateComparisonExpression(reference1, newOp, reference2));
                    }
                    throw new ConversionException("Type could not be converted.");
                }
                TES5ComparisonExpression?containsCall = ConvertGetItemCountCallToContainsItemCall(valueTuple.Item1, op, valueTuple.Item2); //WTM:  Change:  Added
                if (containsCall != null)
                {
                    return(containsCall);
                }
                flipOperator = true;
            }
            return(TES5ExpressionFactory.CreateComparisonExpression(leftValue, op, rightValue));
        }
        private static void SetUpBranch(TES5FunctionScope blockFunctionScope, TES5EventCodeBlock newBlock, ITES5Value expression)
        {
            TES5CodeScope newCodeScope = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope);
            //TES5CodeScope outerBranchCode = PHPFunction.Deserialize<TES5CodeScope>(PHPFunction.Serialize(newBlock.CodeScope));//WTM:  Change:  Why serialize and then deserialize?
            TES5CodeScope outerBranchCode = newBlock.CodeScope;

            outerBranchCode.LocalScope.ParentScope = newCodeScope.LocalScope;
            newCodeScope.AddChunk(new TES5Branch(new TES5SubBranch(expression, outerBranchCode)));
            newBlock.CodeScope = newCodeScope;
        }
 public TES5Return(ITES5Value returnValue = null)
 {
     this.returnValue = returnValue;
 }
Beispiel #21
0
 public TES5LogicalExpression(ITES5Value left, TES5LogicalExpressionOperator op, ITES5Value right)
     : base(left, op, right)
 {
 }
 public TES5SubBranch(ITES5Value expression, TES5CodeScope codeScope)
 {
     this.expression = expression;
     this.CodeScope  = codeScope;
 }
Beispiel #23
0
        //WTM:  Change:  Added:
        //I think GetItemCount returns 0 for all Containers that have ObjectReference scripts before they are opened:
        //https://forums.nexusmods.com/index.php?/topic/7174696-huge-mystery-with-getitemcount/#entry65389511
        //Once the player opens the Container once, then GetItemCount starts returning the correct count.
        //This does not seem to apply to ObjectRefence, so I've excluded it below.
        private TES5ComparisonExpression?ConvertGetItemCountCallToContainsItemCall(ITES5Value leftValue, TES5ComparisonExpressionOperator op, ITES5Value rightValue)
        {
            if (rightValue.TES5Type == TES5BasicType.T_INT)
            {
                TES5ObjectCall?value1ObjectCall = leftValue as TES5ObjectCall;
                if (value1ObjectCall != null && value1ObjectCall.FunctionName.Equals("GetItemCount", StringComparison.OrdinalIgnoreCase))
                {
                    ITES5Referencer accessedObject = value1ObjectCall.AccessedObject;
                    if (accessedObject is TES5PlayerReference)
                    {
                        return(null);
                    }                                                          //WTM:  Note:  GetItemCount works for the player, so the call doesn't need to be converted to ContainsItem.
                    ITES5VariableOrProperty?calledOn = accessedObject.ReferencesTo;
                    if (calledOn == null)
                    {
                        TES5ObjectCall?innerObjectCall = accessedObject as TES5ObjectCall;
                        if (innerObjectCall == null)
                        {
                            throw new InvalidOperationException("Called on object could not be found.");
                        }
                        calledOn = innerObjectCall.AccessedObject.ReferencesTo;
                        if (calledOn == null)
                        {
                            throw new InvalidOperationException("Called on object could not be found.");
                        }
                    }
                    if (calledOn.ReferenceEDID == null)
                    {
                        throw new NullableException(nameof(calledOn.ReferenceEDID));
                    }
                    ITES5Type?referenceType = esmAnalyzer.GetTypeByEDIDWithFollow(calledOn.ReferenceEDID, true, useScriptTypeCache: false);
                    if (referenceType == null)
                    {
                        referenceType = calledOn.TES5Type;
                    }                                                                //WTM:  Note:  Revert to type determined by previous inferences.

                    /*
                     * //WTM:  Note:  Example:
                     * calledOn.ReferenceEDID:  Dark11ChorrolSackRef
                     * referenceType.OriginalName:  Dark11ChorrolDropScript
                     * referenceType.NativeType:  Container
                     * Dark11ChorrolSack "Old Sack" [CONT:00031B2B] SCRI:  Dark11ChorrolDropScript [SCPT:00031B28]
                     * Dark11ChorrolSackRef is an ObjectReference with a base object of a Container,
                     * but Dark11ChorrolDropScript had to be inferred as an ObjectReference for transpilation to complete.
                     */
                    if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(referenceType, TES5BasicType.T_OBJECTREFERENCE))
                    {//WTM:  Note:  I think GetItemCount works for ObjectReferences that are transpiled as ObjectReferences.
                        //So they don't require the use of ContainsItem.
                        return(null);
                    }
                    TES5Integer?value2Integer = rightValue as TES5Integer;
                    if (value2Integer != null)
                    {
                        bool canConvert, negate = false;
                        if (
                            (op == TES5ComparisonExpressionOperator.OPERATOR_GREATER && value2Integer.IntValue == 0) ||
                            (op == TES5ComparisonExpressionOperator.OPERATOR_GREATER_OR_EQUAL && value2Integer.IntValue == 1) ||
                            (op == TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL && value2Integer.IntValue == 0)
                            )
                        {
                            canConvert = true;
                        }
                        else if (
                            (op == TES5ComparisonExpressionOperator.OPERATOR_LESS && value2Integer.IntValue == 1) ||
                            (op == TES5ComparisonExpressionOperator.OPERATOR_LESS_OR_EQUAL && value2Integer.IntValue == 0) ||
                            (op == TES5ComparisonExpressionOperator.OPERATOR_EQUAL && value2Integer.IntValue == 0)
                            )
                        {
                            canConvert = true;
                            negate     = true;
                        }
                        else
                        {
                            canConvert = CanConvertGetItemCountSpecialCases(value1ObjectCall, op, value2Integer);
                        }
                        if (canConvert)
                        {
                            TES5ObjectCall           newObjectCall        = objectCallFactory.CreateObjectCall(value1ObjectCall.AccessedObject, "ContainsItem", value1ObjectCall.Arguments);
                            TES5ComparisonExpression comparisonExpression = TES5ExpressionFactory.CreateComparisonExpression(newObjectCall, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(!negate));
                            return(comparisonExpression);
                        }
                    }
                }
            }
            return(null);
        }
Beispiel #24
0
 public TES5BoolCastedExpression(ITES5Value value)
 {
     this.value = value;
 }
Beispiel #25
0
 public static TES5LogicalExpression CreateLogicalExpression(ITES5Value left, TES5LogicalExpressionOperator op, ITES5Value right)
 {
     return(new TES5LogicalExpression(left, op, right));
 }
        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));
            }
            }
        }
Beispiel #27
0
 public TES5TrueBooleanExpression(ITES5Value value)
 {
     this.value = value;
 }
 public TES5VariableAssignation(ITES5Value reference, ITES5Value value)
 {
     this.Reference = reference;
     this.value     = value;
 }
        public TES5CodeScope Modify(TES4CodeBlock block, TES5BlockList blockList, TES5FunctionScope blockFunctionScope, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            //https://cs.elderscrolls.com/index.php?title=Begin
            //WTM:  Change:  Added:  I reorganized this method and forced each event to account for the first Oblivion parameter.
            bool accountedForParameter = false;

            switch (block.BlockType.ToLower())
            {
            case "gamemode":
            case "scripteffectupdate":
            {
                TES5ObjectCall function = this.objectCallFactory.CreateRegisterForSingleUpdate(globalScope);
                codeScope.AddChunk(function);
                if (globalScope.ScriptHeader.ScriptType.NativeType == TES5BasicType.T_QUEST)
                {
                    TES5EventCodeBlock onInitBlock = TES5BlockFactory.CreateOnInit();
                    onInitBlock.AddChunk(function);
                    blockList.Add(onInitBlock);
                }
                break;
            }

            case "menumode":
            {
                TES5ComparisonExpression isInMenuModeComparisonExpression = GetIsInMenuModeComparisonExpression();
                codeScope             = SetUpBranch(blockFunctionScope, codeScope, isInMenuModeComparisonExpression);
                accountedForParameter = true;        //Skyrim handles menus differently than Oblivion's MenuType.
                break;
            }

            case "onactivate":
            {
                TES5EventCodeBlock onInitBlock = TES5BlockFactory.CreateOnInit();
                TES5ObjectCall     function    = this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "BlockActivation");
                onInitBlock.AddChunk(function);
                blockList.Add(onInitBlock);
                //WTM:  Change:  Added:  The following scripts erroneously add a parameter to their OnActivate block:
                //MS11BradonCorpse, SE01WaitingRoomScript, SE02LoveLetterScript, SE08Xeddefen03DoorSCRIPT, SE08Xeddefen05DoorSCRIPT, SE32TombEpitaph01SCRIPT, SEHillofSuicidesSCRIPT, SEXidPuzButton1, SEXidPuzButton2, SEXidPuzButton3, SEXidPuzButton4, SEXidPuzButtonSCRIPT, SEXidPuzHungerSCRIPT, XPEbroccaCrematorySCRIPT
                //But OnActivate does not take a parameter.  I'm trying to use the author's intended parameter instead of just ignoring it.
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akActivateRef", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }


            case "onactorequip":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, TES5LocalVariableParameterMeaning.CONTAINER, globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onadd":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akNewContainer", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onalarm":
            {
                //@INCONSISTENCE - We don"t account for CrimeType or Criminal.
                codeScope.AddChunk(this.objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "Trace", new TES5ObjectCallArguments()
                    {
                        new TES5String("This function does not account for OnAlarm's CrimeType or Criminal.")
                    }));
                ITES5Value isAlarmed = TES5ExpressionFactory.CreateComparisonExpression(this.objectCallFactory.CreateObjectCall(TES5ReferenceFactory.CreateReferenceToSelf(globalScope), "IsAlarmed"), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Bool(true));
                codeScope             = SetUpBranch(blockFunctionScope, codeScope, isAlarmed);
                accountedForParameter = true;
                break;
            }

            /*
             * case "onalarm":
             * {
             *
             *  this.skyrimGroupEventName = "onhit";
             *
             *  if (this.eventArgs[1] != 3) {
             *      //Nothing eelse is supported really..
             *      this.omit = true;
             *      break;
             *  }
             *
             *  branch = new TES4ConditionalBranch();
             *  expression = new TES4Expression();
             *  leftConstant = new TES4Constant("akAggressor", "ObjectReference");
             *  //actionConstant        = new TES4Constant(this.eventArgs[1],"Package");
             *  actionConstant = TES4Factories.createReference(this.eventArgs[2], this);
             *
             *  expression.left_side = leftConstant;
             *  expression.right_side = actionConstant;
             *  expression.comparision_operator = TES4Expression.COMPARISION_OPERATOR_EQUAL;
             *
             *  codeBlock = new TES4CodeBlock();
             *  codeBlock.chunks = this.chunks;
             *
             *  branch.ifs[] = array(
             *      "rawExpression" => "SCRIPT_GENERATED",
             *      "expression" => expression,
             *      "codeBlock" => codeBlock
             *  );
             *  this.chunks = new TES4ChunkContainer();
             *  this.chunks.parent = this;
             *  this.chunks.addChunk(branch);
             *
             *  break;
             * }
             */

            case "ondeath":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akKiller", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "ondrop":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akOldContainer", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onequip":
            case "onunequip":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akActor", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onhit":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akAggressor", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onhitwith":
            {
                TES4BlockParameterList?parameterList = block.BlockParameterList;
                if (parameterList != null)
                {
                    TES5LocalScope           localScope          = codeScope.LocalScope;
                    ITES5Referencer          hitWithCriteria     = this.referenceFactory.CreateReadReference(parameterList.Parameters[0].BlockParameter, globalScope, multipleScriptsScope, localScope);
                    TES5SignatureParameter   akSource            = localScope.FunctionScope.GetParameter("akSource");
                    TES5ComparisonExpression hitWithEqualsSource = TES5ExpressionFactory.CreateComparisonExpression(TES5ReferenceFactory.CreateReferenceToVariableOrProperty(akSource), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, hitWithCriteria);
                    TES5CodeScope            newCodeScope        = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope);
                    if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(TES5BasicType.T_AMMO, hitWithCriteria.TES5Type))
                    {
                        newCodeScope.AddChunk(this.objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.Debug, "Trace", new TES5ObjectCallArguments()
                            {
                                new TES5String("OBScript called OnHitWith using Ammo, but it's unlikely Papyrus will handle it properly.  When arrows are used, " + akSource.Name + " will be a bow.")
                            }));
                    }
                    newCodeScope.AddChunk(new TES5Branch(new TES5SubBranch(hitWithEqualsSource, codeScope)));
                    codeScope = newCodeScope;
                }
                accountedForParameter = true;
                break;
            }

            case "onmagiceffecthit":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akEffect", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onpackagestart":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akNewPackage", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onpackagechange":
            case "onpackagedone":
            case "onpackageend":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akOldPackage", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onsell":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akSeller", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "onstartcombat":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akTarget", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "ontrigger":
            {
                codeScope             = SetUpBranch(block, codeScope, blockFunctionScope, "akActivateRef", globalScope, multipleScriptsScope);
                accountedForParameter = true;
                break;
            }

            case "ontriggeractor":
            {
                TES4BlockParameterList?  parameterList                = block.BlockParameterList;
                TES5LocalScope           localScope                   = codeScope.LocalScope;
                ITES5VariableOrProperty  activator                    = localScope.GetVariableWithMeaning(TES5LocalVariableParameterMeaning.ACTIVATOR);
                TES5LocalVariable        castedToActor                = new TES5LocalVariable("akAsActor", TES5BasicType.T_ACTOR);
                TES5Reference            referenceToCastedVariable    = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(castedToActor);
                TES5Reference            referenceToNonCastedVariable = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(activator);
                TES5ComparisonExpression expression                   = TES5ExpressionFactory.CreateComparisonExpression(referenceToCastedVariable, TES5ComparisonExpressionOperator.OPERATOR_NOT_EQUAL, new TES5None());
                TES5CodeScope            newCodeScope                 = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope);
                newCodeScope.AddVariable(castedToActor);
                newCodeScope.AddChunk(TES5VariableAssignationFactory.CreateAssignation(referenceToCastedVariable, referenceToNonCastedVariable));
                TES5CodeScope outerBranchCode = TES5CodeScopeFactory.CreateCodeScopeRoot(blockFunctionScope);
                outerBranchCode.LocalScope.CopyVariablesFrom(codeScope.LocalScope);
                if (parameterList != null)
                {
                    ITES5Referencer          targetActor     = this.referenceFactory.CreateReadReference(parameterList.Parameters[0].BlockParameter, globalScope, multipleScriptsScope, localScope);
                    TES5ComparisonExpression interExpression = TES5ExpressionFactory.CreateComparisonExpression(TES5ReferenceFactory.CreateReferenceToVariableOrProperty(activator), TES5ComparisonExpressionOperator.OPERATOR_EQUAL, targetActor);
                    outerBranchCode.AddChunk(new TES5Branch(new TES5SubBranch(interExpression, codeScope)));
                }
                else
                {
                    outerBranchCode.AddChunks(codeScope.CodeChunks);
                }
                newCodeScope.AddChunk(new TES5Branch(new TES5SubBranch(expression, outerBranchCode)));
                codeScope             = newCodeScope;
                accountedForParameter = true;
                break;
            }

            case "onload":
            case "onreset":
            case "ontriggermob":
            case "scripteffectstart":
            case "scripteffectfinish":
            {
                break;
            }

            default:
            {
                throw new InvalidOperationException(block.BlockType + " not found.");
            }
            }
            if (!accountedForParameter)
            {
                TES4BlockParameterList?parameterList = block.BlockParameterList;
                if (parameterList != null && parameterList.Parameters.Any())
                {
                    throw new ConversionException("Parameter not accounted for in " + block.BlockType + ":  " + parameterList.Parameters[0].BlockParameter);
                }
            }
            return(codeScope);
        }
Beispiel #30
0
 public static TES5VariableAssignation CreateAssignation(ITES5Value target, ITES5Value value)
 {
     return(new TES5VariableAssignation(target, value));
 }