mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
1150b41c18
@ -1,9 +1,7 @@
|
||||
OpenMW
|
||||
======
|
||||
|
||||
[![Build Status](https://travis-ci.org/OpenMW/openmw.svg?branch=coverity_scan)](https://travis-ci.org/OpenMW/openmw)
|
||||
|
||||
[![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
|
||||
[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
|
||||
|
||||
OpenMW is an attempt at recreating the engine for the popular role-playing game
|
||||
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
|
||||
|
@ -59,6 +59,7 @@ struct Arguments
|
||||
std::string outname;
|
||||
|
||||
std::vector<std::string> types;
|
||||
std::string name;
|
||||
|
||||
ESMData data;
|
||||
ESM::ESMReader reader;
|
||||
@ -78,6 +79,8 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
||||
("type,t", bpo::value< std::vector<std::string> >(),
|
||||
"Show only records of this type (four character record code). May "
|
||||
"be specified multiple times. Only affects dump mode.")
|
||||
("name,n", bpo::value<std::string>(),
|
||||
"Show only the record with this name. Only affects dump mode.")
|
||||
("plain,p", "Print contents of dialogs, books and scripts. "
|
||||
"(skipped by default)"
|
||||
"Only affects dump mode.")
|
||||
@ -148,7 +151,9 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
||||
}
|
||||
|
||||
if (variables.count("type") > 0)
|
||||
info.types = variables["type"].as< std::vector<std::string> >();
|
||||
info.types = variables["type"].as< std::vector<std::string> >();
|
||||
if (variables.count("name") > 0)
|
||||
info.name = variables["name"].as<std::string>();
|
||||
|
||||
info.mode = variables["mode"].as<std::string>();
|
||||
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
|
||||
@ -265,6 +270,8 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
||||
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
||||
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
||||
std::cout << " Deleted: " << deleted << std::endl;
|
||||
if (!ref.mKey.empty())
|
||||
std::cout << " Key: '" << ref.mKey << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,6 +365,9 @@ int load(Arguments& info)
|
||||
if (id.empty())
|
||||
id = esm.getHNOString("INAM");
|
||||
|
||||
if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, id))
|
||||
interested = false;
|
||||
|
||||
if(!quiet && interested)
|
||||
std::cout << "\nRecord: " << n.toString()
|
||||
<< " '" << id << "'\n";
|
||||
@ -385,7 +395,7 @@ int load(Arguments& info)
|
||||
record->load(esm);
|
||||
if (!quiet && interested) record->print();
|
||||
|
||||
if (record->getType().val == ESM::REC_CELL && loadCells) {
|
||||
if (record->getType().val == ESM::REC_CELL && loadCells && interested) {
|
||||
loadCell(record->cast<ESM::Cell>()->get(), esm, info);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "labels.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
void printAIPackage(ESM::AIPackage p)
|
||||
@ -752,7 +754,7 @@ void Record<ESM::DialInfo>::print()
|
||||
if (mData.mCell != "")
|
||||
std::cout << " Cell: " << mData.mCell << std::endl;
|
||||
if (mData.mData.mDisposition > 0)
|
||||
std::cout << " Disposition: " << mData.mData.mDisposition << std::endl;
|
||||
std::cout << " Disposition/Journal index: " << mData.mData.mDisposition << std::endl;
|
||||
if (mData.mData.mGender != ESM::DialInfo::NA)
|
||||
std::cout << " Gender: " << mData.mData.mGender << std::endl;
|
||||
if (mData.mSound != "")
|
||||
@ -812,7 +814,6 @@ void Record<ESM::Land>::print()
|
||||
{
|
||||
std::cout << " Coordinates: (" << mData.mX << "," << mData.mY << ")" << std::endl;
|
||||
std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " HasData: " << mData.mHasData << std::endl;
|
||||
std::cout << " DataTypes: " << mData.mDataTypes << std::endl;
|
||||
|
||||
// Seems like this should done with reference counting in the
|
||||
|
@ -24,6 +24,7 @@ set(ESSIMPORTER_FILES
|
||||
convertcrec.cpp
|
||||
convertcntc.cpp
|
||||
convertscri.cpp
|
||||
convertscpt.cpp
|
||||
)
|
||||
|
||||
add_executable(openmw-essimporter
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include <OgreImage.h>
|
||||
#include <OgreColourValue.h>
|
||||
|
||||
#include <components/esm/creaturestate.hpp>
|
||||
#include <components/esm/containerstate.hpp>
|
||||
@ -69,7 +70,65 @@ namespace ESSImport
|
||||
esm.getSubHeader();
|
||||
data.resize(esm.getSubSize());
|
||||
esm.getExact(&data[0], data.size());
|
||||
convertImage(&data[0], data.size(), maph.size, maph.size, Ogre::PF_BYTE_RGB, "map.tga");
|
||||
|
||||
Ogre::DataStreamPtr stream (new Ogre::MemoryDataStream(&data[0], data.size()));
|
||||
mGlobalMapImage.loadRawData(stream, maph.size, maph.size, 1, Ogre::PF_BYTE_RGB);
|
||||
// to match openmw size
|
||||
mGlobalMapImage.resize(maph.size*2, maph.size*2, Ogre::Image::FILTER_BILINEAR);
|
||||
}
|
||||
|
||||
void ConvertFMAP::write(ESM::ESMWriter &esm)
|
||||
{
|
||||
int numcells = mGlobalMapImage.getWidth() / 18; // NB truncating, doesn't divide perfectly
|
||||
// with the 512x512 map the game has by default
|
||||
int cellSize = mGlobalMapImage.getWidth()/numcells;
|
||||
|
||||
// Note the upper left corner of the (0,0) cell should be at (width/2, height/2)
|
||||
|
||||
mContext->mGlobalMapState.mBounds.mMinX = -numcells/2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxX = (numcells-1)/2;
|
||||
mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxY = numcells/2;
|
||||
|
||||
Ogre::Image image2;
|
||||
std::vector<Ogre::uint8> data;
|
||||
int width = cellSize*numcells;
|
||||
int height = cellSize*numcells;
|
||||
data.resize(width*height*4, 0);
|
||||
image2.loadDynamicImage(&data[0], width, height, Ogre::PF_BYTE_RGBA);
|
||||
|
||||
for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it)
|
||||
{
|
||||
if (it->first > mContext->mGlobalMapState.mBounds.mMaxX
|
||||
|| it->first < mContext->mGlobalMapState.mBounds.mMinX
|
||||
|| it->second > mContext->mGlobalMapState.mBounds.mMaxY
|
||||
|| it->second < mContext->mGlobalMapState.mBounds.mMinY)
|
||||
{
|
||||
// out of bounds, I think this could happen, since the original engine had a fixed-size map
|
||||
continue;
|
||||
}
|
||||
|
||||
int imageLeftSrc = mGlobalMapImage.getWidth()/2;
|
||||
int imageTopSrc = mGlobalMapImage.getHeight()/2;
|
||||
imageLeftSrc += it->first * cellSize;
|
||||
imageTopSrc -= it->second * cellSize;
|
||||
int imageLeftDst = width/2;
|
||||
int imageTopDst = height/2;
|
||||
imageLeftDst += it->first * cellSize;
|
||||
imageTopDst -= it->second * cellSize;
|
||||
for (int x=0; x<cellSize; ++x)
|
||||
for (int y=0; y<cellSize; ++y)
|
||||
image2.setColourAt(mGlobalMapImage.getColourAt(imageLeftSrc+x, imageTopSrc+y, 0)
|
||||
, imageLeftDst+x, imageTopDst+y, 0);
|
||||
}
|
||||
|
||||
Ogre::DataStreamPtr encoded = image2.encode("png");
|
||||
mContext->mGlobalMapState.mImageData.resize(encoded->size());
|
||||
encoded->read(&mContext->mGlobalMapState.mImageData[0], encoded->size());
|
||||
|
||||
esm.startRecord(ESM::REC_GMAP);
|
||||
mContext->mGlobalMapState.save(esm);
|
||||
esm.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
void ConvertCell::read(ESM::ESMReader &esm)
|
||||
@ -103,6 +162,10 @@ namespace ESSImport
|
||||
// (probably offset of that specific fog texture?)
|
||||
while (esm.isNextSub("NAM8"))
|
||||
{
|
||||
if (cell.isExterior()) // TODO: NAM8 occasionally exists for cells that haven't been explored.
|
||||
// are there any flags marking explored cells?
|
||||
mContext->mExploredCells.insert(std::make_pair(cell.mData.mX, cell.mData.mY));
|
||||
|
||||
esm.getSubHeader();
|
||||
|
||||
if (esm.getSubSize() == 36)
|
||||
@ -313,10 +376,6 @@ namespace ESSImport
|
||||
it->save(esm);
|
||||
esm.endRecord(ESM::REC_MARK);
|
||||
}
|
||||
|
||||
esm.startRecord(ESM::REC_GMAP);
|
||||
mContext->mGlobalMapState.save(esm);
|
||||
esm.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef OPENMW_ESSIMPORT_CONVERTER_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTER_H
|
||||
|
||||
#include <OgreImage.h>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
|
||||
@ -13,6 +15,9 @@
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
#include <components/esm/custommarkerstate.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/weatherstate.hpp>
|
||||
#include <components/esm/globalscript.hpp>
|
||||
#include <components/esm/queststate.hpp>
|
||||
|
||||
#include "importcrec.hpp"
|
||||
#include "importcntc.hpp"
|
||||
@ -29,6 +34,7 @@
|
||||
|
||||
#include "convertacdt.hpp"
|
||||
#include "convertnpcc.hpp"
|
||||
#include "convertscpt.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
@ -206,7 +212,7 @@ public:
|
||||
else
|
||||
{
|
||||
int index = npcc.mNPDT.mIndex;
|
||||
mContext->mNpcChanges.insert(std::make_pair(std::make_pair(index,id), npcc)).second;
|
||||
mContext->mNpcChanges.insert(std::make_pair(std::make_pair(index,id), npcc));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -266,7 +272,7 @@ public:
|
||||
faction.mExpelled = (it->mFlags & 0x2) != 0;
|
||||
faction.mRank = it->mRank;
|
||||
faction.mReputation = it->mReputation;
|
||||
mContext->mPlayer.mObject.mNpcStats.mFactions[it->mFactionName.toString()] = faction;
|
||||
mContext->mPlayer.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(it->mFactionName.toString())] = faction;
|
||||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
mContext->mPlayer.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
@ -308,6 +314,10 @@ class ConvertFMAP : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader &esm);
|
||||
virtual void write(ESM::ESMWriter &esm);
|
||||
|
||||
private:
|
||||
Ogre::Image mGlobalMapImage;
|
||||
};
|
||||
|
||||
class ConvertCell : public Converter
|
||||
@ -428,7 +438,24 @@ public:
|
||||
std::string id = esm.getHNString("NAME");
|
||||
DIAL dial;
|
||||
dial.load(esm);
|
||||
if (dial.mIndex > 0)
|
||||
mDials[id] = dial;
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
for (std::map<std::string, DIAL>::const_iterator it = mDials.begin(); it != mDials.end(); ++it)
|
||||
{
|
||||
esm.startRecord(ESM::REC_QUES);
|
||||
ESM::QuestState state;
|
||||
state.mFinished = 0;
|
||||
state.mState = it->second.mIndex;
|
||||
state.mTopic = Misc::StringUtils::lowerCase(it->first);
|
||||
state.save(esm);
|
||||
esm.endRecord(ESM::REC_QUES);
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::map<std::string, DIAL> mDials;
|
||||
};
|
||||
|
||||
class ConvertQUES : public Converter
|
||||
@ -455,11 +482,69 @@ public:
|
||||
class ConvertGAME : public Converter
|
||||
{
|
||||
public:
|
||||
ConvertGAME() : mHasGame(false) {}
|
||||
|
||||
std::string toString(int weatherId)
|
||||
{
|
||||
switch (weatherId)
|
||||
{
|
||||
case 0:
|
||||
return "clear";
|
||||
case 1:
|
||||
return "cloudy";
|
||||
case 2:
|
||||
return "foggy";
|
||||
case 3:
|
||||
return "overcast";
|
||||
case 4:
|
||||
return "rain";
|
||||
case 5:
|
||||
return "thunderstorm";
|
||||
case 6:
|
||||
return "ashstorm";
|
||||
case 7:
|
||||
return "blight";
|
||||
case 8:
|
||||
return "snow";
|
||||
case 9:
|
||||
return "blizzard";
|
||||
case -1:
|
||||
return "";
|
||||
default:
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "unknown weather id: " << weatherId;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
GAME game;
|
||||
game.load(esm);
|
||||
mGame.load(esm);
|
||||
mHasGame = true;
|
||||
}
|
||||
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
if (!mHasGame)
|
||||
return;
|
||||
esm.startRecord(ESM::REC_WTHR);
|
||||
ESM::WeatherState weather;
|
||||
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
|
||||
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather);
|
||||
weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015*24*3600);
|
||||
weather.mHour = mContext->mHour;
|
||||
weather.mWindSpeed = 0.f;
|
||||
weather.mTimePassed = 0.0;
|
||||
weather.mFirstUpdate = false;
|
||||
weather.save(esm);
|
||||
esm.endRecord(ESM::REC_WTHR);
|
||||
}
|
||||
|
||||
private:
|
||||
bool mHasGame;
|
||||
GAME mGame;
|
||||
};
|
||||
|
||||
/// Running global script
|
||||
@ -470,7 +555,21 @@ public:
|
||||
{
|
||||
SCPT script;
|
||||
script.load(esm);
|
||||
ESM::GlobalScript out;
|
||||
convertSCPT(script, out);
|
||||
mScripts.push_back(out);
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
for (std::vector<ESM::GlobalScript>::const_iterator it = mScripts.begin(); it != mScripts.end(); ++it)
|
||||
{
|
||||
esm.startRecord(ESM::REC_GSCR);
|
||||
it->save(esm);
|
||||
esm.endRecord(ESM::REC_GSCR);
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<ESM::GlobalScript> mScripts;
|
||||
};
|
||||
|
||||
}
|
||||
|
17
apps/essimporter/convertscpt.cpp
Normal file
17
apps/essimporter/convertscpt.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "convertscpt.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "convertscri.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCPT(const SCPT &scpt, ESM::GlobalScript &out)
|
||||
{
|
||||
out.mId = Misc::StringUtils::lowerCase(scpt.mSCHD.mName.toString());
|
||||
out.mRunning = scpt.mRunning;
|
||||
convertSCRI(scpt.mSCRI, out.mLocals);
|
||||
}
|
||||
|
||||
}
|
15
apps/essimporter/convertscpt.hpp
Normal file
15
apps/essimporter/convertscpt.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef OPENMW_ESSIMPORT_CONVERTSCPT_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTSCPT_H
|
||||
|
||||
#include <components/esm/globalscript.hpp>
|
||||
|
||||
#include "importscpt.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -60,10 +60,6 @@ namespace ESSImport
|
||||
if (esm.isNextSub("PWPS"))
|
||||
esm.skipHSub();
|
||||
|
||||
// unsure at which point between LSTN and CHRD
|
||||
if (esm.isNextSub("APUD"))
|
||||
esm.skipHSub(); // 40 bytes, starts with string "ancestor guardian". maybe spellcasting in progress?
|
||||
|
||||
if (esm.isNextSub("WNAM"))
|
||||
{
|
||||
std::string id = esm.getHString();
|
||||
@ -77,6 +73,20 @@ namespace ESSImport
|
||||
esm.skipHSub(); // 4 byte, 0
|
||||
}
|
||||
|
||||
while (esm.isNextSub("APUD"))
|
||||
{
|
||||
// used power
|
||||
esm.getSubHeader();
|
||||
std::string id = esm.getString(32);
|
||||
(void)id;
|
||||
// timestamp can't be used: this is the total hours passed, calculated by
|
||||
// timestamp = 24 * (365 * year + cumulativeDays[month] + day)
|
||||
// unfortunately cumulativeDays[month] is not clearly defined,
|
||||
// in the (non-MCP) vanilla version the first month was missing, but MCP added it.
|
||||
double timestamp;
|
||||
esm.getT(timestamp);
|
||||
}
|
||||
|
||||
// FIXME: not all actors have this, add flag
|
||||
if (esm.isNextSub("CHRD")) // npc only
|
||||
esm.getHExact(mSkills, 27*2*sizeof(int));
|
||||
|
@ -29,6 +29,9 @@ namespace ESSImport
|
||||
|
||||
ESM::DialogueState mDialogueState;
|
||||
|
||||
// cells which should show an explored overlay on the global map
|
||||
std::set<std::pair<int, int> > mExploredCells;
|
||||
|
||||
ESM::GlobalMap mGlobalMapState;
|
||||
|
||||
int mDay, mMonth, mYear;
|
||||
|
@ -7,7 +7,23 @@ namespace ESSImport
|
||||
|
||||
void GAME::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mGMDT, "GMDT");
|
||||
esm.getSubNameIs("GMDT");
|
||||
esm.getSubHeader();
|
||||
if (esm.getSubSize() == 92)
|
||||
{
|
||||
esm.getExact(&mGMDT, 92);
|
||||
mGMDT.mSecundaPhase = 0;
|
||||
}
|
||||
else if (esm.getSubSize() == 96)
|
||||
{
|
||||
esm.getT(mGMDT);
|
||||
}
|
||||
else
|
||||
esm.fail("unexpected subrecord size for GAME.GMDT");
|
||||
|
||||
mGMDT.mWeatherTransition &= (0x000000ff);
|
||||
mGMDT.mSecundaPhase &= (0x000000ff);
|
||||
mGMDT.mMasserPhase &= (0x000000ff);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace ESSImport
|
||||
int mCurrentWeather, mNextWeather;
|
||||
int mWeatherTransition; // 0-100 transition between weathers, top 3 bytes may be garbage
|
||||
float mTimeOfNextTransition; // weather changes when gamehour == timeOfNextTransition
|
||||
int masserPhase, secundaPhase; // top 3 bytes may be garbage
|
||||
int mMasserPhase, mSecundaPhase; // top 3 bytes may be garbage
|
||||
};
|
||||
|
||||
GMDT mGMDT;
|
||||
|
@ -13,8 +13,14 @@ namespace ESSImport
|
||||
|
||||
mSCRI.load(esm);
|
||||
|
||||
mRNAM = -1;
|
||||
esm.getHNOT(mRNAM, "RNAM");
|
||||
mRefNum = -1;
|
||||
if (esm.isNextSub("RNAM"))
|
||||
{
|
||||
mRunning = true;
|
||||
esm.getHT(mRefNum);
|
||||
}
|
||||
else
|
||||
mRunning = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ namespace ESSImport
|
||||
{
|
||||
|
||||
// A running global script
|
||||
// TODO: test how targeted scripts are saved
|
||||
struct SCPT
|
||||
{
|
||||
ESM::Script::SCHD mSCHD;
|
||||
@ -22,7 +21,8 @@ namespace ESSImport
|
||||
// values of local variables
|
||||
SCRI mSCRI;
|
||||
|
||||
int mRNAM; // unknown, seems to be -1 for some scripts, some huge integer for others
|
||||
bool mRunning;
|
||||
int mRefNum; // Targeted reference, -1: no reference
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
@ -453,6 +453,7 @@ namespace MWBase
|
||||
|
||||
/// \todo Probably shouldn't be here
|
||||
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0;
|
||||
virtual void reattachPlayerCamera() = 0;
|
||||
|
||||
/// \todo this does not belong here
|
||||
virtual void frameStarted (float dt, bool paused) = 0;
|
||||
|
@ -296,25 +296,6 @@ namespace MWClass
|
||||
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
// NPC stats
|
||||
if (!ref->mBase->mFaction.empty())
|
||||
{
|
||||
std::string faction = ref->mBase->mFaction;
|
||||
if (const ESM::Faction* fact = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().search(faction))
|
||||
{
|
||||
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
data->mNpcStats.setFactionRank(fact->mId, (int)ref->mBase->mNpdt52.mRank);
|
||||
}
|
||||
else
|
||||
{
|
||||
data->mNpcStats.setFactionRank(fact->mId, (int)ref->mBase->mNpdt12.mRank);
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cerr << "Warning: ignoring nonexistent faction '" << faction << "' on NPC '" << ref->mBase->mId << "'" << std::endl;
|
||||
}
|
||||
|
||||
// creature stats
|
||||
int gold=0;
|
||||
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
@ -371,13 +352,13 @@ namespace MWClass
|
||||
std::cerr << "Warning: ignoring nonexistent race power '" << *iter << "' on NPC '" << ref->mBase->mId << "'" << std::endl;
|
||||
}
|
||||
|
||||
if (data->mNpcStats.getFactionRanks().size())
|
||||
if (!ref->mBase->mFaction.empty())
|
||||
{
|
||||
static const int iAutoRepFacMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iAutoRepFacMod")->getInt();
|
||||
static const int iAutoRepLevMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iAutoRepLevMod")->getInt();
|
||||
int rank = data->mNpcStats.getFactionRanks().begin()->second;
|
||||
int rank = ref->mBase->getFactionRank();
|
||||
|
||||
data->mNpcStats.setReputation(iAutoRepFacMod * (rank+1) + iAutoRepLevMod * (data->mNpcStats.getLevel()-1));
|
||||
}
|
||||
@ -1371,4 +1352,16 @@ namespace MWClass
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Npc::getPrimaryFaction (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
return ref->mBase->mFaction;
|
||||
}
|
||||
|
||||
int Npc::getPrimaryFactionRank (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
return ref->mBase->getFactionRank();
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,9 @@ namespace MWClass
|
||||
virtual void restock (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getPrimaryFaction(const MWWorld::Ptr &ptr) const;
|
||||
virtual int getPrimaryFactionRank(const MWWorld::Ptr &ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -67,14 +67,11 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor);
|
||||
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mFaction));
|
||||
|
||||
if (iter==stats.getFactionRanks().end())
|
||||
if (!Misc::StringUtils::ciEqual(mActor.getClass().getPrimaryFaction(mActor), info.mFaction))
|
||||
return false;
|
||||
|
||||
// check rank
|
||||
if (iter->second < info.mData.mRank)
|
||||
if (mActor.getClass().getPrimaryFactionRank(mActor) < info.mData.mRank)
|
||||
return false;
|
||||
}
|
||||
else if (info.mData.mRank != -1)
|
||||
@ -83,13 +80,8 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
|
||||
return false;
|
||||
|
||||
// Rank requirement, but no faction given. Use the actor's faction, if there is one.
|
||||
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor);
|
||||
|
||||
if (!stats.getFactionRanks().size())
|
||||
return false;
|
||||
|
||||
// check rank
|
||||
if (stats.getFactionRanks().begin()->second < info.mData.mRank)
|
||||
if (mActor.getClass().getPrimaryFactionRank(mActor) < info.mData.mRank)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -336,12 +328,10 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||
|
||||
case SelectWrapper::Function_RankRequirement:
|
||||
{
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
std::string faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||
if (faction.empty())
|
||||
return 0;
|
||||
|
||||
std::string faction =
|
||||
mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first;
|
||||
|
||||
int rank = getFactionRank (player, faction);
|
||||
|
||||
if (rank>=9)
|
||||
@ -376,15 +366,14 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||
|
||||
case SelectWrapper::Function_FactionRankDiff:
|
||||
{
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
std::string faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||
|
||||
if (faction.empty())
|
||||
return 0;
|
||||
|
||||
const std::pair<std::string, int> faction =
|
||||
*mActor.getClass().getNpcStats (mActor).getFactionRanks().begin();
|
||||
|
||||
int rank = getFactionRank (player, faction.first);
|
||||
|
||||
return rank-faction.second;
|
||||
int rank = getFactionRank (player, faction);
|
||||
int npcRank = mActor.getClass().getPrimaryFactionRank(mActor);
|
||||
return rank-npcRank;
|
||||
}
|
||||
|
||||
case SelectWrapper::Function_WerewolfKills:
|
||||
@ -396,11 +385,10 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||
{
|
||||
bool low = select.getFunction()==SelectWrapper::Function_RankLow;
|
||||
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
return 0;
|
||||
std::string factionId = mActor.getClass().getPrimaryFaction(mActor);
|
||||
|
||||
std::string factionId =
|
||||
mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first;
|
||||
if (factionId.empty())
|
||||
return 0;
|
||||
|
||||
int value = 0;
|
||||
|
||||
@ -454,7 +442,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
|
||||
case SelectWrapper::Function_NotFaction:
|
||||
|
||||
return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mFaction, select.getName());
|
||||
return !Misc::StringUtils::ciEqual(mActor.getClass().getPrimaryFaction(mActor), select.getName());
|
||||
|
||||
case SelectWrapper::Function_NotClass:
|
||||
|
||||
@ -494,8 +482,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
|
||||
case SelectWrapper::Function_SameFaction:
|
||||
|
||||
return mActor.getClass().getNpcStats (mActor).isSameFaction (
|
||||
player.getClass().getNpcStats (player));
|
||||
return player.getClass().getNpcStats (player).isInFaction(mActor.getClass().getPrimaryFaction(mActor));
|
||||
|
||||
case SelectWrapper::Function_PcCommonDisease:
|
||||
|
||||
@ -512,11 +499,10 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
|
||||
case SelectWrapper::Function_PcExpelled:
|
||||
{
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
return false;
|
||||
std::string faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||
|
||||
std::string faction =
|
||||
mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first;
|
||||
if (faction.empty())
|
||||
return false;
|
||||
|
||||
return player.getClass().getNpcStats(player).getExpelled(faction);
|
||||
}
|
||||
@ -561,7 +547,7 @@ int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::st
|
||||
{
|
||||
MWMechanics::NpcStats& stats = actor.getClass().getNpcStats (actor);
|
||||
|
||||
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find (factionId);
|
||||
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase(factionId));
|
||||
|
||||
if (iter==stats.getFactionRanks().end())
|
||||
return -1;
|
||||
|
@ -89,7 +89,7 @@ namespace MWDialogue
|
||||
|
||||
for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin());
|
||||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->mData.mDisposition==index) /// \todo cleanup info structure
|
||||
if (iter->mData.mJournalIndex==index)
|
||||
{
|
||||
return iter->mId;
|
||||
}
|
||||
|
@ -259,7 +259,12 @@ namespace MWDialogue
|
||||
record.load (reader);
|
||||
|
||||
if (isThere (record.mTopic))
|
||||
mQuests.insert (std::make_pair (record.mTopic, record));
|
||||
{
|
||||
std::pair<TQuestContainer::iterator, bool> result = mQuests.insert (std::make_pair (record.mTopic, record));
|
||||
// reapply quest index, this is to handle users upgrading from only
|
||||
// Morrowind.esm (no quest states) to Morrowind.esm + Tribunal.esm
|
||||
result.first->second.setIndex(record.mState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace MWDialogue
|
||||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->mId == entry.mInfoId)
|
||||
{
|
||||
index = iter->mData.mDisposition; /// \todo cleanup info structure
|
||||
index = iter->mData.mJournalIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,14 @@
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
void BackgroundImage::setBackgroundImage (const std::string& image, bool fixedRatio, bool correct)
|
||||
void BackgroundImage::setBackgroundImage (const std::string& image, bool fixedRatio, bool stretch)
|
||||
{
|
||||
if (mChild)
|
||||
{
|
||||
MyGUI::Gui::getInstance().destroyWidget(mChild);
|
||||
mChild = NULL;
|
||||
}
|
||||
if (correct)
|
||||
if (!stretch)
|
||||
{
|
||||
setImageTexture("black.png");
|
||||
|
||||
|
@ -18,9 +18,9 @@ namespace MWGui
|
||||
|
||||
/**
|
||||
* @param fixedRatio Use a fixed ratio of 4:3, regardless of the image dimensions
|
||||
* @param correct Add black bars?
|
||||
* @param stretch Stretch to fill the whole screen, or add black bars?
|
||||
*/
|
||||
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool correct=true);
|
||||
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool stretch=true);
|
||||
|
||||
virtual void setSize (const MyGUI::IntSize &_value);
|
||||
virtual void setCoord (const MyGUI::IntCoord &_value);
|
||||
|
@ -290,7 +290,8 @@ namespace MWGui
|
||||
|
||||
// Add the command to the history, and set the current pointer to
|
||||
// the end of the list
|
||||
mCommandHistory.push_back(cm);
|
||||
if (mCommandHistory.empty() || mCommandHistory.back() != cm)
|
||||
mCommandHistory.push_back(cm);
|
||||
mCurrent = mCommandHistory.end();
|
||||
mEditString.clear();
|
||||
|
||||
|
@ -154,8 +154,6 @@ namespace MWGui
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
|
||||
|
||||
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
|
||||
// or we end up using a possibly invalid model.
|
||||
setTitle(container.getClass().getName(container));
|
||||
}
|
||||
|
||||
|
@ -155,11 +155,6 @@ void ItemView::setSize(const MyGUI::IntSize &_value)
|
||||
layoutWidgets();
|
||||
}
|
||||
|
||||
void ItemView::setSize(int _width, int _height)
|
||||
{
|
||||
setSize(MyGUI::IntSize(_width, _height));
|
||||
}
|
||||
|
||||
void ItemView::setCoord(const MyGUI::IntCoord &_value)
|
||||
{
|
||||
bool changed = (_value.width != getWidth() || _value.height != getHeight());
|
||||
@ -168,11 +163,6 @@ void ItemView::setCoord(const MyGUI::IntCoord &_value)
|
||||
layoutWidgets();
|
||||
}
|
||||
|
||||
void ItemView::setCoord(int _left, int _top, int _width, int _height)
|
||||
{
|
||||
setCoord(MyGUI::IntCoord(_left, _top, _width, _height));
|
||||
}
|
||||
|
||||
void ItemView::registerComponents()
|
||||
{
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ItemView>("Widget");
|
||||
|
@ -37,8 +37,6 @@ namespace MWGui
|
||||
|
||||
virtual void setSize(const MyGUI::IntSize& _value);
|
||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
||||
void setSize(int _width, int _height);
|
||||
void setCoord(int _left, int _top, int _width, int _height);
|
||||
|
||||
void onSelectedItem (MyGUI::Widget* sender);
|
||||
void onSelectedBackground (MyGUI::Widget* sender);
|
||||
|
@ -149,7 +149,9 @@ namespace MWGui
|
||||
Ogre::TextureManager::getSingleton ().load (randomSplash, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
|
||||
|
||||
// TODO: add option (filename pattern?) to use image aspect ratio instead of 4:3
|
||||
mBackgroundImage->setBackgroundImage(randomSplash, true, true);
|
||||
// we can't do this by default, because the Morrowind splash screens are 1024x1024, but should be displayed as 4:3
|
||||
bool stretch = Settings::Manager::getBool("stretch menu background", "GUI");
|
||||
mBackgroundImage->setBackgroundImage(randomSplash, true, stretch);
|
||||
}
|
||||
else
|
||||
std::cerr << "No loading screens found!" << std::endl;
|
||||
|
@ -160,6 +160,8 @@ namespace MWGui
|
||||
if (!show)
|
||||
return;
|
||||
|
||||
bool stretch = Settings::Manager::getBool("stretch menu background", "GUI");
|
||||
|
||||
if (mHasAnimatedMenu)
|
||||
{
|
||||
if (!mVideo)
|
||||
@ -180,16 +182,7 @@ namespace MWGui
|
||||
int screenHeight = viewSize.height;
|
||||
mVideoBackground->setSize(screenWidth, screenHeight);
|
||||
|
||||
if (mVideo->getVideoHeight() > 0)
|
||||
{
|
||||
double imageaspect = static_cast<double>(mVideo->getVideoWidth())/mVideo->getVideoHeight();
|
||||
|
||||
int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2);
|
||||
int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2);
|
||||
|
||||
mVideo->setCoord(leftPadding, topPadding,
|
||||
screenWidth - leftPadding*2, screenHeight - topPadding*2);
|
||||
}
|
||||
mVideo->autoResize(stretch);
|
||||
|
||||
mVideo->setVisible(true);
|
||||
}
|
||||
@ -199,7 +192,7 @@ namespace MWGui
|
||||
{
|
||||
mBackground = MyGUI::Gui::getInstance().createWidgetReal<BackgroundImage>("ImageBox", 0,0,1,1,
|
||||
MyGUI::Align::Stretch, "Menu");
|
||||
mBackground->setBackgroundImage("textures\\menu_morrowind.dds");
|
||||
mBackground->setBackgroundImage("textures\\menu_morrowind.dds", true, stretch);
|
||||
}
|
||||
mBackground->setVisible(true);
|
||||
}
|
||||
|
@ -201,11 +201,6 @@ namespace MWGui
|
||||
layoutWidgets();
|
||||
}
|
||||
|
||||
void SpellView::setSize(int _width, int _height)
|
||||
{
|
||||
setSize(MyGUI::IntSize(_width, _height));
|
||||
}
|
||||
|
||||
void SpellView::setCoord(const MyGUI::IntCoord &_value)
|
||||
{
|
||||
bool changed = (_value.width != getWidth() || _value.height != getHeight());
|
||||
@ -214,11 +209,6 @@ namespace MWGui
|
||||
layoutWidgets();
|
||||
}
|
||||
|
||||
void SpellView::setCoord(int _left, int _top, int _width, int _height)
|
||||
{
|
||||
setCoord(MyGUI::IntCoord(_left, _top, _width, _height));
|
||||
}
|
||||
|
||||
void SpellView::adjustSpellWidget(const Spell &spell, SpellModel::ModelIndex index, MyGUI::Widget *widget)
|
||||
{
|
||||
if (spell.mType == Spell::Type_EnchantedItem)
|
||||
|
@ -45,8 +45,6 @@ namespace MWGui
|
||||
|
||||
virtual void setSize(const MyGUI::IntSize& _value);
|
||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
||||
void setSize(int _width, int _height);
|
||||
void setCoord(int _left, int _top, int _width, int _height);
|
||||
|
||||
private:
|
||||
MyGUI::ScrollView* mScrollView;
|
||||
|
@ -108,7 +108,6 @@ namespace MWGui
|
||||
void StatsWindow::setPlayerName(const std::string& playerName)
|
||||
{
|
||||
mMainWidget->castType<MyGUI::Window>()->setCaption(playerName);
|
||||
adjustWindowCaption();
|
||||
}
|
||||
|
||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
|
@ -133,8 +133,6 @@ namespace MWGui
|
||||
|
||||
updateLabels();
|
||||
|
||||
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
|
||||
// or we end up using a possibly invalid model.
|
||||
setTitle(actor.getClass().getName(actor));
|
||||
|
||||
onFilterChanged(mFilterAll);
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <extern/ogre-ffmpeg-videoplayer/videoplayer.hpp>
|
||||
|
||||
#include <MyGUI_RenderManager.h>
|
||||
|
||||
#include "../mwsound/movieaudiofactory.hpp"
|
||||
|
||||
namespace MWGui
|
||||
@ -46,4 +48,24 @@ bool VideoWidget::hasAudioStream()
|
||||
return mPlayer->hasAudioStream();
|
||||
}
|
||||
|
||||
void VideoWidget::autoResize(bool stretch)
|
||||
{
|
||||
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
if (getParent())
|
||||
screenSize = getParent()->getSize();
|
||||
|
||||
if (getVideoHeight() > 0 && !stretch)
|
||||
{
|
||||
double imageaspect = static_cast<double>(getVideoWidth())/getVideoHeight();
|
||||
|
||||
int leftPadding = std::max(0.0, (screenSize.width - screenSize.height * imageaspect) / 2);
|
||||
int topPadding = std::max(0.0, (screenSize.height - screenSize.width / imageaspect) / 2);
|
||||
|
||||
setCoord(leftPadding, topPadding,
|
||||
screenSize.width - leftPadding*2, screenSize.height - topPadding*2);
|
||||
}
|
||||
else
|
||||
setCoord(0,0,screenSize.width,screenSize.height);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,12 @@ namespace MWGui
|
||||
/// Stop video and free resources (done automatically on destruction)
|
||||
void stop();
|
||||
|
||||
/// Adjust the coordinates of this video widget relative to its parent,
|
||||
/// based on the dimensions of the playing video.
|
||||
/// @param stretch Stretch the video to fill the whole screen? If false,
|
||||
/// black bars may be added to fix the aspect ratio.
|
||||
void autoResize (bool stretch);
|
||||
|
||||
private:
|
||||
std::auto_ptr<Video::VideoPlayer> mPlayer;
|
||||
};
|
||||
|
@ -1712,18 +1712,9 @@ namespace MWGui
|
||||
void WindowManager::sizeVideo(int screenWidth, int screenHeight)
|
||||
{
|
||||
// Use black bars to correct aspect ratio
|
||||
bool stretch = Settings::Manager::getBool("stretch menu background", "GUI");
|
||||
mVideoBackground->setSize(screenWidth, screenHeight);
|
||||
|
||||
if (mVideoWidget->getVideoHeight() > 0)
|
||||
{
|
||||
double imageaspect = static_cast<double>(mVideoWidget->getVideoWidth())/mVideoWidget->getVideoHeight();
|
||||
|
||||
int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2);
|
||||
int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2);
|
||||
|
||||
mVideoWidget->setCoord(leftPadding, topPadding,
|
||||
screenWidth - leftPadding*2, screenHeight - topPadding*2);
|
||||
}
|
||||
mVideoWidget->autoResize(stretch);
|
||||
}
|
||||
|
||||
WindowModal* WindowManager::getCurrentModal() const
|
||||
|
@ -58,7 +58,7 @@ namespace
|
||||
// magnitude of pits/obstacles is defined by PATHFIND_Z_REACH
|
||||
bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offsetXY)
|
||||
{
|
||||
if((to - from).length() >= PATHFIND_CAUTION_DIST || abs(from.z - to.z) <= PATHFIND_Z_REACH)
|
||||
if((to - from).length() >= PATHFIND_CAUTION_DIST || std::abs(from.z - to.z) <= PATHFIND_Z_REACH)
|
||||
{
|
||||
Ogre::Vector3 dir = to - from;
|
||||
dir.z = 0;
|
||||
@ -69,7 +69,7 @@ namespace
|
||||
// cast up-down ray and find height in world space of hit
|
||||
float h = _from.z - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, -Ogre::Vector3::UNIT_Z, verticalOffset + PATHFIND_Z_REACH + 1);
|
||||
|
||||
if(abs(from.z - h) <= PATHFIND_Z_REACH)
|
||||
if(std::abs(from.z - h) <= PATHFIND_Z_REACH)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1372,7 +1372,7 @@ void CharacterController::update(float duration)
|
||||
|
||||
//Force Jump Logic
|
||||
|
||||
bool isMoving = (std::abs(cls.getMovementSettings(mPtr).mPosition[0]) > .5 || abs(cls.getMovementSettings(mPtr).mPosition[1]) > .5);
|
||||
bool isMoving = (std::abs(cls.getMovementSettings(mPtr).mPosition[0]) > .5 || std::abs(cls.getMovementSettings(mPtr).mPosition[1]) > .5);
|
||||
if(!inwater && !flying)
|
||||
{
|
||||
//Force Jump
|
||||
|
@ -29,7 +29,7 @@ Ogre::Radian signedAngle(Ogre::Vector3 v1, Ogre::Vector3 v2, Ogre::Vector3 norma
|
||||
);
|
||||
}
|
||||
|
||||
void applyEnchantment (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& object, const Ogre::Vector3& hitPosition)
|
||||
bool applyEnchantment (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& object, const Ogre::Vector3& hitPosition)
|
||||
{
|
||||
std::string enchantmentName = !object.isEmpty() ? object.getClass().getEnchantment(object) : "";
|
||||
if (!enchantmentName.empty())
|
||||
@ -41,8 +41,10 @@ void applyEnchantment (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim,
|
||||
MWMechanics::CastSpell cast(attacker, victim);
|
||||
cast.mHitPosition = hitPosition;
|
||||
cast.cast(object);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@ -216,15 +218,16 @@ namespace MWMechanics
|
||||
damage *= gmst.find("fCombatKODamageMult")->getFloat();
|
||||
|
||||
// Apply "On hit" effect of the weapon
|
||||
applyEnchantment(attacker, victim, weapon, hitPosition);
|
||||
bool appliedEnchantment = applyEnchantment(attacker, victim, weapon, hitPosition);
|
||||
if (weapon != projectile)
|
||||
applyEnchantment(attacker, victim, projectile, hitPosition);
|
||||
appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition);
|
||||
|
||||
if (damage > 0)
|
||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
||||
|
||||
// Arrows shot at enemies have a chance to turn up in their inventory
|
||||
if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
|
||||
if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr()
|
||||
&& !appliedEnchantment)
|
||||
{
|
||||
float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->getFloat();
|
||||
if ((::rand()/(RAND_MAX+1.0)) < fProjectileThrownStoreChance/100.f)
|
||||
|
@ -70,9 +70,9 @@ namespace MWMechanics
|
||||
else
|
||||
{
|
||||
if (ref.getPtr().getTypeName() == typeid(ESM::ItemLevList).name())
|
||||
return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, failChance);
|
||||
return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false, failChance);
|
||||
else
|
||||
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, failChance);
|
||||
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, failChance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,8 +572,7 @@ namespace MWMechanics
|
||||
|
||||
float reaction = 0;
|
||||
int rank = 0;
|
||||
std::string npcFaction = "";
|
||||
if(!npcSkill.getFactionRanks().empty()) npcFaction = npcSkill.getFactionRanks().begin()->first;
|
||||
std::string npcFaction = ptr.getClass().getPrimaryFaction(ptr);
|
||||
|
||||
Misc::StringUtils::toLower(npcFaction);
|
||||
|
||||
@ -1156,10 +1155,10 @@ namespace MWMechanics
|
||||
// If committing a crime against a faction member, expell from the faction
|
||||
if (!victim.isEmpty() && victim.getClass().isNpc())
|
||||
{
|
||||
std::string factionID;
|
||||
if(!victim.getClass().getNpcStats(victim).getFactionRanks().empty())
|
||||
factionID = victim.getClass().getNpcStats(victim).getFactionRanks().begin()->first;
|
||||
if (player.getClass().getNpcStats(player).isSameFaction(victim.getClass().getNpcStats(victim)))
|
||||
std::string factionID = victim.getClass().getPrimaryFaction(victim);
|
||||
|
||||
const std::map<std::string, int>& playerRanks = player.getClass().getNpcStats(player).getFactionRanks();
|
||||
if (playerRanks.find(Misc::StringUtils::lowerCase(factionID)) != playerRanks.end())
|
||||
{
|
||||
player.getClass().getNpcStats(player).expell(factionID);
|
||||
}
|
||||
|
@ -91,12 +91,6 @@ void MWMechanics::NpcStats::lowerRank(const std::string &faction)
|
||||
}
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::setFactionRank(const std::string &faction, int rank)
|
||||
{
|
||||
const std::string lower = Misc::StringUtils::lowerCase(faction);
|
||||
mFactionRank[lower] = rank;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::joinFaction(const std::string& faction)
|
||||
{
|
||||
const std::string lower = Misc::StringUtils::lowerCase(faction);
|
||||
@ -127,14 +121,9 @@ void MWMechanics::NpcStats::clearExpelled(const std::string& factionID)
|
||||
mExpelled.erase(Misc::StringUtils::lowerCase(factionID));
|
||||
}
|
||||
|
||||
bool MWMechanics::NpcStats::isSameFaction (const NpcStats& npcStats) const
|
||||
bool MWMechanics::NpcStats::isInFaction (const std::string& faction) const
|
||||
{
|
||||
for (std::map<std::string, int>::const_iterator iter (mFactionRank.begin()); iter!=mFactionRank.end();
|
||||
++iter)
|
||||
if (npcStats.mFactionRank.find (iter->first)!=npcStats.mFactionRank.end())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return (mFactionRank.find(Misc::StringUtils::lowerCase(faction)) != mFactionRank.end());
|
||||
}
|
||||
|
||||
float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& class_, int usageType,
|
||||
|
@ -33,9 +33,7 @@ namespace MWMechanics
|
||||
// ----- used by the player only, maybe should be moved at some point -------
|
||||
int mBounty;
|
||||
int mWerewolfKills;
|
||||
/// NPCs other than the player can only have one faction. But for the sake of consistency
|
||||
/// we use the same data structure for the PC and the NPCs.
|
||||
/// \note the faction key must be in lowercase
|
||||
/// Used for the player only; NPCs have maximum one faction defined in their NPC record
|
||||
std::map<std::string, int> mFactionRank;
|
||||
std::set<std::string> mExpelled;
|
||||
std::map<std::string, int> mFactionReputation;
|
||||
@ -74,17 +72,13 @@ namespace MWMechanics
|
||||
void lowerRank(const std::string& faction);
|
||||
/// Join this faction, setting the initial rank to 0.
|
||||
void joinFaction(const std::string& faction);
|
||||
/// Warning: this function performs no check whether the rank exists,
|
||||
/// and should be used in initial actor setup only.
|
||||
void setFactionRank(const std::string& faction, int rank);
|
||||
|
||||
const std::set<std::string>& getExpelled() const { return mExpelled; }
|
||||
bool getExpelled(const std::string& factionID) const;
|
||||
void expell(const std::string& factionID);
|
||||
void clearExpelled(const std::string& factionID);
|
||||
|
||||
bool isSameFaction (const NpcStats& npcStats) const;
|
||||
///< Do *this and \a npcStats share a faction?
|
||||
bool isInFaction (const std::string& faction) const;
|
||||
|
||||
float getSkillGain (int skillIndex, const ESM::Class& class_, int usageType = -1,
|
||||
int level = -1, float extraFactor=1.f) const;
|
||||
|
@ -115,8 +115,8 @@ namespace MWMechanics
|
||||
if(mDistSameSpot == -1)
|
||||
mDistSameSpot = DIST_SAME_SPOT * (cls.getSpeed(actor) / 150);
|
||||
|
||||
bool samePosition = (abs(pos.pos[0] - mPrevX) < mDistSameSpot) &&
|
||||
(abs(pos.pos[1] - mPrevY) < mDistSameSpot);
|
||||
bool samePosition = (std::abs(pos.pos[0] - mPrevX) < mDistSameSpot) &&
|
||||
(std::abs(pos.pos[1] - mPrevY) < mDistSameSpot);
|
||||
// update position
|
||||
mPrevX = pos.pos[0];
|
||||
mPrevY = pos.pos[1];
|
||||
|
@ -66,108 +66,83 @@ namespace MWRender
|
||||
loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1));
|
||||
loadingListener->setProgress(0);
|
||||
|
||||
const Ogre::ColourValue waterShallowColour(0.15, 0.2, 0.19);
|
||||
const Ogre::ColourValue waterDeepColour(0.1, 0.14, 0.13);
|
||||
const Ogre::ColourValue groundColour(0.254, 0.19, 0.13);
|
||||
const Ogre::ColourValue mountainColour(0.05, 0.05, 0.05);
|
||||
const Ogre::ColourValue hillColour(0.16, 0.12, 0.08);
|
||||
std::vector<Ogre::uchar> data (mWidth * mHeight * 3);
|
||||
|
||||
//if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png"))
|
||||
if (1)
|
||||
for (int x = mMinX; x <= mMaxX; ++x)
|
||||
{
|
||||
std::vector<Ogre::uchar> data (mWidth * mHeight * 3);
|
||||
|
||||
for (int x = mMinX; x <= mMaxX; ++x)
|
||||
for (int y = mMinY; y <= mMaxY; ++y)
|
||||
{
|
||||
for (int y = mMinY; y <= mMaxY; ++y)
|
||||
ESM::Land* land = esmStore.get<ESM::Land>().search (x,y);
|
||||
|
||||
if (land)
|
||||
{
|
||||
ESM::Land* land = esmStore.get<ESM::Land>().search (x,y);
|
||||
int mask = ESM::Land::DATA_WNAM;
|
||||
if (!land->isDataLoaded(mask))
|
||||
land->loadData(mask);
|
||||
}
|
||||
|
||||
if (land)
|
||||
for (int cellY=0; cellY<mCellSize; ++cellY)
|
||||
{
|
||||
for (int cellX=0; cellX<mCellSize; ++cellX)
|
||||
{
|
||||
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(mask))
|
||||
land->loadData(mask);
|
||||
}
|
||||
int vertexX = float(cellX)/float(mCellSize) * 9;
|
||||
int vertexY = float(cellY)/float(mCellSize) * 9;
|
||||
|
||||
for (int cellY=0; cellY<mCellSize; ++cellY)
|
||||
{
|
||||
for (int cellX=0; cellX<mCellSize; ++cellX)
|
||||
|
||||
int texelX = (x-mMinX) * mCellSize + cellX;
|
||||
int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY);
|
||||
|
||||
unsigned char r,g,b;
|
||||
|
||||
float y = 0;
|
||||
if (land && land->mDataTypes & ESM::Land::DATA_WNAM)
|
||||
y = (land->mLandData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
|
||||
else
|
||||
y = (SCHAR_MIN << 4) / 2048.f;
|
||||
if (y < 0)
|
||||
{
|
||||
int vertexX = float(cellX)/float(mCellSize) * ESM::Land::LAND_SIZE;
|
||||
int vertexY = float(cellY)/float(mCellSize) * ESM::Land::LAND_SIZE;
|
||||
|
||||
|
||||
int texelX = (x-mMinX) * mCellSize + cellX;
|
||||
int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY);
|
||||
|
||||
unsigned char r,g,b;
|
||||
|
||||
if (land)
|
||||
{
|
||||
const float landHeight = land->mLandData->mHeights[vertexY * ESM::Land::LAND_SIZE + vertexX];
|
||||
|
||||
if (landHeight >= 0)
|
||||
{
|
||||
const float hillHeight = 2500.f;
|
||||
if (landHeight >= hillHeight)
|
||||
{
|
||||
const float mountainHeight = 15000.f;
|
||||
float factor = std::min(1.f, float(landHeight-hillHeight)/mountainHeight);
|
||||
r = (hillColour.r * (1-factor) + mountainColour.r * factor) * 255;
|
||||
g = (hillColour.g * (1-factor) + mountainColour.g * factor) * 255;
|
||||
b = (hillColour.b * (1-factor) + mountainColour.b * factor) * 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
float factor = std::min(1.f, float(landHeight)/hillHeight);
|
||||
r = (groundColour.r * (1-factor) + hillColour.r * factor) * 255;
|
||||
g = (groundColour.g * (1-factor) + hillColour.g * factor) * 255;
|
||||
b = (groundColour.b * (1-factor) + hillColour.b * factor) * 255;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (landHeight >= -100)
|
||||
{
|
||||
float factor = std::min(1.f, -1*landHeight/100.f);
|
||||
r = (((waterShallowColour+groundColour)/2).r * (1-factor) + waterShallowColour.r * factor) * 255;
|
||||
g = (((waterShallowColour+groundColour)/2).g * (1-factor) + waterShallowColour.g * factor) * 255;
|
||||
b = (((waterShallowColour+groundColour)/2).b * (1-factor) + waterShallowColour.b * factor) * 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
float factor = std::min(1.f, -1*(landHeight-100)/1000.f);
|
||||
r = (waterShallowColour.r * (1-factor) + waterDeepColour.r * factor) * 255;
|
||||
g = (waterShallowColour.g * (1-factor) + waterDeepColour.g * factor) * 255;
|
||||
b = (waterShallowColour.b * (1-factor) + waterDeepColour.b * factor) * 255;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
r = (14 * y + 38);
|
||||
g = 20 * y + 56;
|
||||
b = 18 * y + 51;
|
||||
}
|
||||
else if (y < 0.3f)
|
||||
{
|
||||
if (y < 0.1f)
|
||||
y *= 8.f;
|
||||
else
|
||||
{
|
||||
r = waterDeepColour.r * 255;
|
||||
g = waterDeepColour.g * 255;
|
||||
b = waterDeepColour.b * 255;
|
||||
y -= 0.1;
|
||||
y += 0.8;
|
||||
}
|
||||
|
||||
data[texelY * mWidth * 3 + texelX * 3] = r;
|
||||
data[texelY * mWidth * 3 + texelX * 3+1] = g;
|
||||
data[texelY * mWidth * 3 + texelX * 3+2] = b;
|
||||
r = 66 - 32 * y;
|
||||
g = 48 - 23 * y;
|
||||
b = 33 - 16 * y;
|
||||
}
|
||||
else
|
||||
{
|
||||
y -= 0.3f;
|
||||
y *= 1.428f;
|
||||
r = 34 - 29 * y;
|
||||
g = 25 - 20 * y;
|
||||
b = 17 - 12 * y;
|
||||
}
|
||||
|
||||
data[texelY * mWidth * 3 + texelX * 3] = r;
|
||||
data[texelY * mWidth * 3 + texelX * 3+1] = g;
|
||||
data[texelY * mWidth * 3 + texelX * 3+2] = b;
|
||||
}
|
||||
}
|
||||
loadingListener->increaseProgress();
|
||||
if (land)
|
||||
land->unloadData();
|
||||
}
|
||||
|
||||
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
|
||||
|
||||
tex = Ogre::TextureManager::getSingleton ().createManual ("GlobalMap.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_B8G8R8, Ogre::TU_STATIC);
|
||||
tex->loadRawData(stream, mWidth, mHeight, Ogre::PF_B8G8R8);
|
||||
}
|
||||
else
|
||||
tex = Ogre::TextureManager::getSingleton ().getByName ("GlobalMap.png");
|
||||
|
||||
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
|
||||
|
||||
tex = Ogre::TextureManager::getSingleton ().createManual ("GlobalMap.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_B8G8R8, Ogre::TU_STATIC);
|
||||
tex->loadRawData(stream, mWidth, mHeight, Ogre::PF_B8G8R8);
|
||||
|
||||
tex->load();
|
||||
|
||||
@ -267,9 +242,9 @@ namespace MWRender
|
||||
{
|
||||
const ESM::GlobalMap::Bounds& bounds = map.mBounds;
|
||||
|
||||
if (bounds.mMaxX-bounds.mMinX <= 0)
|
||||
if (bounds.mMaxX-bounds.mMinX < 0)
|
||||
return;
|
||||
if (bounds.mMaxY-bounds.mMinY <= 0)
|
||||
if (bounds.mMaxY-bounds.mMinY < 0)
|
||||
return;
|
||||
|
||||
if (bounds.mMinX > bounds.mMaxX
|
||||
|
@ -1020,7 +1020,10 @@ void NpcAnimation::setVampire(bool vampire)
|
||||
return;
|
||||
if ((mNpcType == Type_Vampire) != vampire)
|
||||
{
|
||||
rebuild();
|
||||
if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
MWBase::Environment::get().getWorld()->reattachPlayerCamera();
|
||||
else
|
||||
rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,10 +1036,10 @@ void RenderingManager::enableTerrain(bool enable)
|
||||
if (!mTerrain)
|
||||
{
|
||||
if (Settings::Manager::getBool("distant land", "Terrain"))
|
||||
mTerrain = new Terrain::DefaultWorld(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
||||
mTerrain = new Terrain::DefaultWorld(mRendering.getScene(), new MWRender::TerrainStorage(true), RV_Terrain,
|
||||
Settings::Manager::getBool("shader", "Terrain"), Terrain::Align_XY, 1, 64);
|
||||
else
|
||||
mTerrain = new Terrain::TerrainGrid(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
||||
mTerrain = new Terrain::TerrainGrid(mRendering.getScene(), new MWRender::TerrainStorage(false), RV_Terrain,
|
||||
Settings::Manager::getBool("shader", "Terrain"), Terrain::Align_XY);
|
||||
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
|
||||
Settings::Manager::getBool("split", "Shadows"));
|
||||
|
@ -9,6 +9,22 @@
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
TerrainStorage::TerrainStorage(bool preload)
|
||||
{
|
||||
if (preload)
|
||||
{
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
MWWorld::Store<ESM::Land>::iterator it = esmStore.get<ESM::Land>().begin();
|
||||
for (; it != esmStore.get<ESM::Land>().end(); ++it)
|
||||
{
|
||||
ESM::Land* land = const_cast<ESM::Land*>(&*it); // TODO: fix store interface
|
||||
land->loadData(ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainStorage::getBounds(float& minX, float& maxX, float& minY, float& maxY)
|
||||
{
|
||||
minX = 0, minY = 0, maxX = 0, maxY = 0;
|
||||
@ -39,6 +55,12 @@ namespace MWRender
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
ESM::Land* land = esmStore.get<ESM::Land>().search(cellX, cellY);
|
||||
if (!land)
|
||||
return NULL;
|
||||
|
||||
const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(flags))
|
||||
land->loadData(flags);
|
||||
return land;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,10 @@ namespace MWRender
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
|
||||
public:
|
||||
|
||||
///@param preload Preload all Land records at startup? If using the multithreaded terrain component, this
|
||||
/// should be set to "true" in order to avoid race conditions.
|
||||
TerrainStorage(bool preload);
|
||||
|
||||
/// Get bounds of the whole terrain in cell units
|
||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
|
||||
};
|
||||
|
@ -196,7 +196,7 @@ namespace MWScript
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||
|
||||
runtime.push (ptr.getClass().getNpcStats (ptr).isSameFaction (player.getClass().getNpcStats (player)));
|
||||
player.getClass().getNpcStats (player).isInFaction(ptr.getClass().getPrimaryFaction(ptr));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "globalscripts.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/esm/globalscript.hpp>
|
||||
|
@ -313,17 +313,19 @@ namespace MWScript
|
||||
|
||||
std::string InterpreterContext::getNPCRank() const
|
||||
{
|
||||
if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty())
|
||||
const MWWorld::Ptr& ptr = getReferenceImp();
|
||||
std::string faction = ptr.getClass().getPrimaryFaction(ptr);
|
||||
if (faction.empty())
|
||||
throw std::runtime_error("getNPCRank(): NPC is not in a faction");
|
||||
|
||||
const std::map<std::string, int>& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator it = ranks.begin();
|
||||
int rank = ptr.getClass().getPrimaryFactionRank(ptr);
|
||||
if (rank < 0 || rank > 9)
|
||||
throw std::runtime_error("getNPCRank(): invalid rank");
|
||||
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::ESMStore &store = world->getStore();
|
||||
const ESM::Faction *faction = store.get<ESM::Faction>().find(it->first);
|
||||
|
||||
return faction->mRanks[it->second];
|
||||
const ESM::Faction *fact = store.get<ESM::Faction>().find(faction);
|
||||
return fact->mRanks[rank];
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getPCName() const
|
||||
@ -352,13 +354,12 @@ namespace MWScript
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr player = world->getPlayerPtr();
|
||||
|
||||
if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty())
|
||||
std::string factionId = getReferenceImp().getClass().getPrimaryFaction(getReferenceImp());
|
||||
if (factionId.empty())
|
||||
throw std::runtime_error("getPCRank(): NPC is not in a faction");
|
||||
|
||||
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
||||
|
||||
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator it = ranks.find(factionId);
|
||||
std::map<std::string, int>::const_iterator it = ranks.find(Misc::StringUtils::lowerCase(factionId));
|
||||
int rank = -1;
|
||||
if (it != ranks.end())
|
||||
rank = it->second;
|
||||
@ -382,13 +383,12 @@ namespace MWScript
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr player = world->getPlayerPtr();
|
||||
|
||||
if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty())
|
||||
std::string factionId = getReferenceImp().getClass().getPrimaryFaction(getReferenceImp());
|
||||
if (factionId.empty())
|
||||
throw std::runtime_error("getPCNextRank(): NPC is not in a faction");
|
||||
|
||||
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
||||
|
||||
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator it = ranks.find(factionId);
|
||||
std::map<std::string, int>::const_iterator it = ranks.find(Misc::StringUtils::lowerCase(factionId));
|
||||
int rank = -1;
|
||||
if (it != ranks.end())
|
||||
rank = it->second;
|
||||
|
@ -32,13 +32,12 @@ namespace
|
||||
{
|
||||
std::string getDialogueActorFaction(MWWorld::Ptr actor)
|
||||
{
|
||||
const MWMechanics::NpcStats &stats = actor.getClass().getNpcStats (actor);
|
||||
|
||||
if (stats.getFactionRanks().empty())
|
||||
std::string factionId = actor.getClass().getPrimaryFaction(actor);
|
||||
if (factionId.empty())
|
||||
throw std::runtime_error (
|
||||
"failed to determine dialogue actors faction (because actor is factionless)");
|
||||
|
||||
return stats.getFactionRanks().begin()->first;
|
||||
return factionId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -665,14 +664,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
|
||||
{
|
||||
factionID = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first;
|
||||
}
|
||||
factionID = ptr.getClass().getPrimaryFaction(ptr);
|
||||
}
|
||||
::Misc::StringUtils::toLower(factionID);
|
||||
// Make sure this faction exists
|
||||
@ -779,8 +771,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ptr.getClass().getNpcStats (ptr).getFactionRanks().empty())
|
||||
factionId = ptr.getClass().getNpcStats (ptr).getFactionRanks().begin()->first;
|
||||
factionId = getDialogueActorFaction(ptr);
|
||||
}
|
||||
|
||||
if (factionId.empty())
|
||||
@ -815,8 +806,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ptr.getClass().getNpcStats (ptr).getFactionRanks().empty())
|
||||
factionId = ptr.getClass().getNpcStats (ptr).getFactionRanks().begin()->first;
|
||||
factionId = getDialogueActorFaction(ptr);
|
||||
}
|
||||
|
||||
if (factionId.empty())
|
||||
@ -850,8 +840,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ptr.getClass().getNpcStats (ptr).getFactionRanks().empty())
|
||||
factionId = ptr.getClass().getNpcStats (ptr).getFactionRanks().begin()->first;
|
||||
factionId = getDialogueActorFaction(ptr);
|
||||
}
|
||||
|
||||
if (factionId.empty())
|
||||
@ -941,14 +930,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
|
||||
{
|
||||
factionID = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first;
|
||||
}
|
||||
factionID = ptr.getClass().getPrimaryFaction(ptr);
|
||||
}
|
||||
::Misc::StringUtils::toLower(factionID);
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
@ -980,14 +962,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
|
||||
{
|
||||
factionID = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first;
|
||||
}
|
||||
factionID = ptr.getClass().getPrimaryFaction(ptr);
|
||||
}
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
if(factionID!="")
|
||||
@ -1014,14 +989,7 @@ namespace MWScript
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
|
||||
{
|
||||
factionID = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first;
|
||||
}
|
||||
factionID = ptr.getClass().getPrimaryFaction(ptr);
|
||||
}
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
if(factionID!="")
|
||||
@ -1038,13 +1006,10 @@ namespace MWScript
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string factionID = "";
|
||||
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
|
||||
std::string factionID = ptr.getClass().getPrimaryFaction(ptr);
|
||||
if(factionID.empty())
|
||||
return;
|
||||
else
|
||||
{
|
||||
factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first;
|
||||
}
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
|
||||
// no-op when executed on the player
|
||||
@ -1064,13 +1029,10 @@ namespace MWScript
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string factionID = "";
|
||||
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
|
||||
std::string factionID = ptr.getClass().getPrimaryFaction(ptr);
|
||||
if(factionID.empty())
|
||||
return;
|
||||
else
|
||||
{
|
||||
factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first;
|
||||
}
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
|
||||
// no-op when executed on the player
|
||||
|
@ -445,4 +445,13 @@ namespace MWWorld
|
||||
{
|
||||
throw std::runtime_error("class does not support fight rating");
|
||||
}
|
||||
|
||||
std::string Class::getPrimaryFaction (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
int Class::getPrimaryFactionRank (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +342,9 @@ namespace MWWorld
|
||||
virtual std::string getSound(const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getPrimaryFaction (const MWWorld::Ptr& ptr) const;
|
||||
virtual int getPrimaryFactionRank (const MWWorld::Ptr& ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "esmloader.hpp"
|
||||
#include "esmstore.hpp"
|
||||
|
||||
#include "components/to_utf8/to_utf8.hpp"
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include <components/loadinglistener/loadinglistener.hpp>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "localscripts.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "esmstore.hpp"
|
||||
#include "cellstore.hpp"
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include <components/esm/records.hpp>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
struct RecordCmp
|
||||
|
@ -231,6 +231,11 @@ namespace MWWorld
|
||||
cell->getCell()->getGridY()
|
||||
);
|
||||
if (land) {
|
||||
// Actually only VHGT is needed here, but we'll need the rest for rendering anyway.
|
||||
// Load everything now to reduce IO overhead.
|
||||
const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(flags))
|
||||
land->loadData(flags);
|
||||
mPhysics->addHeightField (
|
||||
land->mLandData->mHeights,
|
||||
cell->getCell()->getGridX(),
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "store.hpp"
|
||||
#include "esmstore.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace MWWorld {
|
||||
|
||||
void Store<ESM::Cell>::handleMovedCellRefs(ESM::ESMReader& esm, ESM::Cell* cell)
|
||||
@ -117,4 +119,9 @@ void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
|
||||
}
|
||||
}
|
||||
|
||||
void Store<ESM::LandTexture>::load(ESM::ESMReader &esm, const std::string &id)
|
||||
{
|
||||
load(esm, id, esm.getIndex());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
|
||||
@ -436,9 +437,7 @@ namespace MWWorld
|
||||
ltexl[lt.mIndex] = lt;
|
||||
}
|
||||
|
||||
void load(ESM::ESMReader &esm, const std::string &id) {
|
||||
load(esm, id, esm.getIndex());
|
||||
}
|
||||
void load(ESM::ESMReader &esm, const std::string &id);
|
||||
|
||||
iterator begin(size_t plugin) const {
|
||||
assert(plugin < mStatic.size());
|
||||
|
@ -2457,6 +2457,11 @@ namespace MWWorld
|
||||
return mLevitationEnabled;
|
||||
}
|
||||
|
||||
void World::reattachPlayerCamera()
|
||||
{
|
||||
mRendering->rebuildPtr(getPlayerPtr());
|
||||
}
|
||||
|
||||
void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
|
||||
{
|
||||
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor);
|
||||
|
@ -537,6 +537,7 @@ namespace MWWorld
|
||||
|
||||
/// \todo Probably shouldn't be here
|
||||
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr);
|
||||
virtual void reattachPlayerCamera();
|
||||
|
||||
/// \todo this does not belong here
|
||||
virtual void frameStarted (float dt, bool paused);
|
||||
|
@ -58,7 +58,7 @@ add_component_dir (to_utf8
|
||||
add_component_dir (esm
|
||||
attr defs esmcommon esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell
|
||||
loadclas loadclot loadcont loadcrea loaddial loaddoor loadench loadfact loadglob loadgmst
|
||||
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc
|
||||
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc
|
||||
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
||||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||
@ -113,7 +113,7 @@ add_component_dir (ogreinit
|
||||
)
|
||||
|
||||
add_component_dir (widgets
|
||||
box imagebutton tags list numericeditbox sharedstatebutton widgets
|
||||
box imagebutton tags list numericeditbox sharedstatebutton windowcaption widgets
|
||||
)
|
||||
|
||||
add_component_dir (fontloader
|
||||
|
@ -53,18 +53,6 @@ typedef NAME_T<32> NAME32;
|
||||
typedef NAME_T<64> NAME64;
|
||||
typedef NAME_T<256> NAME256;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
// Data that is only present in save game files
|
||||
struct SaveData
|
||||
{
|
||||
float pos[6]; // Player position and rotation
|
||||
NAME64 cell; // Cell name
|
||||
float unk2; // Unknown value - possibly game time?
|
||||
NAME32 player; // Player name
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/* This struct defines a file 'context' which can be saved and later
|
||||
restored by an ESMReader instance. It will save the position within
|
||||
a file, and when restored will let you read from that position as
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
ESMWriter::ESMWriter()
|
||||
|
@ -4,11 +4,14 @@
|
||||
#include <iosfwd>
|
||||
#include <list>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "esmcommon.hpp"
|
||||
#include "loadtes3.hpp"
|
||||
|
||||
namespace ToUTF8
|
||||
{
|
||||
class Utf8Encoder;
|
||||
}
|
||||
|
||||
namespace ESM {
|
||||
|
||||
class ESMWriter
|
||||
|
@ -12,7 +12,7 @@ namespace ESM
|
||||
|
||||
struct GlobalScript
|
||||
{
|
||||
std::string mId;
|
||||
std::string mId; /// \note must be lowercase
|
||||
Locals mLocals;
|
||||
int mRunning;
|
||||
std::string mTargetId; // for targeted scripts
|
||||
|
@ -32,7 +32,11 @@ struct DialInfo
|
||||
struct DATAstruct
|
||||
{
|
||||
int mUnknown1;
|
||||
int mDisposition;
|
||||
union
|
||||
{
|
||||
int mDisposition; // Used for dialogue responses
|
||||
int mJournalIndex; // Used for journal entries
|
||||
};
|
||||
signed char mRank; // Rank of NPC
|
||||
signed char mGender; // See Gender enum
|
||||
signed char mPCrank; // Player rank
|
||||
|
@ -72,7 +72,6 @@ Land::Land()
|
||||
, mDataLoaded(false)
|
||||
, mLandData(NULL)
|
||||
, mPlugin(0)
|
||||
, mHasData(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -97,8 +96,6 @@ void Land::load(ESMReader &esm)
|
||||
// Store the file position
|
||||
mContext = esm.getContext();
|
||||
|
||||
mHasData = false;
|
||||
|
||||
// Skip these here. Load the actual data when the cell is loaded.
|
||||
if (esm.isNextSub("VNML"))
|
||||
{
|
||||
@ -126,10 +123,6 @@ void Land::load(ESMReader &esm)
|
||||
mDataTypes |= DATA_VTEX;
|
||||
}
|
||||
|
||||
// We need all three of VNML, VHGT and VTEX in order to use the
|
||||
// landscape. (Though Morrowind seems to accept terrain without VTEX/VCLR entries)
|
||||
mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM);
|
||||
|
||||
mDataLoaded = 0;
|
||||
mLandData = NULL;
|
||||
}
|
||||
@ -144,13 +137,12 @@ void Land::save(ESMWriter &esm) const
|
||||
esm.writeHNT("DATA", mFlags);
|
||||
}
|
||||
|
||||
/// \todo remove memory allocation when only defaults needed
|
||||
void Land::loadData(int flags)
|
||||
{
|
||||
// Try to load only available data
|
||||
int actual = flags & mDataTypes;
|
||||
flags = flags & mDataTypes;
|
||||
// Return if all required data is loaded
|
||||
if (flags == 0 || (actual != 0 && (mDataLoaded & actual) == actual)) {
|
||||
if ((mDataLoaded & flags) == flags) {
|
||||
return;
|
||||
}
|
||||
// Create storage if nothing is loaded
|
||||
@ -160,15 +152,13 @@ void Land::loadData(int flags)
|
||||
}
|
||||
mEsm->restoreContext(mContext);
|
||||
|
||||
memset(mLandData->mNormals, 0, sizeof(mLandData->mNormals));
|
||||
|
||||
if (mEsm->isNextSub("VNML")) {
|
||||
condLoad(actual, DATA_VNML, mLandData->mNormals, sizeof(mLandData->mNormals));
|
||||
condLoad(flags, DATA_VNML, mLandData->mNormals, sizeof(mLandData->mNormals));
|
||||
}
|
||||
|
||||
if (mEsm->isNextSub("VHGT")) {
|
||||
static VHGT vhgt;
|
||||
if (condLoad(actual, DATA_VHGT, &vhgt, sizeof(vhgt))) {
|
||||
if (condLoad(flags, DATA_VHGT, &vhgt, sizeof(vhgt))) {
|
||||
float rowOffset = vhgt.mHeightOffset;
|
||||
for (int y = 0; y < LAND_SIZE; y++) {
|
||||
rowOffset += vhgt.mHeightData[y * LAND_SIZE];
|
||||
@ -184,30 +174,18 @@ void Land::loadData(int flags)
|
||||
mLandData->mUnk1 = vhgt.mUnk1;
|
||||
mLandData->mUnk2 = vhgt.mUnk2;
|
||||
}
|
||||
} else if ((flags & DATA_VHGT) && (mDataLoaded & DATA_VHGT) == 0) {
|
||||
for (int i = 0; i < LAND_NUM_VERTS; ++i) {
|
||||
mLandData->mHeights[i] = -256.0f * HEIGHT_SCALE;
|
||||
}
|
||||
mDataLoaded |= DATA_VHGT;
|
||||
}
|
||||
|
||||
if (mEsm->isNextSub("WNAM")) {
|
||||
condLoad(actual, DATA_WNAM, mLandData->mWnam, 81);
|
||||
}
|
||||
if (mEsm->isNextSub("VCLR")) {
|
||||
mLandData->mUsingColours = true;
|
||||
condLoad(actual, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS);
|
||||
} else {
|
||||
mLandData->mUsingColours = false;
|
||||
condLoad(flags, DATA_WNAM, mLandData->mWnam, 81);
|
||||
}
|
||||
if (mEsm->isNextSub("VCLR"))
|
||||
condLoad(flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS);
|
||||
if (mEsm->isNextSub("VTEX")) {
|
||||
static uint16_t vtex[LAND_NUM_TEXTURES];
|
||||
if (condLoad(actual, DATA_VTEX, vtex, sizeof(vtex))) {
|
||||
if (condLoad(flags, DATA_VTEX, vtex, sizeof(vtex))) {
|
||||
LandData::transposeTextureData(vtex, mLandData->mTextures);
|
||||
}
|
||||
} else if ((flags & DATA_VTEX) && (mDataLoaded & DATA_VTEX) == 0) {
|
||||
memset(mLandData->mTextures, 0, sizeof(mLandData->mTextures));
|
||||
mDataLoaded |= DATA_VTEX;
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,4 +210,9 @@ bool Land::condLoad(int flags, int dataFlag, void *ptr, unsigned int size)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Land::isDataLoaded(int flags) const
|
||||
{
|
||||
return (mDataLoaded & flags) == (flags & mDataTypes);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ struct Land
|
||||
ESMReader* mEsm;
|
||||
ESM_Context mContext;
|
||||
|
||||
bool mHasData;
|
||||
int mDataTypes;
|
||||
int mDataLoaded;
|
||||
|
||||
@ -81,16 +80,12 @@ struct Land
|
||||
VNML mNormals[LAND_NUM_VERTS * 3];
|
||||
uint16_t mTextures[LAND_NUM_TEXTURES];
|
||||
|
||||
bool mUsingColours;
|
||||
char mColours[3 * LAND_NUM_VERTS];
|
||||
int mDataTypes;
|
||||
|
||||
// WNAM appears to contain the global map image for this cell. Probably a palette-based format,
|
||||
// since there's only 1 byte for each pixel.
|
||||
// Currently unused (global map is drawn on the fly in OpenMW, takes ~1/2 second at startup for Morrowind.esm).
|
||||
// The problem with using the original data is that we would need to exactly replicate the TES CS's algorithm
|
||||
// for drawing the global map in OpenCS, in order to get seamless edges when creating landmass mods.
|
||||
uint8_t mWnam[81];
|
||||
// low-LOD heightmap (used for rendering the global map)
|
||||
signed char mWnam[81];
|
||||
|
||||
short mUnk1;
|
||||
uint8_t mUnk2;
|
||||
|
||||
@ -116,10 +111,8 @@ struct Land
|
||||
void unloadData();
|
||||
|
||||
/// Check if given data type is loaded
|
||||
/// \todo reimplement this
|
||||
bool isDataLoaded(int flags) {
|
||||
return (mDataLoaded & flags) == flags;
|
||||
}
|
||||
/// @note We only check data types that *can* be loaded (present in mDataTypes)
|
||||
bool isDataLoaded(int flags) const;
|
||||
|
||||
private:
|
||||
Land(const Land& land);
|
||||
|
@ -144,4 +144,14 @@ void NPC::save(ESMWriter &esm) const
|
||||
mHair.clear();
|
||||
mHead.clear();
|
||||
}
|
||||
|
||||
int NPC::getFactionRank() const
|
||||
{
|
||||
if (mFaction.empty())
|
||||
return -1;
|
||||
else if (mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
return mNpdt12.mRank;
|
||||
else // NPC_DEFAULT
|
||||
return mNpdt52.mRank;
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +110,8 @@ struct NPC
|
||||
NPDTstruct52 mNpdt52;
|
||||
NPDTstruct12 mNpdt12; //for autocalculated characters
|
||||
|
||||
int getFactionRank() const; /// wrapper for mNpdt*, -1 = no rank
|
||||
|
||||
int mFlags;
|
||||
|
||||
bool mPersistent;
|
||||
|
@ -1,82 +0,0 @@
|
||||
#ifndef OPENMW_ESM_NPCC_H
|
||||
#define OPENMW_ESM_NPCC_H
|
||||
|
||||
#include <string>
|
||||
|
||||
// TODO: create implementation files to remove this
|
||||
#include "esmreader.hpp"
|
||||
|
||||
namespace ESM {
|
||||
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
/*
|
||||
* NPC change information (found in savegame files only). We can't
|
||||
* read these yet.
|
||||
*
|
||||
* Some general observations about savegames:
|
||||
*
|
||||
* SCPT records do not define new scripts, but assign values to the
|
||||
* variables of existing ones.
|
||||
*
|
||||
* VFXM, SPLM - no clue
|
||||
*
|
||||
* FMAP - MAPH and MAPD, global map image.
|
||||
*
|
||||
* JOUR - the entire journal in html
|
||||
*
|
||||
* QUES - seems to contain all the quests in the game, not just the
|
||||
* ones you have done or begun.
|
||||
*
|
||||
* REGN - lists all regions in the game, even unvisited ones.
|
||||
* notable differences to Regions in ESM files: mMapColor may be missing, and includes an unknown WNAM subrecord.
|
||||
*
|
||||
*
|
||||
* The DIAL/INFO blocks contain changes to characters' dialog status.
|
||||
*
|
||||
* Dammit there's a lot of stuff in there! Should really have
|
||||
* suspected as much. The strategy further is to completely ignore
|
||||
* save files for the time being.
|
||||
*
|
||||
* Several records have a "change" variant, like NPCC, CNTC
|
||||
* (contents), and CREC (creature.) These seem to alter specific
|
||||
* instances of creatures, npcs, etc. I have not identified most of
|
||||
* their subrecords yet.
|
||||
*
|
||||
* Several NPCC records have names that begin with "chargen ", I don't
|
||||
* know if it means something special yet.
|
||||
*
|
||||
* The CNTC blocks seem to be instances of leveled lists. When a
|
||||
* container is supposed to contain this leveled list of this type,
|
||||
* but is referenced elsewhere in the file by an INDX, the CNTC with
|
||||
* the corresponding leveled list identifier and INDX will determine
|
||||
* the container contents instead.
|
||||
*
|
||||
* Some classes of objects seem to be altered, and these include an
|
||||
* INDX, which is probably an index used by specific references other
|
||||
* places within the save file. I guess this means 'use this class for
|
||||
* these objects, not the general class.' All the indices I have
|
||||
* encountered so far are zero, but they have been for different
|
||||
* classes (different containers, really) so possibly we start from
|
||||
* zero for each class. This looks like a mess, but is probably still
|
||||
* easier than to duplicate everything. I think WRITING this format
|
||||
* will be harder than reading it.
|
||||
*/
|
||||
|
||||
struct LoadNPCC
|
||||
{
|
||||
static unsigned int sRecordId;
|
||||
|
||||
std::string mId;
|
||||
|
||||
void load(ESMReader &esm)
|
||||
{
|
||||
esm.skipRecord();
|
||||
}
|
||||
void save(ESMWriter &esm) const
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
@ -34,7 +34,7 @@ namespace ESM
|
||||
StatState<int> mWerewolfAttributes[8];
|
||||
bool mIsWerewolf;
|
||||
|
||||
std::map<std::string, Faction> mFactions;
|
||||
std::map<std::string, Faction> mFactions; // lower case IDs
|
||||
int mDisposition;
|
||||
Skill mSkills[27];
|
||||
int mBounty;
|
||||
@ -43,7 +43,7 @@ namespace ESM
|
||||
int mProfit;
|
||||
int mLevelProgress;
|
||||
int mSkillIncrease[8];
|
||||
std::vector<std::string> mUsedIds;
|
||||
std::vector<std::string> mUsedIds; // lower case IDs
|
||||
float mTimeToStartDrowning;
|
||||
int mCrimeId;
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace ESM
|
||||
|
||||
struct QuestState
|
||||
{
|
||||
std::string mTopic;
|
||||
std::string mTopic; // lower case id
|
||||
int mState;
|
||||
unsigned char mFinished;
|
||||
|
||||
@ -21,4 +21,4 @@ namespace ESM
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "loadmgef.hpp"
|
||||
#include "loadmisc.hpp"
|
||||
#include "loadnpc.hpp"
|
||||
#include "loadnpcc.hpp"
|
||||
#include "loadpgrd.hpp"
|
||||
#include "loadrace.hpp"
|
||||
#include "loadregn.hpp"
|
||||
|
@ -31,7 +31,7 @@ namespace ESMTerrain
|
||||
int cellY = origin.y;
|
||||
|
||||
const ESM::Land* land = getLand(cellX, cellY);
|
||||
if (!land)
|
||||
if (!land || !(land->mDataTypes&ESM::Land::DATA_VHGT))
|
||||
return false;
|
||||
|
||||
min = std::numeric_limits<float>::max();
|
||||
@ -73,7 +73,7 @@ namespace ESMTerrain
|
||||
row += ESM::Land::LAND_SIZE-1;
|
||||
}
|
||||
ESM::Land* land = getLand(cellX, cellY);
|
||||
if (land && land->mHasData)
|
||||
if (land && land->mDataTypes&ESM::Land::DATA_VNML)
|
||||
{
|
||||
normal.x = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3];
|
||||
normal.y = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1];
|
||||
@ -108,7 +108,7 @@ namespace ESMTerrain
|
||||
row = 0;
|
||||
}
|
||||
ESM::Land* land = getLand(cellX, cellY);
|
||||
if (land && land->mLandData->mUsingColours)
|
||||
if (land && land->mDataTypes&ESM::Land::DATA_VCLR)
|
||||
{
|
||||
color.r = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f;
|
||||
color.g = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f;
|
||||
@ -157,9 +157,8 @@ namespace ESMTerrain
|
||||
for (int cellX = startX; cellX < startX + std::ceil(size); ++cellX)
|
||||
{
|
||||
ESM::Land* land = getLand(cellX, cellY);
|
||||
if (land && !land->mHasData)
|
||||
if (land && !(land->mDataTypes&ESM::Land::DATA_VHGT))
|
||||
land = NULL;
|
||||
bool hasColors = land && land->mLandData->mUsingColours;
|
||||
|
||||
int rowStart = 0;
|
||||
int colStart = 0;
|
||||
@ -183,7 +182,7 @@ namespace ESMTerrain
|
||||
else
|
||||
positions[vertX*numVerts*3 + vertY*3 + 2] = -2048;
|
||||
|
||||
if (land)
|
||||
if (land && land->mDataTypes&ESM::Land::DATA_VNML)
|
||||
{
|
||||
normal.x = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3];
|
||||
normal.y = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1];
|
||||
@ -207,7 +206,7 @@ namespace ESMTerrain
|
||||
normals[vertX*numVerts*3 + vertY*3 + 1] = normal.y;
|
||||
normals[vertX*numVerts*3 + vertY*3 + 2] = normal.z;
|
||||
|
||||
if (hasColors)
|
||||
if (land && land->mDataTypes&ESM::Land::DATA_VCLR)
|
||||
{
|
||||
color.r = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f;
|
||||
color.g = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f;
|
||||
@ -263,7 +262,7 @@ namespace ESMTerrain
|
||||
assert(y<ESM::Land::LAND_TEXTURE_SIZE);
|
||||
|
||||
ESM::Land* land = getLand(cellX, cellY);
|
||||
if (land)
|
||||
if (land && (land->mDataTypes&ESM::Land::DATA_VTEX))
|
||||
{
|
||||
int tex = land->mLandData->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||
if (tex == 0)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "box.hpp"
|
||||
#include "imagebutton.hpp"
|
||||
#include "sharedstatebutton.hpp"
|
||||
#include "windowcaption.hpp"
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
@ -22,6 +23,7 @@ namespace Gui
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<Gui::ImageButton>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<Gui::NumericEditBox>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<Gui::SharedStateButton>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<Gui::WindowCaption>("Widget");
|
||||
}
|
||||
|
||||
}
|
||||
|
58
components/widgets/windowcaption.cpp
Normal file
58
components/widgets/windowcaption.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "windowcaption.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
WindowCaption::WindowCaption()
|
||||
: mLeft(NULL)
|
||||
, mRight(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void WindowCaption::initialiseOverride()
|
||||
{
|
||||
Base::initialiseOverride();
|
||||
|
||||
assignWidget(mLeft, "Left");
|
||||
assignWidget(mRight, "Right");
|
||||
|
||||
assignWidget(mClient, "Client");
|
||||
if (!mClient)
|
||||
throw std::runtime_error("WindowCaption needs an EditBox Client widget in its skin");
|
||||
}
|
||||
|
||||
void WindowCaption::setCaption(const MyGUI::UString &_value)
|
||||
{
|
||||
EditBox::setCaption(_value);
|
||||
align();
|
||||
}
|
||||
|
||||
void WindowCaption::setSize(const MyGUI::IntSize& _value)
|
||||
{
|
||||
Base::setSize(_value);
|
||||
align();
|
||||
}
|
||||
|
||||
void WindowCaption::setCoord(const MyGUI::IntCoord& _value)
|
||||
{
|
||||
Base::setCoord(_value);
|
||||
align();
|
||||
}
|
||||
|
||||
void WindowCaption::align()
|
||||
{
|
||||
MyGUI::IntSize textSize = getTextSize();
|
||||
MyGUI::Widget* caption = mClient;
|
||||
caption->setSize(textSize.width + 24, caption->getHeight());
|
||||
|
||||
int barwidth = (getWidth()-caption->getWidth())/2;
|
||||
caption->setPosition(barwidth, caption->getTop());
|
||||
if (mLeft)
|
||||
mLeft->setCoord(0, mLeft->getTop(), barwidth, mLeft->getHeight());
|
||||
if (mRight)
|
||||
mRight->setCoord(barwidth + caption->getWidth(), mRight->getTop(), barwidth, mRight->getHeight());
|
||||
}
|
||||
|
||||
}
|
32
components/widgets/windowcaption.hpp
Normal file
32
components/widgets/windowcaption.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef OPENMW_WIDGETS_WINDOWCAPTION_H
|
||||
#define OPENMW_WIDGETS_WINDOWCAPTION_H
|
||||
|
||||
#include <MyGUI_EditBox.h>
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
/// Window caption that automatically adjusts "Left" and "Right" widgets in its skin
|
||||
/// based on the text size of the caption in the middle
|
||||
class WindowCaption : public MyGUI::EditBox
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(WindowCaption)
|
||||
public:
|
||||
WindowCaption();
|
||||
|
||||
virtual void setCaption(const MyGUI::UString &_value);
|
||||
virtual void initialiseOverride();
|
||||
|
||||
virtual void setSize(const MyGUI::IntSize& _value);
|
||||
virtual void setCoord(const MyGUI::IntCoord& _value);
|
||||
|
||||
private:
|
||||
MyGUI::Widget* mLeft;
|
||||
MyGUI::Widget* mRight;
|
||||
|
||||
void align();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
10
extern/ogre-ffmpeg-videoplayer/videostate.cpp
vendored
10
extern/ogre-ffmpeg-videoplayer/videostate.cpp
vendored
@ -346,11 +346,11 @@ double VideoState::synchronize_video(AVFrame *src_frame, double pts)
|
||||
* buffer. We use this to store the global_pts in
|
||||
* a frame at the time it is allocated.
|
||||
*/
|
||||
static uint64_t global_video_pkt_pts = static_cast<uint64_t>(AV_NOPTS_VALUE);
|
||||
static int64_t global_video_pkt_pts = AV_NOPTS_VALUE;
|
||||
static int our_get_buffer(struct AVCodecContext *c, AVFrame *pic)
|
||||
{
|
||||
int ret = avcodec_default_get_buffer(c, pic);
|
||||
uint64_t *pts = (uint64_t*)av_malloc(sizeof(uint64_t));
|
||||
int64_t *pts = (int64_t*)av_malloc(sizeof(int64_t));
|
||||
*pts = global_video_pkt_pts;
|
||||
pic->opaque = pts;
|
||||
return ret;
|
||||
@ -397,10 +397,10 @@ void VideoState::video_thread_loop(VideoState *self)
|
||||
throw std::runtime_error("Error decoding video frame");
|
||||
|
||||
double pts = 0;
|
||||
if((uint64_t)packet->dts != AV_NOPTS_VALUE)
|
||||
if(packet->dts != AV_NOPTS_VALUE)
|
||||
pts = packet->dts;
|
||||
else if(pFrame->opaque && *(uint64_t*)pFrame->opaque != AV_NOPTS_VALUE)
|
||||
pts = *(uint64_t*)pFrame->opaque;
|
||||
else if(pFrame->opaque && *(int64_t*)pFrame->opaque != AV_NOPTS_VALUE)
|
||||
pts = *(int64_t*)pFrame->opaque;
|
||||
pts *= av_q2d((*self->video_st)->time_base);
|
||||
|
||||
av_free_packet(packet);
|
||||
|
10
extern/sdl4ogre/sdlinputwrapper.cpp
vendored
10
extern/sdl4ogre/sdlinputwrapper.cpp
vendored
@ -30,7 +30,8 @@ namespace SFO
|
||||
mWantMouseVisible(false),
|
||||
mAllowGrab(grab),
|
||||
mWarpX(0),
|
||||
mWarpY(0)
|
||||
mWarpY(0),
|
||||
mFirstMouseMove(true)
|
||||
{
|
||||
_setupOISKeys();
|
||||
}
|
||||
@ -316,6 +317,13 @@ namespace SFO
|
||||
pack_evt.y = mMouseY = evt.motion.y;
|
||||
pack_evt.xrel = evt.motion.xrel;
|
||||
pack_evt.yrel = evt.motion.yrel;
|
||||
if (mFirstMouseMove)
|
||||
{
|
||||
// first event should be treated as non-relative, since there's no point of reference
|
||||
// SDL then (incorrectly) uses (0,0) as point of reference, on Linux at least...
|
||||
pack_evt.xrel = pack_evt.yrel = 0;
|
||||
mFirstMouseMove = false;
|
||||
}
|
||||
}
|
||||
else if(evt.type == SDL_MOUSEWHEEL)
|
||||
{
|
||||
|
2
extern/sdl4ogre/sdlinputwrapper.hpp
vendored
2
extern/sdl4ogre/sdlinputwrapper.hpp
vendored
@ -71,6 +71,8 @@ namespace SFO
|
||||
bool mGrabPointer;
|
||||
bool mMouseRelative;
|
||||
|
||||
bool mFirstMouseMove;
|
||||
|
||||
Sint32 mMouseZ;
|
||||
Sint32 mMouseX;
|
||||
Sint32 mMouseY;
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
<Widget type="Widget" skin="MW_Box" position="8 8 381 381" align="Stretch" name="Client"/>
|
||||
|
||||
<Widget type="Widget" position="13 13 357 371" align="Left Top Stretch">
|
||||
<Widget type="BookPage" skin="MW_BookPage" position="0 0 357 371" name="History" align="Left Top Stretch">
|
||||
<Widget type="Widget" position="15 15 364 370" align="Left Top Stretch">
|
||||
<Widget type="BookPage" skin="MW_BookPage" position="0 0 364 370" name="History" align="Left Top Stretch">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -6,14 +6,14 @@
|
||||
|
||||
<Resource type="ResourceSkin" name="HUD_Box" size="40 40">
|
||||
|
||||
<!-- The interior of the box -->
|
||||
|
||||
<Child type="Widget" skin="BlackBG" offset="0 0 40 40" align="Stretch" name="Client"/>
|
||||
|
||||
<!-- Borders -->
|
||||
|
||||
<Child type="Widget" skin="MW_Box" offset="0 0 40 40" align="Left Stretch" name="Client"/>
|
||||
|
||||
<!-- The interior of the box -->
|
||||
|
||||
<Child type="Widget" skin="BlackBG" offset="2 2 36 36" align="Stretch" name="Client"/>
|
||||
|
||||
</Resource>
|
||||
|
||||
<Resource type="ResourceSkin" name="HUD_Box_Transparent" size="40 40">
|
||||
@ -22,14 +22,14 @@
|
||||
|
||||
<Resource type="ResourceSkin" name="HUD_Box_NoTransp" size="40 40">
|
||||
|
||||
<!-- The interior of the box -->
|
||||
|
||||
<Child type="Widget" skin="DialogBG" offset="0 0 40 40" align="Stretch" name="Client"/>
|
||||
|
||||
<!-- Borders -->
|
||||
|
||||
<Child type="Widget" skin="MW_Box" offset="0 0 40 40" align="Left Stretch" name="Client"/>
|
||||
|
||||
<!-- The interior of the box -->
|
||||
|
||||
<Child type="Widget" skin="DialogBG" offset="2 2 36 36" align="Stretch" name="Client"/>
|
||||
|
||||
</Resource>
|
||||
|
||||
</MyGUI>
|
||||
|
@ -395,17 +395,9 @@
|
||||
<Property key="FontName" value="Default"/>
|
||||
<Property key="TextAlign" value="Center"/>
|
||||
|
||||
<Child type="Widget" skin="DialogBG" offset="0 0 88 20" align="Stretch"/>
|
||||
|
||||
<Child type="TextBox" skin="SandText" offset="2 0 84 20" align="Stretch" name="Client"/>
|
||||
|
||||
<!-- Add the borders of the surrounding blocks -->
|
||||
<Child type="Widget" skin="HB_LEFT" offset="86 2 2 16" align="Top Right"/>
|
||||
<Child type="Widget" skin="HB_RIGHT" offset="0 2 2 16" align="Top Left"/>
|
||||
<Child type="Widget" skin="HB_TR" offset="0 0 2 2" align="Top Left"/>
|
||||
<Child type="Widget" skin="HB_TL" offset="86 0 2 2" align="Top Right"/>
|
||||
<Child type="Widget" skin="HB_BR" offset="0 18 2 2" align="Bottom Left"/>
|
||||
<Child type="Widget" skin="HB_BL" offset="86 18 2 2" align="Bottom Right"/>
|
||||
<Child type="Widget" skin="HB_ALL" offset="0 0 30 20" align="Default" name="Left"/>
|
||||
<Child type="TextBox" skin="SandText" offset="30 0 28 20" align="Left VStretch" name="Client"/>
|
||||
<Child type="Widget" skin="HB_ALL" offset="0 0 30 20" align="Right" name="Right"/>
|
||||
</Resource>
|
||||
|
||||
<!-- ----------------------------------------------------
|
||||
@ -420,7 +412,8 @@
|
||||
<Property key="Snap" value="true"/>
|
||||
<Property key="MinSize" value="64 64"/>
|
||||
|
||||
<Child type="Widget" skin="BlackBG" offset="8 28 240 220" align="Stretch" name="Client"/>
|
||||
<Child type="Widget" skin="BlackBG" offset="0 0 256 256" align="Stretch"/>
|
||||
<Child type="Widget" skin="" offset="8 28 240 220" align="Stretch" name="Client"/>
|
||||
|
||||
<!-- Outer Borders -->
|
||||
<Child type="Widget" skin="TB_T" offset="14 0 228 4" align="Top HStretch" name="Action">
|
||||
@ -538,12 +531,7 @@
|
||||
<Property key="Scale" value="0 0 1 1"/>
|
||||
</Child>
|
||||
|
||||
<!-- Caption -->
|
||||
<Child type="Widget" skin="HB_ALL" offset="4 4 248 20" align="Top HStretch">
|
||||
<Property key="Scale" value="1 1 0 0"/>
|
||||
</Child>
|
||||
|
||||
<Child type="EditBox" skin="MW_Caption" offset="80 4 88 20" align="HCenter Top" name="Caption">
|
||||
<Child type="WindowCaption" skin="MW_Caption" offset="4 4 248 20" align="HStretch Top" name="Caption">
|
||||
</Child>
|
||||
|
||||
<!-- This invisible button makes it possible to move the
|
||||
@ -559,7 +547,8 @@
|
||||
<Property key="Snap" value="true"/>
|
||||
<Property key="MinSize" value="64 64"/>
|
||||
|
||||
<Child type="Widget" skin="BlackBG" offset="8 28 240 220" align="Stretch" name="Client"/>
|
||||
<Child type="Widget" skin="BlackBG" offset=" 0 0 256 256" align="Stretch"/>
|
||||
<Child type="Widget" skin="" offset="8 28 240 220" align="Stretch" name="Client"/>
|
||||
|
||||
<!-- Outer Borders -->
|
||||
<Child type="Widget" skin="TB_T" offset="14 0 228 4" align="Top HStretch" name="Action">
|
||||
@ -695,7 +684,8 @@
|
||||
<Property key="Snap" value="true"/>
|
||||
<Property key="MinSize" value="64 64"/>
|
||||
|
||||
<Child type="Widget" skin="BlackBG" offset="8 28 240 220" align="Stretch" name="Client"/>
|
||||
<Child type="Widget" skin="BlackBG" offset=" 0 0 256 256" align="Stretch"/>
|
||||
<Child type="Widget" skin="" offset="8 28 240 220" align="Stretch" name="Client"/>
|
||||
|
||||
<!-- Outer Borders -->
|
||||
<Child type="Widget" skin="TB_T" offset="14 0 228 4" align="Top HStretch" name="Action">
|
||||
@ -814,12 +804,7 @@
|
||||
</Child>
|
||||
|
||||
<!-- Caption -->
|
||||
|
||||
<Child type="Widget" skin="HB_ALL" offset="4 4 248 20" align="Top HStretch">
|
||||
<Property key="Scale" value="1 1 0 0"/>
|
||||
</Child>
|
||||
|
||||
<Child type="EditBox" skin="MW_Caption" offset="80 4 88 20" align="HCenter Top" name="Caption">
|
||||
<Child type="WindowCaption" skin="MW_Caption" offset="4 4 228 20" align="HStretch Top" name="Caption">
|
||||
</Child>
|
||||
|
||||
<!-- This invisible button makes it possible to move the
|
||||
|
@ -45,6 +45,8 @@ subtitles = false
|
||||
hit fader = true
|
||||
werewolf overlay = true
|
||||
|
||||
stretch menu background = false
|
||||
|
||||
[General]
|
||||
# Camera field of view
|
||||
field of view = 55
|
||||
|
@ -46,27 +46,6 @@ namespace GUI
|
||||
mMainWidget->setCoord(x,y,w,h);
|
||||
}
|
||||
|
||||
void Layout::adjustWindowCaption()
|
||||
{
|
||||
MyGUI::TextBox* box = mMainWidget->castType<MyGUI::Window>(mMainWidget)->getCaptionWidget();
|
||||
box->setSize(box->getTextSize().width + 24, box->getSize().height);
|
||||
|
||||
// in order to trigger alignment updates, we need to update the parent
|
||||
// mygui doesn't provide a proper way of doing this, so we are just changing size
|
||||
box->getParent()->setCoord(MyGUI::IntCoord(
|
||||
box->getParent()->getCoord().left,
|
||||
box->getParent()->getCoord().top,
|
||||
box->getParent()->getCoord().width,
|
||||
box->getParent()->getCoord().height+1
|
||||
));
|
||||
box->getParent()->setCoord(MyGUI::IntCoord(
|
||||
box->getParent()->getCoord().left,
|
||||
box->getParent()->getCoord().top,
|
||||
box->getParent()->getCoord().width,
|
||||
box->getParent()->getCoord().height-1
|
||||
));
|
||||
}
|
||||
|
||||
void Layout::setVisible(bool b)
|
||||
{
|
||||
mMainWidget->setVisible(b);
|
||||
@ -82,7 +61,6 @@ namespace GUI
|
||||
void Layout::setTitle(const std::string& title)
|
||||
{
|
||||
static_cast<MyGUI::Window*>(mMainWidget)->setCaptionWithReplacing(title);
|
||||
adjustWindowCaption();
|
||||
}
|
||||
|
||||
MyGUI::Widget* Layout::getWidget(const std::string &_name)
|
||||
|
@ -45,10 +45,6 @@ namespace GUI
|
||||
public:
|
||||
void setCoord(int x, int y, int w, int h);
|
||||
|
||||
// adjust the size of the window caption so that all text is visible
|
||||
// NOTE: this assumes that mMainWidget is of type Window.
|
||||
void adjustWindowCaption();
|
||||
|
||||
virtual void setVisible(bool b);
|
||||
|
||||
void setText(const std::string& name, const std::string& caption);
|
||||
|
Loading…
x
Reference in New Issue
Block a user