forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
33d905dc03
42 changed files with 320 additions and 144 deletions
|
@ -505,6 +505,9 @@ void OMW::Engine::activate()
|
|||
if (ptr.getClass().getName(ptr) == "") // objects without name presented to user can never be activated
|
||||
return;
|
||||
|
||||
if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat())
|
||||
return;
|
||||
|
||||
MWBase::Environment::get().getWorld()->activate(ptr, MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||
}
|
||||
|
||||
|
|
|
@ -205,6 +205,8 @@ namespace MWBase
|
|||
|
||||
/// Resurrects the player if necessary
|
||||
virtual void keepPlayerAlive() = 0;
|
||||
|
||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -388,6 +388,7 @@ namespace MWBase
|
|||
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
|
||||
|
||||
virtual void togglePOV() = 0;
|
||||
virtual bool isFirstPerson() const = 0;
|
||||
virtual void togglePreviewMode(bool enable) = 0;
|
||||
virtual bool toggleVanityMode(bool enable) = 0;
|
||||
virtual void allowVanityMode(bool allow) = 0;
|
||||
|
|
|
@ -346,10 +346,11 @@ namespace MWClass
|
|||
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
|
||||
}
|
||||
|
||||
if(!object.isEmpty())
|
||||
getCreatureStats(ptr).setLastHitAttemptObject(object.getClass().getId(object));
|
||||
|
||||
if(!successful)
|
||||
{
|
||||
// TODO: Handle HitAttemptOnMe script function
|
||||
|
||||
// Missed
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "miss", 1.0f, 1.0f);
|
||||
return;
|
||||
|
@ -674,13 +675,12 @@ namespace MWClass
|
|||
std::vector<const ESM::SoundGenerator*> sounds;
|
||||
sounds.reserve(8);
|
||||
|
||||
std::string ptrid = Creature::getId(ptr);
|
||||
MWWorld::LiveCellRef<ESM::Creature>* ref = ptr.get<ESM::Creature>();
|
||||
|
||||
MWWorld::Store<ESM::SoundGenerator>::iterator sound = store.begin();
|
||||
while(sound != store.end())
|
||||
{
|
||||
if(type == sound->mType && !sound->mCreature.empty() &&
|
||||
Misc::StringUtils::ciEqual(ptrid.substr(0, sound->mCreature.size()),
|
||||
sound->mCreature))
|
||||
if (type == sound->mType && !sound->mCreature.empty() && Misc::StringUtils::ciEqual(ref->mBase->mOriginal, sound->mCreature))
|
||||
sounds.push_back(&*sound);
|
||||
++sound;
|
||||
}
|
||||
|
|
|
@ -654,10 +654,11 @@ namespace MWClass
|
|||
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
|
||||
}
|
||||
|
||||
if(!object.isEmpty())
|
||||
getCreatureStats(ptr).setLastHitAttemptObject(object.getClass().getId(object));
|
||||
|
||||
if(!successful)
|
||||
{
|
||||
// TODO: Handle HitAttemptOnMe script function
|
||||
|
||||
// Missed
|
||||
sndMgr->playSound3D(ptr, "miss", 1.0f, 1.0f);
|
||||
return;
|
||||
|
@ -1002,37 +1003,6 @@ namespace MWClass
|
|||
return x;
|
||||
}
|
||||
|
||||
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||
|
||||
const float fallDistanceMin = store.find("fFallDamageDistanceMin")->getFloat();
|
||||
|
||||
if (fallHeight >= fallDistanceMin)
|
||||
{
|
||||
const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).getMagnitude();
|
||||
const float fallAcroBase = store.find("fFallAcroBase")->getFloat();
|
||||
const float fallAcroMult = store.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat();
|
||||
const float fallDistanceMult = store.find("fFallDistanceMult")->getFloat();
|
||||
|
||||
float x = fallHeight - fallDistanceMin;
|
||||
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
|
||||
x = std::max(0.0f, x);
|
||||
|
||||
float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill);
|
||||
x = fallDistanceBase + fallDistanceMult * x;
|
||||
x *= a;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ensureCustomData (ptr);
|
||||
|
|
|
@ -104,9 +104,6 @@ namespace MWClass
|
|||
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
||||
///< Return jump velocity (not accounting for movement)
|
||||
|
||||
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
|
||||
///< Return amount of health points lost when falling
|
||||
|
||||
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
|
||||
///< Return desired movement.
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace MWDialogue
|
|||
success = false;
|
||||
}
|
||||
|
||||
if (!success && mScriptVerbose)
|
||||
if (!success)
|
||||
{
|
||||
std::cerr
|
||||
<< "compiling failed (dialogue script)" << std::endl
|
||||
|
|
|
@ -109,8 +109,8 @@ namespace MWGui
|
|||
mCharge->setCaption(boost::lexical_cast<std::string>(mEnchanting.getGemCharge()));
|
||||
|
||||
std::stringstream castCost;
|
||||
castCost << std::setprecision(1) << std::fixed << mEnchanting.getCastCost();
|
||||
mCastCost->setCaption(boost::lexical_cast<std::string>(castCost.str()));
|
||||
castCost << mEnchanting.getCastCost();
|
||||
mCastCost->setCaption(castCost.str());
|
||||
|
||||
mPrice->setCaption(boost::lexical_cast<std::string>(mEnchanting.getEnchantPrice()));
|
||||
|
||||
|
|
|
@ -89,15 +89,22 @@ namespace MWGui
|
|||
|
||||
void EditEffectDialog::newEffect (const ESM::MagicEffect *effect)
|
||||
{
|
||||
bool allowSelf = effect->mData.mFlags & ESM::MagicEffect::CastSelf;
|
||||
bool allowTouch = (effect->mData.mFlags & ESM::MagicEffect::CastTouch) && !constantEffect;
|
||||
bool allowTarget = (effect->mData.mFlags & ESM::MagicEffect::CastTarget) && !constantEffect;
|
||||
|
||||
if (!allowSelf && !allowTouch && !allowTarget)
|
||||
return; // TODO: Show an error message popup?
|
||||
|
||||
setMagicEffect(effect);
|
||||
mEditing = false;
|
||||
|
||||
mDeleteButton->setVisible (false);
|
||||
|
||||
mEffect.mRange = ESM::RT_Self;
|
||||
if (!(mMagicEffect->mData.mFlags & ESM::MagicEffect::CastSelf))
|
||||
if (!allowSelf)
|
||||
mEffect.mRange = ESM::RT_Touch;
|
||||
if (!(mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTouch))
|
||||
if (!allowTouch)
|
||||
mEffect.mRange = ESM::RT_Target;
|
||||
mEffect.mMagnMin = 1;
|
||||
mEffect.mMagnMax = 1;
|
||||
|
@ -118,6 +125,8 @@ namespace MWGui
|
|||
mMagnitudeMinValue->setCaption("1");
|
||||
mMagnitudeMaxValue->setCaption("- 1");
|
||||
mAreaValue->setCaption("0");
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
void EditEffectDialog::editEffect (ESM::ENAMstruct effect)
|
||||
|
@ -190,6 +199,24 @@ namespace MWGui
|
|||
{
|
||||
mEffect.mRange = (mEffect.mRange+1)%3;
|
||||
|
||||
// cycle through range types until we find something that's allowed
|
||||
// does not handle the case where nothing is allowed (this should be prevented before opening the Add Effect dialog)
|
||||
bool allowSelf = mMagicEffect->mData.mFlags & ESM::MagicEffect::CastSelf;
|
||||
bool allowTouch = (mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTouch) && !constantEffect;
|
||||
bool allowTarget = (mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTarget) && !constantEffect;
|
||||
if (mEffect.mRange == ESM::RT_Self && !allowSelf)
|
||||
mEffect.mRange = (mEffect.mRange+1)%3;
|
||||
if (mEffect.mRange == ESM::RT_Touch && !allowTouch)
|
||||
mEffect.mRange = (mEffect.mRange+1)%3;
|
||||
if (mEffect.mRange == ESM::RT_Target && !allowTarget)
|
||||
mEffect.mRange = (mEffect.mRange+1)%3;
|
||||
|
||||
if(mEffect.mRange == ESM::RT_Self)
|
||||
{
|
||||
mAreaSlider->setScrollPosition(0);
|
||||
onAreaChanged(mAreaSlider,0);
|
||||
}
|
||||
|
||||
if (mEffect.mRange == ESM::RT_Self)
|
||||
mRangeButton->setCaptionWithReplacing ("#{sRangeSelf}");
|
||||
else if (mEffect.mRange == ESM::RT_Target)
|
||||
|
@ -197,19 +224,6 @@ namespace MWGui
|
|||
else if (mEffect.mRange == ESM::RT_Touch)
|
||||
mRangeButton->setCaptionWithReplacing ("#{sRangeTouch}");
|
||||
|
||||
// cycle through range types until we find something that's allowed
|
||||
if (mEffect.mRange == ESM::RT_Target && !(mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTarget))
|
||||
onRangeButtonClicked(sender);
|
||||
if (mEffect.mRange == ESM::RT_Self && !(mMagicEffect->mData.mFlags & ESM::MagicEffect::CastSelf))
|
||||
onRangeButtonClicked(sender);
|
||||
if (mEffect.mRange == ESM::RT_Touch && !(mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTouch))
|
||||
onRangeButtonClicked(sender);
|
||||
|
||||
if(mEffect.mRange == ESM::RT_Self)
|
||||
{
|
||||
mAreaSlider->setScrollPosition(0);
|
||||
onAreaChanged(mAreaSlider,0);
|
||||
}
|
||||
updateBoxes();
|
||||
eventEffectModified(mEffect);
|
||||
}
|
||||
|
@ -542,7 +556,6 @@ namespace MWGui
|
|||
|
||||
mAddEffectDialog.newEffect(effect);
|
||||
mAddEffectDialog.setAttribute (mSelectAttributeDialog->getAttributeId());
|
||||
mAddEffectDialog.setVisible(true);
|
||||
MWBase::Environment::get().getWindowManager ()->removeDialog (mSelectAttributeDialog);
|
||||
mSelectAttributeDialog = 0;
|
||||
}
|
||||
|
@ -554,7 +567,6 @@ namespace MWGui
|
|||
|
||||
mAddEffectDialog.newEffect(effect);
|
||||
mAddEffectDialog.setSkill (mSelectSkillDialog->getSkillId());
|
||||
mAddEffectDialog.setVisible(true);
|
||||
MWBase::Environment::get().getWindowManager ()->removeDialog (mSelectSkillDialog);
|
||||
mSelectSkillDialog = 0;
|
||||
}
|
||||
|
@ -611,7 +623,6 @@ namespace MWGui
|
|||
else
|
||||
{
|
||||
mAddEffectDialog.newEffect(effect);
|
||||
mAddEffectDialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -444,6 +444,7 @@ namespace MWGui
|
|||
mVideoBackground->setVisible(false);
|
||||
|
||||
mHud->setVisible(mHudEnabled && mGuiEnabled);
|
||||
mToolTips->setVisible(mGuiEnabled);
|
||||
|
||||
bool gameMode = !isGuiMode();
|
||||
|
||||
|
@ -587,16 +588,11 @@ namespace MWGui
|
|||
mJournal->setVisible(true);
|
||||
break;
|
||||
case GM_LoadingWallpaper:
|
||||
mHud->setVisible(false);
|
||||
setCursorVisible(false);
|
||||
break;
|
||||
case GM_Loading:
|
||||
// Show the pinned windows
|
||||
mMap->setVisible(mMap->pinned() && !(mForceHidden & GW_Map));
|
||||
mStatsWindow->setVisible(mStatsWindow->pinned() && !(mForceHidden & GW_Stats));
|
||||
mInventoryWindow->setVisible(mInventoryWindow->pinned() && !(mForceHidden & GW_Inventory));
|
||||
mSpellWindow->setVisible(mSpellWindow->pinned() && !(mForceHidden & GW_Magic));
|
||||
|
||||
// Don't need to show anything here - GM_LoadingWallpaper covers everything else anyway,
|
||||
// GM_Loading uses a texture of the last rendered frame so everything previously visible will be rendered.
|
||||
mHud->setVisible(false);
|
||||
mToolTips->setVisible(false);
|
||||
setCursorVisible(false);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -869,13 +869,19 @@ namespace MWMechanics
|
|||
|
||||
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
PtrControllerMap::iterator it = mActors.find(ptr);
|
||||
if (it == mActors.end())
|
||||
return;
|
||||
CharacterController* ctrl = it->second;
|
||||
|
||||
NpcStats &stats = ptr.getClass().getNpcStats(ptr);
|
||||
if(world->isSubmerged(ptr) &&
|
||||
stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
bool knockedOutUnderwater = (ctrl->isKnockedOut() && world->isUnderwater(ptr.getCell(), Ogre::Vector3(ptr.getRefData().getPosition().pos)));
|
||||
if((world->isSubmerged(ptr) || knockedOutUnderwater)
|
||||
&& stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
|
||||
{
|
||||
float timeLeft = 0.0f;
|
||||
if(stats.getFatigue().getCurrent() == 0)
|
||||
if(knockedOutUnderwater)
|
||||
stats.setTimeToStartDrowning(0);
|
||||
else
|
||||
{
|
||||
|
@ -1122,15 +1128,6 @@ namespace MWMechanics
|
|||
// target lists get updated once every 1.0 sec
|
||||
if (timerUpdateAITargets >= 1.0f) timerUpdateAITargets = 0;
|
||||
|
||||
// Reset data from previous frame
|
||||
for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
{
|
||||
// Reset last hit object, which is only valid for one frame
|
||||
// Note, the new hit object for this frame may be set by CharacterController::update -> Animation::runAnimation
|
||||
// (below)
|
||||
iter->first.getClass().getCreatureStats(iter->first).setLastHitObject(std::string());
|
||||
}
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
|
||||
int hostilesCount = 0; // need to know this to play Battle music
|
||||
|
@ -1563,4 +1560,13 @@ namespace MWMechanics
|
|||
if (ptr.getClass().isNpc())
|
||||
calculateNpcStatModifiers(ptr, 0.f);
|
||||
}
|
||||
|
||||
bool Actors::isReadyToBlock(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
PtrControllerMap::const_iterator it = mActors.find(ptr);
|
||||
if (it == mActors.end())
|
||||
return false;
|
||||
|
||||
return it->second->isReadyToBlock();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,6 +125,8 @@ namespace MWMechanics
|
|||
|
||||
void clear(); // Clear death counter
|
||||
|
||||
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
||||
|
||||
private:
|
||||
PtrControllerMap mActors;
|
||||
|
||||
|
|
|
@ -92,6 +92,35 @@ MWMechanics::CharacterState runStateToWalkState (MWMechanics::CharacterState sta
|
|||
return ret;
|
||||
}
|
||||
|
||||
float getFallDamage(const MWWorld::Ptr& ptr, float fallHeight)
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||
|
||||
const float fallDistanceMin = store.find("fFallDamageDistanceMin")->getFloat();
|
||||
|
||||
if (fallHeight >= fallDistanceMin)
|
||||
{
|
||||
const float acrobaticsSkill = ptr.getClass().getSkill(ptr, ESM::Skill::Acrobatics);
|
||||
const float jumpSpellBonus = ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Jump).getMagnitude();
|
||||
const float fallAcroBase = store.find("fFallAcroBase")->getFloat();
|
||||
const float fallAcroMult = store.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat();
|
||||
const float fallDistanceMult = store.find("fFallDistanceMult")->getFloat();
|
||||
|
||||
float x = fallHeight - fallDistanceMin;
|
||||
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
|
||||
x = std::max(0.0f, x);
|
||||
|
||||
float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill);
|
||||
x = fallDistanceBase + fallDistanceMult * x;
|
||||
x *= a;
|
||||
|
||||
return x;
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -619,7 +648,8 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
|||
mAnimation->showWeapons(true);
|
||||
mAnimation->setWeaponGroup(mCurrentWeapon);
|
||||
}
|
||||
mAnimation->showCarriedLeft(mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand);
|
||||
|
||||
mAnimation->showCarriedLeft(updateCarriedLeftVisible(mWeaponType));
|
||||
}
|
||||
|
||||
if(!cls.getCreatureStats(mPtr).isDead())
|
||||
|
@ -807,6 +837,25 @@ bool CharacterController::updateCreatureState()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CharacterController::updateCarriedLeftVisible(WeaponType weaptype) const
|
||||
{
|
||||
// Shields/torches shouldn't be visible during any operation involving two hands
|
||||
// There seems to be no text keys for this purpose, except maybe for "[un]equip start/stop",
|
||||
// but they are also present in weapon drawing animation.
|
||||
switch (weaptype)
|
||||
{
|
||||
case WeapType_Spell:
|
||||
case WeapType_BowAndArrow:
|
||||
case WeapType_Crossbow:
|
||||
case WeapType_HandToHand:
|
||||
case WeapType_TwoHand:
|
||||
case WeapType_TwoWide:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterController::updateWeaponState()
|
||||
{
|
||||
const MWWorld::Class &cls = mPtr.getClass();
|
||||
|
@ -821,10 +870,7 @@ bool CharacterController::updateWeaponState()
|
|||
{
|
||||
forcestateupdate = true;
|
||||
|
||||
// Shields/torches shouldn't be visible during spellcasting or hand-to-hand
|
||||
// There seems to be no text keys for this purpose, except maybe for "[un]equip start/stop",
|
||||
// but they are also present in weapon drawing animation.
|
||||
mAnimation->showCarriedLeft(weaptype != WeapType_Spell && weaptype != WeapType_HandToHand);
|
||||
mAnimation->showCarriedLeft(updateCarriedLeftVisible(weaptype));
|
||||
|
||||
std::string weapgroup;
|
||||
if(weaptype == WeapType_None)
|
||||
|
@ -1250,7 +1296,7 @@ void CharacterController::update(float duration)
|
|||
const MWWorld::Class &cls = mPtr.getClass();
|
||||
Ogre::Vector3 movement(0.0f);
|
||||
|
||||
updateVisibility();
|
||||
updateMagicEffects();
|
||||
|
||||
if(!cls.isActor())
|
||||
{
|
||||
|
@ -1449,7 +1495,7 @@ void CharacterController::update(float duration)
|
|||
vec.z = 0.0f;
|
||||
|
||||
float height = cls.getCreatureStats(mPtr).land();
|
||||
float healthLost = cls.getFallDamage(mPtr, height);
|
||||
float healthLost = getFallDamage(mPtr, height);
|
||||
if (healthLost > 0.0f)
|
||||
{
|
||||
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();
|
||||
|
@ -1748,7 +1794,7 @@ void CharacterController::updateContinuousVfx()
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterController::updateVisibility()
|
||||
void CharacterController::updateMagicEffects()
|
||||
{
|
||||
if (!mPtr.getClass().isActor())
|
||||
return;
|
||||
|
@ -1765,9 +1811,11 @@ void CharacterController::updateVisibility()
|
|||
{
|
||||
alpha *= std::max(0.2f, (100.f - chameleon)/100.f);
|
||||
}
|
||||
|
||||
mAnimation->setAlpha(alpha);
|
||||
|
||||
bool vampire = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0.0f;
|
||||
mAnimation->setVampire(vampire);
|
||||
|
||||
float light = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Light).getMagnitude();
|
||||
mAnimation->setLightEffect(light);
|
||||
}
|
||||
|
@ -1787,4 +1835,14 @@ void CharacterController::determineAttackType()
|
|||
}
|
||||
}
|
||||
|
||||
bool CharacterController::isReadyToBlock() const
|
||||
{
|
||||
return updateCarriedLeftVisible(mWeaponType);
|
||||
}
|
||||
|
||||
bool CharacterController::isKnockedOut() const
|
||||
{
|
||||
return mHitState == CharState_KnockOut;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ class CharacterController
|
|||
|
||||
void castSpell(const std::string& spellid);
|
||||
|
||||
void updateVisibility();
|
||||
void updateMagicEffects();
|
||||
|
||||
void playDeath(float startpoint, CharacterState death);
|
||||
void playRandomDeath(float startpoint = 0.0f);
|
||||
|
@ -199,6 +199,8 @@ class CharacterController
|
|||
/// @param num if non-NULL, the chosen animation number will be written here
|
||||
std::string chooseRandomGroup (const std::string& prefix, int* num = NULL);
|
||||
|
||||
bool updateCarriedLeftVisible(WeaponType weaptype) const;
|
||||
|
||||
public:
|
||||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||
virtual ~CharacterController();
|
||||
|
@ -224,6 +226,9 @@ public:
|
|||
void forceStateUpdate();
|
||||
|
||||
AiState& getAiState() { return mAiState; }
|
||||
|
||||
bool isReadyToBlock() const;
|
||||
bool isKnockedOut() const;
|
||||
};
|
||||
|
||||
void getWeaponGroup(WeaponType weaptype, std::string &group);
|
||||
|
|
|
@ -62,17 +62,10 @@ namespace MWMechanics
|
|||
|| blockerStats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0)
|
||||
return false;
|
||||
|
||||
// Don't block when in spellcasting state (shield is equipped, but not visible)
|
||||
if (blockerStats.getDrawState() == DrawState_Spell)
|
||||
if (!MWBase::Environment::get().getMechanicsManager()->isReadyToBlock(blocker))
|
||||
return false;
|
||||
|
||||
MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker);
|
||||
|
||||
// Don't block when in hand-to-hand combat (shield is equipped, but not visible)
|
||||
if (blockerStats.getDrawState() == DrawState_Weapon &&
|
||||
inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight) == inv.end())
|
||||
return false;
|
||||
|
||||
MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name())
|
||||
return false;
|
||||
|
|
|
@ -359,6 +359,16 @@ namespace MWMechanics
|
|||
return mLastHitObject;
|
||||
}
|
||||
|
||||
void CreatureStats::setLastHitAttemptObject(const std::string& objectid)
|
||||
{
|
||||
mLastHitAttemptObject = objectid;
|
||||
}
|
||||
|
||||
const std::string &CreatureStats::getLastHitAttemptObject() const
|
||||
{
|
||||
return mLastHitAttemptObject;
|
||||
}
|
||||
|
||||
void CreatureStats::addToFallHeight(float height)
|
||||
{
|
||||
mFallHeight += height;
|
||||
|
@ -510,6 +520,7 @@ namespace MWMechanics
|
|||
state.mAttackStrength = mAttackStrength;
|
||||
state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?)
|
||||
state.mLastHitObject = mLastHitObject;
|
||||
state.mLastHitAttemptObject = mLastHitAttemptObject;
|
||||
state.mRecalcDynamicStats = mRecalcMagicka;
|
||||
state.mDrawState = mDrawState;
|
||||
state.mLevel = mLevel;
|
||||
|
@ -558,6 +569,7 @@ namespace MWMechanics
|
|||
mAttackStrength = state.mAttackStrength;
|
||||
mFallHeight = state.mFallHeight;
|
||||
mLastHitObject = state.mLastHitObject;
|
||||
mLastHitAttemptObject = state.mLastHitAttemptObject;
|
||||
mRecalcMagicka = state.mRecalcDynamicStats;
|
||||
mDrawState = DrawState_(state.mDrawState);
|
||||
mLevel = state.mLevel;
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace MWMechanics
|
|||
float mFallHeight;
|
||||
|
||||
std::string mLastHitObject; // The last object to hit this actor
|
||||
std::string mLastHitAttemptObject; // The last object to attempt to hit this actor
|
||||
|
||||
bool mRecalcMagicka;
|
||||
|
||||
|
@ -241,7 +242,9 @@ namespace MWMechanics
|
|||
bool getStance (Stance flag) const;
|
||||
|
||||
void setLastHitObject(const std::string &objectid);
|
||||
void setLastHitAttemptObject(const std::string &objectid);
|
||||
const std::string &getLastHitObject() const;
|
||||
const std::string &getLastHitAttemptObject() const;
|
||||
|
||||
// Note, this is just a cache to avoid checking the whole container store every frame. We don't need to store it in saves.
|
||||
// TODO: Put it somewhere else?
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace MWMechanics
|
|||
enchantment.mData.mCharge = getGemCharge();
|
||||
enchantment.mData.mAutocalc = 0;
|
||||
enchantment.mData.mType = mCastStyle;
|
||||
enchantment.mData.mCost = getEnchantPoints();
|
||||
enchantment.mData.mCost = getCastCost();
|
||||
|
||||
store.remove(mSoulGemPtr, 1, player);
|
||||
|
||||
|
@ -156,7 +156,7 @@ namespace MWMechanics
|
|||
*
|
||||
* Formula on UESPWiki is not entirely correct.
|
||||
*/
|
||||
float Enchanting::getEnchantPoints() const
|
||||
int Enchanting::getEnchantPoints() const
|
||||
{
|
||||
if (mEffectList.mList.empty())
|
||||
// No effects added, cost = 0
|
||||
|
@ -195,11 +195,11 @@ namespace MWMechanics
|
|||
--effectsLeftCnt;
|
||||
}
|
||||
|
||||
return enchantmentCost;
|
||||
return static_cast<int>(enchantmentCost);
|
||||
}
|
||||
|
||||
|
||||
float Enchanting::getCastCost() const
|
||||
int Enchanting::getCastCost() const
|
||||
{
|
||||
if (mCastStyle == ESM::Enchantment::ConstantEffect)
|
||||
return 0;
|
||||
|
@ -215,7 +215,7 @@ namespace MWMechanics
|
|||
*/
|
||||
const float castCost = enchantCost - (enchantCost / 100) * (eSkill - 10);
|
||||
|
||||
return (castCost < 1) ? 1 : castCost;
|
||||
return static_cast<int>((castCost < 1) ? 1 : castCost);
|
||||
}
|
||||
|
||||
|
||||
|
@ -240,7 +240,7 @@ namespace MWMechanics
|
|||
return soul->mData.mSoul;
|
||||
}
|
||||
|
||||
float Enchanting::getMaxEnchantValue() const
|
||||
int Enchanting::getMaxEnchantValue() const
|
||||
{
|
||||
if (itemEmpty())
|
||||
return 0;
|
||||
|
|
|
@ -35,10 +35,10 @@ namespace MWMechanics
|
|||
bool create(); //Return true if created, false if failed.
|
||||
void nextCastStyle(); //Set enchant type to next possible type (for mOldItemPtr object)
|
||||
int getCastStyle() const;
|
||||
float getEnchantPoints() const;
|
||||
float getCastCost() const;
|
||||
int getEnchantPoints() const;
|
||||
int getCastCost() const;
|
||||
int getEnchantPrice() const;
|
||||
float getMaxEnchantValue() const;
|
||||
int getMaxEnchantValue() const;
|
||||
int getGemCharge() const;
|
||||
float getEnchantChance() const;
|
||||
bool soulEmpty() const; //Return true if empty
|
||||
|
|
|
@ -1352,4 +1352,9 @@ namespace MWMechanics
|
|||
stats.resurrect();
|
||||
}
|
||||
}
|
||||
|
||||
bool MechanicsManager::isReadyToBlock(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
return mActors.isReadyToBlock(ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,6 +169,8 @@ namespace MWMechanics
|
|||
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, int bias=0, bool ignoreDistance=false);
|
||||
|
||||
virtual void keepPlayerAlive();
|
||||
|
||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -228,6 +228,7 @@ public:
|
|||
virtual void preRender (Ogre::Camera* camera);
|
||||
|
||||
virtual void setAlpha(float alpha) {}
|
||||
virtual void setVampire(bool vampire) {}
|
||||
|
||||
public:
|
||||
void updatePtr(const MWWorld::Ptr &ptr);
|
||||
|
|
|
@ -195,6 +195,7 @@ namespace MWRender
|
|||
MWWorld::InventoryStore &inv = mCharacter.getClass().getInventoryStore(mCharacter);
|
||||
MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
std::string groupname;
|
||||
bool showCarriedLeft = true;
|
||||
if(iter == inv.end())
|
||||
groupname = "inventoryhandtohand";
|
||||
else
|
||||
|
@ -224,11 +225,15 @@ namespace MWRender
|
|||
groupname = "inventoryweapontwowide";
|
||||
else
|
||||
groupname = "inventoryhandtohand";
|
||||
}
|
||||
|
||||
showCarriedLeft = (iter->getClass().canBeEquipped(*iter, mCharacter).first != 2);
|
||||
}
|
||||
else
|
||||
groupname = "inventoryhandtohand";
|
||||
}
|
||||
|
||||
mAnimation->showCarriedLeft(showCarriedLeft);
|
||||
|
||||
mCurrentAnimGroup = groupname;
|
||||
mAnimation->play(mCurrentAnimGroup, 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);
|
||||
|
||||
|
|
|
@ -56,8 +56,13 @@ std::string getVampireHead(const std::string& race, bool female)
|
|||
}
|
||||
}
|
||||
|
||||
assert(sVampireMapping[thisCombination]);
|
||||
return "meshes\\" + sVampireMapping[thisCombination]->mModel;
|
||||
if (sVampireMapping.find(thisCombination) == sVampireMapping.end())
|
||||
sVampireMapping[thisCombination] = NULL;
|
||||
|
||||
const ESM::BodyPart* bodyPart = sVampireMapping[thisCombination];
|
||||
if (!bodyPart)
|
||||
return std::string();
|
||||
return "meshes\\" + bodyPart->mModel;
|
||||
}
|
||||
|
||||
bool isSkinned (NifOgre::ObjectScenePtr scene)
|
||||
|
@ -256,10 +261,15 @@ void NpcAnimation::updateNpcBase()
|
|||
{
|
||||
if (isVampire)
|
||||
mHeadModel = getVampireHead(mNpc->mRace, mNpc->mFlags & ESM::NPC::Female);
|
||||
else
|
||||
else if (!mNpc->mHead.empty())
|
||||
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHead)->mModel;
|
||||
else
|
||||
mHeadModel = "";
|
||||
|
||||
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;
|
||||
if (!mNpc->mHair.empty())
|
||||
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;
|
||||
else
|
||||
mHairModel = "";
|
||||
}
|
||||
|
||||
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||
|
@ -399,9 +409,9 @@ void NpcAnimation::updateParts()
|
|||
|
||||
if(mViewMode != VM_FirstPerson)
|
||||
{
|
||||
if(mPartPriorities[ESM::PRT_Head] < 1)
|
||||
if(mPartPriorities[ESM::PRT_Head] < 1 && !mHeadModel.empty())
|
||||
addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel);
|
||||
if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1)
|
||||
if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1 && !mHairModel.empty())
|
||||
addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel);
|
||||
}
|
||||
if(mViewMode == VM_HeadOnly)
|
||||
|
@ -973,4 +983,14 @@ void NpcAnimation::equipmentChanged()
|
|||
updateParts();
|
||||
}
|
||||
|
||||
void NpcAnimation::setVampire(bool vampire)
|
||||
{
|
||||
if (mNpcType == Type_Werewolf) // we can't have werewolf vampires, can we
|
||||
return;
|
||||
if ((mNpcType == Type_Vampire) != vampire)
|
||||
{
|
||||
rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ public:
|
|||
virtual void setPitchFactor(float factor) { mPitchFactor = factor; }
|
||||
|
||||
virtual void showWeapons(bool showWeapon);
|
||||
virtual void showCarriedLeft(bool showa);
|
||||
virtual void showCarriedLeft(bool show);
|
||||
|
||||
virtual void attachArrow();
|
||||
virtual void releaseArrow();
|
||||
|
@ -168,6 +168,8 @@ public:
|
|||
/// Make the NPC only partially visible
|
||||
virtual void setAlpha(float alpha);
|
||||
|
||||
virtual void setVampire(bool vampire);
|
||||
|
||||
/// Prepare this animation for being rendered with \a camera (rotates billboard nodes)
|
||||
virtual void preRender (Ogre::Camera* camera);
|
||||
};
|
||||
|
|
|
@ -433,5 +433,10 @@ op 0x20002c4-0x20002db: ModMagicEffect
|
|||
op 0x20002dc-0x20002f3: ModMagicEffect, explicit
|
||||
op 0x20002f4: ResetActors
|
||||
op 0x20002f5: ToggleWorld
|
||||
op 0x20002f6: PCForce1stPerson
|
||||
op 0x20002f7: PCForce3rdPerson
|
||||
op 0x20002f8: PCGet3rdPerson
|
||||
op 0x20002f9: HitAttemptOnMe
|
||||
op 0x20002fa: HitAttemptOnMe, explicit
|
||||
|
||||
opcodes 0x20002f6-0x3ffffff unused
|
||||
opcodes 0x20002fb-0x3ffffff unused
|
||||
|
|
|
@ -205,7 +205,6 @@ namespace MWScript
|
|||
|
||||
void InterpreterContext::report (const std::string& message)
|
||||
{
|
||||
messageBox (message);
|
||||
}
|
||||
|
||||
bool InterpreterContext::menuMode()
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace MWScript
|
|||
const std::vector<std::string>& buttons);
|
||||
|
||||
virtual void report (const std::string& message);
|
||||
///< By default echo via messageBox.
|
||||
///< By default, do nothing.
|
||||
|
||||
virtual bool menuMode();
|
||||
|
||||
|
|
|
@ -312,6 +312,35 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
class OpPcForce1stPerson : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
if (!MWBase::Environment::get().getWorld()->isFirstPerson())
|
||||
MWBase::Environment::get().getWorld()->togglePOV();
|
||||
}
|
||||
};
|
||||
|
||||
class OpPcForce3rdPerson : public Interpreter::Opcode0
|
||||
{
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
if (MWBase::Environment::get().getWorld()->isFirstPerson())
|
||||
MWBase::Environment::get().getWorld()->togglePOV();
|
||||
}
|
||||
};
|
||||
|
||||
class OpPcGet3rdPerson : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
virtual void execute(Interpreter::Runtime& runtime)
|
||||
{
|
||||
runtime.push(!MWBase::Environment::get().getWorld()->isFirstPerson());
|
||||
}
|
||||
};
|
||||
|
||||
class OpToggleVanityMode : public Interpreter::Opcode0
|
||||
{
|
||||
static bool sActivate;
|
||||
|
@ -703,6 +732,27 @@ namespace MWScript
|
|||
|
||||
MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||
runtime.push(::Misc::StringUtils::ciEqual(objectID, stats.getLastHitObject()));
|
||||
|
||||
stats.setLastHitObject(std::string());
|
||||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpHitAttemptOnMe : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string objectID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||
runtime.push(::Misc::StringUtils::ciEqual(objectID, stats.getLastHitAttemptObject()));
|
||||
|
||||
stats.setLastHitAttemptObject(std::string());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1002,6 +1052,9 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleWater, new OpToggleWater);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleWorld, new OpToggleWorld);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDontSaveObject, new OpDontSaveObject);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodePcForce1stPerson, new OpPcForce1stPerson);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodePcForce3rdPerson, new OpPcForce3rdPerson);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodePcGet3rdPerson, new OpPcGet3rdPerson);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleVanityMode, new OpToggleVanityMode);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetPcSleep, new OpGetPcSleep);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetPcJumping, new OpGetPcJumping);
|
||||
|
@ -1051,6 +1104,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeGetWindSpeed, new OpGetWindSpeed);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeHitOnMe, new OpHitOnMe<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeHitOnMeExplicit, new OpHitOnMe<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeHitAttemptOnMe, new OpHitAttemptOnMe<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeHitAttemptOnMeExplicit, new OpHitAttemptOnMe<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDisableTeleporting, new OpEnableTeleporting<false>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeEnableTeleporting, new OpEnableTeleporting<true>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars<ImplicitRef>);
|
||||
|
|
|
@ -441,7 +441,8 @@ namespace MWScript
|
|||
pos.rot[2] = zRot;
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
|
||||
ref.getPtr().getCellRef().setPosition(pos);
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
|
||||
placed.getClass().adjustPosition(placed, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -488,7 +489,8 @@ namespace MWScript
|
|||
pos.rot[2] = zRot;
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
|
||||
ref.getPtr().getCellRef().setPosition(pos);
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
|
||||
placed.getClass().adjustPosition(placed, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,11 +31,7 @@ namespace MWWorld
|
|||
{
|
||||
case 0:
|
||||
return;
|
||||
case 2:
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedLeft, actor);
|
||||
break;
|
||||
case 3:
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, actor);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -180,11 +180,6 @@ namespace MWWorld
|
|||
throw std::runtime_error ("class does not support enchanting");
|
||||
}
|
||||
|
||||
float Class::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
|
||||
{
|
||||
throw std::runtime_error ("movement settings not supported by class");
|
||||
|
|
|
@ -184,9 +184,6 @@ namespace MWWorld
|
|||
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
||||
///< Return jump velocity (not accounting for movement)
|
||||
|
||||
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
|
||||
///< Return amount of health points lost when falling
|
||||
|
||||
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
|
||||
///< Return desired movement.
|
||||
|
||||
|
|
|
@ -255,11 +255,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
|||
{
|
||||
case 0:
|
||||
continue;
|
||||
case 2:
|
||||
slots_[MWWorld::InventoryStore::Slot_CarriedLeft] = end();
|
||||
break;
|
||||
case 3:
|
||||
// Prefer keeping twohanded weapon
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -452,6 +452,10 @@ namespace MWWorld
|
|||
mRendering->togglePOV();
|
||||
}
|
||||
|
||||
virtual bool isFirstPerson() const {
|
||||
return mRendering->getCamera()->isFirstPerson();
|
||||
}
|
||||
|
||||
virtual void togglePreviewMode(bool enable) {
|
||||
mRendering->togglePreviewMode(enable);
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("additem", "clX", opcodeAddItem, opcodeAddItemExplicit);
|
||||
extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount,
|
||||
opcodeGetItemCountExplicit);
|
||||
extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem,
|
||||
extensions.registerInstruction ("removeitem", "clX", opcodeRemoveItem,
|
||||
opcodeRemoveItemExplicit);
|
||||
extensions.registerInstruction ("equip", "cX", opcodeEquip, opcodeEquipExplicit);
|
||||
extensions.registerFunction ("getarmortype", 'l', "l", opcodeGetArmorType, opcodeGetArmorTypeExplicit);
|
||||
|
@ -261,6 +261,9 @@ namespace Compiler
|
|||
extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid);
|
||||
extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid);
|
||||
extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);
|
||||
extensions.registerInstruction ("pcforce1stperson", "", opcodePcForce1stPerson);
|
||||
extensions.registerInstruction ("pcforce3rdperson", "", opcodePcForce3rdPerson);
|
||||
extensions.registerFunction ("pcget3rdperson", 'l', "", opcodePcGet3rdPerson);
|
||||
extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode);
|
||||
extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
|
||||
extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
|
||||
|
@ -292,6 +295,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("hurtcollidingactor", "f", opcodeHurtCollidingActor, opcodeHurtCollidingActorExplicit);
|
||||
extensions.registerFunction ("getwindspeed", 'f', "", opcodeGetWindSpeed);
|
||||
extensions.registerFunction ("hitonme", 'l', "S", opcodeHitOnMe, opcodeHitOnMeExplicit);
|
||||
extensions.registerFunction ("hitattemptonme", 'l', "S", opcodeHitAttemptOnMe, opcodeHitAttemptOnMeExplicit);
|
||||
extensions.registerInstruction ("disableteleporting", "", opcodeDisableTeleporting);
|
||||
extensions.registerInstruction ("enableteleporting", "", opcodeEnableTeleporting);
|
||||
extensions.registerInstruction ("showvars", "", opcodeShowVars, opcodeShowVarsExplicit);
|
||||
|
|
|
@ -215,6 +215,9 @@ namespace Compiler
|
|||
const int opcodeToggleWorld = 0x20002f5;
|
||||
const int opcodeTogglePathgrid = 0x2000146;
|
||||
const int opcodeDontSaveObject = 0x2000153;
|
||||
const int opcodePcForce1stPerson = 0x20002f6;
|
||||
const int opcodePcForce3rdPerson = 0x20002f7;
|
||||
const int opcodePcGet3rdPerson = 0x20002f8;
|
||||
const int opcodeToggleVanityMode = 0x2000174;
|
||||
const int opcodeGetPcSleep = 0x200019f;
|
||||
const int opcodeGetPcJumping = 0x2000233;
|
||||
|
@ -266,6 +269,8 @@ namespace Compiler
|
|||
const int opcodePayFineThief = 0x2000237;
|
||||
const int opcodeHitOnMe = 0x2000213;
|
||||
const int opcodeHitOnMeExplicit = 0x2000214;
|
||||
const int opcodeHitAttemptOnMe = 0x20002f9;
|
||||
const int opcodeHitAttemptOnMeExplicit = 0x20002fa;
|
||||
const int opcodeDisableTeleporting = 0x2000215;
|
||||
const int opcodeEnableTeleporting = 0x2000216;
|
||||
const int opcodeShowVars = 0x200021d;
|
||||
|
|
|
@ -68,6 +68,8 @@ void ESM::CreatureStats::load (ESMReader &esm)
|
|||
|
||||
mLastHitObject = esm.getHNOString ("LHIT");
|
||||
|
||||
mLastHitAttemptObject = esm.getHNOString ("LHAT");
|
||||
|
||||
mRecalcDynamicStats = false;
|
||||
esm.getHNOT (mRecalcDynamicStats, "CALC");
|
||||
|
||||
|
@ -179,6 +181,9 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
|
|||
if (!mLastHitObject.empty())
|
||||
esm.writeHNString ("LHIT", mLastHitObject);
|
||||
|
||||
if (!mLastHitAttemptObject.empty())
|
||||
esm.writeHNString ("LHAT", mLastHitAttemptObject);
|
||||
|
||||
if (mRecalcDynamicStats)
|
||||
esm.writeHNT ("CALC", mRecalcDynamicStats);
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ namespace ESM
|
|||
float mAttackStrength;
|
||||
float mFallHeight;
|
||||
std::string mLastHitObject;
|
||||
std::string mLastHitAttemptObject;
|
||||
bool mRecalcDynamicStats;
|
||||
int mDrawState;
|
||||
unsigned char mDeathAnimation;
|
||||
|
|
|
@ -57,6 +57,7 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
|
|||
newFactory.insert(makeEntry("NiCamera", &construct <NiCamera> , RC_NiCamera ));
|
||||
newFactory.insert(makeEntry("RootCollisionNode", &construct <NiNode> , RC_RootCollisionNode ));
|
||||
newFactory.insert(makeEntry("NiTexturingProperty", &construct <NiTexturingProperty> , RC_NiTexturingProperty ));
|
||||
newFactory.insert(makeEntry("NiFogProperty", &construct <NiFogProperty> , RC_NiFogProperty ));
|
||||
newFactory.insert(makeEntry("NiMaterialProperty", &construct <NiMaterialProperty> , RC_NiMaterialProperty ));
|
||||
newFactory.insert(makeEntry("NiZBufferProperty", &construct <NiZBufferProperty> , RC_NiZBufferProperty ));
|
||||
newFactory.insert(makeEntry("NiAlphaProperty", &construct <NiAlphaProperty> , RC_NiAlphaProperty ));
|
||||
|
|
|
@ -155,6 +155,22 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class NiFogProperty : public Property
|
||||
{
|
||||
public:
|
||||
float mFogDepth;
|
||||
Ogre::Vector3 mColour;
|
||||
|
||||
|
||||
void read(NIFStream *nif)
|
||||
{
|
||||
Property::read(nif);
|
||||
|
||||
mFogDepth = nif->getFloat();
|
||||
mColour = nif->getVector3();
|
||||
}
|
||||
};
|
||||
|
||||
// These contain no other data than the 'flags' field in Property
|
||||
class NiShadeProperty : public Property { };
|
||||
class NiDitherProperty : public Property { };
|
||||
|
|
|
@ -44,6 +44,7 @@ enum RecordType
|
|||
RC_NiBSParticleNode,
|
||||
RC_NiCamera,
|
||||
RC_NiTexturingProperty,
|
||||
RC_NiFogProperty,
|
||||
RC_NiMaterialProperty,
|
||||
RC_NiZBufferProperty,
|
||||
RC_NiAlphaProperty,
|
||||
|
|
Loading…
Reference in a new issue