1
0
Fork 1
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:
Evil Eye 2020-06-02 21:59:37 +02:00
parent 1759276ac5
commit 4d7947d27c
14 changed files with 112 additions and 22 deletions

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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

View file

@ -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);
}
};

View file

@ -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;

View file

@ -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");
}
}

View file

@ -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;
};
}

View file

@ -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

View file

@ -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 <>

View file

@ -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;

View file

@ -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;