forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
4fa0bf63c5
16 changed files with 228 additions and 189 deletions
|
@ -138,6 +138,9 @@ namespace MWBase
|
||||||
/// @return was it illegal, and someone saw you doing it?
|
/// @return was it illegal, and someone saw you doing it?
|
||||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
|
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
|
||||||
|
|
||||||
|
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
||||||
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) = 0;
|
||||||
|
|
||||||
enum PersuasionType
|
enum PersuasionType
|
||||||
{
|
{
|
||||||
PT_Admire,
|
PT_Admire,
|
||||||
|
|
|
@ -537,15 +537,14 @@ namespace MWClass
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||||
|
|
||||||
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
|
||||||
|
|
||||||
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||||
|
|
||||||
// The Run speed difference for creatures comes from the animation speed difference (see runStateToWalkState in character.cpp)
|
// The Run speed difference for creatures comes from the animation speed difference (see runStateToWalkState in character.cpp)
|
||||||
float runSpeed = walkSpeed;
|
float runSpeed = walkSpeed;
|
||||||
|
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if(normalizedEncumbrance >= 1.0f)
|
|
||||||
|
if(getEncumbrance(ptr) > getCapacity(ptr))
|
||||||
moveSpeed = 0.0f;
|
moveSpeed = 0.0f;
|
||||||
else if(canFly(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 &&
|
else if(canFly(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 &&
|
||||||
world->isLevitationEnabled()))
|
world->isLevitationEnabled()))
|
||||||
|
@ -553,6 +552,7 @@ namespace MWClass
|
||||||
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||||
mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
|
mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
|
||||||
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
|
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
|
||||||
|
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
||||||
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||||
flySpeed = std::max(0.0f, flySpeed);
|
flySpeed = std::max(0.0f, flySpeed);
|
||||||
moveSpeed = flySpeed;
|
moveSpeed = flySpeed;
|
||||||
|
|
|
@ -23,39 +23,6 @@
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
|
||||||
bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim)
|
|
||||||
{
|
|
||||||
const std::string& owner = item.getCellRef().getOwner();
|
|
||||||
bool isOwned = !owner.empty() && owner != "player";
|
|
||||||
|
|
||||||
const std::string& faction = item.getCellRef().getFaction();
|
|
||||||
bool isFactionOwned = false;
|
|
||||||
if (!faction.empty() && ptr.getClass().isNpc())
|
|
||||||
{
|
|
||||||
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
|
|
||||||
std::map<std::string, int>::const_iterator found = factions.find(Misc::StringUtils::lowerCase(faction));
|
|
||||||
if (found == factions.end()
|
|
||||||
|| found->second < item.getCellRef().getFactionRank())
|
|
||||||
isFactionOwned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& globalVariable = item.getCellRef().getGlobalVariable();
|
|
||||||
if (!globalVariable.empty() && MWBase::Environment::get().getWorld()->getGlobalInt(Misc::StringUtils::lowerCase(globalVariable)) == 1)
|
|
||||||
{
|
|
||||||
isOwned = false;
|
|
||||||
isFactionOwned = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item.getCellRef().getOwner().empty())
|
|
||||||
victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true);
|
|
||||||
|
|
||||||
return (!isOwned && !isFactionOwned);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
void MechanicsManager::buildPlayer()
|
void MechanicsManager::buildPlayer()
|
||||||
|
@ -879,6 +846,35 @@ namespace MWMechanics
|
||||||
mAI = true;
|
mAI = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim)
|
||||||
|
{
|
||||||
|
const std::string& owner = item.getCellRef().getOwner();
|
||||||
|
bool isOwned = !owner.empty() && owner != "player";
|
||||||
|
|
||||||
|
const std::string& faction = item.getCellRef().getFaction();
|
||||||
|
bool isFactionOwned = false;
|
||||||
|
if (!faction.empty() && ptr.getClass().isNpc())
|
||||||
|
{
|
||||||
|
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
|
||||||
|
std::map<std::string, int>::const_iterator found = factions.find(Misc::StringUtils::lowerCase(faction));
|
||||||
|
if (found == factions.end()
|
||||||
|
|| found->second < item.getCellRef().getFactionRank())
|
||||||
|
isFactionOwned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& globalVariable = item.getCellRef().getGlobalVariable();
|
||||||
|
if (!globalVariable.empty() && MWBase::Environment::get().getWorld()->getGlobalInt(Misc::StringUtils::lowerCase(globalVariable)) == 1)
|
||||||
|
{
|
||||||
|
isOwned = false;
|
||||||
|
isFactionOwned = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.getCellRef().getOwner().empty())
|
||||||
|
victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true);
|
||||||
|
|
||||||
|
return (!isOwned && !isFactionOwned);
|
||||||
|
}
|
||||||
|
|
||||||
bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed)
|
bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed)
|
||||||
{
|
{
|
||||||
if (ptr.getClass().getNpcStats(ptr).isWerewolf())
|
if (ptr.getClass().getNpcStats(ptr).isWerewolf())
|
||||||
|
|
|
@ -130,6 +130,9 @@ namespace MWMechanics
|
||||||
/// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby
|
/// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby
|
||||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
|
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
|
||||||
|
|
||||||
|
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
||||||
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim);
|
||||||
|
|
||||||
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
|
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
|
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
|
||||||
|
|
|
@ -41,7 +41,8 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getJournal()->setJournalIndex(quest, index);
|
if (MWBase::Environment::get().getJournal()->getJournalIndex(quest) < index)
|
||||||
|
MWBase::Environment::get().getJournal()->setJournalIndex(quest, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -311,6 +311,9 @@ namespace MWScript
|
||||||
|
|
||||||
std::string InterpreterContext::getNPCRank() const
|
std::string InterpreterContext::getNPCRank() const
|
||||||
{
|
{
|
||||||
|
if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty())
|
||||||
|
throw std::runtime_error("getNPCRank(): NPC is not in a faction");
|
||||||
|
|
||||||
const std::map<std::string, int>& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
|
const std::map<std::string, int>& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
|
||||||
std::map<std::string, int>::const_iterator it = ranks.begin();
|
std::map<std::string, int>::const_iterator it = ranks.begin();
|
||||||
|
|
||||||
|
@ -347,6 +350,9 @@ namespace MWScript
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
|
|
||||||
|
if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty())
|
||||||
|
throw std::runtime_error("getPCRank(): NPC is not in a faction");
|
||||||
|
|
||||||
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
||||||
|
|
||||||
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
||||||
|
@ -374,6 +380,9 @@ namespace MWScript
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
|
|
||||||
|
if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty())
|
||||||
|
throw std::runtime_error("getPCNextRank(): NPC is not in a faction");
|
||||||
|
|
||||||
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
||||||
|
|
||||||
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
||||||
|
|
|
@ -1294,7 +1294,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if (force || !isFlying(ptr))
|
if (force || !isFlying(ptr))
|
||||||
{
|
{
|
||||||
Ogre::Vector3 traced = mPhysics->traceDown(ptr, 300);
|
Ogre::Vector3 traced = mPhysics->traceDown(ptr, 500);
|
||||||
if (traced.z < pos.pos[2])
|
if (traced.z < pos.pos[2])
|
||||||
pos.pos[2] = traced.z;
|
pos.pos[2] = traced.z;
|
||||||
}
|
}
|
||||||
|
@ -2879,7 +2879,8 @@ namespace MWWorld
|
||||||
ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||||
for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) //Move all stolen stuff into chest
|
for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) //Move all stolen stuff into chest
|
||||||
{
|
{
|
||||||
if (!it->getCellRef().getOwner().empty() && it->getCellRef().getOwner() != "player") //Not owned by no one/player?
|
MWWorld::Ptr dummy;
|
||||||
|
if (!MWBase::Environment::get().getMechanicsManager()->isAllowedToUse(getPlayerPtr(), *it, dummy))
|
||||||
{
|
{
|
||||||
closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest);
|
closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest);
|
||||||
store.remove(*it, it->getRefData().getCount(), ptr);
|
store.remove(*it, it->getRefData().getCount(), ptr);
|
||||||
|
|
|
@ -85,6 +85,11 @@ struct Land
|
||||||
char mColours[3 * LAND_NUM_VERTS];
|
char mColours[3 * LAND_NUM_VERTS];
|
||||||
int mDataTypes;
|
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];
|
uint8_t mWnam[81];
|
||||||
short mUnk1;
|
short mUnk1;
|
||||||
uint8_t mUnk2;
|
uint8_t mUnk2;
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace Interpreter{
|
namespace Interpreter{
|
||||||
|
|
||||||
bool Check(const std::string& str, const std::string& escword, unsigned int* i, unsigned int* start){
|
bool check(const std::string& str, const std::string& escword, unsigned int* i, unsigned int* start)
|
||||||
|
{
|
||||||
bool retval = str.find(escword) == 0;
|
bool retval = str.find(escword) == 0;
|
||||||
if(retval){
|
if(retval){
|
||||||
(*i) += escword.length();
|
(*i) += escword.length();
|
||||||
|
@ -18,170 +20,181 @@ namespace Interpreter{
|
||||||
|
|
||||||
std::vector<std::string> globals;
|
std::vector<std::string> globals;
|
||||||
|
|
||||||
bool longerStr(const std::string& a, const std::string& b){
|
bool longerStr(const std::string& a, const std::string& b)
|
||||||
|
{
|
||||||
return a.length() > b.length();
|
return a.length() > b.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fixDefinesReal(std::string text, char eschar, bool isBook, Context& context){
|
std::string fixDefinesReal(std::string text, char eschar, bool isBook, Context& context)
|
||||||
|
{
|
||||||
unsigned int start = 0;
|
unsigned int start = 0;
|
||||||
std::ostringstream retval;
|
std::ostringstream retval;
|
||||||
for(unsigned int i = 0; i < text.length(); i++){
|
for(unsigned int i = 0; i < text.length(); i++)
|
||||||
if(text[i] == eschar){
|
{
|
||||||
|
if(text[i] == eschar)
|
||||||
|
{
|
||||||
retval << text.substr(start, i - start);
|
retval << text.substr(start, i - start);
|
||||||
std::string temp = text.substr(i+1, 100);
|
std::string temp = text.substr(i+1, 100);
|
||||||
transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
|
transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
|
||||||
|
|
||||||
bool found;
|
bool found = false;
|
||||||
|
try
|
||||||
if( (found = Check(temp, "actionslideright", &i, &start))){
|
{
|
||||||
retval << context.getActionBinding("#{sRight}");
|
if( (found = check(temp, "actionslideright", &i, &start))){
|
||||||
}
|
retval << context.getActionBinding("#{sRight}");
|
||||||
else if((found = Check(temp, "actionreadymagic", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sReady_Magic}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionprevweapon", &i, &start))){
|
|
||||||
retval << "PLACEHOLDER_ACTION_PREV_WEAPON";
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionnextweapon", &i, &start))){
|
|
||||||
retval << "PLACEHOLDER_ACTION_PREV_WEAPON";
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actiontogglerun", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sAuto_Run}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionslideleft", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sLeft}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionreadyitem", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sReady_Weapon}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionprevspell", &i, &start))){
|
|
||||||
retval << "PLACEHOLDER_ACTION_PREV_SPELL";
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionnextspell", &i, &start))){
|
|
||||||
retval << "PLACEHOLDER_ACTION_NEXT_SPELL";
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionrestmenu", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sRestKey}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionmenumode", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sInventory}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionactivate", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sActivate}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionjournal", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sJournal}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionforward", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sForward}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "pccrimelevel", &i, &start))){
|
|
||||||
retval << context.getPCBounty();
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actioncrouch", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sCrouch_Sneak}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionjump", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sJump}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionback", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sBack}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionuse", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sUse}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "actionrun", &i, &start))){
|
|
||||||
retval << context.getActionBinding("#{sRun}");
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "pcclass", &i, &start))){
|
|
||||||
retval << context.getPCClass();
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "pcrace", &i, &start))){
|
|
||||||
retval << context.getPCRace();
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "pcname", &i, &start))){
|
|
||||||
retval << context.getPCName();
|
|
||||||
}
|
|
||||||
else if((found = Check(temp, "cell", &i, &start))){
|
|
||||||
retval << context.getCurrentCellName();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(eschar == '%' && !isBook) { // In Dialogue, not messagebox
|
|
||||||
if( (found = Check(temp, "faction", &i, &start))){
|
|
||||||
retval << context.getNPCFaction();
|
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "nextpcrank", &i, &start))){
|
else if((found = check(temp, "actionreadymagic", &i, &start))){
|
||||||
retval << context.getPCNextRank();
|
retval << context.getActionBinding("#{sReady_Magic}");
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "pcnextrank", &i, &start))){
|
else if((found = check(temp, "actionprevweapon", &i, &start))){
|
||||||
retval << context.getPCNextRank();
|
retval << "PLACEHOLDER_ACTION_PREV_WEAPON";
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "pcrank", &i, &start))){
|
else if((found = check(temp, "actionnextweapon", &i, &start))){
|
||||||
retval << context.getPCRank();
|
retval << "PLACEHOLDER_ACTION_PREV_WEAPON";
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "rank", &i, &start))){
|
else if((found = check(temp, "actiontogglerun", &i, &start))){
|
||||||
retval << context.getNPCRank();
|
retval << context.getActionBinding("#{sAuto_Run}");
|
||||||
}
|
}
|
||||||
|
else if((found = check(temp, "actionslideleft", &i, &start))){
|
||||||
else if((found = Check(temp, "class", &i, &start))){
|
retval << context.getActionBinding("#{sLeft}");
|
||||||
retval << context.getNPCClass();
|
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "race", &i, &start))){
|
else if((found = check(temp, "actionreadyitem", &i, &start))){
|
||||||
retval << context.getNPCRace();
|
retval << context.getActionBinding("#{sReady_Weapon}");
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "name", &i, &start))){
|
else if((found = check(temp, "actionprevspell", &i, &start))){
|
||||||
retval << context.getNPCName();
|
retval << "PLACEHOLDER_ACTION_PREV_SPELL";
|
||||||
}
|
}
|
||||||
}
|
else if((found = check(temp, "actionnextspell", &i, &start))){
|
||||||
else { // In messagebox or book, not dialogue
|
retval << "PLACEHOLDER_ACTION_NEXT_SPELL";
|
||||||
|
}
|
||||||
/* empty outside dialogue */
|
else if((found = check(temp, "actionrestmenu", &i, &start))){
|
||||||
if( (found = Check(temp, "faction", &i, &start)));
|
retval << context.getActionBinding("#{sRestKey}");
|
||||||
else if((found = Check(temp, "nextpcrank", &i, &start)));
|
}
|
||||||
else if((found = Check(temp, "pcnextrank", &i, &start)));
|
else if((found = check(temp, "actionmenumode", &i, &start))){
|
||||||
else if((found = Check(temp, "pcrank", &i, &start)));
|
retval << context.getActionBinding("#{sInventory}");
|
||||||
else if((found = Check(temp, "rank", &i, &start)));
|
}
|
||||||
|
else if((found = check(temp, "actionactivate", &i, &start))){
|
||||||
/* uses pc in messageboxes */
|
retval << context.getActionBinding("#{sActivate}");
|
||||||
else if((found = Check(temp, "class", &i, &start))){
|
}
|
||||||
|
else if((found = check(temp, "actionjournal", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sJournal}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "actionforward", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sForward}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "pccrimelevel", &i, &start))){
|
||||||
|
retval << context.getPCBounty();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "actioncrouch", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sCrouch_Sneak}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "actionjump", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sJump}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "actionback", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sBack}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "actionuse", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sUse}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "actionrun", &i, &start))){
|
||||||
|
retval << context.getActionBinding("#{sRun}");
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "pcclass", &i, &start))){
|
||||||
retval << context.getPCClass();
|
retval << context.getPCClass();
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "race", &i, &start))){
|
else if((found = check(temp, "pcrace", &i, &start))){
|
||||||
retval << context.getPCRace();
|
retval << context.getPCRace();
|
||||||
}
|
}
|
||||||
else if((found = Check(temp, "name", &i, &start))){
|
else if((found = check(temp, "pcname", &i, &start))){
|
||||||
retval << context.getPCName();
|
retval << context.getPCName();
|
||||||
}
|
}
|
||||||
}
|
else if((found = check(temp, "cell", &i, &start))){
|
||||||
|
retval << context.getCurrentCellName();
|
||||||
/* Not a builtin, try global variables */
|
|
||||||
if(!found){
|
|
||||||
/* if list of globals is empty, grab it and sort it by descending string length */
|
|
||||||
if(globals.empty()){
|
|
||||||
globals = context.getGlobals();
|
|
||||||
sort(globals.begin(), globals.end(), longerStr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int j = 0; j < globals.size(); j++){
|
else if(eschar == '%' && !isBook) { // In Dialogue, not messagebox
|
||||||
if(globals[j].length() > temp.length()){ // Just in case there's a global with a huuuge name
|
if( (found = check(temp, "faction", &i, &start))){
|
||||||
std::string temp = text.substr(i+1, globals[j].length());
|
retval << context.getNPCFaction();
|
||||||
transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
|
}
|
||||||
|
else if((found = check(temp, "nextpcrank", &i, &start))){
|
||||||
|
retval << context.getPCNextRank();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "pcnextrank", &i, &start))){
|
||||||
|
retval << context.getPCNextRank();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "pcrank", &i, &start))){
|
||||||
|
retval << context.getPCRank();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "rank", &i, &start))){
|
||||||
|
retval << context.getNPCRank();
|
||||||
}
|
}
|
||||||
|
|
||||||
if((found = Check(temp, globals[j], &i, &start))){
|
else if((found = check(temp, "class", &i, &start))){
|
||||||
char type = context.getGlobalType(globals[j]);
|
retval << context.getNPCClass();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "race", &i, &start))){
|
||||||
|
retval << context.getNPCRace();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "name", &i, &start))){
|
||||||
|
retval << context.getNPCName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // In messagebox or book, not dialogue
|
||||||
|
|
||||||
switch(type){
|
/* empty outside dialogue */
|
||||||
case 's': retval << context.getGlobalShort(globals[j]); break;
|
if( (found = check(temp, "faction", &i, &start)));
|
||||||
case 'l': retval << context.getGlobalLong(globals[j]); break;
|
else if((found = check(temp, "nextpcrank", &i, &start)));
|
||||||
case 'f': retval << context.getGlobalFloat(globals[j]); break;
|
else if((found = check(temp, "pcnextrank", &i, &start)));
|
||||||
|
else if((found = check(temp, "pcrank", &i, &start)));
|
||||||
|
else if((found = check(temp, "rank", &i, &start)));
|
||||||
|
|
||||||
|
/* uses pc in messageboxes */
|
||||||
|
else if((found = check(temp, "class", &i, &start))){
|
||||||
|
retval << context.getPCClass();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "race", &i, &start))){
|
||||||
|
retval << context.getPCRace();
|
||||||
|
}
|
||||||
|
else if((found = check(temp, "name", &i, &start))){
|
||||||
|
retval << context.getPCName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not a builtin, try global variables */
|
||||||
|
if(!found){
|
||||||
|
/* if list of globals is empty, grab it and sort it by descending string length */
|
||||||
|
if(globals.empty()){
|
||||||
|
globals = context.getGlobals();
|
||||||
|
sort(globals.begin(), globals.end(), longerStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned int j = 0; j < globals.size(); j++){
|
||||||
|
if(globals[j].length() > temp.length()){ // Just in case there's a global with a huuuge name
|
||||||
|
std::string temp = text.substr(i+1, globals[j].length());
|
||||||
|
transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((found = check(temp, globals[j], &i, &start))){
|
||||||
|
char type = context.getGlobalType(globals[j]);
|
||||||
|
|
||||||
|
switch(type){
|
||||||
|
case 's': retval << context.getGlobalShort(globals[j]); break;
|
||||||
|
case 'l': retval << context.getGlobalLong(globals[j]); break;
|
||||||
|
case 'f': retval << context.getGlobalFloat(globals[j]); break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
/* Not found */
|
{
|
||||||
|
std::cerr << "Failed to replace escape character, with the following error: " << e.what() << std::endl;
|
||||||
|
std::cerr << "Full text below: " << std::endl << text << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not found, or error
|
||||||
if(!found){
|
if(!found){
|
||||||
/* leave unmodified */
|
/* leave unmodified */
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
|
@ -272,7 +272,7 @@ class NiSkinData : public Record
|
||||||
public:
|
public:
|
||||||
struct BoneTrafo
|
struct BoneTrafo
|
||||||
{
|
{
|
||||||
Ogre::Matrix3 rotation; // Rotation offset from bone?
|
Ogre::Matrix3 rotationScale; // Rotation offset from bone, non-uniform scale
|
||||||
Ogre::Vector3 trans; // Translation
|
Ogre::Vector3 trans; // Translation
|
||||||
float scale; // Probably scale (always 1)
|
float scale; // Probably scale (always 1)
|
||||||
};
|
};
|
||||||
|
@ -295,7 +295,7 @@ public:
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
trafo.rotation = nif->getMatrix3();
|
trafo.rotationScale = nif->getMatrix3();
|
||||||
trafo.trans = nif->getVector3();
|
trafo.trans = nif->getVector3();
|
||||||
trafo.scale = nif->getFloat();
|
trafo.scale = nif->getFloat();
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ public:
|
||||||
{
|
{
|
||||||
BoneInfo &bi = bones[i];
|
BoneInfo &bi = bones[i];
|
||||||
|
|
||||||
bi.trafo.rotation = nif->getMatrix3();
|
bi.trafo.rotationScale = nif->getMatrix3();
|
||||||
bi.trafo.trans = nif->getVector3();
|
bi.trafo.trans = nif->getVector3();
|
||||||
bi.trafo.scale = nif->getFloat();
|
bi.trafo.scale = nif->getFloat();
|
||||||
bi.unknown = nif->getVector4();
|
bi.unknown = nif->getVector4();
|
||||||
|
|
|
@ -133,7 +133,7 @@ public:
|
||||||
{
|
{
|
||||||
Transformation t;
|
Transformation t;
|
||||||
t.pos = getVector3();
|
t.pos = getVector3();
|
||||||
t.rotation = getMatrix3();
|
t.rotationScale = getMatrix3();
|
||||||
t.scale = getFloat();
|
t.scale = getFloat();
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace Nif
|
||||||
struct Transformation
|
struct Transformation
|
||||||
{
|
{
|
||||||
Ogre::Vector3 pos;
|
Ogre::Vector3 pos;
|
||||||
Ogre::Matrix3 rotation;
|
Ogre::Matrix3 rotationScale;
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
static const Transformation& getIdentity()
|
static const Transformation& getIdentity()
|
||||||
|
|
|
@ -42,8 +42,9 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
|
||||||
|
|
||||||
Ogre::Matrix4 Node::getLocalTransform() const
|
Ogre::Matrix4 Node::getLocalTransform() const
|
||||||
{
|
{
|
||||||
Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY);
|
Ogre::Matrix4 mat4 = Ogre::Matrix4(trafo.rotationScale);
|
||||||
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
|
mat4.setTrans(trafo.pos);
|
||||||
|
mat4.setScale(Ogre::Vector3(trafo.rotationScale[0][0], trafo.rotationScale[1][1], trafo.rotationScale[2][2]) * trafo.scale);
|
||||||
return mat4;
|
return mat4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,9 +138,10 @@ void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape
|
||||||
const Nif::NodeList &bones = skin->bones;
|
const Nif::NodeList &bones = skin->bones;
|
||||||
for(size_t b = 0;b < bones.length();b++)
|
for(size_t b = 0;b < bones.length();b++)
|
||||||
{
|
{
|
||||||
Ogre::Matrix4 mat;
|
const Ogre::Matrix3& rotationScale = data->bones[b].trafo.rotationScale;
|
||||||
mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale),
|
Ogre::Matrix4 mat (rotationScale);
|
||||||
Ogre::Quaternion(data->bones[b].trafo.rotation));
|
mat.setTrans(data->bones[b].trafo.trans);
|
||||||
|
mat.setScale(Ogre::Vector3(rotationScale[0][0], rotationScale[1][1], rotationScale[2][2]) * data->bones[b].trafo.scale);
|
||||||
mat = bones[b]->getWorldTransform() * mat;
|
mat = bones[b]->getWorldTransform() * mat;
|
||||||
|
|
||||||
const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights;
|
const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights;
|
||||||
|
|
|
@ -36,9 +36,17 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node,
|
||||||
if(parent) parent->addChild(bone);
|
if(parent) parent->addChild(bone);
|
||||||
mNifToOgreHandleMap[node->recIndex] = bone->getHandle();
|
mNifToOgreHandleMap[node->recIndex] = bone->getHandle();
|
||||||
|
|
||||||
bone->setOrientation(node->trafo.rotation);
|
// decompose the local transform into position, scale and orientation.
|
||||||
bone->setPosition(node->trafo.pos);
|
// this is required for cases where the rotationScale matrix includes scaling, which the NIF format allows :(
|
||||||
bone->setScale(Ogre::Vector3(node->trafo.scale));
|
// the code would look a bit nicer if Ogre allowed setting the transform matrix of a Bone directly, but we can't do that.
|
||||||
|
Ogre::Matrix4 mat(node->getLocalTransform());
|
||||||
|
Ogre::Vector3 position, scale;
|
||||||
|
Ogre::Quaternion orientation;
|
||||||
|
mat.decomposition(position, scale, orientation);
|
||||||
|
bone->setOrientation(orientation);
|
||||||
|
bone->setPosition(position);
|
||||||
|
bone->setScale(scale);
|
||||||
|
|
||||||
bone->setBindingPose();
|
bone->setBindingPose();
|
||||||
|
|
||||||
if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */
|
if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */
|
||||||
|
|
|
@ -142,10 +142,8 @@ void TerrainGrid::setVisible(bool visible)
|
||||||
|
|
||||||
Ogre::AxisAlignedBox TerrainGrid::getWorldBoundingBox (const Ogre::Vector2& center)
|
Ogre::AxisAlignedBox TerrainGrid::getWorldBoundingBox (const Ogre::Vector2& center)
|
||||||
{
|
{
|
||||||
float cellSize = getStorage()->getCellWorldSize();
|
int cellX = std::floor(center.x);
|
||||||
|
int cellY = std::floor(center.y);
|
||||||
int cellX = std::floor(center.x/cellSize);
|
|
||||||
int cellY = std::floor(center.y/cellSize);
|
|
||||||
|
|
||||||
Grid::iterator it = mGrid.find(std::make_pair(cellX, cellY));
|
Grid::iterator it = mGrid.find(std::make_pair(cellX, cellY));
|
||||||
if (it == mGrid.end())
|
if (it == mGrid.end())
|
||||||
|
|
Loading…
Reference in a new issue