1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-25 16:43:33 +00:00

Merge remote-tracking branch 'scrawl/master'

This commit is contained in:
Marc Zinnschlag 2015-07-27 11:10:16 +02:00
commit bafa86d3e9
41 changed files with 113 additions and 156 deletions

View File

@ -2,7 +2,6 @@
#define CSM_WOLRD_REFIDADAPTERIMP_H #define CSM_WOLRD_REFIDADAPTERIMP_H
#include <map> #include <map>
#include <iostream>
#include <QVariant> #include <QVariant>

View File

@ -394,8 +394,10 @@ namespace MWClass
damage = scaleDamage(damage, attacker, ptr); damage = scaleDamage(damage, attacker, ptr);
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "Health Damage", 1.0f, 1.0f); MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "Health Damage", 1.0f, 1.0f);
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
setActorHealth(ptr, health, attacker); MWMechanics::DynamicStat<float> health(getCreatureStats(ptr).getHealth());
health.setCurrent(health.getCurrent() - damage);
getCreatureStats(ptr).setHealth(health);
} }
else else
{ {
@ -430,26 +432,6 @@ namespace MWClass
} }
} }
void Creature::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
{
MWMechanics::CreatureStats &crstats = getCreatureStats(ptr);
bool wasDead = crstats.isDead();
MWMechanics::DynamicStat<float> stat(crstats.getHealth());
stat.setCurrent(health);
crstats.setHealth(stat);
if(!wasDead && crstats.isDead())
{
// actor was just killed
}
else if(wasDead && !crstats.isDead())
{
// actor was just resurrected
}
}
boost::shared_ptr<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {

View File

@ -72,8 +72,6 @@ namespace MWClass
virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const; virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const;
virtual void setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const;
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const; const MWWorld::Ptr& actor) const;
///< Generate action for activation ///< Generate action for activation

View File

@ -733,8 +733,9 @@ namespace MWClass
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->activateHitOverlay(); MWBase::Environment::get().getWindowManager()->activateHitOverlay();
} }
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; MWMechanics::DynamicStat<float> health(getCreatureStats(ptr).getHealth());
setActorHealth(ptr, health, attacker); health.setCurrent(health.getCurrent() - damage);
getCreatureStats(ptr).setHealth(health);
} }
else else
{ {
@ -779,26 +780,6 @@ namespace MWClass
} }
} }
void Npc::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
{
MWMechanics::CreatureStats &crstats = getCreatureStats(ptr);
bool wasDead = crstats.isDead();
MWMechanics::DynamicStat<float> stat(crstats.getHealth());
stat.setCurrent(health);
crstats.setHealth(stat);
if(!wasDead && crstats.isDead())
{
// actor was just killed
}
else if(wasDead && !crstats.isDead())
{
// actor was just resurrected
}
}
boost::shared_ptr<MWWorld::Action> Npc::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Npc::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {

View File

@ -87,8 +87,6 @@ namespace MWClass
virtual void block(const MWWorld::Ptr &ptr) const; virtual void block(const MWWorld::Ptr &ptr) const;
virtual void setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const;
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const; const MWWorld::Ptr& actor) const;
///< Generate action for activation ///< Generate action for activation

View File

@ -699,7 +699,9 @@ namespace MWMechanics
{ {
// If drowning, apply 3 points of damage per second // If drowning, apply 3 points of damage per second
static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat(); static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat();
ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - fSuffocationDamage*duration); DynamicStat<float> health = stats.getHealth();
health.setCurrent(health.getCurrent() - fSuffocationDamage*duration);
stats.setHealth(health);
// Play a drowning sound // Play a drowning sound
MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();

View File

@ -8,7 +8,6 @@
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"

View File

@ -1,10 +1,9 @@
#include "aiavoiddoor.hpp" #include "aiavoiddoor.hpp"
#include <iostream>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "creaturestats.hpp" #include "creaturestats.hpp"
#include "movement.hpp" #include "movement.hpp"

View File

@ -5,22 +5,17 @@
#include <components/esm/aisequence.hpp> #include <components/esm/aisequence.hpp>
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/timestamp.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/dialoguemanager.hpp" #include "../mwbase/dialoguemanager.hpp"
#include "../mwrender/animation.hpp" #include "../mwrender/animation.hpp"
#include "creaturestats.hpp" #include "creaturestats.hpp"
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"
#include "character.hpp" // fixme: for getActiveWeapon #include "character.hpp"
#include "aicombataction.hpp" #include "aicombataction.hpp"
#include "combat.hpp" #include "combat.hpp"
@ -291,7 +286,7 @@ namespace MWMechanics
// Get weapon characteristics // Get weapon characteristics
if (actorClass.hasInventoryStore(actor)) if (actorClass.hasInventoryStore(actor))
{ {
//Get weapon speed and range //Get weapon range
MWWorld::ContainerStoreIterator weaponSlot = MWWorld::ContainerStoreIterator weaponSlot =
MWMechanics::getActiveWeapon(actorClass.getCreatureStats(actor), actorClass.getInventoryStore(actor), &weaptype); MWMechanics::getActiveWeapon(actorClass.getCreatureStats(actor), actorClass.getInventoryStore(actor), &weaptype);

View File

@ -6,7 +6,6 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"

View File

@ -1,8 +1,7 @@
#include "aifollow.hpp" #include "aifollow.hpp"
#include <iostream>
#include <components/esm/aisequence.hpp> #include <components/esm/aisequence.hpp>
#include <components/esm/loadcell.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"

View File

@ -1,7 +1,10 @@
#include "aipackage.hpp" #include "aipackage.hpp"
#include <cmath> #include <cmath>
#include <components/esm/loadcell.hpp>
#include <components/esm/loadland.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"

View File

@ -1,12 +1,12 @@
#include "aipursue.hpp" #include "aipursue.hpp"
#include <components/esm/aisequence.hpp> #include <components/esm/aisequence.hpp>
#include <components/esm/loadmgef.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/action.hpp" #include "../mwworld/action.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"

View File

@ -1,6 +1,7 @@
#include "aisequence.hpp" #include "aisequence.hpp"
#include <limits>
#include "aipackage.hpp" #include "aipackage.hpp"
#include "aistate.hpp" #include "aistate.hpp"
@ -14,9 +15,6 @@
#include <components/esm/aisequence.hpp> #include <components/esm/aisequence.hpp>
#include "../mwworld/class.hpp"
#include "creaturestats.hpp"
#include "npcstats.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"

View File

@ -1,6 +1,7 @@
#include "aitravel.hpp" #include "aitravel.hpp"
#include <components/esm/aisequence.hpp> #include <components/esm/aisequence.hpp>
#include <components/esm/loadcell.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"

View File

@ -408,14 +408,13 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
mCurrentMovement = movementAnimName; mCurrentMovement = movementAnimName;
if(!mCurrentMovement.empty()) if(!mCurrentMovement.empty())
{ {
float vel, speedmult = 1.0f;
bool isrunning = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) bool isrunning = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run)
&& !MWBase::Environment::get().getWorld()->isFlying(mPtr); && !MWBase::Environment::get().getWorld()->isFlying(mPtr);
// For non-flying creatures, MW uses the Walk animation to calculate the animation velocity // For non-flying creatures, MW uses the Walk animation to calculate the animation velocity
// even if we are running. This must be replicated, otherwise the observed speed would differ drastically. // even if we are running. This must be replicated, otherwise the observed speed would differ drastically.
std::string anim = mCurrentMovement; std::string anim = mCurrentMovement;
mAdjustMovementAnimSpeed = true;
if (mPtr.getClass().getTypeName() == typeid(ESM::Creature).name() if (mPtr.getClass().getTypeName() == typeid(ESM::Creature).name()
&& !(mPtr.get<ESM::Creature>()->mBase->mFlags & ESM::Creature::Flies)) && !(mPtr.get<ESM::Creature>()->mBase->mFlags & ESM::Creature::Flies))
{ {
@ -423,46 +422,34 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
const StateInfo *stateinfo = std::find_if(sMovementList, sMovementListEnd, FindCharState(walkState)); const StateInfo *stateinfo = std::find_if(sMovementList, sMovementListEnd, FindCharState(walkState));
anim = stateinfo->groupname; anim = stateinfo->groupname;
if (mMovementSpeed > 0.0f && (vel=mAnimation->getVelocity(anim)) > 1.0f) mMovementAnimSpeed = mAnimation->getVelocity(anim);
speedmult = mMovementSpeed / vel; if (mMovementAnimSpeed <= 1.0f)
else {
// Another bug: when using a fallback animation (e.g. RunForward as fallback to SwimRunForward), // Another bug: when using a fallback animation (e.g. RunForward as fallback to SwimRunForward),
// then the equivalent Walk animation will not use a fallback, and if that animation doesn't exist // then the equivalent Walk animation will not use a fallback, and if that animation doesn't exist
// we will play without any scaling. // we will play without any scaling.
// Makes the speed attribute of most water creatures totally useless. // Makes the speed attribute of most water creatures totally useless.
// And again, this can not be fixed without patching game data. // And again, this can not be fixed without patching game data.
speedmult = 1.f; mAdjustMovementAnimSpeed = false;
mMovementAnimSpeed = 1.f;
}
} }
else else
{ {
if(mMovementSpeed > 0.0f && (vel=mAnimation->getVelocity(anim)) > 1.0f) mMovementAnimSpeed = mAnimation->getVelocity(anim);
{
speedmult = mMovementSpeed / vel; if (mMovementAnimSpeed <= 1.0f)
}
else if (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)
speedmult = 1.f; // adjusted each frame
else if (mMovementSpeed > 0.0f)
{ {
// The first person anims don't have any velocity to calculate a speed multiplier from. // The first person anims don't have any velocity to calculate a speed multiplier from.
// We use the third person velocities instead. // We use the third person velocities instead.
// FIXME: should be pulled from the actual animation, but it is not presently loaded. // FIXME: should be pulled from the actual animation, but it is not presently loaded.
speedmult = mMovementSpeed / (isrunning ? 222.857f : 154.064f); mMovementAnimSpeed = (isrunning ? 222.857f : 154.064f);
mMovementAnimationControlled = false; mMovementAnimationControlled = false;
} }
} }
MWRender::Animation::AnimPriority priorityMovement (Priority_Movement); mAnimation->play(mCurrentMovement, Priority_Movement, movemask, false,
if ((movement == CharState_TurnLeft || movement == CharState_TurnRight) 1.f, ((mode!=2)?"start":"loop start"), "stop", 0.0f, ~0ul);
&& mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()
&& MWBase::Environment::get().getWorld()->isFirstPerson())
{
priorityMovement.mPriority[MWRender::Animation::BoneGroup_Torso] = 0;
priorityMovement.mPriority[MWRender::Animation::BoneGroup_LeftArm] = 0;
priorityMovement.mPriority[MWRender::Animation::BoneGroup_RightArm] = 0;
}
mAnimation->play(mCurrentMovement, priorityMovement, movemask, false,
speedmult, ((mode!=2)?"start":"loop start"), "stop", 0.0f, ~0ul);
} }
} }
@ -655,7 +642,6 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
, mAnimation(anim) , mAnimation(anim)
, mIdleState(CharState_None) , mIdleState(CharState_None)
, mMovementState(CharState_None) , mMovementState(CharState_None)
, mMovementSpeed(0.0f)
, mHasMovedInXY(false) , mHasMovedInXY(false)
, mMovementAnimationControlled(true) , mMovementAnimationControlled(true)
, mDeathState(CharState_None) , mDeathState(CharState_None)
@ -1066,7 +1052,7 @@ bool CharacterController::updateWeaponState()
} }
MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon); MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon);
priorityWeapon.mPriority[MWRender::Animation::BoneGroup_LowerBody] = 0; priorityWeapon.mPriority[MWRender::Animation::BoneGroup_LowerBody] = Priority_WeaponLowerBody;
bool forcestateupdate = false; bool forcestateupdate = false;
if(weaptype != mWeaponType && mHitState != CharState_KnockDown && mHitState != CharState_KnockOut if(weaptype != mWeaponType && mHitState != CharState_KnockDown && mHitState != CharState_KnockOut
@ -1487,6 +1473,7 @@ void CharacterController::update(float duration)
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Class &cls = mPtr.getClass(); const MWWorld::Class &cls = mPtr.getClass();
osg::Vec3f movement(0.f, 0.f, 0.f); osg::Vec3f movement(0.f, 0.f, 0.f);
float speed = 0.f;
updateMagicEffects(); updateMagicEffects();
@ -1550,10 +1537,10 @@ void CharacterController::update(float duration)
vec = osg::Vec3f(0.f, 0.f, 0.f); vec = osg::Vec3f(0.f, 0.f, 0.f);
osg::Vec3f rot = cls.getRotationVector(mPtr); osg::Vec3f rot = cls.getRotationVector(mPtr);
mMovementSpeed = cls.getSpeed(mPtr); speed = cls.getSpeed(mPtr);
vec.x() *= mMovementSpeed; vec.x() *= speed;
vec.y() *= mMovementSpeed; vec.y() *= speed;
CharacterState movestate = CharState_None; CharacterState movestate = CharState_None;
CharacterState idlestate = CharState_SpecialIdle; CharacterState idlestate = CharState_SpecialIdle;
@ -1744,10 +1731,7 @@ void CharacterController::update(float duration)
: (sneak ? CharState_SneakBack : (sneak ? CharState_SneakBack
: (isrunning ? CharState_RunBack : CharState_WalkBack))); : (isrunning ? CharState_RunBack : CharState_WalkBack)));
} }
// Don't play turning animations during attack. It would break positioning of the arrow bone when releasing a shot. else if(rot.z() != 0.0f && !inwater && !sneak && !MWBase::Environment::get().getWorld()->isFirstPerson())
// Actually, in vanilla the turning animation is not even played when merely having equipped the weapon,
// but I don't think we need to go as far as that.
else if(rot.z() != 0.0f && !inwater && !sneak && mUpperBodyState < UpperCharState_StartToMinAttack)
{ {
if(rot.z() > 0.0f) if(rot.z() > 0.0f)
movestate = CharState_TurnRight; movestate = CharState_TurnRight;
@ -1807,6 +1791,11 @@ void CharacterController::update(float duration)
if (duration > 0) if (duration > 0)
mAnimation->adjustSpeedMult(mCurrentMovement, std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI))); mAnimation->adjustSpeedMult(mCurrentMovement, std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI)));
} }
else if (mMovementState != CharState_None && mAdjustMovementAnimSpeed)
{
float speedmult = speed / mMovementAnimSpeed;
mAnimation->adjustSpeedMult(mCurrentMovement, speedmult);
}
if (!mSkipAnim) if (!mSkipAnim)
{ {
@ -1845,7 +1834,7 @@ void CharacterController::update(float duration)
moved = osg::Vec3f(0.f, 0.f, 0.f); moved = osg::Vec3f(0.f, 0.f, 0.f);
// Ensure we're moving in generally the right direction... // Ensure we're moving in generally the right direction...
if(mMovementSpeed > 0.f) if(speed > 0.f)
{ {
float l = moved.length(); float l = moved.length();
@ -1927,7 +1916,6 @@ void CharacterController::clearAnimQueue()
mAnimQueue.clear(); mAnimQueue.clear();
} }
void CharacterController::forceStateUpdate() void CharacterController::forceStateUpdate()
{ {
if(!mAnimation) if(!mAnimation)

View File

@ -28,6 +28,7 @@ class CreatureStats;
enum Priority { enum Priority {
Priority_Default, Priority_Default,
Priority_WeaponLowerBody,
Priority_Jump, Priority_Jump,
Priority_Movement, Priority_Movement,
Priority_Hit, Priority_Hit,
@ -150,7 +151,8 @@ class CharacterController : public MWRender::Animation::TextKeyListener
CharacterState mMovementState; CharacterState mMovementState;
std::string mCurrentMovement; std::string mCurrentMovement;
float mMovementSpeed; float mMovementAnimSpeed;
bool mAdjustMovementAnimSpeed;
bool mHasMovedInXY; bool mHasMovedInXY;
bool mMovementAnimationControlled; bool mMovementAnimationControlled;

View File

@ -1049,6 +1049,19 @@ namespace MWMechanics
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
} }
void getFollowers (const MWWorld::Ptr& actor, std::set<MWWorld::Ptr>& out)
{
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
for(std::list<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
{
if (out.insert(*it).second)
{
getFollowers(*it, out);
}
}
}
bool MechanicsManager::commitCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, int arg, bool victimAware) bool MechanicsManager::commitCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, int arg, bool victimAware)
{ {
// NOTE: victim may be empty // NOTE: victim may be empty
@ -1070,6 +1083,10 @@ namespace MWMechanics
if (!victim.isEmpty() && (from - victim.getRefData().getPosition().asVec3()).length2() > radius*radius) if (!victim.isEmpty() && (from - victim.getRefData().getPosition().asVec3()).length2() > radius*radius)
neighbors.push_back(victim); neighbors.push_back(victim);
// get the player's followers / allies (works recursively) that will not report crimes
std::set<MWWorld::Ptr> playerFollowers;
getFollowers(player, playerFollowers);
// Did anyone see it? // Did anyone see it?
bool crimeSeen = false; bool crimeSeen = false;
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it) for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
@ -1085,11 +1102,6 @@ namespace MWMechanics
// TODO: Add mod support for stealth executions! // TODO: Add mod support for stealth executions!
|| (type == OT_Murder && *it != victim)) || (type == OT_Murder && *it != victim))
{ {
if (type == OT_Theft || type == OT_Pickpocket)
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
else if (type == OT_Trespassing)
MWBase::Environment::get().getDialogueManager()->say(*it, "intruder");
// Crime reporting only applies to NPCs // Crime reporting only applies to NPCs
if (!it->getClass().isNpc()) if (!it->getClass().isNpc())
continue; continue;
@ -1097,6 +1109,14 @@ namespace MWMechanics
if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim)) if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim))
continue; continue;
if (playerFollowers.find(*it) != playerFollowers.end())
continue;
if (type == OT_Theft || type == OT_Pickpocket)
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
else if (type == OT_Trespassing)
MWBase::Environment::get().getDialogueManager()->say(*it, "intruder");
crimeSeen = true; crimeSeen = true;
} }
} }

View File

@ -1,5 +1,7 @@
#include "obstacle.hpp" #include "obstacle.hpp"
#include <components/esm/loadcell.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"

View File

@ -12,6 +12,7 @@
#include <osgViewer/Viewer> #include <osgViewer/Viewer>
#include <components/esm/fogstate.hpp> #include <components/esm/fogstate.hpp>
#include <components/esm/loadcell.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/sceneutil/visitor.hpp> #include <components/sceneutil/visitor.hpp>
#include <components/files/memorystream.hpp> #include <components/files/memorystream.hpp>

View File

@ -17,6 +17,8 @@
#include <components/nifosg/controller.hpp> #include <components/nifosg/controller.hpp>
#include <components/sceneutil/controller.hpp> #include <components/sceneutil/controller.hpp>
#include <components/esm/loadcell.hpp>
#include "vismask.hpp" #include "vismask.hpp"
#include "ripplesimulation.hpp" #include "ripplesimulation.hpp"

View File

@ -567,7 +567,8 @@ namespace MWScript
{ {
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Weapon); runtime.push((ptr.getClass().hasInventoryStore(ptr) || ptr.getClass().isBipedal(ptr)) &&
ptr.getClass().getCreatureStats (ptr).getDrawState () == MWMechanics::DrawState_Weapon);
} }
}; };
@ -580,7 +581,7 @@ namespace MWScript
{ {
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Spell); runtime.push(ptr.getClass().getCreatureStats (ptr).getDrawState () == MWMechanics::DrawState_Spell);
} }
}; };

View File

@ -1,8 +1,6 @@
#include "actioneat.hpp" #include "actioneat.hpp"
#include <cstdlib>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"

View File

@ -5,13 +5,32 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <typeinfo> #include <typeinfo>
#include <map>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "livecellref.hpp" #include "livecellref.hpp"
#include "cellreflist.hpp" #include "cellreflist.hpp"
#include <components/esm/fogstate.hpp> #include <components/esm/loadacti.hpp>
#include <components/esm/records.hpp> #include <components/esm/loadalch.hpp>
#include <components/esm/loadappa.hpp>
#include <components/esm/loadarmo.hpp>
#include <components/esm/loadbook.hpp>
#include <components/esm/loadclot.hpp>
#include <components/esm/loadcont.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/loaddoor.hpp>
#include <components/esm/loadingr.hpp>
#include <components/esm/loadlevlist.hpp>
#include <components/esm/loadligh.hpp>
#include <components/esm/loadlock.hpp>
#include <components/esm/loadprob.hpp>
#include <components/esm/loadrepa.hpp>
#include <components/esm/loadstat.hpp>
#include <components/esm/loadweap.hpp>
#include <components/esm/loadnpc.hpp>
#include <components/esm/loadmisc.hpp>
#include "../mwmechanics/pathgrid.hpp" // TODO: maybe belongs in mwworld #include "../mwmechanics/pathgrid.hpp" // TODO: maybe belongs in mwworld

View File

@ -109,11 +109,6 @@ namespace MWWorld
throw std::runtime_error("class cannot be hit"); throw std::runtime_error("class cannot be hit");
} }
void Class::setActorHealth(const Ptr& ptr, float health, const Ptr& attacker) const
{
throw std::runtime_error("class does not have actor health");
}
boost::shared_ptr<Action> Class::activate (const Ptr& ptr, const Ptr& actor) const boost::shared_ptr<Action> Class::activate (const Ptr& ptr, const Ptr& actor) const
{ {
return boost::shared_ptr<Action> (new NullAction); return boost::shared_ptr<Action> (new NullAction);

View File

@ -136,12 +136,6 @@ namespace MWWorld
///< Play the appropriate sound for a blocked attack, depending on the currently equipped shield ///< Play the appropriate sound for a blocked attack, depending on the currently equipped shield
/// (default implementation: throw an exception) /// (default implementation: throw an exception)
virtual void setActorHealth(const Ptr& ptr, float health, const Ptr& attacker=Ptr()) const;
///< Sets a new current health value for the actor, optionally specifying the object causing
/// the change. Use this instead of using CreatureStats directly as this will make sure the
/// correct dialog and actor states are properly handled when being hurt or healed.
/// (default implementation: throw an exception)
virtual boost::shared_ptr<Action> activate (const Ptr& ptr, const Ptr& actor) const; virtual boost::shared_ptr<Action> activate (const Ptr& ptr, const Ptr& actor) const;
///< Generate action for activation (default implementation: return a null action). ///< Generate action for activation (default implementation: return a null action).

View File

@ -490,6 +490,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
{ {
int retCount = ContainerStore::remove(item, count, actor); int retCount = ContainerStore::remove(item, count, actor);
bool wasEquipped = false;
if (!item.getRefData().getCount()) if (!item.getRefData().getCount())
{ {
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
@ -500,6 +501,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
if (*mSlots[slot] == item) if (*mSlots[slot] == item)
{ {
unequipSlot(slot, actor); unequipSlot(slot, actor);
wasEquipped = true;
break; break;
} }
} }
@ -507,7 +509,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
// If an armor/clothing item is removed, try to find a replacement, // If an armor/clothing item is removed, try to find a replacement,
// but not for the player nor werewolves. // but not for the player nor werewolves.
if ((actor != MWBase::Environment::get().getWorld()->getPlayerPtr()) if (wasEquipped && (actor != MWBase::Environment::get().getWorld()->getPlayerPtr())
&& !(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())) && !(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()))
{ {
std::string type = item.getTypeName(); std::string type = item.getTypeName();

View File

@ -87,7 +87,6 @@ namespace MWWorld
float mMultiplier; float mMultiplier;
}; };
// TODO: store in savegame
typedef std::map<std::string, std::vector<EffectParams> > TEffectMagnitudes; typedef std::map<std::string, std::vector<EffectParams> > TEffectMagnitudes;
TEffectMagnitudes mPermanentMagicEffectMagnitudes; TEffectMagnitudes mPermanentMagicEffectMagnitudes;

View File

@ -1,7 +1,6 @@
#include "manualref.hpp" #include "manualref.hpp"
#include "esmstore.hpp" #include "esmstore.hpp"
#include "cellstore.hpp"
namespace namespace
{ {

View File

@ -1,7 +1,7 @@
#include "player.hpp" #include "player.hpp"
#include <stdexcept> #include <stdexcept>
#include <iostream>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
@ -19,11 +19,9 @@
#include "../mwmechanics/movement.hpp" #include "../mwmechanics/movement.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/actors.hpp"
#include "class.hpp" #include "class.hpp"
#include "ptr.hpp" #include "ptr.hpp"
#include "inventorystore.hpp"
#include "cellstore.hpp" #include "cellstore.hpp"
namespace MWWorld namespace MWWorld
@ -327,6 +325,7 @@ namespace MWWorld
} }
catch (...) catch (...)
{ {
std::cerr << "Player cell '" << player.mCellId.mWorldspace << "' no longer exists" << std::endl;
// Cell no longer exists. Place the player in a default cell. // Cell no longer exists. Place the player in a default cell.
ESM::Position pos = mPlayer.mData.getPosition(); ESM::Position pos = mPlayer.mData.getPosition();
MWBase::Environment::get().getWorld()->indexToPosition(0, 0, pos.pos[0], pos.pos[1], true); MWBase::Environment::get().getWorld()->indexToPosition(0, 0, pos.pos[0], pos.pos[1], true);

View File

@ -1,15 +1,12 @@
#include "scene.hpp" #include "scene.hpp"
#include <limits> #include <limits>
#include <iostream>
#include <components/nif/niffile.hpp>
#include <components/loadinglistener/loadinglistener.hpp> #include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/vfs/manager.hpp>
#include <osg/PositionAttitudeTransform>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"

View File

@ -1,5 +1,4 @@
#include "store.hpp" #include "store.hpp"
#include "esmstore.hpp"
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>

View File

@ -14,13 +14,11 @@
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include <components/esm/cellid.hpp>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/files/collections.hpp> #include <components/files/collections.hpp>
#include <components/compiler/locals.hpp>
#include <components/esm/cellid.hpp>
#include <components/esm/esmreader.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>

View File

@ -1,7 +1,5 @@
#include "fileparser.hpp" #include "fileparser.hpp"
#include <iostream>
#include "tokenloc.hpp" #include "tokenloc.hpp"
#include "scanner.hpp" #include "scanner.hpp"

View File

@ -5,8 +5,6 @@
#include <osg/Image> #include <osg/Image>
#include <osg/Plane> #include <osg/Plane>
#include <iostream>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>

View File

@ -1,7 +1,6 @@
#include "constrainedfilestream.hpp" #include "constrainedfilestream.hpp"
#include <streambuf> #include <streambuf>
#include <iostream>
#include "lowlevelfile.hpp" #include "lowlevelfile.hpp"

View File

@ -2,7 +2,6 @@
#include "interpreter.hpp" #include "interpreter.hpp"
#include <cassert> #include <cassert>
#include <iostream>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>

View File

@ -3,7 +3,6 @@
#include <cstdio> #include <cstdio>
#include <vector> #include <vector>
#include <list> #include <list>
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <BulletCollision/CollisionShapes/btBoxShape.h> #include <BulletCollision/CollisionShapes/btBoxShape.h>

View File

@ -1,7 +1,6 @@
#include "attach.hpp" #include "attach.hpp"
#include <stdexcept> #include <stdexcept>
#include <iostream>
#include <osg/NodeVisitor> #include <osg/NodeVisitor>
#include <osg/Group> #include <osg/Group>

View File

@ -1,5 +1,7 @@
#include "lightmanager.hpp" #include "lightmanager.hpp"
#include <stdexcept>
#include <osg/NodeVisitor> #include <osg/NodeVisitor>
#include <osg/Geode> #include <osg/Geode>
@ -9,9 +11,6 @@
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <iostream>
#include <stdexcept>
namespace SceneUtil namespace SceneUtil
{ {

View File

@ -1,7 +1,5 @@
#include "material.hpp" #include "material.hpp"
#include <iostream>
#include <osg/Depth> #include <osg/Depth>
#include <osg/TexEnvCombine> #include <osg/TexEnvCombine>
#include <osg/Texture2D> #include <osg/Texture2D>