public function getData() { switch ($this->operator) { case TES4ArithmeticExpressionOperator::OPERATOR_EQUAL(): return $this->leftValue->getData() == $this->rightValue->getData(); case TES4ArithmeticExpressionOperator::OPERATOR_GREATER(): return $this->leftValue->getData() > $this->rightValue->getData(); case TES4ArithmeticExpressionOperator::OPERATOR_GREATER_OR_EQUAL(): return $this->leftValue->getData() >= $this->rightValue->getData(); case TES4ArithmeticExpressionOperator::OPERATOR_LESS(): return $this->leftValue->getData() < $this->rightValue->getData(); case TES4ArithmeticExpressionOperator::OPERATOR_LESS_OR_EQUAL(): return $this->leftValue->getData() <= $this->rightValue->getData(); case TES4ArithmeticExpressionOperator::OPERATOR_NOT_EQUAL(): return $this->leftValue->getData() != $this->rightValue->getData(); } throw new ConversionException("Unknown TES4ArithmeticExpressionOperator"); }
private function convertArithmeticExpression(TES4Expression $expression, TES5CodeScope $codeScope, TES5GlobalScope $globalScope, TES5MultipleScriptsScope $multipleScriptsScope) { $sets = [[$expression->getLeftValue(), $expression->getRightValue()], [$expression->getRightValue(), $expression->getLeftValue()]]; /** * Scenario 1 - Special functions converted on expression level * @var TES4Value[] $set */ foreach ($sets as $set) { if (!$set[0] instanceof TES4Callable) { continue; } $function = $set[0]->getFunction(); switch (strtolower($function->getFunctionCall()->getFunctionName())) { case "getweaponanimtype": $calledOn = $this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope); $leftValue = $this->createObjectCall($this->createObjectCall($calledOn, "GetEquippedWeapon", $multipleScriptsScope), "GetWeaponType", $multipleScriptsScope); switch ((int) $set[1]->getData()) { case 0: $targetedWeaponTypes = [0]; break; case 1: $targetedWeaponTypes = [1, 2, 3, 4]; break; case 2: $targetedWeaponTypes = [5, 6, 8]; break; case 3: $targetedWeaponTypes = [7, 9]; break; default: throw new ConversionException("GetWeaponAnimType() - Unknown weapon type in expression"); } $expressions = []; foreach ($targetedWeaponTypes as $targetedWeaponType) { $expressions[] = $this->expressionFactory->createArithmeticExpression($leftValue, TES5ArithmeticExpressionOperator::OPERATOR_EQUAL(), new TES5Integer($targetedWeaponType)); } $resultExpression = $expressions[0]; unset($expressions[0]); while (!empty($expressions)) { $resultExpression = $this->expressionFactory->createLogicalExpression($resultExpression, TES5LogicalExpressionOperator::OPERATOR_OR(), array_pop($expressions)); } return $resultExpression; case "getdetected": $inversedArgument = new TES5ObjectCallArguments(); $inversedArgument->add($this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope)); $leftValue = $this->createObjectCall($this->createReadReference($function->getArguments()->getValue(0)->getData(), $globalScope, $multipleScriptsScope, $codeScope->getLocalScope()), "isDetectedBy", $multipleScriptsScope, $inversedArgument); $rightValue = new TES5Integer((int) $set[1]->getData() == 0 ? 0 : 1); $expression = $this->expressionFactory->createArithmeticExpression($leftValue, TES5ArithmeticExpressionOperator::OPERATOR_EQUAL(), $rightValue); return $expression; case "getdetectionlevel": if (!$set[1]->hasFixedValue()) { throw new ConversionException("Cannot convert getDetectionLevel calls with dynamic comparision"); } $boolean = new TES5Bool($set[1]->getData() == 3); //true only if the compared value was 3 $inversedArgument = new TES5ObjectCallArguments(); $inversedArgument->add($this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope)); $expression = $this->expressionFactory->createArithmeticExpression($this->createObjectCall($this->createReadReference($function->getArguments()->getValue(0)->getData(), $globalScope, $multipleScriptsScope, $codeScope->getLocalScope()), "isDetectedBy", $multipleScriptsScope, $inversedArgument), TES5ArithmeticExpressionOperator::OPERATOR_EQUAL(), $boolean); return $expression; case "getcurrentaiprocedure": if (!$set[1]->hasFixedValue()) { throw new ConversionException("Cannot convert getCurrentAIProcedure() calls with dynamic comparision"); } switch ((int) $set[1]->getData()) { case 4: //ref.getSleepState() == 3 $expression = $this->expressionFactory->createArithmeticExpression($this->createObjectCall($this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope), "IsInDialogueWithPlayer", $multipleScriptsScope), TES5ArithmeticExpressionOperator::OPERATOR_EQUAL(), new TES5Bool((bool) $expression->getOperator() == TES4ArithmeticExpressionOperator::OPERATOR_EQUAL())); return $expression; case 8: //ref.getSleepState() == 3 $expression = $this->expressionFactory->createArithmeticExpression($this->createObjectCall($this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope), "getSleepState", $multipleScriptsScope), TES5ArithmeticExpressionOperator::OPERATOR_EQUAL(), new TES5Integer(3)); return $expression; case 13: //ref.getSleepState() == 3 $expression = $this->expressionFactory->createArithmeticExpression($this->createObjectCall($this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope), "IsInCombat", $multipleScriptsScope), TES5ArithmeticExpressionOperator::OPERATOR_EQUAL(), new TES5Bool((bool) $expression->getOperator() == TES4ArithmeticExpressionOperator::OPERATOR_EQUAL())); return $expression; case 0: case 7: case 15: case 17: //@INCONSISTENCE Wander.. idk how to check it tbh. We return always true. Think about better representation return new TES5Bool((bool) $expression->getOperator() == TES4ArithmeticExpressionOperator::OPERATOR_EQUAL()); default: throw new ConversionException("Cannot convert GetCurrentAiProcedure - unknown TES4 procedure number arg " . (int) $set[1]->getData()); } break; 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 switch ((int) $set[1]->getData()) { 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 $expression = $this->expressionFactory->createArithmeticExpression($this->createObjectCall($this->createCalledOnReferenceOfCalledFunction($set[0], $codeScope, $globalScope, $multipleScriptsScope), "GetSitState", $multipleScriptsScope), TES5ArithmeticExpressionOperator::memberByValue($expression->getOperator()->value()), new TES5Integer($goTo)); return $expression; } } $leftValue = $this->createValue($expression->getLeftValue(), $codeScope, $globalScope, $multipleScriptsScope); $rightValue = $this->createValue($expression->getRightValue(), $codeScope, $globalScope, $multipleScriptsScope); $tes5sets = [[$leftValue, $rightValue], [$rightValue, $leftValue]]; $objectReferenceType = TES5BasicType::T_FORM(); //used just to make sure. $operator = TES5ArithmeticExpressionOperator::memberByValueWithDefault($expression->getOperator()->value(), null); /** * @var TES5Value[] $tes5set * Scenario 2: Comparision of ObjectReferences to integers ( quick formid check ) */ foreach ($tes5sets as $tes5set) { if ($tes5set[0]->getType() == $objectReferenceType || TES5InheritanceGraphAnalyzer::isExtending($tes5set[0]->getType(), $objectReferenceType)) { if ($tes5set[1]->getType() == TES5BasicType::T_INT()) { $tes5set[0] = $this->createObjectCall($tes5set[0], "GetFormID", $multipleScriptsScope); return $this->expressionFactory->createArithmeticExpression($tes5set[0], $operator, $tes5set[1]); } } else { if ($tes5set[0]->getType() == TES5TypeFactory::void()) { if ($tes5set[1] instanceof TES5Integer || $tes5set[1] instanceof TES5Float) { if ($tes5set[1]->getValue() == 0) { return $this->expressionFactory->createArithmeticExpression($tes5set[0], $operator, new TES5None()); } } } } } return $this->expressionFactory->createArithmeticExpression($leftValue, $operator, $rightValue); }
public function getOperator() { return TES4ArithmeticExpressionOperator::OPERATOR_EQUAL(); }