mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-01 12:45:36 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
3992125b61
29 changed files with 249 additions and 116 deletions
|
@ -281,9 +281,12 @@ namespace MWClass
|
|||
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
|
||||
}
|
||||
|
||||
bool Container::canLock(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MWWorld::Ptr
|
||||
Container::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
|
||||
MWWorld::Ptr Container::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Container> *ref =
|
||||
ptr.get<ESM::Container>();
|
||||
|
@ -291,8 +294,7 @@ namespace MWClass
|
|||
return MWWorld::Ptr(&cell.get<ESM::Container>().insert(*ref), &cell);
|
||||
}
|
||||
|
||||
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
const
|
||||
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
|
||||
{
|
||||
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
|
||||
|
||||
|
@ -307,8 +309,7 @@ namespace MWClass
|
|||
readState (state2.mInventory);
|
||||
}
|
||||
|
||||
void Container::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||
const
|
||||
void Container::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const
|
||||
{
|
||||
ESM::ContainerState& state2 = dynamic_cast<ESM::ContainerState&> (state);
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace MWClass
|
|||
virtual void unlock (const MWWorld::Ptr& ptr) const;
|
||||
///< Unlock object
|
||||
|
||||
virtual bool canLock(const MWWorld::Ptr &ptr) const;
|
||||
|
||||
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
const;
|
||||
///< Read additional state from \a state into \a ptr.
|
||||
|
|
|
@ -207,6 +207,11 @@ namespace MWClass
|
|||
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
|
||||
}
|
||||
|
||||
bool Door::canLock(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Door::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Door> *ref =
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace MWClass
|
|||
virtual void unlock (const MWWorld::Ptr& ptr) const;
|
||||
///< Unlock object
|
||||
|
||||
virtual bool canLock(const MWWorld::Ptr &ptr) const;
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@ namespace MWGui
|
|||
};
|
||||
}
|
||||
|
||||
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
|
||||
void CharacterCreation::selectPickedClass()
|
||||
{
|
||||
if (mPickClassDialog)
|
||||
{
|
||||
|
@ -332,20 +332,18 @@ namespace MWGui
|
|||
}
|
||||
|
||||
updatePlayerHealth();
|
||||
}
|
||||
|
||||
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
selectPickedClass();
|
||||
|
||||
handleDialogDone(CSE_ClassChosen, GM_Birth);
|
||||
}
|
||||
|
||||
void CharacterCreation::onPickClassDialogBack()
|
||||
{
|
||||
if (mPickClassDialog)
|
||||
{
|
||||
const std::string classId = mPickClassDialog->getClassId();
|
||||
if (!classId.empty())
|
||||
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId);
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog);
|
||||
mPickClassDialog = 0;
|
||||
}
|
||||
selectPickedClass();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
||||
|
@ -390,29 +388,7 @@ namespace MWGui
|
|||
handleDialogDone(CSE_NameChosen, GM_Race);
|
||||
}
|
||||
|
||||
void CharacterCreation::onRaceDialogBack()
|
||||
{
|
||||
if (mRaceDialog)
|
||||
{
|
||||
const ESM::NPC &data = mRaceDialog->getResult();
|
||||
mPlayerRaceId = data.mRace;
|
||||
if (!mPlayerRaceId.empty()) {
|
||||
MWBase::Environment::get().getMechanicsManager()->setPlayerRace(
|
||||
data.mRace,
|
||||
data.isMale(),
|
||||
data.mHead,
|
||||
data.mHair
|
||||
);
|
||||
}
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
|
||||
mRaceDialog = 0;
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
|
||||
}
|
||||
|
||||
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
|
||||
void CharacterCreation::selectRace()
|
||||
{
|
||||
if (mRaceDialog)
|
||||
{
|
||||
|
@ -433,11 +409,24 @@ namespace MWGui
|
|||
}
|
||||
|
||||
updatePlayerHealth();
|
||||
}
|
||||
|
||||
void CharacterCreation::onRaceDialogBack()
|
||||
{
|
||||
selectRace();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
|
||||
}
|
||||
|
||||
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
selectRace();
|
||||
|
||||
handleDialogDone(CSE_RaceChosen, GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
|
||||
void CharacterCreation::selectBirthSign()
|
||||
{
|
||||
if (mBirthSignDialog)
|
||||
{
|
||||
|
@ -449,24 +438,24 @@ namespace MWGui
|
|||
}
|
||||
|
||||
updatePlayerHealth();
|
||||
}
|
||||
|
||||
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
selectBirthSign();
|
||||
|
||||
handleDialogDone(CSE_BirthSignChosen, GM_Review);
|
||||
}
|
||||
|
||||
void CharacterCreation::onBirthSignDialogBack()
|
||||
{
|
||||
if (mBirthSignDialog)
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId());
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog);
|
||||
mBirthSignDialog = 0;
|
||||
}
|
||||
selectBirthSign();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
|
||||
void CharacterCreation::selectCreatedClass()
|
||||
{
|
||||
if (mCreateClassDialog)
|
||||
{
|
||||
|
@ -495,19 +484,23 @@ namespace MWGui
|
|||
mPlayerClass = klass;
|
||||
MWBase::Environment::get().getWindowManager()->setPlayerClass(klass);
|
||||
|
||||
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
|
||||
// Do not delete dialog, so that choices are remembered in case we want to go back and adjust them later
|
||||
mCreateClassDialog->setVisible(false);
|
||||
}
|
||||
|
||||
updatePlayerHealth();
|
||||
}
|
||||
|
||||
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
|
||||
{
|
||||
selectCreatedClass();
|
||||
|
||||
handleDialogDone(CSE_ClassChosen, GM_Birth);
|
||||
}
|
||||
|
||||
void CharacterCreation::onCreateClassDialogBack()
|
||||
{
|
||||
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
|
||||
mCreateClassDialog->setVisible(false);
|
||||
// not done in MW, but we do it for consistency with the other dialogs
|
||||
selectCreatedClass();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
||||
|
@ -631,18 +624,7 @@ namespace MWGui
|
|||
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps(mGenerateClassStep).mSound);
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassBack()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
|
||||
mGenerateClassResultDialog = 0;
|
||||
|
||||
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
|
||||
void CharacterCreation::selectGeneratedClass()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
|
||||
mGenerateClassResultDialog = 0;
|
||||
|
@ -656,6 +638,19 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass);
|
||||
|
||||
updatePlayerHealth();
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassBack()
|
||||
{
|
||||
selectGeneratedClass();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
|
||||
{
|
||||
selectGeneratedClass();
|
||||
|
||||
handleDialogDone(CSE_ClassChosen, GM_Birth);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ namespace MWGui
|
|||
//Race dialog
|
||||
void onRaceDialogDone(WindowBase* parWindow);
|
||||
void onRaceDialogBack();
|
||||
void selectRace();
|
||||
|
||||
//Class dialogs
|
||||
void onClassChoice(int _index);
|
||||
|
@ -94,10 +95,14 @@ namespace MWGui
|
|||
void onClassQuestionChosen(int _index);
|
||||
void onGenerateClassBack();
|
||||
void onGenerateClassDone(WindowBase* parWindow);
|
||||
void selectGeneratedClass();
|
||||
void selectCreatedClass();
|
||||
void selectPickedClass();
|
||||
|
||||
//Birthsign dialog
|
||||
void onBirthSignDialogDone(WindowBase* parWindow);
|
||||
void onBirthSignDialogBack();
|
||||
void selectBirthSign();
|
||||
|
||||
//Review dialog
|
||||
void onReviewDialogDone(WindowBase* parWindow);
|
||||
|
|
|
@ -119,7 +119,12 @@ namespace MWGui
|
|||
{
|
||||
mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||
mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr());
|
||||
mSortModel = new SortFilterItemModel(mTradeModel);
|
||||
|
||||
if (mSortModel) // reuse existing SortModel when possible to keep previous category/filter settings
|
||||
mSortModel->setSourceModel(mTradeModel);
|
||||
else
|
||||
mSortModel = new SortFilterItemModel(mTradeModel);
|
||||
|
||||
mItemView->setModel(mSortModel);
|
||||
|
||||
mPreview->updatePtr(mPtr);
|
||||
|
|
|
@ -120,6 +120,11 @@ namespace MWGui
|
|||
}
|
||||
|
||||
|
||||
ProxyItemModel::ProxyItemModel()
|
||||
: mSourceModel(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
ProxyItemModel::~ProxyItemModel()
|
||||
{
|
||||
delete mSourceModel;
|
||||
|
@ -164,4 +169,18 @@ namespace MWGui
|
|||
return mSourceModel->getIndex(item);
|
||||
}
|
||||
|
||||
void ProxyItemModel::setSourceModel(ItemModel *sourceModel)
|
||||
{
|
||||
if (mSourceModel == sourceModel)
|
||||
return;
|
||||
|
||||
if (mSourceModel)
|
||||
{
|
||||
delete mSourceModel;
|
||||
mSourceModel = NULL;
|
||||
}
|
||||
|
||||
mSourceModel = sourceModel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,11 +80,15 @@ namespace MWGui
|
|||
class ProxyItemModel : public ItemModel
|
||||
{
|
||||
public:
|
||||
ProxyItemModel();
|
||||
virtual ~ProxyItemModel();
|
||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||
virtual void removeItem (const ItemStack& item, size_t count);
|
||||
virtual ModelIndex getIndex (ItemStack item);
|
||||
|
||||
/// @note Takes ownership of the passed pointer.
|
||||
void setSourceModel(ItemModel* sourceModel);
|
||||
|
||||
ModelIndex mapToSource (ModelIndex index);
|
||||
ModelIndex mapFromSource (ModelIndex index);
|
||||
protected:
|
||||
|
|
|
@ -30,8 +30,12 @@ ItemView::~ItemView()
|
|||
|
||||
void ItemView::setModel(ItemModel *model)
|
||||
{
|
||||
if (mModel == model)
|
||||
return;
|
||||
|
||||
delete mModel;
|
||||
mModel = model;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace
|
|||
DisplayStateStack mStates;
|
||||
Book mTopicIndexBook;
|
||||
bool mQuestMode;
|
||||
bool mOptionsMode;
|
||||
bool mAllQuests;
|
||||
|
||||
template <typename T>
|
||||
|
@ -182,6 +183,7 @@ namespace
|
|||
|
||||
mQuestMode = false;
|
||||
mAllQuests = false;
|
||||
mOptionsMode = false;
|
||||
}
|
||||
|
||||
void adjustButton (char const * name, bool optional = false)
|
||||
|
@ -244,6 +246,7 @@ namespace
|
|||
|
||||
void setBookMode ()
|
||||
{
|
||||
mOptionsMode = false;
|
||||
setVisible (OptionsBTN, true);
|
||||
setVisible (OptionsOverlay, false);
|
||||
|
||||
|
@ -253,6 +256,8 @@ namespace
|
|||
|
||||
void setOptionsMode ()
|
||||
{
|
||||
mOptionsMode = true;
|
||||
|
||||
setVisible (OptionsBTN, false);
|
||||
setVisible (OptionsOverlay, true);
|
||||
|
||||
|
@ -508,6 +513,8 @@ namespace
|
|||
|
||||
void notifyNextPage(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (mOptionsMode)
|
||||
return;
|
||||
if (!mStates.empty ())
|
||||
{
|
||||
unsigned int & page = mStates.top ().mPage;
|
||||
|
@ -523,6 +530,8 @@ namespace
|
|||
|
||||
void notifyPrevPage(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (mOptionsMode)
|
||||
return;
|
||||
if (!mStates.empty ())
|
||||
{
|
||||
unsigned int & page = mStates.top ().mPage;
|
||||
|
|
|
@ -783,7 +783,7 @@ namespace MWGui
|
|||
MyGUI::Widget* markerWidget = mGlobalMap->createWidget<MyGUI::Widget>("MarkerButton",
|
||||
widgetCoord, MyGUI::Align::Default);
|
||||
|
||||
markerWidget->setUserString("Caption_TextOneLine", name);
|
||||
markerWidget->setUserString("Caption_TextOneLine", "#{sCell=" + name + "}");
|
||||
|
||||
setGlobalMapMarkerTooltip(markerWidget, x, y);
|
||||
|
||||
|
|
|
@ -190,7 +190,8 @@ namespace MWGui
|
|||
|
||||
void renderGlobalMap(Loading::Listener* loadingListener);
|
||||
|
||||
// adds the marker to the global map
|
||||
/// adds the marker to the global map
|
||||
/// @param name The ESM::Cell::mName
|
||||
void addVisitedLocation(const std::string& name, int x, int y);
|
||||
|
||||
// reveals this cell's map on the global map
|
||||
|
|
|
@ -347,8 +347,8 @@ namespace MWGui
|
|||
char buffer[size];
|
||||
if (std::strftime(buffer, size, "%x %X", timeinfo) > 0)
|
||||
text << buffer << "\n";
|
||||
text << "Level " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
|
||||
text << mCurrentSlot->mProfile.mPlayerCell << "\n";
|
||||
text << "#{sLevel} " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
|
||||
text << "#{sCell=" << mCurrentSlot->mProfile.mPlayerCell << "}\n";
|
||||
// text << "Time played: " << slot->mProfile.mTimePlayed << "\n";
|
||||
|
||||
int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour);
|
||||
|
|
|
@ -71,7 +71,6 @@ namespace MWGui
|
|||
SortFilterItemModel::SortFilterItemModel(ItemModel *sourceModel)
|
||||
: mCategory(Category_All)
|
||||
, mFilter(0)
|
||||
, mShowEquipped(true)
|
||||
, mSortByType(true)
|
||||
{
|
||||
mSourceModel = sourceModel;
|
||||
|
@ -91,9 +90,6 @@ namespace MWGui
|
|||
{
|
||||
MWWorld::Ptr base = item.mBase;
|
||||
|
||||
if (item.mType == ItemStack::Type_Equipped && !mShowEquipped)
|
||||
return false;
|
||||
|
||||
int category = 0;
|
||||
if (base.getTypeName() == typeid(ESM::Armor).name()
|
||||
|| base.getTypeName() == typeid(ESM::Clothing).name())
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace MWGui
|
|||
|
||||
void setCategory (int category);
|
||||
void setFilter (int filter);
|
||||
void setShowEquipped (bool show) { mShowEquipped = show; }
|
||||
|
||||
/// Use ItemStack::Type for sorting?
|
||||
void setSortByType(bool sort) { mSortByType = sort; }
|
||||
|
@ -49,7 +48,6 @@ namespace MWGui
|
|||
|
||||
int mCategory;
|
||||
int mFilter;
|
||||
bool mShowEquipped;
|
||||
bool mSortByType;
|
||||
};
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace MWGui
|
|||
// figure out if player will be woken while sleeping
|
||||
int x = Misc::Rng::rollDice(hoursToWait);
|
||||
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->getFloat();
|
||||
if (x < fSleepRandMod * hoursToWait)
|
||||
if (x < static_cast<int>(fSleepRandMod * hoursToWait))
|
||||
{
|
||||
float fSleepRestMod = world->getStore().get<ESM::GameSetting>().find("fSleepRestMod")->getFloat();
|
||||
mInterruptAt = hoursToWait - int(fSleepRestMod * hoursToWait);
|
||||
|
|
|
@ -993,7 +993,7 @@ namespace MWGui
|
|||
if (cell->getCell()->isExterior())
|
||||
{
|
||||
if (!cell->getCell()->mName.empty())
|
||||
mMap->addVisitedLocation ("#{sCell=" + name + "}", cell->getCell()->getGridX (), cell->getCell()->getGridY ());
|
||||
mMap->addVisitedLocation (name, cell->getCell()->getGridX (), cell->getCell()->getGridY ());
|
||||
|
||||
mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY());
|
||||
}
|
||||
|
|
|
@ -247,15 +247,16 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
|||
bool block = mPtr.getClass().getCreatureStats(mPtr).getBlock();
|
||||
if(mHitState == CharState_None)
|
||||
{
|
||||
if (mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() < 0
|
||||
if ((mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() < 0
|
||||
|| mPtr.getClass().getCreatureStats(mPtr).getFatigue().getBase() == 0)
|
||||
&& mAnimation->hasAnimation("knockout"))
|
||||
{
|
||||
mHitState = CharState_KnockOut;
|
||||
mCurrentHit = "knockout";
|
||||
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, false, 1, "start", "stop", 0.0f, ~0ul);
|
||||
mPtr.getClass().getCreatureStats(mPtr).setKnockedDown(true);
|
||||
}
|
||||
else if(knockdown)
|
||||
else if(knockdown && mAnimation->hasAnimation("knockdown"))
|
||||
{
|
||||
mHitState = CharState_KnockDown;
|
||||
mCurrentHit = "knockdown";
|
||||
|
@ -263,11 +264,15 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
|||
}
|
||||
else if (recovery)
|
||||
{
|
||||
mHitState = CharState_Hit;
|
||||
mCurrentHit = chooseRandomGroup("hit");
|
||||
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::BlendMask_All, true, 1, "start", "stop", 0.0f, 0);
|
||||
std::string anim = chooseRandomGroup("hit");
|
||||
if (mAnimation->hasAnimation(anim))
|
||||
{
|
||||
mHitState = CharState_Hit;
|
||||
mCurrentHit = anim;
|
||||
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::BlendMask_All, true, 1, "start", "stop", 0.0f, 0);
|
||||
}
|
||||
}
|
||||
else if (block)
|
||||
else if (block && mAnimation->hasAnimation("shield"))
|
||||
{
|
||||
mHitState = CharState_Block;
|
||||
mCurrentHit = "shield";
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace MWMechanics
|
|||
void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick,
|
||||
std::string& resultMessage, std::string& resultSound)
|
||||
{
|
||||
if (!(lock.getCellRef().getLockLevel() > 0)) //If it's unlocked back out immediately
|
||||
if (!(lock.getCellRef().getLockLevel() > 0) || !lock.getClass().canLock(lock)) //If it's unlocked back out immediately
|
||||
return;
|
||||
|
||||
int lockStrength = lock.getCellRef().getLockLevel();
|
||||
|
|
|
@ -489,8 +489,8 @@ namespace MWMechanics
|
|||
if (!wasDead && isDead)
|
||||
MWBase::Environment::get().getMechanicsManager()->actorKilled(target, caster);
|
||||
}
|
||||
else
|
||||
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
||||
else if (!applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Re-casting a summon effect will remove the creature from previous castings of that effect.
|
||||
|
@ -559,10 +559,10 @@ namespace MWMechanics
|
|||
target.getClass().onHit(target, 0.f, true, MWWorld::Ptr(), caster, true);
|
||||
}
|
||||
|
||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude)
|
||||
bool CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude)
|
||||
{
|
||||
short effectId = effect.mId;
|
||||
if (!target.getClass().isActor())
|
||||
if (target.getClass().canLock(target))
|
||||
{
|
||||
if (effectId == ESM::MagicEffect::Lock)
|
||||
{
|
||||
|
@ -570,8 +570,9 @@ namespace MWMechanics
|
|||
{
|
||||
if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicLockSuccess}");
|
||||
target.getCellRef().setLockLevel(static_cast<int>(magnitude));
|
||||
target.getClass().lock(target, static_cast<int>(magnitude));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (effectId == ESM::MagicEffect::Open)
|
||||
{
|
||||
|
@ -586,47 +587,59 @@ namespace MWMechanics
|
|||
if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicOpenSuccess}");
|
||||
}
|
||||
target.getCellRef().setLockLevel(-abs(target.getCellRef().getLockLevel()));
|
||||
target.getClass().unlock(target);
|
||||
}
|
||||
else
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (target.getClass().isActor())
|
||||
{
|
||||
if (effectId == ESM::MagicEffect::CurePoison)
|
||||
switch (effectId)
|
||||
{
|
||||
case ESM::MagicEffect::CurePoison:
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
||||
else if (effectId == ESM::MagicEffect::CureParalyzation)
|
||||
return true;
|
||||
case ESM::MagicEffect::CureParalyzation:
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze);
|
||||
else if (effectId == ESM::MagicEffect::CureCommonDisease)
|
||||
return true;
|
||||
case ESM::MagicEffect::CureCommonDisease:
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeCommonDisease();
|
||||
else if (effectId == ESM::MagicEffect::CureBlightDisease)
|
||||
return true;
|
||||
case ESM::MagicEffect::CureBlightDisease:
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeBlightDisease();
|
||||
else if (effectId == ESM::MagicEffect::CureCorprusDisease)
|
||||
return true;
|
||||
case ESM::MagicEffect::CureCorprusDisease:
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
|
||||
else if (effectId == ESM::MagicEffect::Dispel)
|
||||
return true;
|
||||
case ESM::MagicEffect::Dispel:
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude);
|
||||
else if (effectId == ESM::MagicEffect::RemoveCurse)
|
||||
return true;
|
||||
case ESM::MagicEffect::RemoveCurse:
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeCurses();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target != MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
return;
|
||||
if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (effectId == ESM::MagicEffect::DivineIntervention)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker");
|
||||
return true;
|
||||
}
|
||||
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker");
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (effectId == ESM::MagicEffect::Mark)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
||||
target.getCell(), target.getRefData().getPosition());
|
||||
return true;
|
||||
}
|
||||
else if (effectId == ESM::MagicEffect::Recall)
|
||||
{
|
||||
|
@ -640,8 +653,10 @@ namespace MWMechanics
|
|||
markedPosition, false);
|
||||
action.execute(target);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -926,7 +941,8 @@ namespace MWMechanics
|
|||
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
|
||||
MWWorld::ContainerStoreIterator item =
|
||||
inv.getSlot(slot);
|
||||
if (item != inv.end())
|
||||
|
||||
if (item != inv.end() && (item.getType() == MWWorld::ContainerStore::Type_Armor || item.getType() == MWWorld::ContainerStore::Type_Weapon))
|
||||
{
|
||||
if (!item->getClass().hasItemHealth(*item))
|
||||
return false;
|
||||
|
|
|
@ -97,7 +97,8 @@ namespace MWMechanics
|
|||
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false, bool exploded=false);
|
||||
|
||||
/// @note \a caster can be any type of object, or even an empty object.
|
||||
void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
|
||||
/// @return was the target suitable for the effect?
|
||||
bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -208,6 +208,38 @@ namespace
|
|||
std::vector<osg::Node*> mToRemove;
|
||||
};
|
||||
|
||||
class RemoveTriBipVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
RemoveTriBipVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply(osg::Geode &node)
|
||||
{
|
||||
const std::string toFind = "tri bip";
|
||||
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
|
||||
{
|
||||
// Not safe to remove in apply(), since the visitor is still iterating the child list
|
||||
mToRemove.push_back(&node);
|
||||
}
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
osg::Node* node = *it;
|
||||
if (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<osg::Node*> mToRemove;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
|
@ -898,7 +930,7 @@ namespace MWRender
|
|||
return movement;
|
||||
}
|
||||
|
||||
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly)
|
||||
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
|
||||
{
|
||||
if (mObjectRoot)
|
||||
{
|
||||
|
@ -933,6 +965,13 @@ namespace MWRender
|
|||
removeDrawableVisitor.remove();
|
||||
}
|
||||
|
||||
if (isCreature)
|
||||
{
|
||||
RemoveTriBipVisitor removeTriBipVisitor;
|
||||
mObjectRoot->accept(removeTriBipVisitor);
|
||||
removeTriBipVisitor.remove();
|
||||
}
|
||||
|
||||
NodeMapVisitor visitor;
|
||||
mObjectRoot->accept(visitor);
|
||||
mNodeMap = visitor.getNodeMap();
|
||||
|
@ -1308,7 +1347,7 @@ namespace MWRender
|
|||
{
|
||||
if (!model.empty())
|
||||
{
|
||||
setObjectRoot(model, false, false);
|
||||
setObjectRoot(model, false, false, false);
|
||||
if (animated)
|
||||
addAnimSource(model);
|
||||
|
||||
|
|
|
@ -273,7 +273,7 @@ protected:
|
|||
* @param baseonly If true, then any meshes or particle systems in the model are ignored
|
||||
* (useful for NPCs, where only the skeleton is needed for the root, and the actual NPC parts are then assembled from separate files).
|
||||
*/
|
||||
void setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly);
|
||||
void setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature);
|
||||
|
||||
/* Adds the keyframe controllers in the specified model as a new animation source. Note that
|
||||
* the filename portion of the provided model name will be prepended with 'x', and the .nif
|
||||
|
|
|
@ -24,7 +24,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
|
|||
|
||||
if(!model.empty())
|
||||
{
|
||||
setObjectRoot(model, false, false);
|
||||
setObjectRoot(model, false, false, true);
|
||||
|
||||
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||
addAnimSource("meshes\\xbase_anim.nif");
|
||||
|
@ -42,7 +42,7 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const
|
|||
|
||||
if(!model.empty())
|
||||
{
|
||||
setObjectRoot(model, true, false);
|
||||
setObjectRoot(model, true, false, true);
|
||||
|
||||
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||
addAnimSource("meshes\\xbase_anim.nif");
|
||||
|
|
|
@ -378,7 +378,7 @@ void NpcAnimation::updateNpcBase()
|
|||
: "meshes\\wolf\\skin.1st.nif");
|
||||
smodel = Misc::ResourceHelpers::correctActorModelPath(smodel, mResourceSystem->getVFS());
|
||||
|
||||
setObjectRoot(smodel, true, true);
|
||||
setObjectRoot(smodel, true, true, false);
|
||||
|
||||
if(mViewMode != VM_FirstPerson)
|
||||
{
|
||||
|
|
|
@ -144,6 +144,11 @@ namespace MWWorld
|
|||
throw std::runtime_error ("class does not support unlocking");
|
||||
}
|
||||
|
||||
bool Class::canLock(const Ptr &ptr) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const
|
||||
{
|
||||
throw std::runtime_error ("class does not support time-based uses");
|
||||
|
|
|
@ -161,6 +161,8 @@ namespace MWWorld
|
|||
virtual void unlock (const Ptr& ptr) const;
|
||||
///< Unlock object (default implementation: throw an exception)
|
||||
|
||||
virtual bool canLock (const Ptr& ptr) const;
|
||||
|
||||
virtual void setRemainingUsageTime (const Ptr& ptr, float duration) const;
|
||||
///< Sets the remaining duration of the object, such as an equippable light
|
||||
/// source. (default implementation: throw an exception)
|
||||
|
|
|
@ -228,6 +228,7 @@ namespace MWWorld
|
|||
if (findExteriorPosition (mStartCell, pos))
|
||||
{
|
||||
changeToExteriorCell (pos);
|
||||
fixPosition(getPlayerPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2623,12 +2624,10 @@ namespace MWWorld
|
|||
{
|
||||
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||
|
||||
// Get the target to use for "on touch" effects
|
||||
// Get the target to use for "on touch" effects, using the facing direction from Head node
|
||||
MWWorld::Ptr target;
|
||||
float distance = 192.f; // ??
|
||||
osg::Vec3f hitPosition = actor.getRefData().getPosition().asVec3();
|
||||
|
||||
// For NPCs use facing direction from Head node
|
||||
osg::Vec3f origin(actor.getRefData().getPosition().asVec3());
|
||||
|
||||
MWRender::Animation* anim = mRendering->getAnimation(actor);
|
||||
|
@ -2651,13 +2650,33 @@ namespace MWWorld
|
|||
osg::Vec3f direction = orient * osg::Vec3f(0,1,0);
|
||||
osg::Vec3f dest = origin + direction * distance;
|
||||
|
||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(origin, dest, actor);
|
||||
target = result.mHitObject;
|
||||
hitPosition = result.mHitPos;
|
||||
// For actor targets, we want to use bounding boxes (physics raycast).
|
||||
// This is to give a slight tolerance for errors, especially with creatures like the Skeleton that would be very hard to aim at otherwise.
|
||||
// For object targets, we want the detailed shapes (rendering raycast).
|
||||
// If we used the bounding boxes for static objects, then we would not be able to target e.g. objects lying on a shelf.
|
||||
|
||||
// don't allow casting on non-activatable objects
|
||||
if (!target.isEmpty() && !target.getClass().isActor() && target.getClass().getName(target).empty())
|
||||
target = MWWorld::Ptr();
|
||||
MWPhysics::PhysicsSystem::RayResult result1 = mPhysics->castRay(origin, dest, actor, MWPhysics::CollisionType_Actor);
|
||||
|
||||
MWRender::RenderingManager::RayResult result2 = mRendering->castRay(origin, dest, true, true);
|
||||
|
||||
float dist1 = FLT_MAX;
|
||||
float dist2 = FLT_MAX;
|
||||
|
||||
if (result1.mHit)
|
||||
dist1 = (origin - result1.mHitPos).length();
|
||||
if (result2.mHit)
|
||||
dist2 = (origin - result2.mHitPointWorld).length();
|
||||
|
||||
if (dist1 <= dist2 && result1.mHit)
|
||||
{
|
||||
target = result1.mHitObject;
|
||||
hitPosition = result1.mHitPos;
|
||||
}
|
||||
else if (result2.mHit)
|
||||
{
|
||||
target = result2.mHitObject;
|
||||
hitPosition = result2.mHitPointWorld;
|
||||
}
|
||||
|
||||
std::string selectedSpell = stats.getSpells().getSelectedSpell();
|
||||
|
||||
|
|
Loading…
Reference in a new issue