mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
72a81a2381
@ -74,7 +74,7 @@ add_openmw_dir (mwmechanics
|
||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
||||
disease
|
||||
disease pickpocket
|
||||
)
|
||||
|
||||
add_openmw_dir (mwbase
|
||||
|
@ -88,6 +88,9 @@ namespace MWBase
|
||||
virtual int countDeaths (const std::string& id) const = 0;
|
||||
///< Return the number of deaths for actors with the given ID.
|
||||
|
||||
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
|
||||
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0;
|
||||
|
||||
enum PersuasionType
|
||||
{
|
||||
PT_Admire,
|
||||
|
@ -613,7 +613,7 @@ 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, "thief");
|
||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||
|
||||
if(object.isEmpty())
|
||||
{
|
||||
|
@ -6,10 +6,13 @@
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "../mwmechanics/pickpocket.hpp"
|
||||
|
||||
#include "countdialog.hpp"
|
||||
#include "tradewindow.hpp"
|
||||
#include "inventorywindow.hpp"
|
||||
@ -123,6 +126,7 @@ namespace MWGui
|
||||
, mSelectedItem(-1)
|
||||
, mModel(NULL)
|
||||
, mSortModel(NULL)
|
||||
, mPickpocketDetected(false)
|
||||
{
|
||||
getWidget(mDisposeCorpseButton, "DisposeCorpseButton");
|
||||
getWidget(mTakeButton, "TakeButton");
|
||||
@ -171,6 +175,9 @@ namespace MWGui
|
||||
|
||||
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
|
||||
{
|
||||
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
|
||||
return;
|
||||
|
||||
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
|
||||
}
|
||||
|
||||
@ -208,6 +215,7 @@ namespace MWGui
|
||||
|
||||
void ContainerWindow::open(const MWWorld::Ptr& container, bool loot)
|
||||
{
|
||||
mPickpocketDetected = false;
|
||||
mPtr = container;
|
||||
|
||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name() && !loot)
|
||||
@ -230,6 +238,28 @@ namespace MWGui
|
||||
setTitle(MWWorld::Class::get(container).getName(container));
|
||||
}
|
||||
|
||||
void ContainerWindow::close()
|
||||
{
|
||||
WindowBase::close();
|
||||
|
||||
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
|
||||
if (!MWBase::Environment::get().getWindowManager()->containsMode(GM_Container)
|
||||
&& !mPickpocketDetected // If it was already detected while taking an item, no need to check now
|
||||
)
|
||||
{
|
||||
MWMechanics::Pickpocket pickpocket(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(),
|
||||
mPtr);
|
||||
if (pickpocket.finish())
|
||||
{
|
||||
// TODO: crime
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
|
||||
mPickpocketDetected = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
|
||||
@ -255,8 +285,13 @@ namespace MWGui
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
}
|
||||
|
||||
playerModel->copyItem(mModel->getItem(i), mModel->getItem(i).mCount);
|
||||
mModel->removeItem(mModel->getItem(i), mModel->getItem(i).mCount);
|
||||
const ItemStack& item = mModel->getItem(i);
|
||||
|
||||
if (!onTakeItem(item, item.mCount))
|
||||
break;
|
||||
|
||||
playerModel->copyItem(item, item.mCount);
|
||||
mModel->removeItem(item, item.mCount);
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||
@ -283,4 +318,22 @@ namespace MWGui
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||
}
|
||||
|
||||
bool ContainerWindow::onTakeItem(const ItemStack &item, int count)
|
||||
{
|
||||
if (dynamic_cast<PickpocketItemModel*>(mModel))
|
||||
{
|
||||
MWMechanics::Pickpocket pickpocket(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(),
|
||||
mPtr);
|
||||
if (pickpocket.pick(item.mBase, count))
|
||||
{
|
||||
// TODO: crime
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
|
||||
mPickpocketDetected = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -52,10 +52,13 @@ namespace MWGui
|
||||
ContainerWindow(DragAndDrop* dragAndDrop);
|
||||
|
||||
void open(const MWWorld::Ptr& container, bool loot=false);
|
||||
virtual void close();
|
||||
|
||||
private:
|
||||
DragAndDrop* mDragAndDrop;
|
||||
|
||||
bool mPickpocketDetected;
|
||||
|
||||
MWGui::ItemView* mItemView;
|
||||
SortFilterItemModel* mSortModel;
|
||||
ItemModel* mModel;
|
||||
@ -73,6 +76,9 @@ namespace MWGui
|
||||
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
||||
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
|
||||
|
||||
/// @return is taking the item allowed?
|
||||
bool onTakeItem(const ItemStack& item, int count);
|
||||
|
||||
virtual void onReferenceUnavailable();
|
||||
};
|
||||
}
|
||||
|
@ -158,50 +158,49 @@ namespace MWMechanics
|
||||
calculateDynamicStats (ptr);
|
||||
calculateCreatureStatModifiers (ptr, duration);
|
||||
|
||||
if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||
// AI
|
||||
if(MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||
{
|
||||
// AI
|
||||
if(MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
|
||||
//engage combat or not?
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
if(ptr != player && !creatureStats.isHostile())
|
||||
{
|
||||
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
|
||||
//engage combat or not?
|
||||
if(ptr != MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && !creatureStats.isHostile())
|
||||
ESM::Position playerpos = player.getRefData().getPosition();
|
||||
ESM::Position actorpos = ptr.getRefData().getPosition();
|
||||
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
|
||||
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
||||
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
||||
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
|
||||
float disp = 100; //creatures don't have disposition, so set it to 100 by default
|
||||
if(ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition();
|
||||
ESM::Position actorpos = ptr.getRefData().getPosition();
|
||||
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
|
||||
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
||||
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
||||
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
|
||||
float disp = 100; //creatures don't have disposition, so set it to 100 by default
|
||||
if(ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr);
|
||||
}
|
||||
bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
if( ( (fight == 100 )
|
||||
|| (fight >= 95 && d <= 3000)
|
||||
|| (fight >= 90 && d <= 2000)
|
||||
|| (fight >= 80 && d <= 1000)
|
||||
|| (fight >= 80 && disp <= 40)
|
||||
|| (fight >= 70 && disp <= 35 && d <= 1000)
|
||||
|| (fight >= 60 && disp <= 30 && d <= 1000)
|
||||
|| (fight >= 50 && disp == 0)
|
||||
|| (fight >= 40 && disp <= 10 && d <= 500) )
|
||||
&& LOS
|
||||
)
|
||||
{
|
||||
creatureStats.getAiSequence().stack(AiCombat("player"));
|
||||
creatureStats.setHostile(true);
|
||||
}
|
||||
disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr);
|
||||
}
|
||||
bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,player)
|
||||
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr);
|
||||
if( ( (fight == 100 )
|
||||
|| (fight >= 95 && d <= 3000)
|
||||
|| (fight >= 90 && d <= 2000)
|
||||
|| (fight >= 80 && d <= 1000)
|
||||
|| (fight >= 80 && disp <= 40)
|
||||
|| (fight >= 70 && disp <= 35 && d <= 1000)
|
||||
|| (fight >= 60 && disp <= 30 && d <= 1000)
|
||||
|| (fight >= 50 && disp == 0)
|
||||
|| (fight >= 40 && disp <= 10 && d <= 500) )
|
||||
&& LOS
|
||||
)
|
||||
{
|
||||
creatureStats.getAiSequence().stack(AiCombat("player"));
|
||||
creatureStats.setHostile(true);
|
||||
}
|
||||
|
||||
creatureStats.getAiSequence().execute (ptr,duration);
|
||||
}
|
||||
|
||||
// fatigue restoration
|
||||
calculateRestoration(ptr, duration);
|
||||
creatureStats.getAiSequence().execute (ptr,duration);
|
||||
}
|
||||
|
||||
// fatigue restoration
|
||||
calculateRestoration(ptr, duration);
|
||||
}
|
||||
|
||||
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include <OgreSceneNode.h>
|
||||
|
||||
#include "spellcasting.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
@ -725,4 +727,74 @@ namespace MWMechanics
|
||||
{
|
||||
return mAI;
|
||||
}
|
||||
|
||||
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
|
||||
float invisibility = stats.getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude;
|
||||
if (invisibility > 0)
|
||||
return false;
|
||||
|
||||
float sneakTerm = 0;
|
||||
if (ptr.getClass().getStance(ptr, MWWorld::Class::Sneak)
|
||||
&& !MWBase::Environment::get().getWorld()->isSwimming(ptr)
|
||||
&& MWBase::Environment::get().getWorld()->isOnGround(ptr))
|
||||
{
|
||||
static float fSneakSkillMult = store.find("fSneakSkillMult")->getFloat();
|
||||
static float fSneakBootMult = store.find("fSneakBootMult")->getFloat();
|
||||
float sneak = 0;
|
||||
if (ptr.getClass().isNpc())
|
||||
sneak = ptr.getClass().getNpcStats(ptr).getSkill(ESM::Skill::Sneak).getModified();
|
||||
int agility = stats.getAttribute(ESM::Attribute::Agility).getModified();
|
||||
int luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||
float bootWeight = 0;
|
||||
if (ptr.getClass().isNpc())
|
||||
{
|
||||
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
|
||||
MWWorld::ContainerStoreIterator it = inv.getSlot(MWWorld::InventoryStore::Slot_Boots);
|
||||
if (it != inv.end())
|
||||
bootWeight = it->getClass().getWeight(*it);
|
||||
}
|
||||
sneakTerm = fSneakSkillMult * sneak + 0.2 * agility + 0.1 * luck + bootWeight * fSneakBootMult;
|
||||
}
|
||||
|
||||
static float fSneakDistBase = store.find("fSneakDistanceBase")->getFloat();
|
||||
static float fSneakDistMult = store.find("fSneakDistanceMultiplier")->getFloat();
|
||||
|
||||
Ogre::Vector3 pos1 (ptr.getRefData().getPosition().pos);
|
||||
Ogre::Vector3 pos2 (observer.getRefData().getPosition().pos);
|
||||
float distTerm = fSneakDistBase + fSneakDistMult * pos1.distance(pos2);
|
||||
|
||||
float chameleon = stats.getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude;
|
||||
float x = sneakTerm * distTerm * stats.getFatigueTerm() + chameleon + invisibility;
|
||||
|
||||
CreatureStats& observerStats = observer.getClass().getCreatureStats(observer);
|
||||
int obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified();
|
||||
int obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||
float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude;
|
||||
int obsSneak = 0;
|
||||
if (observer.getClass().isNpc())
|
||||
obsSneak = observer.getClass().getNpcStats(observer).getSkill(ESM::Skill::Sneak).getModified();
|
||||
|
||||
float obsTerm = obsSneak + 0.2 * obsAgility + 0.1 * obsLuck - obsBlind;
|
||||
|
||||
// is ptr behind the observer?
|
||||
static float fSneakNoViewMult = store.find("fSneakNoViewMult")->getFloat();
|
||||
static float fSneakViewMult = store.find("fSneakViewMult")->getFloat();
|
||||
float y = 0;
|
||||
Ogre::Vector3 vec = pos1 - pos2;
|
||||
Ogre::Radian angle = observer.getRefData().getBaseNode()->getOrientation().yAxis().angleBetween(vec);
|
||||
if (angle < Ogre::Degree(90))
|
||||
y = obsTerm * observerStats.getFatigueTerm() * fSneakNoViewMult;
|
||||
else
|
||||
y = obsTerm * observerStats.getFatigueTerm() * fSneakViewMult;
|
||||
|
||||
float target = x - y;
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
|
||||
return (roll >= target);
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,9 @@ namespace MWMechanics
|
||||
void toLower(std::string npcFaction);
|
||||
///< Perform a persuasion action on NPC
|
||||
|
||||
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
|
||||
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer);
|
||||
|
||||
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
|
||||
|
||||
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
|
||||
|
67
apps/openmw/mwmechanics/pickpocket.cpp
Normal file
67
apps/openmw/mwmechanics/pickpocket.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "pickpocket.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "npcstats.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
||||
Pickpocket::Pickpocket(const MWWorld::Ptr &thief, const MWWorld::Ptr &victim)
|
||||
: mThief(thief)
|
||||
, mVictim(victim)
|
||||
{
|
||||
}
|
||||
|
||||
float Pickpocket::getChanceModifier(const MWWorld::Ptr &ptr, float add)
|
||||
{
|
||||
NpcStats& stats = ptr.getClass().getNpcStats(ptr);
|
||||
float agility = stats.getAttribute(ESM::Attribute::Agility).getModified();
|
||||
float luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||
float sneak = stats.getSkill(ESM::Skill::Sneak).getModified();
|
||||
return (add + 0.2 * agility + 0.1 * luck + sneak) * stats.getFatigueTerm();
|
||||
}
|
||||
|
||||
bool Pickpocket::getDetected(float valueTerm)
|
||||
{
|
||||
float x = getChanceModifier(mThief);
|
||||
float y = getChanceModifier(mVictim, valueTerm);
|
||||
|
||||
float t = 2*x - y;
|
||||
|
||||
NpcStats& pcStats = mThief.getClass().getNpcStats(mThief);
|
||||
float pcSneak = pcStats.getSkill(ESM::Skill::Sneak).getModified();
|
||||
int iPickMinChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iPickMinChance")->getInt();
|
||||
int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iPickMaxChance")->getInt();
|
||||
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (t < pcSneak / iPickMinChance)
|
||||
{
|
||||
return (roll > int(pcSneak / iPickMinChance));
|
||||
}
|
||||
else
|
||||
{
|
||||
t = std::min(float(iPickMaxChance), t);
|
||||
return (roll > int(t));
|
||||
}
|
||||
}
|
||||
|
||||
bool Pickpocket::pick(MWWorld::Ptr item, int count)
|
||||
{
|
||||
float stackValue = item.getClass().getValue(item) * count;
|
||||
float fPickPocketMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("fPickPocketMod")->getFloat();
|
||||
float valueTerm = 10 * fPickPocketMod * stackValue;
|
||||
|
||||
return getDetected(valueTerm);
|
||||
}
|
||||
|
||||
bool Pickpocket::finish()
|
||||
{
|
||||
return getDetected(0.f);
|
||||
}
|
||||
|
||||
}
|
30
apps/openmw/mwmechanics/pickpocket.hpp
Normal file
30
apps/openmw/mwmechanics/pickpocket.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef OPENMW_MECHANICS_PICKPOCKET_H
|
||||
#define OPENMW_MECHANICS_PICKPOCKET_H
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
||||
class Pickpocket
|
||||
{
|
||||
public:
|
||||
Pickpocket (const MWWorld::Ptr& thief, const MWWorld::Ptr& victim);
|
||||
|
||||
/// Steal some items
|
||||
/// @return Was the thief detected?
|
||||
bool pick (MWWorld::Ptr item, int count);
|
||||
/// End the pickpocketing process
|
||||
/// @return Was the thief detected?
|
||||
bool finish ();
|
||||
|
||||
private:
|
||||
bool getDetected(float valueTerm);
|
||||
float getChanceModifier(const MWWorld::Ptr& ptr, float add=0);
|
||||
MWWorld::Ptr mThief;
|
||||
MWWorld::Ptr mVictim;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -231,6 +231,7 @@ namespace MWMechanics
|
||||
{
|
||||
float mProgress;
|
||||
public:
|
||||
SkillValue() : mProgress(0) {}
|
||||
float getProgress() const { return mProgress; }
|
||||
void setProgress(float progress) { mProgress = progress; }
|
||||
};
|
||||
|
@ -358,19 +358,21 @@ namespace MWScript
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpGetDetected : public Interpreter::Opcode1
|
||||
class OpGetDetected : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
|
||||
MWWorld::Ptr observer = R()(runtime);
|
||||
std::string actorID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer value = false; // TODO replace with implementation
|
||||
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true);
|
||||
|
||||
std::cout << "AiGetDetected: " << actorID << ", " << value << std::endl;
|
||||
Interpreter::Type_Integer value =
|
||||
MWBase::Environment::get().getWorld()->getLOS(observer, actor) &&
|
||||
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, observer);
|
||||
|
||||
runtime.push (value);
|
||||
}
|
||||
@ -432,8 +434,8 @@ namespace MWScript
|
||||
new OpGetAiPackageDone<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeGetCurrentAiPackage, new OpGetCurrentAIPackage<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeGetCurrentAiPackageExplicit, new OpGetCurrentAIPackage<ExplicitRef>);
|
||||
interpreter.installSegment3 (Compiler::Ai::opcodeGetDetected, new OpGetDetected<ImplicitRef>);
|
||||
interpreter.installSegment3 (Compiler::Ai::opcodeGetDetectedExplicit, new OpGetDetected<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeGetDetected, new OpGetDetected<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeGetDetectedExplicit, new OpGetDetected<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSight, new OpGetLineOfSight<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSightExplicit, new OpGetLineOfSight<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Ai::opcodeToggleAI, new OpToggleAI<ImplicitRef>);
|
||||
|
@ -79,13 +79,13 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr,
|
||||
{
|
||||
const MWWorld::ContainerStoreIterator& retVal = MWWorld::ContainerStore::add(itemPtr, count, actorPtr, setOwner);
|
||||
|
||||
// Auto-equip items if an armor/clothing item is added, but not for the player nor werewolves
|
||||
// Auto-equip items if an armor/clothing or weapon item is added, but not for the player nor werewolves
|
||||
if ((actorPtr.getRefData().getHandle() != "player")
|
||||
&& !(MWWorld::Class::get(actorPtr).getNpcStats(actorPtr).isWerewolf())
|
||||
&& !actorPtr.getClass().getCreatureStats(actorPtr).isDead())
|
||||
{
|
||||
std::string type = itemPtr.getTypeName();
|
||||
if ((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()))
|
||||
if ((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()) || (type == typeid(ESM::Weapon).name()))
|
||||
autoEquip(actorPtr);
|
||||
}
|
||||
|
||||
@ -185,7 +185,10 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
||||
|
||||
// Only autoEquip if we are the original owner of the item.
|
||||
// This stops merchants from auto equipping anything you sell to them.
|
||||
if (!Misc::StringUtils::ciEqual(test.getCellRef().mOwner, actor.getCellRef().mRefID))
|
||||
// ...unless this is a companion, he should always equip items given to him.
|
||||
if (!Misc::StringUtils::ciEqual(test.getCellRef().mOwner, actor.getCellRef().mRefID) &&
|
||||
(actor.getClass().getScript(actor).empty() ||
|
||||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion")))
|
||||
continue;
|
||||
|
||||
int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test);
|
||||
|
@ -1840,13 +1840,6 @@ namespace MWWorld
|
||||
|
||||
bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc)
|
||||
{
|
||||
// This is a placeholder! Needs to go into an NPC awareness check function (see
|
||||
// https://wiki.openmw.org/index.php?title=Research:NPC_AI_Behaviour#NPC_Awareness_Check )
|
||||
if (targetNpc.getClass().getCreatureStats(targetNpc).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
|
||||
return false;
|
||||
if (targetNpc.getClass().getCreatureStats(targetNpc).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude > 100)
|
||||
return false;
|
||||
|
||||
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
|
||||
float* pos1 = npc.getRefData().getPosition().pos;
|
||||
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();
|
||||
|
@ -1209,20 +1209,27 @@ ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bo
|
||||
|
||||
if(isskinned)
|
||||
{
|
||||
// Apparently both are allowed. Sigh.
|
||||
// This could also mean that filters are supposed to work on the actual node
|
||||
// hierarchy, rather than just trishapes, and the 'tri ' should be omitted?
|
||||
std::string filter = "@shape=tri "+bonename;
|
||||
std::string filter2 = "@shape="+bonename;
|
||||
Misc::StringUtils::toLower(filter);
|
||||
Misc::StringUtils::toLower(filter2);
|
||||
for(size_t i = 0;i < scene->mEntities.size();i++)
|
||||
{
|
||||
Ogre::Entity *entity = scene->mEntities[i];
|
||||
if(entity->hasSkeleton())
|
||||
{
|
||||
if(entity == scene->mSkelBase ||
|
||||
entity->getMesh()->getName().find(filter) != std::string::npos)
|
||||
entity->getMesh()->getName().find(filter) != std::string::npos
|
||||
|| entity->getMesh()->getName().find(filter2) != std::string::npos)
|
||||
parentNode->attachObject(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(entity->getMesh()->getName().find(filter) == std::string::npos)
|
||||
if(entity->getMesh()->getName().find(filter) == std::string::npos
|
||||
|| entity->getMesh()->getName().find(filter2) == std::string::npos)
|
||||
entity->detachFromParent();
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 600 300" name="_Main">
|
||||
<Property key="MinSize" value="245 145"/>
|
||||
<Property key="Visible" value="false"/>
|
||||
|
||||
<!-- Items -->
|
||||
<Widget type="ItemView" skin="MW_ItemView" position="5 5 575 225" name="ItemView" align="Left Top Stretch">
|
||||
|
Loading…
x
Reference in New Issue
Block a user