From 02d7aa41355a9cfc68061d583f9aa592fcd935f9 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 29 Aug 2012 14:01:10 +0400 Subject: [PATCH 1/3] npc ai packages --- components/esm/defs_ai.hpp | 128 ++++++++++++++++++++++++++++++++++ components/esm/esm_reader.hpp | 12 ++-- components/esm/loadcrea.hpp | 10 +-- components/esm/loadnpc.cpp | 10 +++ components/esm/loadnpc.hpp | 20 +++--- 5 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 components/esm/defs_ai.hpp diff --git a/components/esm/defs_ai.hpp b/components/esm/defs_ai.hpp new file mode 100644 index 0000000000..a7f2a26ea4 --- /dev/null +++ b/components/esm/defs_ai.hpp @@ -0,0 +1,128 @@ +#ifndef _ESM_DEFS_AI_H +#define _ESM_DEFS_AI_H + +#include "esm_reader.hpp" + +#include + +namespace ESM +{ + #pragma pack(push) + #pragma pack(1) + + 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 + + struct AIWander + { + short distance; + short duration; + char timeOfDay; + char idle[8]; + char unk; + }; + + struct AITravel + { + float x, y, z; + long unk; + }; + + struct AITarget + { + float x, y, z; + short duration; + NAME32 id; + short unk; + }; + + struct AIActivate + { + NAME32 name; + char unk; + }; + + #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 type; + + // Anonymous union + union + { + AIWander wander; + AITravel travel; + AITarget target; + AIActivate activate; + }; + + /// \note for AITarget only, placed here to stick with union, + /// overhead should be not so awful + std::string cellName; + }; + + struct AIPackageList + { + std::vector list; + + /// \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) { + while (esm.hasMoreSubs()) { + // initialize every iteration + AIPackage pack; + + esm.getSubName(); + std::cout << esm.retSubName().toString() << std::endl; + if (esm.retSubName() == 0x54444e43) { // CNDT + list.back().cellName = esm.getHString(); + } else if (esm.retSubName() == AI_Wander) { + pack.type = AI_Wander; + esm.getHExact(&pack.wander, 14); + list.push_back(pack); + } else if (esm.retSubName() == AI_Travel) { + pack.type = AI_Travel; + esm.getHExact(&pack.travel, 16); + list.push_back(pack); + } else if (esm.retSubName() == AI_Escort || + esm.retSubName() == AI_Follow) + { + pack.type = + (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow; + + esm.getHExact(&pack.target, 48); + list.push_back(pack); + } else if (esm.retSubName() == AI_Activate) { + pack.type = AI_Activate; + esm.getHExact(&pack.activate, 33); + list.push_back(pack); + } else { // not AI package related data, so leave + return; + } + } + } + }; +} + +#endif + diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 13f1f4a019..66c0710a68 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -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 dest; + AIPackageList aiPack; + std::string name, model, race, cls, faction, script, hair, head; // body parts From 75fa0288a34b8ae5e08b44d8859c5b5404d0c9aa Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 29 Aug 2012 14:34:27 +0400 Subject: [PATCH 2/3] fix creatures has spells, creatures ai data --- components/esm/defs_ai.hpp | 1 - components/esm/loadcrea.cpp | 15 ++------------- components/esm/loadcrea.hpp | 3 +++ 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/components/esm/defs_ai.hpp b/components/esm/defs_ai.hpp index a7f2a26ea4..b14cc7d650 100644 --- a/components/esm/defs_ai.hpp +++ b/components/esm/defs_ai.hpp @@ -93,7 +93,6 @@ namespace ESM AIPackage pack; esm.getSubName(); - std::cout << esm.retSubName().toString() << std::endl; if (esm.retSubName() == 0x54444e43) { // CNDT list.back().cellName = esm.getHString(); } else if (esm.retSubName() == AI_Wander) { diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 8af3526a0f..fcef9ccd46 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -18,6 +18,7 @@ void Creature::load(ESMReader &esm, const std::string& id) esm.getHNOT(scale, "XSCL"); inventory.load(esm); + spells.load(esm); if (esm.isNextSub("AIDT")) { @@ -27,20 +28,8 @@ void Creature::load(ESMReader &esm, const std::string& id) else hasAI = 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? + aiPack.load(esm); esm.skipRecord(); - } } diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 364b10eebb..9db1f3fff2 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -3,6 +3,7 @@ #include "esm_reader.hpp" #include "loadcont.hpp" +#include "defs.hpp" #include "defs_ai.hpp" namespace ESM @@ -61,9 +62,11 @@ struct Creature // Defined in loadcont.hpp InventoryList inventory; + SpellList spells; bool hasAI; AIDTstruct AI; + AIPackageList aiPack; std::string mId; From a90547bbbef6ff431ac5e5047f25aefc018531b9 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 29 Aug 2012 21:35:06 +0400 Subject: [PATCH 3/3] code formatting --- apps/openmw/mwclass/creature.cpp | 8 +- apps/openmw/mwclass/npc.cpp | 8 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 8 +- apps/openmw/mwgui/tradewindow.cpp | 8 +- components/CMakeLists.txt | 2 +- components/esm/aipackage.cpp | 37 +++++ components/esm/aipackage.hpp | 95 +++++++++++++ components/esm/defs_ai.hpp | 127 ------------------ components/esm/loadcrea.cpp | 10 +- components/esm/loadcrea.hpp | 10 +- components/esm/loadnpc.cpp | 14 +- components/esm/loadnpc.hpp | 34 ++--- 12 files changed, 184 insertions(+), 177 deletions(-) create mode 100644 components/esm/aipackage.cpp create mode 100644 components/esm/aipackage.hpp delete mode 100644 components/esm/defs_ai.hpp diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index a22c2d661d..7c60216528 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -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()); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 94c98ba425..909c681a57 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -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()); diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index acd7868921..841e36bf46 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -769,14 +769,14 @@ namespace MWDialogue if (mActor.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mActor.get(); - 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* ref = mActor.get(); - if (ref->base->hasAI) - services = ref->base->AI.services; + if (ref->base->mHasAI) + services = ref->base->mAiData.mServices; } if (services & ESM::NPC::Weapon diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 8471367c68..9abd97bb7e 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -291,14 +291,14 @@ namespace MWGui if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::LiveCellRef* ref = mPtr.get(); - 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* ref = mPtr.get(); - 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?? diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index c0585d5ee5..1bc5e65f8b 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -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 diff --git a/components/esm/aipackage.cpp b/components/esm/aipackage.cpp new file mode 100644 index 0000000000..a2fd8beb19 --- /dev/null +++ b/components/esm/aipackage.cpp @@ -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; + } + } + } +} diff --git a/components/esm/aipackage.hpp b/components/esm/aipackage.hpp new file mode 100644 index 0000000000..3a8547402a --- /dev/null +++ b/components/esm/aipackage.hpp @@ -0,0 +1,95 @@ +#ifndef OPENMW_ESM_AIPACKAGE_H +#define OPENMW_ESM_AIPACKAGE_H + +#include "esm_reader.hpp" + +#include + +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 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 + diff --git a/components/esm/defs_ai.hpp b/components/esm/defs_ai.hpp deleted file mode 100644 index b14cc7d650..0000000000 --- a/components/esm/defs_ai.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _ESM_DEFS_AI_H -#define _ESM_DEFS_AI_H - -#include "esm_reader.hpp" - -#include - -namespace ESM -{ - #pragma pack(push) - #pragma pack(1) - - 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 - - struct AIWander - { - short distance; - short duration; - char timeOfDay; - char idle[8]; - char unk; - }; - - struct AITravel - { - float x, y, z; - long unk; - }; - - struct AITarget - { - float x, y, z; - short duration; - NAME32 id; - short unk; - }; - - struct AIActivate - { - NAME32 name; - char unk; - }; - - #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 type; - - // Anonymous union - union - { - AIWander wander; - AITravel travel; - AITarget target; - AIActivate activate; - }; - - /// \note for AITarget only, placed here to stick with union, - /// overhead should be not so awful - std::string cellName; - }; - - struct AIPackageList - { - std::vector list; - - /// \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) { - while (esm.hasMoreSubs()) { - // initialize every iteration - AIPackage pack; - - esm.getSubName(); - if (esm.retSubName() == 0x54444e43) { // CNDT - list.back().cellName = esm.getHString(); - } else if (esm.retSubName() == AI_Wander) { - pack.type = AI_Wander; - esm.getHExact(&pack.wander, 14); - list.push_back(pack); - } else if (esm.retSubName() == AI_Travel) { - pack.type = AI_Travel; - esm.getHExact(&pack.travel, 16); - list.push_back(pack); - } else if (esm.retSubName() == AI_Escort || - esm.retSubName() == AI_Follow) - { - pack.type = - (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow; - - esm.getHExact(&pack.target, 48); - list.push_back(pack); - } else if (esm.retSubName() == AI_Activate) { - pack.type = AI_Activate; - esm.getHExact(&pack.activate, 33); - list.push_back(pack); - } else { // not AI package related data, so leave - return; - } - } - } - }; -} - -#endif - diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index fcef9ccd46..e729447877 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -18,17 +18,17 @@ void Creature::load(ESMReader &esm, const std::string& id) esm.getHNOT(scale, "XSCL"); inventory.load(esm); - spells.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; - aiPack.load(esm); + mAiPackage.load(esm); esm.skipRecord(); } diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 9db1f3fff2..59e9264464 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -4,7 +4,7 @@ #include "esm_reader.hpp" #include "loadcont.hpp" #include "defs.hpp" -#include "defs_ai.hpp" +#include "aipackage.hpp" namespace ESM { @@ -62,11 +62,11 @@ struct Creature // Defined in loadcont.hpp InventoryList inventory; - SpellList spells; + SpellList mSpells; - bool hasAI; - AIDTstruct AI; - AIPackageList aiPack; + bool mHasAI; + AIData mAiData; + AIPackageList mAiPackage; std::string mId; diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 9fba482469..637aa0e622 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -36,22 +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.pos, 24); - dest.push_back(dodt); + esm.getHExact(&dodt.mPos, 24); + mTransport.push_back(dodt); } else if (esm.retSubName() == 0x4d414e44) { // DNAM struct - dest.back().cellName = esm.getHString(); + mTransport.back().mCellName = esm.getHString(); } } - aiPack.load(esm); + mAiPackage.load(esm); esm.skipRecord(); } diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index c636d1f319..eec978e9f2 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -4,7 +4,7 @@ #include "esm_reader.hpp" #include "loadcont.hpp" #include "defs.hpp" -#include "defs_ai.hpp" +#include "aipackage.hpp" namespace ESM { @@ -19,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, @@ -47,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) @@ -76,8 +76,8 @@ struct NPC struct Dest { - Position pos; - std::string cellName; + Position mPos; + std::string mCellName; }; NPDTstruct52 npdt52; @@ -88,19 +88,21 @@ struct NPC InventoryList inventory; SpellList spells; - AIDTstruct AI; - bool hasAI; + AIData mAiData; + bool mHasAI; - std::vector dest; - AIPackageList aiPack; + std::vector mTransport; + AIPackageList mAiPackage; - std::string name, model, race, cls, faction, script, - hair, head; // body parts + 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