void CWorld::ScanCell() { auto player = DYNAMIC_CAST( LookupFormByID(0x14), TESForm, TESObjectREFR ); if(!player) goto FAILED; auto cell = player->parentCell; if(!cell) goto FAILED; m_pWorld->markForWrite(); if(m_pCell != cell) { LogInfo("Cell changed..."); m_characters.clear(); m_pCell = cell; for(auto& i : m_systems) { i.second->RemoveFromWorld(); i.second->AddToWorld(m_pWorld); } } else { for(auto i=m_characters.begin(); i!=m_characters.end();) { auto form = i->first; auto object = (TESObjectREFR*)LookupFormByID(form); if(object->parentCell != cell) { LogInfo("%08x no longer in cell, release it", form); m_characters.erase(i++); } else if(!i->second->CreateIfValid()) { LogInfo("%08x now invalid, release it", form); m_characters.erase(i++); } else (i++)->second->AddToWorld(m_pWorld); } for(int i=0; i<cell->objectList.count; ++i) { auto object = cell->objectList.arr.entries[i]; if(DYNAMIC_CAST(object, TESObjectREFR, Actor)) AddCharacter(object->formID); } } m_pWorld->unmarkForWrite(); return; FAILED: m_pWorld->markForWrite(); m_characters.clear(); m_pCell = 0; m_pWorld->unmarkForWrite(); }
TESForm* ScriptToken::GetTESForm() const { // ###TODO: handle Ref (RefVariable)? Read() turns RefVariable into Form so that type is compile-time only #if OBLIVION if (type == kTokenType_Form) return LookupFormByID(value.formID); else if (type == kTokenType_RefVar && value.var) return LookupFormByID(*((UInt64*)(&value.var->data))); #endif if (type == kTokenType_Ref && value.refVar) return value.refVar->form; else return NULL; }
EventResult TESEquipEventHandler::ReceiveEvent(TESEquipEvent* evn, EventDispatcher<TESEquipEvent>* dispatcher) { if (evn->actor->baseForm != (*g_thePlayer)->baseForm) return kEvent_Continue; TESForm* equippedForm = LookupFormByID(evn->equippedFormID); EnchantmentItem* enchantment = DYNAMIC_CAST(equippedForm, TESForm, EnchantmentItem); if (!enchantment) //check active effects to see if an armor enchantment was equipped { if (evn->isEquipping) g_activeEnchantEffects.ProcessEquipped(); //find new equipped enchanted item and send event to papyrus else //unequipping g_activeEnchantEffects.ProcessUnequipped(); //find removed enchanted item and send event to papyrus } else if (enchantment->data.unk14 != 0x0C) //weapon enchantment equipped (but ignore staff enchantments for now) { if (evn->isEquipping) playerEquippedWeaponEnchantments.Push(evn->equippedFormID); else playerEquippedWeaponEnchantments.Pop(evn->equippedFormID); g_userExclusions.UpdateWeaponExclusions(); g_hitEventExDispatcher->RemoveEventSink(&g_hitEventExHandler); if (playerEquippedWeaponEnchantments.HasData()) g_hitEventExDispatcher->AddEventSink(&g_hitEventExHandler); } return kEvent_Continue; }
void EditorHookWindow::OnButtonHit(void) { char text[256]; GetWindowText(m_editText, text, sizeof(text)); char comment[256]; GetWindowText(m_editText2, comment, sizeof(comment)); UInt32 id; if(sscanf_s(text, "%x", &id) == 1) { void * ptr = LookupFormByID(id); sprintf_s(text, sizeof(text), "%08X = %08X (%s)", id, (UInt32)ptr, GetObjectClassName(ptr)); _MESSAGE("%s", text); MessageBox(m_window, text, "receive bacon", MB_OK); static int idx = 0; char fileName[256]; if(comment[0]) sprintf_s(fileName, sizeof(fileName), "mem%08X_%08X_%08X_%s", idx, id, (UInt32)ptr, comment); else sprintf_s(fileName, sizeof(fileName), "mem%08X_%08X_%08X", idx, id, (UInt32)ptr); idx++; IFileStream dst; if(dst.Create(fileName)) dst.WriteBuf(ptr, 0x200); } else { MessageBox(m_window, "couldn't read text box", "receive bacon", MB_OK); } };
//now we process each cell... BOOST_FOREACH(TESObjectCELL *Cell,cells) { TESObjectCELL::ObjectListEntry * ListIterator = &Cell->objectList; while(ListIterator) // Iterate the entities { if(IsRefIDIgnore(ListIterator->refr->refID)) // Do not synchronize objects used by OblivionOnline { ent = (ClientEntity *) gClient->GetEntities()->GetOrCreateEntity(ListIterator->refr->refID); if(GetIsMasterClient()) SendActorPosition(ListIterator->refr,ent); if(ListIterator->Info()->IsActor()) { Actor * actor = (Actor *)LookupFormByID(ListIterator->refr->refID); { if(GetIsMasterClient()) { SendActorValues(actor,ent); SendActorEquip(actor,ent); SendActorAnimation(actor,ent); } SendActorValueMod(actor,ent); } } } ListIterator = ListIterator->next; } }
__declspec(dllexport) bool GetScriptDataForForm(bool* OperationResult, UInt32 FormID, Script** ResultScript, ScriptEventList** ResultEventList) { bool Result = false; if (FormID) { TESForm* Form = LookupFormByID(FormID); if (Form) { TESQuest* Quest = OBLIVION_CAST(Form, TESForm, TESQuest); TESObjectREFR* Ref = OBLIVION_CAST(Form, TESForm, TESObjectREFR); if (Quest) { *ResultScript = Quest->scriptable.script; *ResultEventList = Quest->scriptEventList; Result = true; } else if (Ref) { BSExtraData* xData = Ref->baseExtraList.GetByType(kExtraData_Script); if (xData) { ExtraScript* xScript = OBLIVION_CAST(xData, BSExtraData, ExtraScript); *ResultScript = xScript->script; *ResultEventList = xScript->eventList; Result = true; } } } } *OperationResult = Result; return Result; }
TESObjectREFR * GetRefrFromEntity( ClientEntity * ent ) { if(ent->RefID() == gClient->GetLocalPlayer()) return (TESObjectREFR * )(*g_thePlayer); else return (TESObjectREFR * )LookupFormByID(ent->RefID()); }
WorldSpace::WorldSpace(Location location) { if (location.has_world_space()) { auto world_space_form = LookupFormByID(location.world_space_id()); if (world_space_form->GetFormType() == kFormType_WorldSpace) { world_space_ = static_cast<TESWorldSpace*>(world_space_form); } } }
TESForm* TESHitEvent::GetProjectileForm() { if (projectileFormID) return LookupFormByID(projectileFormID); TESObjectREFR* ref = GetProjectileRef(); return (ref) ? ref->baseForm : NULL; }
Cell::Cell(Location location) { if (location.has_cell()) { auto cell_form = LookupFormByID(location.cell_id()); if(cell_form->GetFormType() == kFormType_Cell) { cell_ = static_cast<TESObjectCELL*>(cell_form); } } }
void ActionHandler::actionSetActiveQuest(UInt32 refID) { TESQuest *quest = DYNAMIC_CAST(LookupFormByID(refID), TESForm, TESQuest); if (quest == NULL) { return; } sprintf_s(commandBuf, "ForceActiveQuest %x", quest->refID); Script::RunScriptLine(commandBuf); }
void ActionHandler::actionTuneRadio(UInt32 refID) { sprintf_s(commandBuf, "pipboyRadio off"); Script::RunScriptLine(commandBuf); if (refID != 0) { TESObjectREFR *radio = DYNAMIC_CAST(LookupFormByID(refID), TESForm, TESObjectREFR); if (radio == NULL) return; sprintf_s(commandBuf, "pipboyRadio on %x", radio->refID); Script::RunScriptLine(commandBuf); } }
TESForm * AddItemHealthPercentOwner(TESObjectREFR* thisObj, UInt32 refID, SInt32 NumItems, float Health, TESForm* pOwner, UInt32 Rank) { if (!thisObj) return NULL; TESForm * pForm = LookupFormByID(refID); if (!pForm) return NULL; TESHealthForm* pHealth = DYNAMIC_CAST(pForm, TESForm, TESHealthForm); if (!pHealth && (Health != -1.0)) { _MESSAGE("\t\tInventoryInfo\t\tAddItemHealthPercentOwner:\tInvalid refID:%#10X, no health attribute", thisObj->refID); return NULL; } TESScriptableForm* pScript = DYNAMIC_CAST(pForm, TESForm, TESScriptableForm); if (pScript && !pScript->script) pScript = NULL; // Only existing scripts matter ExtraHealth* pXHealth = NULL; ExtraOwnership* pXOwner = NULL; ExtraRank* pXRank = NULL; ExtraCount* pXCount = NULL; ExtraDataList* pExtraDataList = NULL; ExtraScript * pXScript = NULL; if (!(1.0 == Health) || pOwner || Rank || pScript) { pExtraDataList = ExtraDataList::Create(); if (!(1.0 == Health)) { pXHealth = ExtraHealth::Create(); if (!pExtraDataList->Add(pXHealth)) FormHeap_Free(pXHealth); else pXHealth->health = pHealth->GetHealth() * Health; } if (pOwner) { pXOwner = ExtraOwnership::Create(); if (!pExtraDataList->Add(pXOwner)) FormHeap_Free(pXOwner); else pXOwner->owner = pOwner; } if (Rank) { pXRank = ExtraRank::Create(); if (!pExtraDataList->Add(pXRank)) FormHeap_Free(pXRank); else pXRank->rank = Rank; } if (pScript) { pXScript = ExtraScript::Create(pForm, true); if (!pExtraDataList->Add(pXScript)) FormHeap_Free(pXScript); } } thisObj->AddItem(pForm, pExtraDataList, NumItems); return pForm; }
void Script::RefVariable::Resolve(ScriptEventList * eventList) { if(varIdx && eventList) { ScriptEventList::Var * var = eventList->GetVariable(varIdx); if(var) { UInt32 refID = *((UInt32 *)&var->data); form = LookupFormByID(refID); } } }
TESForm* GetJCStringForm(std::string formString) { TESForm * result = nullptr; std::vector<std::string> stringData; std::string formData("__formData"); std::istringstream str(formString); std::string token; while (std::getline(str, token, '|')) { //std::cout << token << std::endl; stringData.push_back(token); } if (stringData[0] != formData) return result; if (!stringData[2].length()) return result; UInt8 modIndex = 0xff; if (stringData[1].length()) { DataHandler* pDataHandler = DataHandler::GetSingleton(); modIndex = pDataHandler->GetModIndex(stringData[1].c_str()); } if (modIndex == 0xff) return result; std::string formIdString(stringData[2].c_str()); UInt32 formId; try { formId = std::stoul(std::string(formIdString.begin(), formIdString.end()), nullptr, 0); } catch (const std::invalid_argument&) { return result; } catch (const std::out_of_range&) { return result; } formId |= modIndex << 24; result = LookupFormByID(formId); return result; }
void UpdateItem3D(const FxDelegateArgs & params) { if(params.menu) { UInt32 formId = (UInt32)params.args->GetNumber(); if(formId) { TESForm * form = LookupFormByID(formId); if(form) { CALL_MEMBER_FN(Inventory3DManager::GetSingleton(), UpdateMagic3D)(form, 0); } } else { CALL_MEMBER_FN(Inventory3DManager::GetSingleton(), Clear3D)(); } } }
bool AddOneItemCommand(Actor *thisObj,UINT32 FormID) { TESObjectREFR *refr = (TESObjectREFR * )LookupFormByID(FormID); if(!refr || !thisObj) return false; //TODO: Is Inventory Item? //TODO: rework this double result; TESObjectREFR * arg1[2] = { refr, (TESObjectREFR *) 1 }; // Parameter list, parameters, thisOBj, arg3= param count, ScriptEventList ( what to put in there?) , Result ptr, and offset ( is 0 ok ? ) CallCmdExecuteGeneric(Cmd_AddItem_Execute,kParams_CmdAddItem,&arg1, 1,thisObj,&result); // NULL denotes incomplete params }
UInt32 ProcessLoadEntry(SKSESerializationInterface* intfc) { EnchantmentInfoEntry thisEntry; UInt32 sizeRead = intfc->ReadRecordData(&thisEntry, sizeof(EnchantmentInfoEntry)); if (sizeRead == sizeof(EnchantmentInfoEntry)) { EnchantmentItem* thisEnchant = DYNAMIC_CAST(LookupFormByID(thisEntry.formID), TESForm, EnchantmentItem); if (!thisEnchant) return 0; thisEnchant->data.unk00.unk04 |= thisEntry.flags; //Set to manualCalc and correct cost thisEnchant->data.unk00.unk00 = thisEntry.enchantmentCost; //This ended up causing a crash on subsequent loads, most likely because the game rebuilds the condition table. //I could probably work around it by detaching all conditions during Revert, and then letting the Load process //re-attach them. But I'm just going to disable them for now to be safe, it's relatively unimportant. // if (thisEntry.cData.hasConditions) //Update enchantment conditions // { // EnchantmentItem* parentEnchant = DYNAMIC_CAST(LookupFormByID(thisEntry.cData.parentFormID), TESForm, EnchantmentItem); // if (parentEnchant) // { // for (UInt32 i = 0; (i < parentEnchant->effectItemList.count) && (i < thisEnchant->effectItemList.count); ++i) // { // MagicItem::EffectItem* parentEffect = NULL; // parentEnchant->effectItemList.GetNthItem(i, parentEffect); // if (parentEffect && parentEffect->condition) // { // MagicItem::EffectItem* childEffect = NULL; // thisEnchant->effectItemList.GetNthItem(i, childEffect); // childEffect->condition = parentEffect->condition; // } // } // } // } enchantTracker[thisEnchant] = thisEntry; //Add to main tracker return 1; } else { _MESSAGE("Error Reading From Cosave: INVALID CHUNK SIZE (%u Expected %u)" " -- Data Entry Will Be Skipped.", sizeRead, sizeof(EnchantmentInfoEntry)); return 0; } }
bool EquipItemCommand(Actor *thisObj,UINT32 FormID) { TESObjectREFR *refr = (TESObjectREFR * ) LookupFormByID(FormID); if(!refr || !thisObj) return false; //TODO: Is Inventory Item? //TODO: rework this double result; // Call AddItem: 1 Pointer to the form TESForm * arg1 [2]= { refr, (TESObjectREFR *)0 }; // Set parameter 1 ( Object) // Parameter list, parameters, thisOBj, arg3= param count, ScriptEventList ( what to put in there?) , Result ptr, and offset ( is 0 ok ? ) CallCmdExecuteGeneric(Cmd_EquipItem_Execute,kParams_CmdEquipItem,&arg1,2,thisObj,&result); return true; }
bool InjectEquip( ClientEntity *ent,BYTE slot,UINT32 formid ) { return true; if(!ent) return false; TESObjectREFR * refr = GetRefrFromEntity(ent); if(!refr || !refr->IsActor()) return false; else { Actor * act= (Actor*)refr; if(formid && LookupFormByID(formid)) { feGetObject getObject; double itemResult; UInt32* itemRef = (UInt32 *)&itemResult; if (FindEquipped(act, slot, &getObject, &itemResult) ) // If we find nothing, there already is no equip { ent->AddUnequipItem(*itemRef); ent->AddRemoveItem(*itemRef); //UnEquipItemCommand(act,*itemRef); //RemoveOneItemQueue.push(pair<Actor *,UINT32>(act,*itemRef)); } //AddOneItemCommand(act,formid); ent->AddAddItem(formid); //ent->AddEquipItem(formid); } else { //Unequip the item in that slot. feGetObject getObject; double itemResult; UInt32* itemRef = (UInt32 *)&itemResult; if (FindEquipped(act, slot, &getObject, &itemResult) ) // If we find nothing, there already is no equip { ent->AddUnequipItem(*itemRef); //ent->AddRemoveItem(*itemRef); //UnEquipItemCommand(act,*itemRef); //RemoveOneItemQueue.push(pair<Actor *,UINT32>(act,*itemRef)); } } SafeAddUpdateQueue(ent); } return true; }
bool GameClient::RunFrame() { ClientEntity * ent; Actor * actor = NULL; BYTE Status; if(!gClient->GetIsConnected()) return false; //Check if Menu Mode: InterfaceManager* intfc = InterfaceManager::GetSingleton(); if(!intfc->IsGameMode()) g_bRenderGUI = false; else g_bRenderGUI = true; if(!gClient->GetIsInitialized() ) { gClient->GetConnection().Process();//Poll connection until a player id is received return true; } // A heavy command xD // 1 - send local player data up . // 2 - send health magicka and fatigue + equip up. // if MC : // 2 - send up position , stat equip , etc of NPCs //(*g_thePlayer) is ignored ent = (ClientEntity *)gClient->GetEntities()->GetOrCreateEntity(gClient->GetLocalPlayer()); //gClient->GetServerStream()->Send(); // Prevent Lag SendActorPosition(*g_thePlayer,ent); SendActorValues(*g_thePlayer,ent); SendActorEquip(*g_thePlayer,ent); SendActorAnimation(*g_thePlayer,ent); //Find all cells any "ignored objects" are in. these are mostly players. std::set<TESObjectCELL *> cells; cells.insert((*g_thePlayer)->parentCell); BOOST_FOREACH(UINT32 i,ignore) { TESObjectREFR *form = (TESObjectREFR *)LookupFormByID(i); if(!form) continue; if(!form->parentCell) continue; if(cells.find(form->parentCell) == cells.end())//Not present cells.insert(form->parentCell); }
EnchantmentItem* TESHitEvent::GetMagicHitEnchantment() { //enchantment hit will have either weapon or enchantment as sourceForm (for melee & bow attacks, respectively) TESForm* src = LookupFormByID(sourceFormID); EnchantmentItem* enchantment = DYNAMIC_CAST(src, TESForm, EnchantmentItem); if (!enchantment) if (src->formType == TESObjectWEAP::kTypeID) if (ActorMagicCaster* magicHitData = GetMagicHitData()) { enchantment = DYNAMIC_CAST(magicHitData->magicItem, MagicItem, EnchantmentItem); if (!enchantment) enchantment = ExtraEnchantmentInfo::GetActorSourceEnchantment(*g_thePlayer, GetMagicHitSource()); //This last part may not be necessary. In testing, as long as there was ActorMagicCaster data, I was //always able to retrieve the enchantment without checking actor's source equipData. Added just in case. } return enchantment; }
void FormChangesMap::Load(OBSESerializationInterface* intfc) { UInt32 recType, recVersion, recLength, formID, nuFormID; UInt16 changeType; TESForm* curForm = NULL; Clear(); _MESSAGE("Loading form changes"); bool bContinue = true; bool bSkipCurrentRecord = false; while (bContinue && intfc->GetNextRecordInfo(&recType, &recVersion, &recLength)) { switch (recType) { case 'FMCE': //end of data bContinue = false; break; case 'FMCR': //new form bSkipCurrentRecord = false; intfc->ReadRecordData(&formID, sizeof(formID)); bSkipCurrentRecord = !intfc->ResolveRefID(formID, &nuFormID); //if can't resolve refID, skip changes curForm = LookupFormByID(nuFormID); if (!curForm) //probably non-persistent reference; skip bSkipCurrentRecord = true; break; case 'FMCH': //change entry for current form if (!bSkipCurrentRecord) { intfc->ReadRecordData(&changeType, sizeof(changeType)); FormChangeInfo info(changeType, curForm, NULL); FormChangeEntry* changeEntry = FormChangeEntry::Create(info); if (changeEntry->Load(intfc)) changes.insert(ChangeMapValue(curForm->refID, changeEntry)); } break; default: _MESSAGE("Error loading form changes: unhandled chunk type %d", recType); } } }
void VisitFormList(BGSListForm * formList, std::function<void(TESForm*)> functor) { for (int i = 0; i < formList->forms.count; i++) { TESForm* childForm = NULL; if (formList->forms.GetNthItem(i, childForm)) functor(childForm); } // Script Added Forms if (formList->addedForms) { for (int i = 0; i < formList->addedForms->count; i++) { UInt32 formid = 0; formList->addedForms->GetNthItem(i, formid); TESForm* childForm = LookupFormByID(formid); if (childForm) functor(childForm); } } }
void ActionHandler::actionFastTravel(UInt32 refID) { PlayerCharacter *player = PlayerCharacter::GetSingleton(); TESObjectREFR *marker = (TESObjectREFR *)LookupFormByID(refID); if (marker == NULL) return; ExtraMapMarker *markerData = (ExtraMapMarker *) marker->extraDataList.GetByType(kExtraData_MapMarker); if (markerData == NULL || !markerData->CanTravel()) return; _MESSAGE("Flags %08x, %08x, %08x", player->unk650[6], player->unk650[7], player->unk650[8]); if (player->unk650[7] & 0x100 && !player->parentCell->IsInterior()) { _VMESSAGE("Fast travel"); ExtraReferencePointer *ftp = (ExtraReferencePointer *) marker->extraDataList.GetByType(kExtraData_LinkedRef); if (ftp == NULL || ftp->refr == NULL) { _ERROR("Fast travel heading not found"); } sprintf_s(commandBuf, "player.moveto %x 0 0 0", ftp->refr->refID); Script::RunScriptLine(commandBuf); } }
void VisitFormListRecursive(BGSListForm * formList, std::function<void(TESForm*)> functor, UInt8 recurseMax = 3) { if (recurseMax <= 0) { _WARNING("%s: Too many recursions, aborting!", __FUNCTION__); return; } _MESSAGE("%s: Checking formlist %08x, recursion %d of 3...", __FUNCTION__, formList->formID, 3 - recurseMax); for (int i = 0; i < formList->forms.count; i++) { TESForm* childForm = NULL; if (formList->forms.GetNthItem(i, childForm)) { BGSListForm* childList = NULL; childList = DYNAMIC_CAST(childForm, TESForm, BGSListForm); if (childList) { _MESSAGE("%s: Recursing into formlist %08x...", __FUNCTION__, formList->formID); VisitFormListRecursive(childList, functor, recurseMax - 1); } else functor(childForm); } } // Script Added Forms if (formList->addedForms) { for (int i = 0; i < formList->addedForms->count; i++) { UInt32 formid = 0; formList->addedForms->GetNthItem(i, formid); TESForm* childForm = LookupFormByID(formid); if (childForm) { BGSListForm* childList = NULL; childList = DYNAMIC_CAST(childForm, TESForm, BGSListForm); if (childList) { VisitFormListRecursive(formList, functor, recurseMax - 1); } else functor(childForm); } } } }
void SKSETaskRefreshTintMask::Run() { TESForm * form = LookupFormByID(m_formId); Actor * actor = DYNAMIC_CAST(form, TESForm, Actor); if (!actor) return; NiTriBasedGeom * geometry = GetHeadTriBasedGeom(actor, BGSHeadPart::kTypeFace); if (geometry) { BSShaderProperty * shaderProperty = niptr_cast<BSShaderProperty>(geometry->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->SetTexturePath(6, m_ddsPath.data); material->ReleaseTextures(); CALL_MEMBER_FN(lightingShader, InvalidateTextures)(0); CALL_MEMBER_FN(lightingShader, InitializeShader)(geometry); } } } } }
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); } }
bool xEditCommand() { #if RUNTIME_VERSION == REQUIRED_RUNTIME static const UInt32 s_doShowChangeFlagsName = 0x00CD6940; // Skyrim 1.9.32: 00675DB0, Fallout3: 006C9510 FalloutNV: 0x0083FEF0 static const UInt32 s_changeFormTypeArray = 0x037C1F10; // Skyrim: 012724C0 Fallout3: 00F6D1D0 FalloutNV: 0x011A2428 // xRef at second xRef to s_changeFormTypeArray, offset 0x0B static const UInt32 s_FormToChangeType = 0x05AAC730; // after initialisation Skyrim: 01B2E4D0 Fallout3: 01079BD0 FalloutNV: 0x011DE360 // first entry is NONE, then TES4 static const UInt32 s_nickNames = 0x02C830D8; // Array of form signatures // 4th to last xRef to s_nickNames. array of 159 FormTypeNickName static const UInt32 s_formTypeNicknames = 0x0370E7D0; // Skyrim: 0123F2C4 Fallout3: 00F4A74C FalloutNV: 0x01187004 // Starts with "Misc Stats" as aMiscStats_0, first xref static const UInt32 s_GlobalData1Names = 0x037C18C0; // Skyrim: 01272310, 01272334, 01272370, Fallout3: 00F6CED8 FalloutNV: 0x011A216C static const UInt32 s_GlobalData2Names = s_GlobalData1Names + 12; // 100 + index static const UInt32 s_GlobalData3Names = s_GlobalData2Names + 18; // 1000 + index static const UInt32 s_GlobalData3NamesEnd = s_GlobalData3Names + 8; static const UInt64 s_DialogSubtypes = 0x0374E430; // First is CUST Custom as aCustom_0 xRef 2 static const UInt64 s_DialogSubtypesEnd = 0x0374F7B8; // past PlayerAquireFeaturedItem as aPlayeraquirefe xRef 1 static const UInt64 s_DefaultObjectManagerObjectArray = 0x03723C50; // First is UNUSED01, WWSP as aUnused01 xRef 1 static const UInt64 s_DefaultObjectManagerObjectArrayEnd = 0x03726D90; // ??_R0?AVBGSDefaultObjectManager@@@8 as BGSDefaultObjectManager `RTTI Type Descriptor' #else #error #endif typedef char * (* _s_doShowChangeFlagsName)(UInt32 flag, UInt32 formType, bool returnDescription); RelocAddr <_s_doShowChangeFlagsName> doShowChangeFlagsName(s_doShowChangeFlagsName); RelocPtr <UInt32> changeToFormType(s_changeFormTypeArray); struct FormTypeNickname { char formType; char pad01[7]; char *nickname; UInt32 unk10; UInt32 pad14; }; RelocPtr <FormTypeNickname> formTypeNicknames(s_formTypeNicknames); // array size = kFormType_Max _MESSAGE("*****************************************************************************************************"); // create the list of signatures _MESSAGE("formType;formSignature; %d elements not counting the 6 specials for Papyrus", kFormType_Max); for (UInt32 formType = 0; formType < kFormType_Max; formType++) { _MESSAGE("%03d;%s", formType, formTypeNicknames[formType].nickname); } _MESSAGE(""); _MESSAGE("*****************************************************************************************************"); // create the list of script commands UInt32 i = 0; _MESSAGE(" wbConsoleFunctions : array[] of TFunction = ("); for(ObScriptCommand * iter = g_firstConsoleCommand; iter->opcode < (kObScript_NumConsoleCommands+kObScript_ConsoleOpBase); ++iter, i++) { _MESSAGE(" (Index: %3d; Name: '%s'%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s),", i, iter->longName, CheckParam(iter, 0) ? "; Paramtype1: pt" : "", CheckParam(iter, 0) ? iter->params[0].typeStr : "", CheckParam(iter, 1) ? "; Paramtype2: pt" : "", CheckParam(iter, 1) ? iter->params[1].typeStr : "", CheckParam(iter, 2) ? "; Paramtype3: pt" : "", CheckParam(iter, 2) ? iter->params[2].typeStr : "", CheckParam(iter, 3) ? "; Paramtype3: pt" : "", CheckParam(iter, 3) ? iter->params[3].typeStr : "", CheckParam(iter, 4) ? "; Paramtype4: pt" : "", CheckParam(iter, 4) ? iter->params[4].typeStr : "", CheckParam(iter, 5) ? "; Paramtype5: pt" : "", CheckParam(iter, 5) ? iter->params[5].typeStr : "", CheckParam(iter, 6) ? "; Paramtype6: pt" : "", CheckParam(iter, 6) ? iter->params[6].typeStr : "", CheckParam(iter, 7) ? "; Paramtype7: pt" : "", CheckParam(iter, 7) ? iter->params[7].typeStr : "", CheckParam(iter, 8) ? "; Paramtype8: pt" : "", CheckParam(iter, 8) ? iter->params[8].typeStr : "", CheckParam(iter, 9) ? "// ; More..." : ""); } _MESSAGE(" );"); // Don't forget to remove the last , _MESSAGE(""); _MESSAGE("*****************************************************************************************************"); // create the list of script commands i = 0; _MESSAGE(" wbFunctions : array[] of TFunction = ("); for(ObScriptCommand * iter = g_firstObScriptCommand; iter->opcode < (kObScript_NumObScriptCommands+kObScript_ScriptOpBase); ++iter, i++) { _MESSAGE(" (Index: %3d; Name: '%s'%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s),", i, iter->longName, CheckParam(iter, 0) ? "; Paramtype1: pt" : "", CheckParam(iter, 0) ? iter->params[0].typeStr : "", CheckParam(iter, 1) ? "; Paramtype2: pt" : "", CheckParam(iter, 1) ? iter->params[1].typeStr : "", CheckParam(iter, 2) ? "; Paramtype3: pt" : "", CheckParam(iter, 2) ? iter->params[2].typeStr : "", CheckParam(iter, 3) ? "; Paramtype3: pt" : "", CheckParam(iter, 3) ? iter->params[3].typeStr : "", CheckParam(iter, 4) ? "; Paramtype4: pt" : "", CheckParam(iter, 4) ? iter->params[4].typeStr : "", CheckParam(iter, 5) ? "; Paramtype5: pt" : "", CheckParam(iter, 5) ? iter->params[5].typeStr : "", CheckParam(iter, 6) ? "; Paramtype6: pt" : "", CheckParam(iter, 6) ? iter->params[6].typeStr : "", CheckParam(iter, 7) ? "; Paramtype7: pt" : "", CheckParam(iter, 7) ? iter->params[7].typeStr : "", CheckParam(iter, 8) ? "; Paramtype8: pt" : "", CheckParam(iter, 8) ? iter->params[8].typeStr : "", CheckParam(iter, 9) ? "// ; More..." : ""); } _MESSAGE(" );"); // Don't forget to remove the last , _MESSAGE(""); _MESSAGE("*****************************************************************************************************"); // create the list of condition commands i = 0; UInt32 j = 0; _MESSAGE(" wbCTDAFunctions : array[] of TCTDAFunction = ("); for(ObScriptCommand * iter = g_firstObScriptCommand; iter->opcode < (kObScript_NumObScriptCommands+kObScript_ScriptOpBase); ++iter, i++) { if(iter->eval) { _MESSAGE(" (Index: %3d; Name: '%s'%s%s%s%s%s%s),\t\t// %3d", i, iter->longName, CheckParam(iter, 0) ? "; Paramtype1: pt" : "", CheckParam(iter, 0) ? iter->params[0].typeStr : "", CheckParam(iter, 1) ? "; Paramtype2: pt" : "", CheckParam(iter, 1) ? iter->params[1].typeStr : "", CheckParam(iter, 2) ? "; Paramtype3: pt" : "", CheckParam(iter, 2) ? iter->params[2].typeStr : "", j); j++; } } _MESSAGE(" );"); // Don't forget to remove the last , _MESSAGE(""); _MESSAGE("*****************************************************************************************************"); // create the list of condition commands for WB i = 0; j = 0; _MESSAGE("conditionFunctionData = ( #--0: no param; 1: int param; 2: formid param; 3: float param"); for (ObScriptCommand * iter = g_firstObScriptCommand; iter->opcode < (kObScript_NumObScriptCommands + kObScript_ScriptOpBase); ++iter, i++) { if (iter->eval) { _MESSAGE(" (%3d, '%s', %d, %d, %d),", i, iter->longName, CheckParam(iter, 0) ? WBEncode(iter->params[0]) : 0, CheckParam(iter, 1) ? WBEncode(iter->params[1]) : 0, CheckParam(iter, 2) ? WBEncode(iter->params[2]) : 0, j); j++; } } _MESSAGE(" )"); // Don't forget to add xSE functions _MESSAGE(""); _MESSAGE("*****************************************************************************************************"); // create the Changed Form flags variables UInt32 changeTypeCount = 50; // First being 13 = TESClass. 16 different cases, 50 valid are: 0, 1, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 2, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 3, 4, 11h, 11h, 11h, 5, 11h, 11h, 11h, 11h, 11h, 4, 11h, 11h, 11h, 11h, 11h, 11h, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 11h, 11h, 11h, 11h, 11h, 8, 9, 11h, 0Ah, 11h, 11h, 4, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 0Bh, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 0Ch, 0Dh, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 0Eh, 11h, 11h, 11h, 11h, 11h, 11h, 11h, 0Fh, 10h for (UInt32 changeType = 0; changeType < changeTypeCount; changeType++) { _MESSAGE(" wbChangeFlags%03u : IwbIntegerDef;", changeType); } _MESSAGE(""); // create the Changed Form Data union variables for (UInt32 changeType = 0; changeType < changeTypeCount; changeType++) { UInt32 formType = changeToFormType[changeType]; UInt32 flagValue; char * changeFlagsName; for (UInt8 flagShift = 0; flagShift < 32; flagShift++) { flagValue = 1 << flagShift; changeFlagsName = doShowChangeFlagsName(flagValue, formType, 0); if (strcmp("Bad Flag Name", changeFlagsName)) { _MESSAGE(" wbUnion%s : IwbUnionDef;", changeFlagsName); } } } _MESSAGE("*****************************************************************************************************"); // decode the Change Type name _MESSAGE(" wbChangeTypes := wbKey2Data6Enum(["); for (UInt32 changeType = 0; changeType < changeTypeCount-1; changeType++) { UInt32 formType = changeToFormType[changeType]; _MESSAGE(" '%02u (%03X : %s)',", changeType, formType, formTypeNicknames[formType].nickname); } UInt32 formType = changeToFormType[changeTypeCount-1]; _MESSAGE(" '%02u (%03X : %s)'", changeTypeCount-1, formType, formTypeNicknames[formType].nickname); _MESSAGE(" ]);\n"); _MESSAGE("*****************************************************************************************************"); // decode the Changed form flags for (UInt32 changeType = 0; changeType < changeTypeCount; changeType++) { UInt32 formType = changeToFormType[changeType]; _MESSAGE(" // changeType: %03u = formType: %03u : %s", changeType, formType, formTypeNicknames[formType].nickname); _MESSAGE(" wbChangeFlags%03u := wbInteger('Change Flags', itU32 , wbFlags([", changeType); UInt32 flagValue; char * changeFlagsName; char * changeFlagsDescription; for (UInt8 flagShift = 0; flagShift < 31; flagShift++) { flagValue = 1 << flagShift; changeFlagsName = doShowChangeFlagsName(flagValue, formType, 0); if (0==strcmp("Bad Flag Name", changeFlagsName)) { _MESSAGE(" {%02u} 'UnnamedFlag%02u',", flagShift, flagShift); } else { changeFlagsDescription = doShowChangeFlagsName(flagValue, formType, 1); _MESSAGE(" {%02u} '%s', // %s", flagShift, changeFlagsName, changeFlagsDescription); } } flagValue = 1 << 31; changeFlagsName = doShowChangeFlagsName(flagValue, formType, 0); if (0==strcmp("Bad Flag Name", changeFlagsName)) { _MESSAGE(" {%02u} 'UnnamedFlag%02u'", 31, 31); } else { changeFlagsDescription = doShowChangeFlagsName(flagValue, formType, 1); _MESSAGE(" {%02u} '%s' // %s", 31, changeFlagsName, changeFlagsDescription); } _MESSAGE(" ]));\n"); } _MESSAGE("*****************************************************************************************************"); // Build the Changed Form flags union _MESSAGE(" wbChangeFlags := wbUnion('Change Flags', ChangedFormFlagsDecider, ["); for (UInt32 changeType = 0; changeType < changeTypeCount-1; changeType++) { _MESSAGE(" wbChangeFlags%03u,", changeType); } _MESSAGE(" wbChangeFlags%03u", changeTypeCount-1); _MESSAGE(" ]);\n"); // Build the Changed Form union for (UInt32 changeType = 0; changeType < changeTypeCount; changeType++) { UInt32 formType = changeToFormType[changeType]; UInt32 flagValue; char * changeFlagsName; for (UInt8 flagShift = 0; flagShift < 32; flagShift++) { flagValue = 1 << flagShift; changeFlagsName = doShowChangeFlagsName(flagValue, formType, 0); if (strcmp("Bad Flag Name", changeFlagsName)) { _MESSAGE(" wbUnion%s := wbUnion('%s', ChangedFlag%02uDecider, [wbNull, wbNull]);", changeFlagsName, doShowChangeFlagsName(flagValue, formType, 1), flagShift); } } _MESSAGE(""); } _MESSAGE(""); _MESSAGE("*****************************************************************************************************"); // Build the Changed Form Data struct UInt32 flagValue = 1; char * changeFlagsName = doShowChangeFlagsName(flagValue, formType, 0); _MESSAGE(" wbChangedFormData := wbStruct('Changed Form Data', ["); _MESSAGE(" wbInitialDataType,"); _MESSAGE(" wbUnion('CForm Union', ChangedFormDataDecider, ["); _MESSAGE(" wbNull"); for (UInt32 changeType = 0; changeType < changeTypeCount; changeType++) { bool first = true; UInt32 formType = changeToFormType[changeType]; _MESSAGE(" ,wbStruct('Change %s Data', [ {%03X}", formTypeNicknames[formType].nickname, formType); for (UInt8 flagShift = 0; flagShift < 32; flagShift++) { flagValue = 1 << flagShift; changeFlagsName = doShowChangeFlagsName(flagValue, formType, 0); if (strcmp("Bad Flag Name", changeFlagsName)) { if (first) { first = false; _MESSAGE(" wbUnion%s", changeFlagsName); } else _MESSAGE(" ,wbUnion%s", changeFlagsName); } } _MESSAGE(" ])"); } _MESSAGE(" ]),"); _MESSAGE(" wbByteArray('Undecoded Data', ChangedFormRemainingDataCounter)"); _MESSAGE(" ]);\n"); _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); _MESSAGE("avID;avName;formID;\"fullName\";description.unk08;flags;avType"); UInt32 firstAV = 0x2BC; UInt32 avID = 0; do { TESForm* pForm = LookupFormByID(avID+firstAV); ActorValueInfo_X* pActorValueInfo = NULL; if (pForm && pForm->formType == 98) pActorValueInfo = (ActorValueInfo_X*)pForm; if (pActorValueInfo) { _MESSAGE("%d;%s;%x;\"%s\";%x;%x;%x", avID, pActorValueInfo->avName, pActorValueInfo->formID, pActorValueInfo->fullName.Get(), pActorValueInfo->description.unk08, pActorValueInfo->avFlags, pActorValueInfo->avType); } avID++; } while ((avID+firstAV) < 0x800); _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); struct DialogSubtype { const char * name; // 000 char unk008; // 008 char fil009[3]; // 009 char shortName[4]; // 00C char dstID; // 010 char fil011[3]; // 011 char unk014; // 014 char unk015; // 015 char fil016[2]; // 016 char unk018; // 018 char fil019[15]; // 019 }; // 028 _MESSAGE("dstID;dstName;dstType;dstShort;dstUnk014;dstUnk015;dstUnk018"); RelocPtr <DialogSubtype> g_DialogSubtypes(s_DialogSubtypes); RelocPtr <DialogSubtype> g_DialogSubtypesEnd(s_DialogSubtypesEnd); DialogSubtype* curr = g_DialogSubtypes; UInt32 dstID = 0; do { char shortName[5] = " "; for (UInt8 i = 0; i < 4 ; i++) shortName[i] = curr->shortName[i]; shortName[4] = 0; _MESSAGE("%d;\"%s\";%d;\"%s\";%d;%d;%d", dstID, curr->name, curr->dstID, shortName, curr->unk008, curr->unk014, curr->unk015, curr->unk018); dstID++; curr++; } while (curr < g_DialogSubtypesEnd); _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); struct DataDOM { const char * name; // 000 UInt8 formType; // 008 UInt8 fil009[3]; // 009 char shortName[4]; // 00C UInt32 unk010; // 010 UInt32 unk014; // 014 UInt32 formID; // 018 UInt32 pad01C; // 01C }; // 020 RelocPtr <DataDOM> g_DefaultObjectManagerObject(s_DefaultObjectManagerObjectArray); UInt32 domCount = (s_DefaultObjectManagerObjectArrayEnd - s_DefaultObjectManagerObjectArray) / sizeof(DataDOM); DataDOM* dom = g_DefaultObjectManagerObject; _MESSAGE("domID;domName;domShort;formType;domUnk010;domUnk014;domFormID; %d elements", domCount); for (UInt32 domID = 0; domID < domCount ; domID++) { char shortName[5] = " "; for (UInt8 i = 0; i < 4 ; i++) shortName[i] = dom->shortName[i]; shortName[4] = 0; _MESSAGE("%d;\"%s\";\"%s\";%d;%d;%d;%08x", domID, dom->name, shortName, dom->formType, dom->unk010, dom->unk014, dom->formID); dom++; }; _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); dom = g_DefaultObjectManagerObject; for (UInt32 domID = 0; domID < domCount ; domID++) { char shortName[5] = " "; for (UInt8 i = 0; i < 4 ; i++) shortName[i] = dom->shortName[i]; shortName[4] = 0; _MESSAGE("sig2Int('%s'), '%s'", shortName, dom->name); dom++; }; _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); DefaultObjectMap * domap = *(g_defaultObjectMap); domap->Dump(); _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); _MESSAGE("formType;formSignature;formID;"); DataHandler* theDH = *g_dataHandler.GetPtr(); UnkFormXArray* unkFormArrays = (UnkFormXArray*)&(theDH->arrNONE); for (UInt8 i = 0; i < kFormType_Max; i++) { UnkFormXArray* a = (UnkFormXArray*) ((uintptr_t)unkFormArrays + i * sizeof(UnkFormXArray)); for (UInt64 j = 0; j < a->count; j++) { TESForm_X* f = (*a)[j]; if (f && !f->mods) _MESSAGE("%04d;%s;%08X;", f->formType, formTypeNicknames[f->formType].nickname, f->formID); } } _MESSAGE("*****************************************************************************************************"); _MESSAGE("\n\n\n"); return true; }
static bool GetActiveMenuElement(COMMAND_ARGS, eMenuValue whichValue, MenuInfo* out, UInt32 whichMenu = 0) { InterfaceManager* intfc = InterfaceManager::GetSingleton(); Menu* activeMenu = intfc->activeMenu; Tile* activeTile = intfc->activeTile; if (!activeTile) { // theoretically this is active tile if user is navigating by keyboard - for this to work user must pass whichMenu arg activeTile = intfc->altActiveTile; } bool gotValue = false; UInt32 intArg = -1; //Extract arguments if (whichValue < kMenu_Ingredient && whichValue >= kMenu_Selection) //optional int param specifies menu type { ExtractArgs(EXTRACT_ARGS, &intArg); if (intArg != -1) activeMenu = GetMenuByType(intArg); } else if (whichValue >= kMenu_Ingredient) { ExtractArgs(EXTRACT_ARGS, &intArg); if (intArg == -1) return false; } if (whichMenu) //specific menu, so look it up directly activeMenu = GetMenuByType(whichMenu); if (!activeMenu) return false; //get element based on menu type switch (activeMenu->id) { case kMenuType_Message: { MessageMenu* msgMenu = (MessageMenu*)activeMenu; switch (whichValue) { case kMenu_Object: if (ShowMessageBox_pScriptRefID && msgMenu->IsScriptMessageBox()) { out->form = LookupFormByID(*ShowMessageBox_pScriptRefID); gotValue = true; } else out->form = 0; default: break; } } break; case kMenuType_Alchemy: { AlchemyMenu* menu = (AlchemyMenu*)activeMenu; switch (whichValue) { case kMenu_Object: out->form = menu->potion; gotValue = true; break; case kMenu_Ingredient: out->form = menu->GetIngredientItem(intArg); gotValue = true; break; case kMenu_IngredientCount: out->integer = menu->GetIngredientCount(intArg); gotValue = true; break; case kMenu_Apparatus: out->form = menu->GetApparatus(intArg); gotValue = true; break; default: break; } } break; case kMenuType_Container: { ContainerMenu* menu = (ContainerMenu*)activeMenu; switch (whichValue) { case kMenu_ContainerView: if (menu->isContainerContents) out->integer = 0; else out->integer = 1; gotValue = true; break; case kMenu_Ref: { out->form = menu->refr; gotValue = true; break; } case kMenu_Filter: out->integer = menu->filterType; gotValue = true; break; case kMenu_Selection: { if (activeTile) { float fIndex; if (activeTile->GetFloatValue(kTileValue_user11, &fIndex)) { UInt32 index = fIndex; if (menu->isContainerContents) out->form = menu->refr->GetInventoryItem(index, menu->isBarter); else out->form = (*g_thePlayer)->GetInventoryItem(index, 0); gotValue = true; } } } break; case kMenu_Barter: out->integer = menu->isBarter; gotValue = true; break; default: break; } break; } case kMenuType_Magic: { MagicMenu* menu = (MagicMenu*)activeMenu; switch (whichValue) { case kMenu_Selection: { if (activeTile && menu->filterType != MagicMenu::kFilter_ActiveEffects) { float fIndex; if (activeTile->GetFloatValue(kTileValue_user13, &fIndex)) { DEBUG_PRINT("Index of active magic item: %.0f", fIndex); UInt32 index = fIndex; float fObjType; if (activeTile->GetFloatValue(kTileValue_user7, &fObjType)) { if (fObjType == 8) { // a scroll TESForm* form = menu->GetMagicItemForIndex(index); if (form) { out->form = form; gotValue = true; } } else { // a spell out->form = MenuSpellListVisitor(&menu->spells).GetNthInfo(index-1); gotValue = true; } } } } } break; case kMenu_Filter: out->integer = menu->filterType; gotValue = true; break; default: break; } break; } case kMenuType_SpellPurchase: { SpellPurchaseMenu* menu = (SpellPurchaseMenu*)activeMenu; switch (whichValue) { case kMenu_Selection: { if (activeTile) { float fIndex; //if (activeTile->GetFloatValue(kTileValue_user11, &fIndex)) if (activeTile->GetFloatValue(kTileValue_user0, &fIndex)) { UInt32 index = fIndex; out->form = MenuSpellListVisitor(&menu->spells).GetNthInfo(index); gotValue = true; } } break; } case kMenu_Ref: { out->form = menu->spellMerchant; gotValue = true; break; } default: break; } } break; case kMenuType_Enchantment: { EnchantmentMenu* menu = (EnchantmentMenu*)activeMenu; switch (whichValue) { case kMenu_Soulgem: if (menu->soulGemInfo) { out->form = menu->soulGemInfo->form; gotValue = true; } break; case kMenu_EnchantItem: out->form = menu->enchantItem; gotValue = true; break; default: break; } } break; case kMenuType_Book: { BookMenu* menu = (BookMenu*)activeMenu; switch (whichValue) { case kMenu_Ref: out->form = menu->bookRef; gotValue = true; break; case kMenu_Object: out->form = menu->book; gotValue = true; break; default: break; } } break; case kMenuType_Inventory: { InventoryMenu* menu = (InventoryMenu*)activeMenu; switch (whichValue) { case kMenu_Selection: { if (activeTile) { float fIndex; if (activeTile->GetFloatValue(kTileValue_user11, &fIndex)) { UInt32 index = fIndex; out->form = (*g_thePlayer)->GetInventoryItem(index, 0); gotValue = true; } } } break; case kMenu_Filter: out->integer = menu->filterType; gotValue = true; break; default: break; } } break; case kMenuType_Dialog: { DialogMenu* menu = (DialogMenu*)activeMenu; switch (whichValue) { case kMenu_Ref: out->form = menu->speaker; gotValue = true; break; default: break; } } break; default: break; } return gotValue; }