/**
  * @param TypeMapper $typeMapper
  * @param string $dataFile
  */
 public function __construct(TypeMapper $typeMapper, $dataFile = "Oblivion.esm")
 {
     $this->typeMapper = $typeMapper;
     if ($this->esm === null) {
         $this->esm = file_get_contents($dataFile);
     }
     if ($this->scriptTypes === null) {
         preg_match_all("#SCPT................EDID..([a-zA-Z0-9_-]+)\\x{00}SCHR..................(..)#si", $this->esm, $scripts);
         foreach ($scripts[2] as $i => $type) {
             $is_q = (bool) ord($type[0]);
             $is_m = (bool) ord($type[1]);
             if ($is_q) {
                 $scriptType = TES5BasicType::T_QUEST();
             } else {
                 if ($is_m) {
                     $scriptType = TES5BasicType::T_ACTIVEMAGICEFFECT();
                 } else {
                     $scriptType = TES5BasicType::T_OBJECTREFERENCE();
                 }
             }
             $this->scriptTypes[strtolower($scripts[1][$i])] = $scriptType;
         }
     }
     if ($this->globals === null) {
         preg_match_all("#GLOB................EDID..([a-zA-Z0-9_-]+)\\x{00}#si", $this->esm, $globals);
         $globalArray = [];
         foreach ($globals[1] as $global) {
             $globalArray[] = new TES5GlobalVariable($global);
         }
         $this->globals = $globalArray;
     }
     if (self::$instance === null) {
         self::$instance = $this;
     }
 }
 public function createFromFragmentType(TES5FragmentType $fragmentType)
 {
     $localScope = new TES5LocalScope();
     switch ($fragmentType) {
         case TES5FragmentType::T_TIF():
             $localScope->addVariable(new TES5LocalVariable("akSpeakerRef", TES5BasicType::T_OBJECTREFERENCE(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case TES5FragmentType::T_PF():
             $localScope->addVariable(new TES5LocalVariable("akActor", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case TES5FragmentType::T_QF():
             break;
     }
     return $localScope;
 }
 /**
  * Extracts implicit reference from calls.
  * Returns a reference from calls like:
  * Enable
  * Disable
  * Activate
  * GetInFaction whatsoever
  * @param TES5GlobalScope $globalScope
  * @param TES5MultipleScriptsScope $multipleScriptsScope
  * @param TES5LocalScope $localScope
  * @return TES5Referencer
  * @throws \Ormin\OBSLexicalParser\TES5\Exception\ConversionException
  */
 private function extractImplicitReference(TES5GlobalScope $globalScope, TES5MultipleScriptsScope $multipleScriptsScope, TES5LocalScope $localScope)
 {
     switch ($globalScope->getScriptHeader()->getBasicScriptType()) {
         case TES5BasicType::T_OBJECTREFERENCE():
             return $this->referenceFactory->createReferenceToSelf($globalScope);
         case TES5BasicType::T_ACTIVEMAGICEFFECT():
             $self = $this->referenceFactory->createReferenceToSelf($globalScope);
             return $this->createObjectCall($self, "GetTargetActor", $multipleScriptsScope);
         case TES5BasicType::T_QUEST():
             //todo - this should not be done like this
             //we should actually not try to extract the implicit reference on the non-reference oblivion functions like "stopQuest"
             //think of this line as a hacky way to just get code forward.
             return $this->referenceFactory->createReferenceToSelf($globalScope);
             /**
              * TIF Fragments
              */
         /**
          * TIF Fragments
          */
         case TES5BasicType::T_TOPICINFO():
             return $this->createReadReference('akSpeakerRef', $globalScope, $multipleScriptsScope, $localScope);
         default:
             throw new ConversionException("Cannot extract implicit reference - unknown basic script type.");
     }
 }
 public function createFromBlockType($blockType, TES5GlobalScope $globalScope)
 {
     $localScope = new TES5LocalScope();
     switch ($blockType) {
         case 'OnUpdate':
             break;
         case 'OnActivate':
             $localScope->addVariable(new TES5LocalVariable("akActivateRef", TES5BasicType::T_OBJECTREFERENCE(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case 'OnInit':
             break;
         case 'OnSell':
             $localScope->addVariable(new TES5LocalVariable("akSeller", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case 'OnDeath':
             $localScope->addVariable(new TES5LocalVariable("akKiller", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case 'OnLoad':
             break;
         case 'OnObjectEquipped':
             $localScope->addVariable(new TES5LocalVariable("akBaseObject", TES5BasicType::T_FORM(), [TES5LocalVariableParameterMeaning::CONTAINER()]));
             $localScope->addVariable(new TES5LocalVariable("akReference", TES5BasicType::T_OBJECTREFERENCE()));
             break;
         case 'OnTriggerEnter':
             $localScope->addVariable(new TES5LocalVariable("akActivateRef", TES5BasicType::T_OBJECTREFERENCE(), [TES5LocalVariableParameterMeaning::ACTIVATOR(), TES5LocalVariableParameterMeaning::CONTAINER()]));
             break;
         case 'OnEquipped':
             $localScope->addVariable(new TES5LocalVariable("akActor", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR(), TES5LocalVariableParameterMeaning::CONTAINER()]));
             break;
         case 'OnUnequipped':
             $localScope->addVariable(new TES5LocalVariable("akActor", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case 'OnContainerChanged':
             $localScope->addVariable(new TES5LocalVariable("akNewContainer", TES5BasicType::T_OBJECTREFERENCE()));
             $localScope->addVariable(new TES5LocalVariable("akOldContainer", TES5BasicType::T_OBJECTREFERENCE()));
             break;
         case 'OnTrigger':
             $localScope->addVariable(new TES5LocalVariable("akActivateRef", TES5BasicType::T_OBJECTREFERENCE(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case 'OnHit':
             $localScope->addVariable(new TES5LocalVariable("akAggressor", TES5BasicType::T_OBJECTREFERENCE(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             $localScope->addVariable(new TES5LocalVariable("akSource", TES5BasicType::T_FORM()));
             $localScope->addVariable(new TES5LocalVariable("akProjectile", TES5BasicType::T_PROJECTILE()));
             $localScope->addVariable(new TES5LocalVariable("abPowerAttack", TES5BasicType::T_BOOL()));
             $localScope->addVariable(new TES5LocalVariable("abSneakAttack", TES5BasicType::T_BOOL()));
             $localScope->addVariable(new TES5LocalVariable("abBashAttack", TES5BasicType::T_BOOL()));
             $localScope->addVariable(new TES5LocalVariable("abHitBlocked", TES5BasicType::T_BOOL()));
             break;
         case 'OnCombatStateChanged':
             $localScope->addVariable(new TES5LocalVariable("akTarget", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             $localScope->addVariable(new TES5LocalVariable("aeCombatState", TES5BasicType::T_INT()));
             break;
         case 'OnPackageStart':
             $localScope->addVariable(new TES5LocalVariable("akNewPackage", TES5BasicType::T_PACKAGE()));
             break;
         case 'OnPackageDone':
             $localScope->addVariable(new TES5LocalVariable("akDonePackage", TES5BasicType::T_PACKAGE()));
             break;
         case 'OnPackageEnd':
             $localScope->addVariable(new TES5LocalVariable("akOldPackage", TES5BasicType::T_PACKAGE()));
             break;
         case 'OnPackageChange':
             $localScope->addVariable(new TES5LocalVariable("akOldPackage", TES5BasicType::T_PACKAGE()));
             break;
         case 'OnMagicEffectApply':
             $localScope->addVariable(new TES5LocalVariable("akCaster", TES5BasicType::T_OBJECTREFERENCE(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             $localScope->addVariable(new TES5LocalVariable("akMagicEffect", TES5BasicType::T_MAGICEFFECT()));
             break;
         case 'OnReset':
             break;
         case 'OnEffectStart':
             $localScope->addVariable(new TES5LocalVariable("akTarget", TES5BasicType::T_ACTOR()));
             $localScope->addVariable(new TES5LocalVariable("akCaster", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         case 'OnEffectFinish':
             $localScope->addVariable(new TES5LocalVariable("akTarget", TES5BasicType::T_ACTOR()));
             $localScope->addVariable(new TES5LocalVariable("akCaster", TES5BasicType::T_ACTOR(), [TES5LocalVariableParameterMeaning::ACTIVATOR()]));
             break;
         default:
             throw new ConversionException("Cannot find new block type local scope variables out of " . $blockType);
     }
     return $localScope;
 }