#include "PapyrusRace.h" #include "GameObjects.h" #include "GameFormComponents.h" #include "GameForms.h" #include "GameData.h" #include #include "common/ICriticalSection.h" UInt32 g_invalidatePlayableRaceCache = 0; UInt32 g_invalidateRaceCache = 0; namespace papyrusRace { typedef std::map RaceCache; static ICriticalSection s_raceCacheLock; static RaceCache s_raceCache; TESRace* GetRace(StaticFunctionTag*, BSFixedString editorID) { s_raceCacheLock.Enter(); if(g_invalidateRaceCache == 1) { s_raceCache.clear(); g_invalidateRaceCache = 0; } if (s_raceCache.empty()) { DataHandler* pDataHandler = DataHandler::GetSingleton(); tArray& races = pDataHandler->races; for (UInt32 n = 0; n < races.count; n++) { TESRace* pRace = NULL; races.GetNthItem(n, pRace); if (pRace) { s_raceCache.insert(RaceCache::value_type(pRace->editorId, pRace)); } } } s_raceCacheLock.Leave(); RaceCache::iterator it = s_raceCache.find(editorID); TESRace* pRace = (it != s_raceCache.end()) ? it->second : NULL; return pRace; } typedef std::vector PlayableRaceCache; static ICriticalSection s_playableRaceCacheLock; static PlayableRaceCache s_playableRaceCache; UInt32 GetNumPlayableRaces(StaticFunctionTag * base) { s_playableRaceCacheLock.Enter(); if(g_invalidatePlayableRaceCache == 1) { s_playableRaceCache.clear(); g_invalidatePlayableRaceCache = 0; } if (s_playableRaceCache.empty()) { DataHandler* pDataHandler = DataHandler::GetSingleton(); tArray& races = pDataHandler->races; for (UInt32 n = 0; n < races.count; n++) { TESRace* pRace = NULL; races.GetNthItem(n, pRace); if (pRace && IsRaceFlagSet(pRace, TESRace::kRace_Playable)) { s_playableRaceCache.push_back(pRace); } } } s_playableRaceCacheLock.Leave(); return s_playableRaceCache.size(); } TESRace * GetNthPlayableRace(StaticFunctionTag * base, UInt32 n) { if(n < 0) { return NULL; } s_playableRaceCacheLock.Enter(); if(g_invalidatePlayableRaceCache == 1) { s_playableRaceCache.clear(); g_invalidatePlayableRaceCache = 0; } if (s_playableRaceCache.empty()) { DataHandler* pDataHandler = DataHandler::GetSingleton(); tArray& races = pDataHandler->races; for (UInt32 n = 0; n < races.count; n++) { TESRace* pRace = NULL; races.GetNthItem(n, pRace); if (pRace && IsRaceFlagSet(pRace, TESRace::kRace_Playable)) { s_playableRaceCache.push_back(pRace); } } } s_playableRaceCacheLock.Leave(); return (n < s_playableRaceCache.size()) ? s_playableRaceCache.at(n) : NULL; } UInt32 GetSpellCount(TESRace* thisRace) { return (thisRace)? thisRace->spellList.GetSpellCount() : 0; } SpellItem* GetNthSpell(TESRace* thisRace, UInt32 n) { return (thisRace) ? thisRace->spellList.GetNthSpell(n) : NULL; } bool IsRaceFlagSet(TESRace* thisRace, UInt32 flag) { return (thisRace) ? (thisRace->data.raceFlags & flag) == flag : false; } void SetRaceFlag(TESRace* thisRace, UInt32 flag) { if (thisRace) { thisRace->data.raceFlags |= flag; if((flag & TESRace::kRace_Playable) == TESRace::kRace_Playable) g_invalidatePlayableRaceCache = 1; } } void ClearRaceFlag(TESRace* thisRace, UInt32 flag) { if (thisRace) { thisRace->data.raceFlags &= ~flag; if((flag & TESRace::kRace_Playable) == TESRace::kRace_Playable) g_invalidatePlayableRaceCache = 1; } } BGSVoiceType* GetDefaultVoiceType(TESRace* thisRace, bool female) { return (thisRace) ? thisRace->voiceTypes[female] : NULL; } void SetDefaultVoiceType(TESRace* thisRace, bool female, BGSVoiceType* voiceType) { if(thisRace) { thisRace->voiceTypes[female] = voiceType; } } TESObjectARMO * GetSkin(TESRace* thisRace) { return (thisRace) ? thisRace->skin.skin : NULL; } void SetSkin(TESRace* thisRace, TESObjectARMO * skin) { if(thisRace) { thisRace->skin.skin = skin; } } } #include "PapyrusVM.h" #include "PapyrusNativeFunctions.h" void papyrusRace::RegisterFuncs(VMClassRegistry* registry) { registry->RegisterFunction( new NativeFunction0 ("GetSpellCount", "Race", papyrusRace::GetSpellCount, registry)); registry->RegisterFunction( new NativeFunction1 ("GetNthSpell", "Race", papyrusRace::GetNthSpell, registry)); registry->RegisterFunction( new NativeFunction1 ("IsRaceFlagSet", "Race", papyrusRace::IsRaceFlagSet, registry)); registry->RegisterFunction( new NativeFunction1 ("SetRaceFlag", "Race", papyrusRace::SetRaceFlag, registry)); registry->RegisterFunction( new NativeFunction1 ("ClearRaceFlag", "Race", papyrusRace::ClearRaceFlag, registry)); registry->RegisterFunction( new NativeFunction1 ("GetDefaultVoiceType", "Race", papyrusRace::GetDefaultVoiceType, registry)); registry->RegisterFunction( new NativeFunction2 ("SetDefaultVoiceType", "Race", papyrusRace::SetDefaultVoiceType, registry)); registry->RegisterFunction( new NativeFunction1 ("GetRace", "Race", papyrusRace::GetRace, registry)); registry->RegisterFunction( new NativeFunction0 ("GetNumPlayableRaces", "Race", papyrusRace::GetNumPlayableRaces, registry)); registry->RegisterFunction( new NativeFunction1 ("GetNthPlayableRace", "Race", papyrusRace::GetNthPlayableRace, registry)); registry->RegisterFunction( new NativeFunction0 ("GetSkin", "Race", papyrusRace::GetSkin, registry)); registry->RegisterFunction( new NativeFunction1 ("SetSkin", "Race", papyrusRace::SetSkin, registry)); }