forked from teamnwah/openmw-tes3coop
Add Vampirism and Sun Damage effects. Some fixes.
This commit is contained in:
parent
7f735c2c4c
commit
4ed4c1e319
5 changed files with 84 additions and 29 deletions
|
@ -211,7 +211,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude
|
float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude
|
||||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude
|
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude
|
||||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth)).mMagnitude;
|
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth+i)).mMagnitude;
|
||||||
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
||||||
|
|
||||||
creatureStats.setDynamic(i, stat);
|
creatureStats.setDynamic(i, stat);
|
||||||
|
@ -219,16 +219,34 @@ namespace MWMechanics
|
||||||
|
|
||||||
// Apply damage ticks
|
// Apply damage ticks
|
||||||
int damageEffects[] = {
|
int damageEffects[] = {
|
||||||
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison
|
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
||||||
|
ESM::MagicEffect::SunDamage
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DynamicStat<float> health = creatureStats.getHealth();
|
||||||
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
|
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
|
||||||
{
|
{
|
||||||
float magnitude = creatureStats.getMagicEffects().get(EffectKey(damageEffects[i])).mMagnitude;
|
float magnitude = creatureStats.getMagicEffects().get(EffectKey(damageEffects[i])).mMagnitude;
|
||||||
DynamicStat<float> health = creatureStats.getHealth();
|
|
||||||
health.setCurrent(health.getCurrent() - magnitude * duration);
|
if (damageEffects[i] == ESM::MagicEffect::SunDamage)
|
||||||
creatureStats.setHealth(health);
|
{
|
||||||
|
// isInCell shouldn't be needed, but updateActor called during game start
|
||||||
|
if (!ptr.isInCell() || !ptr.getCell()->isExterior())
|
||||||
|
continue;
|
||||||
|
float time = MWBase::Environment::get().getWorld()->getTimeStamp().getHour();
|
||||||
|
float timeDiff = std::min(7.f, std::max(0.f, std::abs(time - 13)));
|
||||||
|
float damageScale = 1.f - timeDiff / 7.f;
|
||||||
|
// When cloudy, the sun damage effect is halved
|
||||||
|
int weather = MWBase::Environment::get().getWorld()->getCurrentWeather();
|
||||||
|
if (weather > 1)
|
||||||
|
damageScale *= 0.5;
|
||||||
|
health.setCurrent(health.getCurrent() - magnitude * duration * damageScale);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
health.setCurrent(health.getCurrent() - magnitude * duration);
|
||||||
|
|
||||||
|
}
|
||||||
|
creatureStats.setHealth(health);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr)
|
void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr)
|
||||||
|
@ -324,7 +342,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Actors::Actors() : mDuration (0) {}
|
Actors::Actors() {}
|
||||||
|
|
||||||
void Actors::addActor (const MWWorld::Ptr& ptr)
|
void Actors::addActor (const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
|
@ -377,14 +395,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
void Actors::update (float duration, bool paused)
|
void Actors::update (float duration, bool paused)
|
||||||
{
|
{
|
||||||
mDuration += duration;
|
|
||||||
|
|
||||||
//if (mDuration>=0.25)
|
|
||||||
if (!paused)
|
if (!paused)
|
||||||
{
|
{
|
||||||
float totalDuration = mDuration;
|
|
||||||
mDuration = 0;
|
|
||||||
|
|
||||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
|
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
||||||
|
@ -396,9 +408,9 @@ namespace MWMechanics
|
||||||
if(iter->second->isDead())
|
if(iter->second->isDead())
|
||||||
iter->second->resurrect();
|
iter->second->resurrect();
|
||||||
|
|
||||||
updateActor(iter->first, totalDuration);
|
updateActor(iter->first, duration);
|
||||||
if(iter->first.getTypeName() == typeid(ESM::NPC).name())
|
if(iter->first.getTypeName() == typeid(ESM::NPC).name())
|
||||||
updateNpc(iter->first, totalDuration, paused);
|
updateNpc(iter->first, duration, paused);
|
||||||
|
|
||||||
if(!stats.isDead())
|
if(!stats.isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -30,8 +30,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
std::map<std::string, int> mDeathCount;
|
std::map<std::string, int> mDeathCount;
|
||||||
|
|
||||||
float mDuration;
|
|
||||||
|
|
||||||
void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused);
|
void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace MWMechanics
|
||||||
int i=0;
|
int i=0;
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
||||||
{
|
{
|
||||||
effects.add (*it, iter->second[i]);
|
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * iter->second[i]);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,6 @@ namespace MWRender
|
||||||
|
|
||||||
mAnimation = new NpcAnimation(mCharacter, mNode,
|
mAnimation = new NpcAnimation(mCharacter, mNode,
|
||||||
0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
|
0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
|
||||||
mAnimation->updateParts();
|
|
||||||
|
|
||||||
Ogre::Vector3 scale = mNode->getScale();
|
Ogre::Vector3 scale = mNode->getScale();
|
||||||
mCamera->setPosition(mPosition * scale);
|
mCamera->setPosition(mPosition * scale);
|
||||||
|
@ -114,7 +113,6 @@ namespace MWRender
|
||||||
delete mAnimation;
|
delete mAnimation;
|
||||||
mAnimation = new NpcAnimation(mCharacter, mNode,
|
mAnimation = new NpcAnimation(mCharacter, mNode,
|
||||||
0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
|
0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
|
||||||
mAnimation->updateParts();
|
|
||||||
|
|
||||||
float scale=1.f;
|
float scale=1.f;
|
||||||
MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale);
|
MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale);
|
||||||
|
@ -142,6 +140,9 @@ namespace MWRender
|
||||||
|
|
||||||
void InventoryPreview::update(int sizeX, int sizeY)
|
void InventoryPreview::update(int sizeX, int sizeY)
|
||||||
{
|
{
|
||||||
|
// TODO: can we avoid this. Vampire state needs to be updated.
|
||||||
|
mAnimation->rebuild();
|
||||||
|
|
||||||
MWWorld::InventoryStore &inv = MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter);
|
MWWorld::InventoryStore &inv = MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter);
|
||||||
MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
std::string groupname;
|
std::string groupname;
|
||||||
|
@ -176,11 +177,12 @@ namespace MWRender
|
||||||
groupname = "inventoryhandtohand";
|
groupname = "inventoryhandtohand";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(groupname != mCurrentAnimGroup)
|
// TODO see above
|
||||||
{
|
//if(groupname != mCurrentAnimGroup)
|
||||||
|
//{
|
||||||
mCurrentAnimGroup = groupname;
|
mCurrentAnimGroup = groupname;
|
||||||
mAnimation->play(mCurrentAnimGroup, 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);
|
mAnimation->play(mCurrentAnimGroup, 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);
|
||||||
}
|
//}
|
||||||
|
|
||||||
MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name())
|
if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name())
|
||||||
|
|
|
@ -19,6 +19,42 @@
|
||||||
#include "renderconst.hpp"
|
#include "renderconst.hpp"
|
||||||
#include "camera.hpp"
|
#include "camera.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string getVampireHead(const std::string& race, bool female)
|
||||||
|
{
|
||||||
|
static std::map <std::pair<std::string,int>, const ESM::BodyPart* > sVampireMapping;
|
||||||
|
|
||||||
|
std::pair<std::string, int> thisCombination = std::make_pair(race, int(female));
|
||||||
|
|
||||||
|
if (sVampireMapping.find(thisCombination) == sVampireMapping.end())
|
||||||
|
{
|
||||||
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
||||||
|
for(MWWorld::Store<ESM::BodyPart>::iterator it = partStore.begin(); it != partStore.end(); ++it)
|
||||||
|
{
|
||||||
|
const ESM::BodyPart& bodypart = *it;
|
||||||
|
if (!bodypart.mData.mVampire)
|
||||||
|
continue;
|
||||||
|
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
|
||||||
|
continue;
|
||||||
|
if (bodypart.mData.mPart != ESM::BodyPart::MP_Head)
|
||||||
|
continue;
|
||||||
|
if (female != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
|
||||||
|
continue;
|
||||||
|
if (!Misc::StringUtils::ciEqual(bodypart.mRace, race))
|
||||||
|
continue;
|
||||||
|
sVampireMapping[thisCombination] = &*it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sVampireMapping[thisCombination]);
|
||||||
|
return "meshes\\" + sVampireMapping[thisCombination]->mModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
@ -110,18 +146,23 @@ void NpcAnimation::updateNpcBase()
|
||||||
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
||||||
bool isWerewolf = MWWorld::Class::get(mPtr).getNpcStats(mPtr).isWerewolf();
|
bool isWerewolf = mPtr.getClass().getNpcStats(mPtr).isWerewolf();
|
||||||
|
bool vampire = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).mMagnitude;
|
||||||
|
|
||||||
if(!isWerewolf)
|
if (isWerewolf)
|
||||||
{
|
|
||||||
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHead)->mModel;
|
|
||||||
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find("WerewolfHead")->mModel;
|
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find("WerewolfHead")->mModel;
|
||||||
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find("WerewolfHair")->mModel;
|
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find("WerewolfHair")->mModel;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (vampire)
|
||||||
|
mHeadModel = getVampireHead(mNpc->mRace, mNpc->mFlags & ESM::NPC::Female);
|
||||||
|
else
|
||||||
|
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHead)->mModel;
|
||||||
|
|
||||||
|
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;
|
||||||
|
}
|
||||||
|
|
||||||
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||||
std::string smodel = (mViewMode != VM_FirstPerson) ?
|
std::string smodel = (mViewMode != VM_FirstPerson) ?
|
||||||
|
@ -270,6 +311,8 @@ void NpcAnimation::updateParts()
|
||||||
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
|
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
|
||||||
static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping;
|
static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping;
|
||||||
|
|
||||||
|
static std::map <std::pair<std::string,int>, std::vector<const ESM::BodyPart*> > sVampireMapping;
|
||||||
|
|
||||||
static const int Flag_Female = 1<<0;
|
static const int Flag_Female = 1<<0;
|
||||||
static const int Flag_FirstPerson = 1<<1;
|
static const int Flag_FirstPerson = 1<<1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue