mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 09:23:52 +00:00
3bd8aa82fe
Whenever an item is added to or removed from the player's ContainerStore, that player sends a PlayerInventory packet with just that addition or removal.
This eliminates all the unnecessary packet spam related to oversized PlayerInventory packets that had existed in one form or another since the initial implementation of inventory sync in 1b259e2d33
Additionally, move booleans from BasePlayer to LocalPlayer when they are only needed on the client, and make the usage of the isReceivingQuickKeys boolean consistent with the new isReceivingInventory boolean by having them both in the processors of their associated packets.
693 lines
24 KiB
C++
693 lines
24 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>
|
|
|
|
/*
|
|
Start of tes3mp addition
|
|
|
|
Include additional headers for multiplayer purposes
|
|
*/
|
|
#include "../mwmp/Main.hpp"
|
|
#include "../mwmp/Networking.hpp"
|
|
#include "../mwmp/ObjectList.hpp"
|
|
#include "../mwworld/cellstore.hpp"
|
|
/*
|
|
End of tes3mp addition
|
|
*/
|
|
|
|
#include <components/settings/settings.hpp>
|
|
#include <components/openmw-mp/Log.hpp>
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/windowmanager.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwworld/class.hpp"
|
|
#include "../mwworld/esmstore.hpp"
|
|
|
|
#include "../mwmechanics/creaturestats.hpp"
|
|
#include "../mwmechanics/npcstats.hpp"
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
|
|
#include "inventorywindow.hpp"
|
|
#include "spellicons.hpp"
|
|
#include "itemmodel.hpp"
|
|
#include "draganddrop.hpp"
|
|
|
|
#include "itemmodel.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() {}
|
|
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false)
|
|
{
|
|
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);
|
|
if (setNewOwner)
|
|
dropped.getCellRef().setOwner("");
|
|
|
|
/*
|
|
Start of tes3mp addition
|
|
|
|
Send an ID_OBJECT_PLACE packet every time an object is dropped into the world from
|
|
the inventory screen
|
|
*/
|
|
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
objectList->reset();
|
|
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
|
|
objectList->addObjectPlace(dropped, true);
|
|
objectList->sendObjectPlace();
|
|
/*
|
|
End of tes3mp addition
|
|
*/
|
|
|
|
/*
|
|
Start of tes3mp change (major)
|
|
|
|
Instead of actually keeping this object as is, delete it after sending the packet
|
|
and wait for the server to send it back with a unique mpNum of its own
|
|
*/
|
|
MWBase::Environment::get().getWorld()->deleteObject(dropped);
|
|
/*
|
|
End of tes3mp change (major)
|
|
*/
|
|
|
|
return dropped;
|
|
}
|
|
|
|
virtual void removeItem (const ItemStack& item, size_t count) { throw std::runtime_error("removeItem not implemented"); }
|
|
virtual ModelIndex getIndex (ItemStack item) { throw std::runtime_error("getIndex not implemented"); }
|
|
virtual void update() {}
|
|
virtual size_t getItemCount() { return 0; }
|
|
virtual ItemStack getItem (ModelIndex index) { throw std::runtime_error("getItem not implemented"); }
|
|
|
|
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(NULL)
|
|
, mMagicka(NULL)
|
|
, mStamina(NULL)
|
|
, mDrowning(NULL)
|
|
, mWeapImage(NULL)
|
|
, mSpellImage(NULL)
|
|
, mWeapStatus(NULL)
|
|
, mSpellStatus(NULL)
|
|
, mEffectBox(NULL)
|
|
, mMinimap(NULL)
|
|
, mCrosshair(NULL)
|
|
, mCellNameBox(NULL)
|
|
, mDrowningFrame(NULL)
|
|
, mDrowningFlash(NULL)
|
|
, 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)
|
|
{
|
|
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
|
|
|
|
// 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(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");
|
|
|
|
int mapSize = std::max(1, Settings::Manager::getInt("local map hud widget size", "Map"));
|
|
int cellDistance = std::max(1, Settings::Manager::getInt("local map cell distance", "Map"));
|
|
LocalMapBase::init(mMinimap, mCompass, mapSize, cellDistance);
|
|
|
|
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)
|
|
{
|
|
mDrowningFrame->setVisible(visible);
|
|
}
|
|
|
|
void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
|
{
|
|
if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ())
|
|
return;
|
|
|
|
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, NULL);
|
|
|
|
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
|
}
|
|
else
|
|
{
|
|
GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
|
|
|
|
if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) )
|
|
return;
|
|
|
|
MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject();
|
|
|
|
if (mode == GM_Console)
|
|
MWBase::Environment::get().getWindowManager()->setConsoleSelectedObject(object);
|
|
else if ((mode == GM_Container) || (mode == GM_Inventory))
|
|
{
|
|
// pick up object
|
|
if (!object.isEmpty())
|
|
MWBase::Environment::get().getWindowManager()->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));
|
|
}
|
|
|
|
if (mIsDrowning)
|
|
mDrowningFlashTheta += dt * osg::PI*2;
|
|
|
|
mSpellIcons->updateWidgets(mEffectBox, true);
|
|
|
|
if (mEnemyActorId != -1 && mEnemyHealth->getVisible())
|
|
{
|
|
updateEnemyHealthBar();
|
|
}
|
|
|
|
if (mIsDrowning)
|
|
{
|
|
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 = MWBase::Environment::get().getWindowManager()->correctIconPath(icon);
|
|
|
|
mSpellImage->setItem(MWWorld::Ptr());
|
|
mSpellImage->setIcon(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 = (viewSize.width - mMinimapBoxBaseRight) - (viewSize.width - mEffectBoxBaseRight);
|
|
|
|
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().getCurrent() / stats.getHealth().getModified() * 100));
|
|
|
|
static const float fNPCHealthBarFade = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarFade")->getFloat();
|
|
if (fNPCHealthBarFade > 0.f)
|
|
mEnemyHealth->setAlpha(std::max(0.f, std::min(1.f, mEnemyHealthTimer/fNPCHealthBarFade)));
|
|
|
|
}
|
|
|
|
void HUD::setEnemy(const MWWorld::Ptr &enemy)
|
|
{
|
|
mEnemyActorId = enemy.getClass().getCreatureStats(enemy).getActorId();
|
|
mEnemyHealthTimer = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarTime")->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);
|
|
}
|
|
|
|
}
|