Conflicts:
	apps/openmw/main.cpp
actorid
scrawl 11 years ago
commit 19e5978a01

@ -989,8 +989,7 @@ void Record<ESM::NPC>::print()
std::cout << " Faction: " << mData.mFaction << std::endl;
std::cout << " Flags: " << npcFlags(mData.mFlags) << std::endl;
// Seriously?
if (mData.mNpdt52.mGold == -10)
if (mData.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
{
std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl;
std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl;
@ -1022,7 +1021,7 @@ void Record<ESM::NPC>::print()
std::cout << " Luck: " << (int)mData.mNpdt52.mLuck << std::endl;
std::cout << " Skills:" << std::endl;
for (int i = 0; i != 27; i++)
for (int i = 0; i != ESM::Skill::Length; i++)
std::cout << " " << skillLabel(i) << ": "
<< (int)((unsigned char)mData.mNpdt52.mSkills[i]) << std::endl;

@ -24,7 +24,12 @@ namespace EsmTool
bool mPrintPlain;
public:
RecordBase () { mPrintPlain = false; }
RecordBase ()
: mFlags(0)
, mPrintPlain(false)
{
}
virtual ~RecordBase() {}
const std::string &getId() const {

@ -75,15 +75,9 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile)
mLauncherSettings.setValue(QString("Profiles/currentprofile"), ui.profilesComboBox->currentText());
foreach(const ContentSelectorModel::EsmFile *item, items) {
if (item->gameFiles().size() == 0) {
mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName());
mGameSettings.setMultiValue(QString("content"), item->fileName());
} else {
mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName());
mGameSettings.setMultiValue(QString("content"), item->fileName());
}
}
}

@ -7,8 +7,6 @@ namespace CSMFilter
{
class AndNode : public NAryNode
{
bool mAnd;
public:
AndNode (const std::vector<boost::shared_ptr<Node> >& nodes);

@ -7,8 +7,6 @@ namespace CSMFilter
{
class OrNode : public NAryNode
{
bool mAnd;
public:
OrNode (const std::vector<boost::shared_ptr<Node> >& nodes);

@ -61,11 +61,11 @@ namespace CSMFilter
bool isString() const;
};
Token::Token (Type type) : mType (type) {}
Token::Token (Type type) : mType (type), mNumber(0.0) {}
Token::Token (Type type, const std::string& string) : mType (type), mString (string) {}
Token::Token (Type type, const std::string& string) : mType (type), mString (string), mNumber(0.0) {}
Token::Token (const std::string& string) : mType (Type_String), mString (string) {}
Token::Token (const std::string& string) : mType (Type_String), mString (string), mNumber(0.0) {}
Token::Token (double number) : mType (Type_Number), mNumber (number) {}

@ -44,7 +44,11 @@ namespace CSMSettings
inline QStringPair *getValuePair() { return mValuePair; }
/// set value range (spinbox / integer use)
inline void setValuePair (QStringPair valuePair) { mValuePair = new QStringPair(valuePair); }
inline void setValuePair (QStringPair valuePair)
{
delete mValuePair;
mValuePair = new QStringPair(valuePair);
}
inline bool isMultivalue () { return mIsMultiValue; }

@ -58,7 +58,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Topics,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, TopicCreatorFactory>);
manager.add (CSMWorld::UniversalId::Type_Journal,
manager.add (CSMWorld::UniversalId::Type_Journals,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>);
manager.add (CSMWorld::UniversalId::Type_TopicInfos,

@ -281,9 +281,11 @@ int main(int argc, char**argv)
}
catch (std::exception &e)
{
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
if (isatty(fileno(stdin)) || !SDL_WasInit(SDL_INIT_VIDEO))
std::cerr << "\nERROR: " << e.what() << std::endl;
else
#endif
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
return 1;

@ -199,7 +199,7 @@ namespace MWClass
else
{
MWMechanics::DynamicStat<float> fatigue(getCreatureStats(ptr).getFatigue());
fatigue.setCurrent(fatigue.getCurrent() - damage);
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
getCreatureStats(ptr).setFatigue(fatigue);
}
}

@ -63,7 +63,6 @@ namespace
bool male = (npc->mFlags & ESM::NPC::Female) == 0;
int level = creatureStats.getLevel();
for (int i=0; i<ESM::Attribute::Length; ++i)
{
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
@ -131,6 +130,89 @@ namespace
creatureStats.setHealth(static_cast<int> (0.5 * (strength + endurance)) + multiplier * (creatureStats.getLevel() - 1));
}
/**
* @brief autoCalculateSkills
*
* Skills are calculated with following formulae ( http://www.uesp.net/wiki/Morrowind:NPCs#Skills ):
*
* Skills: (Level - 1) × (Majority Multiplier + Specialization Multiplier)
*
* The Majority Multiplier is 1.0 for a Major or Minor Skill, or 0.1 for a Miscellaneous Skill.
*
* The Specialization Multiplier is 0.5 for a Skill in the same Specialization as the class,
* zero for other Skills.
*
* and by adding class, race, specialization bonus.
*/
void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats)
{
const ESM::Class *class_ =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc->mClass);
unsigned int level = npcStats.getLevel();
const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npc->mRace);
for (int i = 0; i < 2; ++i)
{
int bonus = (i==0) ? 10 : 25;
for (int i2 = 0; i2 < 5; ++i2)
{
int index = class_->mData.mSkills[i2][i];
if (index >= 0 && index < ESM::Skill::Length)
{
npcStats.getSkill(index).setBase (npcStats.getSkill(index).getBase() + bonus);
}
}
}
for (int skillIndex = 0; skillIndex < ESM::Skill::Length; ++skillIndex)
{
float majorMultiplier = 0.1f;
float specMultiplier = 0.0f;
int raceBonus = 0;
int specBonus = 0;
for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex)
{
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
{
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
break;
}
}
for (int k = 0; k < 5; ++k)
{
// is this a minor or major skill?
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
{
majorMultiplier = 1.0f;
break;
}
}
// is this skill in the same Specialization as the class?
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillIndex);
if (skill->mData.mSpecialization == class_->mData.mSpecialization)
{
specMultiplier = 0.5f;
specBonus = 5;
}
npcStats.getSkill(skillIndex).setBase(
std::min(
npcStats.getSkill(skillIndex).getBase()
+ 5
+ raceBonus
+ specBonus
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100.0f));
}
}
}
namespace MWClass
@ -173,7 +255,7 @@ namespace MWClass
{
std::string faction = ref->mBase->mFaction;
Misc::StringUtils::toLower(faction);
if(ref->mBase->mNpdt52.mGold != -10)
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
{
data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank;
}
@ -185,11 +267,11 @@ namespace MWClass
// creature stats
int gold=0;
if(ref->mBase->mNpdt52.mGold != -10)
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
{
gold = ref->mBase->mNpdt52.mGold;
for (int i=0; i<27; ++i)
for (unsigned int i=0; i< ESM::Skill::Length; ++i)
data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt52.mSkills[i]);
data->mNpcStats.getAttribute(0).set (ref->mBase->mNpdt52.mStrength);
@ -220,6 +302,7 @@ namespace MWClass
data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation);
autoCalculateAttributes(ref->mBase, data->mNpcStats);
autoCalculateSkills(ref->mBase, data->mNpcStats);
}
data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage);
@ -586,7 +669,7 @@ namespace MWClass
else
{
MWMechanics::DynamicStat<float> fatigue(getCreatureStats(ptr).getFatigue());
fatigue.setCurrent(fatigue.getCurrent() - damage);
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
getCreatureStats(ptr).setFatigue(fatigue);
}
}
@ -628,6 +711,8 @@ namespace MWClass
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
if(get(actor).getStance(actor, MWWorld::Class::Sneak))
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr)); // stealing
if(get(ptr).getCreatureStats(ptr).isHostile())
return boost::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction("#{sActorInCombat}"));
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
}

@ -174,37 +174,31 @@ namespace MWGui
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
{
static const char *ids[] =
{
"HBar", "MBar", "FBar", 0
};
int current = std::max(0, static_cast<int>(value.getCurrent()));
int modified = static_cast<int>(value.getModified());
for (int i=0; ids[i]; ++i)
if (ids[i]==id)
{
MyGUI::Widget* w;
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
switch (i)
std::string valStr = boost::lexical_cast<std::string>(current) + "/" + boost::lexical_cast<std::string>(modified);
if (id == "HBar")
{
case 0:
mHealth->setProgressRange (value.getModified());
mHealth->setProgressPosition (value.getCurrent());
mHealth->setProgressRange(modified);
mHealth->setProgressPosition(current);
getWidget(w, "HealthFrame");
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
break;
case 1:
mMagicka->setProgressRange (value.getModified());
mMagicka->setProgressPosition (value.getCurrent());
}
else if (id == "MBar")
{
mMagicka->setProgressRange (modified);
mMagicka->setProgressPosition (current);
getWidget(w, "MagickaFrame");
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
break;
case 2:
mStamina->setProgressRange (value.getModified());
mStamina->setProgressPosition (value.getCurrent());
}
else if (id == "FBar")
{
mStamina->setProgressRange (modified);
mStamina->setProgressPosition (current);
getWidget(w, "FatigueFrame");
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
break;
}
}
}

@ -134,40 +134,30 @@ namespace MWGui
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{
static const char *ids[] =
{
"HBar", "MBar", "FBar",
0
};
int current = std::max(0, static_cast<int>(value.getCurrent()));
int modified = static_cast<int>(value.getModified());
for (int i=0; ids[i]; ++i)
{
if (ids[i]==id)
{
std::string id (ids[i]);
setBar (id, id + "T", static_cast<int>(value.getCurrent()), static_cast<int>(value.getModified()));
setBar (id, id + "T", current, modified);
// health, magicka, fatigue tooltip
MyGUI::Widget* w;
std::string valStr = boost::lexical_cast<std::string>(int(value.getCurrent())) + "/" + boost::lexical_cast<std::string>(int(value.getModified()));
if (i==0)
std::string valStr = boost::lexical_cast<std::string>(current) + "/" + boost::lexical_cast<std::string>(modified);
if (id == "HBar")
{
getWidget(w, "Health");
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
}
else if (i==1)
else if (id == "MBar")
{
getWidget(w, "Magicka");
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
}
else if (i==2)
else if (id == "FBar")
{
getWidget(w, "Fatigue");
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
}
}
}
}
void StatsWindow::setValue (const std::string& id, const std::string& value)
{
@ -420,8 +410,6 @@ namespace MWGui
}
mSkillWidgets.clear();
mSkillView->setViewOffset (MyGUI::IntPoint(0,0));
const int valueSize = 40;
MyGUI::IntCoord coord1(10, 0, mSkillView->getWidth() - (10 + valueSize) - 24, 18);
MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height);

@ -112,9 +112,6 @@ namespace MWGui
, mPlayerMinorSkills()
, mPlayerMajorSkills()
, mPlayerSkillValues()
, mPlayerHealth()
, mPlayerMagicka()
, mPlayerFatigue()
, mGui(NULL)
, mGuiModes()
, mCursorManager(NULL)
@ -590,31 +587,7 @@ namespace MWGui
mStatsWindow->setValue (id, value);
mHud->setValue (id, value);
mCharGen->setValue(id, value);
if (id == "HBar")
{
mPlayerHealth = value;
}
else if (id == "MBar")
{
mPlayerMagicka = value;
}
else if (id == "FBar")
{
mPlayerFatigue = value;
}
}
#if 0
MWMechanics::DynamicStat<int> WindowManager::getValue(const std::string& id)
{
if(id == "HBar")
return mPlayerHealth;
else if (id == "MBar")
return mPlayerMagicka;
else if (id == "FBar")
return mPlayerFatigue;
}
#endif
void WindowManager::setValue (const std::string& id, const std::string& value)
{

@ -346,8 +346,6 @@ namespace MWGui
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
MWMechanics::DynamicStat<float> mPlayerHealth, mPlayerMagicka, mPlayerFatigue;
MyGUI::Gui *mGui; // Gui
std::vector<GuiMode> mGuiModes;

@ -37,6 +37,7 @@ MWMechanics::AiSequence& MWMechanics::AiSequence::operator= (const AiSequence& s
{
clear();
copy (sequence);
mDone = sequence.mDone;
}
return *this;

@ -1112,7 +1112,7 @@ void CharacterController::resurrect()
if(mAnimation)
mAnimation->disable(mCurrentDeath);
mCurrentDeath.empty();
mCurrentDeath.clear();
mDeathState = CharState_None;
}

@ -86,7 +86,7 @@ void MWMechanics::NpcStats::setMovementFlag (Flag flag, bool state)
const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) const
{
if (index<0 || index>=27)
if (index<0 || index>=ESM::Skill::Length)
throw std::runtime_error ("skill index out of range");
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
@ -94,7 +94,7 @@ const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) cons
MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index)
{
if (index<0 || index>=27)
if (index<0 || index>=ESM::Skill::Length)
throw std::runtime_error ("skill index out of range");
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);

@ -162,15 +162,27 @@ namespace MWMechanics
setCurrent (getCurrent()+diff);
}
void setCurrent (const T& value)
void setCurrent (const T& value, bool allowDecreaseBelowZero = false)
{
if (value > mCurrent)
{
// increase
mCurrent = value;
if (mCurrent<0)
mCurrent = 0;
else if (mCurrent>getModified())
if (mCurrent > getModified())
mCurrent = getModified();
}
else if (value > 0 || allowDecreaseBelowZero)
{
// allowed decrease
mCurrent = value;
}
else if (mCurrent > 0)
{
// capped decrease
mCurrent = 0;
}
}
void setModifier (const T& modifier)
{

@ -209,6 +209,7 @@ namespace MWScript
.getDynamic (mIndex));
stat.setModified (value, 0);
stat.setCurrent(value);
MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat);
}

@ -473,7 +473,7 @@ void WeatherManager::update(float duration)
{
// pick a random sound
int sound = rand() % 4;
std::string* soundName;
std::string* soundName = NULL;
if (sound == 0) soundName = &mThunderSoundID0;
else if (sound == 1) soundName = &mThunderSoundID1;
else if (sound == 2) soundName = &mThunderSoundID2;

@ -214,7 +214,7 @@ namespace MWWorld
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (true), mCells (mStore, mEsm),
mActivationDistanceOverride (mActivationDistanceOverride),
mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true),
mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), mLevitationEnabled(false),
mFacedDistance(FLT_MAX), mGodMode(false)
{
mPhysics = new PhysicsSystem(renderer);

@ -160,10 +160,10 @@ void Land::loadData(int flags)
}
mEsm->restoreContext(mContext);
memset(mLandData->mNormals, 0, LAND_NUM_VERTS * 3);
memset(mLandData->mNormals, 0, sizeof(mLandData->mNormals));
if (mEsm->isNextSub("VNML")) {
condLoad(actual, DATA_VNML, mLandData->mNormals, sizeof(VNML));
condLoad(actual, DATA_VNML, mLandData->mNormals, sizeof(mLandData->mNormals));
}
if (mEsm->isNextSub("VHGT")) {

@ -72,13 +72,13 @@ struct Land
};
#pragma pack(pop)
typedef signed char VNML[LAND_NUM_VERTS * 3];
typedef signed char VNML;
struct LandData
{
float mHeightOffset;
float mHeights[LAND_NUM_VERTS];
VNML mNormals;
VNML mNormals[LAND_NUM_VERTS * 3];
uint16_t mTextures[LAND_NUM_TEXTURES];
bool mUsingColours;

@ -10,7 +10,7 @@ namespace ESM
void NPC::load(ESMReader &esm)
{
mNpdt52.mGold = -10;
//mNpdt52.mGold = -10;
mPersistent = esm.getRecordFlags() & 0x0400;
@ -29,12 +29,12 @@ void NPC::load(ESMReader &esm)
esm.getSubHeader();
if (esm.getSubSize() == 52)
{
mNpdtType = 52;
mNpdtType = NPC_DEFAULT;
esm.getExact(&mNpdt52, 52);
}
else if (esm.getSubSize() == 12)
{
mNpdtType = 12;
mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
esm.getExact(&mNpdt12, 12);
}
else
@ -76,9 +76,9 @@ void NPC::save(ESMWriter &esm) const
esm.writeHNCString("KNAM", mHair);
esm.writeHNOCString("SCRI", mScript);
if (mNpdtType == 52)
if (mNpdtType == NPC_DEFAULT)
esm.writeHNT("NPDT", mNpdt52, 52);
else if (mNpdtType == 12)
else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS)
esm.writeHNT("NPDT", mNpdt12, 12);
esm.writeHNT("FLAG", mFlags);
@ -114,7 +114,7 @@ void NPC::save(ESMWriter &esm) const
mNpdt52.mLevel = 0;
mNpdt52.mStrength = mNpdt52.mIntelligence = mNpdt52.mWillpower = mNpdt52.mAgility =
mNpdt52.mSpeed = mNpdt52.mEndurance = mNpdt52.mPersonality = mNpdt52.mLuck = 0;
for (int i=0; i<27; ++i) mNpdt52.mSkills[i] = 0;
for (int i=0; i< Skill::Length; ++i) mNpdt52.mSkills[i] = 0;
mNpdt52.mReputation = 0;
mNpdt52.mHealth = mNpdt52.mMana = mNpdt52.mFatigue = 0;
mNpdt52.mDisposition = 0;

@ -8,6 +8,7 @@
#include "loadcont.hpp"
#include "aipackage.hpp"
#include "spelllist.hpp"
#include "loadskil.hpp"
namespace ESM {
@ -58,6 +59,12 @@ struct NPC
Metal = 0x0800 // Metal blood effect (golden?)
};
enum NpcType
{
NPC_WITH_AUTOCALCULATED_STATS = 12,
NPC_DEFAULT = 52
};
#pragma pack(push)
#pragma pack(1)
@ -73,7 +80,7 @@ struct NPC
mPersonality,
mLuck;
char mSkills[27];
char mSkills[Skill::Length];
char mReputation;
short mHealth, mMana, mFatigue;
char mDisposition, mFactionID, mRank;

@ -27,6 +27,7 @@ public:
Ogre::String doGet(const void *target) const
{
assert(false && "Unimplemented");
return "";
}
void doSet(void *target, const Ogre::String &val)
{
@ -41,6 +42,7 @@ public:
Ogre::String doGet(const void *target) const
{
assert(false && "Unimplemented");
return "";
}
void doSet(void *target, const Ogre::String &val)
{
@ -563,6 +565,7 @@ public:
Ogre::String doGet(const void *target) const
{
assert(false && "Unimplemented");
return "";
}
void doSet(void *target, const Ogre::String &val)
{
@ -577,6 +580,7 @@ public:
Ogre::String doGet(const void *target) const
{
assert(false && "Unimplemented");
return "";
}
void doSet(void *target, const Ogre::String &val)
{

@ -349,7 +349,7 @@ protected:
{
//strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe),
// and the null terminator isn't needed
for( int i=0; p[i] && i<*length; ++i ) {
for( int i=0; i<*length && p[i]; ++i ) {
_value[i] = p[i];
}
return p + (*length);

@ -819,6 +819,8 @@ namespace BtOgre {
*/
DynamicRenderable::DynamicRenderable()
: mVertexBufferCapacity(0)
, mIndexBufferCapacity(0)
{
}

Loading…
Cancel
Save