Add AI packages table to dialogue subview. Also minor bug fixes.

test
cc9cii 10 years ago
parent 60e5ff8811
commit 526b53fce0

@ -192,9 +192,9 @@ namespace CSMWorld
{ ColumnId_NpcDestinations, "Destinations" },
{ ColumnId_DestinationCell, "Cell"},
{ ColumnId_PosX, "X"},
{ ColumnId_PosY, "Y"},
{ ColumnId_PosZ, "Z"},
{ ColumnId_PosX, "Dest X"},
{ ColumnId_PosY, "Dest Y"},
{ ColumnId_PosZ, "Dest Z"},
{ ColumnId_RotX, "Rotation X"},
{ ColumnId_RotY, "Rotation Y"},
{ ColumnId_RotZ, "Rotation Z"},
@ -247,6 +247,17 @@ namespace CSMWorld
{ ColumnId_EffectRange, "Range"},
{ ColumnId_EffectArea, "Area"},
{ ColumnId_AiPackageList, "Ai Packages"},
{ ColumnId_AiPackage, "Package"},
{ ColumnId_AiWanderDist, "Wander Dist"},
{ ColumnId_AiWanderDuration, "Wander Duration"},
{ ColumnId_AiWanderToD, "Wander ToD"},
{ ColumnId_AiWanderIdle, "Wander Idle"},
{ ColumnId_AiWanderRepeat, "Wander Repeat"},
{ ColumnId_AiActivateName, "Activate"},
{ ColumnId_AiTargetId, "Target ID"},
{ ColumnId_AiTargetCell, "Target Cell"},
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },
{ ColumnId_UseValue3, "Use value 3" },

@ -183,9 +183,9 @@ namespace CSMWorld
ColumnId_SpellId = 168,
ColumnId_NpcDestinations = 169,
ColumnId_DestinationCell = 170,
ColumnId_PosX = 171,
ColumnId_PosY = 172,
ColumnId_PosZ = 173,
ColumnId_PosX = 171, // these are float
ColumnId_PosY = 172, // these are float
ColumnId_PosZ = 173, // these are float
ColumnId_RotX = 174,
ColumnId_RotY = 175,
ColumnId_RotZ = 176,
@ -214,9 +214,9 @@ namespace CSMWorld
ColumnId_PathgridPoints = 199,
ColumnId_PathgridIndex = 200,
ColumnId_PathgridPosX = 201,
ColumnId_PathgridPosY = 202,
ColumnId_PathgridPosZ = 203,
ColumnId_PathgridPosX = 201, // these are int
ColumnId_PathgridPosY = 202, // these are int
ColumnId_PathgridPosZ = 203, // these are int
ColumnId_PathgridEdges = 204,
ColumnId_PathgridEdgeIndex = 205,
ColumnId_PathgridEdge0 = 206,
@ -236,6 +236,18 @@ namespace CSMWorld
ColumnId_EffectRange = 217,
ColumnId_EffectArea = 218,
ColumnId_AiPackageList = 219,
ColumnId_AiPackage = 220,
ColumnId_AiWanderDist = 221,
ColumnId_AiWanderDuration = 222,
ColumnId_AiWanderToD = 223,
ColumnId_AiWanderIdle = 224,
ColumnId_AiWanderRepeat = 225,
ColumnId_AiActivateName = 226,
// use ColumnId_PosX, etc for AI destinations
ColumnId_AiTargetId = 227,
ColumnId_AiTargetCell = 228,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.
ColumnId_UseValue1 = 0x10000,

@ -121,7 +121,7 @@ namespace CSMWorld
ESM::Pathgrid::Point point = pathgrid.mPoints[subRowIndex];
switch (subColIndex)
{
case 0: break;
case 0: return; // return without saving
case 1: point.mX = value.toInt(); break;
case 2: point.mY = value.toInt(); break;
case 3: point.mZ = value.toInt(); break;
@ -228,7 +228,7 @@ namespace CSMWorld
ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex];
switch (subColIndex)
{
case 0: break;
case 0: return; // return without saving
case 1: edge.mV0 = value.toInt(); break;
case 2: edge.mV1 = value.toInt(); break;
default: throw std::runtime_error("Pathgrid edge subcolumn index out of range");

@ -457,7 +457,8 @@ namespace CSMWorld
effect.mRange = ESM::RT_Touch;
else if (effectId == "Target")
effect.mRange = ESM::RT_Target;
// else leave unchanged
else
return; // leave unchanged
break;
}
case 4: effect.mArea = value.toInt(); break;

@ -10,8 +10,6 @@
#include <components/esm/loadappa.hpp>
#include <components/esm/loadnpc.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/loadcont.hpp>
#include <components/esm/transport.hpp>
#include "record.hpp"
#include "refiddata.hpp"
@ -489,6 +487,7 @@ namespace CSMWorld
const RefIdColumn *mInventory;
const RefIdColumn *mSpells;
const RefIdColumn *mDestinations;
const RefIdColumn *mAiPackages;
std::map<const RefIdColumn *, unsigned int> mServices;
ActorColumns (const NameColumns& base) : NameColumns (base) {}
@ -549,6 +548,9 @@ namespace CSMWorld
if (column==mActors.mDestinations)
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
if (column==mActors.mAiPackages)
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mActors.mServices.find (column);
@ -985,7 +987,7 @@ namespace CSMWorld
ESXRecordT container = record.get();
container.mInventory.mList =
static_cast<const NestedTableWrapper<typename std::vector<ESM::ContItem> >&>(nestedTable).mNestedTable;
static_cast<const NestedTableWrapper<std::vector<typename ESM::ContItem> >&>(nestedTable).mNestedTable;
record.setModified (container);
}
@ -997,7 +999,7 @@ namespace CSMWorld
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<typename std::vector<ESM::ContItem> >(record.get().mInventory.mList);
return new NestedTableWrapper<std::vector<typename ESM::ContItem> >(record.get().mInventory.mList);
}
virtual QVariant getNestedData (const RefIdColumn *column,
@ -1123,7 +1125,7 @@ namespace CSMWorld
ESXRecordT caster = record.get();
caster.mSpells.mList =
static_cast<const NestedTableWrapper<typename std::vector<std::string> >&>(nestedTable).mNestedTable;
static_cast<const NestedTableWrapper<std::vector<typename std::string> >&>(nestedTable).mNestedTable;
record.setModified (caster);
}
@ -1135,7 +1137,7 @@ namespace CSMWorld
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<typename std::vector<std::string> >(record.get().mSpells.mList);
return new NestedTableWrapper<std::vector<typename std::string> >(record.get().mSpells.mList);
}
virtual QVariant getNestedData (const RefIdColumn *column,
@ -1258,7 +1260,7 @@ namespace CSMWorld
ESXRecordT traveller = record.get();
traveller.mTransport.mList =
static_cast<const NestedTableWrapper<typename std::vector<ESM::Transport::Dest> >&>(nestedTable).mNestedTable;
static_cast<const NestedTableWrapper<std::vector<typename ESM::Transport::Dest> >&>(nestedTable).mNestedTable;
record.setModified (traveller);
}
@ -1270,7 +1272,7 @@ namespace CSMWorld
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<typename std::vector<ESM::Transport::Dest> >(record.get().mTransport.mList);
return new NestedTableWrapper<std::vector<typename ESM::Transport::Dest> >(record.get().mTransport.mList);
}
virtual QVariant getNestedData (const RefIdColumn *column,
@ -1375,6 +1377,304 @@ namespace CSMWorld
return static_cast<int>(record.get().mTransport.mList.size());
}
};
template <typename ESXRecordT>
class ActorAiRefIdAdapter : public NestedRefIdAdapterBase
{
UniversalId::Type mType;
// not implemented
ActorAiRefIdAdapter (const ActorAiRefIdAdapter&);
ActorAiRefIdAdapter& operator= (const ActorAiRefIdAdapter&);
public:
ActorAiRefIdAdapter(UniversalId::Type type) :mType(type) {}
virtual ~ActorAiRefIdAdapter() {}
virtual void addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
ESXRecordT actor = record.get();
std::vector<ESM::AIPackage>& list = actor.mAiPackage.mList;
ESM::AIPackage newRow;
newRow.mType = ESM::AI_CNDT;
newRow.mCellName = "";
if (position >= (int)list.size())
list.push_back(newRow);
else
list.insert(list.begin()+position, newRow);
record.setModified (actor);
}
virtual void removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
ESXRecordT actor = record.get();
std::vector<ESM::AIPackage>& list = actor.mAiPackage.mList;
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (list.size()))
throw std::runtime_error ("index out of range");
list.erase (list.begin () + rowToRemove);
record.setModified (actor);
}
virtual void setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
ESXRecordT actor = record.get();
actor.mAiPackage.mList =
static_cast<const NestedTableWrapper<std::vector<typename ESM::AIPackage> >&>(nestedTable).mNestedTable;
record.setModified (actor);
}
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const
{
const Record<ESXRecordT>& record =
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename ESM::AIPackage> >(record.get().mAiPackage.mList);
}
virtual QVariant getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
{
const Record<ESXRecordT>& record =
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
const std::vector<ESM::AIPackage>& list = record.get().mAiPackage.mList;
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (list.size()))
throw std::runtime_error ("index out of range");
const ESM::AIPackage& content = list.at(subRowIndex);
switch (subColIndex)
{
case 0:
switch (content.mType)
{
case ESM::AI_Wander: return QString("AI Wander");
case ESM::AI_Travel: return QString("AI Travel");
case ESM::AI_Follow: return QString("AI Follow");
case ESM::AI_Escort: return QString("AI Escort");
case ESM::AI_Activate: return QString("AI Activate");
case ESM::AI_CNDT:
default: return QString("None");
}
case 1: // wander dist
if (content.mType == ESM::AI_Wander)
return content.mWander.mDistance;
else
return QVariant();
case 2: // wander dur
if (content.mType == ESM::AI_Wander ||
content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
return content.mWander.mDuration;
else
return QVariant();
case 3: // wander ToD
if (content.mType == ESM::AI_Wander)
return content.mWander.mTimeOfDay; // FIXME: not sure of the format
else
return QVariant();
case 4: // wander idle
if (content.mType == ESM::AI_Wander)
{
return static_cast<int>(content.mWander.mIdle[0]); // FIXME:
}
else
return QVariant();
case 5: // wander repeat
if (content.mType == ESM::AI_Wander)
return QString(content.mWander.mShouldRepeat ? "Yes" : "No");
else
return QVariant();
case 6: // activate name
if (content.mType == ESM::AI_Activate)
return QString(content.mActivate.mName.toString().c_str());
else
return QVariant();
case 7: // target id
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
return QString(content.mTarget.mId.toString().c_str());
else
return QVariant();
case 8: // target cell
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
return QString::fromUtf8(content.mCellName.c_str());
else
return QVariant();
case 9:
if (content.mType == ESM::AI_Travel)
return content.mTravel.mX;
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
return content.mTarget.mX;
else
return QVariant();
case 10:
if (content.mType == ESM::AI_Travel)
return content.mTravel.mY;
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
return content.mTarget.mY;
else
return QVariant();
case 11:
if (content.mType == ESM::AI_Travel)
return content.mTravel.mZ;
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
return content.mTarget.mZ;
else
return QVariant();
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
}
virtual void setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (row, mType)));
ESXRecordT actor = record.get();
std::vector<ESM::AIPackage>& list = actor.mAiPackage.mList;
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (list.size()))
throw std::runtime_error ("index out of range");
ESM::AIPackage& content = list.at(subRowIndex);
switch(subColIndex)
{
case 0: // ai package type
if ("AI Wander" == value.toString().toStdString())
content.mType = ESM::AI_Wander;
else if ("AI Travel" == value.toString().toStdString())
content.mType = ESM::AI_Travel;
else if ("AI Follow" == value.toString().toStdString())
content.mType = ESM::AI_Follow;
else if ("AI Escort" == value.toString().toStdString())
content.mType = ESM::AI_Escort;
else if ("AI Activate" == value.toString().toStdString())
content.mType = ESM::AI_Activate;
else
content.mType = ESM::AI_CNDT;
break; // always save
case 1:
if (content.mType == ESM::AI_Wander)
content.mWander.mDistance = static_cast<short>(value.toInt());
else
return; // return without saving
case 2:
if (content.mType == ESM::AI_Wander ||
content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
content.mWander.mDuration = static_cast<short>(value.toInt());
else
return; // return without saving
case 3:
if (content.mType == ESM::AI_Wander)
content.mWander.mTimeOfDay = static_cast<unsigned char>(value.toInt());
else
return; // return without saving
case 4:
if (content.mType == ESM::AI_Wander)
break; // FIXME: idle
else
return; // return without saving
case 5:
if (content.mType == ESM::AI_Wander)
{
if ("Yes" == value.toString().toStdString())
content.mWander.mShouldRepeat = 1;
if ("No" == value.toString().toStdString())
content.mWander.mShouldRepeat = 0;
else
return; // return without saving
}
case 6: // NAME32
if (content.mType == ESM::AI_Activate)
{
content.mActivate.mName.assign(value.toString().toUtf8().constData());
break;
}
else
return; // return without saving
case 7: // NAME32
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
{
content.mTarget.mId.assign(value.toString().toUtf8().constData());
break;
}
else
return; // return without saving
case 8:
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
{
content.mCellName = std::string(value.toString().toUtf8().constData());
break;
}
else
return; // return without saving
case 9:
if (content.mType == ESM::AI_Travel)
content.mTravel.mZ = value.toFloat();
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
content.mTarget.mZ = value.toFloat();
else
return; // return without saving
case 10:
if (content.mType == ESM::AI_Travel)
content.mTravel.mZ = value.toFloat();
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
content.mTarget.mZ = value.toFloat();
else
return; // return without saving
case 11:
if (content.mType == ESM::AI_Travel)
content.mTravel.mZ = value.toFloat();
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
content.mTarget.mZ = value.toFloat();
else
return; // return without saving
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
record.setModified (actor);
}
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
{
return 12;
}
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
{
const Record<ESXRecordT>& record =
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
return static_cast<int>(record.get().mAiPackage.mList.size());
}
};
}
#endif

@ -180,6 +180,42 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float));
// Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
actorsColumns.mAiPackages = &mColumns.back();
std::map<UniversalId::Type, NestedRefIdAdapterBase*> aiMap;
aiMap.insert(
std::make_pair(UniversalId::Type_Npc, new ActorAiRefIdAdapter<ESM::NPC> (UniversalId::Type_Npc)));
aiMap.insert(
std::make_pair(UniversalId::Type_Creature, new ActorAiRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), aiMap));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiPackage, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderDist, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderDuration, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderIdle, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiActivateName, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiTargetId, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiTargetCell, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PosY, CSMWorld::ColumnBase::Display_Float));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float));
static const struct
{
int mName;

Loading…
Cancel
Save