1
0
Fork 0
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:
Capostrophic 2019-02-08 16:32:34 +03:00
parent acbc885ae6
commit 594ea39f5d
14 changed files with 29 additions and 47 deletions

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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 =

View file

@ -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();

View file

@ -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);

View file

@ -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

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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();

View file

@ -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();
} }

View file

@ -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;

View file

@ -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();

View file

@ -122,7 +122,6 @@ struct NPC
SpellList mSpells; SpellList mSpells;
AIData mAiData; AIData mAiData;
bool mHasAI;
Transport mTransport; Transport mTransport;