mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-02 04:41:31 +00:00
Revise AI data handling
Make Hello 16-bit unsigned as it's intended to be Get rid of redundant mHasAI boolean Always save AI data subrecord Adjust creature and NPC default rating values to Morrowind defaults
This commit is contained in:
parent
acbc885ae6
commit
594ea39f5d
14 changed files with 29 additions and 47 deletions
|
@ -34,6 +34,7 @@
|
||||||
Bug #4828: Potion looping effects VFX are not shown for NPCs
|
Bug #4828: Potion looping effects VFX are not shown for NPCs
|
||||||
Bug #4837: CTD when a mesh with NiLODNode root node with particles is loaded
|
Bug #4837: CTD when a mesh with NiLODNode root node with particles is loaded
|
||||||
Bug #4860: Actors outside of processing range visible for one frame after spawning
|
Bug #4860: Actors outside of processing range visible for one frame after spawning
|
||||||
|
Bug #4876: AI ratings handling inconsistencies
|
||||||
Feature #2229: Improve pathfinding AI
|
Feature #2229: Improve pathfinding AI
|
||||||
Feature #3442: Default values for fallbacks from ini file
|
Feature #3442: Default values for fallbacks from ini file
|
||||||
Feature #3610: Option to invert X axis
|
Feature #3610: Option to invert X axis
|
||||||
|
|
|
@ -660,7 +660,7 @@ void Record<ESM::Creature>::print()
|
||||||
|
|
||||||
printTransport(mData.getTransport());
|
printTransport(mData.getTransport());
|
||||||
|
|
||||||
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
|
std::cout << " Artificial Intelligence: " << std::endl;
|
||||||
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
|
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
|
||||||
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
||||||
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
||||||
|
@ -668,7 +668,6 @@ void Record<ESM::Creature>::print()
|
||||||
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
||||||
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
||||||
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
||||||
std::cout << " AI U4:" << (int)mData.mAiData.mU4 << std::endl;
|
|
||||||
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
|
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
|
||||||
|
|
||||||
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
|
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
|
||||||
|
@ -1079,7 +1078,7 @@ void Record<ESM::NPC>::print()
|
||||||
|
|
||||||
printTransport(mData.getTransport());
|
printTransport(mData.getTransport());
|
||||||
|
|
||||||
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
|
std::cout << " Artificial Intelligence: " << std::endl;
|
||||||
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
|
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
|
||||||
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
||||||
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
||||||
|
@ -1087,7 +1086,6 @@ void Record<ESM::NPC>::print()
|
||||||
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
||||||
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
||||||
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
||||||
std::cout << " AI U4:" << (int)mData.mAiData.mU4 << std::endl;
|
|
||||||
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
|
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
|
||||||
|
|
||||||
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
|
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
|
||||||
|
|
|
@ -87,6 +87,7 @@ namespace CSMWorld
|
||||||
//CONCRETE TYPES ENDS HERE
|
//CONCRETE TYPES ENDS HERE
|
||||||
|
|
||||||
Display_UnsignedInteger8,
|
Display_UnsignedInteger8,
|
||||||
|
Display_UnsignedInteger16,
|
||||||
Display_Integer,
|
Display_Integer,
|
||||||
Display_Float,
|
Display_Float,
|
||||||
Display_Double,
|
Display_Double,
|
||||||
|
|
|
@ -627,12 +627,12 @@ namespace CSMWorld
|
||||||
RecordT record2 = record.get();
|
RecordT record2 = record.get();
|
||||||
if (column==mActors.mHello)
|
if (column==mActors.mHello)
|
||||||
record2.mAiData.mHello = value.toInt();
|
record2.mAiData.mHello = value.toInt();
|
||||||
else if (column==mActors.mFlee)
|
else if (column==mActors.mFlee) // Flee, Fight and Alarm ratings are probabilities.
|
||||||
record2.mAiData.mFlee = value.toInt();
|
record2.mAiData.mFlee = std::min(100, value.toInt());
|
||||||
else if (column==mActors.mFight)
|
else if (column==mActors.mFight)
|
||||||
record2.mAiData.mFight = value.toInt();
|
record2.mAiData.mFight = std::min(100, value.toInt());
|
||||||
else if (column==mActors.mAlarm)
|
else if (column==mActors.mAlarm)
|
||||||
record2.mAiData.mAlarm = value.toInt();
|
record2.mAiData.mAlarm = std::min(100, value.toInt());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||||
|
|
|
@ -128,7 +128,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
||||||
|
|
||||||
ActorColumns actorsColumns (nameColumns);
|
ActorColumns actorsColumns (nameColumns);
|
||||||
|
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_UnsignedInteger8));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_UnsignedInteger16));
|
||||||
actorsColumns.mHello = &mColumns.back();
|
actorsColumns.mHello = &mColumns.back();
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8));
|
||||||
actorsColumns.mFlee = &mColumns.back();
|
actorsColumns.mFlee = &mColumns.back();
|
||||||
|
|
|
@ -219,6 +219,13 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CSMWorld::ColumnBase::Display_UnsignedInteger16:
|
||||||
|
{
|
||||||
|
DialogueSpinBox *sb = new DialogueSpinBox(parent);
|
||||||
|
sb->setRange(0, std::numeric_limits<unsigned short>::max());
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Var:
|
case CSMWorld::ColumnBase::Display_Var:
|
||||||
|
|
||||||
return new QLineEdit(parent);
|
return new QLineEdit(parent);
|
||||||
|
|
|
@ -608,11 +608,7 @@ namespace MWClass
|
||||||
|
|
||||||
int Creature::getServices(const MWWorld::ConstPtr &actor) const
|
int Creature::getServices(const MWWorld::ConstPtr &actor) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Creature>* ref = actor.get<ESM::Creature>();
|
return actor.get<ESM::Creature>()->mBase->mAiData.mServices;
|
||||||
if (ref->mBase->mHasAI)
|
|
||||||
return ref->mBase->mAiData.mServices;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Creature::isPersistent(const MWWorld::ConstPtr &actor) const
|
bool Creature::isPersistent(const MWWorld::ConstPtr &actor) const
|
||||||
|
|
|
@ -1205,11 +1205,7 @@ namespace MWClass
|
||||||
|
|
||||||
int Npc::getServices(const MWWorld::ConstPtr &actor) const
|
int Npc::getServices(const MWWorld::ConstPtr &actor) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::NPC>* ref = actor.get<ESM::NPC>();
|
return actor.get<ESM::NPC>()->mBase->mAiData.mServices;
|
||||||
if (ref->mBase->mHasAI)
|
|
||||||
return ref->mBase->mAiData.mServices;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace ESM
|
||||||
{
|
{
|
||||||
void AIData::blank()
|
void AIData::blank()
|
||||||
{
|
{
|
||||||
mHello = mU1 = mFight = mFlee = mAlarm = mU2 = mU3 = mU4 = 0;
|
mHello = mFight = mFlee = mAlarm = mU1 = mU2 = mU3 = 0;
|
||||||
mServices = 0;
|
mServices = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,9 @@ namespace ESM
|
||||||
|
|
||||||
struct AIData
|
struct AIData
|
||||||
{
|
{
|
||||||
unsigned char mHello;
|
unsigned short mHello; // This is the base value for greeting distance [0, 65535]
|
||||||
char mU1;
|
|
||||||
unsigned char mFight, mFlee, mAlarm; // These are probabilities [0, 100]
|
unsigned char mFight, mFlee, mAlarm; // These are probabilities [0, 100]
|
||||||
char mU2, mU3, mU4; // Unknown values
|
char mU1, mU2, mU3; // Unknown values
|
||||||
int mServices; // See the Services enum
|
int mServices; // See the Services enum
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
|
|
|
@ -22,8 +22,9 @@ namespace ESM {
|
||||||
mTransport.mList.clear();
|
mTransport.mList.clear();
|
||||||
|
|
||||||
mScale = 1.f;
|
mScale = 1.f;
|
||||||
mHasAI = false;
|
|
||||||
mAiData.blank();
|
mAiData.blank();
|
||||||
|
mAiData.mFight = 90;
|
||||||
|
mAiData.mFlee = 20;
|
||||||
|
|
||||||
bool hasName = false;
|
bool hasName = false;
|
||||||
bool hasNpdt = false;
|
bool hasNpdt = false;
|
||||||
|
@ -68,7 +69,6 @@ namespace ESM {
|
||||||
break;
|
break;
|
||||||
case ESM::FourCC<'A','I','D','T'>::value:
|
case ESM::FourCC<'A','I','D','T'>::value:
|
||||||
esm.getHExact(&mAiData, sizeof(mAiData));
|
esm.getHExact(&mAiData, sizeof(mAiData));
|
||||||
mHasAI = true;
|
|
||||||
break;
|
break;
|
||||||
case ESM::FourCC<'D','O','D','T'>::value:
|
case ESM::FourCC<'D','O','D','T'>::value:
|
||||||
case ESM::FourCC<'D','N','A','M'>::value:
|
case ESM::FourCC<'D','N','A','M'>::value:
|
||||||
|
@ -128,14 +128,7 @@ namespace ESM {
|
||||||
|
|
||||||
mInventory.save(esm);
|
mInventory.save(esm);
|
||||||
mSpells.save(esm);
|
mSpells.save(esm);
|
||||||
if (mAiData.mHello != 0
|
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
|
||||||
|| mAiData.mFight != 0
|
|
||||||
|| mAiData.mFlee != 0
|
|
||||||
|| mAiData.mAlarm != 0
|
|
||||||
|| mAiData.mServices != 0)
|
|
||||||
{
|
|
||||||
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
|
|
||||||
}
|
|
||||||
mTransport.save(esm);
|
mTransport.save(esm);
|
||||||
mAiPackage.save(esm);
|
mAiPackage.save(esm);
|
||||||
}
|
}
|
||||||
|
@ -159,8 +152,9 @@ namespace ESM {
|
||||||
mOriginal.clear();
|
mOriginal.clear();
|
||||||
mInventory.mList.clear();
|
mInventory.mList.clear();
|
||||||
mSpells.mList.clear();
|
mSpells.mList.clear();
|
||||||
mHasAI = false;
|
|
||||||
mAiData.blank();
|
mAiData.blank();
|
||||||
|
mAiData.mFight = 90;
|
||||||
|
mAiData.mFlee = 20;
|
||||||
mAiPackage.mList.clear();
|
mAiPackage.mList.clear();
|
||||||
mTransport.mList.clear();
|
mTransport.mList.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@ struct Creature
|
||||||
InventoryList mInventory;
|
InventoryList mInventory;
|
||||||
SpellList mSpells;
|
SpellList mSpells;
|
||||||
|
|
||||||
bool mHasAI;
|
|
||||||
AIData mAiData;
|
AIData mAiData;
|
||||||
AIPackageList mAiPackage;
|
AIPackageList mAiPackage;
|
||||||
Transport mTransport;
|
Transport mTransport;
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace ESM
|
||||||
mTransport.mList.clear();
|
mTransport.mList.clear();
|
||||||
mAiPackage.mList.clear();
|
mAiPackage.mList.clear();
|
||||||
mAiData.blank();
|
mAiData.blank();
|
||||||
mHasAI = false;
|
mAiData.mHello = mAiData.mFight = mAiData.mFlee = 30;
|
||||||
|
|
||||||
bool hasName = false;
|
bool hasName = false;
|
||||||
bool hasNpdt = false;
|
bool hasNpdt = false;
|
||||||
|
@ -96,7 +96,6 @@ namespace ESM
|
||||||
break;
|
break;
|
||||||
case ESM::FourCC<'A','I','D','T'>::value:
|
case ESM::FourCC<'A','I','D','T'>::value:
|
||||||
esm.getHExact(&mAiData, sizeof(mAiData));
|
esm.getHExact(&mAiData, sizeof(mAiData));
|
||||||
mHasAI= true;
|
|
||||||
break;
|
break;
|
||||||
case ESM::FourCC<'D','O','D','T'>::value:
|
case ESM::FourCC<'D','O','D','T'>::value:
|
||||||
case ESM::FourCC<'D','N','A','M'>::value:
|
case ESM::FourCC<'D','N','A','M'>::value:
|
||||||
|
@ -165,14 +164,7 @@ namespace ESM
|
||||||
|
|
||||||
mInventory.save(esm);
|
mInventory.save(esm);
|
||||||
mSpells.save(esm);
|
mSpells.save(esm);
|
||||||
if (mAiData.mHello != 0
|
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
|
||||||
|| mAiData.mFight != 0
|
|
||||||
|| mAiData.mFlee != 0
|
|
||||||
|| mAiData.mAlarm != 0
|
|
||||||
|| mAiData.mServices != 0)
|
|
||||||
{
|
|
||||||
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
|
|
||||||
}
|
|
||||||
|
|
||||||
mTransport.save(esm);
|
mTransport.save(esm);
|
||||||
|
|
||||||
|
@ -198,7 +190,7 @@ namespace ESM
|
||||||
mInventory.mList.clear();
|
mInventory.mList.clear();
|
||||||
mSpells.mList.clear();
|
mSpells.mList.clear();
|
||||||
mAiData.blank();
|
mAiData.blank();
|
||||||
mHasAI = false;
|
mAiData.mHello = mAiData.mFight = mAiData.mFlee = 30;
|
||||||
mTransport.mList.clear();
|
mTransport.mList.clear();
|
||||||
mAiPackage.mList.clear();
|
mAiPackage.mList.clear();
|
||||||
mName.clear();
|
mName.clear();
|
||||||
|
|
|
@ -122,7 +122,6 @@ struct NPC
|
||||||
SpellList mSpells;
|
SpellList mSpells;
|
||||||
|
|
||||||
AIData mAiData;
|
AIData mAiData;
|
||||||
bool mHasAI;
|
|
||||||
|
|
||||||
Transport mTransport;
|
Transport mTransport;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue