mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:53:50 +00:00
Mutate base records when editing AI settings (#2798)
This commit is contained in:
parent
1759276ac5
commit
4d7947d27c
14 changed files with 112 additions and 22 deletions
|
@ -35,6 +35,7 @@ namespace ESM
|
|||
struct Position;
|
||||
struct Cell;
|
||||
struct Class;
|
||||
struct Creature;
|
||||
struct Potion;
|
||||
struct Spell;
|
||||
struct NPC;
|
||||
|
@ -377,6 +378,14 @@ namespace MWBase
|
|||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||
/// \return pointer to created record
|
||||
|
||||
virtual const ESM::Creature *createOverrideRecord (const ESM::Creature& record) = 0;
|
||||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||
/// \return pointer to created record
|
||||
|
||||
virtual const ESM::NPC *createOverrideRecord (const ESM::NPC& record) = 0;
|
||||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||
/// \return pointer to created record
|
||||
|
||||
virtual void update (float duration, bool paused) = 0;
|
||||
virtual void updatePhysics (float duration, bool paused) = 0;
|
||||
|
||||
|
|
|
@ -878,4 +878,9 @@ namespace MWClass
|
|||
const MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||
scale *= ref->mBase->mScale;
|
||||
}
|
||||
|
||||
void Creature::setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const
|
||||
{
|
||||
MWMechanics::setBaseAISetting<ESM::Creature>(id, setting, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,8 @@ namespace MWClass
|
|||
|
||||
virtual void adjustScale(const MWWorld::ConstPtr& ptr, osg::Vec3f& scale, bool rendering) const;
|
||||
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
|
||||
|
||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1437,4 +1437,9 @@ namespace MWClass
|
|||
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
return ref->mBase->getFactionRank();
|
||||
}
|
||||
|
||||
void Npc::setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const
|
||||
{
|
||||
MWMechanics::setBaseAISetting<ESM::NPC>(id, setting, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,6 +164,8 @@ namespace MWClass
|
|||
|
||||
virtual std::string getPrimaryFaction(const MWWorld::ConstPtr &ptr) const;
|
||||
virtual int getPrimaryFactionRank(const MWWorld::ConstPtr &ptr) const;
|
||||
|
||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
#ifndef OPENMW_MWMECHANICS_ACTORUTIL_H
|
||||
#define OPENMW_MWMECHANICS_ACTORUTIL_H
|
||||
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "./creaturestats.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Ptr;
|
||||
|
@ -11,6 +21,33 @@ namespace MWMechanics
|
|||
MWWorld::Ptr getPlayer();
|
||||
bool isPlayerInCombat();
|
||||
bool canActorMoveByZAxis(const MWWorld::Ptr& actor);
|
||||
|
||||
template<class T>
|
||||
void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value)
|
||||
{
|
||||
T copy = *MWBase::Environment::get().getWorld()->getStore().get<T>().find(id);
|
||||
switch(setting)
|
||||
{
|
||||
case MWMechanics::CreatureStats::AiSetting::AI_Hello:
|
||||
copy.mAiData.mHello = value;
|
||||
break;
|
||||
case MWMechanics::CreatureStats::AiSetting::AI_Fight:
|
||||
copy.mAiData.mFight = value;
|
||||
break;
|
||||
case MWMechanics::CreatureStats::AiSetting::AI_Flee:
|
||||
copy.mAiData.mFlee = value;
|
||||
break;
|
||||
case MWMechanics::CreatureStats::AiSetting::AI_Alarm:
|
||||
copy.mAiData.mAlarm = value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->createOverrideRecord(copy);
|
||||
}
|
||||
|
||||
template void setBaseAISetting<ESM::Creature>(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value);
|
||||
template void setBaseAISetting<ESM::NPC>(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -257,8 +257,10 @@ namespace MWScript
|
|||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
ptr.getClass().getCreatureStats (ptr).setAiSetting (mIndex,
|
||||
ptr.getClass().getCreatureStats (ptr).getAiSetting (mIndex).getBase() + value);
|
||||
int modified = ptr.getClass().getCreatureStats (ptr).getAiSetting (mIndex).getBase() + value;
|
||||
|
||||
ptr.getClass().getCreatureStats (ptr).setAiSetting (mIndex, modified);
|
||||
ptr.getClass().setBaseAISetting(ptr.getCellRef().getRefId(), mIndex, modified);
|
||||
}
|
||||
};
|
||||
template<class R>
|
||||
|
@ -277,6 +279,7 @@ namespace MWScript
|
|||
MWMechanics::Stat<int> stat = ptr.getClass().getCreatureStats(ptr).getAiSetting(mIndex);
|
||||
stat.setModified(value, 0);
|
||||
ptr.getClass().getCreatureStats(ptr).setAiSetting(mIndex, stat);
|
||||
ptr.getClass().setBaseAISetting(ptr.getCellRef().getRefId(), mIndex, value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -460,6 +460,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
case ESM::REC_ENAB:
|
||||
case ESM::REC_LEVC:
|
||||
case ESM::REC_LEVI:
|
||||
case ESM::REC_CREA:
|
||||
MWBase::Environment::get().getWorld()->readRecord(reader, n.intval, contentFileMap);
|
||||
break;
|
||||
|
||||
|
|
|
@ -516,4 +516,9 @@ namespace MWWorld
|
|||
result.z() = magicEffect->mData.mBlue / 255.f;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Class::setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const
|
||||
{
|
||||
throw std::runtime_error ("class does not have creature stats");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "ptr.hpp"
|
||||
#include "doorstate.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -28,7 +29,6 @@ namespace MWPhysics
|
|||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class CreatureStats;
|
||||
class NpcStats;
|
||||
struct Movement;
|
||||
}
|
||||
|
@ -360,6 +360,8 @@ namespace MWWorld
|
|||
virtual float getEffectiveArmorRating(const MWWorld::ConstPtr& armor, const MWWorld::Ptr& actor) const;
|
||||
|
||||
virtual osg::Vec4f getEnchantmentColor(const MWWorld::ConstPtr& item) const;
|
||||
|
||||
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -273,7 +273,8 @@ void ESMStore::validate()
|
|||
+mSpells.getDynamicSize()
|
||||
+mWeapons.getDynamicSize()
|
||||
+mCreatureLists.getDynamicSize()
|
||||
+mItemLists.getDynamicSize();
|
||||
+mItemLists.getDynamicSize()
|
||||
+mCreatures.getDynamicSize();
|
||||
}
|
||||
|
||||
void ESMStore::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||
|
@ -295,6 +296,7 @@ void ESMStore::validate()
|
|||
mNpcs.write (writer, progress);
|
||||
mItemLists.write (writer, progress);
|
||||
mCreatureLists.write (writer, progress);
|
||||
mCreatures.write (writer, progress);
|
||||
}
|
||||
|
||||
bool ESMStore::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
|
@ -312,24 +314,8 @@ void ESMStore::validate()
|
|||
case ESM::REC_NPC_:
|
||||
case ESM::REC_LEVI:
|
||||
case ESM::REC_LEVC:
|
||||
|
||||
{
|
||||
mStores[type]->read (reader);
|
||||
}
|
||||
|
||||
if (type==ESM::REC_NPC_)
|
||||
{
|
||||
// NPC record will always be last and we know that there can be only one
|
||||
// dynamic NPC record (player) -> We are done here with dynamic record loading
|
||||
setUp();
|
||||
|
||||
const ESM::NPC *player = mNpcs.find ("player");
|
||||
|
||||
if (!mRaces.find (player->mRace) ||
|
||||
!mClasses.find (player->mClass))
|
||||
throw std::runtime_error ("Invalid player record (race or class unavailable");
|
||||
}
|
||||
|
||||
case ESM::REC_CREA:
|
||||
mStores[type]->read (reader);
|
||||
return true;
|
||||
|
||||
case ESM::REC_DYNA:
|
||||
|
@ -343,4 +329,15 @@ void ESMStore::validate()
|
|||
}
|
||||
}
|
||||
|
||||
void ESMStore::checkPlayer()
|
||||
{
|
||||
setUp();
|
||||
|
||||
const ESM::NPC *player = mNpcs.find ("player");
|
||||
|
||||
if (!mRaces.find (player->mRace) ||
|
||||
!mClasses.find (player->mClass))
|
||||
throw std::runtime_error ("Invalid player record (race or class unavailable");
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
|
|
@ -239,6 +239,9 @@ namespace MWWorld
|
|||
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
///< \return Known type?
|
||||
|
||||
// To be called when we are done with dynamic record loading
|
||||
void checkPlayer();
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
|
@ -403,6 +403,7 @@ namespace MWWorld
|
|||
reader.getHNT(mLevitationEnabled, "LEVT");
|
||||
return;
|
||||
case ESM::REC_PLAY:
|
||||
mStore.checkPlayer();
|
||||
mPlayer->readRecord(reader, type);
|
||||
if (getPlayerPtr().isInCell())
|
||||
{
|
||||
|
@ -1815,6 +1816,16 @@ namespace MWWorld
|
|||
return mStore.overrideRecord(record);
|
||||
}
|
||||
|
||||
const ESM::Creature *World::createOverrideRecord(const ESM::Creature &record)
|
||||
{
|
||||
return mStore.overrideRecord(record);
|
||||
}
|
||||
|
||||
const ESM::NPC *World::createOverrideRecord(const ESM::NPC &record)
|
||||
{
|
||||
return mStore.overrideRecord(record);
|
||||
}
|
||||
|
||||
const ESM::NPC *World::createRecord(const ESM::NPC &record)
|
||||
{
|
||||
bool update = false;
|
||||
|
|
|
@ -490,6 +490,14 @@ namespace MWWorld
|
|||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||
/// \return pointer to created record
|
||||
|
||||
const ESM::Creature *createOverrideRecord (const ESM::Creature& record) override;
|
||||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||
/// \return pointer to created record
|
||||
|
||||
const ESM::NPC *createOverrideRecord (const ESM::NPC& record) override;
|
||||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||
/// \return pointer to created record
|
||||
|
||||
void update (float duration, bool paused) override;
|
||||
void updatePhysics (float duration, bool paused) override;
|
||||
|
||||
|
|
Loading…
Reference in a new issue