//==================================================== // すべてのMODが読み込まれた後に呼ばれる //==================================================== virtual void OnModLoaded() { // TopicInfoイベントを受け取るラムダ関数 auto onTopicInfo = [](TESTopicInfoEvent* e) -> EventResult { if (!e->speaker) return kEvent_Continue; // 会話中に頭をでかくする static BSFixedString nodeName = "NPC Head [Head]"; NiAVObject* node = (NiAVObject*)e->speaker->GetNiNode(); if(node) { node = node->GetObjectByName(&nodeName.data); if (node) { // 会話開始で倍率を2.0に、会話終了で1.0に戻す node->m_localTransform.scale = (e->flag) ? 1.0 : 2.0; } } return kEvent_Continue; }; // イベントの送信元 (ソース) をイベントの受信側 (シンク) と接続する // 受信側には、関数・ラムダ関数・関数オブジェクトを指定可能 g_topicInfoEventSource += onTopicInfo; // ラムダ g_hitEventSource += OnHit; // 関数 static SwitchRaceCompleteEventFunctor switchRaceFunctor; g_switchRaceCompleteEventSource += switchRaceFunctor; // 関数オブジェクト // -= で切断 g_switchRaceCompleteEventSource -= switchRaceFunctor; g_topicInfoEventSource -= onTopicInfo; }
void SetNodeScale(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, float value, bool firstPerson) { NiAVObject * object = ResolveNode(obj, nodeName, firstPerson); if(object) { object->m_localTransform.scale = value; NiAVObject::ControllerUpdateContext ctx; object->UpdateWorldData(&ctx); } }
NiTriBasedGeom * GetTriBasedGeomByHeadPart(BSFaceGenNiNode * faceNode, BGSHeadPart * headPart) { for (UInt32 p = 0; p < faceNode->m_children.m_size; p++) { NiAVObject * object = faceNode->m_children.m_data[p]; if (object && BSFixedString(object->m_name) == headPart->partName) { NiTriBasedGeom * geometry = object->GetAsNiTriBasedGeom(); if (geometry) { return geometry; } } } return NULL; }
NiAVObject * ResolveNode(TESObjectREFR * obj, BSFixedString nodeName, bool firstPerson) { if(!obj) return NULL; NiAVObject * result = obj->GetNiNode(); // special-case for the player, switch between first/third-person PlayerCharacter * player = DYNAMIC_CAST(obj, TESObjectREFR, PlayerCharacter); if(player && player->loadedState) result = firstPerson ? player->firstPersonSkeleton : player->loadedState->node; // name lookup if(nodeName.data[0] && result) result = result->GetObjectByName(&nodeName.data); return result; }
void SetNodeTextureSet(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, BGSTextureSet * textureSet, bool firstPerson) { if(!textureSet) return; NiAVObject * object = ResolveNode(obj, nodeName, firstPerson); if(object) { NiGeometry * geometry = object->GetAsNiGeometry(); if(geometry) { BSTaskPool * taskPool = BSTaskPool::GetSingleton(); if(taskPool) { CALL_MEMBER_FN(taskPool, SetNiGeometryTexture)(geometry, textureSet); } } } }
NiTriBasedGeom * GetHeadTriBasedGeom(Actor * actor, UInt32 partType) { BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode(); TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); if(faceNode && actorBase) { BGSHeadPart * facePart = actorBase->GetCurrentHeadPartByType(partType); if(facePart) { NiAVObject * headNode = faceNode->GetObjectByName(&facePart->partName.data); if(headNode) { NiTriBasedGeom * geometry = headNode->GetAsNiTriBasedGeom(); if(geometry) return geometry; } } } return NULL; }
void SKSETaskExportHead::Run() { if (!m_formId) return; TESForm * form = LookupFormByID(m_formId); Actor * actor = DYNAMIC_CAST(form, TESForm, Actor); if (!actor) return; BSFaceGenNiNode * faceNode = actor->GetFaceGenNiNode(); TESNPC * actorBase = DYNAMIC_CAST(actor->baseForm, TESForm, TESNPC); if (!actorBase || !faceNode) return; BSFaceGenAnimationData * animationData = actor->GetFaceGenAnimationData(); if (animationData) { FaceGen::GetSingleton()->isReset = 0; for (UInt32 t = BSFaceGenAnimationData::kKeyframeType_Expression; t <= BSFaceGenAnimationData::kKeyframeType_Phoneme; t++) { BSFaceGenKeyframeMultiple * keyframe = &animationData->keyFrames[t]; for (UInt32 i = 0; i < keyframe->count; i++) keyframe->values[i] = 0.0; keyframe->isUpdated = 0; } UpdateModelFace(faceNode); } IFileStream::MakeAllDirs(m_nifPath.data); BSFadeNode * rootNode = BSFadeNode::Create(); rootNode->IncRef(); NiNode * skinnedNode = NiNode::Create(0); skinnedNode->m_name = BSFixedString("BSFaceGenNiNodeSkinned").data; std::map<NiAVObject*, NiAVObject*> boneMap; for (UInt32 i = 0; i < faceNode->m_children.m_size; i++) { NiAVObject * object = faceNode->m_children.m_data[i]; if (!object) continue; if (NiGeometry * geometry = object->GetAsNiGeometry()) { NiGeometryData * geometryData = niptr_cast<NiGeometryData>(geometry->m_spModelData); NiGeometryData * newGeometryData = NULL; if (geometryData) CALL_MEMBER_FN(geometryData, DeepCopy)((NiObject **)&newGeometryData); NiProperty * trishapeEffect = niptr_cast<NiProperty>(geometry->m_spEffectState); NiProperty * newTrishapeEffect = NULL; if (trishapeEffect) CALL_MEMBER_FN(trishapeEffect, DeepCopy)((NiObject **)&newTrishapeEffect); NiProperty * trishapeProperty = niptr_cast<NiProperty>(geometry->m_spPropertyState); NiProperty * newTrishapeProperty = NULL; if (trishapeProperty) CALL_MEMBER_FN(trishapeProperty, DeepCopy)((NiObject **)&newTrishapeProperty); NiSkinInstance * skinInstance = niptr_cast<NiSkinInstance>(geometry->m_spSkinInstance); NiSkinInstance * newSkinInstance = NULL; if (skinInstance) { newSkinInstance = skinInstance->Clone(false); newSkinInstance->m_pkRootParent = skinnedNode; UInt32 numBones = 0; NiSkinData * skinData = niptr_cast<NiSkinData>(skinInstance->m_spSkinData); NiSkinData * newSkinData = NULL; if (skinData) { numBones = skinData->m_uiBones; CALL_MEMBER_FN(skinData, DeepCopy)((NiObject **)&newSkinData); } NiSkinPartition * skinPartition = niptr_cast<NiSkinPartition>(skinInstance->m_spSkinPartition); NiSkinPartition * newSkinPartition = NULL; if (skinPartition) CALL_MEMBER_FN(skinPartition, DeepCopy)((NiObject **)&newSkinPartition); newSkinInstance->m_spSkinData = newSkinData; newSkinData->DecRef(); newSkinInstance->m_spSkinPartition = newSkinPartition; newSkinPartition->DecRef(); // Remap the bones to new NiNode instances if (numBones > 0) { newSkinInstance->m_ppkBones = (NiAVObject**)NiAllocate(numBones * sizeof(NiAVObject*)); for (UInt32 i = 0; i < numBones; i++) { NiAVObject * bone = skinInstance->m_ppkBones[i]; if (bone) { auto it = boneMap.find(bone); if (it == boneMap.end()) { NiNode * newBone = NiNode::Create(); newBone->m_name = bone->m_name; newBone->m_flags = bone->m_flags; boneMap.insert(std::make_pair(bone, newBone)); newSkinInstance->m_ppkBones[i] = newBone; } else newSkinInstance->m_ppkBones[i] = it->second; } else { newSkinInstance->m_ppkBones[i] = nullptr; } } } } NiGeometry * newGeometry = NULL; if (NiTriShape * trishape = geometry->GetAsNiTriShape()) { NiTriShape * newTrishape = NiTriShape::Create(static_cast<NiTriShapeData*>(newGeometryData)); newGeometryData->DecRef(); newTrishape->m_localTransform = geometry->m_localTransform; newTrishape->m_name = geometry->m_name; memcpy(&newTrishape->unk88, &geometry->unk88, 0x1F); newTrishape->m_spEffectState = newTrishapeEffect; newTrishape->m_spPropertyState = newTrishapeProperty; newTrishape->m_spSkinInstance = newSkinInstance; newGeometry = newTrishape; } else if (NiTriStrips * tristrips = geometry->GetAsNiTriStrips()) { NiTriStrips * newTristrips = NiTriStrips::Create(static_cast<NiTriStripsData*>(newGeometryData)); newGeometryData->DecRef(); newTristrips->m_localTransform = geometry->m_localTransform; newTristrips->m_name = geometry->m_name; memcpy(&newTristrips->unk88, &geometry->unk88, 0x1F); newTristrips->m_spEffectState = newTrishapeEffect; newTristrips->m_spPropertyState = newTrishapeProperty; newTristrips->m_spSkinInstance = newSkinInstance; newGeometry = newTristrips; } if (newGeometry) { auto textureData = GetTextureSetForPartByName(actorBase, newGeometry->m_name); if (textureData.first && textureData.second) { BSShaderProperty * shaderProperty = niptr_cast<BSShaderProperty>(newGeometry->m_spEffectState); if (shaderProperty) { if (shaderProperty->GetRTTI() == NiRTTI_BSLightingShaderProperty) { BSLightingShaderProperty * lightingShader = static_cast<BSLightingShaderProperty *>(shaderProperty); BSLightingShaderMaterial * material = static_cast<BSLightingShaderMaterial *>(shaderProperty->material); if (material && material->textureSet) { for (UInt32 i = 0; i < BGSTextureSet::kNumTextures; i++) material->textureSet->SetTexturePath(i, textureData.first->textureSet.GetTexturePath(i)); if (textureData.second->type == BGSHeadPart::kTypeFace) material->textureSet->SetTexturePath(6, m_ddsPath.data); } } } // Save the previous tint mask BSShaderProperty * originalShaderProperty = niptr_cast<BSShaderProperty>(geometry->m_spEffectState); if (originalShaderProperty) { if (originalShaderProperty->GetRTTI() == NiRTTI_BSLightingShaderProperty) { BSLightingShaderProperty * lightingShader = static_cast<BSLightingShaderProperty *>(originalShaderProperty); BSLightingShaderMaterial * material = static_cast<BSLightingShaderMaterial *>(originalShaderProperty->material); if (material) { if (material->GetShaderType() == BSShaderMaterial::kShaderType_FaceGen) { BSMaskedShaderMaterial * maskedMaterial = static_cast<BSMaskedShaderMaterial *>(material); SaveRenderedDDS(niptr_cast<NiRenderedTexture>(maskedMaterial->renderedTexture), m_ddsPath.data); } } } } } skinnedNode->AttachChild(newGeometry, true); } } } for (auto & bones : boneMap) rootNode->AttachChild(bones.second, true); rootNode->AttachChild(skinnedNode, true); UInt8 niStreamMemory[0x5B4]; memset(niStreamMemory, 0, 0x5B4); NiStream * niStream = (NiStream *)niStreamMemory; CALL_MEMBER_FN(niStream, ctor)(); CALL_MEMBER_FN(niStream, AddObject)(rootNode); niStream->SavePath(m_nifPath.data); CALL_MEMBER_FN(niStream, dtor)(); rootNode->DecRef(); if (animationData) { animationData->overrideFlag = 0; CALL_MEMBER_FN(animationData, Reset)(1.0, 1, 1, 0, 0); FaceGen::GetSingleton()->isReset = 1; UpdateModelFace(faceNode); } }
//--------------------------------------------------------------------------- void Player::Update(float fTime) { float fDeltaTime = NiAbs(fTime - m_fLastUpdateTime); if (fDeltaTime > 1.0f) { m_fLastUpdateTime = fTime; return; } if (m_pkTarget) // if there is an object, move it { NiAVObject* pkObject = (NiAVObject*)m_pkTarget; NIASSERT(NiIsKindOf(NiAVObject, pkObject)); // Check the Keyboard exists NiInputKeyboard* pkKeyboard = NULL; if (m_pkGameApp->GetInputSystem()) { pkKeyboard = m_pkGameApp->GetInputSystem()->GetKeyboard(); } int iHorz = 0; int iVert = 0; if (pkKeyboard != NULL) { if (pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_LEFT) || pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_A)) iHorz = -127; if (pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_RIGHT)|| pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_D)) iHorz = 127; if (pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_DOWN)|| pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_S)) iVert = 127; if (pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_UP)|| pkKeyboard->KeyIsDown(NiInputKeyboard::KEY_W)) iVert = -127; } if (iHorz) { float fZ = iHorz * (1.0f / 127.0f); NiPoint3 kTrans(.1*fZ,0,0); kTrans = kTrans + pkObject->GetTranslate(); if(kTrans.x > m_xBoundNeg && kTrans.x <m_xBoundPos) pkObject->SetTranslate(kTrans); } if (iVert) { float fZ = iVert * (1.0f / 127.0f); NiPoint3 kTrans(0,0,.1*fZ); kTrans = kTrans + pkObject->GetTranslate(); if(kTrans.z > m_zBoundNeg && kTrans.z <m_zBoundPos) pkObject->SetTranslate(kTrans); } } m_fLastUpdateTime = fTime; }