mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 12:35:46 +00:00
ce263af393
Remove WindowManager wrappers. It's not safe to use WindowManager in all places and it's not required. Environment stores resource system providing VFS required to call these functions. In the case of ObjectPaging it's available from the member variable. Also ObjectPaging::createChunk may access WindowManager when it's already destructed when exiting the game because it's destructed before CellPreloader finishes all background jobs. Engine::mResourceSystem is destructed after all other systems so it's safe to use it.
653 lines
22 KiB
C++
653 lines
22 KiB
C++
#include "hud.hpp"
|
|
|
|
#include <MyGUI_RenderManager.h>
|
|
#include <MyGUI_ProgressBar.h>
|
|
#include <MyGUI_Button.h>
|
|
#include <MyGUI_InputManager.h>
|
|
#include <MyGUI_ImageBox.h>
|
|
#include <MyGUI_ScrollView.h>
|
|
|
|
#include <components/settings/settings.hpp>
|
|
#include <components/misc/resourcehelpers.hpp>
|
|
#include <components/resource/resourcesystem.hpp>
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/windowmanager.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwworld/class.hpp"
|
|
#include "../mwworld/esmstore.hpp"
|
|
|
|
#include "../mwmechanics/npcstats.hpp"
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
|
|
#include "inventorywindow.hpp"
|
|
#include "spellicons.hpp"
|
|
#include "itemmodel.hpp"
|
|
#include "draganddrop.hpp"
|
|
|
|
#include "itemwidget.hpp"
|
|
|
|
namespace MWGui
|
|
{
|
|
|
|
/**
|
|
* Makes it possible to use ItemModel::moveItem to move an item from an inventory to the world.
|
|
*/
|
|
class WorldItemModel : public ItemModel
|
|
{
|
|
public:
|
|
WorldItemModel(float left, float top) : mLeft(left), mTop(top) {}
|
|
virtual ~WorldItemModel() override {}
|
|
MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool /*allowAutoEquip*/) override
|
|
{
|
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
|
|
|
MWWorld::Ptr dropped;
|
|
if (world->canPlaceObject(mLeft, mTop))
|
|
dropped = world->placeObject(item.mBase, mLeft, mTop, count);
|
|
else
|
|
dropped = world->dropObjectOnGround(world->getPlayerPtr(), item.mBase, count);
|
|
dropped.getCellRef().setOwner("");
|
|
|
|
return dropped;
|
|
}
|
|
|
|
void removeItem (const ItemStack& item, size_t count) override { throw std::runtime_error("removeItem not implemented"); }
|
|
ModelIndex getIndex (const ItemStack &item) override { throw std::runtime_error("getIndex not implemented"); }
|
|
void update() override {}
|
|
size_t getItemCount() override { return 0; }
|
|
ItemStack getItem (ModelIndex index) override { throw std::runtime_error("getItem not implemented"); }
|
|
bool usesContainer(const MWWorld::Ptr&) override { return false; }
|
|
|
|
private:
|
|
// Where to drop the item
|
|
float mLeft;
|
|
float mTop;
|
|
};
|
|
|
|
|
|
HUD::HUD(CustomMarkerCollection &customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
|
|
: WindowBase("openmw_hud.layout")
|
|
, LocalMapBase(customMarkers, localMapRender, Settings::Manager::getBool("local map hud fog of war", "Map"))
|
|
, mHealth(nullptr)
|
|
, mMagicka(nullptr)
|
|
, mStamina(nullptr)
|
|
, mDrowning(nullptr)
|
|
, mWeapImage(nullptr)
|
|
, mSpellImage(nullptr)
|
|
, mWeapStatus(nullptr)
|
|
, mSpellStatus(nullptr)
|
|
, mEffectBox(nullptr)
|
|
, mMinimap(nullptr)
|
|
, mCrosshair(nullptr)
|
|
, mCellNameBox(nullptr)
|
|
, mDrowningBar(nullptr)
|
|
, mDrowningFlash(nullptr)
|
|
, mHealthManaStaminaBaseLeft(0)
|
|
, mWeapBoxBaseLeft(0)
|
|
, mSpellBoxBaseLeft(0)
|
|
, mMinimapBoxBaseRight(0)
|
|
, mEffectBoxBaseRight(0)
|
|
, mDragAndDrop(dragAndDrop)
|
|
, mCellNameTimer(0.0f)
|
|
, mWeaponSpellTimer(0.f)
|
|
, mMapVisible(true)
|
|
, mWeaponVisible(true)
|
|
, mSpellVisible(true)
|
|
, mWorldMouseOver(false)
|
|
, mEnemyActorId(-1)
|
|
, mEnemyHealthTimer(-1)
|
|
, mIsDrowning(false)
|
|
, mDrowningFlashTheta(0.f)
|
|
{
|
|
// Energy bars
|
|
getWidget(mHealthFrame, "HealthFrame");
|
|
getWidget(mHealth, "Health");
|
|
getWidget(mMagicka, "Magicka");
|
|
getWidget(mStamina, "Stamina");
|
|
getWidget(mEnemyHealth, "EnemyHealth");
|
|
mHealthManaStaminaBaseLeft = mHealthFrame->getLeft();
|
|
|
|
MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame;
|
|
getWidget(healthFrame, "HealthFrame");
|
|
getWidget(magickaFrame, "MagickaFrame");
|
|
getWidget(fatigueFrame, "FatigueFrame");
|
|
healthFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
|
|
magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
|
|
fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
|
|
|
|
//Drowning bar
|
|
getWidget(mDrowningBar, "DrowningBar");
|
|
getWidget(mDrowningFrame, "DrowningFrame");
|
|
getWidget(mDrowning, "Drowning");
|
|
getWidget(mDrowningFlash, "Flash");
|
|
mDrowning->setProgressRange(200);
|
|
|
|
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
|
|
// Item and spell images and status bars
|
|
getWidget(mWeapBox, "WeapBox");
|
|
getWidget(mWeapImage, "WeapImage");
|
|
getWidget(mWeapStatus, "WeapStatus");
|
|
mWeapBoxBaseLeft = mWeapBox->getLeft();
|
|
mWeapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWeaponClicked);
|
|
|
|
getWidget(mSpellBox, "SpellBox");
|
|
getWidget(mSpellImage, "SpellImage");
|
|
getWidget(mSpellStatus, "SpellStatus");
|
|
mSpellBoxBaseLeft = mSpellBox->getLeft();
|
|
mSpellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
|
|
|
|
getWidget(mSneakBox, "SneakBox");
|
|
mSneakBoxBaseLeft = mSneakBox->getLeft();
|
|
|
|
getWidget(mEffectBox, "EffectBox");
|
|
mEffectBoxBaseRight = viewSize.width - mEffectBox->getRight();
|
|
|
|
getWidget(mMinimapBox, "MiniMapBox");
|
|
mMinimapBoxBaseRight = viewSize.width - mMinimapBox->getRight();
|
|
getWidget(mMinimap, "MiniMap");
|
|
getWidget(mCompass, "Compass");
|
|
getWidget(mMinimapButton, "MiniMapButton");
|
|
mMinimapButton->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
|
|
|
getWidget(mCellNameBox, "CellName");
|
|
getWidget(mWeaponSpellBox, "WeaponSpellName");
|
|
|
|
getWidget(mCrosshair, "Crosshair");
|
|
|
|
LocalMapBase::init(mMinimap, mCompass);
|
|
|
|
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
|
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
|
mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus);
|
|
|
|
mSpellIcons = new SpellIcons();
|
|
}
|
|
|
|
HUD::~HUD()
|
|
{
|
|
mMainWidget->eventMouseLostFocus.clear();
|
|
mMainWidget->eventMouseMove.clear();
|
|
mMainWidget->eventMouseButtonClick.clear();
|
|
|
|
delete mSpellIcons;
|
|
}
|
|
|
|
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
|
{
|
|
int current = static_cast<int>(value.getCurrent());
|
|
int modified = static_cast<int>(value.getModified());
|
|
|
|
// Fatigue can be negative
|
|
if (id != "FBar")
|
|
current = std::max(0, current);
|
|
|
|
MyGUI::Widget* w;
|
|
std::string valStr = MyGUI::utility::toString(current) + " / " + MyGUI::utility::toString(modified);
|
|
if (id == "HBar")
|
|
{
|
|
mHealth->setProgressRange(std::max(0, modified));
|
|
mHealth->setProgressPosition(std::max(0, current));
|
|
getWidget(w, "HealthFrame");
|
|
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
|
|
}
|
|
else if (id == "MBar")
|
|
{
|
|
mMagicka->setProgressRange(std::max(0, modified));
|
|
mMagicka->setProgressPosition(std::max(0, current));
|
|
getWidget(w, "MagickaFrame");
|
|
w->setUserString("Caption_HealthDescription", "#{sMagDesc}\n" + valStr);
|
|
}
|
|
else if (id == "FBar")
|
|
{
|
|
mStamina->setProgressRange(std::max(0, modified));
|
|
mStamina->setProgressPosition(std::max(0, current));
|
|
getWidget(w, "FatigueFrame");
|
|
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
|
}
|
|
}
|
|
|
|
void HUD::setDrowningTimeLeft(float time, float maxTime)
|
|
{
|
|
size_t progress = static_cast<size_t>(time / maxTime * 200);
|
|
mDrowning->setProgressPosition(progress);
|
|
|
|
bool isDrowning = (progress == 0);
|
|
if (isDrowning && !mIsDrowning) // Just started drowning
|
|
mDrowningFlashTheta = 0.0f; // Start out on bright red every time.
|
|
|
|
mDrowningFlash->setVisible(isDrowning);
|
|
mIsDrowning = isDrowning;
|
|
}
|
|
|
|
void HUD::setDrowningBarVisible(bool visible)
|
|
{
|
|
mDrowningBar->setVisible(visible);
|
|
}
|
|
|
|
void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
|
{
|
|
if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ())
|
|
return;
|
|
|
|
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
|
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
|
{
|
|
// drop item into the gameworld
|
|
MWBase::Environment::get().getWorld()->breakInvisibility(
|
|
MWMechanics::getPlayer());
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
|
float mouseX = cursorPosition.left / float(viewSize.width);
|
|
float mouseY = cursorPosition.top / float(viewSize.height);
|
|
|
|
WorldItemModel drop (mouseX, mouseY);
|
|
mDragAndDrop->drop(&drop, nullptr);
|
|
|
|
winMgr->changePointer("arrow");
|
|
}
|
|
else
|
|
{
|
|
GuiMode mode = winMgr->getMode();
|
|
|
|
if (!winMgr->isConsoleMode() && (mode != GM_Container) && (mode != GM_Inventory))
|
|
return;
|
|
|
|
MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject();
|
|
|
|
if (winMgr->isConsoleMode())
|
|
winMgr->setConsoleSelectedObject(object);
|
|
else //if ((mode == GM_Container) || (mode == GM_Inventory))
|
|
{
|
|
// pick up object
|
|
if (!object.isEmpty())
|
|
winMgr->getInventoryWindow()->pickUpObject(object);
|
|
}
|
|
}
|
|
}
|
|
|
|
void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
|
|
{
|
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
|
{
|
|
mWorldMouseOver = false;
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
|
float mouseX = cursorPosition.left / float(viewSize.width);
|
|
float mouseY = cursorPosition.top / float(viewSize.height);
|
|
|
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
|
|
|
// if we can't drop the object at the wanted position, show the "drop on ground" cursor.
|
|
bool canDrop = world->canPlaceObject(mouseX, mouseY);
|
|
|
|
if (!canDrop)
|
|
MWBase::Environment::get().getWindowManager()->changePointer("drop_ground");
|
|
else
|
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
|
|
|
}
|
|
else
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
|
mWorldMouseOver = true;
|
|
}
|
|
}
|
|
|
|
void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new)
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
|
mWorldMouseOver = false;
|
|
}
|
|
|
|
void HUD::onHMSClicked(MyGUI::Widget* _sender)
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats);
|
|
}
|
|
|
|
void HUD::onMapClicked(MyGUI::Widget* _sender)
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
|
|
}
|
|
|
|
void HUD::onWeaponClicked(MyGUI::Widget* _sender)
|
|
{
|
|
const MWWorld::Ptr& player = MWMechanics::getPlayer();
|
|
if (player.getClass().getNpcStats(player).isWerewolf())
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}");
|
|
return;
|
|
}
|
|
|
|
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
|
|
}
|
|
|
|
void HUD::onMagicClicked(MyGUI::Widget* _sender)
|
|
{
|
|
const MWWorld::Ptr& player = MWMechanics::getPlayer();
|
|
if (player.getClass().getNpcStats(player).isWerewolf())
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}");
|
|
return;
|
|
}
|
|
|
|
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic);
|
|
}
|
|
|
|
void HUD::setCellName(const std::string& cellName)
|
|
{
|
|
if (mCellName != cellName)
|
|
{
|
|
mCellNameTimer = 5.0f;
|
|
mCellName = cellName;
|
|
|
|
mCellNameBox->setCaptionWithReplacing("#{sCell=" + mCellName + "}");
|
|
mCellNameBox->setVisible(mMapVisible);
|
|
}
|
|
}
|
|
|
|
void HUD::onFrame(float dt)
|
|
{
|
|
LocalMapBase::onFrame(dt);
|
|
|
|
mCellNameTimer -= dt;
|
|
mWeaponSpellTimer -= dt;
|
|
if (mCellNameTimer < 0)
|
|
mCellNameBox->setVisible(false);
|
|
if (mWeaponSpellTimer < 0)
|
|
mWeaponSpellBox->setVisible(false);
|
|
|
|
mEnemyHealthTimer -= dt;
|
|
if (mEnemyHealth->getVisible() && mEnemyHealthTimer < 0)
|
|
{
|
|
mEnemyHealth->setVisible(false);
|
|
mWeaponSpellBox->setPosition(mWeaponSpellBox->getPosition() + MyGUI::IntPoint(0,20));
|
|
}
|
|
|
|
mSpellIcons->updateWidgets(mEffectBox, true);
|
|
|
|
if (mEnemyActorId != -1 && mEnemyHealth->getVisible())
|
|
{
|
|
updateEnemyHealthBar();
|
|
}
|
|
|
|
if (mDrowningBar->getVisible())
|
|
mDrowningBar->setPosition(mMainWidget->getWidth()/2 - mDrowningFrame->getWidth()/2, mMainWidget->getTop());
|
|
|
|
if (mIsDrowning)
|
|
{
|
|
mDrowningFlashTheta += dt * osg::PI*2;
|
|
|
|
float intensity = (cos(mDrowningFlashTheta) + 2.0f) / 3.0f;
|
|
|
|
mDrowningFlash->setAlpha(intensity);
|
|
}
|
|
}
|
|
|
|
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
|
|
{
|
|
const ESM::Spell* spell =
|
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
|
|
|
std::string spellName = spell->mName;
|
|
if (spellName != mSpellName && mSpellVisible)
|
|
{
|
|
mWeaponSpellTimer = 5.0f;
|
|
mSpellName = spellName;
|
|
mWeaponSpellBox->setCaption(mSpellName);
|
|
mWeaponSpellBox->setVisible(true);
|
|
}
|
|
|
|
mSpellStatus->setProgressRange(100);
|
|
mSpellStatus->setProgressPosition(successChancePercent);
|
|
|
|
mSpellBox->setUserString("ToolTipType", "Spell");
|
|
mSpellBox->setUserString("Spell", spellId);
|
|
|
|
// use the icon of the first effect
|
|
const ESM::MagicEffect* effect =
|
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(spell->mEffects.mList.front().mEffectID);
|
|
|
|
std::string icon = effect->mIcon;
|
|
int slashPos = icon.rfind('\\');
|
|
icon.insert(slashPos+1, "b_");
|
|
icon = Misc::ResourceHelpers::correctIconPath(icon, MWBase::Environment::get().getResourceSystem()->getVFS());
|
|
|
|
mSpellImage->setSpellIcon(icon);
|
|
}
|
|
|
|
void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
|
|
{
|
|
std::string itemName = item.getClass().getName(item);
|
|
if (itemName != mSpellName && mSpellVisible)
|
|
{
|
|
mWeaponSpellTimer = 5.0f;
|
|
mSpellName = itemName;
|
|
mWeaponSpellBox->setCaption(mSpellName);
|
|
mWeaponSpellBox->setVisible(true);
|
|
}
|
|
|
|
mSpellStatus->setProgressRange(100);
|
|
mSpellStatus->setProgressPosition(chargePercent);
|
|
|
|
mSpellBox->setUserString("ToolTipType", "ItemPtr");
|
|
mSpellBox->setUserData(MWWorld::Ptr(item));
|
|
|
|
mSpellImage->setItem(item);
|
|
}
|
|
|
|
void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
|
|
{
|
|
std::string itemName = item.getClass().getName(item);
|
|
if (itemName != mWeaponName && mWeaponVisible)
|
|
{
|
|
mWeaponSpellTimer = 5.0f;
|
|
mWeaponName = itemName;
|
|
mWeaponSpellBox->setCaption(mWeaponName);
|
|
mWeaponSpellBox->setVisible(true);
|
|
}
|
|
|
|
mWeapBox->clearUserStrings();
|
|
mWeapBox->setUserString("ToolTipType", "ItemPtr");
|
|
mWeapBox->setUserData(MWWorld::Ptr(item));
|
|
|
|
mWeapStatus->setProgressRange(100);
|
|
mWeapStatus->setProgressPosition(durabilityPercent);
|
|
|
|
mWeapImage->setItem(item);
|
|
}
|
|
|
|
void HUD::unsetSelectedSpell()
|
|
{
|
|
std::string spellName = "#{sNone}";
|
|
if (spellName != mSpellName && mSpellVisible)
|
|
{
|
|
mWeaponSpellTimer = 5.0f;
|
|
mSpellName = spellName;
|
|
mWeaponSpellBox->setCaptionWithReplacing(mSpellName);
|
|
mWeaponSpellBox->setVisible(true);
|
|
}
|
|
|
|
mSpellStatus->setProgressRange(100);
|
|
mSpellStatus->setProgressPosition(0);
|
|
mSpellImage->setItem(MWWorld::Ptr());
|
|
mSpellBox->clearUserStrings();
|
|
}
|
|
|
|
void HUD::unsetSelectedWeapon()
|
|
{
|
|
std::string itemName = "#{sSkillHandtohand}";
|
|
if (itemName != mWeaponName && mWeaponVisible)
|
|
{
|
|
mWeaponSpellTimer = 5.0f;
|
|
mWeaponName = itemName;
|
|
mWeaponSpellBox->setCaptionWithReplacing(mWeaponName);
|
|
mWeaponSpellBox->setVisible(true);
|
|
}
|
|
|
|
mWeapStatus->setProgressRange(100);
|
|
mWeapStatus->setProgressPosition(0);
|
|
|
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
|
MWWorld::Ptr player = world->getPlayerPtr();
|
|
|
|
mWeapImage->setItem(MWWorld::Ptr());
|
|
std::string icon = (player.getClass().getNpcStats(player).isWerewolf()) ? "icons\\k\\tx_werewolf_hand.dds" : "icons\\k\\stealth_handtohand.dds";
|
|
mWeapImage->setIcon(icon);
|
|
|
|
mWeapBox->clearUserStrings();
|
|
mWeapBox->setUserString("ToolTipType", "Layout");
|
|
mWeapBox->setUserString("ToolTipLayout", "HandToHandToolTip");
|
|
mWeapBox->setUserString("Caption_HandToHandText", itemName);
|
|
mWeapBox->setUserString("ImageTexture_HandToHandImage", icon);
|
|
}
|
|
|
|
void HUD::setCrosshairVisible(bool visible)
|
|
{
|
|
mCrosshair->setVisible (visible);
|
|
}
|
|
|
|
void HUD::setCrosshairOwned(bool owned)
|
|
{
|
|
if(owned)
|
|
{
|
|
mCrosshair->changeWidgetSkin("HUD_Crosshair_Owned");
|
|
}
|
|
else
|
|
{
|
|
mCrosshair->changeWidgetSkin("HUD_Crosshair");
|
|
}
|
|
}
|
|
|
|
void HUD::setHmsVisible(bool visible)
|
|
{
|
|
mHealth->setVisible(visible);
|
|
mMagicka->setVisible(visible);
|
|
mStamina->setVisible(visible);
|
|
updatePositions();
|
|
}
|
|
|
|
void HUD::setWeapVisible(bool visible)
|
|
{
|
|
mWeapBox->setVisible(visible);
|
|
updatePositions();
|
|
}
|
|
|
|
void HUD::setSpellVisible(bool visible)
|
|
{
|
|
mSpellBox->setVisible(visible);
|
|
updatePositions();
|
|
}
|
|
|
|
void HUD::setSneakVisible(bool visible)
|
|
{
|
|
mSneakBox->setVisible(visible);
|
|
updatePositions();
|
|
}
|
|
|
|
void HUD::setEffectVisible(bool visible)
|
|
{
|
|
mEffectBox->setVisible (visible);
|
|
updatePositions();
|
|
}
|
|
|
|
void HUD::setMinimapVisible(bool visible)
|
|
{
|
|
mMinimapBox->setVisible (visible);
|
|
updatePositions();
|
|
}
|
|
|
|
void HUD::updatePositions()
|
|
{
|
|
int weapDx = 0, spellDx = 0, sneakDx = 0;
|
|
if (!mHealth->getVisible())
|
|
sneakDx = spellDx = weapDx = mWeapBoxBaseLeft - mHealthManaStaminaBaseLeft;
|
|
|
|
if (!mWeapBox->getVisible())
|
|
{
|
|
spellDx += mSpellBoxBaseLeft - mWeapBoxBaseLeft;
|
|
sneakDx = spellDx;
|
|
}
|
|
|
|
if (!mSpellBox->getVisible())
|
|
sneakDx += mSneakBoxBaseLeft - mSpellBoxBaseLeft;
|
|
|
|
mWeaponVisible = mWeapBox->getVisible();
|
|
mSpellVisible = mSpellBox->getVisible();
|
|
if (!mWeaponVisible && !mSpellVisible)
|
|
mWeaponSpellBox->setVisible(false);
|
|
|
|
mWeapBox->setPosition(mWeapBoxBaseLeft - weapDx, mWeapBox->getTop());
|
|
mSpellBox->setPosition(mSpellBoxBaseLeft - spellDx, mSpellBox->getTop());
|
|
mSneakBox->setPosition(mSneakBoxBaseLeft - sneakDx, mSneakBox->getTop());
|
|
|
|
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
|
|
// effect box can have variable width -> variable left coordinate
|
|
int effectsDx = 0;
|
|
if (!mMinimapBox->getVisible ())
|
|
effectsDx = mEffectBoxBaseRight - mMinimapBoxBaseRight;
|
|
|
|
mMapVisible = mMinimapBox->getVisible ();
|
|
if (!mMapVisible)
|
|
mCellNameBox->setVisible(false);
|
|
|
|
mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop());
|
|
}
|
|
|
|
void HUD::updateEnemyHealthBar()
|
|
{
|
|
MWWorld::Ptr enemy = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mEnemyActorId);
|
|
if (enemy.isEmpty())
|
|
return;
|
|
MWMechanics::CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
|
|
mEnemyHealth->setProgressRange(100);
|
|
// Health is usually cast to int before displaying. Actors die whenever they are < 1 health.
|
|
// Therefore any value < 1 should show as an empty health bar. We do the same in statswindow :)
|
|
mEnemyHealth->setProgressPosition(static_cast<size_t>(stats.getHealth().getRatio() * 100));
|
|
|
|
static const float fNPCHealthBarFade = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarFade")->mValue.getFloat();
|
|
if (fNPCHealthBarFade > 0.f)
|
|
mEnemyHealth->setAlpha(std::clamp(mEnemyHealthTimer / fNPCHealthBarFade, 0.f, 1.f));
|
|
|
|
}
|
|
|
|
void HUD::setEnemy(const MWWorld::Ptr &enemy)
|
|
{
|
|
mEnemyActorId = enemy.getClass().getCreatureStats(enemy).getActorId();
|
|
mEnemyHealthTimer = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarTime")->mValue.getFloat();
|
|
if (!mEnemyHealth->getVisible())
|
|
mWeaponSpellBox->setPosition(mWeaponSpellBox->getPosition() - MyGUI::IntPoint(0,20));
|
|
mEnemyHealth->setVisible(true);
|
|
updateEnemyHealthBar();
|
|
}
|
|
|
|
void HUD::resetEnemy()
|
|
{
|
|
mEnemyActorId = -1;
|
|
mEnemyHealthTimer = -1;
|
|
}
|
|
|
|
void HUD::clear()
|
|
{
|
|
unsetSelectedSpell();
|
|
unsetSelectedWeapon();
|
|
resetEnemy();
|
|
}
|
|
|
|
void HUD::customMarkerCreated(MyGUI::Widget *marker)
|
|
{
|
|
marker->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
|
}
|
|
|
|
void HUD::doorMarkerCreated(MyGUI::Widget *marker)
|
|
{
|
|
marker->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
|
}
|
|
|
|
}
|