Merge branch 'master' into pinned since added PR #1250

0.6.1
Andrei Kortunov 8 years ago
commit 72a16dc78b

@ -70,6 +70,7 @@ opencs_units (view/world
cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
bodypartcreator
) )
opencs_units_noqt (view/world opencs_units_noqt (view/world

@ -632,7 +632,7 @@ namespace CSVRender
getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix()); getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix());
} }
void OrbitCameraController::onActivate() void OrbitCameraController::reset()
{ {
mInitialized = false; mInitialized = false;
} }

@ -63,8 +63,6 @@ namespace CSVRender
protected: protected:
virtual void onActivate(){}
void addShortcut(CSMPrefs::Shortcut* shortcut); void addShortcut(CSMPrefs::Shortcut* shortcut);
private: private:
@ -159,9 +157,10 @@ namespace CSVRender
void update(double dt); void update(double dt);
private: /// \brief Flag controller to be re-initialized.
void reset();
void onActivate(); private:
void initialize(); void initialize();

@ -15,6 +15,7 @@
#include "../widget/scenetooltoggle.hpp" #include "../widget/scenetooltoggle.hpp"
#include "../widget/scenetooltoggle2.hpp" #include "../widget/scenetooltoggle2.hpp"
#include "cameracontroller.hpp"
#include "mask.hpp" #include "mask.hpp"
#include "tagbase.hpp" #include "tagbase.hpp"
@ -92,6 +93,8 @@ bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld:
mCellId = universalIdData.begin()->getId(); mCellId = universalIdData.begin()->getId();
mCell.reset (new Cell (getDocument().getData(), mRootNode, mCellId)); mCell.reset (new Cell (getDocument().getData(), mRootNode, mCellId));
mCamPositionSet = false;
mOrbitCamControl->reset();
update(); update();
emit cellChanged(*universalIdData.begin()); emit cellChanged(*universalIdData.begin());

@ -0,0 +1,54 @@
#include "bodypartcreator.hpp"
#include <QCheckBox>
#include "../../model/world/data.hpp"
#include "../../model/world/universalid.hpp"
std::string CSVWorld::BodyPartCreator::getId() const
{
std::string id = CSVWorld::GenericCreator::getId();
if (mFirstPerson->isChecked())
{
id += ".1st";
}
return id;
}
CSVWorld::BodyPartCreator::BodyPartCreator(
CSMWorld::Data& data,
QUndoStack& undoStack,
const CSMWorld::UniversalId& id
) : GenericCreator(data, undoStack, id)
{
mFirstPerson = new QCheckBox("First Person", this);
insertBeforeButtons(mFirstPerson, false);
connect(mFirstPerson, SIGNAL(clicked(bool)), this, SLOT(checkboxClicked()));
}
std::string CSVWorld::BodyPartCreator::getErrors() const
{
std::string errors;
std::string id = getId();
if (getData().hasId(id))
{
errors = "ID is already in use";
}
return errors;
}
void CSVWorld::BodyPartCreator::reset()
{
CSVWorld::GenericCreator::reset();
mFirstPerson->setChecked(false);
}
void CSVWorld::BodyPartCreator::checkboxClicked()
{
update();
}

@ -0,0 +1,47 @@
#ifndef BODYPARTCREATOR_HPP
#define BODYPARTCREATOR_HPP
class QCheckBox;
#include "genericcreator.hpp"
namespace CSMWorld
{
class Data;
class UniversalId;
}
namespace CSVWorld
{
/// \brief Record creator for body parts.
class BodyPartCreator : public GenericCreator
{
Q_OBJECT
QCheckBox *mFirstPerson;
private:
/// \return ID entered by user.
virtual std::string getId() const;
public:
BodyPartCreator(
CSMWorld::Data& data,
QUndoStack& undoStack,
const CSMWorld::UniversalId& id);
/// \return Error description for current user input.
virtual std::string getErrors() const;
/// \brief Clear ID and checkbox input widgets.
virtual void reset();
private slots:
void checkboxClicked();
};
}
#endif // BODYPARTCREATOR_HPP

@ -45,14 +45,20 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager)
: GenericCreator (data, undoStack, id) : GenericCreator (data, undoStack, id)
{ {
QLabel *label = new QLabel ("Topic", this); // Determine if we're dealing with topics or journals.
insertBeforeButtons (label, false);
CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic;
QString labelText = "Topic";
if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos) if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos)
{ {
displayType = CSMWorld::ColumnBase::Display_Journal; displayType = CSMWorld::ColumnBase::Display_Journal;
labelText = "Journal";
} }
QLabel *label = new QLabel (labelText, this);
insertBeforeButtons (label, false);
// Add topic/journal ID input with auto-completion.
// Only existing topic/journal IDs are accepted so no ID validation is performed.
mTopic = new CSVWidget::DropLineEdit(displayType, this); mTopic = new CSVWidget::DropLineEdit(displayType, this);
mTopic->setCompleter(completionManager.getCompleter(displayType).get()); mTopic->setCompleter(completionManager.getCompleter(displayType).get());
insertBeforeButtons (mTopic, true); insertBeforeButtons (mTopic, true);

@ -10,7 +10,6 @@
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../widget/droplineedit.hpp" #include "../widget/droplineedit.hpp"
#include "idvalidator.hpp"
std::string CSVWorld::PathgridCreator::getId() const std::string CSVWorld::PathgridCreator::getId() const
{ {
@ -28,20 +27,19 @@ CSVWorld::PathgridCreator::PathgridCreator(
CSMWorld::Data& data, CSMWorld::Data& data,
QUndoStack& undoStack, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, const CSMWorld::UniversalId& id,
CSMWorld::IdCompletionManager& completionManager, CSMWorld::IdCompletionManager& completionManager
bool relaxedIdRules ) : GenericCreator(data, undoStack, id)
) : GenericCreator(data, undoStack, id, relaxedIdRules)
{ {
setManualEditing(false); setManualEditing(false);
QLabel *label = new QLabel("Cell ID", this); QLabel *label = new QLabel("Cell", this);
insertBeforeButtons(label, false); insertBeforeButtons(label, false);
// Add cell ID input with auto-completion. // Add cell ID input with auto-completion.
// Only existing cell IDs are accepted so no ID validation is performed.
CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Cell; CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Cell;
mCell = new CSVWidget::DropLineEdit(displayType, this); mCell = new CSVWidget::DropLineEdit(displayType, this);
mCell->setCompleter(completionManager.getCompleter(displayType).get()); mCell->setCompleter(completionManager.getCompleter(displayType).get());
mCell->setValidator(new IdValidator(relaxedIdRules, this));
insertBeforeButtons(mCell, true); insertBeforeButtons(mCell, true);
connect(mCell, SIGNAL (textChanged(const QString&)), this, SLOT (cellChanged())); connect(mCell, SIGNAL (textChanged(const QString&)), this, SLOT (cellChanged()));
@ -65,8 +63,6 @@ std::string CSVWorld::PathgridCreator::getErrors() const
std::string cellId = getId(); std::string cellId = getId();
// Check user input for any errors. // Check user input for any errors.
// The last two checks, cell with existing pathgrid and non-existent cell,
// shouldn't be needed but we absolutely want to make sure they never happen.
std::string errors; std::string errors;
if (cellId.empty()) if (cellId.empty())
{ {

@ -44,8 +44,7 @@ namespace CSVWorld
CSMWorld::Data& data, CSMWorld::Data& data,
QUndoStack& undoStack, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, const CSMWorld::UniversalId& id,
CSMWorld::IdCompletionManager& completionManager, CSMWorld::IdCompletionManager& completionManager);
bool relaxedIdRules = false);
/// \brief Set cell ID input widget to ID of record to be cloned. /// \brief Set cell ID input widget to ID of record to be cloned.
/// \param originId Cell ID to be cloned. /// \param originId Cell ID to be cloned.

@ -35,6 +35,8 @@ CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack&
QLabel *label = new QLabel ("Cell", this); QLabel *label = new QLabel ("Cell", this);
insertBeforeButtons (label, false); insertBeforeButtons (label, false);
// Add cell ID input with auto-completion.
// Only existing cell IDs are accepted so no ID validation is performed.
mCell = new CSVWidget::DropLineEdit(CSMWorld::ColumnBase::Display_Cell, this); mCell = new CSVWidget::DropLineEdit(CSMWorld::ColumnBase::Display_Cell, this);
mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get()); mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get());
insertBeforeButtons (mCell, true); insertBeforeButtons (mCell, true);

@ -29,15 +29,16 @@ CSVWorld::StartScriptCreator::StartScriptCreator(
QUndoStack &undoStack, QUndoStack &undoStack,
const CSMWorld::UniversalId &id, const CSMWorld::UniversalId &id,
CSMWorld::IdCompletionManager& completionManager CSMWorld::IdCompletionManager& completionManager
) : GenericCreator(data, undoStack, id, true) ) : GenericCreator(data, undoStack, id)
{ {
setManualEditing(false); setManualEditing(false);
// Add script ID input label. // Add script ID input label.
QLabel *label = new QLabel("Script ID", this); QLabel *label = new QLabel("Script", this);
insertBeforeButtons(label, false); insertBeforeButtons(label, false);
// Add script ID input with auto-completion. // Add script ID input with auto-completion.
// Only existing script IDs are accepted so no ID validation is performed.
CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Script; CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Script;
mScript = new CSVWidget::DropLineEdit(displayType, this); mScript = new CSVWidget::DropLineEdit(displayType, this);
mScript->setCompleter(completionManager.getCompleter(displayType).get()); mScript->setCompleter(completionManager.getCompleter(displayType).get());

@ -17,6 +17,7 @@
#include "infocreator.hpp" #include "infocreator.hpp"
#include "pathgridcreator.hpp" #include "pathgridcreator.hpp"
#include "previewsubview.hpp" #include "previewsubview.hpp"
#include "bodypartcreator.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{ {
@ -41,7 +42,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Birthsigns,
CSMWorld::UniversalId::Type_Spells, CSMWorld::UniversalId::Type_Spells,
CSMWorld::UniversalId::Type_Enchantments, CSMWorld::UniversalId::Type_Enchantments,
CSMWorld::UniversalId::Type_BodyParts,
CSMWorld::UniversalId::Type_SoundGens, CSMWorld::UniversalId::Type_SoundGens,
CSMWorld::UniversalId::Type_None // end marker CSMWorld::UniversalId::Type_None // end marker
@ -51,6 +51,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (sTableTypes[i], manager.add (sTableTypes[i],
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator> >); new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator> >);
manager.add (CSMWorld::UniversalId::Type_BodyParts,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<BodyPartCreator> >);
manager.add (CSMWorld::UniversalId::Type_StartScripts, manager.add (CSMWorld::UniversalId::Type_StartScripts,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, StartScriptCreatorFactory>); new CSVDoc::SubViewFactoryWithCreator<TableSubView, StartScriptCreatorFactory>);
@ -129,7 +132,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Sound, CSMWorld::UniversalId::Type_Sound,
CSMWorld::UniversalId::Type_Faction, CSMWorld::UniversalId::Type_Faction,
CSMWorld::UniversalId::Type_Enchantment, CSMWorld::UniversalId::Type_Enchantment,
CSMWorld::UniversalId::Type_BodyPart,
CSMWorld::UniversalId::Type_SoundGen, CSMWorld::UniversalId::Type_SoundGen,
CSMWorld::UniversalId::Type_None // end marker CSMWorld::UniversalId::Type_None // end marker
@ -140,6 +142,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
CreatorFactory<GenericCreator> > (false)); CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_BodyPart,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<BodyPartCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_StartScript, manager.add (CSMWorld::UniversalId::Type_StartScript,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, StartScriptCreatorFactory>(false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, StartScriptCreatorFactory>(false));

@ -323,6 +323,9 @@ namespace MWClass
if (MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage, attackStrength)) if (MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage, attackStrength))
damage = 0; damage = 0;
if (victim == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState())
damage = 0;
MWMechanics::diseaseContact(victim, ptr); MWMechanics::diseaseContact(victim, ptr);
victim.getClass().onHit(victim, damage, healthdmg, weapon, ptr, hitPosition, true); victim.getClass().onHit(victim, damage, healthdmg, weapon, ptr, hitPosition, true);
@ -371,6 +374,11 @@ namespace MWClass
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1); ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
} }
bool godmode = object == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if (godmode)
damage = 0;
if (!successful) if (!successful)
{ {
// Missed // Missed
@ -405,7 +413,7 @@ namespace MWClass
if(ishealth) if(ishealth)
{ {
if (!attacker.isEmpty()) if (!attacker.isEmpty() && !godmode)
{ {
damage = scaleDamage(damage, attacker, ptr); damage = scaleDamage(damage, attacker, ptr);
MWBase::Environment::get().getWorld()->spawnBloodEffect(ptr, hitPosition); MWBase::Environment::get().getWorld()->spawnBloodEffect(ptr, hitPosition);

@ -651,6 +651,9 @@ namespace MWClass
if (MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage, attackStrength)) if (MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage, attackStrength))
damage = 0; damage = 0;
if (victim == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState())
damage = 0;
MWMechanics::diseaseContact(victim, ptr); MWMechanics::diseaseContact(victim, ptr);
othercls.onHit(victim, damage, healthdmg, weapon, ptr, hitPosition, true); othercls.onHit(victim, damage, healthdmg, weapon, ptr, hitPosition, true);
@ -717,6 +720,11 @@ namespace MWClass
if (damage < 0.001f) if (damage < 0.001f)
damage = 0; damage = 0;
bool godmode = ptr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if (godmode)
damage = 0;
if (damage > 0.0f && !attacker.isEmpty()) if (damage > 0.0f && !attacker.isEmpty())
{ {
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying // 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
@ -802,7 +810,7 @@ namespace MWClass
if (ishealth) if (ishealth)
{ {
if (!attacker.isEmpty()) if (!attacker.isEmpty() && !godmode)
damage = scaleDamage(damage, attacker, ptr); damage = scaleDamage(damage, attacker, ptr);
if (damage > 0.0f) if (damage > 0.0f)

@ -777,6 +777,12 @@ namespace MWGui
mLastScrollWindowCoordinates = currentCoordinates; mLastScrollWindowCoordinates = currentCoordinates;
} }
void MapWindow::setVisible(bool visible)
{
WindowBase::setVisible(visible);
mButton->setVisible(visible && MWBase::Environment::get().getWindowManager()->isGuiMode());
}
void MapWindow::renderGlobalMap() void MapWindow::renderGlobalMap()
{ {
mGlobalMapRender->render(); mGlobalMapRender->render();

@ -204,6 +204,7 @@ namespace MWGui
void setCellName(const std::string& cellName); void setCellName(const std::string& cellName);
virtual void setAlpha(float alpha); virtual void setAlpha(float alpha);
void setVisible(bool visible);
void renderGlobalMap(); void renderGlobalMap();

@ -12,6 +12,7 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/containerstore.hpp" #include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
@ -137,10 +138,16 @@ void Recharge::onItemClicked(MyGUI::Widget *sender, const MWWorld::Ptr& item)
item.getCellRef().setEnchantmentCharge( item.getCellRef().setEnchantmentCharge(
std::min(item.getCellRef().getEnchantmentCharge() + restored, static_cast<float>(enchantment->mData.mCharge))); std::min(item.getCellRef().getEnchantmentCharge() + restored, static_cast<float>(enchantment->mData.mCharge)));
MWBase::Environment::get().getSoundManager()->playSound("Enchant Success",1,1);
player.getClass().getContainerStore(player).restack(item); player.getClass().getContainerStore(player).restack(item);
player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0); player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0);
} }
else
{
MWBase::Environment::get().getSoundManager()->playSound("Enchant Fail",1,1);
}
gem.getContainerStore()->remove(gem, 1, player); gem.getContainerStore()->remove(gem, 1, player);

@ -11,6 +11,7 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
@ -62,6 +63,8 @@ void Repair::exit()
void Repair::startRepairItem(const MWWorld::Ptr &item) void Repair::startRepairItem(const MWWorld::Ptr &item)
{ {
MWBase::Environment::get().getSoundManager()->playSound("Item Repair Up",1,1);
mRepair.setTool(item); mRepair.setTool(item);
mToolIcon->setItem(item); mToolIcon->setItem(item);

@ -815,7 +815,10 @@ namespace MWMechanics
timeLeft = 0.0f; timeLeft = 0.0f;
stats.setTimeToStartDrowning(timeLeft); stats.setTimeToStartDrowning(timeLeft);
} }
if(timeLeft == 0.0f)
bool godmode = ptr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if(timeLeft == 0.0f && !godmode)
{ {
// If drowning, apply 3 points of damage per second // If drowning, apply 3 points of damage per second
static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat(); static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat();

@ -1574,6 +1574,8 @@ void CharacterController::update(float duration)
updateMagicEffects(); updateMagicEffects();
bool godmode = mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if(!cls.isActor()) if(!cls.isActor())
updateAnimQueue(); updateAnimQueue();
else if(!cls.getCreatureStats(mPtr).isDead()) else if(!cls.getCreatureStats(mPtr).isDead())
@ -1691,8 +1693,12 @@ void CharacterController::update(float duration)
} }
fatigueLoss *= duration; fatigueLoss *= duration;
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue(); DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss, fatigue.getCurrent() < 0);
cls.getCreatureStats(mPtr).setFatigue(fatigue); if (!godmode)
{
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss, fatigue.getCurrent() < 0);
cls.getCreatureStats(mPtr).setFatigue(fatigue);
}
if(sneak || inwater || flying) if(sneak || inwater || flying)
vec.z() = 0.0f; vec.z() = 0.0f;
@ -1748,8 +1754,12 @@ void CharacterController::update(float duration)
if (normalizedEncumbrance > 1) if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1; normalizedEncumbrance = 1;
const float fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; const float fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
cls.getCreatureStats(mPtr).setFatigue(fatigue); if (!godmode)
{
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
cls.getCreatureStats(mPtr).setFatigue(fatigue);
}
} }
} }
else if(mJumpState == JumpState_InAir) else if(mJumpState == JumpState_InAir)
@ -1760,16 +1770,22 @@ void CharacterController::update(float duration)
float height = cls.getCreatureStats(mPtr).land(); float height = cls.getCreatureStats(mPtr).land();
float healthLost = getFallDamage(mPtr, height); float healthLost = getFallDamage(mPtr, height);
bool godmode = mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if (healthLost > 0.0f) if (healthLost > 0.0f)
{ {
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm(); const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();
// inflict fall damages // inflict fall damages
DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth(); if (!godmode)
float realHealthLost = static_cast<float>(healthLost * (1.0f - 0.25f * fatigueTerm)); {
health.setCurrent(health.getCurrent() - realHealthLost); DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth();
cls.getCreatureStats(mPtr).setHealth(health); float realHealthLost = static_cast<float>(healthLost * (1.0f - 0.25f * fatigueTerm));
cls.onHit(mPtr, realHealthLost, true, MWWorld::Ptr(), MWWorld::Ptr(), osg::Vec3f(), true); health.setCurrent(health.getCurrent() - realHealthLost);
cls.getCreatureStats(mPtr).setHealth(health);
cls.onHit(mPtr, realHealthLost, true, MWWorld::Ptr(), MWWorld::Ptr(), osg::Vec3f(), true);
}
const int acrobaticsSkill = cls.getSkill(mPtr, ESM::Skill::Acrobatics); const int acrobaticsSkill = cls.getSkill(mPtr, ESM::Skill::Acrobatics);
if (healthLost > (acrobaticsSkill * fatigueTerm)) if (healthLost > (acrobaticsSkill * fatigueTerm))

@ -327,11 +327,17 @@ namespace MWMechanics
{ {
int weaphealth = weapon.getClass().getItemHealth(weapon); int weaphealth = weapon.getClass().getItemHealth(weapon);
const float fWeaponDamageMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWeaponDamageMult")->getFloat(); bool godmode = attacker == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
float x = std::max(1.f, fWeaponDamageMult * damage);
weaphealth -= std::min(int(x), weaphealth); // weapon condition does not degrade when godmode is on
weapon.getCellRef().setCharge(weaphealth); if (!godmode)
{
const float fWeaponDamageMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWeaponDamageMult")->getFloat();
float x = std::max(1.f, fWeaponDamageMult * damage);
weaphealth -= std::min(int(x), weaphealth);
weapon.getCellRef().setCharge(weaphealth);
}
// Weapon broken? unequip it // Weapon broken? unequip it
if (weaphealth == 0) if (weaphealth == 0)
@ -405,11 +411,17 @@ namespace MWMechanics
CreatureStats& stats = attacker.getClass().getCreatureStats(attacker); CreatureStats& stats = attacker.getClass().getCreatureStats(attacker);
MWMechanics::DynamicStat<float> fatigue = stats.getFatigue(); MWMechanics::DynamicStat<float> fatigue = stats.getFatigue();
const float normalizedEncumbrance = attacker.getClass().getNormalizedEncumbrance(attacker); const float normalizedEncumbrance = attacker.getClass().getNormalizedEncumbrance(attacker);
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon.isEmpty()) bool godmode = attacker == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
fatigueLoss += weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); if (!godmode)
stats.setFatigue(fatigue); {
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon.isEmpty())
fatigueLoss += weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
stats.setFatigue(fatigue);
}
} }
bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim) bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim)

@ -99,6 +99,9 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), mTool.getCellRef().getRefId())) if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), mTool.getCellRef().getRefId()))
{ {
mTool = *iter; mTool = *iter;
MWBase::Environment::get().getSoundManager()->playSound("Item Repair Up",1,1);
break; break;
} }
} }

@ -46,11 +46,6 @@ namespace MWMechanics
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap) float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap)
{ {
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude())
return 0;
float y = std::numeric_limits<float>::max(); float y = std::numeric_limits<float>::max();
float lowestSkill = 0; float lowestSkill = 0;
@ -80,6 +75,13 @@ namespace MWMechanics
} }
} }
bool godmode = actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude()&& !godmode)
return 0;
if (spell->mData.mType == ESM::Spell::ST_Power) if (spell->mData.mType == ESM::Spell::ST_Power)
return stats.getSpells().canUsePower(spell) ? 100 : 0; return stats.getSpells().canUsePower(spell) ? 100 : 0;
@ -89,6 +91,11 @@ namespace MWMechanics
if (spell->mData.mFlags & ESM::Spell::F_Always) if (spell->mData.mFlags & ESM::Spell::F_Always)
return 100; return 100;
if (godmode)
{
return 100;
}
float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude(); float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
@ -709,14 +716,19 @@ namespace MWMechanics
mStack = false; mStack = false;
bool godmode = mCaster == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
// Check if there's enough charge left // Check if there's enough charge left
if (enchantment->mData.mType == ESM::Enchantment::WhenUsed || enchantment->mData.mType == ESM::Enchantment::WhenStrikes) if (enchantment->mData.mType == ESM::Enchantment::WhenUsed || enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
{ {
const int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), mCaster); int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), mCaster);
if (item.getCellRef().getEnchantmentCharge() == -1) if (item.getCellRef().getEnchantmentCharge() == -1)
item.getCellRef().setEnchantmentCharge(static_cast<float>(enchantment->mData.mCharge)); item.getCellRef().setEnchantmentCharge(static_cast<float>(enchantment->mData.mCharge));
if (godmode)
castCost = 0;
if (item.getCellRef().getEnchantmentCharge() < castCost) if (item.getCellRef().getEnchantmentCharge() < castCost)
{ {
if (mCaster == getPlayer()) if (mCaster == getPlayer())
@ -746,8 +758,10 @@ namespace MWMechanics
if (mCaster == getPlayer()) if (mCaster == getPlayer())
mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 1); mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 1);
} }
if (enchantment->mData.mType == ESM::Enchantment::CastOnce) if (enchantment->mData.mType == ESM::Enchantment::CastOnce && !godmode)
{
item.getContainerStore()->remove(item, 1, mCaster); item.getContainerStore()->remove(item, 1, mCaster);
}
else if (enchantment->mData.mType != ESM::Enchantment::WhenStrikes) else if (enchantment->mData.mType != ESM::Enchantment::WhenStrikes)
{ {
if (mCaster == getPlayer()) if (mCaster == getPlayer())
@ -797,44 +811,50 @@ namespace MWMechanics
int school = 0; int school = 0;
bool godmode = mCaster == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if (mCaster.getClass().isActor() && !mAlwaysSucceed) if (mCaster.getClass().isActor() && !mAlwaysSucceed)
{ {
school = getSpellSchool(spell, mCaster); school = getSpellSchool(spell, mCaster);
CreatureStats& stats = mCaster.getClass().getCreatureStats(mCaster); CreatureStats& stats = mCaster.getClass().getCreatureStats(mCaster);
// Reduce fatigue (note that in the vanilla game, both GMSTs are 0, and there's no fatigue loss) if (!godmode)
static const float fFatigueSpellBase = store.get<ESM::GameSetting>().find("fFatigueSpellBase")->getFloat(); {
static const float fFatigueSpellMult = store.get<ESM::GameSetting>().find("fFatigueSpellMult")->getFloat(); // Reduce fatigue (note that in the vanilla game, both GMSTs are 0, and there's no fatigue loss)
DynamicStat<float> fatigue = stats.getFatigue(); static const float fFatigueSpellBase = store.get<ESM::GameSetting>().find("fFatigueSpellBase")->getFloat();
const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster); static const float fFatigueSpellMult = store.get<ESM::GameSetting>().find("fFatigueSpellMult")->getFloat();
float fatigueLoss = spell->mData.mCost * (fFatigueSpellBase + normalizedEncumbrance * fFatigueSpellMult); DynamicStat<float> fatigue = stats.getFatigue();
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); stats.setFatigue(fatigue); const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster);
bool fail = false; float fatigueLoss = spell->mData.mCost * (fFatigueSpellBase + normalizedEncumbrance * fFatigueSpellMult);
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); stats.setFatigue(fatigue);
// Check success bool fail = false;
if (!(mCaster == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState()))
{ // Check success
float successChance = getSpellSuccessChance(spell, mCaster); if (!(mCaster == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState()))
if (Misc::Rng::roll0to99() >= successChance)
{ {
if (mCaster == getPlayer()) float successChance = getSpellSuccessChance(spell, mCaster);
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}"); if (Misc::Rng::roll0to99() >= successChance)
fail = true; {
if (mCaster == getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
fail = true;
}
} }
}
if (fail) if (fail)
{ {
// Failure sound // Failure sound
static const std::string schools[] = { static const std::string schools[] = {
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
}; };
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
sndMgr->playSound3D(mCaster, "Spell Failure " + schools[school], 1.0f, 1.0f); sndMgr->playSound3D(mCaster, "Spell Failure " + schools[school], 1.0f, 1.0f);
return false; return false;
}
} }
// A power can be used once per 24h // A power can be used once per 24h
@ -1042,6 +1062,8 @@ namespace MWMechanics
bool receivedMagicDamage = false; bool receivedMagicDamage = false;
bool godmode = actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
switch (effectKey.mId) switch (effectKey.mId)
{ {
case ESM::MagicEffect::DamageAttribute: case ESM::MagicEffect::DamageAttribute:
@ -1064,21 +1086,34 @@ namespace MWMechanics
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::RestoreHealth, magnitude); adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::RestoreHealth, magnitude);
break; break;
case ESM::MagicEffect::DamageHealth: case ESM::MagicEffect::DamageHealth:
receivedMagicDamage = true; if (!godmode)
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude); {
break; receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
}
case ESM::MagicEffect::DamageMagicka: case ESM::MagicEffect::DamageMagicka:
case ESM::MagicEffect::DamageFatigue: case ESM::MagicEffect::DamageFatigue:
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude); if (!godmode)
{
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
}
break; break;
case ESM::MagicEffect::AbsorbHealth: case ESM::MagicEffect::AbsorbHealth:
if (magnitude > 0.f) if (!godmode)
receivedMagicDamage = true; {
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude); if (magnitude > 0.f)
break; receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
}
case ESM::MagicEffect::AbsorbMagicka: case ESM::MagicEffect::AbsorbMagicka:
case ESM::MagicEffect::AbsorbFatigue: case ESM::MagicEffect::AbsorbFatigue:
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude); if (!godmode)
{
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
}
break; break;
case ESM::MagicEffect::DisintegrateArmor: case ESM::MagicEffect::DisintegrateArmor:
@ -1123,9 +1158,13 @@ namespace MWMechanics
if (weather > 1) if (weather > 1)
damageScale *= fMagicSunBlockedMult; damageScale *= fMagicSunBlockedMult;
adjustDynamicStat(creatureStats, 0, -magnitude * damageScale); if (!godmode)
if (magnitude * damageScale > 0.f) {
receivedMagicDamage = true; adjustDynamicStat(creatureStats, 0, -magnitude * damageScale);
if (magnitude * damageScale > 0.f)
receivedMagicDamage = true;
}
break; break;
} }
@ -1134,8 +1173,12 @@ namespace MWMechanics
case ESM::MagicEffect::FrostDamage: case ESM::MagicEffect::FrostDamage:
case ESM::MagicEffect::Poison: case ESM::MagicEffect::Poison:
{ {
adjustDynamicStat(creatureStats, 0, -magnitude); if (!godmode)
receivedMagicDamage = true; {
adjustDynamicStat(creatureStats, 0, -magnitude);
receivedMagicDamage = true;
}
break; break;
} }

@ -2340,12 +2340,16 @@ namespace MWWorld
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.isDead()) if (stats.isDead())
continue; continue;
mPhysics->markAsNonSolid (object);
if (actor == getPlayerPtr() && MWBase::Environment::get().getWorld()->getGodModeState())
return;
MWMechanics::DynamicStat<float> health = stats.getHealth(); MWMechanics::DynamicStat<float> health = stats.getHealth();
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
stats.setHealth(health); stats.setHealth(health);
mPhysics->markAsNonSolid (object);
if (healthPerSecond > 0.0f) if (healthPerSecond > 0.0f)
{ {
if (actor == getPlayerPtr()) if (actor == getPlayerPtr())
@ -2370,12 +2374,16 @@ namespace MWWorld
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.isDead()) if (stats.isDead())
continue; continue;
mPhysics->markAsNonSolid (object);
if (actor == getPlayerPtr() && MWBase::Environment::get().getWorld()->getGodModeState())
return;
MWMechanics::DynamicStat<float> health = stats.getHealth(); MWMechanics::DynamicStat<float> health = stats.getHealth();
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
stats.setHealth(health); stats.setHealth(health);
mPhysics->markAsNonSolid (object);
if (healthPerSecond > 0.0f) if (healthPerSecond > 0.0f)
{ {
if (actor == getPlayerPtr()) if (actor == getPlayerPtr())

@ -311,22 +311,6 @@ namespace Compiler
return true; return true;
} }
// die in a fire, Morrowind script compiler!
if (const Extensions *extensions = getContext().getExtensions())
{
if (getContext().isJournalId (name2))
{
// JournalID used as an argument. Use the index of that JournalID
Generator::pushString (mCode, mLiterals, name2);
int keyword = extensions->searchKeyword ("getjournalindex");
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit, 0);
mNextOperand = false;
mOperands.push_back ('l');
return true;
}
}
if (mExplicit.empty() && getContext().isId (name2)) if (mExplicit.empty() && getContext().isId (name2))
{ {
mExplicit = name2; mExplicit = name2;

@ -127,9 +127,7 @@ std::string Misc::ResourceHelpers::correctBookartPath(const std::string &resPath
std::string Misc::ResourceHelpers::correctActorModelPath(const std::string &resPath, const VFS::Manager* vfs) std::string Misc::ResourceHelpers::correctActorModelPath(const std::string &resPath, const VFS::Manager* vfs)
{ {
std::string mdlname = resPath; std::string mdlname = resPath;
std::string::size_type p = mdlname.rfind('\\'); std::string::size_type p = mdlname.find_last_of("/\\");
if(p == std::string::npos)
p = mdlname.rfind('/');
if(p != std::string::npos) if(p != std::string::npos)
mdlname.insert(mdlname.begin()+p+1, 'x'); mdlname.insert(mdlname.begin()+p+1, 'x');
else else

@ -8,3 +8,6 @@ resources=${OPENMW_RESOURCE_FILES}
script-blacklist=Museum script-blacklist=Museum
script-blacklist=MockChangeScript script-blacklist=MockChangeScript
script-blacklist=doortestwarp script-blacklist=doortestwarp
script-blacklist=WereChange2Script
script-blacklist=wereDreamScript2
script-blacklist=wereDreamScript3

@ -9,3 +9,6 @@ resources=./resources
script-blacklist=Museum script-blacklist=Museum
script-blacklist=MockChangeScript script-blacklist=MockChangeScript
script-blacklist=doortestwarp script-blacklist=doortestwarp
script-blacklist=WereChange2Script
script-blacklist=wereDreamScript2
script-blacklist=wereDreamScript3

Loading…
Cancel
Save