forked from teamnwah/openmw-tes3coop
Implement AI related magic effects (calm, frenzy, rally, demoralize, turn undead)
This commit is contained in:
parent
634a53211c
commit
14b70a3ce6
10 changed files with 81 additions and 30 deletions
|
@ -263,7 +263,7 @@ namespace
|
||||||
|
|
||||||
static const char *sCreatureTypes[] =
|
static const char *sCreatureTypes[] =
|
||||||
{
|
{
|
||||||
"Creature", "Deadra", "Undead", "Humanoid", 0
|
"Creature", "Daedra", "Undead", "Humanoid", 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *sWeaponTypes[] =
|
static const char *sWeaponTypes[] =
|
||||||
|
@ -342,4 +342,4 @@ std::vector<std::string> CSMWorld::Columns::getEnums (ColumnId column)
|
||||||
}
|
}
|
||||||
|
|
||||||
return enums;
|
return enums;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,10 +84,10 @@ namespace MWClass
|
||||||
|
|
||||||
data->mCreatureStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
data->mCreatureStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
||||||
|
|
||||||
data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello);
|
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
|
||||||
data->mCreatureStats.setAiSetting (1, ref->mBase->mAiData.mFight);
|
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, ref->mBase->mAiData.mFight);
|
||||||
data->mCreatureStats.setAiSetting (2, ref->mBase->mAiData.mFlee);
|
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
||||||
data->mCreatureStats.setAiSetting (3, ref->mBase->mAiData.mAlarm);
|
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
|
||||||
|
|
||||||
// spells
|
// spells
|
||||||
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
||||||
|
|
|
@ -309,10 +309,10 @@ namespace MWClass
|
||||||
|
|
||||||
data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
||||||
|
|
||||||
data->mNpcStats.setAiSetting (0, ref->mBase->mAiData.mHello);
|
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
|
||||||
data->mNpcStats.setAiSetting (1, ref->mBase->mAiData.mFight);
|
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, ref->mBase->mAiData.mFight);
|
||||||
data->mNpcStats.setAiSetting (2, ref->mBase->mAiData.mFlee);
|
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
||||||
data->mNpcStats.setAiSetting (3, ref->mBase->mAiData.mAlarm);
|
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
|
||||||
|
|
||||||
// spells
|
// spells
|
||||||
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
||||||
|
|
|
@ -279,7 +279,8 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||||
|
|
||||||
case SelectWrapper::Function_AiSetting:
|
case SelectWrapper::Function_AiSetting:
|
||||||
|
|
||||||
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (select.getArgument());
|
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (
|
||||||
|
(MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified();
|
||||||
|
|
||||||
case SelectWrapper::Function_PcAttribute:
|
case SelectWrapper::Function_PcAttribute:
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ namespace MWMechanics
|
||||||
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
|
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
|
||||||
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
||||||
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
||||||
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(1);
|
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
|
||||||
float disp = 100; //creatures don't have disposition, so set it to 100 by default
|
float disp = 100; //creatures don't have disposition, so set it to 100 by default
|
||||||
if(ptr.getTypeName() == typeid(ESM::NPC).name())
|
if(ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
{
|
{
|
||||||
|
@ -341,6 +341,30 @@ namespace MWMechanics
|
||||||
creatureStats.setDynamic(i, stat);
|
creatureStats.setDynamic(i, stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AI setting modifiers
|
||||||
|
int creature = !ptr.getClass().isNpc();
|
||||||
|
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Humanoid)
|
||||||
|
creature = false;
|
||||||
|
// Note: the Creature variants only work on normal creatures, not on daedra or undead creatures.
|
||||||
|
if (!creature || ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Creatures)
|
||||||
|
{
|
||||||
|
Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Fight);
|
||||||
|
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::FrenzyHumanoid+creature).mMagnitude
|
||||||
|
- creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid+creature).mMagnitude);
|
||||||
|
creatureStats.setAiSetting(CreatureStats::AI_Fight, stat);
|
||||||
|
|
||||||
|
stat = creatureStats.getAiSetting(CreatureStats::AI_Flee);
|
||||||
|
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::DemoralizeHumanoid+creature).mMagnitude
|
||||||
|
- creatureStats.getMagicEffects().get(ESM::MagicEffect::RallyHumanoid+creature).mMagnitude);
|
||||||
|
creatureStats.setAiSetting(CreatureStats::AI_Flee, stat);
|
||||||
|
}
|
||||||
|
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Undead)
|
||||||
|
{
|
||||||
|
Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Flee);
|
||||||
|
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::TurnUndead).mMagnitude);
|
||||||
|
creatureStats.setAiSetting(CreatureStats::AI_Flee, stat);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply disintegration (reduces item health)
|
// Apply disintegration (reduces item health)
|
||||||
float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).mMagnitude;
|
float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).mMagnitude;
|
||||||
if (disintegrateWeapon > 0)
|
if (disintegrateWeapon > 0)
|
||||||
|
|
|
@ -122,7 +122,7 @@ namespace MWMechanics
|
||||||
return mLevel;
|
return mLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CreatureStats::getAiSetting (int index) const
|
Stat<int> CreatureStats::getAiSetting (AiSetting index) const
|
||||||
{
|
{
|
||||||
assert (index>=0 && index<4);
|
assert (index>=0 && index<4);
|
||||||
return mAiSettings[index];
|
return mAiSettings[index];
|
||||||
|
@ -240,12 +240,18 @@ namespace MWMechanics
|
||||||
mAttackingOrSpell = attackingOrSpell;
|
mAttackingOrSpell = attackingOrSpell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureStats::setAiSetting (int index, int value)
|
void CreatureStats::setAiSetting (AiSetting index, Stat<int> value)
|
||||||
{
|
{
|
||||||
assert (index>=0 && index<4);
|
assert (index>=0 && index<4);
|
||||||
mAiSettings[index] = value;
|
mAiSettings[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreatureStats::setAiSetting (AiSetting index, int base)
|
||||||
|
{
|
||||||
|
Stat<int> stat(base);
|
||||||
|
setAiSetting(index, stat);
|
||||||
|
}
|
||||||
|
|
||||||
bool CreatureStats::isDead() const
|
bool CreatureStats::isDead() const
|
||||||
{
|
{
|
||||||
return mDead;
|
return mDead;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace MWMechanics
|
||||||
Spells mSpells;
|
Spells mSpells;
|
||||||
ActiveSpells mActiveSpells;
|
ActiveSpells mActiveSpells;
|
||||||
MagicEffects mMagicEffects;
|
MagicEffects mMagicEffects;
|
||||||
int mAiSettings[4];
|
Stat<int> mAiSettings[4];
|
||||||
AiSequence mAiSequence;
|
AiSequence mAiSequence;
|
||||||
float mLevelHealthBonus;
|
float mLevelHealthBonus;
|
||||||
bool mDead;
|
bool mDead;
|
||||||
|
@ -85,9 +85,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
int getLevel() const;
|
int getLevel() const;
|
||||||
|
|
||||||
int getAiSetting (int index) const;
|
|
||||||
///< 0: hello, 1 fight, 2 flee, 3 alarm
|
|
||||||
|
|
||||||
Spells & getSpells();
|
Spells & getSpells();
|
||||||
|
|
||||||
ActiveSpells & getActiveSpells();
|
ActiveSpells & getActiveSpells();
|
||||||
|
@ -125,8 +122,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
void setLevel(int level);
|
void setLevel(int level);
|
||||||
|
|
||||||
void setAiSetting (int index, int value);
|
enum AiSetting
|
||||||
///< 0: hello, 1 fight, 2 flee, 3 alarm
|
{
|
||||||
|
AI_Hello,
|
||||||
|
AI_Fight,
|
||||||
|
AI_Flee,
|
||||||
|
AI_Alarm
|
||||||
|
};
|
||||||
|
void setAiSetting (AiSetting index, Stat<int> value);
|
||||||
|
void setAiSetting (AiSetting index, int base);
|
||||||
|
Stat<int> getAiSetting (AiSetting index) const;
|
||||||
|
|
||||||
const AiSequence& getAiSequence() const;
|
const AiSequence& getAiSequence() const;
|
||||||
|
|
||||||
|
|
|
@ -605,8 +605,12 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
float s = int(r * fPerDieRollMult * fPerTempMult);
|
float s = int(r * fPerDieRollMult * fPerTempMult);
|
||||||
|
|
||||||
npcStats.setAiSetting (2, std::max(0, std::min(100, npcStats.getAiSetting (2) + int(std::max(iPerMinChange, s)))));
|
int flee = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Flee).getBase();
|
||||||
npcStats.setAiSetting (1, std::max(0, std::min(100, npcStats.getAiSetting (1) + int(std::min(-iPerMinChange, -s)))));
|
int fight = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Fight).getBase();
|
||||||
|
npcStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee,
|
||||||
|
std::max(0, std::min(100, flee + int(std::max(iPerMinChange, s)))));
|
||||||
|
npcStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight,
|
||||||
|
std::max(0, std::min(100, fight + int(std::min(-iPerMinChange, -s)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
float c = -std::abs(int(r * fPerDieRollMult));
|
float c = -std::abs(int(r * fPerDieRollMult));
|
||||||
|
@ -640,8 +644,12 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
float s = c * fPerDieRollMult * fPerTempMult;
|
float s = c * fPerDieRollMult * fPerTempMult;
|
||||||
|
|
||||||
npcStats.setAiSetting (2, std::max(0, std::min(100, npcStats.getAiSetting (2) + std::min(-int(iPerMinChange), int(-s)))));
|
int flee = npcStats.getAiSetting (CreatureStats::AI_Flee).getBase();
|
||||||
npcStats.setAiSetting (1, std::max(0, std::min(100, npcStats.getAiSetting (1) + std::max(int(iPerMinChange), int(s)))));
|
int fight = npcStats.getAiSetting (CreatureStats::AI_Fight).getBase();
|
||||||
|
npcStats.setAiSetting (CreatureStats::AI_Flee,
|
||||||
|
std::max(0, std::min(100, flee + std::min(-int(iPerMinChange), int(-s)))));
|
||||||
|
npcStats.setAiSetting (CreatureStats::AI_Fight,
|
||||||
|
std::max(0, std::min(100, fight + std::max(int(iPerMinChange), int(s)))));
|
||||||
}
|
}
|
||||||
x = int(-c * fPerDieRollMult);
|
x = int(-c * fPerDieRollMult);
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,8 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
runtime.push(MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSetting (mIndex));
|
runtime.push(MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSetting (
|
||||||
|
(MWMechanics::CreatureStats::AiSetting)mIndex).getModified());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<class R>
|
template<class R>
|
||||||
|
@ -241,8 +242,11 @@ namespace MWScript
|
||||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (mIndex,
|
MWMechanics::CreatureStats::AiSetting setting
|
||||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSetting (mIndex) + value);
|
= MWMechanics::CreatureStats::AiSetting(mIndex);
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (setting,
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSetting (setting).getBase() + value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<class R>
|
template<class R>
|
||||||
|
@ -258,8 +262,11 @@ namespace MWScript
|
||||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).setAiSetting (mIndex,
|
MWMechanics::CreatureStats::AiSetting setting = (MWMechanics::CreatureStats::AiSetting)mIndex;
|
||||||
value);
|
|
||||||
|
MWMechanics::Stat<int> stat = ptr.getClass().getCreatureStats(ptr).getAiSetting(setting);
|
||||||
|
stat.setModified(value, 0);
|
||||||
|
ptr.getClass().getCreatureStats(ptr).setAiSetting(setting, stat);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct Creature
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
Creatures = 0,
|
Creatures = 0,
|
||||||
Deadra = 1,
|
Daedra = 1,
|
||||||
Undead = 2,
|
Undead = 2,
|
||||||
Humanoid = 3
|
Humanoid = 3
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue