1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 18:35:20 +00:00

Merge remote-tracking branch 'scrawl/master'

This commit is contained in:
Marc Zinnschlag 2014-04-26 18:05:04 +02:00
commit 5e7cd806c4
32 changed files with 197 additions and 163 deletions

View File

@ -45,9 +45,6 @@ namespace MWBase
virtual void goodbye() = 0; virtual void goodbye() = 0;
virtual MWWorld::Ptr getActor() const = 0;
///< Return the actor the player is currently talking to.
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const = 0; virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const = 0;
//calbacks for the GUI //calbacks for the GUI

View File

@ -468,11 +468,6 @@ namespace MWDialogue
mIsInChoice = true; mIsInChoice = true;
} }
MWWorld::Ptr DialogueManager::getActor() const
{
return mActor;
}
void DialogueManager::goodbye() void DialogueManager::goodbye()
{ {
mIsInChoice = true; mIsInChoice = true;

View File

@ -68,9 +68,6 @@ namespace MWDialogue
virtual void goodbye(); virtual void goodbye();
virtual MWWorld::Ptr getActor() const;
///< Return the actor the player is currently talking to.
virtual bool checkServiceRefused (); virtual bool checkServiceRefused ();
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const; virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const;

View File

@ -111,8 +111,14 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
// check cell // check cell
if (!info.mCell.empty()) if (!info.mCell.empty())
if (!Misc::StringUtils::ciEqual(player.getCell()->getCell()->mName, info.mCell)) {
// supports partial matches, just like getPcCell
const std::string& playerCell = player.getCell()->getCell()->mName;
bool match = playerCell.length()>=info.mCell.length() &&
Misc::StringUtils::ciEqual(playerCell.substr (0, info.mCell.length()), info.mCell);
if (!match)
return false; return false;
}
return true; return true;
} }

View File

@ -52,7 +52,7 @@ namespace MWGui
, mWeaponVisible(true) , mWeaponVisible(true)
, mSpellVisible(true) , mSpellVisible(true)
, mWorldMouseOver(false) , mWorldMouseOver(false)
, mEnemyHealthTimer(0) , mEnemyHealthTimer(-1)
, mIsDrowning(false) , mIsDrowning(false)
, mWeaponSpellTimer(0.f) , mWeaponSpellTimer(0.f)
, mDrowningFlashTheta(0.f) , mDrowningFlashTheta(0.f)
@ -639,4 +639,10 @@ namespace MWGui
updateEnemyHealthBar(); updateEnemyHealthBar();
} }
void HUD::resetEnemy()
{
mEnemy = MWWorld::Ptr();
mEnemyHealthTimer = -1;
}
} }

View File

@ -56,6 +56,7 @@ namespace MWGui
void update(); void update();
void setEnemy(const MWWorld::Ptr& enemy); void setEnemy(const MWWorld::Ptr& enemy);
void resetEnemy();
private: private:
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning; MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;

View File

@ -14,6 +14,8 @@
#include "../mwrender/globalmap.hpp" #include "../mwrender/globalmap.hpp"
#include "../components/esm/globalmap.hpp"
#include "widgets.hpp" #include "widgets.hpp"
namespace MWGui namespace MWGui
@ -436,7 +438,6 @@ namespace MWGui
worldY * mGlobalMapRender->getHeight()+6, worldY * mGlobalMapRender->getHeight()+6,
12, 12); 12, 12);
static int _counter=0; static int _counter=0;
MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage", MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter)); widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
@ -452,6 +453,11 @@ namespace MWGui
markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name); markerWidget->setUserString("Caption_TextOneLine", name);
CellId cell;
cell.first = x;
cell.second = y;
mMarkers.push_back(cell);
} }
void MapWindow::cellExplored(int x, int y) void MapWindow::cellExplored(int x, int y)
@ -580,6 +586,7 @@ namespace MWGui
void MapWindow::clear() void MapWindow::clear()
{ {
mMarkers.clear();
mGlobalMapRender->clear(); mGlobalMapRender->clear();
while (mEventBoxGlobal->getChildCount()) while (mEventBoxGlobal->getChildCount())
@ -590,19 +597,31 @@ namespace MWGui
void MapWindow::write(ESM::ESMWriter &writer) void MapWindow::write(ESM::ESMWriter &writer)
{ {
mGlobalMapRender->write(writer); ESM::GlobalMap map;
mGlobalMapRender->write(map);
map.mMarkers = mMarkers;
writer.startRecord(ESM::REC_GMAP);
map.save(writer);
writer.endRecord(ESM::REC_GMAP);
} }
void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type) void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type)
{ {
std::vector<std::pair<int, int> > exploredCells; if (type == ESM::REC_GMAP)
mGlobalMapRender->readRecord(reader, type, exploredCells);
for (std::vector<std::pair<int, int> >::iterator it = exploredCells.begin(); it != exploredCells.end(); ++it)
{ {
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second); ESM::GlobalMap map;
if (cell && !cell->mName.empty()) map.load(reader);
addVisitedLocation(cell->mName, it->first, it->second);
mGlobalMapRender->read(map);
for (std::vector<ESM::GlobalMap::CellId>::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it)
{
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
if (cell && !cell->mName.empty())
addVisitedLocation(cell->mName, it->first, it->second);
}
} }
} }
} }

View File

@ -55,6 +55,9 @@ namespace MWGui
bool mChanged; bool mChanged;
bool mFogOfWar; bool mFogOfWar;
typedef std::pair<int, int> CellId;
std::vector<CellId> mMarkers;
std::vector<MyGUI::ImageBox*> mMapWidgets; std::vector<MyGUI::ImageBox*> mMapWidgets;
std::vector<MyGUI::ImageBox*> mFogWidgets; std::vector<MyGUI::ImageBox*> mFogWidgets;

View File

@ -325,7 +325,6 @@ namespace MWGui
} }
store.setSelectedEnchantItem(it); store.setSelectedEnchantItem(it);
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
} }
} }

View File

@ -322,7 +322,6 @@ namespace MWGui
} }
store.setSelectedEnchantItem(it); store.setSelectedEnchantItem(it);
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
updateSpells(); updateSpells();
} }

View File

@ -187,7 +187,7 @@ namespace MWGui
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
SDL_ShowCursor(false); //SDL_ShowCursor(false);
mCursorManager->setEnabled(true); mCursorManager->setEnabled(true);
@ -289,6 +289,10 @@ namespace MWGui
void WindowManager::setNewGame(bool newgame) void WindowManager::setNewGame(bool newgame)
{ {
// This method will always be called after loading a savegame or starting a new game
// Reset enemy, it could be a dangling pointer from a previous game
mHud->resetEnemy();
if (newgame) if (newgame)
{ {
disallowAll(); disallowAll();

View File

@ -114,6 +114,7 @@ namespace MWInput
, mTimeIdle(0.f) , mTimeIdle(0.f)
, mOverencumberedMessageDelay(0.f) , mOverencumberedMessageDelay(0.f)
, mAlwaysRunActive(false) , mAlwaysRunActive(false)
, mControlsDisabled(false)
{ {
Ogre::RenderWindow* window = ogre.getWindow (); Ogre::RenderWindow* window = ogre.getWindow ();
@ -265,19 +266,20 @@ namespace MWInput
void InputManager::update(float dt, bool disableControls, bool disableEvents) void InputManager::update(float dt, bool disableControls, bool disableEvents)
{ {
mControlsDisabled = disableControls;
mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible()); mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
mInputManager->capture(disableEvents); mInputManager->capture(disableEvents);
// inject some fake mouse movement to force updating MyGUI's widget states // inject some fake mouse movement to force updating MyGUI's widget states
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel);
// update values of channels (as a result of pressed keys) if (mControlsDisabled)
if (!disableControls)
mInputBinder->update(dt);
if (disableControls)
return; return;
// update values of channels (as a result of pressed keys)
mInputBinder->update(dt);
bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console; && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console;
@ -484,7 +486,7 @@ namespace MWInput
if (text) if (text)
{ {
edit->addText(MyGUI::UString(text)); edit->insertText(MyGUI::UString(text), edit->getTextCursor());
SDL_free(text); SDL_free(text);
} }
} }
@ -509,7 +511,8 @@ namespace MWInput
} }
} }
mInputBinder->keyPressed (arg); if (!mControlsDisabled)
mInputBinder->keyPressed (arg);
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);

View File

@ -68,7 +68,7 @@ namespace MWInput
/// Clear all savegame-specific data /// Clear all savegame-specific data
virtual void clear(); virtual void clear();
virtual void update(float dt, bool disableControls, bool disableEvents=false); virtual void update(float dt, bool disableControls=false, bool disableEvents=false);
void setPlayer (MWWorld::Player* player) { mPlayer = player; } void setPlayer (MWWorld::Player* player) { mPlayer = player; }
@ -145,6 +145,8 @@ namespace MWInput
bool mInvertY; bool mInvertY;
bool mControlsDisabled;
float mCameraSensitivity; float mCameraSensitivity;
float mUISensitivity; float mUISensitivity;
float mCameraYMultiplier; float mCameraYMultiplier;

View File

@ -8,6 +8,7 @@
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"
#include "creaturestats.hpp"
namespace MWMechanics namespace MWMechanics
{ {
@ -30,6 +31,8 @@ namespace MWMechanics
Movement &movement = actor.getClass().getMovementSettings(actor); Movement &movement = actor.getClass().getMovementSettings(actor);
const ESM::Cell *cell = actor.getCell()->getCell(); const ESM::Cell *cell = actor.getCell()->getCell();
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false);
MWWorld::Ptr player = world->getPlayerPtr(); MWWorld::Ptr player = world->getPlayerPtr();
if(cell->mData.mX != player.getCell()->getCell()->mData.mX) if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
{ {

View File

@ -740,10 +740,6 @@ bool CharacterController::updateWeaponState()
MWBase::Environment::get().getWindowManager()->messageBox(resultMessage); MWBase::Environment::get().getWindowManager()->messageBox(resultMessage);
if(!resultSound.empty()) if(!resultSound.empty())
MWBase::Environment::get().getSoundManager()->playSound(resultSound, 1.0f, 1.0f); MWBase::Environment::get().getSoundManager()->playSound(resultSound, 1.0f, 1.0f);
// Set again, just to update the charge bar
if(item.getRefData().getCount())
MWBase::Environment::get().getWindowManager()->setSelectedWeapon(item);
} }
else if (ammunition) else if (ammunition)
{ {

View File

@ -325,6 +325,19 @@ namespace MWMechanics
winMgr->updateSkillArea(); winMgr->updateSkillArea();
winMgr->setValue("level", stats.getLevel()); winMgr->setValue("level", stats.getLevel());
// Update the equipped weapon icon
MWWorld::InventoryStore& inv = mWatched.getClass().getInventoryStore(mWatched);
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weapon == inv.end())
winMgr->unsetSelectedWeapon();
else
winMgr->setSelectedWeapon(*weapon);
// Update the selected spell icon
MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem();
if (enchantItem != inv.end())
winMgr->setSelectedEnchantItem(*enchantItem);
} }
if (mUpdatePlayer) if (mUpdatePlayer)

View File

@ -491,7 +491,7 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
if (iter->second.mExpelled) if (iter->second.mExpelled)
mExpelled.insert (iter->first); mExpelled.insert (iter->first);
if (iter->second.mRank) if (iter->second.mRank >= 0)
mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank)); mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank));
if (iter->second.mReputation) if (iter->second.mReputation)

View File

@ -575,7 +575,6 @@ namespace MWMechanics
{ {
if (mCaster.getRefData().getHandle() == "player") if (mCaster.getRefData().getHandle() == "player")
{ {
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); // Set again to show the modified charge
mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 3); mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 3);
} }
} }

View File

@ -231,9 +231,8 @@ namespace MWRender
mOverlayTexture->getBuffer()->blitFromMemory(pb); mOverlayTexture->getBuffer()->blitFromMemory(pb);
} }
void GlobalMap::write(ESM::ESMWriter &writer) void GlobalMap::write(ESM::GlobalMap& map)
{ {
ESM::GlobalMap map;
map.mBounds.mMinX = mMinX; map.mBounds.mMinX = mMinX;
map.mBounds.mMaxX = mMaxX; map.mBounds.mMaxX = mMaxX;
map.mBounds.mMinY = mMinY; map.mBounds.mMinY = mMinY;
@ -244,95 +243,68 @@ namespace MWRender
Ogre::DataStreamPtr encoded = image.encode("png"); Ogre::DataStreamPtr encoded = image.encode("png");
map.mImageData.resize(encoded->size()); map.mImageData.resize(encoded->size());
encoded->read(&map.mImageData[0], encoded->size()); encoded->read(&map.mImageData[0], encoded->size());
writer.startRecord(ESM::REC_GMAP);
map.save(writer);
writer.endRecord(ESM::REC_GMAP);
} }
void GlobalMap::readRecord(ESM::ESMReader &reader, int32_t type, std::vector<std::pair<int, int> >& exploredCells) void GlobalMap::read(ESM::GlobalMap& map)
{ {
if (type == ESM::REC_GMAP) const ESM::GlobalMap::Bounds& bounds = map.mBounds;
{
ESM::GlobalMap map;
map.load(reader);
const ESM::GlobalMap::Bounds& bounds = map.mBounds; if (bounds.mMaxX-bounds.mMinX <= 0)
return;
if (bounds.mMaxY-bounds.mMinY <= 0)
return;
if (bounds.mMaxX-bounds.mMinX <= 0) if (bounds.mMinX > bounds.mMaxX
return; || bounds.mMinY > bounds.mMaxY)
if (bounds.mMaxY-bounds.mMinY <= 0) throw std::runtime_error("invalid map bounds");
return;
if (bounds.mMinX > bounds.mMaxX Ogre::Image image;
|| bounds.mMinY > bounds.mMaxY) Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&map.mImageData[0], map.mImageData.size()));
throw std::runtime_error("invalid map bounds"); image.load(stream, "png");
Ogre::Image image; int xLength = (bounds.mMaxX-bounds.mMinX+1);
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&map.mImageData[0], map.mImageData.size())); int yLength = (bounds.mMaxY-bounds.mMinY+1);
image.load(stream, "png");
int xLength = (bounds.mMaxX-bounds.mMinX+1); // Size of one cell in image space
int yLength = (bounds.mMaxY-bounds.mMinY+1); int cellImageSizeSrc = image.getWidth() / xLength;
if (int(image.getHeight() / yLength) != cellImageSizeSrc)
throw std::runtime_error("cell size must be quadratic");
// Size of one cell in image space // If cell bounds of the currently loaded content and the loaded savegame do not match,
int cellImageSizeSrc = image.getWidth() / xLength; // we need to resize source/dest boxes to accommodate
if (int(image.getHeight() / yLength) != cellImageSizeSrc) // This means nonexisting cells will be dropped silently
throw std::runtime_error("cell size must be quadratic"); int cellImageSizeDst = 24;
// Determine which cells were explored by reading the image data // Completely off-screen? -> no need to blit anything
for (int x=0; x < xLength; ++x) if (bounds.mMaxX < mMinX
{ || bounds.mMaxY < mMinY
for (int y=0; y < yLength; ++y) || bounds.mMinX > mMaxX
{ || bounds.mMinY > mMaxY)
unsigned int imageX = (x) * cellImageSizeSrc; return;
// NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is
unsigned int imageY = (yLength - (y + 1)) * cellImageSizeSrc;
assert(imageX < image.getWidth()); int leftDiff = (mMinX - bounds.mMinX);
assert(imageY < image.getHeight()); int topDiff = (bounds.mMaxY - mMaxY);
int rightDiff = (bounds.mMaxX - mMaxX);
int bottomDiff = (mMinY - bounds.mMinY);
Ogre::Image::Box srcBox ( std::max(0, leftDiff * cellImageSizeSrc),
std::max(0, topDiff * cellImageSizeSrc),
std::min(image.getWidth(), image.getWidth() - rightDiff * cellImageSizeSrc),
std::min(image.getHeight(), image.getHeight() - bottomDiff * cellImageSizeSrc));
if (image.getColourAt(imageX, imageY, 0).a > 0) Ogre::Image::Box destBox ( std::max(0, -leftDiff * cellImageSizeDst),
exploredCells.push_back(std::make_pair(x+bounds.mMinX,y+bounds.mMinY)); std::max(0, -topDiff * cellImageSizeDst),
} std::min(mOverlayTexture->getWidth(), mOverlayTexture->getWidth() + rightDiff * cellImageSizeDst),
} std::min(mOverlayTexture->getHeight(), mOverlayTexture->getHeight() + bottomDiff * cellImageSizeDst));
// If cell bounds of the currently loaded content and the loaded savegame do not match, // Looks like there is no interface for blitting from memory with src/dst boxes.
// we need to resize source/dest boxes to accommodate // So we create a temporary texture for blitting.
// This means nonexisting cells will be dropped silently Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual("@temp",
int cellImageSizeDst = 24; Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, image.getWidth(),
image.getHeight(), 0, Ogre::PF_A8B8G8R8);
tex->loadImage(image);
// Completely off-screen? -> no need to blit anything mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox);
if (bounds.mMaxX < mMinX
|| bounds.mMaxY < mMinY
|| bounds.mMinX > mMaxX
|| bounds.mMinY > mMaxY)
return;
int leftDiff = (mMinX - bounds.mMinX); Ogre::TextureManager::getSingleton().remove("@temp");
int topDiff = (bounds.mMaxY - mMaxY);
int rightDiff = (bounds.mMaxX - mMaxX);
int bottomDiff = (mMinY - bounds.mMinY);
Ogre::Image::Box srcBox ( std::max(0, leftDiff * cellImageSizeSrc),
std::max(0, topDiff * cellImageSizeSrc),
std::min(image.getWidth(), image.getWidth() - rightDiff * cellImageSizeSrc),
std::min(image.getHeight(), image.getHeight() - bottomDiff * cellImageSizeSrc));
Ogre::Image::Box destBox ( std::max(0, -leftDiff * cellImageSizeDst),
std::max(0, -topDiff * cellImageSizeDst),
std::min(mOverlayTexture->getWidth(), mOverlayTexture->getWidth() + rightDiff * cellImageSizeDst),
std::min(mOverlayTexture->getHeight(), mOverlayTexture->getHeight() + bottomDiff * cellImageSizeDst));
// Looks like there is no interface for blitting from memory with src/dst boxes.
// So we create a temporary texture for blitting.
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual("@temp",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, image.getWidth(),
image.getHeight(), 0, Ogre::PF_A8B8G8R8);
tex->loadImage(image);
mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox);
Ogre::TextureManager::getSingleton().remove("@temp");
}
} }
} }

View File

@ -12,8 +12,7 @@ namespace Loading
namespace ESM namespace ESM
{ {
class ESMWriter; class GlobalMap;
class ESMReader;
} }
namespace MWRender namespace MWRender
@ -40,8 +39,8 @@ namespace MWRender
/// Clears the overlay /// Clears the overlay
void clear(); void clear();
void write (ESM::ESMWriter& writer); void write (ESM::GlobalMap& map);
void readRecord (ESM::ESMReader& reader, int32_t type, std::vector<std::pair<int, int> >& exploredCells); void read (ESM::GlobalMap& map);
private: private:
std::string mCacheDir; std::string mCacheDir;

View File

@ -68,7 +68,8 @@ namespace MWRender
float HeadAnimationTime::getValue() const float HeadAnimationTime::getValue() const
{ {
// TODO: Handle eye blinking (time is in the text keys) // TODO use time from text keys (Talk Start/Stop, Blink Start/Stop)
// TODO: Handle eye blinking
if (MWBase::Environment::get().getSoundManager()->sayDone(mReference)) if (MWBase::Environment::get().getSoundManager()->sayDone(mReference))
return 0; return 0;
else else

View File

@ -54,7 +54,10 @@ op 0x20025: AiFollowCell, explicit reference
op 0x20026: ModRegion op 0x20026: ModRegion
op 0x20027: RemoveSoulGem op 0x20027: RemoveSoulGem
op 0x20028: RemoveSoulGem, explicit reference op 0x20028: RemoveSoulGem, explicit reference
opcodes 0x20029-0x3ffff unused op 0x20029: PCRaiseRank, explicit reference
op 0x2002a: PCLowerRank, explicit reference
op 0x2002b: PCJoinFaction, explicit reference
opcodes 0x2002c-0x3ffff unused
Segment 4: Segment 4:
(not implemented yet) (not implemented yet)

View File

@ -29,10 +29,8 @@
namespace namespace
{ {
std::string getDialogueActorFaction() std::string getDialogueActorFaction(MWWorld::Ptr actor)
{ {
MWWorld::Ptr actor = MWBase::Environment::get().getDialogueManager()->getActor();
const MWMechanics::NpcStats &stats = MWWorld::Class::get (actor).getNpcStats (actor); const MWMechanics::NpcStats &stats = MWWorld::Class::get (actor).getNpcStats (actor);
if (stats.getFactionRanks().empty()) if (stats.getFactionRanks().empty())
@ -523,6 +521,7 @@ namespace MWScript
} }
}; };
template<class R>
class OpPCJoinFaction : public Interpreter::Opcode1 class OpPCJoinFaction : public Interpreter::Opcode1
{ {
public: public:
@ -533,7 +532,8 @@ namespace MWScript
if(arg0==0) if(arg0==0)
{ {
factionID = getDialogueActorFaction(); MWWorld::Ptr actor = R()(runtime);
factionID = getDialogueActorFaction(actor);
} }
else else
{ {
@ -552,6 +552,7 @@ namespace MWScript
} }
}; };
template<class R>
class OpPCRaiseRank : public Interpreter::Opcode1 class OpPCRaiseRank : public Interpreter::Opcode1
{ {
public: public:
@ -562,7 +563,8 @@ namespace MWScript
if(arg0==0) if(arg0==0)
{ {
factionID = getDialogueActorFaction(); MWWorld::Ptr actor = R()(runtime);
factionID = getDialogueActorFaction(actor);
} }
else else
{ {
@ -585,6 +587,7 @@ namespace MWScript
} }
}; };
template<class R>
class OpPCLowerRank : public Interpreter::Opcode1 class OpPCLowerRank : public Interpreter::Opcode1
{ {
public: public:
@ -595,7 +598,8 @@ namespace MWScript
if(arg0==0) if(arg0==0)
{ {
factionID = getDialogueActorFaction(); MWWorld::Ptr actor = R()(runtime);
factionID = getDialogueActorFaction(actor);
} }
else else
{ {
@ -1180,9 +1184,12 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell<ImplicitRef>); interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>); interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRank,new OpPCRaiseRank); interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRank,new OpPCRaiseRank<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCLowerRank,new OpPCLowerRank); interpreter.installSegment3(Compiler::Stats::opcodePCLowerRank,new OpPCLowerRank<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCJoinFaction,new OpPCJoinFaction); interpreter.installSegment3(Compiler::Stats::opcodePCJoinFaction,new OpPCJoinFaction<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRankExplicit,new OpPCRaiseRank<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCLowerRankExplicit,new OpPCLowerRank<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCJoinFactionExplicit,new OpPCJoinFaction<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodeGetPCRank,new OpGetPCRank<ImplicitRef>); interpreter.installSegment3(Compiler::Stats::opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>); interpreter.installSegment3(Compiler::Stats::opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>);

View File

@ -335,13 +335,6 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr();
//Update the weapon icon in the hud with whatever the player is currently holding.
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr);
MWWorld::ContainerStoreIterator item = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (item != invStore.end())
MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*item);
ESM::CellId cellId = ptr.getCell()->getCell()->getCellId(); ESM::CellId cellId = ptr.getCell()->getCell()->getCellId();
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition()); MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition());

View File

@ -52,7 +52,7 @@ namespace
iter!=collection.mList.end(); ++iter) iter!=collection.mList.end(); ++iter)
{ {
if (iter->mData.getCount()==0 && iter->mRef.mRefNum.mContentFile==-1) if (iter->mData.getCount()==0 && iter->mRef.mRefNum.mContentFile==-1)
continue; // deleted file that did not came from a content file -> ignore continue; // deleted reference that did not come from a content file -> ignore
RecordType state; RecordType state;
iter->save (state); iter->save (state);
@ -72,13 +72,17 @@ namespace
RecordType state; RecordType state;
state.load (reader); state.load (reader);
std::map<int, int>::const_iterator iter = // If the reference came from a content file, make sure this content file is loaded
contentFileMap.find (state.mRef.mRefNum.mContentFile); if (state.mRef.mRefNum.mContentFile != -1)
{
std::map<int, int>::const_iterator iter =
contentFileMap.find (state.mRef.mRefNum.mContentFile);
if (iter==contentFileMap.end()) if (iter==contentFileMap.end())
return; // content file has been removed -> skip return; // content file has been removed -> skip
state.mRef.mRefNum.mContentFile = iter->second; state.mRef.mRefNum.mContentFile = iter->second;
}
if (!MWWorld::LiveCellRef<T>::checkState (state)) if (!MWWorld::LiveCellRef<T>::checkState (state))
return; // not valid anymore with current content files -> skip return; // not valid anymore with current content files -> skip

View File

@ -8,7 +8,6 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
@ -150,10 +149,6 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite
fireEquipmentChangedEvent(); fireEquipmentChangedEvent();
updateMagicEffects(actor); updateMagicEffects(actor);
// Update HUD icon for player weapon
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*getSlot(slot));
} }
void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor)
@ -494,7 +489,6 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
&& *mSelectedEnchantItem == item && actor.getRefData().getHandle() == "player") && *mSelectedEnchantItem == item && actor.getRefData().getHandle() == "player")
{ {
mSelectedEnchantItem = end(); mSelectedEnchantItem = end();
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
} }
updateRechargingItems(); updateRechargingItems();
@ -532,18 +526,9 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c
if (script != "") if (script != "")
(*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0); (*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
// Update HUD icon when removing player weapon or selected enchanted item.
// We have to check for both as the weapon could also be the enchanted item.
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
{
// weapon
MWBase::Environment::get().getWindowManager()->unsetSelectedWeapon();
}
if ((mSelectedEnchantItem != end()) && (mSelectedEnchantItem == it)) if ((mSelectedEnchantItem != end()) && (mSelectedEnchantItem == it))
{ {
// enchanted item
mSelectedEnchantItem = end(); mSelectedEnchantItem = end();
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
} }
} }

View File

@ -2056,7 +2056,6 @@ namespace MWWorld
{ {
// Update the GUI only when called on the player // Update the GUI only when called on the player
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
windowManager->unsetSelectedWeapon();
if (werewolf) if (werewolf)
{ {

View File

@ -409,9 +409,9 @@ namespace Compiler
opcodeResurrectExplicit); opcodeResurrectExplicit);
extensions.registerFunction ("getspell", 'l', "c", opcodeGetSpell, opcodeGetSpellExplicit); extensions.registerFunction ("getspell", 'l', "c", opcodeGetSpell, opcodeGetSpellExplicit);
extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank); extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank, opcodePCRaiseRankExplicit);
extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank); extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank, opcodePCLowerRankExplicit);
extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction); extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction, opcodePCJoinFactionExplicit);
extensions.registerInstruction ("moddisposition","l",opcodeModDisposition, extensions.registerInstruction ("moddisposition","l",opcodeModDisposition,
opcodeModDispositionExplicit); opcodeModDispositionExplicit);
extensions.registerInstruction ("setdisposition","l",opcodeSetDisposition, extensions.registerInstruction ("setdisposition","l",opcodeSetDisposition,

View File

@ -330,6 +330,10 @@ namespace Compiler
const int opcodePCRaiseRank = 0x2000b; const int opcodePCRaiseRank = 0x2000b;
const int opcodePCLowerRank = 0x2000c; const int opcodePCLowerRank = 0x2000c;
const int opcodePCJoinFaction = 0x2000d; const int opcodePCJoinFaction = 0x2000d;
const int opcodePCRaiseRankExplicit = 0x20029;
const int opcodePCLowerRankExplicit = 0x2002a;
const int opcodePCJoinFactionExplicit = 0x2002b;
const int opcodeGetPCRank = 0x2000e; const int opcodeGetPCRank = 0x2000e;
const int opcodeGetPCRankExplicit = 0x2000f; const int opcodeGetPCRankExplicit = 0x2000f;
const int opcodeModDisposition = 0x200014d; const int opcodeModDisposition = 0x200014d;

View File

@ -14,6 +14,15 @@ void ESM::GlobalMap::load (ESMReader &esm)
esm.getSubHeader(); esm.getSubHeader();
mImageData.resize(esm.getSubSize()); mImageData.resize(esm.getSubSize());
esm.getExact(&mImageData[0], mImageData.size()); esm.getExact(&mImageData[0], mImageData.size());
while (esm.isNextSub("MRK_"))
{
esm.getSubHeader();
CellId cell;
esm.getT(cell.first);
esm.getT(cell.second);
mMarkers.push_back(cell);
}
} }
void ESM::GlobalMap::save (ESMWriter &esm) const void ESM::GlobalMap::save (ESMWriter &esm) const
@ -23,4 +32,12 @@ void ESM::GlobalMap::save (ESMWriter &esm) const
esm.startSubRecord("DATA"); esm.startSubRecord("DATA");
esm.write(&mImageData[0], mImageData.size()); esm.write(&mImageData[0], mImageData.size());
esm.endRecord("DATA"); esm.endRecord("DATA");
for (std::vector<CellId>::const_iterator it = mMarkers.begin(); it != mMarkers.end(); ++it)
{
esm.startSubRecord("MRK_");
esm.writeT(it->first);
esm.writeT(it->second);
esm.endRecord("MRK_");
}
} }

View File

@ -25,6 +25,9 @@ namespace ESM
std::vector<char> mImageData; std::vector<char> mImageData;
typedef std::pair<int, int> CellId;
std::vector<CellId> mMarkers;
void load (ESMReader &esm); void load (ESMReader &esm);
void save (ESMWriter &esm) const; void save (ESMWriter &esm) const;
}; };

View File

@ -199,6 +199,11 @@ struct KeyListT {
key.mContinuity = nif->getFloat(); key.mContinuity = nif->getFloat();
} }
} }
else if (mInterpolationType == 0)
{
if (count != 0)
nif->file->fail("Interpolation type 0 doesn't work with keys");
}
else else
nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType));
} }