Merge branch 'master' of https://github.com/zinnschlag/openmw into videoplayback

Conflicts:
	apps/openmw/mwrender/renderingmanager.cpp
	apps/openmw/mwscript/miscextensions.cpp
actorid
scrawl 12 years ago
commit 5f676f9c6b

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version
set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 19)
set (OPENMW_VERSION_MINOR 20)
set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -26,6 +26,7 @@ configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
# Apps and tools
option(BUILD_ESMTOOL "build ESM inspector" ON)
@ -197,6 +198,10 @@ if (Boost_VERSION LESS 104900)
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} wave)
endif()
IF(BOOST_STATIC)
set(Boost_USE_STATIC_LIBS ON)
endif()
find_package(OGRE REQUIRED)
find_package(MyGUI REQUIRED)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})

@ -131,9 +131,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
->default_value(false), "enable console-only script functionality")
("script-run", bpo::value<std::string>()->default_value(""),
"select a file that is executed in the console on startup\n\n"
"Note: The file contains a list of script lines, but not a complete scripts. "
"That means no begin/end and no variable declarations.")
"select a file containing a list of console commands that is executed on startup")
("new-game", bpo::value<bool>()->implicit_value(true)
->default_value(false), "activate char gen/new game mechanics")

@ -109,17 +109,10 @@ namespace MWDialogue
{
size_t pos = find_str_ci(text,*it,0);
if(pos !=std::string::npos)
{
if(pos==0)
{
mKnownTopics[*it] = true;
}
else if(text.substr(pos -1,1) == " ")
{
mKnownTopics[*it] = true;
}
}
}
updateTopics();
}
@ -245,6 +238,44 @@ namespace MWDialogue
}
}
void DialogueManager::executeTopic (const std::string& topic)
{
Filter filter (mActor, mChoice, mTalkedTo);
const MWWorld::Store<ESM::Dialogue> &dialogues =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
const ESM::Dialogue& dialogue = *dialogues.find (topic);
if (const ESM::DialInfo *info = filter.search (dialogue))
{
parseText (info->mResponse);
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
if (dialogue.mType==ESM::Dialogue::Persuasion)
{
std::string modifiedTopic = "s" + topic;
modifiedTopic.erase (std::remove (modifiedTopic.begin(), modifiedTopic.end(), ' '), modifiedTopic.end());
const MWWorld::Store<ESM::GameSetting>& gmsts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
win->addTitle (gmsts.find (modifiedTopic)->getString());
}
else
win->addTitle (topic);
win->addText (info->mResponse);
executeScript (info->mResultScript);
mLastTopic = topic;
mLastDialogue = *info;
}
}
void DialogueManager::updateTopics()
{
std::list<std::string> keywordList;
@ -339,24 +370,7 @@ namespace MWDialogue
ESM::Dialogue ndialogue = mDialogueMap[keyword];
if (mDialogueMap[keyword].mType == ESM::Dialogue::Topic)
{
Filter filter (mActor, mChoice, mTalkedTo);
if (const ESM::DialInfo *info = filter.search (mDialogueMap[keyword]))
{
std::string text = info->mResponse;
std::string script = info->mResultScript;
parseText (text);
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
win->addTitle (keyword);
win->addText (info->mResponse);
executeScript (script);
mLastTopic = keyword;
mLastDialogue = *info;
}
executeTopic (keyword);
}
}
}
@ -452,30 +466,22 @@ namespace MWDialogue
else if (curDisp + mTemporaryDispositionChange > 100)
mTemporaryDispositionChange = 100 - curDisp;
// practice skill
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Speechcraft, success ? 0 : 1);
if (success)
MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Speechcraft, 0);
// add status message to dialogue window
std::string text;
if (type == MWBase::MechanicsManager::PT_Admire)
text = "sAdmire";
text = "Admire";
else if (type == MWBase::MechanicsManager::PT_Taunt)
text = "sTaunt";
text = "Taunt";
else if (type == MWBase::MechanicsManager::PT_Intimidate)
text = "sIntimidate";
else
text = "sBribe";
text += (success ? "Success" : "Fail");
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
win->addTitle(MyGUI::LanguageManager::getInstance().replaceTags("#{"+text+"}"));
text = "Intimidate";
else{
text = "Bribe";
}
/// \todo text from INFO record, how to get the ID?
executeTopic (text + (success ? " Success" : " Fail"));
}
int DialogueManager::getTemporaryDispositionChange() const

@ -46,6 +46,8 @@ namespace MWDialogue
void printError (const std::string& error);
void executeTopic (const std::string& topic);
public:
DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose);

@ -119,7 +119,6 @@ namespace MWGui
if (mIngredients[i]->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredients[i]->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredients[i]);
}

@ -48,6 +48,11 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su
return lower_string(str).find(lower_string(substr),pos);
}
bool sortByLength (const std::string& left, const std::string& right)
{
return left.size() > right.size();
}
}
@ -287,7 +292,7 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (mServices & Service_Training)
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
if (anyService)
if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name())
mTopicsList->addSeparator();
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); ++it)
@ -311,43 +316,52 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c
size_t pos = 0;
while((pos = find_str_ci(str,keyword, pos)) != std::string::npos)
{
if(pos==0)
// do not add color if this portion of text is already colored.
{
str.insert(pos,color1);
pos += color1.length();
pos += keyword.length();
str.insert(pos,color2);
pos+= color2.length();
}
else
{
if(str.substr(pos -1,1) == " ")
MyGUI::TextIterator iterator (str);
MyGUI::UString colour;
while(iterator.moveNext())
{
size_t iteratorPos = iterator.getPosition();
iterator.getTagColour(colour);
if (iteratorPos == pos)
break;
}
if (colour == color1)
return;
}
str.insert(pos,color1);
pos += color1.length();
pos += keyword.length();
str.insert(pos,color2);
pos+= color2.length();
}
else
{
pos += keyword.length();
}
}
}
}
std::string DialogueWindow::parseText(std::string text)
{
bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored)
std::vector<std::string> topics;
for(unsigned int i = 0;i<mTopicsList->getItemCount();i++)
{
std::string keyWord = mTopicsList->getItemNameAt(i);
if (separatorReached && keyWord != "")
addColorInString(text,keyWord,"#686EBA","#B29154");
else
if (separatorReached)
topics.push_back(keyWord);
else if (keyWord == "")
separatorReached = true;
}
// sort by length to make sure longer topics are replaced first
std::sort(topics.begin(), topics.end(), sortByLength);
for(std::vector<std::string>::const_iterator it = topics.begin(); it != topics.end(); ++it)
{
addColorInString(text,*it,"#686EBA","#B29154");
}
return text;
}

@ -226,9 +226,14 @@ namespace MWGui
if (start == "splash")
splash.push_back (*it);
}
if (splash.size())
{
std::string randomSplash = splash[rand() % splash.size()];
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General");
mBackgroundImage->setImageTexture (randomSplash);
}
else
std::cerr << "No loading screens found!" << std::endl;
}
}

@ -252,11 +252,14 @@ void StatsWindow::onFrame ()
}
setFactions(PCstats.getFactionRanks());
setExpelled(PCstats.getExpelled ());
const std::string &signId =
MWBase::Environment::get().getWorld()->getPlayer().getBirthSign();
setBirthSign(signId);
setReputation (PCstats.getReputation ());
setBounty (PCstats.getBounty ());
if (mChanged)
updateSkillArea();
@ -271,6 +274,15 @@ void StatsWindow::setFactions (const FactionList& factions)
}
}
void StatsWindow::setExpelled (const std::set<std::string>& expelled)
{
if (mExpelled != expelled)
{
mExpelled = expelled;
mChanged = true;
}
}
void StatsWindow::setBirthSign (const std::string& signId)
{
if (signId != mBirthSignId)
@ -460,6 +472,10 @@ void StatsWindow::updateSkillArea()
if (!mSkillWidgets.empty())
addSeparator(coord1, coord2);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player);
std::set<std::string>& expelled = PCstats.getExpelled ();
addGroup(mWindowManager.getGameSettingString("sFaction", "Faction"), coord1, coord2);
FactionList::const_iterator end = mFactions.end();
for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it)
@ -471,6 +487,11 @@ void StatsWindow::updateSkillArea()
std::string text;
text += std::string("#DDC79E") + faction->mName;
if (expelled.find(it->first) != expelled.end())
text += "\n#{sExpelled}";
else
{
text += std::string("\n#BF9959") + faction->mRanks[it->second];
if (it->second < 9)
@ -502,6 +523,7 @@ void StatsWindow::updateSkillArea()
if (rankData.mSkill2 > 0)
text += "\n#{sNeedTwoSkills} " + boost::lexical_cast<std::string>(rankData.mSkill2);
}
}
w->setUserString("ToolTipType", "Layout");
w->setUserString("ToolTipLayout", "TextToolTip");

@ -38,8 +38,8 @@ namespace MWGui
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void configureSkills (const SkillList& major, const SkillList& minor);
void setReputation (int reputation) { this->mReputation = reputation; }
void setBounty (int bounty) { this->mBounty = bounty; }
void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; }
void updateSkillArea();
private:
@ -50,6 +50,7 @@ namespace MWGui
MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void setFactions (const FactionList& factions);
void setExpelled (const std::set<std::string>& expelled);
void setBirthSign (const std::string &signId);
void onWindowResize(MyGUI::Window* window);
@ -71,6 +72,7 @@ namespace MWGui
std::string mBirthSignId;
int mReputation, mBounty;
std::vector<MyGUI::WidgetPtr> mSkillWidgets; //< Skills and other information
std::set<std::string> mExpelled;
bool mChanged;

@ -31,6 +31,7 @@ ToolTips::ToolTips(MWBase::WindowManager* windowManager) :
, mRemainingDelay(0.0)
, mLastMouseX(0)
, mLastMouseY(0)
, mHorizontalScrollIndex(0)
{
getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
@ -52,6 +53,7 @@ void ToolTips::setEnabled(bool enabled)
void ToolTips::onFrame(float frameDuration)
{
while (mDynamicToolTipBox->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0));
@ -114,11 +116,13 @@ void ToolTips::onFrame(float frameDuration)
}
else
{
mHorizontalScrollIndex = 0;
mRemainingDelay = mDelay;
}
mLastMouseX = mousePos.left;
mLastMouseY = mousePos.top;
if (mRemainingDelay > 0)
return;
@ -149,6 +153,7 @@ void ToolTips::onFrame(float frameDuration)
return;
}
// special handling for markers on the local map: the tooltip should only be visible
// if the marker is not hidden due to the fog of war.
if (focus->getUserString ("IsMarker") == "true")
@ -389,6 +394,8 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
const IntPoint padding(8, 8);
const int maximumWidth = 500;
const int imageCaptionHPadding = (caption != "" ? 8 : 0);
const int imageCaptionVPadding = (caption != "" ? 4 : 0);
@ -411,7 +418,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
IntSize textSize = textWidget->getTextSize();
captionSize += IntSize(imageSize, 0); // adjust for image
IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
IntSize totalSize = IntSize( std::min(std::max(textSize.width,captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),maximumWidth),
((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
if (!info.effects.empty())
@ -500,7 +507,23 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
captionSize.width-imageSize,
captionSize.height);
//if its too long we do hscroll with the caption
if (captionSize.width > maximumWidth){
mHorizontalScrollIndex = mHorizontalScrollIndex + 2;
if (mHorizontalScrollIndex > captionSize.width){
mHorizontalScrollIndex = -totalSize.width;
}
int horizontal_scroll = mHorizontalScrollIndex;
if (horizontal_scroll < 40){
horizontal_scroll = 40;
}else{
horizontal_scroll = 80 - mHorizontalScrollIndex;
}
captionWidget->setPosition (IntPoint(horizontal_scroll, captionWidget->getPosition().top + padding.top));
} else {
captionWidget->setPosition (captionWidget->getPosition() + padding);
}
textWidget->setPosition (textWidget->getPosition() + IntPoint(0, padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter
if (image != "")

@ -91,6 +91,9 @@ namespace MWGui
float mFocusToolTipX;
float mFocusToolTipY;
int mHorizontalScrollIndex;
float mDelay;
float mRemainingDelay; // remaining time until tooltip will show

@ -239,6 +239,9 @@ namespace MWGui
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterFailDisposition);
return;
}
//skill use!
MWWorld::Class::get(playerPtr).skillUsageSucceeded(playerPtr, ESM::Skill::Mercantile, 0);
}
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();

@ -204,6 +204,7 @@ namespace MWGui
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.2);
mProgressBar.setVisible (false);
mWindowManager.removeGuiMode (GM_Rest);
mWindowManager.removeGuiMode (GM_RestBed);
mWaiting = false;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();

@ -624,6 +624,8 @@ namespace MWInput
void InputManager::toggleAutoMove()
{
if (mWindows.isGuiMode()) return;
if (mControlSwitch["playercontrols"])
mPlayer.setAutoMove (!mPlayer.getAutoMove());
}

@ -3,6 +3,8 @@
#include <cstdlib>
#include <boost/algorithm/string.hpp>
#include <components/esm/loadalch.hpp>
#include <components/esm/loadspel.hpp>
#include <components/esm/loadingr.hpp>
@ -258,4 +260,18 @@ namespace MWMechanics
return scaledDuration-usedUp;
}
bool ActiveSpells::isSpellActive(std::string id) const
{
boost::algorithm::to_lower(id);
for (TContainer::iterator iter = mSpells.begin(); iter != mSpells.end(); ++iter)
{
std::string left = iter->first;
boost::algorithm::to_lower(left);
if (iter->first == id)
return true;
}
return false;
}
}

@ -58,6 +58,9 @@ namespace MWMechanics
void removeSpell (const std::string& id);
bool isSpellActive (std::string id) const;
///< case insensitive
const MagicEffects& getMagicEffects() const;
TIterator begin() const;

@ -203,7 +203,7 @@ const ESM::Potion *MWMechanics::Alchemy::getRecord() const
bool mismatch = false;
for (int i=0; i<static_cast<int> (iter->mEffects.mList.size()); ++iter)
for (int i=0; i<static_cast<int> (iter->mEffects.mList.size()); ++i)
{
const ESM::ENAMstruct& first = iter->mEffects.mList[i];
const ESM::ENAMstruct& second = mEffects[i];

@ -442,7 +442,7 @@ namespace MWMechanics
if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease())
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispDiseaseMod")->getFloat();
if (playerNpcStats.getDrawState() == MWMechanics::DrawState_::DrawState_Weapon)
if (playerNpcStats.getDrawState() == MWMechanics::DrawState_Weapon)
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat();
int effective_disposition = std::max(0,std::min(int(x),100));//, normally clamped to [0..100] when used

@ -117,12 +117,15 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
if (usageType>=4)
throw std::runtime_error ("skill usage type out of range");
if (usageType>0)
if (usageType>=0)
{
skillFactor = skill->mData.mUseValue[usageType];
if (skillFactor<=0)
if (skillFactor<0)
throw std::runtime_error ("invalid skill gain factor");
if (skillFactor==0)
return 0;
}
const MWWorld::Store<ESM::GameSetting> &gmst =
@ -217,7 +220,7 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
std::stringstream message;
message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
% std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
% base;
% static_cast<int> (base);
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), std::vector<std::string>());
if (mLevelProgress >= 10)

@ -337,6 +337,8 @@ void RenderingManager::update (float duration, bool paused)
mVideoPlayer->update ();
mRendering.update(duration);
if(paused)
{
Ogre::ControllerManager::getSingleton().setTimeFactor(0.f);
@ -355,8 +357,6 @@ void RenderingManager::update (float duration, bool paused)
mSkyManager->setGlare(mOcclusionQuery->getSunVisibility());
mRendering.update(duration);
MWWorld::RefData &data =
MWBase::Environment::get()
.getWorld()

@ -114,71 +114,56 @@ namespace MWScript
// discard additional arguments (reset), because we have no idea what they mean.
for (unsigned int i=0; i<arg0; ++i) runtime.pop();
std::cout << "AiWanter" << std::endl;
std::cout << "AiWander" << std::endl;
}
};
template<class R>
class OpSetHello : public Interpreter::Opcode0
class OpGetAiSetting : public Interpreter::Opcode0
{
int mIndex;
public:
OpGetAiSetting(int index) : mIndex(index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (0, value);
runtime.push(MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSetting (mIndex));
}
};
template<class R>
class OpSetFight : public Interpreter::Opcode0
class OpModAiSetting : public Interpreter::Opcode0
{
int mIndex;
public:
OpModAiSetting(int index) : mIndex(index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (1, value);
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (mIndex,
MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSetting (mIndex) + value);
}
};
template<class R>
class OpSetFlee : public Interpreter::Opcode0
class OpSetAiSetting : public Interpreter::Opcode0
{
int mIndex;
public:
OpSetAiSetting(int index) : mIndex(index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (2, value);
}
};
template<class R>
class OpSetAlarm : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (3, value);
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (mIndex,
value);
}
};
@ -199,6 +184,22 @@ namespace MWScript
const int opcodeSetFleeExplicit = 0x2000161;
const int opcodeSetAlarm = 0x2000162;
const int opcodeSetAlarmExplicit = 0x2000163;
const int opcodeModHello = 0x20001b7;
const int opcodeModHelloExplicit = 0x20001b8;
const int opcodeModFight = 0x20001b9;
const int opcodeModFightExplicit = 0x20001ba;
const int opcodeModFlee = 0x20001bb;
const int opcodeModFleeExplicit = 0x20001bc;
const int opcodeModAlarm = 0x20001bd;
const int opcodeModAlarmExplicit = 0x20001be;
const int opcodeGetHello = 0x20001bf;
const int opcodeGetHelloExplicit = 0x20001c0;
const int opcodeGetFight = 0x20001c1;
const int opcodeGetFightExplicit = 0x20001c2;
const int opcodeGetFlee = 0x20001c3;
const int opcodeGetFleeExplicit = 0x20001c4;
const int opcodeGetAlarm = 0x20001c5;
const int opcodeGetAlarmExplicit = 0x20001c6;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -216,6 +217,14 @@ namespace MWScript
extensions.registerInstruction ("setfight", "l", opcodeSetFight, opcodeSetFightExplicit);
extensions.registerInstruction ("setflee", "l", opcodeSetFlee, opcodeSetFleeExplicit);
extensions.registerInstruction ("setalarm", "l", opcodeSetAlarm, opcodeSetAlarmExplicit);
extensions.registerInstruction ("modhello", "l", opcodeModHello, opcodeModHelloExplicit);
extensions.registerInstruction ("modfight", "l", opcodeModFight, opcodeModFightExplicit);
extensions.registerInstruction ("modflee", "l", opcodeModFlee, opcodeModFleeExplicit);
extensions.registerInstruction ("modalarm", "l", opcodeModAlarm, opcodeModAlarmExplicit);
extensions.registerFunction ("gethello", 'l', "", opcodeGetHello, opcodeGetHelloExplicit);
extensions.registerFunction ("getfight", 'l', "", opcodeGetFight, opcodeGetFightExplicit);
extensions.registerFunction ("getflee", 'l', "", opcodeGetFlee, opcodeGetFleeExplicit);
extensions.registerFunction ("getalarm", 'l', "", opcodeGetAlarm, opcodeGetAlarmExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -229,14 +238,32 @@ namespace MWScript
interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone<ImplicitRef>);
interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit,
new OpGetAiPackageDone<ExplicitRef>);
interpreter.installSegment5 (opcodeSetHello, new OpSetHello<ImplicitRef>);
interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetHello<ExplicitRef>);
interpreter.installSegment5 (opcodeSetFight, new OpSetFight<ImplicitRef>);
interpreter.installSegment5 (opcodeSetFightExplicit, new OpSetFight<ExplicitRef>);
interpreter.installSegment5 (opcodeSetFlee, new OpSetFlee<ImplicitRef>);
interpreter.installSegment5 (opcodeSetFleeExplicit, new OpSetFlee<ExplicitRef>);
interpreter.installSegment5 (opcodeSetAlarm, new OpSetAlarm<ImplicitRef>);
interpreter.installSegment5 (opcodeSetAlarmExplicit, new OpSetAlarm<ExplicitRef>);
interpreter.installSegment5 (opcodeSetHello, new OpSetAiSetting<ImplicitRef>(0));
interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetAiSetting<ExplicitRef>(0));
interpreter.installSegment5 (opcodeSetFight, new OpSetAiSetting<ImplicitRef>(1));
interpreter.installSegment5 (opcodeSetFightExplicit, new OpSetAiSetting<ExplicitRef>(1));
interpreter.installSegment5 (opcodeSetFlee, new OpSetAiSetting<ImplicitRef>(2));
interpreter.installSegment5 (opcodeSetFleeExplicit, new OpSetAiSetting<ExplicitRef>(2));
interpreter.installSegment5 (opcodeSetAlarm, new OpSetAiSetting<ImplicitRef>(3));
interpreter.installSegment5 (opcodeSetAlarmExplicit, new OpSetAiSetting<ExplicitRef>(3));
interpreter.installSegment5 (opcodeModHello, new OpModAiSetting<ImplicitRef>(0));
interpreter.installSegment5 (opcodeModHelloExplicit, new OpModAiSetting<ExplicitRef>(0));
interpreter.installSegment5 (opcodeModFight, new OpModAiSetting<ImplicitRef>(1));
interpreter.installSegment5 (opcodeModFightExplicit, new OpModAiSetting<ExplicitRef>(1));
interpreter.installSegment5 (opcodeModFlee, new OpModAiSetting<ImplicitRef>(2));
interpreter.installSegment5 (opcodeModFleeExplicit, new OpModAiSetting<ExplicitRef>(2));
interpreter.installSegment5 (opcodeModAlarm, new OpModAiSetting<ImplicitRef>(3));
interpreter.installSegment5 (opcodeModAlarmExplicit, new OpModAiSetting<ExplicitRef>(3));
interpreter.installSegment5 (opcodeGetHello, new OpGetAiSetting<ImplicitRef>(0));
interpreter.installSegment5 (opcodeGetHelloExplicit, new OpGetAiSetting<ExplicitRef>(0));
interpreter.installSegment5 (opcodeGetFight, new OpGetAiSetting<ImplicitRef>(1));
interpreter.installSegment5 (opcodeGetFightExplicit, new OpGetAiSetting<ExplicitRef>(1));
interpreter.installSegment5 (opcodeGetFlee, new OpGetAiSetting<ImplicitRef>(2));
interpreter.installSegment5 (opcodeGetFleeExplicit, new OpGetAiSetting<ExplicitRef>(2));
interpreter.installSegment5 (opcodeGetAlarm, new OpGetAiSetting<ImplicitRef>(3));
interpreter.installSegment5 (opcodeGetAlarmExplicit, new OpGetAiSetting<ExplicitRef>(3));
}
}
}

@ -14,6 +14,8 @@
#include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
@ -128,12 +130,196 @@ namespace MWScript
}
};
template <class R>
class OpEquip : public Interpreter::Opcode0
{
public:
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr);
MWWorld::ContainerStoreIterator it = invStore.begin();
for (; it != invStore.end(); ++it)
{
if (toLower(it->getCellRef().mRefID) == toLower(item))
break;
}
if (it == invStore.end())
throw std::runtime_error("Item to equip not found");
MWWorld::ActionEquip action (*it);
action.execute(ptr);
}
};
template <class R>
class OpGetArmorType : public Interpreter::Opcode0
{
public:
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer location = runtime[0].mInteger;
runtime.pop();
int slot;
switch (location)
{
case 0:
slot = MWWorld::InventoryStore::Slot_Helmet;
break;
case 1:
slot = MWWorld::InventoryStore::Slot_Cuirass;
break;
case 2:
slot = MWWorld::InventoryStore::Slot_LeftPauldron;
break;
case 3:
slot = MWWorld::InventoryStore::Slot_RightPauldron;
break;
case 4:
slot = MWWorld::InventoryStore::Slot_Greaves;
break;
case 5:
slot = MWWorld::InventoryStore::Slot_Boots;
break;
case 6:
slot = MWWorld::InventoryStore::Slot_LeftGauntlet;
break;
case 7:
slot = MWWorld::InventoryStore::Slot_RightGauntlet;
break;
case 8:
slot = MWWorld::InventoryStore::Slot_CarriedLeft; // shield
break;
case 9:
slot = MWWorld::InventoryStore::Slot_LeftGauntlet;
break;
case 10:
slot = MWWorld::InventoryStore::Slot_RightGauntlet;
break;
default:
throw std::runtime_error ("armor index out of range");
}
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr);
MWWorld::ContainerStoreIterator it = invStore.getSlot (slot);
if (it == invStore.end() || it->getTypeName () != typeid(ESM::Armor).name())
{
runtime.push(-1);
return;
}
int skill = MWWorld::Class::get(*it).getEquipmentSkill (*it) ;
if (skill == ESM::Skill::HeavyArmor)
runtime.push(2);
else if (skill == ESM::Skill::MediumArmor)
runtime.push(1);
else if (skill == ESM::Skill::LightArmor)
runtime.push(0);
else
runtime.push(-1);
}
};
template <class R>
class OpHasItemEquipped : public Interpreter::Opcode0
{
public:
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr);
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot)
{
MWWorld::ContainerStoreIterator it = invStore.getSlot (slot);
if (it != invStore.end() && toLower(it->getCellRef().mRefID) == toLower(item))
{
runtime.push(1);
return;
}
}
runtime.push(0);
}
};
template <class R>
class OpHasSoulGem : public Interpreter::Opcode0
{
public:
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string creatureName = toLower (runtime.getStringLiteral (runtime[0].mInteger));
runtime.pop();
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr);
for (MWWorld::ContainerStoreIterator it = invStore.begin(MWWorld::ContainerStore::Type_Miscellaneous);
it != invStore.end(); ++it)
{
if (toLower(it->getCellRef().mSoul) == toLower(creatureName))
{
runtime.push(1);
return;
}
}
runtime.push(0);
}
};
template <class R>
class OpGetWeaponType : public Interpreter::Opcode0
{
public:
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr);
MWWorld::ContainerStoreIterator it = invStore.getSlot (MWWorld::InventoryStore::Slot_CarriedRight);
if (it == invStore.end() || it->getTypeName () != typeid(ESM::Weapon).name())
{
runtime.push(-1);
return;
}
runtime.push(it->get<ESM::Weapon>()->mBase->mData.mType);
}
};
const int opcodeAddItem = 0x2000076;
const int opcodeAddItemExplicit = 0x2000077;
const int opcodeGetItemCount = 0x2000078;
const int opcodeGetItemCountExplicit = 0x2000079;
const int opcodeRemoveItem = 0x200007a;
const int opcodeRemoveItemExplicit = 0x200007b;
const int opcodeEquip = 0x20001b3;
const int opcodeEquipExplicit = 0x20001b4;
const int opcodeGetArmorType = 0x20001d1;
const int opcodeGetArmorTypeExplicit = 0x20001d2;
const int opcodeHasItemEquipped = 0x20001d5;
const int opcodeHasItemEquippedExplicit = 0x20001d6;
const int opcodeHasSoulGem = 0x20001de;
const int opcodeHasSoulGemExplicit = 0x20001df;
const int opcodeGetWeaponType = 0x20001e0;
const int opcodeGetWeaponTypeExplicit = 0x20001e1;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -142,6 +328,11 @@ namespace MWScript
opcodeGetItemCountExplicit);
extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem,
opcodeRemoveItemExplicit);
extensions.registerInstruction ("equip", "c", opcodeEquip, opcodeEquipExplicit);
extensions.registerFunction ("getarmortype", 'l', "l", opcodeGetArmorType, opcodeGetArmorTypeExplicit);
extensions.registerFunction ("hasitemequipped", 'l', "c", opcodeHasItemEquipped, opcodeHasItemEquippedExplicit);
extensions.registerFunction ("hassoulgem", 'l', "c", opcodeHasSoulGem, opcodeHasSoulGemExplicit);
extensions.registerFunction ("getweapontype", 'l', "", opcodeGetWeaponType, opcodeGetWeaponTypeExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -152,6 +343,16 @@ namespace MWScript
interpreter.installSegment5 (opcodeGetItemCountExplicit, new OpGetItemCount<ExplicitRef>);
interpreter.installSegment5 (opcodeRemoveItem, new OpRemoveItem<ImplicitRef>);
interpreter.installSegment5 (opcodeRemoveItemExplicit, new OpRemoveItem<ExplicitRef>);
interpreter.installSegment5 (opcodeEquip, new OpEquip<ImplicitRef>);
interpreter.installSegment5 (opcodeEquipExplicit, new OpEquip<ExplicitRef>);
interpreter.installSegment5 (opcodeGetArmorType, new OpGetArmorType<ImplicitRef>);
interpreter.installSegment5 (opcodeGetArmorTypeExplicit, new OpGetArmorType<ExplicitRef>);
interpreter.installSegment5 (opcodeHasItemEquipped, new OpHasItemEquipped<ImplicitRef>);
interpreter.installSegment5 (opcodeHasItemEquippedExplicit, new OpHasItemEquipped<ExplicitRef>);
interpreter.installSegment5 (opcodeHasSoulGem, new OpHasSoulGem<ImplicitRef>);
interpreter.installSegment5 (opcodeHasSoulGemExplicit, new OpHasSoulGem<ExplicitRef>);
interpreter.installSegment5 (opcodeGetWeaponType, new OpGetWeaponType<ImplicitRef>);
interpreter.installSegment5 (opcodeGetWeaponTypeExplicit, new OpGetWeaponType<ExplicitRef>);
}
}
}

@ -106,6 +106,58 @@ namespace MWScript
}
};
template <class R>
class OpGetForceRun : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats (ptr);
runtime.push (npcStats.getMovementFlag (MWMechanics::NpcStats::Flag_ForceRun));
}
};
template <class R>
class OpGetForceSneak : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats (ptr);
runtime.push (npcStats.getMovementFlag (MWMechanics::NpcStats::Flag_ForceSneak));
}
};
class OpGetPcRunning : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer();
runtime.push (MWWorld::Class::get(ptr).getStance (ptr, MWWorld::Class::Run));
}
};
class OpGetPcSneaking : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer();
runtime.push (MWWorld::Class::get(ptr).getStance (ptr, MWWorld::Class::Sneak));
}
};
const int numberOfControls = 7;
const int opcodeEnable = 0x200007e;
@ -120,6 +172,12 @@ namespace MWScript
const int opcodeForceSneak = 0x200015a;
const int opcodeForceSneakExplicit = 0x200015b;
const int opcodeGetDisabled = 0x2000175;
const int opcodeGetPcRunning = 0x20001c9;
const int opcodeGetPcSneaking = 0x20001ca;
const int opcodeGetForceRun = 0x20001cb;
const int opcodeGetForceSneak = 0x20001cc;
const int opcodeGetForceRunExplicit = 0x20001cd;
const int opcodeGetForceSneakExplicit = 0x20001ce;
const char *controls[numberOfControls] =
{
@ -151,6 +209,10 @@ namespace MWScript
opcodeClearForceSneakExplicit);
extensions.registerInstruction ("forcesneak", "", opcodeForceSneak,
opcodeForceSneakExplicit);
extensions.registerFunction ("getpcrunning", 'l', "", opcodeGetPcRunning);
extensions.registerFunction ("getpcsneaking", 'l', "", opcodeGetPcSneaking);
extensions.registerFunction ("getforcerun", 'l', "", opcodeGetForceRun, opcodeGetForceRunExplicit);
extensions.registerFunction ("getforcesneak", 'l', "", opcodeGetForceSneak, opcodeGetForceSneakExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -181,6 +243,12 @@ namespace MWScript
new OpClearMovementFlag<ExplicitRef> (MWMechanics::NpcStats::Flag_ForceSneak));
interpreter.installSegment5 (opcodeForceSneakExplicit,
new OpSetMovementFlag<ExplicitRef> (MWMechanics::NpcStats::Flag_ForceSneak));
interpreter.installSegment5 (opcodeGetPcRunning, new OpGetPcRunning);
interpreter.installSegment5 (opcodeGetPcSneaking, new OpGetPcSneaking);
interpreter.installSegment5 (opcodeGetForceRun, new OpGetForceRun<ImplicitRef>);
interpreter.installSegment5 (opcodeGetForceRunExplicit, new OpGetForceRun<ExplicitRef>);
interpreter.installSegment5 (opcodeGetForceSneak, new OpGetForceSneak<ImplicitRef>);
interpreter.installSegment5 (opcodeGetForceSneakExplicit, new OpGetForceSneak<ExplicitRef>);
}
}
}

@ -11,6 +11,10 @@
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/journal.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
@ -126,6 +130,64 @@ namespace MWScript
}
};
template<class R>
class OpModReputation : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get(ptr).getNpcStats (ptr).setReputation (MWWorld::Class::get(ptr).getNpcStats (ptr).getReputation () + value);
}
};
template<class R>
class OpSetReputation : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get(ptr).getNpcStats (ptr).setReputation (value);
}
};
template<class R>
class OpGetReputation : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push (MWWorld::Class::get(ptr).getNpcStats (ptr).getReputation ());
}
};
template<class R>
class OpSameFaction : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer();
runtime.push (MWWorld::Class::get(ptr).getNpcStats (ptr).isSameFaction (MWWorld::Class::get(player).getNpcStats (player)));
}
};
const int opcodeJournal = 0x2000133;
const int opcodeSetJournalIndex = 0x2000134;
const int opcodeGetJournalIndex = 0x2000135;
@ -134,6 +196,14 @@ namespace MWScript
const int opcodeForceGreeting = 0x200014f;
const int opcodeForceGreetingExplicit = 0x2000150;
const int opcodeGoodbye = 0x2000152;
const int opcodeSetReputation = 0x20001ad;
const int opcodeModReputation = 0x20001ae;
const int opcodeSetReputationExplicit = 0x20001af;
const int opcodeModReputationExplicit = 0x20001b0;
const int opcodeGetReputation = 0x20001b1;
const int opcodeGetReputationExplicit = 0x20001b2;
const int opcodeSameFaction = 0x20001b5;
const int opcodeSameFactionExplicit = 0x20001b6;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -146,6 +216,14 @@ namespace MWScript
extensions.registerInstruction("forcegreeting","",opcodeForceGreeting,
opcodeForceGreetingExplicit);
extensions.registerInstruction("goodbye", "", opcodeGoodbye);
extensions.registerInstruction("setreputation", "l", opcodeSetReputation,
opcodeSetReputationExplicit);
extensions.registerInstruction("modreputation", "l", opcodeModReputation,
opcodeModReputationExplicit);
extensions.registerFunction("getreputation", 'l', "", opcodeGetReputation,
opcodeGetReputationExplicit);
extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction,
opcodeSameFactionExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -158,6 +236,14 @@ namespace MWScript
interpreter.installSegment5 (opcodeForceGreeting, new OpForceGreeting<ImplicitRef>);
interpreter.installSegment5 (opcodeForceGreetingExplicit, new OpForceGreeting<ExplicitRef>);
interpreter.installSegment5 (opcodeGoodbye, new OpGoodbye);
interpreter.installSegment5 (opcodeGetReputation, new OpGetReputation<ImplicitRef>);
interpreter.installSegment5 (opcodeSetReputation, new OpSetReputation<ImplicitRef>);
interpreter.installSegment5 (opcodeModReputation, new OpModReputation<ImplicitRef>);
interpreter.installSegment5 (opcodeSetReputationExplicit, new OpSetReputation<ExplicitRef>);
interpreter.installSegment5 (opcodeModReputationExplicit, new OpModReputation<ExplicitRef>);
interpreter.installSegment5 (opcodeGetReputationExplicit, new OpGetReputation<ExplicitRef>);
interpreter.installSegment5 (opcodeSameFaction, new OpSameFaction<ImplicitRef>);
interpreter.installSegment5 (opcodeSameFactionExplicit, new OpSameFaction<ExplicitRef>);
}
}

@ -37,7 +37,13 @@ op 0x20014: SetPCFacRep
op 0x20015: SetPCFacRep, explicit reference
op 0x20016: ModPCFacRep
op 0x20017: ModPCFacRep, explicit reference
op s 0x20018-0x3ffff unused
op 0x20018: PcExpelled
op 0x20019: PcExpelled, explicit
op 0x2001a: PcExpell
op 0x2001b: PcExpell, explicit
op 0x2001c: PcClearExpelled
op 0x2001d: PcClearExpelled, explicit
op s 0x2001e-0x3ffff unused
Segment 4:
(not implemented yet)
@ -222,5 +228,72 @@ op 0x20001a9: CommonDisease, explicit reference
op 0x20001aa: BlightDisease
op 0x20001ab: BlightDisease, explicit reference
op 0x20001ac: ToggleCollisionBoxes
opcodes 0x20001ac-0x3ffffff unused
op 0x20001ad: SetReputation
op 0x20001ae: ModReputation
op 0x20001af: SetReputation, explicit
op 0x20001b0: ModReputation, explicit
op 0x20001b1: GetReputation
op 0x20001b2: GetReputation, explicit
op 0x20001b3: Equip
op 0x20001b4: Equip, explicit
op 0x20001b5: SameFaction
op 0x20001b6: SameFaction, explicit
op 0x20001b7: ModHello
op 0x20001b8: ModHello, explicit reference
op 0x20001b9: ModFight
op 0x20001ba: ModFight, explicit reference
op 0x20001bb: ModFlee
op 0x20001bc: ModFlee, explicit reference
op 0x20001bd: ModAlarm
op 0x20001be: ModAlarm, explicit reference
op 0x20001bf: GetHello
op 0x20001c0: GetHello, explicit reference
op 0x20001c1: GetFight
op 0x20001c2: GetFight, explicit reference
op 0x20001c3: GetFlee
op 0x20001c4: GetFlee, explicit reference
op 0x20001c5: GetAlarm
op 0x20001c6: GetAlarm, explicit reference
op 0x20001c7: GetLocked
op 0x20001c8: GetLocked, explicit reference
op 0x20001c9: GetPcRunning
op 0x20001ca: GetPcSneaking
op 0x20001cb: GetForceRun
op 0x20001cc: GetForceSneak
op 0x20001cd: GetForceRun, explicit
op 0x20001ce: GetForceSneak, explicit
op 0x20001cf: GetEffect
op 0x20001d0: GetEffect, explicit
op 0x20001d1: GetArmorType
op 0x20001d2: GetArmorType, explicit
op 0x20001d3: GetAttacked
op 0x20001d4: GetAttacked, explicit
op 0x20001d5: HasItemEquipped
op 0x20001d6: HasItemEquipped, explicit
op 0x20001d7: GetWeaponDrawn
op 0x20001d8: GetWeaponDrawn, explicit
op 0x20001d9: GetRace
op 0x20001da: GetRace, explicit
op 0x20001db: GetSpellEffects
op 0x20001dc: GetSpellEffects, explicit
op 0x20001dd: GetCurrentTime
op 0x20001de: HasSoulGem
op 0x20001df: HasSoulGem, explicit
op 0x20001e0: GetWeaponType
op 0x20001e1: GetWeaponType, explicit
op 0x20001e2: GetWerewolfKills
op 0x20001e3: ModScale
op 0x20001e4: ModScale, explicit
op 0x20001e5: SetDelete
op 0x20001e6: SetDelete, explicit
op 0x20001e7: GetSquareRoot
op 0x20001e8: RaiseRank
op 0x20001e9: RaiseRank, explicit
op 0x20001ea: LowerRank
op 0x20001eb: LowerRank, explicit
op 0x20001ec: PlayBink
opcodes 0x20001ed-0x3ffffff unused

@ -13,6 +13,10 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
@ -285,6 +289,121 @@ namespace MWScript
};
bool OpToggleVanityMode::sActivate = true;
template <class R>
class OpGetLocked : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push (ptr.getCellRef ().mLockLevel > 0);
}
};
template <class R>
class OpGetEffect : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
int key = runtime[0].mInteger;
runtime.pop();
runtime.push (MWWorld::Class::get(ptr).getCreatureStats (ptr).getMagicEffects ().get (
MWMechanics::EffectKey(key)).mMagnitude > 0);
}
};
template <class R>
class OpGetAttacked : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(MWWorld::Class::get(ptr).getCreatureStats (ptr).getAttacked ());
}
};
template <class R>
class OpGetWeaponDrawn : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(MWWorld::Class::get(ptr).getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Weapon);
}
};
template <class R>
class OpGetSpellEffects : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string id = runtime.getStringLiteral(runtime[0].mInteger);
runtime.pop();
runtime.push(MWWorld::Class::get(ptr).getCreatureStats(ptr).getActiveSpells().isSpellActive(id));
}
};
class OpGetCurrentTime : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
runtime.push(MWBase::Environment::get().getWorld()->getTimeStamp().getHour());
}
};
template <class R>
class OpSetDelete : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
int parameter = runtime[0].mInteger;
runtime.pop();
if (parameter == 1)
{
if (ptr.isInCell())
MWBase::Environment::get().getWorld()->deleteObject (ptr);
else
ptr.getRefData().setCount(0);
}
}
};
class OpGetSquareRoot : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
float param = runtime[0].mFloat;
runtime.pop();
runtime.push(std::sqrt (param));
}
};
const int opcodeXBox = 0x200000c;
const int opcodeOnActivate = 0x200000d;
const int opcodeActivate = 0x2000075;
@ -304,8 +423,22 @@ namespace MWScript
const int opcodeToggleVanityMode = 0x2000174;
const int opcodeGetPcSleep = 0x200019f;
const int opcodeWakeUpPc = 0x20001a2;
const int opcodePlayBink = 0x20001a3;
const int opcodeGetLocked = 0x20001c7;
const int opcodeGetLockedExplicit = 0x20001c8;
const int opcodeGetEffect = 0x20001cf;
const int opcodeGetEffectExplicit = 0x20001d0;
const int opcodeGetAttacked = 0x20001d3;
const int opcodeGetAttackedExplicit = 0x20001d4;
const int opcodeGetWeaponDrawn = 0x20001d7;
const int opcodeGetWeaponDrawnExplicit = 0x20001d8;
const int opcodeGetSpellEffects = 0x20001db;
const int opcodeGetSpellEffectsExplicit = 0x20001dc;
const int opcodeGetCurrentTime = 0x20001dd;
const int opcodeSetDelete = 0x20001e5;
const int opcodeSetDeleteExplicit = 0x20001e6;
const int opcodeGetSquareRoot = 0x20001e7;
const int opcodePlayBink = 0x20001ec;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -332,8 +465,15 @@ namespace MWScript
extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
extensions.registerInstruction ("wakeuppc", "", opcodeWakeUpPc);
extensions.registerInstruction ("playbink", "S", opcodePlayBink);
extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit);
extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
extensions.registerFunction ("getcurrenttime", 'f', "", opcodeGetCurrentTime);
extensions.registerInstruction ("setdelete", "l", opcodeSetDelete, opcodeSetDeleteExplicit);
extensions.registerFunction ("getsquareroot", 'f', "f", opcodeGetSquareRoot);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -357,8 +497,21 @@ namespace MWScript
interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode);
interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep);
interpreter.installSegment5 (opcodeWakeUpPc, new OpWakeUpPc);
interpreter.installSegment5 (opcodePlayBink, new OpPlayBink);
interpreter.installSegment5 (opcodeGetLocked, new OpGetLocked<ImplicitRef>);
interpreter.installSegment5 (opcodeGetLockedExplicit, new OpGetLocked<ExplicitRef>);
interpreter.installSegment5 (opcodeGetEffect, new OpGetEffect<ImplicitRef>);
interpreter.installSegment5 (opcodeGetEffectExplicit, new OpGetEffect<ExplicitRef>);
interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
interpreter.installSegment5 (opcodeGetWeaponDrawnExplicit, new OpGetWeaponDrawn<ExplicitRef>);
interpreter.installSegment5 (opcodeGetSpellEffects, new OpGetSpellEffects<ImplicitRef>);
interpreter.installSegment5 (opcodeGetSpellEffectsExplicit, new OpGetSpellEffects<ExplicitRef>);
interpreter.installSegment5 (opcodeGetCurrentTime, new OpGetCurrentTime);
interpreter.installSegment5 (opcodeSetDelete, new OpSetDelete<ImplicitRef>);
interpreter.installSegment5 (opcodeSetDeleteExplicit, new OpSetDelete<ExplicitRef>);
interpreter.installSegment5 (opcodeGetSquareRoot, new OpGetSquareRoot);
}
}
}

@ -780,6 +780,210 @@ namespace MWScript
}
};
template<class R>
class OpGetRace : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string race = runtime.getStringLiteral(runtime[0].mInteger);
boost::algorithm::to_lower(race);
runtime.pop();
std::string npcRace = ptr.get<ESM::NPC>()->mBase->mRace;
boost::algorithm::to_lower(npcRace);
runtime.push (npcRace == race);
}
};
class OpGetWerewolfKills : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ();
runtime.push (MWWorld::Class::get(ptr).getNpcStats (ptr).getWerewolfKills ());
}
};
template <class R>
class OpPcExpelled : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = "";
if(arg0 >0 )
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty())
{
factionID = "";
}
else
{
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
}
}
boost::algorithm::to_lower(factionID);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(factionID!="")
{
std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled ();
if (expelled.find (factionID) != expelled.end())
{
runtime.push(1);
}
else
{
runtime.push(0);
}
}
else
{
runtime.push(0);
}
}
};
template <class R>
class OpPcExpell : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = "";
if(arg0 >0 )
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty())
{
factionID = "";
}
else
{
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
}
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(factionID!="")
{
std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled ();
boost::algorithm::to_lower(factionID);
expelled.insert(factionID);
}
}
};
template <class R>
class OpPcClearExpelled : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = "";
if(arg0 >0 )
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty())
{
factionID = "";
}
else
{
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
}
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(factionID!="")
{
std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled ();
boost::algorithm::to_lower(factionID);
expelled.erase (factionID);
}
}
};
template <class R>
class OpRaiseRank : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = "";
if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty())
return;
else
{
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
// no-op when executed on the player
if (ptr == player)
return;
std::map<std::string, int>& ranks = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks ();
ranks[factionID] = ranks[factionID]+1;
}
};
template <class R>
class OpLowerRank : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = "";
if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty())
return;
else
{
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
// no-op when executed on the player
if (ptr == player)
return;
std::map<std::string, int>& ranks = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks ();
ranks[factionID] = ranks[factionID]-1;
}
};
const int numberOfAttributes = 8;
@ -850,6 +1054,22 @@ namespace MWScript
const int opcodeGetBlightDisease = 0x20001aa;
const int opcodeGetBlightDiseaseExplicit = 0x20001ab;
const int opcodeGetRace = 0x20001d9;
const int opcodeGetRaceExplicit = 0x20001da;
const int opcodeGetWerewolfKills = 0x20001e2;
const int opcodePcExpelled = 0x20018;
const int opcodePcExpelledExplicit = 0x20019;
const int opcodePcExpell = 0x2001a;
const int opcodePcExpellExplicit = 0x2001b;
const int opcodePcClearExpelled = 0x2001c;
const int opcodePcClearExpelledExplicit = 0x2001d;
const int opcodeRaiseRank = 0x20001e8;
const int opcodeRaiseRankExplicit = 0x20001e9;
const int opcodeLowerRank = 0x20001ea;
const int opcodeLowerRankExplicit = 0x20001eb;
void registerExtensions (Compiler::Extensions& extensions)
{
static const char *attributes[numberOfAttributes] =
@ -870,7 +1090,7 @@ namespace MWScript
"alteration", "illusion", "conjuration", "mysticism",
"restoration", "alchemy", "unarmored", "security", "sneak",
"acrobatics", "lightarmor", "shortblade", "marksman",
"merchantile", "speechcraft", "handtohand"
"mercantile", "speechcraft", "handtohand"
};
std::string get ("get");
@ -950,6 +1170,15 @@ namespace MWScript
opcodeGetCommonDiseaseExplicit);
extensions.registerFunction ("getblightdisease", 'l', "", opcodeGetBlightDisease,
opcodeGetBlightDiseaseExplicit);
extensions.registerFunction ("getrace", 'l', "c", opcodeGetRace,
opcodeGetRaceExplicit);
extensions.registerFunction ("getwerewolfkills", 'f', "", opcodeGetWerewolfKills);
extensions.registerFunction ("pcexpelled", 'l', "/S", opcodePcExpelled, opcodePcExpelledExplicit);
extensions.registerInstruction ("pcexpell", "/S", opcodePcExpell, opcodePcExpellExplicit);
extensions.registerInstruction ("pcclearexpelled", "/S", opcodePcClearExpelled, opcodePcClearExpelledExplicit);
extensions.registerInstruction ("raiserank", "", opcodeRaiseRank, opcodeRaiseRankExplicit);
extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -1045,6 +1274,21 @@ namespace MWScript
interpreter.installSegment5 (opcodeGetCommonDiseaseExplicit, new OpGetCommonDisease<ExplicitRef>);
interpreter.installSegment5 (opcodeGetBlightDisease, new OpGetBlightDisease<ImplicitRef>);
interpreter.installSegment5 (opcodeGetBlightDiseaseExplicit, new OpGetBlightDisease<ExplicitRef>);
interpreter.installSegment5 (opcodeGetRace, new OpGetRace<ImplicitRef>);
interpreter.installSegment5 (opcodeGetRaceExplicit, new OpGetRace<ExplicitRef>);
interpreter.installSegment5 (opcodeGetWerewolfKills, new OpGetWerewolfKills);
interpreter.installSegment3 (opcodePcExpelled, new OpPcExpelled<ImplicitRef>);
interpreter.installSegment3 (opcodePcExpelledExplicit, new OpPcExpelled<ExplicitRef>);
interpreter.installSegment3 (opcodePcExpell, new OpPcExpell<ImplicitRef>);
interpreter.installSegment3 (opcodePcExpellExplicit, new OpPcExpell<ExplicitRef>);
interpreter.installSegment3 (opcodePcClearExpelled, new OpPcClearExpelled<ImplicitRef>);
interpreter.installSegment3 (opcodePcClearExpelledExplicit, new OpPcClearExpelled<ExplicitRef>);
interpreter.installSegment5 (opcodeRaiseRank, new OpRaiseRank<ImplicitRef>);
interpreter.installSegment5 (opcodeRaiseRankExplicit, new OpRaiseRank<ExplicitRef>);
interpreter.installSegment5 (opcodeLowerRank, new OpLowerRank<ImplicitRef>);
interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
}
}
}

@ -53,6 +53,23 @@ namespace MWScript
}
};
template<class R>
class OpModScale : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float scale = runtime[0].mFloat;
runtime.pop();
// add the parameter to the object's scale.
MWBase::Environment::get().getWorld()->scaleObject(ptr,ptr.getCellRef().mScale + scale);
}
};
template<class R>
class OpSetAngle : public Interpreter::Opcode0
{
@ -532,6 +549,8 @@ namespace MWScript
const int opcodePlaceAtPc = 0x200019c;
const int opcodePlaceAtMe = 0x200019d;
const int opcodePlaceAtMeExplicit = 0x200019e;
const int opcodeModScale = 0x20001e3;
const int opcodeModScaleExplicit = 0x20001e4;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -548,6 +567,7 @@ namespace MWScript
extensions.registerInstruction("placeitem","cffff",opcodePlaceItem);
extensions.registerInstruction("placeatpc","clfl",opcodePlaceAtPc);
extensions.registerInstruction("placeatme","clfl",opcodePlaceAtMe,opcodePlaceAtMeExplicit);
extensions.registerInstruction("modscale","f",opcodeModScale,opcodeModScaleExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -575,6 +595,8 @@ namespace MWScript
interpreter.installSegment5(opcodePlaceAtPc,new OpPlaceAtPc<ImplicitRef>);
interpreter.installSegment5(opcodePlaceAtMe,new OpPlaceAtMe<ImplicitRef>);
interpreter.installSegment5(opcodePlaceAtMeExplicit,new OpPlaceAtMe<ExplicitRef>);
interpreter.installSegment5(opcodeModScale,new OpModScale<ImplicitRef>);
interpreter.installSegment5(opcodeModScaleExplicit,new OpModScale<ExplicitRef>);
}
}
}

@ -313,7 +313,12 @@ void FFmpeg_Decoder::close()
mStreams.erase(mStreams.begin());
}
if(mFormatCtx)
{
AVIOContext* context = mFormatCtx->pb;
av_free(context);
mFormatCtx->pb = NULL;
av_close_input_file(mFormatCtx);
}
mFormatCtx = NULL;
mDataStream.setNull();

@ -287,6 +287,16 @@ namespace MWWorld
public:
typedef SharedIterator<ESM::Land> iterator;
virtual ~Store<ESM::Land>()
{
for (std::vector<ESM::Land *>::const_iterator it =
mStatic.begin(); it != mStatic.end(); ++it)
{
delete *it;
}
}
int getSize() const {
return mStatic.size();
}

@ -203,6 +203,8 @@ namespace MWWorld
mGlobalVariables->setInt ("chargenstate", 1);
}
mGlobalVariables->setInt ("pcrace", 3);
mWorldScene = new Scene(*mRendering, mPhysics);
setFallbackValues(fallbackMap);
@ -802,7 +804,23 @@ namespace MWWorld
const ESM::NPC *World::createRecord(const ESM::NPC &record)
{
bool update = false;
if (StringUtils::ciEqual(record.mId, "player")) {
if (StringUtils::ciEqual(record.mId, "player"))
{
static const char *sRaces[] =
{
"Argonian", "Breton", "Dark Elf", "High Elf", "Imperial", "Khajiit", "Nord", "Orc", "Redguard",
"Woodelf", 0
};
int i=0;
for (; sRaces[i]; ++i)
if (StringUtils::ciEqual (sRaces[i], record.mRace))
break;
mGlobalVariables->setInt ("pcrace", sRaces[i] ? i+1 : 0);
const ESM::NPC *player =
mPlayer->getPlayer().get<ESM::NPC>()->mBase;

@ -1,5 +1,6 @@
#define gammaCorrectRead(v) pow(v, float3(gammaCorrection,gammaCorrection,gammaCorrection))
#define gammaCorrectOutput(v) pow(v, float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection))
#define gammaCorrectRead(v) pow(max(v, 0.00001f), float3(gammaCorrection,gammaCorrection,gammaCorrection))
#define gammaCorrectOutput(v) pow(max(v, 0.00001f), float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection))
#if SH_HLSL == 1 || SH_CG == 1

@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind
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.
Version: 0.19.0
Version: 0.20.0
License: GPL (see GPL3.txt for more information)
Website: http://www.openmw.org
@ -69,12 +69,9 @@ Allowed options:
--script-all [=arg(=1)] (=0) compile all scripts (excluding dialogue scri
pts) at startup
--script-console [=arg(=1)] (=0) enable console-only script functionality
--script-run arg select a file that is executed in the consol
e on startup
--script-run arg select a file containing a list of console
commands that is executed on startup
Note: The file contains a list of script
lines, but not a complete scripts. That mean
s no begin/end and no variable declarations.
--new-game [=arg(=1)] (=0) activate char gen/new game mechanics
--fs-strict [=arg(=1)] (=0) strict file system handling (no case folding
)
@ -97,6 +94,36 @@ Allowed options:
CHANGELOG
0.20.0
Bug #366: Changing the player's race during character creation does not change the look of the player character
Bug #430: Teleporting and using loading doors linking within the same cell reloads the cell
Bug #437: Stop animations when paused
Bug #438: Time displays as "0 a.m." when it should be "12 a.m."
Bug #439: Text in "name" field of potion/spell creation window is persistent
Bug #440: Starting date at a new game is off by one day
Bug #442: Console window doesn't close properly sometimes
Bug #448: Do not break container window formatting when item names are very long
Bug #458: Topics sometimes not automatically added to known topic list
Bug #476: Auto-Moving allows player movement after using DisablePlayerControls
Bug #478: After sleeping in a bed the rest dialogue window opens automtically again
Bug #492: On creating potions the ingredients are removed twice
Feature #63: Mercantile skill
Feature #82: Persuasion Dialogue
Feature #219: Missing dialogue filters/functions
Feature #369: Add a FailedAction
Feature #377: Select head/hair on character creation
Feature #391: Dummy AI package classes
Feature #435: Global Map, 2nd Layer
Feature #450: Persuasion
Feature #457: Add more script instructions
Feature #474: update the global variable pcrace when the player's race is changed
Task #158: Move dynamically generated classes from Player class to World Class
Task #159: ESMStore rework and cleanup
Task #163: More Component Namespace Cleanup
Task #402: Move player data from MWWorld::Player to the player's NPC record
Task #446: Fix no namespace in BulletShapeLoader
0.19.0
Bug #374: Character shakes in 3rd person mode near the origin

Loading…
Cancel
Save