1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-21 05:39:42 +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.setHello(ref->base->AI.hello);
data->mCreatureStats.setFight(ref->base->AI.fight);
data->mCreatureStats.setFlee(ref->base->AI.flee);
data->mCreatureStats.setAlarm(ref->base->AI.alarm);
data->mCreatureStats.setHello(ref->base->mAiData.mHello);
data->mCreatureStats.setFight(ref->base->mAiData.mFight);
data->mCreatureStats.setFlee(ref->base->mAiData.mFlee);
data->mCreatureStats.setAlarm(ref->base->mAiData.mAlarm);
// store
ptr.getRefData().setCustomData (data.release());

View file

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

View file

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

View file

@ -291,14 +291,14 @@ namespace MWGui
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{
MWWorld::LiveCellRef<ESM::NPC>* ref = mPtr.get<ESM::NPC>();
if (ref->base->hasAI)
services = ref->base->AI.services;
if (ref->base->mHasAI)
services = ref->base->mAiData.mServices;
}
else if (mPtr.getTypeName() == typeid(ESM::Creature).name())
{
MWWorld::LiveCellRef<ESM::Creature>* ref = mPtr.get<ESM::Creature>();
if (ref->base->hasAI)
services = ref->base->AI.services;
if (ref->base->mHasAI)
services = ref->base->mAiData.mServices;
}
/// \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
loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records
loadweap records aipackage
)
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];
int32_t val;
bool operator==(const char *str)
bool operator==(const char *str) const
{
for(int i=0; i<LEN; i++)
if(name[i] != str[i]) return false;
else if(name[i] == 0) return true;
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();
}
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) { return v != val; }
bool operator==(int v) const { return v == val; }
bool operator!=(int v) const { return v != val; }
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");
inventory.load(esm);
mSpells.load(esm);
if (esm.isNextSub("AIDT"))
{
esm.getHExact(&AI, sizeof(AI));
hasAI = true;
esm.getHExact(&mAiData, sizeof(mAiData));
mHasAI = true;
}
else
hasAI = false;
mHasAI = false;
// More subrecords:
// 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?
mAiPackage.load(esm);
esm.skipRecord();
}
}

View file

@ -3,6 +3,8 @@
#include "esm_reader.hpp"
#include "loadcont.hpp"
#include "defs.hpp"
#include "aipackage.hpp"
namespace ESM
{
@ -51,15 +53,6 @@ struct Creature
int gold;
}; // 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;
int flags;
@ -69,9 +62,11 @@ struct Creature
// Defined in loadcont.hpp
InventoryList inventory;
SpellList mSpells;
bool hasAI;
AIDTstruct AI;
bool mHasAI;
AIData mAiData;
AIPackageList mAiPackage;
std::string mId;

View file

@ -36,12 +36,22 @@ void NPC::load(ESMReader &esm, const std::string& id)
if (esm.isNextSub("AIDT"))
{
esm.getHExact(&AI, sizeof(AI));
hasAI = true;
esm.getHExact(&mAiData, sizeof(mAiData));
mHasAI= true;
}
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();
}

View file

@ -4,6 +4,7 @@
#include "esm_reader.hpp"
#include "loadcont.hpp"
#include "defs.hpp"
#include "aipackage.hpp"
namespace ESM {
@ -18,16 +19,16 @@ struct NPC
{
// This merchant buys:
Weapon = 0x00001,
Armor = 0x00002,
Armor = 0x00002,
Clothing = 0x00004,
Books = 0x00008,
Books = 0x00008,
Ingredients = 0x00010,
Picks = 0x00020,
Picks = 0x00020,
Probes = 0x00040,
Lights = 0x00080,
Apparatus = 0x00100,
RepairItem = 0x00200,
Misc = 0x00400,
Misc = 0x00400,
// Other services
Spells = 0x00800,
@ -46,7 +47,7 @@ struct NPC
Respawn = 0x0004,
Autocalc = 0x0008,
Skeleton = 0x0400, // Skeleton blood effect (white)
Metal = 0x0800 // Metal blood effect (golden?)
Metal = 0x0800 // Metal blood effect (golden?)
};
#pragma pack(push)
@ -71,18 +72,14 @@ struct NPC
unknown1, unknown2, unknown3;
int gold; // ?? not certain
}; // 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)
struct Dest
{
Position mPos;
std::string mCellName;
};
NPDTstruct52 npdt52;
NPDTstruct12 npdt12; // Use this if npdt52.gold == -10
@ -91,16 +88,21 @@ struct NPC
InventoryList inventory;
SpellList spells;
AIDTstruct AI;
bool hasAI;
AIData mAiData;
bool mHasAI;
std::string name, model, race, cls, faction, script,
hair, head; // body parts
std::vector<Dest> mTransport;
AIPackageList mAiPackage;
std::string name, model, race, cls, faction, script;
// body parts
std::string hair, head;
std::string mId;
// Implementation moved to load_impl.cpp
void load(ESMReader &esm, const std::string& id);
// Implementation moved to load_impl.cpp
void load(ESMReader &esm, const std::string& id);
};
}
#endif