Merge remote-tracking branch 'scrawl/master'

openmw-30
Marc Zinnschlag 11 years ago
commit 72b4945128

@ -67,7 +67,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
drawstate spells activespells npcstats aipackage aisequence aipersue alchemy aiwander aitravel aifollow drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
disease pickpocket levelledlist combat steering obstacle disease pickpocket levelledlist combat steering obstacle
) )

@ -624,6 +624,8 @@ namespace MWClass
if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
getCreatureStats(ptr).setAttacked(true);
if(!successful) if(!successful)
{ {
// TODO: Handle HitAttemptOnMe script function // TODO: Handle HitAttemptOnMe script function
@ -659,7 +661,6 @@ namespace MWClass
{ {
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit"); MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
} }
getCreatureStats(ptr).setAttacked(true);
// Check for knockdown // Check for knockdown
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat(); float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();

@ -215,16 +215,22 @@ namespace MWGui
{ {
std::vector<std::string> matches; std::vector<std::string> matches;
listNames(); listNames();
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches )); std::string oldCaption = mCommandLine->getCaption();
#if 0 std::string newCaption = complete( mCommandLine->getOnlyText(), matches );
int i = 0; mCommandLine->setCaption(newCaption);
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
// List candidates if repeatedly pressing tab
if (oldCaption == newCaption && matches.size())
{ {
printOK( *it ); int i = 0;
if( i == 50 ) printOK("");
break; for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
{
printOK( *it );
if( i == 50 )
break;
}
} }
#endif
} }
if(mCommandHistory.empty()) return; if(mCommandHistory.empty()) return;

@ -29,7 +29,7 @@
#include "aicombat.hpp" #include "aicombat.hpp"
#include "aifollow.hpp" #include "aifollow.hpp"
#include "aipersue.hpp" #include "aipursue.hpp"
namespace namespace
{ {
@ -719,34 +719,33 @@ namespace MWMechanics
CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr); NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr);
// If I'm a guard and I'm not hostile if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile())
if (ptr.getClass().isClass(ptr, "Guard") && !creatureStats.isHostile())
{ {
/// \todo Move me! I shouldn't be here... /// \todo Move me! I shouldn't be here...
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt()) * float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt());
float(esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt()) * // Force dialogue on sight if bounty is greater than the cutoff
esmStore.get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat(); // In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty)
// Attack on sight if bounty is greater than the cutoff
if ( player.getClass().getNpcStats(player).getBounty() >= cutoff if ( player.getClass().getNpcStats(player).getBounty() >= cutoff
// TODO: do not run these two every frame. keep an Aware state for each actor and update it every 0.2 s or so?
&& MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getWorld()->getLOS(ptr, player)
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr))
{ {
creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
creatureStats.setHostile(true); creatureStats.setAlarmed(true);
npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId());
} }
} }
// if I was a witness to a crime // if I was a witness to a crime
if (npcStats.getCrimeId() != -1) if (npcStats.getCrimeId() != -1)
{ {
// if you've payed for your crimes and I havent noticed // if you've paid for your crimes and I havent noticed
if( npcStats.getCrimeId() <= MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ) if( npcStats.getCrimeId() <= MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() )
{ {
// Calm witness down // Calm witness down
if (ptr.getClass().isClass(ptr, "Guard")) if (ptr.getClass().isClass(ptr, "Guard"))
creatureStats.getAiSequence().stopPersue(); creatureStats.getAiSequence().stopPursuit();
creatureStats.getAiSequence().stopCombat(); creatureStats.getAiSequence().stopCombat();
// Reset factors to attack // Reset factors to attack
@ -761,13 +760,12 @@ namespace MWMechanics
else if (!creatureStats.isHostile()) else if (!creatureStats.isHostile())
{ {
if (ptr.getClass().isClass(ptr, "Guard")) if (ptr.getClass().isClass(ptr, "Guard"))
creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
else else
creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.getAiSequence().stack(AiCombat(player), ptr);
creatureStats.setHostile(true); creatureStats.setHostile(true);
} }
} }
// if I didn't report a crime was I attacked? // if I didn't report a crime was I attacked?
else if (creatureStats.getAttacked() && !creatureStats.isHostile()) else if (creatureStats.getAttacked() && !creatureStats.isHostile())
{ {

@ -20,7 +20,7 @@ namespace MWMechanics
TypeIdFollow = 3, TypeIdFollow = 3,
TypeIdActivate = 4, TypeIdActivate = 4,
TypeIdCombat = 5, TypeIdCombat = 5,
TypeIdPersue = 6 TypeIdPursue = 6
}; };
virtual ~AiPackage(); virtual ~AiPackage();

@ -1,4 +1,4 @@
#include "aipersue.hpp" #include "aipursue.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -11,15 +11,15 @@
#include "movement.hpp" #include "movement.hpp"
#include "creaturestats.hpp" #include "creaturestats.hpp"
MWMechanics::AiPersue::AiPersue(const std::string &objectId) MWMechanics::AiPursue::AiPursue(const std::string &objectId)
: mObjectId(objectId) : mObjectId(objectId)
{ {
} }
MWMechanics::AiPersue *MWMechanics::AiPersue::clone() const MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const
{ {
return new AiPersue(*this); return new AiPursue(*this);
} }
bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
@ -52,11 +52,13 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration)
} }
} }
// Big TODO: Sync this with current AiFollow. Move common code to a shared base class or helpers (applies to all AI packages, way too much duplicated code)
MWWorld::Ptr target = world->getPtr(mObjectId,false); MWWorld::Ptr target = world->getPtr(mObjectId,false);
ESM::Position targetPos = target.getRefData().getPosition(); ESM::Position targetPos = target.getRefData().getPosition();
bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY;
if(!mPathFinder.isPathConstructed() || cellChange) if(!mPathFinder.isPathConstructed() || cellChange || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
{ {
mCellX = cell->mData.mX; mCellX = cell->mData.mX;
mCellY = cell->mData.mY; mCellY = cell->mData.mY;
@ -76,15 +78,7 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration)
if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+
(pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+
(pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200) (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 100*100)
{
movement.mPosition[1] = 0;
MWWorld::Ptr target = world->getPtr(mObjectId,false);
MWWorld::Class::get(target).activate(target,actor).get()->execute(actor);
return true;
}
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
{ {
movement.mPosition[1] = 0; movement.mPosition[1] = 0;
MWWorld::Ptr target = world->getPtr(mObjectId,false); MWWorld::Ptr target = world->getPtr(mObjectId,false);
@ -100,7 +94,7 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration)
return false; return false;
} }
int MWMechanics::AiPersue::getTypeId() const int MWMechanics::AiPursue::getTypeId() const
{ {
return TypeIdPersue; return TypeIdPursue;
} }

@ -1,5 +1,5 @@
#ifndef GAME_MWMECHANICS_AIPERSUE_H #ifndef GAME_MWMECHANICS_AIPURSUE_H
#define GAME_MWMECHANICS_AIPERSUE_H #define GAME_MWMECHANICS_AIPURSUE_H
#include "aipackage.hpp" #include "aipackage.hpp"
#include <string> #include <string>
@ -9,11 +9,11 @@
namespace MWMechanics namespace MWMechanics
{ {
class AiPersue : public AiPackage class AiPursue : public AiPackage
{ {
public: public:
AiPersue(const std::string &objectId); AiPursue(const std::string &objectId);
virtual AiPersue *clone() const; virtual AiPursue *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration); virtual bool execute (const MWWorld::Ptr& actor,float duration);
///< \return Package completed? ///< \return Package completed?
virtual int getTypeId() const; virtual int getTypeId() const;

@ -73,9 +73,9 @@ void MWMechanics::AiSequence::stopCombat()
} }
} }
void MWMechanics::AiSequence::stopPersue() void MWMechanics::AiSequence::stopPursuit()
{ {
while (getTypeId() == AiPackage::TypeIdPersue) while (getTypeId() == AiPackage::TypeIdPursue)
{ {
delete *mPackages.begin(); delete *mPackages.begin();
mPackages.erase (mPackages.begin()); mPackages.erase (mPackages.begin());
@ -93,11 +93,16 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration)
{ {
if (!mPackages.empty()) if (!mPackages.empty())
{ {
mLastAiPackage = mPackages.front()->getTypeId(); MWMechanics::AiPackage* package = mPackages.front();
if (mPackages.front()->execute (actor,duration)) mLastAiPackage = package->getTypeId();
if (package->execute (actor,duration))
{ {
delete *mPackages.begin(); // To account for the rare case where AiPackage::execute() queued another AI package
mPackages.erase (mPackages.begin()); // (e.g. AiPursue executing a dialogue script that uses startCombat)
std::list<MWMechanics::AiPackage*>::iterator toRemove =
std::find(mPackages.begin(), mPackages.end(), package);
mPackages.erase(toRemove);
delete package;
mDone = true; mDone = true;
} }
else else
@ -118,7 +123,7 @@ void MWMechanics::AiSequence::clear()
void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor) void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor)
{ {
if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPersue) if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPursue)
{ {
// Notify AiWander of our current position so we can return to it after combat finished // Notify AiWander of our current position so we can return to it after combat finished
for (std::list<AiPackage *>::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) for (std::list<AiPackage *>::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter)

@ -50,8 +50,8 @@ namespace MWMechanics
void stopCombat(); void stopCombat();
///< Removes all combat packages until first non-combat or stack empty. ///< Removes all combat packages until first non-combat or stack empty.
void stopPersue(); void stopPursuit();
///< Removes all persue packages until first non-persue or stack empty. ///< Removes all pursue packages until first non-pursue or stack empty.
bool isPackageDone() const; bool isPackageDone() const;
///< Has a package been completed during the last update? ///< Has a package been completed during the last update?

@ -563,7 +563,8 @@ void RenderingManager::configureAmbient(MWWorld::CellStore &mCell)
Ogre::ColourValue colour; Ogre::ColourValue colour;
colour.setAsABGR (mCell.getCell()->mAmbi.mSunlight); colour.setAsABGR (mCell.getCell()->mAmbi.mSunlight);
mSun->setDiffuseColour (colour); mSun->setDiffuseColour (colour);
mSun->setDirection(0,-1,0); mSun->setDirection(1,-1,-1);
sunEnable(false);
} }
} }
// Switch through lighting modes. // Switch through lighting modes.

@ -227,10 +227,6 @@ namespace MWWorld
Ogre::Vector3 inertia(0.0f); Ogre::Vector3 inertia(0.0f);
Ogre::Vector3 velocity; Ogre::Vector3 velocity;
bool canWalk = ptr.getClass().canWalk(ptr);
bool isBipedal = ptr.getClass().isBipedal(ptr);
bool isNpc = ptr.getClass().isNpc();
if(position.z < waterlevel || isFlying) // under water by 3/4 or can fly if(position.z < waterlevel || isFlying) // under water by 3/4 or can fly
{ {
// TODO: Shouldn't water have higher drag in calculating velocity? // TODO: Shouldn't water have higher drag in calculating velocity?
@ -277,14 +273,11 @@ namespace MWWorld
// NOTE: velocity is either z axis only or x & z axis // NOTE: velocity is either z axis only or x & z axis
Ogre::Vector3 nextpos = newPosition + velocity * remainingTime; Ogre::Vector3 nextpos = newPosition + velocity * remainingTime;
// If not able to fly, walk or bipedal don't allow to move out of water // If not able to fly, don't allow to swim up into the air
// TODO: this if condition may not work for large creatures or situations // TODO: this if condition may not work for large creatures or situations
// where the creature gets above the waterline for some reason // where the creature gets above the waterline for some reason
if(newPosition.z < waterlevel && // started 3/4 under water if(newPosition.z < waterlevel && // started 3/4 under water
!isFlying && // can't fly !isFlying && // can't fly
!canWalk && // can't walk
!isBipedal && // not bipedal (assume bipedals can walk)
!isNpc && // FIXME: shouldn't really need this
nextpos.z > waterlevel && // but about to go above water nextpos.z > waterlevel && // but about to go above water
newPosition.z <= waterlevel) newPosition.z <= waterlevel)
{ {

@ -37,7 +37,7 @@ namespace MWWorld
mTeleported(false), mTeleported(false),
mMarkedCell(NULL), mMarkedCell(NULL),
mCurrentCrimeId(-1), mCurrentCrimeId(-1),
mPayedCrimeId(-1) mPaidCrimeId(-1)
{ {
mPlayer.mBase = player; mPlayer.mBase = player;
mPlayer.mRef.mRefID = "player"; mPlayer.mRef.mRefID = "player";
@ -223,7 +223,7 @@ namespace MWWorld
player.mCellId = mCellStore->getCell()->getCellId(); player.mCellId = mCellStore->getCell()->getCellId();
player.mCurrentCrimeId = mCurrentCrimeId; player.mCurrentCrimeId = mCurrentCrimeId;
player.mPayedCrimeId = mPayedCrimeId; player.mPaidCrimeId = mPaidCrimeId;
player.mBirthsign = mSign; player.mBirthsign = mSign;
@ -273,7 +273,7 @@ namespace MWWorld
throw std::runtime_error ("invalid player state record (birthsign)"); throw std::runtime_error ("invalid player state record (birthsign)");
mCurrentCrimeId = player.mCurrentCrimeId; mCurrentCrimeId = player.mCurrentCrimeId;
mPayedCrimeId = player.mPayedCrimeId; mPaidCrimeId = player.mPaidCrimeId;
mSign = player.mBirthsign; mSign = player.mBirthsign;
@ -318,11 +318,11 @@ namespace MWWorld
void Player::recordCrimeId() void Player::recordCrimeId()
{ {
mPayedCrimeId = mCurrentCrimeId; mPaidCrimeId = mCurrentCrimeId;
} }
int Player::getCrimeId() const int Player::getCrimeId() const
{ {
return mPayedCrimeId; return mPaidCrimeId;
} }
} }

@ -48,7 +48,7 @@ namespace MWWorld
bool mTeleported; bool mTeleported;
int mCurrentCrimeId; // the id assigned witnesses int mCurrentCrimeId; // the id assigned witnesses
int mPayedCrimeId; // the last id payed off (0 bounty) int mPaidCrimeId; // the last id paid off (0 bounty)
public: public:
@ -105,8 +105,8 @@ namespace MWWorld
bool readRecord (ESM::ESMReader& reader, int32_t type); bool readRecord (ESM::ESMReader& reader, int32_t type);
int getNewCrimeId(); // get new id for witnesses int getNewCrimeId(); // get new id for witnesses
void recordCrimeId(); // record the payed crime id when bounty is 0 void recordCrimeId(); // record the paid crime id when bounty is 0
int getCrimeId() const; // get the last payed crime id int getCrimeId() const; // get the last paid crime id
}; };
} }
#endif #endif

@ -329,7 +329,6 @@ void WeatherManager::update(float duration)
const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior()); const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior());
if (!exterior) if (!exterior)
{ {
mRendering->sunDisable(false);
mRendering->skyDisable(); mRendering->skyDisable();
mRendering->getSkyManager()->setLightningStrength(0.f); mRendering->getSkyManager()->setLightningStrength(0.f);
stopSounds(true); stopSounds(true);

@ -33,7 +33,7 @@ struct Creature
Respawn = 0x002, Respawn = 0x002,
Weapon = 0x004, // Has weapon and shield Weapon = 0x004, // Has weapon and shield
None = 0x008, // ?? None = 0x008, // ?? This flag appears set for every creature in Morrowind.esm
Essential = 0x080, Essential = 0x080,
// Blood types // Blood types

@ -28,8 +28,8 @@ void ESM::Player::load (ESMReader &esm)
mCurrentCrimeId = -1; mCurrentCrimeId = -1;
esm.getHNOT (mCurrentCrimeId, "CURD"); esm.getHNOT (mCurrentCrimeId, "CURD");
mPayedCrimeId = -1; mPaidCrimeId = -1;
esm.getHNOT (mPayedCrimeId, "PAYD"); esm.getHNOT (mPaidCrimeId, "PAYD");
} }
void ESM::Player::save (ESMWriter &esm) const void ESM::Player::save (ESMWriter &esm) const
@ -52,5 +52,5 @@ void ESM::Player::save (ESMWriter &esm) const
esm.writeHNString ("SIGN", mBirthsign); esm.writeHNString ("SIGN", mBirthsign);
esm.writeHNT ("CURD", mCurrentCrimeId); esm.writeHNT ("CURD", mCurrentCrimeId);
esm.writeHNT ("PAYD", mPayedCrimeId); esm.writeHNT ("PAYD", mPaidCrimeId);
} }

@ -26,11 +26,11 @@ namespace ESM
std::string mBirthsign; std::string mBirthsign;
int mCurrentCrimeId; int mCurrentCrimeId;
int mPayedCrimeId; int mPaidCrimeId;
void load (ESMReader &esm); void load (ESMReader &esm);
void save (ESMWriter &esm) const; void save (ESMWriter &esm) const;
}; };
} }
#endif #endif

@ -115,7 +115,7 @@ namespace SFO
mWindowListener->windowClosed(); mWindowListener->windowClosed();
break; break;
default: default:
std::cerr << "Unhandled SDL event of type " << evt.type << std::endl; std::cerr << "Unhandled SDL event of type 0x" << std::hex << evt.type << std::endl;
break; break;
} }
} }
@ -241,8 +241,8 @@ namespace SFO
//eep, wrap the pointer manually if the input driver doesn't support //eep, wrap the pointer manually if the input driver doesn't support
//relative positioning natively //relative positioning natively
int success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE); bool success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0;
if(relative && success != 0) if(relative && !success)
mWrapPointer = true; mWrapPointer = true;
//now remove all mouse events using the old setting from the queue //now remove all mouse events using the old setting from the queue

@ -133,9 +133,9 @@ distant land = false
shader = true shader = true
[Water] [Water]
shader = true shader = false
refraction = true refraction = false
rtt size = 512 rtt size = 512
reflect terrain = true reflect terrain = true

Loading…
Cancel
Save