Commit 594ea39f authored by Capostrophic's avatar Capostrophic

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
parent acbc885a
......@@ -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
......
......@@ -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)
......
......@@ -87,6 +87,7 @@ namespace CSMWorld
//CONCRETE TYPES ENDS HERE
Display_UnsignedInteger8,
Display_UnsignedInteger16,
Display_Integer,
Display_Float,
Display_Double,
......
......@@ -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 =
......
......@@ -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();
......
......@@ -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);
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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();
......
......@@ -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();
}
......
......@@ -91,7 +91,6 @@ struct Creature
InventoryList mInventory;
SpellList mSpells;
bool mHasAI;
AIData mAiData;
AIPackageList mAiPackage;
Transport mTransport;
......
......@@ -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();
......
......@@ -122,7 +122,6 @@ struct NPC
SpellList mSpells;
AIData mAiData;
bool mHasAI;
Transport mTransport;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment