1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 02:09:41 +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 #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 #4876: AI ratings handling inconsistencies
Feature #2229: Improve pathfinding AI
Feature #3442: Default values for fallbacks from ini file
Feature #3610: Option to invert X axis

View file

@ -660,7 +660,7 @@ void Record<ESM::Creature>::print()
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 Fight:" << (int)mData.mAiData.mFight << 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 U2:" << (int)mData.mAiData.mU2 << 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;
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
@ -1079,7 +1078,7 @@ void Record<ESM::NPC>::print()
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 Fight:" << (int)mData.mAiData.mFight << 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 U2:" << (int)mData.mAiData.mU2 << 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;
for (const ESM::AIPackage &package : mData.mAiPackage.mList)

View file

@ -87,6 +87,7 @@ namespace CSMWorld
//CONCRETE TYPES ENDS HERE
Display_UnsignedInteger8,
Display_UnsignedInteger16,
Display_Integer,
Display_Float,
Display_Double,

View file

@ -627,12 +627,12 @@ namespace CSMWorld
RecordT record2 = record.get();
if (column==mActors.mHello)
record2.mAiData.mHello = value.toInt();
else if (column==mActors.mFlee)
record2.mAiData.mFlee = value.toInt();
else if (column==mActors.mFlee) // Flee, Fight and Alarm ratings are probabilities.
record2.mAiData.mFlee = std::min(100, value.toInt());
else if (column==mActors.mFight)
record2.mAiData.mFight = value.toInt();
record2.mAiData.mFight = std::min(100, value.toInt());
else if (column==mActors.mAlarm)
record2.mAiData.mAlarm = value.toInt();
record2.mAiData.mAlarm = std::min(100, value.toInt());
else
{
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =

View file

@ -128,7 +128,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
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();
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8));
actorsColumns.mFlee = &mColumns.back();

View file

@ -219,6 +219,13 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
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:
return new QLineEdit(parent);

View file

@ -608,11 +608,7 @@ namespace MWClass
int Creature::getServices(const MWWorld::ConstPtr &actor) const
{
const MWWorld::LiveCellRef<ESM::Creature>* ref = actor.get<ESM::Creature>();
if (ref->mBase->mHasAI)
return ref->mBase->mAiData.mServices;
else
return 0;
return actor.get<ESM::Creature>()->mBase->mAiData.mServices;
}
bool Creature::isPersistent(const MWWorld::ConstPtr &actor) const

View file

@ -1205,11 +1205,7 @@ namespace MWClass
int Npc::getServices(const MWWorld::ConstPtr &actor) const
{
const MWWorld::LiveCellRef<ESM::NPC>* ref = actor.get<ESM::NPC>();
if (ref->mBase->mHasAI)
return ref->mBase->mAiData.mServices;
else
return 0;
return actor.get<ESM::NPC>()->mBase->mAiData.mServices;
}

View file

@ -7,7 +7,7 @@ namespace ESM
{
void AIData::blank()
{
mHello = mU1 = mFight = mFlee = mAlarm = mU2 = mU3 = mU4 = 0;
mHello = mFight = mFlee = mAlarm = mU1 = mU2 = mU3 = 0;
mServices = 0;
}

View file

@ -16,10 +16,9 @@ namespace ESM
struct AIData
{
unsigned char mHello;
char mU1;
unsigned short mHello; // This is the base value for greeting distance [0, 65535]
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
void blank();

View file

@ -22,8 +22,9 @@ namespace ESM {
mTransport.mList.clear();
mScale = 1.f;
mHasAI = false;
mAiData.blank();
mAiData.mFight = 90;
mAiData.mFlee = 20;
bool hasName = false;
bool hasNpdt = false;
@ -68,7 +69,6 @@ namespace ESM {
break;
case ESM::FourCC<'A','I','D','T'>::value:
esm.getHExact(&mAiData, sizeof(mAiData));
mHasAI = true;
break;
case ESM::FourCC<'D','O','D','T'>::value:
case ESM::FourCC<'D','N','A','M'>::value:
@ -128,14 +128,7 @@ namespace ESM {
mInventory.save(esm);
mSpells.save(esm);
if (mAiData.mHello != 0
|| mAiData.mFight != 0
|| mAiData.mFlee != 0
|| mAiData.mAlarm != 0
|| mAiData.mServices != 0)
{
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
}
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
mTransport.save(esm);
mAiPackage.save(esm);
}
@ -159,8 +152,9 @@ namespace ESM {
mOriginal.clear();
mInventory.mList.clear();
mSpells.mList.clear();
mHasAI = false;
mAiData.blank();
mAiData.mFight = 90;
mAiData.mFlee = 20;
mAiPackage.mList.clear();
mTransport.mList.clear();
}

View file

@ -91,7 +91,6 @@ struct Creature
InventoryList mInventory;
SpellList mSpells;
bool mHasAI;
AIData mAiData;
AIPackageList mAiPackage;
Transport mTransport;

View file

@ -19,7 +19,7 @@ namespace ESM
mTransport.mList.clear();
mAiPackage.mList.clear();
mAiData.blank();
mHasAI = false;
mAiData.mHello = mAiData.mFight = mAiData.mFlee = 30;
bool hasName = false;
bool hasNpdt = false;
@ -96,7 +96,6 @@ namespace ESM
break;
case ESM::FourCC<'A','I','D','T'>::value:
esm.getHExact(&mAiData, sizeof(mAiData));
mHasAI= true;
break;
case ESM::FourCC<'D','O','D','T'>::value:
case ESM::FourCC<'D','N','A','M'>::value:
@ -165,14 +164,7 @@ namespace ESM
mInventory.save(esm);
mSpells.save(esm);
if (mAiData.mHello != 0
|| mAiData.mFight != 0
|| mAiData.mFlee != 0
|| mAiData.mAlarm != 0
|| mAiData.mServices != 0)
{
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
}
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
mTransport.save(esm);
@ -198,7 +190,7 @@ namespace ESM
mInventory.mList.clear();
mSpells.mList.clear();
mAiData.blank();
mHasAI = false;
mAiData.mHello = mAiData.mFight = mAiData.mFlee = 30;
mTransport.mList.clear();
mAiPackage.mList.clear();
mName.clear();

View file

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