1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-09 03:39:14 +00:00
OpenMW/apps/openmw/mwgui/statswatcher.cpp
2023-08-20 10:28:46 +02:00

189 lines
6.2 KiB
C++

#include "statswatcher.hpp"
#include <components/esm3/loadclas.hpp>
#include <components/esm3/loadrace.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include <string>
namespace MWGui
{
// mWatchedTimeToStartDrowning = -1 for correct drowning state check,
// if stats.getTimeToStartDrowning() == 0 already on game start
StatsWatcher::StatsWatcher()
: mWatchedLevel(-1)
, mWatchedTimeToStartDrowning(-1)
, mWatchedStatsEmpty(true)
{
}
void StatsWatcher::watchActor(const MWWorld::Ptr& ptr)
{
mWatched = ptr;
}
void StatsWatcher::update()
{
if (mWatched.isEmpty())
return;
const auto& store = MWBase::Environment::get().getESMStore();
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
const MWMechanics::NpcStats& stats = mWatched.getClass().getNpcStats(mWatched);
for (const ESM::Attribute& attribute : store->get<ESM::Attribute>())
{
const auto& value = stats.getAttribute(attribute.mId);
if (value != mWatchedAttributes[attribute.mId] || mWatchedStatsEmpty)
{
mWatchedAttributes[attribute.mId] = value;
setAttribute(attribute.mId, value);
}
}
if (stats.getHealth() != mWatchedHealth || mWatchedStatsEmpty)
{
mWatchedHealth = stats.getHealth();
setValue("HBar", stats.getHealth());
}
if (stats.getMagicka() != mWatchedMagicka || mWatchedStatsEmpty)
{
mWatchedMagicka = stats.getMagicka();
setValue("MBar", stats.getMagicka());
}
if (stats.getFatigue() != mWatchedFatigue || mWatchedStatsEmpty)
{
mWatchedFatigue = stats.getFatigue();
setValue("FBar", stats.getFatigue());
}
float timeToDrown = stats.getTimeToStartDrowning();
if (timeToDrown != mWatchedTimeToStartDrowning)
{
static const float fHoldBreathTime = MWBase::Environment::get()
.getESMStore()
->get<ESM::GameSetting>()
.find("fHoldBreathTime")
->mValue.getFloat();
mWatchedTimeToStartDrowning = timeToDrown;
if (timeToDrown >= fHoldBreathTime || timeToDrown == -1.0) // -1.0 is a special value during initialization
winMgr->setDrowningBarVisibility(false);
else
{
winMgr->setDrowningBarVisibility(true);
winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning(), fHoldBreathTime);
}
}
for (const ESM::Skill& skill : store->get<ESM::Skill>())
{
const auto& value = stats.getSkill(skill.mId);
if (value != mWatchedSkills[skill.mId] || mWatchedStatsEmpty)
{
mWatchedSkills[skill.mId] = value;
setValue(skill.mId, value);
}
}
if (stats.getLevel() != mWatchedLevel || mWatchedStatsEmpty)
{
mWatchedLevel = stats.getLevel();
setValue("level", mWatchedLevel);
}
if (mWatched.getClass().isNpc())
{
const ESM::NPC* watchedRecord = mWatched.get<ESM::NPC>()->mBase;
if (watchedRecord->mName != mWatchedName || mWatchedStatsEmpty)
{
mWatchedName = watchedRecord->mName;
setValue("name", watchedRecord->mName);
}
if (watchedRecord->mRace != mWatchedRace || mWatchedStatsEmpty)
{
mWatchedRace = watchedRecord->mRace;
const ESM::Race* race = store->get<ESM::Race>().find(watchedRecord->mRace);
setValue("race", race->mName);
}
if (watchedRecord->mClass != mWatchedClass || mWatchedStatsEmpty)
{
mWatchedClass = watchedRecord->mClass;
const ESM::Class* cls = store->get<ESM::Class>().find(watchedRecord->mClass);
setValue("class", cls->mName);
size_t size = cls->mData.mSkills.size();
std::vector<ESM::RefId> majorSkills(size);
std::vector<ESM::RefId> minorSkills(size);
for (size_t i = 0; i < size; ++i)
{
minorSkills[i] = ESM::Skill::indexToRefId(cls->mData.mSkills[i][0]);
majorSkills[i] = ESM::Skill::indexToRefId(cls->mData.mSkills[i][1]);
}
configureSkills(majorSkills, minorSkills);
}
}
mWatchedStatsEmpty = false;
}
void StatsWatcher::addListener(StatsListener* listener)
{
mListeners.insert(listener);
}
void StatsWatcher::removeListener(StatsListener* listener)
{
mListeners.erase(listener);
}
void StatsWatcher::setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value)
{
for (StatsListener* listener : mListeners)
listener->setAttribute(id, value);
}
void StatsWatcher::setValue(ESM::RefId id, const MWMechanics::SkillValue& value)
{
for (StatsListener* listener : mListeners)
listener->setValue(id, value);
}
void StatsWatcher::setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value)
{
for (StatsListener* listener : mListeners)
listener->setValue(id, value);
}
void StatsWatcher::setValue(std::string_view id, const std::string& value)
{
for (StatsListener* listener : mListeners)
listener->setValue(id, value);
}
void StatsWatcher::setValue(std::string_view id, int value)
{
for (StatsListener* listener : mListeners)
listener->setValue(id, value);
}
void StatsWatcher::configureSkills(const std::vector<ESM::RefId>& major, const std::vector<ESM::RefId>& minor)
{
for (StatsListener* listener : mListeners)
listener->configureSkills(major, minor);
}
}