Ejemplo n.º 1
0
void Interpreter::doSuperSend(long bytecodeIndex) {
    VMSymbol* signature = static_cast<VMSymbol*>(method->GetConstant(bytecodeIndex));

    VMFrame* ctxt = GetFrame()->GetOuterContext();
    VMMethod* realMethod = ctxt->GetMethod();
    VMClass* holder = realMethod->GetHolder();
    VMClass* super = holder->GetSuperClass();
    VMInvokable* invokable = static_cast<VMInvokable*>(super->LookupInvokable(signature));

    if (invokable != nullptr)
        (*invokable)(GetFrame());
    else {
        long numOfArgs = Signature::GetNumberOfArguments(signature);
        vm_oop_t receiver = GetFrame()->GetStackElement(numOfArgs - 1);
        VMArray* argumentsArray = GetUniverse()->NewArray(numOfArgs);

        for (long i = numOfArgs - 1; i >= 0; --i) {
            vm_oop_t o = GetFrame()->Pop();
            argumentsArray->SetIndexableField(i, o);
        }
        vm_oop_t arguments[] = {signature, argumentsArray};

        AS_OBJ(receiver)->Send(doesNotUnderstand, arguments, 2);
    }
}
	bool SetNodeLocalRotationEuler(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);
		if(object && inArray.Length() == 3) {
			float heading, attitude, bank;

			inArray.Get(&heading, 0);
			inArray.Get(&attitude, 1);
			inArray.Get(&bank, 2);

			// Degrees to radians
			heading *= MATH_PI / 180;
			attitude *= MATH_PI / 180;
			bank *= MATH_PI / 180;

			object->m_localTransform.rot.SetEulerAngles(heading, attitude, bank);

			BSTaskPool * taskPool = BSTaskPool::GetSingleton();
			if(taskPool)
				taskPool->UpdateWorldData(object);

			return true;
		}

		return false;
	}
Ejemplo n.º 3
0
    // 配列の要素の順番を反転させる。引数の配列自体を変更する。
    static void ReverseArray(VMArray<SInt32> arr)
    {
        std::size_t size = arr.GetSize();
        std::size_t n = size / 2;

        for (int i = 0; i < n; i++)
        {
            arr.Swap(i, size-i-1);
        }
    }
	bool GetNodeLocalPosition(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);
		if(object && inArray.Length() == 3) {
			inArray.Set(&object->m_localTransform.pos.x, 0);
			inArray.Set(&object->m_localTransform.pos.y, 1);
			inArray.Set(&object->m_localTransform.pos.z, 2);
			return true;
		}

		return false;
	}
Ejemplo n.º 5
0
void ApplyMultByIndex(VMArray<float> &multsToModify, UInt32 index, float iniVal, float max)
{
	//Enforce limits
	if (iniVal < 0.0)
		iniVal = 0.0;
	else if (iniVal > max)
		iniVal = max;

	float data;
	multsToModify.Get(&data, index);
	data *= iniVal;
	multsToModify.Set(&data, index);
}
	void CreateEnchantment(TESForm* baseForm, BaseExtraList * extraData, float maxCharge, VMArray<EffectSetting*> effects, VMArray<float> magnitudes, VMArray<UInt32> areas, VMArray<UInt32> durations)
	{
		if(baseForm && (baseForm->formType == TESObjectWEAP::kTypeID || baseForm->formType == TESObjectARMO::kTypeID)) {
			EnchantmentItem * enchantment = NULL;
			if(effects.Length() > 0 && magnitudes.Length() == effects.Length() && areas.Length() == effects.Length() && durations.Length() == effects.Length()) {
				tArray<MagicItem::EffectItem> effectItems;
				effectItems.Allocate(effects.Length());

				UInt32 j = 0;
				for(UInt32 i = 0; i < effects.Length(); i++) {
					EffectSetting * magicEffect = NULL;
					effects.Get(&magicEffect, i);
					if(magicEffect) { // Only add effects that actually exist
						magnitudes.Get(&effectItems[j].magnitude, i);
						areas.Get(&effectItems[j].area, i);
						durations.Get(&effectItems[j].duration, i);
						effectItems[j].mgef = magicEffect;
						j++;
					}
				}
				effectItems.count = j; // Set count to existing count

				if(baseForm->formType == TESObjectWEAP::kTypeID)
					enchantment = CALL_MEMBER_FN(PersistentFormManager::GetSingleton(), CreateOffensiveEnchantment)(&effectItems);
				else
					enchantment = CALL_MEMBER_FN(PersistentFormManager::GetSingleton(), CreateDefensiveEnchantment)(&effectItems);

				FormHeap_Free(effectItems.arr.entries);
			}

			if(enchantment) {
				if(maxCharge > 0xFFFF) // Charge exceeds uint16 clip it
					maxCharge = 0xFFFF;

				ExtraEnchantment* extraEnchant = static_cast<ExtraEnchantment*>(extraData->GetByType(kExtraData_Enchantment));
				if(extraEnchant) {
					PersistentFormManager::GetSingleton()->DecRefEnchantment(extraEnchant->enchant);
					extraEnchant->enchant = enchantment;
					PersistentFormManager::GetSingleton()->IncRefEnchantment(extraEnchant->enchant);

					extraEnchant->maxCharge = (UInt16)maxCharge;
				} else {
					ExtraEnchantment* extraEnchant = ExtraEnchantment::Create();
					extraEnchant->enchant = enchantment;
					extraEnchant->maxCharge = (UInt16)maxCharge;
					extraData->Add(kExtraData_Enchantment, extraEnchant);
				}
			}
		}
	}
Ejemplo n.º 7
0
void Interpreter::send(VMSymbol* signature, VMClass* receiverClass) {
    VMInvokable* invokable = receiverClass->LookupInvokable(signature);

    if (invokable != nullptr) {
#ifdef LOG_RECEIVER_TYPES
        StdString name = receiverClass->GetName()->GetStdString();
        if (GetUniverse()->callStats.find(name) == GetUniverse()->callStats.end())
        GetUniverse()->callStats[name] = {0,0};
        GetUniverse()->callStats[name].noCalls++;
        if (invokable->IsPrimitive())
        GetUniverse()->callStats[name].noPrimitiveCalls++;
#endif
        // since an invokable is able to change/use the frame, we have to write
        // cached values before, and read cached values after calling
        GetFrame()->SetBytecodeIndex(bytecodeIndexGlobal);
        (*invokable)(GetFrame());
        bytecodeIndexGlobal = GetFrame()->GetBytecodeIndex();
    } else {
        GetFrame()->PrintStackTrace();
        //doesNotUnderstand
        long numberOfArgs = Signature::GetNumberOfArguments(signature);

        vm_oop_t receiver = GetFrame()->GetStackElement(numberOfArgs-1);

        VMArray* argumentsArray = GetUniverse()->NewArray(numberOfArgs - 1); // without receiver

        // the receiver should not go into the argumentsArray
        // so, numberOfArgs - 2
        for (long i = numberOfArgs - 2; i >= 0; --i) {
            vm_oop_t o = GetFrame()->Pop();
            argumentsArray->SetIndexableField(i, o);
        }
        vm_oop_t arguments[] = {signature, argumentsArray};
        
        GetFrame()->Pop(); // pop the receiver

        //check if current frame is big enough for this unplanned Send
        //doesNotUnderstand: needs 3 slots, one for this, one for method name, one for args
        long additionalStackSlots = 3 - GetFrame()->RemainingStackSize();
        if (additionalStackSlots > 0) {
            GetFrame()->SetBytecodeIndex(bytecodeIndexGlobal);
            //copy current frame into a bigger one and replace the current frame
            SetFrame(VMFrame::EmergencyFrameFrom(GetFrame(), additionalStackSlots));
        }

        AS_OBJ(receiver)->Send(doesNotUnderstand, arguments, 2);
    }
}
Ejemplo n.º 8
0
void _Method::InvokeOn_With_(Interpreter* interp, VMFrame* frame) {
    // REM: this is a clone with _Primitive::InvokeOn_With_
    VMArray* args  = static_cast<VMArray*>(frame->Pop());
    vm_oop_t rcvr  = static_cast<vm_oop_t>(frame->Pop());
    VMMethod* mthd = static_cast<VMMethod*>(frame->Pop());
    
    
    frame->Push(rcvr);
    
    size_t num_args = args->GetNumberOfIndexableFields();
    for (size_t i = 0; i < num_args; i++) {
        vm_oop_t arg = args->GetIndexableField(i);
        frame->Push(arg);
    }
    mthd->Invoke(interp, frame);
}
	bool GetRelativeNodePosition(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeNameA, BSFixedString nodeNameB, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* objectA = ResolveNode(obj, nodeNameA, firstPerson);
		NiAVObject	* objectB = ResolveNode(obj, nodeNameB, firstPerson);
		if(objectA && objectB && inArray.Length() == 3) {
			float x = objectB->m_worldTransform.pos.x - objectA->m_worldTransform.pos.x;
			float y = objectB->m_worldTransform.pos.y - objectA->m_worldTransform.pos.y;
			float z = objectB->m_worldTransform.pos.z - objectA->m_worldTransform.pos.z;
			inArray.Set(&x, 0);
			inArray.Set(&y, 1);
			inArray.Set(&z, 2);
			return true;
		}

		return false;
	}
	bool SetNodeLocalPosition(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);
		if(object && inArray.Length() == 3) {
			inArray.Get(&object->m_localTransform.pos.x, 0);
			inArray.Get(&object->m_localTransform.pos.y, 1);
			inArray.Get(&object->m_localTransform.pos.z, 2);

			BSTaskPool * taskPool = BSTaskPool::GetSingleton();
			if(taskPool)
				taskPool->UpdateWorldData(object);

			return true;
		}

		return false;
	}
	bool SetNodeLocalRotationMatrix(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);
		if(object && inArray.Length() == 9) {
			inArray.Get(&object->m_localTransform.rot.data[0][0], 0);
			inArray.Get(&object->m_localTransform.rot.data[0][1], 1);
			inArray.Get(&object->m_localTransform.rot.data[0][2], 2);

			inArray.Get(&object->m_localTransform.rot.data[1][0], 3);
			inArray.Get(&object->m_localTransform.rot.data[1][1], 4);
			inArray.Get(&object->m_localTransform.rot.data[1][2], 5);

			inArray.Get(&object->m_localTransform.rot.data[2][0], 6);
			inArray.Get(&object->m_localTransform.rot.data[2][1], 7);
			inArray.Get(&object->m_localTransform.rot.data[2][2], 8);

			BSTaskPool * taskPool = BSTaskPool::GetSingleton();
			if(taskPool)
				taskPool->UpdateWorldData(object);

			return true;
		}

		return false;
	}
Ejemplo n.º 12
0
void SetFloatByIndex(VMArray<float> &dest, UInt32 index, float iniVal, float min, float max)
{
	//Enforce limits
	if (iniVal < min)
		iniVal = min;
	else if (iniVal > max)
		iniVal = max;

	dest.Set(&iniVal, index);
}
	bool GetNodeWorldRotationEuler(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);
		if(object && inArray.Length() == 3) {
			float heading, attitude, bank;
			object->m_localTransform.rot.GetEulerAngles(&heading, &attitude, &bank);

			// Radians to degrees
			heading *= 180 / MATH_PI;
			attitude *= 180 / MATH_PI;
			bank *= 180 / MATH_PI;

			inArray.Set(&heading, 0);
			inArray.Set(&attitude, 1);
			inArray.Set(&bank, 2);
			return true;
		}

		return false;
	}
Ejemplo n.º 14
0
ExceptionCode inb(VMValue &result, const VMArray &args)
{
	if(args.length() != 1)
		return ExceptionCode::InvalidArgument;
	if(args[0].type() != VMType::UInt16)
		return ExceptionCode::InvalidArgument;

	result = VMValue::UInt8(
		::inb(args[0].value<VMUInt16>()));

	return ExceptionCode::None;
}
Ejemplo n.º 15
0
ExceptionCode outb(VMValue &, const VMArray &args)
{
	if(args.length() != 2)
		return ExceptionCode::InvalidArgument;
	if(args[0].type() != VMType::UInt16)
		return ExceptionCode::InvalidArgument;
	if(args[1].type() != VMType::UInt8)
		return ExceptionCode::InvalidArgument;

	::outb(args[0].value<VMUInt16>(), args[1].value<VMUInt8>());

	return ExceptionCode::None;
}
	void PushArgs(VMArray<T> args)
	{
		using namespace papyrusUI;

		UInt32 argCount = args.Length();

		UInt32 offset = invokeDelegate_->argCount;
		UInt32 newArgCount = offset + argCount;

		if (newArgCount > 128)
		{
			_WARNING("Tried to push more than 128 arguments into PapyrusUICallback.");
			return;
		}
		
		invokeDelegate_->argCount = newArgCount;
		for (UInt32 i=0; i<argCount; i++, offset++)
		{
			T arg;
			args.Get(&arg, i);
			SetGFxValue<T>(&invokeDelegate_->args[offset], arg);
		}
	}
	bool GetNodeWorldRotationMatrix(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, VMArray<float> inArray, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);
		if(object && inArray.Length() == 9) {
			inArray.Set(&object->m_worldTransform.rot.data[0][0], 0);
			inArray.Set(&object->m_worldTransform.rot.data[0][1], 1);
			inArray.Set(&object->m_worldTransform.rot.data[0][2], 2);

			inArray.Set(&object->m_worldTransform.rot.data[1][0], 3);
			inArray.Set(&object->m_worldTransform.rot.data[1][1], 4);
			inArray.Set(&object->m_worldTransform.rot.data[1][2], 5);

			inArray.Set(&object->m_worldTransform.rot.data[2][0], 6);
			inArray.Set(&object->m_worldTransform.rot.data[2][1], 7);
			inArray.Set(&object->m_worldTransform.rot.data[2][2], 8);
			return true;
		}

		return false;
	}
Ejemplo n.º 18
0
bool EAr_MGEFInfoLib::SetMainArrays(
	VMArray<TESEffectShader*>	eShaders,
	VMArray<BGSArtObject*>		eArt,
	VMArray<TESEffectShader*>	hShaders,
	VMArray<BGSArtObject*>		hArt,
	VMArray<BGSProjectile*>		projectiles,
	VMArray<BGSImpactDataSet*>	impactData,
	VMArray<UInt32>				persistFlags,
	VMArray<float>				tWeights,
	VMArray<float>				tCurves,
	VMArray<float>				tDurations)
{
	if ((eShaders.Length() < 126) ||
		(eArt.Length() < 126) ||
		(hShaders.Length() < 126) ||
		(hArt.Length() < 126) ||
		(projectiles.Length() < 126) ||
		(impactData.Length() < 126) ||
		(persistFlags.Length() < 126) ||
		(tWeights.Length() < 126) ||
		(tCurves.Length() < 126) ||
		(tDurations.Length() < 126))
		return false;

	for (UInt32 i = 0; i < 126; i++)
	{
		TESEffectShader*  pESh = NULL;
		BGSArtObject*     pEAr = NULL;
		TESEffectShader*  pHSh = NULL;
		BGSArtObject*     pHAr = NULL;
		BGSProjectile*    pPro = NULL;
		BGSImpactDataSet* pIDS = NULL;
		UInt32            flag;
		float             tWei;
		float             tCur;
		float             tDur;

		eShaders.Get		(&pESh, i);
		eArt.Get			(&pEAr, i);
		hShaders.Get		(&pHSh, i);
		hArt.Get			(&pHAr, i);
		projectiles.Get		(&pPro, i);
		impactData.Get		(&pIDS, i);
		persistFlags.Get	(&flag, i);
		tWeights.Get		(&tWei, i);
		tCurves.Get			(&tCur, i);
		tDurations.Get		(&tDur, i);

		_eShaders.push_back		(pESh);
		_eArt.push_back			(pEAr);
		_hShaders.push_back		(pHSh);
		_hArt.push_back			(pHAr);
		_projectiles.push_back	(pPro);
		_impactData.push_back	(pIDS);
		_persistFlags.push_back	(flag);
		_tWeights.push_back		(tWei);
		_tCurves.push_back		(tCur);
		_tDurations.push_back	(tDur);
	}

	battleaxeKeyword = papyrusKeyword::GetKeyword(NULL, "WeapTypeBattleaxe");
	READY = true;
	_MESSAGE("Internal effect library loaded successfully.");
	return true;
}
Ejemplo n.º 19
0
	// 一定距離内に居るアクターをすべて返す
	VMArray<Actor*> FindCloseActor(float distance, UInt32 sortOrder)
	{
		enum Order {
			kSortOrder_distance		= 0,		// 距離が近い順
			kSortOrder_crosshair	= 1,		// クロスヘアに近い順
			kSortOrder_zaxis_clock	= 2,		// Z軸時計回り
			kSortOrder_zaxis_rclock	= 3,		// Z軸逆時計回り
			kSortOrder_invalid      = 4
		};

		double fovThreshold = (double)PlayerCamera::GetSingleton()->worldFOV / 180.0 * M_PI /2;

		VMArray<Actor*> result;
		result.arr = NULL;

		tArray<UInt32>* actorHandles = &(*s_cellInfo)->actorHandles;
		if (actorHandles->count == 0)
			return result;

		std::vector<std::pair<double, Actor*>> vec;
		vec.reserve(actorHandles->count);

		PlayerCharacter* player = *g_thePlayer;
		NiPoint3 camPos;
		GetCameraPos(&camPos);

		UInt32 handle;
		size_t i = 0;
		while (actorHandles->GetNthItem(i++, handle))
		{
			TESObjectREFR* ref = NULL;
			if (handle != *g_invalidRefHandle)
				LookupREFRByHandle(&handle, &ref);

			if (ref && ref->formType == kFormType_Character)
			{
				Actor* actor = (Actor*)ref;
				NiPoint3 pos;
				GetTargetPos(actor, &pos);
				double dx = pos.x - camPos.x;
				double dy = pos.y - camPos.y;
				double dz = pos.z - camPos.z;
				double dd = sqrt(dx*dx + dy*dy + dz*dz);

				if (distance <= 0 || dd <= distance)
				{
					double point;
					NiPoint3 cameraAngle;
					GetCameraAngle(&cameraAngle);
					double angleZ = NormalRelativeAngle(atan2(dx, dy) - cameraAngle.z);
					double angleX = NormalRelativeAngle(atan2(-dz, sqrt(dx*dx + dy*dy)) - cameraAngle.x);
					
					if (abs(angleZ) < fovThreshold)
					{
						switch (sortOrder)
						{
						case kSortOrder_distance:
							point = dd;
							break;
						case kSortOrder_crosshair:
							point = sqrt(angleZ*angleZ + angleX*angleX);
							break;
						case kSortOrder_zaxis_clock:
							point = NormalAbsoluteAngle(atan2(dx, dy) - cameraAngle.z);
							break;
						case kSortOrder_zaxis_rclock:
							point = 2*M_PI - NormalAbsoluteAngle(atan2(dx, dy) - cameraAngle.z);
							break;
						default:
							point = 0;
							break;
						}

						if (point >= 0)
						{
							vec.push_back(std::make_pair(point, actor));
						}
					}
				}
			}
		}

		if (vec.size() == 0)
			return result;

		if (sortOrder < kSortOrder_invalid)
			std::sort(vec.begin(), vec.end());

		// Papyrusに返す配列を確保
		if (result.Allocate(vec.size()))
		{
			for (i = 0; i < vec.size(); i++)
			{
				result.Set(&vec[i].second, i);
			}
		}

		return result;
	}
Ejemplo n.º 20
0
void CloneObjectsTest::testCloneArray() {
    VMArray* orig = GetUniverse()->NewArray(3);
    orig->SetIndexableField(0, GetUniverse()->NewString("foobar42"));
    orig->SetIndexableField(1, GetUniverse()->NewString("foobar43"));
    orig->SetIndexableField(2, GetUniverse()->NewString("foobar44"));
    VMArray* clone = orig->Clone();

    CPPUNIT_ASSERT((intptr_t)orig != (intptr_t)clone);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("class differs!!", orig->clazz, clone->clazz);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("objectSize differs!!", orig->objectSize, clone->objectSize);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("numberOfFields differs!!", orig->numberOfFields, clone->numberOfFields);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("numberOfFields differs!!", orig->GetNumberOfIndexableFields(), clone->GetNumberOfIndexableFields());

    CPPUNIT_ASSERT_EQUAL_MESSAGE("field 0 differs", orig->GetIndexableField(0),
            clone->GetIndexableField(0));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("field 1 differs", orig->GetIndexableField(1),
            clone->GetIndexableField(1));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("field 2 differs", orig->GetIndexableField(2),
            clone->GetIndexableField(2));
}