forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
1b03eec63e
46 changed files with 390 additions and 154 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <OgreRoot.h>
|
||||
#include <OgreRenderWindow.h>
|
||||
#include <OgreEntity.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
|
|
|
@ -112,6 +112,8 @@ namespace MWBase
|
|||
OffenseType type, int arg=0) = 0;
|
||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
|
||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0;
|
||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||
/// @return was it illegal, and someone saw you doing it?
|
||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
|
||||
|
|
|
@ -227,9 +227,6 @@ namespace MWBase
|
|||
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons = std::vector<std::string>(), bool showInDialogueModeOnly = false) = 0;
|
||||
virtual void staticMessageBox(const std::string& message) = 0;
|
||||
virtual void removeStaticMessageBox() = 0;
|
||||
|
||||
virtual void enterPressed () = 0;
|
||||
virtual void activateKeyPressed () = 0;
|
||||
virtual int readPressedButton() = 0;
|
||||
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||
|
||||
|
|
|
@ -157,6 +157,10 @@ namespace MWBase
|
|||
///< Return a pointer to a liveCellRef with the given name.
|
||||
/// \param activeOnly do non search inactive cells.
|
||||
|
||||
virtual MWWorld::Ptr searchPtr (const std::string& name, bool activeOnly) = 0;
|
||||
///< Return a pointer to a liveCellRef with the given name.
|
||||
/// \param activeOnly do non search inactive cells.
|
||||
|
||||
virtual MWWorld::Ptr getPtrViaHandle (const std::string& handle) = 0;
|
||||
///< Return a pointer to a liveCellRef with the given Ogre handle.
|
||||
|
||||
|
@ -451,6 +455,11 @@ namespace MWBase
|
|||
/// Update the value of some globals according to the world state, which may be used by dialogue entries.
|
||||
/// This should be called when initiating a dialogue.
|
||||
virtual void updateDialogueGlobals() = 0;
|
||||
|
||||
/// Moves all stolen items from \a ptr to the closest evidence chest.
|
||||
virtual void confiscateStolenItems(const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
virtual void goToJail () = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -307,6 +307,17 @@ namespace MWClass
|
|||
autoCalculateSkills(ref->mBase, data->mNpcStats);
|
||||
}
|
||||
|
||||
if (data->mNpcStats.getFactionRanks().size())
|
||||
{
|
||||
static const int iAutoRepFacMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iAutoRepFacMod")->getInt();
|
||||
static const int iAutoRepLevMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iAutoRepLevMod")->getInt();
|
||||
int rank = data->mNpcStats.getFactionRanks().begin()->second;
|
||||
|
||||
data->mNpcStats.setReputation(iAutoRepFacMod * (rank+1) + iAutoRepLevMod * (data->mNpcStats.getLevel()-1));
|
||||
}
|
||||
|
||||
data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
||||
|
||||
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
|
||||
|
@ -587,6 +598,10 @@ namespace MWClass
|
|||
|
||||
// NOTE: 'object' and/or 'attacker' may be empty.
|
||||
|
||||
// Attacking peaceful NPCs is a crime
|
||||
if (ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
|
||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
||||
|
||||
if(!successful)
|
||||
{
|
||||
// TODO: Handle HitAttemptOnMe script function
|
||||
|
@ -615,7 +630,13 @@ namespace MWClass
|
|||
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
||||
// something, alert the character controller, scripts, etc.
|
||||
|
||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (roll < chance)
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||
}
|
||||
getCreatureStats(ptr).setAttacked(true);//used in CharacterController
|
||||
|
||||
if(object.isEmpty())
|
||||
|
|
|
@ -29,11 +29,12 @@ namespace MWGui
|
|||
|
||||
MyGUI::Button* backButton;
|
||||
getWidget(backButton, "BackButton");
|
||||
backButton->setCaptionWithReplacing("#{sMessageQuestionAnswer3}");
|
||||
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
|
||||
|
||||
MyGUI::Button* okButton;
|
||||
getWidget(okButton, "OKButton");
|
||||
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
|
||||
okButton->setCaptionWithReplacing("#{sMessageQuestionAnswer2}");
|
||||
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,6 +139,7 @@ namespace MWGui
|
|||
|
||||
mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked);
|
||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
|
||||
mCloseButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ContainerWindow::onKeyPressed);
|
||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
||||
|
||||
setCoord(200,0,600,300);
|
||||
|
@ -234,11 +235,21 @@ namespace MWGui
|
|||
|
||||
mItemView->setModel (mSortModel);
|
||||
|
||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
|
||||
|
||||
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
|
||||
// or we end up using a possibly invalid model.
|
||||
setTitle(MWWorld::Class::get(container).getName(container));
|
||||
}
|
||||
|
||||
void ContainerWindow::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
||||
{
|
||||
if (_key == MyGUI::KeyCode::Space)
|
||||
onCloseButtonClicked(mCloseButton);
|
||||
if (_key == MyGUI::KeyCode::Return || _key == MyGUI::KeyCode::NumpadEnter)
|
||||
onTakeAllButtonClicked(mTakeButton);
|
||||
}
|
||||
|
||||
void ContainerWindow::close()
|
||||
{
|
||||
WindowBase::close();
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace MWGui
|
|||
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
||||
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
||||
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
|
||||
void onKeyPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char);
|
||||
|
||||
/// @return is taking the item allowed?
|
||||
bool onTakeItem(const ItemStack& item, int count);
|
||||
|
|
|
@ -257,7 +257,7 @@ namespace MWGui
|
|||
{
|
||||
if (mEffects.size() <= 0)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage30}");
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu11}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
namespace MWGui
|
||||
{
|
||||
|
||||
MessageBoxManager::MessageBoxManager ()
|
||||
MessageBoxManager::MessageBoxManager (float timePerChar)
|
||||
{
|
||||
// TODO: fMessageTimePerChar
|
||||
mMessageBoxSpeed = 0.1;
|
||||
mInterMessageBoxe = NULL;
|
||||
mStaticMessageBox = NULL;
|
||||
mLastButtonPressed = -1;
|
||||
mMessageBoxSpeed = timePerChar;
|
||||
}
|
||||
|
||||
MessageBoxManager::~MessageBoxManager ()
|
||||
|
@ -63,7 +62,8 @@ namespace MWGui
|
|||
{
|
||||
MessageBox *box = new MessageBox(*this, message);
|
||||
box->mCurrentTime = 0;
|
||||
box->mMaxTime = message.length()*mMessageBoxSpeed;
|
||||
std::string realMessage = MyGUI::LanguageManager::getInstance().replaceTags(message);
|
||||
box->mMaxTime = realMessage.length()*mMessageBoxSpeed;
|
||||
|
||||
if(stat)
|
||||
mStaticMessageBox = box;
|
||||
|
@ -127,12 +127,6 @@ namespace MWGui
|
|||
mMessageBoxSpeed = speed;
|
||||
}
|
||||
|
||||
void MessageBoxManager::okayPressed ()
|
||||
{
|
||||
if(mInterMessageBoxe != NULL)
|
||||
mInterMessageBoxe->okayPressed();
|
||||
}
|
||||
|
||||
int MessageBoxManager::readPressedButton ()
|
||||
{
|
||||
int pressed = mLastButtonPressed;
|
||||
|
@ -333,23 +327,25 @@ namespace MWGui
|
|||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveMessageBox::okayPressed()
|
||||
{
|
||||
|
||||
// Set key focus to "Ok" button
|
||||
std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}"));
|
||||
std::vector<MyGUI::Button*>::const_iterator button;
|
||||
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
||||
{
|
||||
if(Misc::StringUtils::lowerCase((*button)->getCaption()) == ok)
|
||||
{
|
||||
buttonActivated(*button);
|
||||
MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f);
|
||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(*button);
|
||||
(*button)->eventKeyButtonPressed += MyGUI::newDelegate(this, &InteractiveMessageBox::onKeyPressed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveMessageBox::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
||||
{
|
||||
if (_key == MyGUI::KeyCode::Return || _key == MyGUI::KeyCode::NumpadEnter || _key == MyGUI::KeyCode::Space)
|
||||
buttonActivated(_sender);
|
||||
}
|
||||
|
||||
void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed)
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace MWGui
|
|||
class MessageBoxManager
|
||||
{
|
||||
public:
|
||||
MessageBoxManager ();
|
||||
MessageBoxManager (float timePerChar);
|
||||
~MessageBoxManager ();
|
||||
void onFrame (float frameDuration);
|
||||
void createMessageBox (const std::string& message, bool stat = false);
|
||||
|
@ -33,7 +33,6 @@ namespace MWGui
|
|||
bool removeMessageBox (MessageBox *msgbox);
|
||||
void setMessageBoxSpeed (int speed);
|
||||
|
||||
void okayPressed();
|
||||
int readPressedButton ();
|
||||
|
||||
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
|
||||
|
@ -74,7 +73,6 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons);
|
||||
void okayPressed ();
|
||||
void mousePressed (MyGUI::Widget* _widget);
|
||||
int readPressedButton ();
|
||||
|
||||
|
@ -82,6 +80,7 @@ namespace MWGui
|
|||
|
||||
private:
|
||||
void buttonActivated (MyGUI::Widget* _widget);
|
||||
void onKeyPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char);
|
||||
|
||||
MessageBoxManager& mMessageBoxManager;
|
||||
MyGUI::EditBox* mMessageWidget;
|
||||
|
|
|
@ -130,6 +130,14 @@ namespace MWGui
|
|||
return;
|
||||
}
|
||||
|
||||
// You can not train a skill above its governing attribute
|
||||
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillId);
|
||||
if (pcStats.getSkill(skillId).getBase() >= pcStats.getAttribute(skill->mData.mAttribute).getBase())
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage17}");
|
||||
return;
|
||||
}
|
||||
|
||||
// increase skill
|
||||
MWWorld::LiveCellRef<ESM::NPC> *playerRef = player.get<ESM::NPC>();
|
||||
|
||||
|
|
|
@ -207,7 +207,8 @@ namespace MWGui
|
|||
mConsole = new Console(w,h, mConsoleOnlyScripts);
|
||||
trackWindow(mConsole, "console");
|
||||
mJournal = JournalWindow::create(JournalViewModel::create ());
|
||||
mMessageBoxManager = new MessageBoxManager();
|
||||
mMessageBoxManager = new MessageBoxManager(
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fMessageTimePerChar")->getFloat());
|
||||
mInventoryWindow = new InventoryWindow(mDragAndDrop);
|
||||
mTradeWindow = new TradeWindow();
|
||||
trackWindow(mTradeWindow, "barter");
|
||||
|
@ -676,17 +677,6 @@ namespace MWGui
|
|||
mMessageBoxManager->removeStaticMessageBox();
|
||||
}
|
||||
|
||||
void WindowManager::enterPressed ()
|
||||
{
|
||||
mMessageBoxManager->okayPressed();
|
||||
}
|
||||
|
||||
void WindowManager::activateKeyPressed ()
|
||||
{
|
||||
mMessageBoxManager->okayPressed();
|
||||
mCountDialog->cancel();
|
||||
}
|
||||
|
||||
int WindowManager::readPressedButton ()
|
||||
{
|
||||
return mMessageBoxManager->readPressedButton();
|
||||
|
|
|
@ -222,8 +222,6 @@ namespace MWGui
|
|||
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons = std::vector<std::string>(), bool showInDialogueModeOnly = false);
|
||||
virtual void staticMessageBox(const std::string& message);
|
||||
virtual void removeStaticMessageBox();
|
||||
virtual void enterPressed ();
|
||||
virtual void activateKeyPressed ();
|
||||
virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||
|
||||
virtual void onFrame (float frameDuration);
|
||||
|
|
|
@ -195,14 +195,7 @@ namespace MWInput
|
|||
case A_Activate:
|
||||
resetIdleTime();
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
{
|
||||
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container)
|
||||
toggleContainer ();
|
||||
else
|
||||
MWBase::Environment::get().getWindowManager()->activateKeyPressed();
|
||||
}
|
||||
else
|
||||
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
activate();
|
||||
break;
|
||||
case A_Journal:
|
||||
|
@ -511,13 +504,6 @@ namespace MWInput
|
|||
|
||||
mInputBinder->keyPressed (arg);
|
||||
|
||||
if((arg.keysym.sym == SDLK_RETURN || arg.keysym.sym == SDLK_KP_ENTER)
|
||||
&& MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
{
|
||||
// Pressing enter when a messagebox is prompting for "ok" will activate the ok button
|
||||
MWBase::Environment::get().getWindowManager()->enterPressed();
|
||||
}
|
||||
|
||||
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
|
||||
|
||||
if (kc != OIS::KC_UNASSIGNED)
|
||||
|
@ -730,21 +716,6 @@ namespace MWInput
|
|||
// .. but don't touch any other mode, except container.
|
||||
}
|
||||
|
||||
void InputManager::toggleContainer()
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance ().isModalAny())
|
||||
return;
|
||||
|
||||
if(MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
{
|
||||
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container)
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
else
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InputManager::toggleConsole()
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance ().isModalAny())
|
||||
|
|
|
@ -173,7 +173,6 @@ namespace MWInput
|
|||
void toggleSpell();
|
||||
void toggleWeapon();
|
||||
void toggleInventory();
|
||||
void toggleContainer();
|
||||
void toggleConsole();
|
||||
void screenshot();
|
||||
void toggleJournal();
|
||||
|
|
|
@ -525,7 +525,7 @@ namespace MWMechanics
|
|||
ref.getPtr().getCellRef().mPos = ipos;
|
||||
|
||||
// TODO: Add AI to follow player and fight for him
|
||||
|
||||
// TODO: VFX_SummonStart, VFX_SummonEnd
|
||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos).getRefData().getHandle()));
|
||||
}
|
||||
|
@ -581,7 +581,8 @@ namespace MWMechanics
|
|||
if(timeLeft == 0.0f)
|
||||
{
|
||||
// If drowning, apply 3 points of damage per second
|
||||
ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - 3.0f*duration);
|
||||
static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat();
|
||||
ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - fSuffocationDamage*duration);
|
||||
|
||||
// Play a drowning sound as necessary for the player
|
||||
if(ptr == world->getPlayerPtr())
|
||||
|
@ -593,7 +594,10 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
else
|
||||
stats.setTimeToStartDrowning(20);
|
||||
{
|
||||
static const float fHoldBreathTime = world->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->getFloat();
|
||||
stats.setTimeToStartDrowning(fHoldBreathTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
#include "creaturestats.hpp"
|
||||
#include "npcstats.hpp"
|
||||
|
@ -118,6 +119,17 @@ namespace MWMechanics
|
|||
}
|
||||
if( mTimer > 1)
|
||||
{
|
||||
if (actor.getClass().isNpc())
|
||||
{
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->getInt();
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (roll < chance)
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
|
||||
}
|
||||
}
|
||||
|
||||
MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true);
|
||||
mTimer = 0;
|
||||
}
|
||||
|
|
|
@ -598,7 +598,12 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
const ESM::MagicEffect *effect;
|
||||
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID);
|
||||
|
||||
const ESM::Static* castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
||||
const ESM::Static* castStatic;
|
||||
if (!effect->mCasting.empty())
|
||||
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
||||
else
|
||||
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
||||
|
||||
mAnimation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex);
|
||||
|
||||
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Hands");
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
namespace
|
||||
{
|
||||
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
||||
bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item)
|
||||
bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim)
|
||||
{
|
||||
const std::string& owner = item.getCellRef().mOwner;
|
||||
bool isOwned = !owner.empty();
|
||||
|
@ -33,6 +33,9 @@ namespace
|
|||
isFactionOwned = true;
|
||||
}
|
||||
|
||||
if (!item.getCellRef().mOwner.empty())
|
||||
victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().mOwner, true);
|
||||
|
||||
return (!isOwned && !isFactionOwned);
|
||||
}
|
||||
}
|
||||
|
@ -752,11 +755,9 @@ namespace MWMechanics
|
|||
|
||||
bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed)
|
||||
{
|
||||
if (isAllowedToUse(ptr, bed))
|
||||
return false;
|
||||
MWWorld::Ptr victim;
|
||||
if (!bed.getCellRef().mOwner.empty())
|
||||
victim = MWBase::Environment::get().getWorld()->getPtr(bed.getCellRef().mOwner, true);
|
||||
if (isAllowedToUse(ptr, bed, victim))
|
||||
return false;
|
||||
|
||||
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
|
||||
{
|
||||
|
@ -767,20 +768,26 @@ namespace MWMechanics
|
|||
return false;
|
||||
}
|
||||
|
||||
void MechanicsManager::objectOpened(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item)
|
||||
{
|
||||
MWWorld::Ptr victim;
|
||||
if (isAllowedToUse(ptr, item, victim))
|
||||
return;
|
||||
commitCrime(ptr, victim, OT_Trespassing);
|
||||
}
|
||||
|
||||
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, int count)
|
||||
{
|
||||
if (isAllowedToUse(ptr, item))
|
||||
return;
|
||||
MWWorld::Ptr victim;
|
||||
if (!item.getCellRef().mOwner.empty())
|
||||
victim = MWBase::Environment::get().getWorld()->getPtr(item.getCellRef().mOwner, true);
|
||||
|
||||
if (isAllowedToUse(ptr, item, victim))
|
||||
return;
|
||||
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
|
||||
}
|
||||
|
||||
bool MechanicsManager::commitCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg)
|
||||
{
|
||||
// TODO: expell from faction
|
||||
if (ptr.getRefData().getHandle() != "player")
|
||||
return false;
|
||||
|
||||
bool reported=false;
|
||||
for (Actors::PtrControllerMap::const_iterator it = mActors.begin(); it != mActors.end(); ++it)
|
||||
|
@ -797,10 +804,7 @@ namespace MWMechanics
|
|||
|
||||
// Actor has witnessed a crime. Will he report it?
|
||||
// (not sure, is > 0 correct?)
|
||||
if (it->first.getClass().getCreatureStats(it->first).getAiSetting(CreatureStats::AI_Alarm).getModified() > 0
|
||||
// This is a bit inconsistent, but AFAIK assaulted NPCs can not report if they are alone
|
||||
&& (type != OT_Assault || it->first != victim)
|
||||
)
|
||||
if (it->first.getClass().getCreatureStats(it->first).getAiSetting(CreatureStats::AI_Alarm).getModified() > 0)
|
||||
{
|
||||
// TODO: stats.setAlarmed(true) on NPCs within earshot
|
||||
// fAlarmRadius ?
|
||||
|
@ -830,10 +834,32 @@ namespace MWMechanics
|
|||
else if (type == OT_Theft)
|
||||
arg *= store.find("fCrimeStealing")->getFloat();
|
||||
|
||||
// TODO: In some cases (type == Assault), if no NPCs are within earshot, the report will have no effect.
|
||||
// however other crime types seem to be always produce a bounty.
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sCrimeMessage}");
|
||||
ptr.getClass().getNpcStats(ptr).setBounty(ptr.getClass().getNpcStats(ptr).getBounty()
|
||||
+ arg);
|
||||
|
||||
if (!victim.isEmpty())
|
||||
{
|
||||
int fight = 0;
|
||||
// Increase in fight rating for each type of crime
|
||||
if (type == OT_Trespassing || type == OT_SleepingInOwnedBed)
|
||||
fight = store.find("iFightTrespass")->getFloat();
|
||||
else if (type == OT_Pickpocket)
|
||||
fight = store.find("iFightPickpocket")->getInt();
|
||||
else if (type == OT_Assault)
|
||||
fight = store.find("iFightAttack")->getInt();
|
||||
else if (type == OT_Murder)
|
||||
fight = store.find("iFightKilling")->getInt();
|
||||
else if (type == OT_Theft)
|
||||
fight = store.find("fFightStealing")->getFloat();
|
||||
// Not sure if this should be permanent?
|
||||
fight = victim.getClass().getCreatureStats(victim).getAiSetting(CreatureStats::AI_Fight).getBase() + fight;
|
||||
victim.getClass().getCreatureStats(victim).setAiSetting(CreatureStats::AI_Fight, fight);
|
||||
}
|
||||
|
||||
// If committing a crime against a faction member, expell from the faction
|
||||
if (!victim.isEmpty() && victim.getClass().isNpc())
|
||||
{
|
||||
|
@ -851,6 +877,9 @@ namespace MWMechanics
|
|||
|
||||
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)
|
||||
{
|
||||
if (observer.getClass().getCreatureStats(observer).isDead())
|
||||
return false;
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
|
|
|
@ -113,6 +113,8 @@ namespace MWMechanics
|
|||
OffenseType type, int arg=0);
|
||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
|
||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item);
|
||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||
/// @return was it illegal, and someone saw you doing it?
|
||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "npcstats.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
|
@ -45,6 +46,7 @@ namespace MWMechanics
|
|||
resultMessage = "#{sLockImpossible}";
|
||||
else
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->objectOpened(mActor, lock);
|
||||
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
|
||||
if (roll <= x)
|
||||
{
|
||||
|
@ -86,6 +88,7 @@ namespace MWMechanics
|
|||
resultMessage = "#{sTrapImpossible}";
|
||||
else
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->objectOpened(mActor, trap);
|
||||
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
|
||||
if (roll <= x)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/actionteleport.hpp"
|
||||
|
@ -57,6 +57,7 @@ namespace MWMechanics
|
|||
ESM::EffectList reflectedEffects;
|
||||
std::vector<ActiveSpells::Effect> appliedLastingEffects;
|
||||
bool firstAppliedEffect = true;
|
||||
bool anyHarmfulEffect = false;
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt (effects.mList.begin());
|
||||
effectIt!=effects.mList.end(); ++effectIt)
|
||||
|
@ -77,6 +78,8 @@ namespace MWMechanics
|
|||
float magnitudeMult = 1;
|
||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && target.getClass().isActor())
|
||||
{
|
||||
anyHarmfulEffect = true;
|
||||
|
||||
// If player is attempting to cast a harmful spell, show the target's HP bar
|
||||
if (caster.getRefData().getHandle() == "player" && target != caster)
|
||||
MWBase::Environment::get().getWindowManager()->setEnemy(target);
|
||||
|
@ -167,7 +170,7 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
else
|
||||
applyInstantEffect(target, EffectKey(*effectIt), magnitude);
|
||||
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
||||
|
||||
// HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent.
|
||||
// This was probably just done to have the effect visible in the magic menu for a while
|
||||
|
@ -177,7 +180,7 @@ namespace MWMechanics
|
|||
|| effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute
|
||||
|| effectIt->mEffectID == ESM::MagicEffect::RestoreSkill
|
||||
)
|
||||
applyInstantEffect(target, EffectKey(*effectIt), magnitude);
|
||||
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
||||
|
||||
if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)
|
||||
{
|
||||
|
@ -197,15 +200,17 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
// Add VFX
|
||||
const ESM::Static* castStatic;
|
||||
if (!magicEffect->mHit.empty())
|
||||
{
|
||||
const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
|
||||
bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx;
|
||||
// Note: in case of non actor, a free effect should be fine as well
|
||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||
if (anim)
|
||||
anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "");
|
||||
}
|
||||
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
|
||||
else
|
||||
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_DefaultHit");
|
||||
|
||||
bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx;
|
||||
// Note: in case of non actor, a free effect should be fine as well
|
||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||
if (anim)
|
||||
anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "");
|
||||
}
|
||||
|
||||
// TODO: For Area effects, launch a growing particle effect that applies the effect to more actors as it hits them. Best managed in World.
|
||||
|
@ -218,9 +223,13 @@ namespace MWMechanics
|
|||
if (appliedLastingEffects.size())
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects,
|
||||
mSourceName, caster.getRefData().getHandle());
|
||||
|
||||
if (anyHarmfulEffect && target.getClass().isActor()
|
||||
&& target.getClass().getCreatureStats(target).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
|
||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(caster, target, MWBase::MechanicsManager::OT_Assault);
|
||||
}
|
||||
|
||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, MWMechanics::EffectKey effect, float magnitude)
|
||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, MWMechanics::EffectKey effect, float magnitude)
|
||||
{
|
||||
short effectId = effect.mId;
|
||||
if (!target.getClass().isActor())
|
||||
|
@ -232,11 +241,13 @@ namespace MWMechanics
|
|||
}
|
||||
else if (effectId == ESM::MagicEffect::Open)
|
||||
{
|
||||
// TODO: This is a crime
|
||||
if (target.getCellRef().mLockLevel <= magnitude)
|
||||
{
|
||||
if (target.getCellRef().mLockLevel > 0)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f);
|
||||
MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target);
|
||||
}
|
||||
target.getCellRef().mLockLevel = 0;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace MWMechanics
|
|||
inline int spellSchoolToSkill(int school)
|
||||
{
|
||||
std::map<int, int> schoolSkillMap; // maps spell school to skill id
|
||||
schoolSkillMap[0] = 11; // alteration
|
||||
schoolSkillMap[1] = 13; // conjuration
|
||||
schoolSkillMap[3] = 12; // illusion
|
||||
schoolSkillMap[2] = 10; // destruction
|
||||
schoolSkillMap[4] = 14; // mysticism
|
||||
schoolSkillMap[5] = 15; // restoration
|
||||
schoolSkillMap[0] = ESM::Skill::Alteration;
|
||||
schoolSkillMap[1] = ESM::Skill::Conjuration;
|
||||
schoolSkillMap[3] = ESM::Skill::Illusion;
|
||||
schoolSkillMap[2] = ESM::Skill::Destruction;
|
||||
schoolSkillMap[4] = ESM::Skill::Mysticism;
|
||||
schoolSkillMap[5] = ESM::Skill::Restoration;
|
||||
assert(schoolSkillMap.find(school) != schoolSkillMap.end());
|
||||
return schoolSkillMap[school];
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ namespace MWMechanics
|
|||
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
||||
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false);
|
||||
|
||||
void applyInstantEffect (const MWWorld::Ptr& target, MWMechanics::EffectKey effect, float magnitude);
|
||||
void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, MWMechanics::EffectKey effect, float magnitude);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -226,11 +226,10 @@ namespace MWRender
|
|||
mCamera->setPosition(0.f, 0.f, offset);
|
||||
}
|
||||
|
||||
void Camera::setSneakOffset()
|
||||
void Camera::setSneakOffset(float offset)
|
||||
{
|
||||
// TODO: iFirstPersonSneakDelta
|
||||
if(mAnimation)
|
||||
mAnimation->addFirstPersonOffset(Ogre::Vector3(0.f, 0.f, -9.8f));
|
||||
mAnimation->addFirstPersonOffset(Ogre::Vector3(0.f, 0.f, -offset));
|
||||
}
|
||||
|
||||
float Camera::getYaw()
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace MWRender
|
|||
/// As animation is tied to the camera, this needs
|
||||
/// to be set each frame after the animation is
|
||||
/// applied.
|
||||
void setSneakOffset();
|
||||
void setSneakOffset(float offset);
|
||||
|
||||
bool isFirstPerson() const
|
||||
{ return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); }
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <OgreSceneManager.h>
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
#include <libs/openengine/ogre/selectionbuffer.hpp>
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <OgreSubEntity.h>
|
||||
#include <OgreMeshManager.h>
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
#include "renderconst.hpp"
|
||||
|
||||
|
|
|
@ -351,8 +351,10 @@ void RenderingManager::update (float duration, bool paused)
|
|||
bool isInAir = !world->isOnGround(player);
|
||||
bool isSwimming = world->isSwimming(player);
|
||||
|
||||
static const int i1stPersonSneakDelta = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("i1stPersonSneakDelta")->getInt();
|
||||
if(isSneaking && !(isSwimming || isInAir))
|
||||
mCamera->setSneakOffset();
|
||||
mCamera->setSneakOffset(i1stPersonSneakDelta);
|
||||
|
||||
|
||||
mOcclusionQuery->update(duration);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <OgreShadowCameraSetupLiSPSM.h>
|
||||
#include <OgreShadowCameraSetupPSSM.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
#include <extern/shiny/Main/Factory.hpp>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <OgreMeshManager.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
#include "sky.hpp"
|
||||
#include "renderingmanager.hpp"
|
||||
|
|
|
@ -766,12 +766,7 @@ namespace MWScript
|
|||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr player = world->getPlayerPtr();
|
||||
world->teleportToClosestMarker(player, "prisonmarker");
|
||||
player.getClass().getNpcStats(player).setBounty(0);
|
||||
// TODO: pass time, change skills, show messagebox
|
||||
// TODO: move stolen items to closest evidence chest
|
||||
// iDaysinPrisonMod
|
||||
world->goToJail();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -782,8 +777,7 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
player.getClass().getNpcStats(player).setBounty(0);
|
||||
|
||||
// TODO: move stolen items to closest evidence chest
|
||||
MWBase::Environment::get().getWorld()->confiscateStolenItems(player);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -271,3 +271,15 @@ void MWWorld::Cells::getExteriorPtrs(const std::string &name, std::vector<MWWorl
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
void MWWorld::Cells::getInteriorPtrs(const std::string &name, std::vector<MWWorld::Ptr> &out)
|
||||
{
|
||||
for (std::map<std::string, Ptr::CellStore>::iterator iter = mInteriors.begin();
|
||||
iter!=mInteriors.end(); ++iter)
|
||||
{
|
||||
Ptr ptr = getPtrAndCache (name, iter->second);
|
||||
if (!ptr.isEmpty())
|
||||
out.push_back(ptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@ namespace MWWorld
|
|||
/// @note Due to the current implementation of getPtr this only supports one Ptr per cell.
|
||||
/// @note name must be lower case
|
||||
void getExteriorPtrs (const std::string& name, std::vector<MWWorld::Ptr>& out);
|
||||
|
||||
/// Get all Ptrs referencing \a name in interior cells
|
||||
/// @note Due to the current implementation of getPtr this only supports one Ptr per cell.
|
||||
/// @note name must be lower case
|
||||
void getInteriorPtrs (const std::string& name, std::vector<MWWorld::Ptr>& out);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,6 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot)
|
|||
void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
||||
{
|
||||
const MWMechanics::NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor);
|
||||
|
||||
TSlots slots_;
|
||||
initSlots (slots_);
|
||||
|
@ -266,10 +265,10 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
|||
case 0:
|
||||
continue;
|
||||
case 2:
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedLeft, actor);
|
||||
slots_[MWWorld::InventoryStore::Slot_CarriedLeft] = end();
|
||||
break;
|
||||
case 3:
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, actor);
|
||||
// Prefer keeping twohanded weapon
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -392,7 +391,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor)
|
|||
// Apply instant effects
|
||||
MWMechanics::CastSpell cast(actor, actor);
|
||||
if (magnitude)
|
||||
cast.applyInstantEffect(actor, effectIt->mEffectID, magnitude);
|
||||
cast.applyInstantEffect(actor, actor, effectIt->mEffectID, magnitude);
|
||||
}
|
||||
|
||||
if (magnitude)
|
||||
|
|
|
@ -216,7 +216,7 @@ namespace MWWorld
|
|||
mSky (true), mCells (mStore, mEsm),
|
||||
mActivationDistanceOverride (mActivationDistanceOverride),
|
||||
mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), mLevitationEnabled(false),
|
||||
mFacedDistance(FLT_MAX), mGodMode(false)
|
||||
mFacedDistance(FLT_MAX), mGodMode(false), mGoToJail(false)
|
||||
{
|
||||
mPhysics = new PhysicsSystem(renderer);
|
||||
mPhysEngine = mPhysics->getEngine();
|
||||
|
@ -259,6 +259,9 @@ namespace MWWorld
|
|||
|
||||
void World::startNewGame()
|
||||
{
|
||||
mGoToJail = false;
|
||||
mLevitationEnabled = true;
|
||||
mTeleportEnabled = true;
|
||||
mWorldScene->changeToVoid();
|
||||
|
||||
mStore.clearDynamic();
|
||||
|
@ -485,8 +488,9 @@ namespace MWWorld
|
|||
mLocalScripts.remove (ref);
|
||||
}
|
||||
|
||||
Ptr World::getPtr (const std::string& name, bool activeOnly)
|
||||
Ptr World::searchPtr (const std::string& name, bool activeOnly)
|
||||
{
|
||||
Ptr ret;
|
||||
// the player is always in an active cell.
|
||||
if (name=="player")
|
||||
{
|
||||
|
@ -514,12 +518,16 @@ namespace MWWorld
|
|||
|
||||
if (!activeOnly)
|
||||
{
|
||||
Ptr ptr = mCells.getPtr (lowerCaseName);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
ret = mCells.getPtr (lowerCaseName);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Ptr World::getPtr (const std::string& name, bool activeOnly)
|
||||
{
|
||||
Ptr ret = searchPtr(name, activeOnly);
|
||||
if (!ret.isEmpty())
|
||||
return ret;
|
||||
throw std::runtime_error ("unknown ID: " + name);
|
||||
}
|
||||
|
||||
|
@ -1267,6 +1275,9 @@ namespace MWWorld
|
|||
mRendering->playVideo(mFallback.getFallbackString("Movies_New_Game"), true);
|
||||
}
|
||||
|
||||
if (mGoToJail && !paused)
|
||||
goToJail();
|
||||
|
||||
updateWeather(duration);
|
||||
|
||||
mWorldScene->update (duration, paused);
|
||||
|
@ -2174,14 +2185,13 @@ namespace MWWorld
|
|||
|
||||
Ogre::Vector3 rot(ptr.getRefData().getPosition().rot);
|
||||
|
||||
// TODO: Why -rot.z, but not -rot.x?
|
||||
// TODO: Why -rot.z, but not -rot.x? (note: same issue in MovementSolver::move)
|
||||
Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z);
|
||||
orient = orient * Ogre::Quaternion(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X);
|
||||
|
||||
// This is just a guess, probably wrong
|
||||
static float fProjectileMinSpeed = getStore().get<ESM::GameSetting>().find("fProjectileMinSpeed")->getFloat();
|
||||
static float fProjectileMaxSpeed = getStore().get<ESM::GameSetting>().find("fProjectileMaxSpeed")->getFloat();
|
||||
float speed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * it->second.mSpeed;
|
||||
|
||||
static float fTargetSpellMaxSpeed = getStore().get<ESM::GameSetting>().find("fTargetSpellMaxSpeed")->getFloat();
|
||||
float speed = fTargetSpellMaxSpeed * it->second.mSpeed;
|
||||
|
||||
Ogre::Vector3 direction = orient.yAxis();
|
||||
direction.normalise();
|
||||
|
@ -2447,4 +2457,115 @@ namespace MWWorld
|
|||
mGlobalVariables->setInt("crimegoldturnin", turnIn);
|
||||
mGlobalVariables->setInt("pchasturnin", (turnIn <= playerGold) ? 1 : 0);
|
||||
}
|
||||
|
||||
void World::confiscateStolenItems(const Ptr &ptr)
|
||||
{
|
||||
Ogre::Vector3 playerPos;
|
||||
if (!findInteriorPositionInWorldSpace(ptr.getCell(), playerPos))
|
||||
playerPos = mPlayer->getLastKnownExteriorPosition();
|
||||
|
||||
MWWorld::Ptr closestChest;
|
||||
float closestDistance = FLT_MAX;
|
||||
|
||||
std::vector<MWWorld::Ptr> chests;
|
||||
mCells.getInteriorPtrs("stolen_goods", chests);
|
||||
|
||||
Ogre::Vector3 chestPos;
|
||||
for (std::vector<MWWorld::Ptr>::iterator it = chests.begin(); it != chests.end(); ++it)
|
||||
{
|
||||
if (!findInteriorPositionInWorldSpace(it->getCell(), chestPos))
|
||||
continue;
|
||||
|
||||
float distance = playerPos.squaredDistance(chestPos);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestChest = *it;
|
||||
}
|
||||
}
|
||||
|
||||
if (!closestChest.isEmpty())
|
||||
{
|
||||
ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
if (!it->getCellRef().mOwner.empty() && it->getCellRef().mOwner != "player")
|
||||
{
|
||||
closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest);
|
||||
store.remove(*it, it->getRefData().getCount(), ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::goToJail()
|
||||
{
|
||||
if (!mGoToJail)
|
||||
{
|
||||
// Save for next update, since the player should be able to read the dialog text first
|
||||
mGoToJail = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
mGoToJail = false;
|
||||
|
||||
MWWorld::Ptr player = getPlayerPtr();
|
||||
teleportToClosestMarker(player, "prisonmarker");
|
||||
int bounty = player.getClass().getNpcStats(player).getBounty();
|
||||
player.getClass().getNpcStats(player).setBounty(0);
|
||||
confiscateStolenItems(player);
|
||||
|
||||
int iDaysinPrisonMod = getStore().get<ESM::GameSetting>().find("iDaysinPrisonMod")->getInt();
|
||||
int days = std::max(1, bounty / iDaysinPrisonMod);
|
||||
|
||||
advanceTime(days * 24);
|
||||
|
||||
std::set<int> skills;
|
||||
for (int day=0; day<days; ++day)
|
||||
{
|
||||
int skill = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * ESM::Skill::Length;
|
||||
skills.insert(skill);
|
||||
|
||||
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill);
|
||||
if (skill == ESM::Skill::Security || skill == ESM::Skill::Sneak)
|
||||
value.setBase(std::min(100, value.getBase()+1));
|
||||
else
|
||||
value.setBase(value.getBase()-1);
|
||||
}
|
||||
|
||||
const Store<ESM::GameSetting>& gmst = getStore().get<ESM::GameSetting>();
|
||||
|
||||
std::string message;
|
||||
if (days == 1)
|
||||
message = gmst.find("sNotifyMessage42")->getString();
|
||||
else
|
||||
message = gmst.find("sNotifyMessage43")->getString();
|
||||
|
||||
std::stringstream dayStr;
|
||||
dayStr << days;
|
||||
if (message.find("%d") != std::string::npos)
|
||||
message.replace(message.find("%d"), 2, dayStr.str());
|
||||
|
||||
for (std::set<int>::iterator it = skills.begin(); it != skills.end(); ++it)
|
||||
{
|
||||
std::string skillName = gmst.find(ESM::Skill::sSkillNameIds[*it])->getString();
|
||||
std::stringstream skillValue;
|
||||
skillValue << player.getClass().getNpcStats(player).getSkill(*it).getBase();
|
||||
std::string skillMsg = gmst.find("sNotifyMessage44")->getString();
|
||||
if (*it == ESM::Skill::Sneak || *it == ESM::Skill::Security)
|
||||
skillMsg = gmst.find("sNotifyMessage39")->getString();
|
||||
|
||||
if (skillMsg.find("%s") != std::string::npos)
|
||||
skillMsg.replace(skillMsg.find("%s"), 2, skillName);
|
||||
if (skillMsg.find("%d") != std::string::npos)
|
||||
skillMsg.replace(skillMsg.find("%d"), 2, skillValue.str());
|
||||
message += "\n" + skillMsg;
|
||||
}
|
||||
|
||||
std::vector<std::string> buttons;
|
||||
buttons.push_back("#{sOk}");
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(message, buttons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ namespace MWWorld
|
|||
|
||||
bool mTeleportEnabled;
|
||||
bool mLevitationEnabled;
|
||||
bool mGoToJail;
|
||||
|
||||
/// Called when \a object is moved to an inactive cell
|
||||
void objectLeftActiveCell (MWWorld::Ptr object, MWWorld::Ptr movedPtr);
|
||||
|
@ -232,6 +233,10 @@ namespace MWWorld
|
|||
///< Return a pointer to a liveCellRef with the given name.
|
||||
/// \param activeOnly do non search inactive cells.
|
||||
|
||||
virtual Ptr searchPtr (const std::string& name, bool activeOnly);
|
||||
///< Return a pointer to a liveCellRef with the given name.
|
||||
/// \param activeOnly do non search inactive cells.
|
||||
|
||||
virtual Ptr getPtrViaHandle (const std::string& handle);
|
||||
///< Return a pointer to a liveCellRef with the given Ogre handle.
|
||||
|
||||
|
@ -536,6 +541,11 @@ namespace MWWorld
|
|||
/// Update the value of some globals according to the world state, which may be used by dialogue entries.
|
||||
/// This should be called when initiating a dialogue.
|
||||
virtual void updateDialogueGlobals();
|
||||
|
||||
/// Moves all stolen items from \a ptr to the closest evidence chest.
|
||||
virtual void confiscateStolenItems(const MWWorld::Ptr& ptr);
|
||||
|
||||
virtual void goToJail ();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -277,6 +277,8 @@ Ogre::String NIFMaterialLoader::getMaterial(const Nif::ShapeData *shapedata,
|
|||
if (itr != sMaterialMap.end())
|
||||
{
|
||||
// a suitable material exists already - use it
|
||||
sh::MaterialInstance* instance = sh::Factory::getInstance().getMaterialInstance(itr->second);
|
||||
needTangents = !sh::retrieveValue<sh::StringValue>(instance->getProperty("normalMap"), instance).get().empty();
|
||||
return itr->second;
|
||||
}
|
||||
// not found, create a new one
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <OgreTechnique.h>
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreEntity.h>
|
||||
#include <OgreSubEntity.h>
|
||||
#include <OgreTagPoint.h>
|
||||
|
@ -36,6 +35,9 @@
|
|||
#include <OgreMeshManager.h>
|
||||
#include <OgreSkeletonManager.h>
|
||||
#include <OgreControllerManager.h>
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreSceneManager.h>
|
||||
|
||||
#include <extern/shiny/Main/Factory.hpp>
|
||||
|
||||
|
|
|
@ -281,6 +281,7 @@ namespace Terrain
|
|||
// normal map (optional)
|
||||
bool useNormalMap = mNormalMapping && !mLayerList[layerOffset+i].mNormalMap.empty() && !renderCompositeMap;
|
||||
bool useParallax = useNormalMap && mParallaxMapping && layer.mParallax;
|
||||
bool useSpecular = layer.mSpecular;
|
||||
if (useNormalMap)
|
||||
{
|
||||
anyNormalMaps = true;
|
||||
|
@ -292,8 +293,11 @@ namespace Terrain
|
|||
sh::makeProperty (new sh::BooleanValue(useNormalMap)));
|
||||
p->mShaderProperties.setProperty ("use_parallax_" + Ogre::StringConverter::toString(i),
|
||||
sh::makeProperty (new sh::BooleanValue(useParallax)));
|
||||
p->mShaderProperties.setProperty ("use_specular_" + Ogre::StringConverter::toString(i),
|
||||
sh::makeProperty (new sh::BooleanValue(useSpecular)));
|
||||
boost::hash_combine(normalMaps, useNormalMap);
|
||||
boost::hash_combine(normalMaps, useNormalMap && layer.mParallax);
|
||||
boost::hash_combine(normalMaps, useSpecular);
|
||||
|
||||
if (i+layerOffset > 0)
|
||||
{
|
||||
|
|
|
@ -475,6 +475,7 @@ namespace Terrain
|
|||
|
||||
LayerInfo info;
|
||||
info.mParallax = false;
|
||||
info.mSpecular = false;
|
||||
info.mDiffuseMap = "textures\\" + texture;
|
||||
std::string texture_ = texture;
|
||||
boost::replace_last(texture_, ".", "_nh.");
|
||||
|
@ -491,6 +492,14 @@ namespace Terrain
|
|||
info.mNormalMap = "textures\\" + texture_;
|
||||
}
|
||||
|
||||
texture_ = texture;
|
||||
boost::replace_last(texture_, ".", "_diffusespec.");
|
||||
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("textures\\" + texture_))
|
||||
{
|
||||
info.mDiffuseMap = "textures\\" + texture_;
|
||||
info.mSpecular = true;
|
||||
}
|
||||
|
||||
mLayerInfoMap[texture] = info;
|
||||
|
||||
return info;
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Terrain
|
|||
std::string mDiffuseMap;
|
||||
std::string mNormalMap;
|
||||
bool mParallax; // Height info in normal map alpha channel?
|
||||
bool mSpecular; // Specular info in diffuse map alpha channel?
|
||||
};
|
||||
|
||||
/// We keep storage of terrain data abstract here since we need different implementations for game and editor
|
||||
|
|
|
@ -337,6 +337,7 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
|||
float2 layerUV = float2(UV.x, 1.f-UV.y) * 16; // Reverse Y, required to get proper tangents
|
||||
float2 thisLayerUV;
|
||||
float4 normalTex;
|
||||
float4 diffuseTex;
|
||||
|
||||
float3 eyeDir = normalize(cameraPos.xyz - worldPos);
|
||||
#if PARALLAX
|
||||
|
@ -358,19 +359,18 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
|||
thisLayerUV += TSeyeDir.xy * ( normalTex.a * PARALLAX_SCALE + PARALLAX_BIAS );
|
||||
#endif
|
||||
|
||||
#if IS_FIRST_PASS
|
||||
#if @shIterator == 0
|
||||
// first layer of first pass is the base layer and doesn't need a blend map
|
||||
albedo = shSample(diffuseMap0, layerUV);
|
||||
#else
|
||||
albedo = shLerp(albedo, shSample(diffuseMap@shIterator, thisLayerUV), blendValues@shPropertyString(blendmap_component_@shIterator));
|
||||
#endif
|
||||
diffuseTex = shSample(diffuseMap@shIterator, layerUV);
|
||||
#if !@shPropertyBool(use_specular_@shIterator)
|
||||
diffuseTex.a = 0;
|
||||
#endif
|
||||
|
||||
#if @shIterator == 0
|
||||
albedo = diffuseTex;
|
||||
#else
|
||||
#if @shIterator == 0
|
||||
albedo = shSample(diffuseMap@shIterator, layerUV);
|
||||
#else
|
||||
albedo = shLerp(albedo, shSample(diffuseMap@shIterator, thisLayerUV), blendValues@shPropertyString(blendmap_component_@shIterator));
|
||||
#endif
|
||||
albedo = shLerp(albedo, diffuseTex, blendValues@shPropertyString(blendmap_component_@shIterator));
|
||||
#endif
|
||||
|
||||
#if !IS_FIRST_PASS
|
||||
previousAlpha *= 1.f-blendValues@shPropertyString(blendmap_component_@shIterator);
|
||||
#endif
|
||||
|
||||
|
@ -448,7 +448,7 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
|||
float3 halfVec = normalize (light0Dir + eyeDir);
|
||||
|
||||
float3 specular = pow(max(dot(normal, halfVec), 0), 32) * lightSpec0;
|
||||
shOutputColour(0).xyz += specular * (1.f-albedo.a) * shadow;
|
||||
shOutputColour(0).xyz += specular * (albedo.a) * shadow;
|
||||
#endif
|
||||
|
||||
#if FOG
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</Widget>
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 450 18" align="Right Top">
|
||||
<Property key="TextAlign" value="Center"/>
|
||||
<Property key="Caption" value="#{sSpells}"/>
|
||||
<Property key="Caption" value="#{sServiceSpellsTitle}"/>
|
||||
</Widget>
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 0 24 24" name="Travel" align="Right Top">
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
<Property key="Caption" value="#D8C09A#{sTravel}"/>
|
||||
<Property key="Caption" value="#D8C09A#{sServiceTravelTitle}"/>
|
||||
</Widget>
|
||||
|
||||
|
||||
|
@ -32,4 +32,4 @@
|
|||
|
||||
</Widget>
|
||||
|
||||
</MyGUI>
|
||||
</MyGUI>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <OgreTextureManager.h>
|
||||
#include <OgreTexture.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
#include <extern/sdl4ogre/sdlwindowhelper.hpp>
|
||||
|
||||
|
|
Loading…
Reference in a new issue