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
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
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)
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
getCreatureStats(ptr).setAttacked(true);
if(!successful)
{
// TODO: Handle HitAttemptOnMe script function
@ -659,7 +661,6 @@ namespace MWClass
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
}
getCreatureStats(ptr).setAttacked(true);
// Check for knockdown
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();

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

@ -29,7 +29,7 @@
#include "aicombat.hpp"
#include "aifollow.hpp"
#include "aipersue.hpp"
#include "aipursue.hpp"
namespace
{
@ -719,34 +719,33 @@ namespace MWMechanics
CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(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.isHostile())
if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile())
{
/// \todo Move me! I shouldn't be here...
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt()) *
float(esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt()) *
esmStore.get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat();
// Attack on sight if bounty is greater than the cutoff
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt());
// Force dialogue on sight if bounty is greater than the cutoff
// In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty)
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().getMechanicsManager()->awarenessCheck(player, ptr))
{
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
creatureStats.setHostile(true);
npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() );
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
creatureStats.setAlarmed(true);
npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId());
}
}
// if I was a witness to a crime
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() )
{
// Calm witness down
if (ptr.getClass().isClass(ptr, "Guard"))
creatureStats.getAiSequence().stopPersue();
creatureStats.getAiSequence().stopPursuit();
creatureStats.getAiSequence().stopCombat();
// Reset factors to attack
@ -761,13 +760,12 @@ namespace MWMechanics
else if (!creatureStats.isHostile())
{
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
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
creatureStats.setHostile(true);
}
}
// if I didn't report a crime was I attacked?
else if (creatureStats.getAttacked() && !creatureStats.isHostile())
{

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

@ -1,4 +1,4 @@
#include "aipersue.hpp"
#include "aipursue.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
@ -11,15 +11,15 @@
#include "movement.hpp"
#include "creaturestats.hpp"
MWMechanics::AiPersue::AiPersue(const std::string &objectId)
MWMechanics::AiPursue::AiPursue(const std::string &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();
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);
ESM::Position targetPos = target.getRefData().getPosition();
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;
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])+
(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)
{
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]))
(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);
@ -100,7 +94,7 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration)
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
#define GAME_MWMECHANICS_AIPERSUE_H
#ifndef GAME_MWMECHANICS_AIPURSUE_H
#define GAME_MWMECHANICS_AIPURSUE_H
#include "aipackage.hpp"
#include <string>
@ -9,11 +9,11 @@
namespace MWMechanics
{
class AiPersue : public AiPackage
class AiPursue : public AiPackage
{
public:
AiPersue(const std::string &objectId);
virtual AiPersue *clone() const;
AiPursue(const std::string &objectId);
virtual AiPursue *clone() const;
virtual bool execute (const MWWorld::Ptr& actor,float duration);
///< \return Package completed?
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();
mPackages.erase (mPackages.begin());
@ -93,11 +93,16 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration)
{
if (!mPackages.empty())
{
mLastAiPackage = mPackages.front()->getTypeId();
if (mPackages.front()->execute (actor,duration))
MWMechanics::AiPackage* package = mPackages.front();
mLastAiPackage = package->getTypeId();
if (package->execute (actor,duration))
{
delete *mPackages.begin();
mPackages.erase (mPackages.begin());
// To account for the rare case where AiPackage::execute() queued another AI package
// (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;
}
else
@ -118,7 +123,7 @@ void MWMechanics::AiSequence::clear()
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
for (std::list<AiPackage *>::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter)

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

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

@ -227,10 +227,6 @@ namespace MWWorld
Ogre::Vector3 inertia(0.0f);
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
{
// 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
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
// where the creature gets above the waterline for some reason
if(newPosition.z < waterlevel && // started 3/4 under water
!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
newPosition.z <= waterlevel)
{

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

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

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

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

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

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

@ -115,7 +115,7 @@ namespace SFO
mWindowListener->windowClosed();
break;
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;
}
}
@ -241,8 +241,8 @@ namespace SFO
//eep, wrap the pointer manually if the input driver doesn't support
//relative positioning natively
int success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE);
if(relative && success != 0)
bool success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0;
if(relative && !success)
mWrapPointer = true;
//now remove all mouse events using the old setting from the queue

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

Loading…
Cancel
Save