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; }
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; }
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; }
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); }
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; }
// 一定距離内に居るアクターをすべて返す 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; }