Merge remote-tracking branch 'upstream/master'

pull/131/head
cc9cii 11 years ago
commit eb1589fd54

@ -707,9 +707,9 @@ void Record<ESM::Faction>::print()
std::cout << " Faction Reaction: "
<< mData.mData.mRankData[i].mFactReaction << std::endl;
}
std::vector<ESM::Faction::Reaction>::iterator rit;
std::map<std::string, int>::iterator rit;
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++)
std::cout << " Reaction: " << rit->mReaction << " = " << rit->mFaction << std::endl;
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
}
template<>

@ -68,6 +68,12 @@ namespace MWBase
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
/// Changes faction1's opinion of faction2 by \a diff.
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) = 0;
/// @return faction1's opinion of faction2
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;
};
}

@ -642,6 +642,8 @@ namespace MWDialogue
if (iter->second)
state.mKnownTopics.push_back (iter->first);
state.mModFactionReaction = mModFactionReaction;
writer.startRecord (ESM::REC_DIAS);
state.save (writer);
writer.endRecord (ESM::REC_DIAS);
@ -661,9 +663,46 @@ namespace MWDialogue
iter!=state.mKnownTopics.end(); ++iter)
if (store.get<ESM::Dialogue>().search (*iter))
mKnownTopics.insert (std::make_pair (*iter, true));
mModFactionReaction = state.mModFactionReaction;
}
}
void DialogueManager::modFactionReaction(const std::string &faction1, const std::string &faction2, int diff)
{
std::string fact1 = Misc::StringUtils::lowerCase(faction1);
std::string fact2 = Misc::StringUtils::lowerCase(faction2);
// Make sure the factions exist
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1);
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact2);
std::map<std::string, int>& map = mModFactionReaction[fact1];
if (map.find(fact2) == map.end())
map[fact2] = 0;
map[fact2] += diff;
}
int DialogueManager::getFactionReaction(const std::string &faction1, const std::string &faction2) const
{
std::string fact1 = Misc::StringUtils::lowerCase(faction1);
std::string fact2 = Misc::StringUtils::lowerCase(faction2);
ModFactionReactionMap::const_iterator map = mModFactionReaction.find(fact1);
int diff = 0;
if (map != mModFactionReaction.end() && map->second.find(fact2) != map->second.end())
diff = map->second.at(fact2);
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(fact1);
std::map<std::string, int>::const_iterator it = faction->mReactions.begin();
for (; it != faction->mReactions.end(); ++it)
{
if (Misc::StringUtils::ciEqual(it->first, fact2))
return it->second + diff;
}
return diff;
}
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
{

@ -24,6 +24,11 @@ namespace MWDialogue
{
std::map<std::string, ESM::Dialogue> mDialogueMap;
std::map<std::string, bool> mKnownTopics;// Those are the topics the player knows.
// Modified faction reactions. <Faction1, <Faction2, Difference> >
typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
ModFactionReactionMap mModFactionReaction;
std::list<std::string> mActorKnownTopics;
Translation::Storage& mTranslationDataStorage;
@ -86,6 +91,12 @@ namespace MWDialogue
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
/// Changes faction1's opinion of faction2 by \a diff.
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff);
/// @return faction1's opinion of faction2
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const;
};

@ -396,16 +396,15 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
int value = 0;
const ESM::Faction& faction =
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find (factionId);
MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats (player);
for (std::vector<ESM::Faction::Reaction>::const_iterator iter (faction.mReactions.begin());
iter!=faction.mReactions.end(); ++iter)
if (playerStats.getFactionRanks().find (iter->mFaction)!=playerStats.getFactionRanks().end())
if (low ? iter->mReaction<value : iter->mReaction>value)
value = iter->mReaction;
std::map<std::string, int>::const_iterator playerFactionIt = playerStats.getFactionRanks().begin();
for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt)
{
int reaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(factionId, playerFactionIt->first);
if (low ? reaction < value : reaction > value)
value = reaction;
}
return value;
}

@ -492,7 +492,8 @@ namespace MWInput
}
if (arg.keysym.sym == SDLK_x && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
{
std::string text = edit->getTextSelection();
// Discard color codes and other escape characters
std::string text = MyGUI::TextIterator::getOnlyText(edit->getTextSelection());
if (text.length())
{
SDL_SetClipboardText(text.c_str());
@ -504,7 +505,8 @@ namespace MWInput
{
if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
{
std::string text = edit->getTextSelection();
// Discard color codes and other escape characters
std::string text = MyGUI::TextIterator::getOnlyText(edit->getTextSelection());
if (text.length())
SDL_SetClipboardText(text.c_str());
}

@ -498,27 +498,24 @@ namespace MWMechanics
if (playerStats.getFactionRanks().find(npcFaction) != playerStats.getFactionRanks().end())
{
for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.begin();
it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.end(); ++it)
if (!playerStats.getExpelled(npcFaction))
{
if(Misc::StringUtils::ciEqual(it->mFaction, npcFaction)
&& !playerStats.getExpelled(it->mFaction))
reaction = it->mReaction;
reaction = playerStats.getFactionReputation(npcFaction);
rank = playerStats.getFactionRanks().find(npcFaction)->second;
}
rank = playerStats.getFactionRanks().find(npcFaction)->second;
}
else if (npcFaction != "")
else if (!npcFaction.empty())
{
for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.begin();
it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npcFaction)->mReactions.end();++it)
std::map<std::string, int>::const_iterator playerFactionIt = playerStats.getFactionRanks().begin();
for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt)
{
if(playerStats.getFactionRanks().find(Misc::StringUtils::lowerCase(it->mFaction)) != playerStats.getFactionRanks().end() )
{
if(it->mReaction < reaction)
reaction = it->mReaction;
}
std::string itFaction = playerFactionIt->first;
int itReaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, itFaction);
if (playerFactionIt == playerStats.getFactionRanks().begin() || itReaction < reaction)
reaction = itReaction;
}
rank = 0;
}
else
{

@ -196,6 +196,45 @@ namespace MWScript
}
};
class OpModFactionReaction : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
std::string faction2 = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
int modReaction = runtime[0].mInteger;
runtime.pop();
MWBase::Environment::get().getDialogueManager()->modFactionReaction(faction1, faction2, modReaction);
}
};
class OpGetFactionReaction : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
std::string faction2 = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
// ignore extra garbage argument
runtime.pop();
runtime.push(MWBase::Environment::get().getDialogueManager()
->getFactionReaction(faction1, faction2));
}
};
void installOpcodes (Interpreter::Interpreter& interpreter)
{
@ -215,6 +254,8 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Dialogue::opcodeGetReputationExplicit, new OpGetReputation<ExplicitRef>);
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFaction, new OpSameFaction<ImplicitRef>);
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction<ExplicitRef>);
interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction);
interpreter.installSegment5 (Compiler::Dialogue::opcodeGetFactionReaction, new OpGetFactionReaction);
}
}

@ -390,5 +390,7 @@ op 0x200023e: GetPcInJail
op 0x200023f: GetPcTraveling
op 0x2000240: onKnockout
op 0x2000241: onKnockoutExplicit
op 0x2000242: ModFactionReaction
op 0x2000243: GetFactionReaction
opcodes 0x2000242-0x3ffffff unused
opcodes 0x2000244-0x3ffffff unused

@ -541,6 +541,9 @@ namespace MWScript
runtime.pop();
}
::Misc::StringUtils::toLower(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
if(factionID != "")
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
@ -572,6 +575,9 @@ namespace MWScript
runtime.pop();
}
::Misc::StringUtils::toLower(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
if(factionID != "")
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
@ -607,6 +613,9 @@ namespace MWScript
runtime.pop();
}
::Misc::StringUtils::toLower(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
if(factionID != "")
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
@ -645,6 +654,9 @@ namespace MWScript
}
}
::Misc::StringUtils::toLower(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if(factionID!="")
{

@ -492,7 +492,7 @@ namespace MWWorld
return std::make_pair(true, ray.getPoint(len * test.second));
}
std::pair<bool, Ogre::Vector3> PhysicsSystem::castRay(float mouseX, float mouseY)
std::pair<bool, Ogre::Vector3> PhysicsSystem::castRay(float mouseX, float mouseY, Ogre::Vector3* normal)
{
Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay(
mouseX,
@ -504,7 +504,7 @@ namespace MWWorld
_from = btVector3(from.x, from.y, from.z);
_to = btVector3(to.x, to.y, to.z);
std::pair<std::string, float> result = mEngine->rayTest(_from, _to);
std::pair<std::string, float> result = mEngine->rayTest(_from, _to, true, false, normal);
if (result.first == "")
return std::make_pair(false, Ogre::Vector3());

@ -70,8 +70,9 @@ namespace MWWorld
std::pair<bool, Ogre::Vector3>
castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len);
std::pair<bool, Ogre::Vector3> castRay(float mouseX, float mouseY);
///< cast ray from the mouse, return true if it hit something and the first result (in OGRE coordinates)
std::pair<bool, Ogre::Vector3> castRay(float mouseX, float mouseY, Ogre::Vector3* normal = NULL);
///< cast ray from the mouse, return true if it hit something and the first result
/// @param normal if non-NULL, the hit normal will be written there (if there is a hit)
OEngine::Physic::PhysicEngine* getEngine();

@ -1620,25 +1620,39 @@ namespace MWWorld
bool World::canPlaceObject(float cursorX, float cursorY)
{
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY);
/// \todo also check if the wanted position is on a flat surface, and not e.g. against a vertical wall!
Ogre::Vector3 normal(0,0,0);
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY, &normal);
if (!result.first)
if (result.first)
{
// check if the wanted position is on a flat surface, and not e.g. against a vertical wall
return (normal.angleBetween(Ogre::Vector3(0.f,0.f,1.f)).valueDegrees() < 30);
}
else
return false;
return true;
}
Ptr World::copyObjectToCell(const Ptr &object, CellStore* cell, ESM::Position pos, bool adjustPos)
{
if (object.getClass().isActor() || adjustPos)
if (!object.getClass().isActor() && adjustPos)
{
// Adjust position so the location we wanted ends up in the middle of the object bounding box
Ogre::Vector3 min, max;
if (mPhysics->getObjectAABB(object, min, max)) {
pos.pos[0] -= (min.x + max.x) / 2;
pos.pos[1] -= (min.y + max.y) / 2;
pos.pos[2] -= min.z;
Ogre::Quaternion xr(Ogre::Radian(-pos.rot[0]), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr(Ogre::Radian(-pos.rot[1]), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr(Ogre::Radian(-pos.rot[2]), Ogre::Vector3::UNIT_Z);
Ogre::Vector3 adjust (
(min.x + max.x) / 2,
(min.y + max.y) / 2,
min.z
);
adjust = (xr*yr*zr) * adjust;
pos.pos[0] -= adjust.x;
pos.pos[1] -= adjust.y;
pos.pos[2] -= adjust.z;
}
}

@ -730,7 +730,7 @@ namespace Compiler
}
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
std::vector<Interpreter::Type_Code>& code, bool invert)
std::vector<Interpreter::Type_Code>& code)
{
bool optional = false;
int optionalCount = 0;
@ -762,15 +762,10 @@ namespace Compiler
if (*iter!='x')
{
if (invert)
{
std::vector<Interpreter::Type_Code> tmp;
stringParser.append (tmp);
std::vector<Interpreter::Type_Code> tmp;
stringParser.append (tmp);
stack.push (tmp);
}
else
stringParser.append (code);
stack.push (tmp);
if (optional)
++optionalCount;
@ -795,10 +790,7 @@ namespace Compiler
if (type!=*iter)
Generator::convert (tmp, type, *iter);
if (invert)
stack.push (tmp);
else
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
stack.push (tmp);
if (optional)
++optionalCount;

@ -96,7 +96,7 @@ namespace Compiler
/// \return Type ('l': integer, 'f': float)
int parseArguments (const std::string& arguments, Scanner& scanner,
std::vector<Interpreter::Type_Code>& code, bool invert = false);
std::vector<Interpreter::Type_Code>& code);
///< Parse sequence of arguments specified by \a arguments.
/// \param arguments Uses ScriptArgs typedef
/// \see Compiler::ScriptArgs

@ -179,6 +179,8 @@ namespace Compiler
opcodeGetReputationExplicit);
extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction,
opcodeSameFactionExplicit);
extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction);
extensions.registerFunction("getfactionreaction", 'l', "ccl", opcodeGetFactionReaction);
}
}

@ -166,7 +166,7 @@ namespace Compiler
if (!arguments.empty())
{
mExprParser.reset();
mExprParser.parseArguments (arguments, scanner, mCode, true);
mExprParser.parseArguments (arguments, scanner, mCode);
}
mName = name;
@ -278,7 +278,7 @@ namespace Compiler
mExplicit.clear();
}
int optionals = mExprParser.parseArguments (argumentType, scanner, mCode, true);
int optionals = mExprParser.parseArguments (argumentType, scanner, mCode);
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals);
mState = EndState;
@ -363,14 +363,14 @@ namespace Compiler
case Scanner::K_startscript:
mExprParser.parseArguments ("c", scanner, mCode, true);
mExprParser.parseArguments ("c", scanner, mCode);
Generator::startScript (mCode);
mState = EndState;
return true;
case Scanner::K_stopscript:
mExprParser.parseArguments ("c", scanner, mCode, true);
mExprParser.parseArguments ("c", scanner, mCode);
Generator::stopScript (mCode);
mState = EndState;
return true;

@ -152,6 +152,8 @@ namespace Compiler
const int opcodeGetReputationExplicit = 0x20001b2;
const int opcodeSameFaction = 0x20001b5;
const int opcodeSameFactionExplicit = 0x20001b6;
const int opcodeModFactionReaction = 0x2000242;
const int opcodeGetFactionReaction = 0x2000243;
}
namespace Gui

@ -8,6 +8,20 @@ void ESM::DialogueState::load (ESMReader &esm)
{
while (esm.isNextSub ("TOPI"))
mKnownTopics.push_back (esm.getHString());
while (esm.isNextSub ("FACT"))
{
std::string faction = esm.getHString();
while (esm.isNextSub ("REAC"))
{
std::string faction2 = esm.getHString();
int reaction;
esm.getHNT(reaction, "INTV");
mModFactionReaction[faction][faction2] = reaction;
}
}
}
void ESM::DialogueState::save (ESMWriter &esm) const
@ -16,6 +30,18 @@ void ESM::DialogueState::save (ESMWriter &esm) const
iter!=mKnownTopics.end(); ++iter)
{
esm.writeHNString ("TOPI", *iter);
}
for (std::map<std::string, std::map<std::string, int> >::const_iterator iter = mModFactionReaction.begin();
iter != mModFactionReaction.end(); ++iter)
{
esm.writeHNString ("FACT", iter->first);
for (std::map<std::string, int>::const_iterator reactIter = iter->second.begin();
reactIter != iter->second.end(); ++reactIter)
{
esm.writeHNString ("REAC", reactIter->first);
esm.writeHNT ("INTV", reactIter->second);
}
}
}
}

@ -3,6 +3,7 @@
#include <string>
#include <vector>
#include <map>
namespace ESM
{
@ -15,9 +16,11 @@ namespace ESM
{
std::vector<std::string> mKnownTopics;
std::map<std::string, std::map<std::string, int> > mModFactionReaction;
void load (ESMReader &esm);
void save (ESMWriter &esm) const;
};
}
#endif
#endif

@ -44,10 +44,10 @@ void Faction::load(ESMReader &esm)
// Read faction response values
while (esm.hasMoreSubs())
{
Reaction r;
r.mFaction = esm.getHNString("ANAM");
esm.getHNT(r.mReaction, "INTV");
mReactions.push_back(r);
std::string faction = esm.getHNString("ANAM");
int reaction;
esm.getHNT(reaction, "INTV");
mReactions[faction] = reaction;
}
}
void Faction::save(ESMWriter &esm) const
@ -64,10 +64,10 @@ void Faction::save(ESMWriter &esm) const
esm.writeHNT("FADT", mData, 240);
for (std::vector<Reaction>::const_iterator it = mReactions.begin(); it != mReactions.end(); ++it)
for (std::map<std::string, int>::const_iterator it = mReactions.begin(); it != mReactions.end(); ++it)
{
esm.writeHNString("ANAM", it->mFaction);
esm.writeHNT("INTV", it->mReaction);
esm.writeHNString("ANAM", it->first);
esm.writeHNT("INTV", it->second);
}
}

@ -2,7 +2,7 @@
#define OPENMW_ESM_FACT_H
#include <string>
#include <vector>
#include <map>
namespace ESM
{
@ -53,13 +53,8 @@ struct Faction
FADTstruct mData;
struct Reaction
{
std::string mFaction;
int mReaction;
};
std::vector<Reaction> mReactions;
// <Faction ID, Reaction>
std::map<std::string, int> mReactions;
// Name of faction ranks (may be empty for NPC factions)
std::string mRanks[10];

@ -677,7 +677,7 @@ namespace Physic
{
}
std::pair<std::string,float> PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly,bool ignoreHeightMap)
std::pair<std::string,float> PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly,bool ignoreHeightMap, Ogre::Vector3* normal)
{
std::string name = "";
float d = -1;
@ -694,7 +694,11 @@ namespace Physic
if (resultCallback1.hasHit())
{
name = static_cast<const RigidBody&>(*resultCallback1.m_collisionObject).mName;
d = resultCallback1.m_closestHitFraction;;
d = resultCallback1.m_closestHitFraction;
if (normal)
*normal = Ogre::Vector3(resultCallback1.m_hitNormalWorld.x(),
resultCallback1.m_hitNormalWorld.y(),
resultCallback1.m_hitNormalWorld.z());
}
return std::pair<std::string,float>(name,d);

@ -308,8 +308,10 @@ namespace Physic
/**
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
* If \a normal is non-NULL, the hit normal will be written there (if there is a hit)
*/
std::pair<std::string,float> rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true,bool ignoreHeightMap = false);
std::pair<std::string,float> rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true,
bool ignoreHeightMap = false, Ogre::Vector3* normal = NULL);
/**
* Return all objects hit by a ray.

Loading…
Cancel
Save