1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-04-17 15:06:44 +00:00

Merge remote-tracking branch 'greye/aidata'

This commit is contained in:
Marc Zinnschlag 2012-08-30 09:55:01 +02:00
commit bc34fab17f
12 changed files with 202 additions and 74 deletions

View file

@ -61,10 +61,10 @@ namespace MWClass
data->mCreatureStats.setLevel(ref->base->data.level); data->mCreatureStats.setLevel(ref->base->data.level);
data->mCreatureStats.setHello(ref->base->AI.hello); data->mCreatureStats.setHello(ref->base->mAiData.mHello);
data->mCreatureStats.setFight(ref->base->AI.fight); data->mCreatureStats.setFight(ref->base->mAiData.mFight);
data->mCreatureStats.setFlee(ref->base->AI.flee); data->mCreatureStats.setFlee(ref->base->mAiData.mFlee);
data->mCreatureStats.setAlarm(ref->base->AI.alarm); data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm);
// store // store
ptr.getRefData().setCustomData (data.release()); ptr.getRefData().setCustomData (data.release());

View file

@ -100,10 +100,10 @@ namespace MWClass
/// \todo do something with npdt12 maybe:p /// \todo do something with npdt12 maybe:p
} }
data->mCreatureStats.setHello(ref->base->AI.hello); data->mCreatureStats.setHello(ref->base->mAiData.mHello);
data->mCreatureStats.setFight(ref->base->AI.fight); data->mCreatureStats.setFight(ref->base->mAiData.mFight);
data->mCreatureStats.setFlee(ref->base->AI.flee); data->mCreatureStats.setFlee(ref->base->mAiData.mFlee);
data->mCreatureStats.setAlarm(ref->base->AI.alarm); data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm);
// store // store
ptr.getRefData().setCustomData (data.release()); ptr.getRefData().setCustomData (data.release());

View file

@ -769,14 +769,14 @@ namespace MWDialogue
if (mActor.getTypeName() == typeid(ESM::NPC).name()) if (mActor.getTypeName() == typeid(ESM::NPC).name())
{ {
MWWorld::LiveCellRef<ESM::NPC>* ref = mActor.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC>* ref = mActor.get<ESM::NPC>();
if (ref->base->hasAI) if (ref->base->mHasAI)
services = ref->base->AI.services; services = ref->base->mAiData.mServices;
} }
else if (mActor.getTypeName() == typeid(ESM::Creature).name()) else if (mActor.getTypeName() == typeid(ESM::Creature).name())
{ {
MWWorld::LiveCellRef<ESM::Creature>* ref = mActor.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature>* ref = mActor.get<ESM::Creature>();
if (ref->base->hasAI) if (ref->base->mHasAI)
services = ref->base->AI.services; services = ref->base->mAiData.mServices;
} }
if (services & ESM::NPC::Weapon if (services & ESM::NPC::Weapon

View file

@ -291,14 +291,14 @@ namespace MWGui
if (mPtr.getTypeName() == typeid(ESM::NPC).name()) if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{ {
MWWorld::LiveCellRef<ESM::NPC>* ref = mPtr.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC>* ref = mPtr.get<ESM::NPC>();
if (ref->base->hasAI) if (ref->base->mHasAI)
services = ref->base->AI.services; services = ref->base->mAiData.mServices;
} }
else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) else if (mPtr.getTypeName() == typeid(ESM::Creature).name())
{ {
MWWorld::LiveCellRef<ESM::Creature>* ref = mPtr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature>* ref = mPtr.get<ESM::Creature>();
if (ref->base->hasAI) if (ref->base->mHasAI)
services = ref->base->AI.services; services = ref->base->mAiData.mServices;
} }
/// \todo what about potions, there doesn't seem to be a flag for them?? /// \todo what about potions, there doesn't seem to be a flag for them??

View file

@ -43,7 +43,7 @@ add_component_dir (esm
loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst
loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records loadweap records aipackage
) )
add_component_dir (misc add_component_dir (misc

View file

@ -0,0 +1,37 @@
#include "aipackage.hpp"
namespace ESM
{
void AIPackageList::load(ESMReader &esm)
{
while (esm.hasMoreSubs()) {
// initialize every iteration
AIPackage pack;
esm.getSubName();
if (esm.retSubName() == 0x54444e43) { // CNDT
mList.back().mCellName = esm.getHString();
} else if (esm.retSubName() == AI_Wander) {
pack.mType = AI_Wander;
esm.getHExact(&pack.mWander, 14);
mList.push_back(pack);
} else if (esm.retSubName() == AI_Travel) {
pack.mType = AI_Travel;
esm.getHExact(&pack.mTravel, 16);
mList.push_back(pack);
} else if (esm.retSubName() == AI_Escort ||
esm.retSubName() == AI_Follow)
{
pack.mType =
(esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow;
esm.getHExact(&pack.mTarget, 48);
mList.push_back(pack);
} else if (esm.retSubName() == AI_Activate) {
pack.mType = AI_Activate;
esm.getHExact(&pack.mActivate, 33);
mList.push_back(pack);
} else { // not AI package related data, so leave
return;
}
}
}
}

View file

@ -0,0 +1,95 @@
#ifndef OPENMW_ESM_AIPACKAGE_H
#define OPENMW_ESM_AIPACKAGE_H
#include "esm_reader.hpp"
#include <vector>
namespace ESM
{
#pragma pack(push)
#pragma pack(1)
struct AIData
{
// These are probabilities
char mHello, mU1, mFight, mFlee, mAlarm, mU2, mU3, mU4;
// The last u's might be the skills that this NPC can train you
// in?
int mServices; // See the Services enum
}; // 12 bytes
struct AIWander
{
short mDistance;
short mDuration;
unsigned char mTimeOfDay;
unsigned char mIdle[8];
unsigned char mUnk;
};
struct AITravel
{
float mX, mY, mZ;
long mUnk;
};
struct AITarget
{
float mX, mY, mZ;
short mDuration;
NAME32 mId;
short mUnk;
};
struct AIActivate
{
NAME32 mName;
unsigned char mUnk;
};
#pragma pack(pop)
enum
{
AI_Wander = 0x575f4941,
AI_Travel = 0x545f4941,
AI_Follow = 0x465f4941,
AI_Escort = 0x455f4941,
AI_Activate = 0x415f4941,
};
/// \note Used for storaging packages in a single container
/// w/o manual memory allocation accordingly to policy standards
struct AIPackage
{
int mType;
// Anonymous union
union
{
AIWander mWander;
AITravel mTravel;
AITarget mTarget;
AIActivate mActivate;
};
/// \note for AITarget only, placed here to stick with union,
/// overhead should be not so awful
std::string mCellName;
};
struct AIPackageList
{
std::vector<AIPackage> mList;
/// \note This breaks consistency of subrecords reading:
/// after calling it subrecord name is already read, so
/// it needs to use retSubName() if needed. But, hey, there
/// is only one field left (XSCL) and only two records uses AI
void load(ESMReader &esm);
};
}
#endif

View file

@ -49,23 +49,23 @@ union NAME_T
char name[LEN]; char name[LEN];
int32_t val; int32_t val;
bool operator==(const char *str) bool operator==(const char *str) const
{ {
for(int i=0; i<LEN; i++) for(int i=0; i<LEN; i++)
if(name[i] != str[i]) return false; if(name[i] != str[i]) return false;
else if(name[i] == 0) return true; else if(name[i] == 0) return true;
return str[LEN] == 0; return str[LEN] == 0;
} }
bool operator!=(const char *str) { return !((*this)==str); } bool operator!=(const char *str) const { return !((*this)==str); }
bool operator==(const std::string &str) bool operator==(const std::string &str) const
{ {
return (*this) == str.c_str(); return (*this) == str.c_str();
} }
bool operator!=(const std::string &str) { return !((*this)==str); } bool operator!=(const std::string &str) const { return !((*this)==str); }
bool operator==(int v) { return v == val; } bool operator==(int v) const { return v == val; }
bool operator!=(int v) { return v != val; } bool operator!=(int v) const { return v != val; }
std::string toString() const { return std::string(name, strnlen(name, LEN)); } std::string toString() const { return std::string(name, strnlen(name, LEN)); }
}; };

View file

@ -18,29 +18,18 @@ void Creature::load(ESMReader &esm, const std::string& id)
esm.getHNOT(scale, "XSCL"); esm.getHNOT(scale, "XSCL");
inventory.load(esm); inventory.load(esm);
mSpells.load(esm);
if (esm.isNextSub("AIDT")) if (esm.isNextSub("AIDT"))
{ {
esm.getHExact(&AI, sizeof(AI)); esm.getHExact(&mAiData, sizeof(mAiData));
hasAI = true; mHasAI = true;
} }
else else
hasAI = false; mHasAI = false;
// More subrecords: mAiPackage.load(esm);
// AI_W - wander (14 bytes, i don't understand it)
// short distance
// byte duration
// byte timeOfDay
// byte idle[10]
//
// Rest is optional:
// AI_T - travel?
// AI_F - follow?
// AI_E - escort?
// AI_A - activate?
esm.skipRecord(); esm.skipRecord();
} }
} }

View file

@ -3,6 +3,8 @@
#include "esm_reader.hpp" #include "esm_reader.hpp"
#include "loadcont.hpp" #include "loadcont.hpp"
#include "defs.hpp"
#include "aipackage.hpp"
namespace ESM namespace ESM
{ {
@ -51,15 +53,6 @@ struct Creature
int gold; int gold;
}; // 96 bytes }; // 96 bytes
struct AIDTstruct
{
// These are probabilities
char hello, u1, fight, flee, alarm, u2, u3, u4;
// The last u's might be the skills that this NPC can train you
// in?
int services; // See the NPC::Services enum
}; // 12 bytes
NPDTstruct data; NPDTstruct data;
int flags; int flags;
@ -69,9 +62,11 @@ struct Creature
// Defined in loadcont.hpp // Defined in loadcont.hpp
InventoryList inventory; InventoryList inventory;
SpellList mSpells;
bool hasAI; bool mHasAI;
AIDTstruct AI; AIData mAiData;
AIPackageList mAiPackage;
std::string mId; std::string mId;

View file

@ -36,12 +36,22 @@ void NPC::load(ESMReader &esm, const std::string& id)
if (esm.isNextSub("AIDT")) if (esm.isNextSub("AIDT"))
{ {
esm.getHExact(&AI, sizeof(AI)); esm.getHExact(&mAiData, sizeof(mAiData));
hasAI = true; mHasAI= true;
} }
else else
hasAI = false; mHasAI = false;
while (esm.isNextSub("DODT") || esm.isNextSub("DNAM")) {
if (esm.retSubName() == 0x54444f44) { // DODT struct
Dest dodt;
esm.getHExact(&dodt.mPos, 24);
mTransport.push_back(dodt);
} else if (esm.retSubName() == 0x4d414e44) { // DNAM struct
mTransport.back().mCellName = esm.getHString();
}
}
mAiPackage.load(esm);
esm.skipRecord(); esm.skipRecord();
} }

View file

@ -4,6 +4,7 @@
#include "esm_reader.hpp" #include "esm_reader.hpp"
#include "loadcont.hpp" #include "loadcont.hpp"
#include "defs.hpp" #include "defs.hpp"
#include "aipackage.hpp"
namespace ESM { namespace ESM {
@ -71,18 +72,14 @@ struct NPC
unknown1, unknown2, unknown3; unknown1, unknown2, unknown3;
int gold; // ?? not certain int gold; // ?? not certain
}; // 12 bytes }; // 12 bytes
struct AIDTstruct
{
// These are probabilities
char hello, u1, fight, flee, alarm, u2, u3, u4;
// The last u's might be the skills that this NPC can train you
// in?
int services; // See the Services enum
}; // 12 bytes
#pragma pack(pop) #pragma pack(pop)
struct Dest
{
Position mPos;
std::string mCellName;
};
NPDTstruct52 npdt52; NPDTstruct52 npdt52;
NPDTstruct12 npdt12; // Use this if npdt52.gold == -10 NPDTstruct12 npdt12; // Use this if npdt52.gold == -10
@ -91,11 +88,16 @@ struct NPC
InventoryList inventory; InventoryList inventory;
SpellList spells; SpellList spells;
AIDTstruct AI; AIData mAiData;
bool hasAI; bool mHasAI;
std::string name, model, race, cls, faction, script, std::vector<Dest> mTransport;
hair, head; // body parts AIPackageList mAiPackage;
std::string name, model, race, cls, faction, script;
// body parts
std::string hair, head;
std::string mId; std::string mId;