mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53:53 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
7991dfb907
45 changed files with 359 additions and 186 deletions
|
@ -319,6 +319,8 @@ int main(int argc, char**argv)
|
|||
|
||||
boost::filesystem::ofstream logfile;
|
||||
|
||||
std::auto_ptr<OMW::Engine> engine;
|
||||
|
||||
int ret = 0;
|
||||
try
|
||||
{
|
||||
|
@ -360,11 +362,11 @@ int main(int argc, char**argv)
|
|||
boost::filesystem::current_path(bundlePath);
|
||||
#endif
|
||||
|
||||
OMW::Engine engine(cfgMgr);
|
||||
engine.reset(new OMW::Engine(cfgMgr));
|
||||
|
||||
if (parseOptions(argc, argv, engine, cfgMgr))
|
||||
if (parseOptions(argc, argv, *engine, cfgMgr))
|
||||
{
|
||||
engine.go();
|
||||
engine->go();
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
|
|
|
@ -366,10 +366,17 @@ namespace MWClass
|
|||
getCreatureStats(ptr).setAttacked(true);
|
||||
|
||||
// Self defense
|
||||
if (!attacker.isEmpty() && !MWBase::Environment::get().getMechanicsManager()->isAggressive(ptr, attacker)
|
||||
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr))) // No retaliation for totally static creatures
|
||||
// (they have no movement or attacks anyway)
|
||||
if ( ((!attacker.isEmpty() && attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr))
|
||||
|| attacker == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
&& !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)
|
||||
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
|
||||
// (they have no movement or attacks anyway)
|
||||
)
|
||||
{
|
||||
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back.
|
||||
// Note: accidental or collateral damage attacks are ignored.
|
||||
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
||||
}
|
||||
|
||||
if(!successful)
|
||||
{
|
||||
|
|
|
@ -396,6 +396,31 @@ namespace MWGui
|
|||
mLinks.clear();
|
||||
|
||||
updateOptions();
|
||||
|
||||
restock();
|
||||
}
|
||||
|
||||
void DialogueWindow::restock()
|
||||
{
|
||||
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
float delay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getFloat();
|
||||
|
||||
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getLastRestockTime() + delay)
|
||||
{
|
||||
sellerStats.setGoldPool(mPtr.getClass().getBaseGold(mPtr));
|
||||
|
||||
mPtr.getClass().restock(mPtr);
|
||||
|
||||
// Also restock any containers owned by this merchant, which are also available to buy in the trade window
|
||||
std::vector<MWWorld::Ptr> itemSources;
|
||||
MWBase::Environment::get().getWorld()->getContainersOwnedBy(mPtr, itemSources);
|
||||
for (std::vector<MWWorld::Ptr>::iterator it = itemSources.begin(); it != itemSources.end(); ++it)
|
||||
{
|
||||
it->getClass().restock(*it);
|
||||
}
|
||||
|
||||
sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp());
|
||||
}
|
||||
}
|
||||
|
||||
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
||||
|
|
|
@ -152,6 +152,7 @@ namespace MWGui
|
|||
|
||||
private:
|
||||
void updateOptions();
|
||||
void restock();
|
||||
|
||||
int mServices;
|
||||
|
||||
|
|
|
@ -144,9 +144,14 @@ namespace MWGui
|
|||
mEnchanting.setSelfEnchanting(false);
|
||||
mEnchanting.setEnchanter(actor);
|
||||
|
||||
mBuyButton->setCaptionWithReplacing("#{sBuy}");
|
||||
|
||||
mPtr = actor;
|
||||
|
||||
startEditing ();
|
||||
mPrice->setVisible(true);
|
||||
mPriceText->setVisible(true);
|
||||
updateLabels();
|
||||
}
|
||||
|
||||
void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem)
|
||||
|
@ -156,9 +161,10 @@ namespace MWGui
|
|||
mEnchanting.setSelfEnchanting(true);
|
||||
mEnchanting.setEnchanter(player);
|
||||
|
||||
mBuyButton->setCaptionWithReplacing("#{sCreate}");
|
||||
|
||||
mPtr = player;
|
||||
startEditing();
|
||||
mEnchanting.setSoulGem(soulgem);
|
||||
|
||||
setSoulGem(soulgem);
|
||||
|
||||
|
@ -299,7 +305,7 @@ namespace MWGui
|
|||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
|
||||
if (mEnchanting.getEnchantPrice() > playerGold)
|
||||
if (mPtr != player && mEnchanting.getEnchantPrice() > playerGold)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage18}");
|
||||
return;
|
||||
|
|
|
@ -115,7 +115,13 @@ void ItemView::update()
|
|||
}
|
||||
x += 42;
|
||||
MyGUI::IntSize size = MyGUI::IntSize(std::max(mScrollView->getSize().width, x), mScrollView->getSize().height);
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mScrollView->setVisibleVScroll(false);
|
||||
mScrollView->setVisibleHScroll(false);
|
||||
mScrollView->setCanvasSize(size);
|
||||
mScrollView->setVisibleVScroll(true);
|
||||
mScrollView->setVisibleHScroll(true);
|
||||
dragArea->setSize(size);
|
||||
}
|
||||
|
||||
|
|
|
@ -400,7 +400,10 @@ namespace
|
|||
|
||||
getPage (pageId)->showPage (book, 0);
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
getWidget <MyGUI::ScrollView> (listId)->setVisibleVScroll(false);
|
||||
getWidget <MyGUI::ScrollView> (listId)->setCanvasSize (size.first, size.second);
|
||||
getWidget <MyGUI::ScrollView> (listId)->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void notifyIndexLinkClicked (MWGui::TypesetBook::InteractiveId character)
|
||||
|
|
|
@ -93,7 +93,11 @@ namespace MWGui
|
|||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mScrollView->setVisibleVScroll(false);
|
||||
mScrollView->setCanvasSize(mClient->getSize().width, std::max(mItemHeight, mClient->getSize().height));
|
||||
mScrollView->setVisibleVScroll(true);
|
||||
|
||||
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
|
||||
redraw(true);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
@ -91,7 +93,10 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
|
|||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick);
|
||||
}
|
||||
}
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mList->setVisibleVScroll(false);
|
||||
mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY)));
|
||||
mList->setVisibleVScroll(true);
|
||||
|
||||
mGoldLabel->setCaptionWithReplacing("#{sGold}: "
|
||||
+ boost::lexical_cast<std::string>(playerGold));
|
||||
|
@ -131,6 +136,10 @@ void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender)
|
|||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& actorStats = mActor.getClass().getCreatureStats(mActor);
|
||||
actorStats.setGoldPool(actorStats.getGoldPool() + price);
|
||||
|
||||
startRepair(mActor);
|
||||
}
|
||||
|
||||
|
|
|
@ -654,9 +654,10 @@ namespace MWGui
|
|||
mHeight += spellHeight;
|
||||
}
|
||||
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mMagicList->setVisibleVScroll(false);
|
||||
mMagicList->setCanvasSize (mWidth, std::max(mMagicList->getHeight(), mHeight));
|
||||
|
||||
mMagicList->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void MagicSelectionDialog::addGroup(const std::string &label, const std::string& label2)
|
||||
|
|
|
@ -119,7 +119,11 @@ void Recharge::updateView()
|
|||
|
||||
currentY += 32 + 4;
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mView->setVisibleVScroll(false);
|
||||
mView->setCanvasSize (MyGUI::IntSize(mView->getWidth(), std::max(mView->getHeight(), currentY)));
|
||||
mView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void Recharge::onCancel(MyGUI::Widget *sender)
|
||||
|
|
|
@ -126,7 +126,10 @@ void Repair::updateRepairView()
|
|||
currentY += 32 + 4;
|
||||
}
|
||||
}
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mRepairView->setVisibleVScroll(false);
|
||||
mRepairView->setCanvasSize (MyGUI::IntSize(mRepairView->getWidth(), std::max(mRepairView->getHeight(), currentY)));
|
||||
mRepairView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void Repair::onCancel(MyGUI::Widget *sender)
|
||||
|
|
|
@ -320,7 +320,10 @@ namespace MWGui
|
|||
if (!mMiscSkills.empty())
|
||||
addSkills(mMiscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2);
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mSkillView->setVisibleVScroll(false);
|
||||
mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), coord1.top));
|
||||
mSkillView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
// widget controls
|
||||
|
|
|
@ -57,10 +57,13 @@ namespace MWGui
|
|||
BookTextParser parser;
|
||||
MyGUI::IntSize size = parser.parseScroll(ref->mBase->mText, mTextView, 390);
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mTextView->setVisibleVScroll(false);
|
||||
if (size.height > mTextView->getSize().height)
|
||||
mTextView->setCanvasSize(MyGUI::IntSize(410, size.height));
|
||||
else
|
||||
mTextView->setCanvasSize(410, mTextView->getSize().height);
|
||||
mTextView->setVisibleVScroll(true);
|
||||
|
||||
mTextView->setViewOffset(MyGUI::IntPoint(0,0));
|
||||
|
||||
|
|
|
@ -473,7 +473,10 @@ namespace MWGui
|
|||
curH += h;
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mControlsBox->setVisibleVScroll(false);
|
||||
mControlsBox->setCanvasSize (mControlsBox->getWidth(), std::max(curH, mControlsBox->getHeight()));
|
||||
mControlsBox->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void SettingsWindow::onRebindAction(MyGUI::Widget* _sender)
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace MWGui
|
|||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
|
||||
|
||||
// TODO: refactor to use MyGUI::ListBox
|
||||
|
||||
MyGUI::Button* toAdd =
|
||||
mSpellsView->createWidget<MyGUI::Button>(
|
||||
"SandTextButton",
|
||||
|
@ -106,7 +108,10 @@ namespace MWGui
|
|||
|
||||
updateLabels();
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mSpellsView->setVisibleVScroll(false);
|
||||
mSpellsView->setCanvasSize (MyGUI::IntSize(mSpellsView->getWidth(), std::max(mSpellsView->getHeight(), mCurrentY)));
|
||||
mSpellsView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
bool SpellBuyingWindow::playerHasSpell(const std::string &id)
|
||||
|
@ -130,6 +135,11 @@ namespace MWGui
|
|||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
spells.add (mSpellsWidgetMap.find(_sender)->second);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
npcStats.setGoldPool(npcStats.getGoldPool() + price);
|
||||
|
||||
startSpellBuying(mPtr);
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0);
|
||||
|
|
|
@ -352,7 +352,13 @@ namespace MWGui
|
|||
|
||||
mSpell.mName = mNameEdit->getCaption();
|
||||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, boost::lexical_cast<int>(mPriceLabel->getCaption()), player);
|
||||
int price = boost::lexical_cast<int>(mPriceLabel->getCaption());
|
||||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
npcStats.setGoldPool(npcStats.getGoldPool() + price);
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0);
|
||||
|
||||
|
@ -637,7 +643,10 @@ namespace MWGui
|
|||
++i;
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with HScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mUsedEffectsView->setVisibleHScroll(false);
|
||||
mUsedEffectsView->setCanvasSize(size);
|
||||
mUsedEffectsView->setVisibleHScroll(true);
|
||||
|
||||
notifyEffectsChanged();
|
||||
}
|
||||
|
|
|
@ -261,7 +261,10 @@ namespace MWGui
|
|||
mHeight += spellHeight;
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mSpellView->setVisibleVScroll(false);
|
||||
mSpellView->setCanvasSize(mSpellView->getWidth(), std::max(mSpellView->getHeight(), mHeight));
|
||||
mSpellView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void SpellWindow::addGroup(const std::string &label, const std::string& label2)
|
||||
|
|
|
@ -82,7 +82,10 @@ namespace MWGui
|
|||
{
|
||||
mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) );
|
||||
mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) );
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mSkillView->setVisibleVScroll(false);
|
||||
mSkillView->setCanvasSize (mSkillView->getWidth(), mSkillView->getCanvasSize().height);
|
||||
mSkillView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max)
|
||||
|
@ -578,7 +581,10 @@ namespace MWGui
|
|||
mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sCrimeHelp}");
|
||||
}
|
||||
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mSkillView->setVisibleVScroll(false);
|
||||
mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), coord1.top));
|
||||
mSkillView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void StatsWindow::onPinToggled()
|
||||
|
|
|
@ -99,8 +99,6 @@ namespace MWGui
|
|||
mCurrentBalance = 0;
|
||||
mCurrentMerchantOffer = 0;
|
||||
|
||||
restock();
|
||||
|
||||
std::vector<MWWorld::Ptr> itemSources;
|
||||
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
|
||||
|
||||
|
@ -509,29 +507,6 @@ namespace MWGui
|
|||
return merchantGold;
|
||||
}
|
||||
|
||||
void TradeWindow::restock()
|
||||
{
|
||||
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
float delay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getFloat();
|
||||
|
||||
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getLastRestockTime() + delay)
|
||||
{
|
||||
sellerStats.setGoldPool(mPtr.getClass().getBaseGold(mPtr));
|
||||
|
||||
mPtr.getClass().restock(mPtr);
|
||||
|
||||
// Also restock any containers owned by this merchant, which are also available to buy in the trade window
|
||||
std::vector<MWWorld::Ptr> itemSources;
|
||||
MWBase::Environment::get().getWorld()->getContainersOwnedBy(mPtr, itemSources);
|
||||
for (std::vector<MWWorld::Ptr>::iterator it = itemSources.begin(); it != itemSources.end(); ++it)
|
||||
{
|
||||
it->getClass().restock(*it);
|
||||
}
|
||||
|
||||
sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp());
|
||||
}
|
||||
}
|
||||
|
||||
void TradeWindow::resetReference()
|
||||
{
|
||||
ReferenceInterface::resetReference();
|
||||
|
|
|
@ -104,8 +104,6 @@ namespace MWGui
|
|||
virtual void onReferenceUnavailable();
|
||||
|
||||
int getMerchantGold();
|
||||
|
||||
void restock();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,9 @@ namespace MWGui
|
|||
// remove gold
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
npcStats.setGoldPool(npcStats.getGoldPool() + price);
|
||||
|
||||
// go back to game mode
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training);
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/actionteleport.hpp"
|
||||
|
@ -126,7 +128,10 @@ namespace MWGui
|
|||
}
|
||||
|
||||
updateLabels();
|
||||
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
|
||||
mDestinationsView->setVisibleVScroll(false);
|
||||
mDestinationsView->setCanvasSize (MyGUI::IntSize(mDestinationsView->getWidth(), std::max(mDestinationsView->getHeight(), mCurrentY)));
|
||||
mDestinationsView->setVisibleVScroll(true);
|
||||
}
|
||||
|
||||
void TravelWindow::onTravelButtonClick(MyGUI::Widget* _sender)
|
||||
|
@ -147,6 +152,10 @@ namespace MWGui
|
|||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
npcStats.setGoldPool(npcStats.getGoldPool() + price);
|
||||
|
||||
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1);
|
||||
ESM::Position pos = *_sender->getUserData<ESM::Position>();
|
||||
std::string cellname = _sender->getUserString("Destination");
|
||||
|
|
|
@ -192,6 +192,15 @@ namespace MWMechanics
|
|||
CreatureStats& creatureStats = actor1.getClass().getCreatureStats(actor1);
|
||||
|
||||
if (againstPlayer && creatureStats.isHostile()) return; // already fighting against player
|
||||
if (actor2.getClass().getCreatureStats(actor2).isDead()
|
||||
|| actor1.getClass().getCreatureStats(actor1).isDead())
|
||||
return;
|
||||
|
||||
const ESM::Position& actor1Pos = actor2.getRefData().getPosition();
|
||||
const ESM::Position& actor2Pos = actor2.getRefData().getPosition();
|
||||
float sqrDist = Ogre::Vector3(actor1Pos.pos).squaredDistance(Ogre::Vector3(actor2Pos.pos));
|
||||
if (sqrDist > 7168*7168)
|
||||
return;
|
||||
|
||||
// pure water creatures won't try to fight with the target on the ground
|
||||
// except that creature is already hostile
|
||||
|
@ -208,9 +217,9 @@ namespace MWMechanics
|
|||
else
|
||||
{
|
||||
aggressive = false;
|
||||
// if one of actors is creature then we should make a decision to start combat or not
|
||||
// NOTE: function doesn't take into account combat between 2 creatures
|
||||
if (!actor1.getClass().isNpc())
|
||||
|
||||
// Make guards fight aggressive creatures
|
||||
if (!actor1.getClass().isNpc() && actor2.getClass().isClass(actor2, "Guard"))
|
||||
{
|
||||
// if creature is hostile then it is necessarily to start combat
|
||||
if (creatureStats.isHostile()) aggressive = true;
|
||||
|
@ -218,24 +227,34 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
// start combat if we are in combat with any followers of this actor
|
||||
const std::list<MWWorld::Ptr>& followers = getActorsFollowing(actor2);
|
||||
for (std::list<MWWorld::Ptr>::const_iterator it = followers.begin(); it != followers.end(); ++it)
|
||||
{
|
||||
if (creatureStats.getAiSequence().isInCombat(*it))
|
||||
aggressive = true;
|
||||
}
|
||||
// start combat if we are in combat with someone this actor is following
|
||||
const CreatureStats& creatureStats2 = actor2.getClass().getCreatureStats(actor2);
|
||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = creatureStats2.getAiSequence().begin(); it != creatureStats2.getAiSequence().end(); ++it)
|
||||
{
|
||||
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow &&
|
||||
creatureStats.getAiSequence().isInCombat(dynamic_cast<MWMechanics::AiFollow*>(*it)->getTarget()))
|
||||
aggressive = true;
|
||||
}
|
||||
|
||||
if(aggressive)
|
||||
{
|
||||
const ESM::Position& actor1Pos = actor2.getRefData().getPosition();
|
||||
const ESM::Position& actor2Pos = actor2.getRefData().getPosition();
|
||||
float d = Ogre::Vector3(actor1Pos.pos).distance(Ogre::Vector3(actor2Pos.pos));
|
||||
if (againstPlayer || actor2.getClass().getCreatureStats(actor2).getAiSequence().canAddTarget(actor2Pos, d))
|
||||
bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2);
|
||||
|
||||
if (againstPlayer) LOS &= MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor2, actor1);
|
||||
|
||||
if (LOS)
|
||||
{
|
||||
bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2);
|
||||
|
||||
if (againstPlayer) LOS &= MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor2, actor1);
|
||||
|
||||
if (LOS)
|
||||
MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2);
|
||||
if (!againstPlayer) // start combat between each other
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2);
|
||||
if (!againstPlayer) // start combat between each other
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->startCombat(actor2, actor1);
|
||||
}
|
||||
MWBase::Environment::get().getMechanicsManager()->startCombat(actor2, actor1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -905,12 +924,7 @@ namespace MWMechanics
|
|||
|
||||
Actors::~Actors()
|
||||
{
|
||||
PtrControllerMap::iterator it(mActors.begin());
|
||||
for (; it != mActors.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately)
|
||||
|
@ -964,19 +978,10 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
static Ogre::Vector3 sBasePoint;
|
||||
bool comparePtrDist (const MWWorld::Ptr& ptr1, const MWWorld::Ptr& ptr2)
|
||||
{
|
||||
return (sBasePoint.squaredDistance(Ogre::Vector3(ptr1.getRefData().getPosition().pos))
|
||||
< sBasePoint.squaredDistance(Ogre::Vector3(ptr2.getRefData().getPosition().pos)));
|
||||
}
|
||||
|
||||
void Actors::update (float duration, bool paused)
|
||||
{
|
||||
if(!paused)
|
||||
{
|
||||
std::list<MWWorld::Ptr> listGuards; // at the moment only guards certainly will fight with creatures
|
||||
|
||||
static float timerUpdateAITargets = 0;
|
||||
|
||||
// target lists get updated once every 1.0 sec
|
||||
|
@ -989,16 +994,10 @@ namespace MWMechanics
|
|||
// Note, the new hit object for this frame may be set by CharacterController::update -> Animation::runAnimation
|
||||
// (below)
|
||||
iter->first.getClass().getCreatureStats(iter->first).setLastHitObject(std::string());
|
||||
|
||||
// add guards to list to later make them fight with creatures
|
||||
if (timerUpdateAITargets == 0 && iter->first.getClass().isClass(iter->first, "Guard"))
|
||||
listGuards.push_back(iter->first);
|
||||
}
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
|
||||
listGuards.push_back(player);
|
||||
|
||||
// AI and magic effects update
|
||||
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
{
|
||||
|
@ -1008,20 +1007,16 @@ namespace MWMechanics
|
|||
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||
{
|
||||
// make guards and creatures fight each other
|
||||
if (timerUpdateAITargets == 0 && iter->first.getTypeName() == typeid(ESM::Creature).name() && !listGuards.empty())
|
||||
if (timerUpdateAITargets == 0)
|
||||
{
|
||||
sBasePoint = Ogre::Vector3(iter->first.getRefData().getPosition().pos);
|
||||
listGuards.sort(comparePtrDist); // try to engage combat starting from the nearest guard
|
||||
|
||||
for (std::list<MWWorld::Ptr>::iterator it = listGuards.begin(); it != listGuards.end(); ++it)
|
||||
for(PtrControllerMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
|
||||
{
|
||||
engageCombat(iter->first, *it, *it == player);
|
||||
if (it->first == iter->first || iter->first == player) // player is not AI-controlled
|
||||
continue;
|
||||
engageCombat(iter->first, it->first, it->first == player);
|
||||
}
|
||||
}
|
||||
|
||||
if (iter->first != player) engageCombat(iter->first, player, true);
|
||||
|
||||
if (iter->first.getClass().isNpc() && iter->first != player)
|
||||
updateCrimePersuit(iter->first, duration);
|
||||
|
||||
|
@ -1359,6 +1354,13 @@ namespace MWMechanics
|
|||
|
||||
void Actors::clear()
|
||||
{
|
||||
PtrControllerMap::iterator it(mActors.begin());
|
||||
for (; it != mActors.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
mActors.clear();
|
||||
mDeathCount.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,6 +174,8 @@ namespace MWMechanics
|
|||
return true;
|
||||
|
||||
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
||||
if (target.isEmpty())
|
||||
return false;
|
||||
|
||||
if(target.getClass().getCreatureStats(target).isDead())
|
||||
return true;
|
||||
|
|
|
@ -121,3 +121,8 @@ MWMechanics::AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow)
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
MWWorld::Ptr MWMechanics::AiFollow::getTarget() const
|
||||
{
|
||||
return MWBase::Environment::get().getWorld()->searchPtr(mActorId, false);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace MWMechanics
|
|||
|
||||
AiFollow(const ESM::AiSequence::AiFollow* follow);
|
||||
|
||||
MWWorld::Ptr getTarget() const;
|
||||
|
||||
virtual AiFollow *clone() const;
|
||||
|
||||
virtual bool execute (const MWWorld::Ptr& actor,float duration);
|
||||
|
|
|
@ -72,6 +72,16 @@ bool AiSequence::getCombatTarget(MWWorld::Ptr &targetActor) const
|
|||
return true;
|
||||
}
|
||||
|
||||
std::list<AiPackage*>::const_iterator AiSequence::begin() const
|
||||
{
|
||||
return mPackages.begin();
|
||||
}
|
||||
|
||||
std::list<AiPackage*>::const_iterator AiSequence::end() const
|
||||
{
|
||||
return mPackages.end();
|
||||
}
|
||||
|
||||
bool AiSequence::isInCombat() const
|
||||
{
|
||||
for(std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
|
||||
|
|
|
@ -50,6 +50,10 @@ namespace MWMechanics
|
|||
|
||||
virtual ~AiSequence();
|
||||
|
||||
/// Iterator may be invalidated by any function calls other than begin() or end().
|
||||
std::list<AiPackage*>::const_iterator begin() const;
|
||||
std::list<AiPackage*>::const_iterator end() const;
|
||||
|
||||
/// Returns currently executing AiPackage type
|
||||
/** \see enum AiPackage::TypeId **/
|
||||
int getTypeId() const;
|
||||
|
|
|
@ -181,7 +181,13 @@ void MWMechanics::Alchemy::updateEffects()
|
|||
ESM::ENAMstruct effect;
|
||||
effect.mEffectID = iter->mId;
|
||||
|
||||
effect.mSkill = effect.mAttribute = iter->mArg; // somewhat hack-ish, but should work
|
||||
effect.mAttribute = -1;
|
||||
effect.mSkill = -1;
|
||||
|
||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||
effect.mSkill = iter->mArg;
|
||||
else if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||
effect.mAttribute = iter->mArg;
|
||||
|
||||
effect.mRange = 0;
|
||||
effect.mArea = 0;
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace MWMechanics
|
|||
|
||||
if(mSelfEnchanting)
|
||||
{
|
||||
if(getEnchantChance()<std::rand()/static_cast<double> (RAND_MAX)*100)
|
||||
if(std::rand()/static_cast<double> (RAND_MAX)*100 < getEnchantChance())
|
||||
return false;
|
||||
|
||||
mEnchanter.getClass().skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2);
|
||||
|
@ -292,5 +292,9 @@ namespace MWMechanics
|
|||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||
|
||||
store.remove(MWWorld::ContainerStore::sGoldId, getEnchantPrice(), player);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
CreatureStats& enchanterStats = mEnchanter.getClass().getCreatureStats(mEnchanter);
|
||||
enchanterStats.setGoldPool(enchanterStats.getGoldPool() + getEnchantPrice());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1171,6 +1171,8 @@ namespace MWMechanics
|
|||
|
||||
void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
|
||||
{
|
||||
if (ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(target))
|
||||
return;
|
||||
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr);
|
||||
if (target == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
{
|
||||
|
|
|
@ -287,6 +287,27 @@ namespace MWMechanics
|
|||
|
||||
bool castByPlayer = (!caster.isEmpty() && caster.getRefData().getHandle() == "player");
|
||||
|
||||
// Try absorbing if it's a spell
|
||||
// NOTE: Vanilla does this once per effect source instead of adding the % from all sources together, not sure
|
||||
// if that is worth replicating.
|
||||
bool absorbed = false;
|
||||
if (spell && caster != target && target.getClass().isActor())
|
||||
{
|
||||
int absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).mMagnitude;
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
absorbed = (roll < absorb);
|
||||
if (absorbed)
|
||||
{
|
||||
const ESM::Static* absorbStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Absorb");
|
||||
MWBase::Environment::get().getWorld()->getAnimation(target)->addEffect(
|
||||
"meshes\\" + absorbStatic->mModel, ESM::MagicEffect::SpellAbsorption, false, "");
|
||||
// Magicka is increased by cost of spell
|
||||
DynamicStat<float> magicka = target.getClass().getCreatureStats(target).getMagicka();
|
||||
magicka.setCurrent(magicka.getCurrent() + spell->mData.mCost);
|
||||
target.getClass().getCreatureStats(target).setMagicka(magicka);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt (effects.mList.begin());
|
||||
effectIt!=effects.mList.end(); ++effectIt)
|
||||
{
|
||||
|
@ -326,31 +347,13 @@ namespace MWMechanics
|
|||
{
|
||||
anyHarmfulEffect = true;
|
||||
|
||||
if (absorbed) // Absorbed, and we know there was a harmful effect (figuring that out is the only reason we are in this loop)
|
||||
break;
|
||||
|
||||
// If player is attempting to cast a harmful spell, show the target's HP bar
|
||||
if (castByPlayer && target != caster)
|
||||
MWBase::Environment::get().getWindowManager()->setEnemy(target);
|
||||
|
||||
// Try absorbing if it's a spell
|
||||
// NOTE: Vanilla does this once per effect source instead of adding the % from all sources together, not sure
|
||||
// if that is worth replicating.
|
||||
if (spell && caster != target)
|
||||
{
|
||||
int absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).mMagnitude;
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
bool isAbsorbed = (roll < absorb);
|
||||
if (isAbsorbed)
|
||||
{
|
||||
const ESM::Static* absorbStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Absorb");
|
||||
MWBase::Environment::get().getWorld()->getAnimation(target)->addEffect(
|
||||
"meshes\\" + absorbStatic->mModel, ESM::MagicEffect::Reflect, false, "");
|
||||
// Magicka is increased by cost of spell
|
||||
DynamicStat<float> magicka = target.getClass().getCreatureStats(target).getMagicka();
|
||||
magicka.setCurrent(magicka.getCurrent() + spell->mData.mCost);
|
||||
target.getClass().getCreatureStats(target).setMagicka(magicka);
|
||||
magnitudeMult = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Try reflecting
|
||||
if (!reflected && magnitudeMult > 0 && !caster.isEmpty() && caster != target && !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable))
|
||||
{
|
||||
|
@ -382,8 +385,7 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (magnitudeMult > 0)
|
||||
if (magnitudeMult > 0 && !absorbed)
|
||||
{
|
||||
float random = std::rand() / static_cast<float>(RAND_MAX);
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||
|
|
|
@ -72,12 +72,6 @@ namespace MWWorld
|
|||
|
||||
public:
|
||||
|
||||
/// NPC-stances.
|
||||
enum Stance
|
||||
{
|
||||
Run, Sneak
|
||||
};
|
||||
|
||||
virtual ~Class();
|
||||
|
||||
const std::string& getTypeName() const {
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace MWWorld
|
|||
mSky (true), mCells (mStore, mEsm),
|
||||
mActivationDistanceOverride (activationDistanceOverride),
|
||||
mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true),
|
||||
mFacedDistance(FLT_MAX), mGodMode(false), mContentFiles (contentFiles),
|
||||
mGodMode(false), mContentFiles (contentFiles),
|
||||
mGoToJail(false),
|
||||
mStartCell (startCell), mStartupScript(startupScript)
|
||||
{
|
||||
|
@ -290,7 +290,6 @@ namespace MWWorld
|
|||
mGodMode = false;
|
||||
mSky = true;
|
||||
mTeleportEnabled = true;
|
||||
mFacedDistance = FLT_MAX;
|
||||
|
||||
mGlobalVariables.fill (mStore);
|
||||
}
|
||||
|
@ -320,8 +319,9 @@ namespace MWWorld
|
|||
MWMechanics::CreatureStats::writeActorIdCounter(writer);
|
||||
progress.increaseProgress();
|
||||
|
||||
mStore.write (writer, progress); // dynamic Store must be written (and read) before Cells, so that
|
||||
// references to custom made records will be recognized
|
||||
mCells.write (writer, progress);
|
||||
mStore.write (writer, progress);
|
||||
mGlobalVariables.write (writer, progress);
|
||||
mPlayer->write (writer, progress);
|
||||
mWeatherManager->write (writer, progress);
|
||||
|
@ -1462,30 +1462,22 @@ namespace MWWorld
|
|||
updateFacedHandle ();
|
||||
}
|
||||
|
||||
void World::updateFacedHandle ()
|
||||
void World::getFacedHandle(std::string& facedHandle, float maxDistance)
|
||||
{
|
||||
float telekinesisRangeBonus =
|
||||
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
|
||||
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
|
||||
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
|
||||
maxDistance += mRendering->getCameraDistance();
|
||||
|
||||
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
|
||||
activationDistance += mRendering->getCameraDistance();
|
||||
|
||||
// send new query
|
||||
// figure out which object we want to test against
|
||||
std::vector < std::pair < float, std::string > > results;
|
||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
{
|
||||
float x, y;
|
||||
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
|
||||
results = mPhysics->getFacedHandles(x, y, activationDistance);
|
||||
results = mPhysics->getFacedHandles(x, y, maxDistance);
|
||||
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
||||
}
|
||||
else
|
||||
{
|
||||
results = mPhysics->getFacedHandles(activationDistance);
|
||||
results = mPhysics->getFacedHandles(maxDistance);
|
||||
}
|
||||
|
||||
// ignore the player and other things we're not interested in
|
||||
|
@ -1508,15 +1500,21 @@ namespace MWWorld
|
|||
|
||||
if (results.empty()
|
||||
|| results.front().second.find("HeightField") != std::string::npos) // Blocked by terrain
|
||||
{
|
||||
mFacedHandle = "";
|
||||
mFacedDistance = FLT_MAX;
|
||||
}
|
||||
facedHandle = "";
|
||||
else
|
||||
{
|
||||
mFacedHandle = results.front().second;
|
||||
mFacedDistance = results.front().first;
|
||||
}
|
||||
facedHandle = results.front().second;
|
||||
}
|
||||
|
||||
void World::updateFacedHandle ()
|
||||
{
|
||||
float telekinesisRangeBonus =
|
||||
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
|
||||
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
|
||||
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
|
||||
|
||||
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
|
||||
|
||||
getFacedHandle(mFacedHandle, activationDistance);
|
||||
}
|
||||
|
||||
bool World::isCellExterior() const
|
||||
|
@ -2114,8 +2112,8 @@ namespace MWWorld
|
|||
void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable)
|
||||
{
|
||||
OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||
|
||||
physicActor->enableCollisionBody(enable);
|
||||
if (physicActor)
|
||||
physicActor->enableCollisionBody(enable);
|
||||
}
|
||||
|
||||
bool World::findInteriorPosition(const std::string &name, ESM::Position &pos)
|
||||
|
@ -2344,8 +2342,49 @@ namespace MWWorld
|
|||
{
|
||||
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||
|
||||
// TODO: this only works for the player
|
||||
MWWorld::Ptr target = getFacedObject();
|
||||
// Get the target to use for "on touch" effects
|
||||
MWWorld::Ptr target;
|
||||
float distance = 192.f; // ??
|
||||
|
||||
if (actor == getPlayerPtr())
|
||||
{
|
||||
// For the player, use camera to aim
|
||||
std::string facedHandle;
|
||||
getFacedHandle(facedHandle, distance);
|
||||
if (!facedHandle.empty())
|
||||
target = getPtrViaHandle(facedHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For NPCs use facing direction from Head node
|
||||
Ogre::Vector3 origin(actor.getRefData().getPosition().pos);
|
||||
MWRender::Animation *anim = mRendering->getAnimation(actor);
|
||||
if(anim != NULL)
|
||||
{
|
||||
Ogre::Node *node = anim->getNode("Head");
|
||||
if (node == NULL)
|
||||
node = anim->getNode("Bip01 Head");
|
||||
if(node != NULL)
|
||||
origin += node->_getDerivedPosition();
|
||||
}
|
||||
Ogre::Quaternion orient;
|
||||
orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
||||
Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
|
||||
Ogre::Vector3 direction = orient.yAxis();
|
||||
Ogre::Vector3 dest = origin + direction * distance;
|
||||
|
||||
|
||||
std::vector<std::pair<float, std::string> > collisions = mPhysEngine->rayTest2(btVector3(origin.x, origin.y, origin.z), btVector3(dest.x, dest.y, dest.z));
|
||||
for (std::vector<std::pair<float, std::string> >::iterator cIt = collisions.begin(); cIt != collisions.end(); ++cIt)
|
||||
{
|
||||
MWWorld::Ptr collided = getPtrViaHandle(cIt->second);
|
||||
if (collided != actor)
|
||||
{
|
||||
target = collided;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string selectedSpell = stats.getSpells().getSelectedSpell();
|
||||
|
||||
|
|
|
@ -92,7 +92,6 @@ namespace MWWorld
|
|||
|
||||
int mActivationDistanceOverride;
|
||||
std::string mFacedHandle;
|
||||
float mFacedDistance;
|
||||
|
||||
std::string mStartupScript;
|
||||
|
||||
|
@ -114,6 +113,7 @@ namespace MWWorld
|
|||
void updateWindowManager ();
|
||||
void performUpdateSceneQueries ();
|
||||
void updateFacedHandle ();
|
||||
void getFacedHandle(std::string& facedHandle, float maxDistance);
|
||||
|
||||
float getMaxActivationDistance ();
|
||||
float getNpcActivationDistance ();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
|
||||
ESM::NpcStats::Faction::Faction() : mExpelled (false), mRank (0), mReputation (0) {}
|
||||
ESM::NpcStats::Faction::Faction() : mExpelled (false), mRank (-1), mReputation (0) {}
|
||||
|
||||
void ESM::NpcStats::load (ESMReader &esm)
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
esm.writeHNT ("FAEX", expelled);
|
||||
}
|
||||
|
||||
if (iter->second.mRank)
|
||||
if (iter->second.mRank >= 0)
|
||||
esm.writeHNT ("FARA", iter->second.mRank);
|
||||
|
||||
if (iter->second.mReputation)
|
||||
|
|
30
extern/shiny/Main/Factory.cpp
vendored
30
extern/shiny/Main/Factory.cpp
vendored
|
@ -51,24 +51,32 @@ namespace sh
|
|||
{
|
||||
assert(mCurrentLanguage != Language_None);
|
||||
|
||||
if (boost::filesystem::exists (mPlatform->getCacheFolder () + "/lastModified.txt"))
|
||||
try
|
||||
{
|
||||
std::ifstream file;
|
||||
file.open(std::string(mPlatform->getCacheFolder () + "/lastModified.txt").c_str());
|
||||
|
||||
std::string line;
|
||||
while (getline(file, line))
|
||||
if (boost::filesystem::exists (mPlatform->getCacheFolder () + "/lastModified.txt"))
|
||||
{
|
||||
std::string sourceFile = line;
|
||||
std::ifstream file;
|
||||
file.open(std::string(mPlatform->getCacheFolder () + "/lastModified.txt").c_str());
|
||||
|
||||
if (!getline(file, line))
|
||||
assert(0);
|
||||
std::string line;
|
||||
while (getline(file, line))
|
||||
{
|
||||
std::string sourceFile = line;
|
||||
|
||||
int modified = boost::lexical_cast<int>(line);
|
||||
if (!getline(file, line))
|
||||
assert(0);
|
||||
|
||||
mShadersLastModified[sourceFile] = modified;
|
||||
int modified = boost::lexical_cast<int>(line);
|
||||
|
||||
mShadersLastModified[sourceFile] = modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Failed to load shader modification index: " << e.what() << std::endl;
|
||||
mShadersLastModified.clear();
|
||||
}
|
||||
|
||||
// load configurations
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
SH_START_PROGRAM
|
||||
{
|
||||
shOutputColour(0) = alphaFade * atmosphereColour + (1.f - alphaFade) * horizonColour;
|
||||
shOutputColour(0) = alphaFade * atmosphereColour + (1.0 - alphaFade) * horizonColour;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
shOutputPosition = shMatrixMult(proj, shMatrixMult(worldviewFixed, shInputPosition));
|
||||
UV = uv0;
|
||||
alphaFade = (shInputPosition.z <= 200.f) ? ((shInputPosition.z <= 100.f) ? 0.0 : 0.25) : 1.0;
|
||||
alphaFade = (shInputPosition.z <= 200.0) ? ((shInputPosition.z <= 100.0) ? 0.0 : 0.25) : 1.0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
SH_START_PROGRAM
|
||||
{
|
||||
shOutputPosition = float4(shInputPosition.xyz, 1.f);
|
||||
shOutputPosition = float4(shInputPosition.xyz, 1.0);
|
||||
#if TEXTURE
|
||||
UV.xy = uv0;
|
||||
#endif
|
||||
|
|
|
@ -210,11 +210,11 @@
|
|||
#if VERTEXCOLOR_MODE == 2
|
||||
lightResult.xyz += colour.xyz * lightDiffuse[@shIterator].xyz
|
||||
* shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d)))
|
||||
* max(dot(viewNormal.xyz, lightDir), 0);
|
||||
* max(dot(viewNormal.xyz, lightDir), 0.0);
|
||||
#else
|
||||
lightResult.xyz += materialDiffuse.xyz * lightDiffuse[@shIterator].xyz
|
||||
* shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d)))
|
||||
* max(dot(viewNormal.xyz, lightDir), 0);
|
||||
* max(dot(viewNormal.xyz, lightDir), 0.0);
|
||||
#endif
|
||||
|
||||
#if @shIterator == 0
|
||||
|
@ -432,11 +432,11 @@
|
|||
#if VERTEXCOLOR_MODE == 2
|
||||
lightResult.xyz += colourPassthrough.xyz * lightDiffuse[@shIterator].xyz
|
||||
* shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d)))
|
||||
* max(dot(viewNormal.xyz, lightDir), 0);
|
||||
* max(dot(viewNormal.xyz, lightDir), 0.0);
|
||||
#else
|
||||
lightResult.xyz += materialDiffuse.xyz * lightDiffuse[@shIterator].xyz
|
||||
* shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d)))
|
||||
* max(dot(viewNormal.xyz, lightDir), 0);
|
||||
* max(dot(viewNormal.xyz, lightDir), 0.0);
|
||||
#endif
|
||||
|
||||
#if @shIterator == 0
|
||||
|
@ -504,8 +504,8 @@
|
|||
|
||||
#if ENV_MAP
|
||||
// Everything looks better with fresnel
|
||||
float facing = 1.0 - max(abs(dot(-eyeDir, normal)), 0);
|
||||
float envFactor = shSaturate(0.25 + 0.75 * pow(facing, 1));
|
||||
float facing = 1.0 - max(abs(dot(-eyeDir, normal)), 0.0);
|
||||
float envFactor = shSaturate(0.25 + 0.75 * pow(facing, 1.0));
|
||||
|
||||
shOutputColour(0).xyz += shSample(envMap, UV.zw).xyz * envFactor * env_map_color;
|
||||
#endif
|
||||
|
@ -513,7 +513,7 @@
|
|||
#if SPECULAR
|
||||
float3 light0Dir = normalize(lightPosObjSpace0.xyz);
|
||||
|
||||
float NdotL = max(dot(normal, light0Dir), 0);
|
||||
float NdotL = max(dot(normal, light0Dir), 0.0);
|
||||
float3 halfVec = normalize (light0Dir + eyeDir);
|
||||
|
||||
float shininess = matShininess;
|
||||
|
@ -522,7 +522,7 @@
|
|||
shininess *= (specTex.a);
|
||||
#endif
|
||||
|
||||
float3 specular = pow(max(dot(normal, halfVec), 0), shininess) * lightSpec0 * matSpec;
|
||||
float3 specular = pow(max(dot(normal, halfVec), 0.0), shininess) * lightSpec0 * matSpec;
|
||||
#if SPEC_MAP
|
||||
specular *= specTex.xyz;
|
||||
#else
|
||||
|
|
|
@ -175,7 +175,7 @@
|
|||
|
||||
lightResult.xyz += lightDiffuse[@shIterator].xyz
|
||||
* shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d)))
|
||||
* max(dot(normal.xyz, lightDir), 0);
|
||||
* max(dot(normal.xyz, lightDir), 0.0);
|
||||
|
||||
#if @shIterator == 0
|
||||
directionalResult = lightResult.xyz;
|
||||
|
@ -310,7 +310,7 @@ shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position)
|
|||
|
||||
#if !IS_FIRST_PASS
|
||||
// Opacity the previous passes should have, i.e. 1 - (opacity of this pass)
|
||||
float previousAlpha = 1.f;
|
||||
float previousAlpha = 1.0;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -334,7 +334,7 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
|||
|
||||
float4 albedo = float4(0,0,0,1);
|
||||
|
||||
float2 layerUV = float2(UV.x, 1.f-UV.y) * 16; // Reverse Y, required to get proper tangents
|
||||
float2 layerUV = float2(UV.x, 1.0-UV.y) * 16.0; // Reverse Y, required to get proper tangents
|
||||
float2 thisLayerUV;
|
||||
float4 normalTex;
|
||||
float4 diffuseTex;
|
||||
|
@ -349,9 +349,9 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
|||
#if @shPropertyBool(use_normal_map_@shIterator)
|
||||
normalTex = shSample(normalMap@shIterator, thisLayerUV);
|
||||
#if @shIterator == 0 && IS_FIRST_PASS
|
||||
TSnormal = normalize(normalTex.xyz * 2 - 1);
|
||||
TSnormal = normalize(normalTex.xyz * 2.0 - 1.0);
|
||||
#else
|
||||
TSnormal = shLerp(TSnormal, normalTex.xyz * 2 - 1, blendValues@shPropertyString(blendmap_component_@shIterator));
|
||||
TSnormal = shLerp(TSnormal, normalTex.xyz * 2.0 - 1.0, blendValues@shPropertyString(blendmap_component_@shIterator));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -361,7 +361,7 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
|||
|
||||
diffuseTex = shSample(diffuseMap@shIterator, layerUV);
|
||||
#if !@shPropertyBool(use_specular_@shIterator)
|
||||
diffuseTex.a = 0;
|
||||
diffuseTex.a = 0.0;
|
||||
#endif
|
||||
|
||||
#if @shIterator == 0
|
||||
|
@ -371,7 +371,7 @@ albedo = shLerp(albedo, diffuseTex, blendValues@shPropertyString(blendmap_compon
|
|||
#endif
|
||||
|
||||
#if !IS_FIRST_PASS
|
||||
previousAlpha *= 1.f-blendValues@shPropertyString(blendmap_component_@shIterator);
|
||||
previousAlpha *= 1.0-blendValues@shPropertyString(blendmap_component_@shIterator);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -404,7 +404,7 @@ albedo = shLerp(albedo, diffuseTex, blendValues@shPropertyString(blendmap_compon
|
|||
|
||||
lightResult.xyz += lightDiffuse[@shIterator].xyz
|
||||
* shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d)))
|
||||
* max(dot(normal.xyz, lightDir), 0);
|
||||
* max(dot(normal.xyz, lightDir), 0.0);
|
||||
#if @shIterator == 0
|
||||
float3 directionalResult = lightResult.xyz;
|
||||
#endif
|
||||
|
@ -444,10 +444,10 @@ albedo = shLerp(albedo, diffuseTex, blendValues@shPropertyString(blendmap_compon
|
|||
// Specular
|
||||
float3 light0Dir = normalize(lightPos0.xyz);
|
||||
|
||||
float NdotL = max(dot(normal, light0Dir), 0);
|
||||
float NdotL = max(dot(normal, light0Dir), 0.0);
|
||||
float3 halfVec = normalize (light0Dir + eyeDir);
|
||||
|
||||
float3 specular = pow(max(dot(normal, halfVec), 0), 32) * lightSpec0;
|
||||
float3 specular = pow(max(dot(normal, halfVec), 0.0), 32.0) * lightSpec0;
|
||||
shOutputColour(0).xyz += specular * (albedo.a) * shadow;
|
||||
#endif
|
||||
|
||||
|
@ -465,9 +465,9 @@ albedo = shLerp(albedo, diffuseTex, blendValues@shPropertyString(blendmap_compon
|
|||
shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0));
|
||||
|
||||
#if IS_FIRST_PASS
|
||||
shOutputColour(0).a = 1;
|
||||
shOutputColour(0).a = 1.0;
|
||||
#else
|
||||
shOutputColour(0).a = 1.f-previousAlpha;
|
||||
shOutputColour(0).a = 1.0-previousAlpha;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -737,7 +737,7 @@ namespace Physic
|
|||
{
|
||||
}
|
||||
|
||||
std::pair<std::string,float> PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly,bool ignoreHeightMap, Ogre::Vector3* normal)
|
||||
std::pair<std::string,float> PhysicEngine::rayTest(const btVector3 &from, const btVector3 &to, bool raycastingObjectOnly, bool ignoreHeightMap, Ogre::Vector3* normal)
|
||||
{
|
||||
std::string name = "";
|
||||
float d = -1;
|
||||
|
@ -801,7 +801,7 @@ namespace Physic
|
|||
return std::make_pair(false, 1);
|
||||
}
|
||||
|
||||
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
|
||||
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(const btVector3& from, const btVector3& to)
|
||||
{
|
||||
MyRayResultCallback resultCallback1;
|
||||
resultCallback1.m_collisionFilterGroup = 0xff;
|
||||
|
|
|
@ -302,13 +302,13 @@ namespace Physic
|
|||
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
|
||||
* If \a normal is non-NULL, the hit normal will be written there (if there is a hit)
|
||||
*/
|
||||
std::pair<std::string,float> rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true,
|
||||
std::pair<std::string,float> rayTest(const btVector3& from,const btVector3& to,bool raycastingObjectOnly = true,
|
||||
bool ignoreHeightMap = false, Ogre::Vector3* normal = NULL);
|
||||
|
||||
/**
|
||||
* Return all objects hit by a ray.
|
||||
*/
|
||||
std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
|
||||
std::vector< std::pair<float, std::string> > rayTest2(const btVector3 &from, const btVector3 &to);
|
||||
|
||||
std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to);
|
||||
///< @return (hit, relative distance)
|
||||
|
|
Loading…
Reference in a new issue