From 46a734852b5b6a36ddb554cb86d297c2bd19e71a Mon Sep 17 00:00:00 2001 From: gus Date: Tue, 10 Sep 2013 16:16:13 +0200 Subject: [PATCH 01/23] adding script instruction getLOS + some test about AI --- apps/openmw/mwbase/world.hpp | 3 ++ apps/openmw/mwmechanics/aisequence.cpp | 51 ++++++++++++++++++++++++++ apps/openmw/mwscript/aiextensions.cpp | 28 ++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 2 + apps/openmw/mwworld/worldimp.cpp | 5 +++ apps/openmw/mwworld/worldimp.hpp | 3 ++ components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 2 + 8 files changed, 95 insertions(+) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 6ca900a4d..071d2a16c 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -356,6 +356,9 @@ namespace MWBase virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector& out) = 0; ///< get all items in active cells owned by this Npc + virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) = 0; + ///< get Line of Sight (morrowind stupid implementation) + virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0; virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 2f06b849a..79ecf1586 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -9,6 +9,13 @@ #include "aifollow.hpp" #include "aiactivate.hpp" +#include "..\mwworld\class.hpp" +#include "creaturestats.hpp" +#include "npcstats.hpp" +#include "..\mwbase\environment.hpp" +#include "..\mwbase\world.hpp" +#include "..\mwworld\player.hpp" + void MWMechanics::AiSequence::copy (const AiSequence& sequence) { for (std::list::const_iterator iter (sequence.mPackages.begin()); @@ -54,6 +61,50 @@ bool MWMechanics::AiSequence::isPackageDone() const void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) { + /*if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) + { + MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); + if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) + MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + ESM::Position pos = actor.getRefData().getPosition(); + const ESM::Pathgrid *pathgrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + + int cellX = actor.getCell()->mCell->mData.mX; + int cellY = actor.getCell()->mCell->mData.mY; + float xCell = 0; + float yCell = 0; + + if (actor.getCell()->mCell->isExterior()) + { + xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + } + + ESM::Pathgrid::Point dest; + dest.mX = player.getRefData().getPosition().pos[0]; + dest.mY = player.getRefData().getPosition().pos[1]; + dest.mZ = player.getRefData().getPosition().pos[2]; + + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + PathFinder mPathFinder; + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + + if(dest.mX - start.mX < 100) + { + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); + } + }*/ if (!mPackages.empty()) { if (mPackages.front()->execute (actor)) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index fac44c08f..39ed36ac7 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -17,6 +17,9 @@ #include "../mwmechanics/aitravel.hpp" #include "../mwmechanics/aiwander.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + #include "interpretercontext.hpp" #include "ref.hpp" @@ -364,6 +367,28 @@ namespace MWScript } }; + template + class OpGetLineOfSight : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + + MWWorld::Ptr source = R()(runtime); + + std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + MWWorld::Ptr dest = MWBase::Environment::get().getWorld()->getPtr(actorID,true); + bool value = false; + if(dest != MWWorld::Ptr() ) + { + value = MWBase::Environment::get().getWorld()->getLOS(source,dest); + } + runtime.push (value); + } + }; void installOpcodes (Interpreter::Interpreter& interpreter) { @@ -389,6 +414,9 @@ namespace MWScript interpreter.installSegment5 (Compiler::Ai::opcodeGetCurrentAiPackageExplicit, new OpGetCurrentAIPackage); interpreter.installSegment3 (Compiler::Ai::opcodeGetDetected, new OpGetDetected); interpreter.installSegment3 (Compiler::Ai::opcodeGetDetectedExplicit, new OpGetDetected); + interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSight, new OpGetLineOfSight); + interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSightExplicit, new OpGetLineOfSight); + interpreter.installSegment5 (Compiler::Ai::opcodeSetHello, new OpSetAiSetting(0)); interpreter.installSegment5 (Compiler::Ai::opcodeSetHelloExplicit, new OpSetAiSetting(0)); interpreter.installSegment5 (Compiler::Ai::opcodeSetFight, new OpSetAiSetting(1)); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 08b499175..053964eff 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -351,5 +351,7 @@ op 0x200021b: SetWerewolfAcrobatics op 0x200021c: SetWerewolfAcrobaticsExplicit op 0x200021d: ShowVars op 0x200021e: ShowVarsExplicit +op 0x200021f: GetLineOfSight +op 0x200022a: GetLineOfSightExplicit opcodes 0x200021f-0x3ffffff unused diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 09dc0493e..5e293a292 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1779,6 +1779,11 @@ namespace MWWorld } } + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) + { + return false; + } + void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable) { OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle()); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 71391239b..ac1e0b383 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -403,6 +403,9 @@ namespace MWWorld virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector& out); ///< get all items in active cells owned by this Npc + virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc); + ///< get Line of Sight (morrowind stupid implementation) + virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable); virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 9e0c36825..a671420d4 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -63,6 +63,7 @@ namespace Compiler extensions.registerFunction ("getfight", 'l', "", opcodeGetFight, opcodeGetFightExplicit); extensions.registerFunction ("getflee", 'l', "", opcodeGetFlee, opcodeGetFleeExplicit); extensions.registerFunction ("getalarm", 'l', "", opcodeGetAlarm, opcodeGetAlarmExplicit); + extensions.registerFunction ("getlineofsight", 'l', "c", opcodeGetLineOfSight, opcodeGetLineOfSightExplicit); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index c4e2c1bc6..185eb3c21 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -49,6 +49,8 @@ namespace Compiler const int opcodeGetFleeExplicit = 0x20001c4; const int opcodeGetAlarm = 0x20001c5; const int opcodeGetAlarmExplicit = 0x20001c6; + const int opcodeGetLineOfSight = 0x200021f; + const int opcodeGetLineOfSightExplicit = 0x200022a; } namespace Animation From 9353f4d14f9b96fffe23b92eaa75a974fb061fb6 Mon Sep 17 00:00:00 2001 From: gus Date: Wed, 25 Sep 2013 18:01:36 +0200 Subject: [PATCH 02/23] WIP AI combat --- apps/openmw/mwmechanics/aicombat.cpp | 87 ++++++++++++++++++++++++++ apps/openmw/mwmechanics/aicombat.hpp | 39 ++++++++++++ apps/openmw/mwmechanics/aisequence.cpp | 71 +++++++++++++-------- apps/openmw/mwmechanics/aisequence.hpp | 3 + 4 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 apps/openmw/mwmechanics/aicombat.cpp create mode 100644 apps/openmw/mwmechanics/aicombat.hpp diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp new file mode 100644 index 000000000..071aa50e3 --- /dev/null +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -0,0 +1,87 @@ +#include "aicombat.hpp" + +#include "movement.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/timestamp.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" + + +namespace MWMechanics +{ + + AiCombat::AiCombat(const std::string &targetId) + :mTargetId(targetId) + { + } + + bool AiCombat::execute (const MWWorld::Ptr& actor) + { + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();//MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); + + MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); + if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) + MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + + ESM::Position pos = actor.getRefData().getPosition(); + const ESM::Pathgrid *pathgrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + + int cellX = actor.getCell()->mCell->mData.mX; + int cellY = actor.getCell()->mCell->mData.mY; + float xCell = 0; + float yCell = 0; + + if (actor.getCell()->mCell->isExterior()) + { + xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + } + + ESM::Pathgrid::Point dest; + dest.mX = target.getRefData().getPosition().pos[0]; + dest.mY = target.getRefData().getPosition().pos[1]; + dest.mZ = target.getRefData().getPosition().pos[2]; + + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + std::cout << start.mX << " " << dest.mX << "\n"; + + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) + { + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + } + + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + std::cout << zAngle; + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + + if(dest.mX - start.mX < 100) + { + //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); + } + + return false; + } + + int AiCombat::getTypeId() const + { + return 2; + } + + AiCombat *MWMechanics::AiCombat::clone() const + { + return new AiCombat(*this); + } +} + diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp new file mode 100644 index 000000000..3b2ae6fc0 --- /dev/null +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -0,0 +1,39 @@ +#ifndef GAME_MWMECHANICS_AICOMBAT_H +#define GAME_MWMECHANICS_AICOMBAT_H + +#include "aipackage.hpp" + +#include "pathfinding.hpp" + + +#include "..\mwworld\class.hpp" +#include "creaturestats.hpp" +#include "npcstats.hpp" +#include "..\mwbase\environment.hpp" +#include "..\mwbase\world.hpp" +#include "..\mwworld\player.hpp" + +#include "movement.hpp" + +namespace MWMechanics +{ + class AiCombat : public AiPackage + { + public: + AiCombat(const std::string &targetId); + + virtual AiCombat *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor); + ///< \return Package completed? + + virtual int getTypeId() const; + + private: + std::string mTargetId; + + PathFinder mPathFinder; + }; +} + +#endif \ No newline at end of file diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 79ecf1586..d02f03e18 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -8,6 +8,7 @@ #include "aitravel.hpp" #include "aifollow.hpp" #include "aiactivate.hpp" +#include "aicombat.hpp" #include "..\mwworld\class.hpp" #include "creaturestats.hpp" @@ -21,9 +22,11 @@ void MWMechanics::AiSequence::copy (const AiSequence& sequence) for (std::list::const_iterator iter (sequence.mPackages.begin()); iter!=sequence.mPackages.end(); ++iter) mPackages.push_back ((*iter)->clone()); + mCombat = sequence.mCombat; + mCombatPackage = sequence.mCombatPackage; } -MWMechanics::AiSequence::AiSequence() : mDone (false) {} +MWMechanics::AiSequence::AiSequence() : mDone (false), mCombat (false), mCombatPackage (0) {} MWMechanics::AiSequence::AiSequence (const AiSequence& sequence) : mDone (false) { @@ -61,16 +64,27 @@ bool MWMechanics::AiSequence::isPackageDone() const void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) { - /*if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) + if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) { - MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); - if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) - MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + if(mCombat) + { + //mCombatPackage->execute(actor); + } + else + { + //mCombat = true; + //mCombatPackage = new AiCombat("player"); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - ESM::Position pos = actor.getRefData().getPosition(); - const ESM::Pathgrid *pathgrid = + /*if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) + { + MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); + if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) + MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + ESM::Position pos = actor.getRefData().getPosition(); + const ESM::Pathgrid *pathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); int cellX = actor.getCell()->mCell->mData.mX; @@ -80,8 +94,8 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) if (actor.getCell()->mCell->isExterior()) { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; } ESM::Pathgrid::Point dest; @@ -96,24 +110,26 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) PathFinder mPathFinder; mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - if(dest.mX - start.mX < 100) - { + if(dest.mX - start.mX < 100) + { MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); + } + }*/ + if (!mPackages.empty()) + { + if (mPackages.front()->execute (actor)) + { + mPackages.erase (mPackages.begin()); + mDone = true; + } + else + mDone = false; + } } - }*/ - if (!mPackages.empty()) - { - if (mPackages.front()->execute (actor)) - { - mPackages.erase (mPackages.begin()); - mDone = true; - } - else - mDone = false; } } @@ -121,7 +137,8 @@ void MWMechanics::AiSequence::clear() { for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) delete *iter; - + + if(mCombatPackage) delete mCombatPackage; mPackages.clear(); } diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 9f70daeb8..37084a1e5 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -18,6 +18,9 @@ namespace MWMechanics class AiSequence { std::list mPackages; + AiPackage* mCombatPackage; + bool mCombat; + bool mDone; void copy (const AiSequence& sequence); From 2537384c502c8cc74769bcd7d968542eff82ce2a Mon Sep 17 00:00:00 2001 From: gus Date: Sat, 28 Sep 2013 12:25:37 +0200 Subject: [PATCH 03/23] bug fix --- apps/openmw/mwmechanics/aicombat.cpp | 98 ++++++++++++++------------ apps/openmw/mwmechanics/aisequence.cpp | 51 +------------- 2 files changed, 54 insertions(+), 95 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 071aa50e3..4988dc9e3 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -22,55 +22,59 @@ namespace MWMechanics { const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();//MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); - MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); - if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) - MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); - - ESM::Position pos = actor.getRefData().getPosition(); - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); - - int cellX = actor.getCell()->mCell->mData.mX; - int cellY = actor.getCell()->mCell->mData.mY; - float xCell = 0; - float yCell = 0; - - if (actor.getCell()->mCell->isExterior()) + if(actor.getTypeName() == typeid(ESM::NPC).name()) { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + + MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); + if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) + MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + + ESM::Position pos = actor.getRefData().getPosition(); + const ESM::Pathgrid *pathgrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + + int cellX = actor.getCell()->mCell->mData.mX; + int cellY = actor.getCell()->mCell->mData.mY; + float xCell = 0; + float yCell = 0; + + if (actor.getCell()->mCell->isExterior()) + { + xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + } + + ESM::Pathgrid::Point dest; + dest.mX = target.getRefData().getPosition().pos[0]; + dest.mY = target.getRefData().getPosition().pos[1]; + dest.mZ = target.getRefData().getPosition().pos[2]; + + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + std::cout << start.mX << " " << dest.mX << "\n"; + + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + + mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]) + + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + std::cout << zAngle; + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + + float range = 100; + + if((dest.mX - start.mX)*(dest.mX - start.mX)+(dest.mY - start.mY)*(dest.mY - start.mY)+(dest.mZ - start.mZ)*(dest.mZ - start.mZ) + < range*range) + { + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(!MWWorld::Class::get(actor).getCreatureStats(actor).getAttackingOrSpell()); + } } - - ESM::Pathgrid::Point dest; - dest.mX = target.getRefData().getPosition().pos[0]; - dest.mY = target.getRefData().getPosition().pos[1]; - dest.mZ = target.getRefData().getPosition().pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - std::cout << start.mX << " " << dest.mX << "\n"; - - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); - - if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - } - - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - std::cout << zAngle; - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - - if(dest.mX - start.mX < 100) - { - //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); - } - return false; } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index d02f03e18..f3aa877e2 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -68,57 +68,12 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) { if(mCombat) { - //mCombatPackage->execute(actor); + mCombatPackage->execute(actor); } else { - //mCombat = true; - //mCombatPackage = new AiCombat("player"); - - /*if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) - { - MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); - if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) - MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); - - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - ESM::Position pos = actor.getRefData().getPosition(); - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); - - int cellX = actor.getCell()->mCell->mData.mX; - int cellY = actor.getCell()->mCell->mData.mY; - float xCell = 0; - float yCell = 0; - - if (actor.getCell()->mCell->isExterior()) - { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; - } - - ESM::Pathgrid::Point dest; - dest.mX = player.getRefData().getPosition().pos[0]; - dest.mY = player.getRefData().getPosition().pos[1]; - dest.mZ = player.getRefData().getPosition().pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - PathFinder mPathFinder; - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - - if(dest.mX - start.mX < 100) - { - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); - } - }*/ + mCombat = true; + mCombatPackage = new AiCombat("player"); if (!mPackages.empty()) { if (mPackages.front()->execute (actor)) From 83a375b55d6f6a0b93f476c92fedf385dadd216b Mon Sep 17 00:00:00 2001 From: gus Date: Sat, 28 Sep 2013 21:17:06 +0200 Subject: [PATCH 04/23] AI now continue to hit you. TODO: change the way time is handled --- apps/openmw/mwmechanics/aicombat.cpp | 17 ++++++++++++++--- apps/openmw/mwmechanics/aicombat.hpp | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 4988dc9e3..bf5968e8c 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -14,7 +14,7 @@ namespace MWMechanics { AiCombat::AiCombat(const std::string &targetId) - :mTargetId(targetId) + :mTargetId(targetId),mStartingSecond(0) { } @@ -28,7 +28,7 @@ namespace MWMechanics MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); ESM::Position pos = actor.getRefData().getPosition(); const ESM::Pathgrid *pathgrid = @@ -59,7 +59,7 @@ namespace MWMechanics mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); - mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]) + mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); std::cout << zAngle; @@ -71,6 +71,17 @@ namespace MWMechanics if((dest.mX - start.mX)*(dest.mX - start.mX)+(dest.mY - start.mY)*(dest.mY - start.mY)+(dest.mZ - start.mZ)*(dest.mZ - start.mZ) < range*range) { + MWWorld::TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); + if(mStartingSecond == 0) + { + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); + mStartingSecond = ((time.getHour() - int(time.getHour())) * 100); + } + else if( ((time.getHour() - int(time.getHour())) * 100) - mStartingSecond > 1) + { + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + mStartingSecond = 0; + } MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(!MWWorld::Class::get(actor).getCreatureStats(actor).getAttackingOrSpell()); } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 3b2ae6fc0..bde66a46b 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -33,6 +33,7 @@ namespace MWMechanics std::string mTargetId; PathFinder mPathFinder; + unsigned int mStartingSecond; }; } From 1ac3d99c78adc9bbef46256ba33c0a109e2a41b0 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 7 Oct 2013 10:20:02 +0200 Subject: [PATCH 05/23] pathfinding now works in AICombat. --- apps/openmw/mwmechanics/aicombat.cpp | 20 ++++++++++++++------ apps/openmw/mwmechanics/aicombat.hpp | 1 + apps/openmw/mwmechanics/pathfinding.cpp | 17 ++++++++++++++++- apps/openmw/mwmechanics/pathfinding.hpp | 12 ++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index bf5968e8c..529855b2f 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -55,14 +55,20 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - std::cout << start.mX << " " << dest.mX << "\n"; - - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); - + if(!mPathFinder.isPathConstructed()) + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + else + { + mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); + ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); + if(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || + (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200) + mPathFinder = mPathFinder2; + } + mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - std::cout << zAngle; MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; @@ -71,7 +77,9 @@ namespace MWMechanics if((dest.mX - start.mX)*(dest.mX - start.mX)+(dest.mY - start.mY)*(dest.mY - start.mY)+(dest.mZ - start.mZ)*(dest.mZ - start.mZ) < range*range) { - MWWorld::TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); + mPathFinder.clearPath(); + + MWWorld::TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); if(mStartingSecond == 0) { MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index bde66a46b..f61582adc 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -33,6 +33,7 @@ namespace MWMechanics std::string mTargetId; PathFinder mPathFinder; + PathFinder mPathFinder2; unsigned int mStartingSecond; }; } diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 8ef0edab8..ff266f9ae 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -189,7 +189,7 @@ namespace MWMechanics // This should never happen (programmers should have an if statement checking mIsPathConstructed that prevents this call // if otherwise). if(mPath.empty()) - return 0; + return 0.; const ESM::Pathgrid::Point &nextPoint = *mPath.begin(); float directionX = nextPoint.mX - x; @@ -199,6 +199,21 @@ namespace MWMechanics return Ogre::Radian(acos(directionY / directionResult) * sgn(asin(directionX / directionResult))).valueDegrees(); } + bool PathFinder::checkWaypoint(float x, float y, float z) + { + if(mPath.empty()) + return true; + + ESM::Pathgrid::Point nextPoint = *mPath.begin(); + if(distanceZCorrected(nextPoint, x, y, z) < 64) + { + mPath.pop_front(); + if(mPath.empty()) mIsPathConstructed = false; + return true; + } + return false; + } + bool PathFinder::checkPathCompleted(float x, float y, float z) { if(mPath.empty()) diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 35e0fa908..916df850b 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -18,6 +18,8 @@ namespace MWMechanics bool checkPathCompleted(float x, float y, float z); ///< \Returns true if the last point of the path has been reached. + bool checkWaypoint(float x, float y, float z); + ///< \Returns true if a way point was reached float getZAngleToNext(float x, float y) const; bool isPathConstructed() const @@ -25,6 +27,16 @@ namespace MWMechanics return mIsPathConstructed; } + int getPathSize() const + { + return mPath.size(); + } + + std::list getPath() const + { + return mPath; + } + private: std::list mPath; bool mIsPathConstructed; From 94069e3a7e35225f9264fc9970e80257e4903011 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 7 Oct 2013 20:30:12 +0200 Subject: [PATCH 06/23] bugfix --- apps/openmw/mwmechanics/aisequence.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index f3aa877e2..ecd21d04c 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -23,7 +23,7 @@ void MWMechanics::AiSequence::copy (const AiSequence& sequence) iter!=sequence.mPackages.end(); ++iter) mPackages.push_back ((*iter)->clone()); mCombat = sequence.mCombat; - mCombatPackage = sequence.mCombatPackage; + mCombatPackage = sequence.mCombatPackage->clone(); } MWMechanics::AiSequence::AiSequence() : mDone (false), mCombat (false), mCombatPackage (0) {} @@ -93,7 +93,11 @@ void MWMechanics::AiSequence::clear() for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) delete *iter; - if(mCombatPackage) delete mCombatPackage; + if(mCombatPackage) + { + delete mCombatPackage; + mCombatPackage = 0; + } mPackages.clear(); } From 882b136b35736eb78fbcce63c7e2e16ccdb85f9a Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 27 Oct 2013 13:21:16 +0100 Subject: [PATCH 07/23] bugfix of bugfix ^^ --- apps/openmw/mwmechanics/aisequence.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index ecd21d04c..5e1bc1791 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -23,7 +23,8 @@ void MWMechanics::AiSequence::copy (const AiSequence& sequence) iter!=sequence.mPackages.end(); ++iter) mPackages.push_back ((*iter)->clone()); mCombat = sequence.mCombat; - mCombatPackage = sequence.mCombatPackage->clone(); + mCombatPackage = 0; + if(sequence.mCombat) mCombatPackage = sequence.mCombatPackage->clone(); } MWMechanics::AiSequence::AiSequence() : mDone (false), mCombat (false), mCombatPackage (0) {} From a0edb55f600844b7f5474df1395f7476983d7e99 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 27 Oct 2013 13:50:29 +0100 Subject: [PATCH 08/23] only NPC with fight over 80 will attack you now --- apps/openmw/mwmechanics/aisequence.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 5e1bc1791..86c07947f 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -73,8 +73,11 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) } else { - mCombat = true; - mCombatPackage = new AiCombat("player"); + if(actor.getClass().getCreatureStats(actor).getAiSetting(1)> 80) + { + mCombat = true; + mCombatPackage = new AiCombat("player"); + } if (!mPackages.empty()) { if (mPackages.front()->execute (actor)) From 968968502e623857ae730a2a386cbc64108c1066 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 27 Oct 2013 14:03:58 +0100 Subject: [PATCH 09/23] NPC always face you when fighting --- apps/openmw/mwmechanics/aicombat.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 529855b2f..8f51c462f 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -9,6 +9,17 @@ #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" +#include "OgreMath.h" + +namespace +{ + static float sgn(float a) + { + if(a > 0) + return 1.0; + return -1.0; + } +} namespace MWMechanics { @@ -71,12 +82,20 @@ namespace MWMechanics float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + float range = 100; - + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); if((dest.mX - start.mX)*(dest.mX - start.mX)+(dest.mY - start.mY)*(dest.mY - start.mY)+(dest.mZ - start.mZ)*(dest.mZ - start.mZ) < range*range) { + float directionX = dest.mX - start.mX; + float directionY = dest.mY - start.mY; + float directionResult = sqrt(directionX * directionX + directionY * directionY); + + zAngle = Ogre::Radian( acos(directionY / directionResult) * sgn(asin(directionX / directionResult)) ).valueDegrees(); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + mPathFinder.clearPath(); MWWorld::TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); From 2515a1239e67b169f0e1d3a189f6eb25f18a18cd Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 27 Oct 2013 14:22:51 +0100 Subject: [PATCH 10/23] improved combat conditions --- apps/openmw/mwmechanics/aisequence.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 86c07947f..a798040fe 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -17,6 +17,8 @@ #include "..\mwbase\world.hpp" #include "..\mwworld\player.hpp" +#include "..\mwbase\mechanicsmanager.hpp" + void MWMechanics::AiSequence::copy (const AiSequence& sequence) { for (std::list::const_iterator iter (sequence.mPackages.begin()); @@ -73,7 +75,23 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) } else { - if(actor.getClass().getCreatureStats(actor).getAiSetting(1)> 80) + ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); + ESM::Position actorpos = actor.getRefData().getPosition(); + float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) + +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) + +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); + float fight = actor.getClass().getCreatureStats(actor).getAiSetting(1); + float disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(actor); + if(fight == 100 + || (fight >= 95 && d <= 3000) + || (fight >= 90 && d <= 2000) + || (fight >= 80 && d <= 1000) + || (fight >= 80 && disp <= 40) + || (fight >= 70 && disp <= 35 && d <= 1000) + || (fight >= 60 && disp <= 30 && d <= 1000) + || (fight >= 50 && disp == 0) + || (fight >= 40 && disp <= 10 && d <= 500) + ) { mCombat = true; mCombatPackage = new AiCombat("player"); From d7584f9df7f6d39d7191aa7d8fe4448ba04b11f1 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 18:01:40 +0100 Subject: [PATCH 11/23] getLineOfSight, no script instruction yet --- apps/openmw/mwmechanics/aisequence.cpp | 6 ++++-- apps/openmw/mwworld/worldimp.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index a798040fe..940002a57 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -82,7 +82,8 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); float fight = actor.getClass().getCreatureStats(actor).getAiSetting(1); float disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(actor); - if(fight == 100 + bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + if( ( (fight == 100 ) || (fight >= 95 && d <= 3000) || (fight >= 90 && d <= 2000) || (fight >= 80 && d <= 1000) @@ -90,7 +91,8 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) || (fight >= 70 && disp <= 35 && d <= 1000) || (fight >= 60 && disp <= 30 && d <= 1000) || (fight >= 50 && disp == 0) - || (fight >= 40 && disp <= 10 && d <= 500) + || (fight >= 40 && disp <= 10 && d <= 500) ) + && LOS ) { mCombat = true; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 724972600..b6d6cc2d8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1786,6 +1786,16 @@ namespace MWWorld bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { + Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents(); + float* pos1 = npc.getRefData().getPosition().pos; + Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents(); + float* pos2 = targetNpc.getRefData().getPosition().pos; + + btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z); + btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z); + + std::pair result = mPhysEngine->rayTest(from, to,false); + if(result.first == "") return true; return false; } From 2d84f7d33dd2d65d5f53acf8439737d6563f6058 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 18:10:00 +0100 Subject: [PATCH 12/23] NPC run --- apps/openmw/mwmechanics/aicombat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8f51c462f..c3ac8cb55 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -35,7 +35,7 @@ namespace MWMechanics if(actor.getTypeName() == typeid(ESM::NPC).name()) { - + MWWorld::Class::get(actor).setStance(actor, MWWorld::Class::Run,true); MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); From 12d8b4e0f888ef50f8704db9f4ad9bd79a78ab5e Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 18:13:07 +0100 Subject: [PATCH 13/23] bugfix --- apps/openmw/mwmechanics/aicombat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index c3ac8cb55..b01889f89 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -31,7 +31,7 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor) { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();//MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); if(actor.getTypeName() == typeid(ESM::NPC).name()) { From b7a92431733f729f89196713a9b19fdbd22138d1 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 18:22:36 +0100 Subject: [PATCH 14/23] fighting should stop when the target is dead --- apps/openmw/mwmechanics/aicombat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index b01889f89..80ad241ef 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -33,6 +33,8 @@ namespace MWMechanics { const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); + if(MWWorld::Class::get(actor).getCreatureStats(actor).getHealth().getCurrent() <= 0) return true; + if(actor.getTypeName() == typeid(ESM::NPC).name()) { MWWorld::Class::get(actor).setStance(actor, MWWorld::Class::Run,true); @@ -45,8 +47,6 @@ namespace MWMechanics const ESM::Pathgrid *pathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); - int cellX = actor.getCell()->mCell->mData.mX; - int cellY = actor.getCell()->mCell->mData.mY; float xCell = 0; float yCell = 0; From 0e862092241c3f1d22bd153165b20a5df9fd3fcf Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 18:33:10 +0100 Subject: [PATCH 15/23] linux fix :p --- apps/openmw/mwmechanics/aicombat.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 80ad241ef..66b93e8c9 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -2,12 +2,12 @@ #include "movement.hpp" -#include "../mwworld/class.hpp" -#include "../mwworld/player.hpp" -#include "../mwworld/timestamp.hpp" -#include "../mwbase/world.hpp" -#include "../mwbase/environment.hpp" -#include "../mwbase/mechanicsmanager.hpp" +#include "..\mwworld\class.hpp" +#include "..\mwworld\player.hpp" +#include "..\mwworld\timestamp.hpp" +#include "..\mwbase\world.hpp" +#include "..\mwbase\environment.hpp" +#include "..\mwbase\mechanicsmanager.hpp" #include "OgreMath.h" From 5b20cce849d21d8ddb54bbee1c2c2cbfe1389324 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 18:36:09 +0100 Subject: [PATCH 16/23] CMake fix --- apps/openmw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a44fd4b34..a35fc9197 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -68,7 +68,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow - aiescort aiactivate repair enchanting pathfinding security + aiescort aiactivate aicombat repair enchanting pathfinding security ) add_openmw_dir (mwbase From a6e7c6c1049d8b7a4a97fc76bdcc285d51caa7b8 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 28 Oct 2013 23:04:46 +0100 Subject: [PATCH 17/23] disable AI combat for creatures --- apps/openmw/mwmechanics/aisequence.cpp | 45 ++++++++++++++------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 940002a57..f94bb4b5f 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -75,28 +75,31 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) } else { - ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); - ESM::Position actorpos = actor.getRefData().getPosition(); - float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) - +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) - +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); - float fight = actor.getClass().getCreatureStats(actor).getAiSetting(1); - float disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(actor); - bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - if( ( (fight == 100 ) - || (fight >= 95 && d <= 3000) - || (fight >= 90 && d <= 2000) - || (fight >= 80 && d <= 1000) - || (fight >= 80 && disp <= 40) - || (fight >= 70 && disp <= 35 && d <= 1000) - || (fight >= 60 && disp <= 30 && d <= 1000) - || (fight >= 50 && disp == 0) - || (fight >= 40 && disp <= 10 && d <= 500) ) - && LOS - ) + if(actor.getTypeName() == typeid(ESM::NPC).name()) { - mCombat = true; - mCombatPackage = new AiCombat("player"); + ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); + ESM::Position actorpos = actor.getRefData().getPosition(); + float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) + +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) + +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); + float fight = actor.getClass().getCreatureStats(actor).getAiSetting(1); + float disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(actor); + bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + if( ( (fight == 100 ) + || (fight >= 95 && d <= 3000) + || (fight >= 90 && d <= 2000) + || (fight >= 80 && d <= 1000) + || (fight >= 80 && disp <= 40) + || (fight >= 70 && disp <= 35 && d <= 1000) + || (fight >= 60 && disp <= 30 && d <= 1000) + || (fight >= 50 && disp == 0) + || (fight >= 40 && disp <= 10 && d <= 500) ) + && LOS + ) + { + mCombat = true; + mCombatPackage = new AiCombat("player"); + } } if (!mPackages.empty()) { From 650a112e2e5168ae3ab26d5ebf8a9c98d5ed46b5 Mon Sep 17 00:00:00 2001 From: gus Date: Wed, 30 Oct 2013 20:42:50 +0100 Subject: [PATCH 18/23] better timer --- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/aiactivate.cpp | 2 +- apps/openmw/mwmechanics/aiactivate.hpp | 2 +- apps/openmw/mwmechanics/aicombat.cpp | 20 ++++++++++++-------- apps/openmw/mwmechanics/aicombat.hpp | 4 ++-- apps/openmw/mwmechanics/aiescort.cpp | 2 +- apps/openmw/mwmechanics/aiescort.hpp | 2 +- apps/openmw/mwmechanics/aifollow.cpp | 2 +- apps/openmw/mwmechanics/aifollow.hpp | 2 +- apps/openmw/mwmechanics/aipackage.hpp | 2 +- apps/openmw/mwmechanics/aisequence.cpp | 6 +++--- apps/openmw/mwmechanics/aisequence.hpp | 2 +- apps/openmw/mwmechanics/aitravel.cpp | 2 +- apps/openmw/mwmechanics/aitravel.hpp | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 2 +- apps/openmw/mwmechanics/aiwander.hpp | 2 +- 16 files changed, 30 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 566d4bc50..52c1685a0 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -35,7 +35,7 @@ namespace MWMechanics if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) { CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); - creatureStats.getAiSequence().execute (ptr); + creatureStats.getAiSequence().execute (ptr,duration); } } diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index b94c8c259..ee0dcf96e 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -9,7 +9,7 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const { return new AiActivate(*this); } -bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor) +bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) { std::cout << "AiActivate completed.\n"; return true; diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index 7f3d4016d..f922e238c 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -12,7 +12,7 @@ namespace MWMechanics public: AiActivate(const std::string &objectId); virtual AiActivate *clone() const; - virtual bool execute (const MWWorld::Ptr& actor); + virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 66b93e8c9..bab183f11 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -25,11 +25,11 @@ namespace MWMechanics { AiCombat::AiCombat(const std::string &targetId) - :mTargetId(targetId),mStartingSecond(0) + :mTargetId(targetId),mTimer(0) { } - bool AiCombat::execute (const MWWorld::Ptr& actor) + bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); @@ -97,18 +97,22 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); mPathFinder.clearPath(); - - MWWorld::TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); - if(mStartingSecond == 0) + + if(mTimer == 0) { MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); - mStartingSecond = ((time.getHour() - int(time.getHour())) * 100); + //mTimer = mTimer + duration; } - else if( ((time.getHour() - int(time.getHour())) * 100) - mStartingSecond > 1) + if( mTimer > 1) { MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); - mStartingSecond = 0; + mTimer = 0; } + else + { + mTimer = mTimer + duration; + } + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(!MWWorld::Class::get(actor).getCreatureStats(actor).getAttackingOrSpell()); } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index f61582adc..8e2c3cb94 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -24,7 +24,7 @@ namespace MWMechanics virtual AiCombat *clone() const; - virtual bool execute (const MWWorld::Ptr& actor); + virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; @@ -34,7 +34,7 @@ namespace MWMechanics PathFinder mPathFinder; PathFinder mPathFinder2; - unsigned int mStartingSecond; + float mTimer; }; } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 556e0b126..3615c8546 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -71,7 +71,7 @@ namespace MWMechanics return new AiEscort(*this); } - bool AiEscort::execute (const MWWorld::Ptr& actor) + bool AiEscort::execute (const MWWorld::Ptr& actor,float duration) { // If AiEscort has ran for as long or longer then the duration specified // and the duration is not infinite, the package is complete. diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index 3ae604035..f3f6d2bd9 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -18,7 +18,7 @@ namespace MWMechanics virtual AiEscort *clone() const; - virtual bool execute (const MWWorld::Ptr& actor); + virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index dab9e0283..73bf9259a 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -15,7 +15,7 @@ MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const return new AiFollow(*this); } - bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor) + bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { std::cout << "AiFollow completed.\n"; return true; diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 0b37b0a2d..39df024e4 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -13,7 +13,7 @@ namespace MWMechanics AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); virtual AiFollow *clone() const; - virtual bool execute (const MWWorld::Ptr& actor); + virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index d286fbba8..794708f22 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -17,7 +17,7 @@ namespace MWMechanics virtual AiPackage *clone() const = 0; - virtual bool execute (const MWWorld::Ptr& actor) = 0; + virtual bool execute (const MWWorld::Ptr& actor,float duration) = 0; ///< \return Package completed? virtual int getTypeId() const = 0; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index f94bb4b5f..bdde23e0d 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -65,13 +65,13 @@ bool MWMechanics::AiSequence::isPackageDone() const return mDone; } -void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) +void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) { if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) { if(mCombat) { - mCombatPackage->execute(actor); + mCombatPackage->execute(actor,duration); } else { @@ -103,7 +103,7 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor) } if (!mPackages.empty()) { - if (mPackages.front()->execute (actor)) + if (mPackages.front()->execute (actor,duration)) { mPackages.erase (mPackages.begin()); mDone = true; diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 37084a1e5..ea2a048f1 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -41,7 +41,7 @@ namespace MWMechanics bool isPackageDone() const; ///< Has a package been completed during the last update? - void execute (const MWWorld::Ptr& actor); + void execute (const MWWorld::Ptr& actor,float duration); ///< Execute package. void clear(); diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index d47a49c70..08d758638 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -31,7 +31,7 @@ namespace MWMechanics return new AiTravel(*this); } - bool AiTravel::execute (const MWWorld::Ptr& actor) + bool AiTravel::execute (const MWWorld::Ptr& actor,float duration) { MWBase::World *world = MWBase::Environment::get().getWorld(); ESM::Position pos = actor.getRefData().getPosition(); diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index 6eb9af8ce..b479dfd43 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -13,7 +13,7 @@ namespace MWMechanics AiTravel(float x, float y, float z); virtual AiTravel *clone() const; - virtual bool execute (const MWWorld::Ptr& actor); + virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 96a41883b..ecc41489a 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -63,7 +63,7 @@ namespace MWMechanics return new AiWander(*this); } - bool AiWander::execute (const MWWorld::Ptr& actor) + bool AiWander::execute (const MWWorld::Ptr& actor,float duration) { MWBase::World *world = MWBase::Environment::get().getWorld(); if(mDuration) diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index c82ccc215..48bc62c62 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -16,7 +16,7 @@ namespace MWMechanics AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat); virtual AiPackage *clone() const; - virtual bool execute (const MWWorld::Ptr& actor); + virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; ///< 0: Wander From 2a927f65d396e8c9d249e55a42a90f8376e18195 Mon Sep 17 00:00:00 2001 From: gus Date: Wed, 30 Oct 2013 20:52:23 +0100 Subject: [PATCH 19/23] perfomances optimisations (pathfinding is computed less often, max 4 times per sec) --- apps/openmw/mwmechanics/aicombat.cpp | 11 ++++++++--- apps/openmw/mwmechanics/aicombat.hpp | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index bab183f11..0a64abec3 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -25,7 +25,7 @@ namespace MWMechanics { AiCombat::AiCombat(const std::string &targetId) - :mTargetId(targetId),mTimer(0) + :mTargetId(targetId),mTimer(0),mTimer2(0) { } @@ -66,15 +66,20 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; + mTimer2 = mTimer2 + duration; + if(!mPathFinder.isPathConstructed()) mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); else { mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); - if(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || - (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200) + if((mTimer2 > 0.25)&&(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || + (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200)) + { + mTimer2 = 0; mPathFinder = mPathFinder2; + } } mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 8e2c3cb94..7321b2cde 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -35,6 +35,7 @@ namespace MWMechanics PathFinder mPathFinder; PathFinder mPathFinder2; float mTimer; + float mTimer2; }; } From 02ded18fc55d313fbd39e6e683a7e8726c702020 Mon Sep 17 00:00:00 2001 From: gus Date: Thu, 31 Oct 2013 09:43:12 +0100 Subject: [PATCH 20/23] Linux backslash fix --- apps/openmw/mwmechanics/aicombat.cpp | 12 ++++++------ apps/openmw/mwmechanics/aisequence.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 0a64abec3..3054a9456 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -2,12 +2,12 @@ #include "movement.hpp" -#include "..\mwworld\class.hpp" -#include "..\mwworld\player.hpp" -#include "..\mwworld\timestamp.hpp" -#include "..\mwbase\world.hpp" -#include "..\mwbase\environment.hpp" -#include "..\mwbase\mechanicsmanager.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/timestamp.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "OgreMath.h" diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index bdde23e0d..994a7a932 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -10,14 +10,14 @@ #include "aiactivate.hpp" #include "aicombat.hpp" -#include "..\mwworld\class.hpp" +#include "../mwworld/class.hpp" #include "creaturestats.hpp" #include "npcstats.hpp" -#include "..\mwbase\environment.hpp" -#include "..\mwbase\world.hpp" -#include "..\mwworld\player.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwworld/player.hpp" -#include "..\mwbase\mechanicsmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" void MWMechanics::AiSequence::copy (const AiSequence& sequence) { From 683b8d77dd3bb7f83b31f870f6e07e732291a818 Mon Sep 17 00:00:00 2001 From: gus Date: Thu, 31 Oct 2013 11:02:26 +0100 Subject: [PATCH 21/23] build fix (thanks travis) --- apps/openmw/mwmechanics/aicombat.cpp | 3 +++ apps/openmw/mwmechanics/aicombat.hpp | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 3054a9456..aeddb4781 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -9,6 +9,9 @@ #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" +#include "creaturestats.hpp" +#include "npcstats.hpp" + #include "OgreMath.h" namespace diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 7321b2cde..eed92ef3a 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -5,14 +5,6 @@ #include "pathfinding.hpp" - -#include "..\mwworld\class.hpp" -#include "creaturestats.hpp" -#include "npcstats.hpp" -#include "..\mwbase\environment.hpp" -#include "..\mwbase\world.hpp" -#include "..\mwworld\player.hpp" - #include "movement.hpp" namespace MWMechanics From 4559e932ae0b9d1319b6d0fc99396c819a51dfb7 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 18 Nov 2013 12:33:09 +0100 Subject: [PATCH 22/23] AI packages have priority and combat is triggered in actor.cpp using the Hostile setting in CreaturesState --- apps/openmw/mwmechanics/actors.cpp | 38 +++++++ apps/openmw/mwmechanics/aicombat.cpp | 141 +++++++++++++------------ apps/openmw/mwmechanics/aicombat.hpp | 2 + apps/openmw/mwmechanics/aipackage.hpp | 3 + apps/openmw/mwmechanics/aisequence.cpp | 68 +++--------- apps/openmw/mwmechanics/aisequence.hpp | 6 +- 6 files changed, 135 insertions(+), 123 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 03a161e86..cbd369a81 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -22,6 +22,11 @@ #include "creaturestats.hpp" #include "movement.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" + +#include "aicombat.hpp" + namespace MWMechanics { void Actors::updateActor (const MWWorld::Ptr& ptr, float duration) @@ -35,6 +40,39 @@ namespace MWMechanics { // AI CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + + //engage combat or not? + if(ptr != MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && !creatureStats.isHostile()) + { + ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); + ESM::Position actorpos = ptr.getRefData().getPosition(); + float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) + +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) + +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); + float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(1); + float disp = 100; //creatures don't have disposition, so set it to 100 by default + if(ptr.getTypeName() == typeid(ESM::NPC).name()) + { + disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr); + } + bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + if( ( (fight == 100 ) + || (fight >= 95 && d <= 3000) + || (fight >= 90 && d <= 2000) + || (fight >= 80 && d <= 1000) + || (fight >= 80 && disp <= 40) + || (fight >= 70 && disp <= 35 && d <= 1000) + || (fight >= 60 && disp <= 30 && d <= 1000) + || (fight >= 50 && disp == 0) + || (fight >= 40 && disp <= 10 && d <= 500) ) + && LOS + ) + { + creatureStats.getAiSequence().stack(AiCombat("player")); + creatureStats.setHostile(true); + } + } + creatureStats.getAiSequence().execute (ptr,duration); // fatigue restoration diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index aeddb4781..39a97df6c 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -34,103 +34,110 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { + if(!MWWorld::Class::get(actor).getCreatureStats(actor).isHostile()) return true; + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mTargetId, false); if(MWWorld::Class::get(actor).getCreatureStats(actor).getHealth().getCurrent() <= 0) return true; if(actor.getTypeName() == typeid(ESM::NPC).name()) { + MWWorld::Class::get(actor). MWWorld::Class::get(actor).setStance(actor, MWWorld::Class::Run,true); MWMechanics::DrawState_ state = MWWorld::Class::get(actor).getNpcStats(actor).getDrawState(); if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) MWWorld::Class::get(actor).getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon); //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + } + ESM::Position pos = actor.getRefData().getPosition(); + const ESM::Pathgrid *pathgrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); - ESM::Position pos = actor.getRefData().getPosition(); - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + float xCell = 0; + float yCell = 0; - float xCell = 0; - float yCell = 0; + if (actor.getCell()->mCell->isExterior()) + { + xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + } - if (actor.getCell()->mCell->isExterior()) + ESM::Pathgrid::Point dest; + dest.mX = target.getRefData().getPosition().pos[0]; + dest.mY = target.getRefData().getPosition().pos[1]; + dest.mZ = target.getRefData().getPosition().pos[2]; + + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + mTimer2 = mTimer2 + duration; + + if(!mPathFinder.isPathConstructed()) + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + else + { + mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); + ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); + if((mTimer2 > 0.25)&&(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || + (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200)) { - xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; - yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; + mTimer2 = 0; + mPathFinder = mPathFinder2; } + } - ESM::Pathgrid::Point dest; - dest.mX = target.getRefData().getPosition().pos[0]; - dest.mY = target.getRefData().getPosition().pos[1]; - dest.mZ = target.getRefData().getPosition().pos[2]; + mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - mTimer2 = mTimer2 + duration; - if(!mPathFinder.isPathConstructed()) - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + float range = 100; + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); + if((dest.mX - start.mX)*(dest.mX - start.mX)+(dest.mY - start.mY)*(dest.mY - start.mY)+(dest.mZ - start.mZ)*(dest.mZ - start.mZ) + < range*range) + { + float directionX = dest.mX - start.mX; + float directionY = dest.mY - start.mY; + float directionResult = sqrt(directionX * directionX + directionY * directionY); + + zAngle = Ogre::Radian( acos(directionY / directionResult) * sgn(asin(directionX / directionResult)) ).valueDegrees(); + MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); + + mPathFinder.clearPath(); + + if(mTimer == 0) + { + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); + //mTimer = mTimer + duration; + } + if( mTimer > 1) + { + MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); + mTimer = 0; + } else { - mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); - ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); - if((mTimer2 > 0.25)&&(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || - (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200)) - { - mTimer2 = 0; - mPathFinder = mPathFinder2; - } + mTimer = mTimer + duration; } - - mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - - - float range = 100; - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); - if((dest.mX - start.mX)*(dest.mX - start.mX)+(dest.mY - start.mY)*(dest.mY - start.mY)+(dest.mZ - start.mZ)*(dest.mZ - start.mZ) - < range*range) - { - float directionX = dest.mX - start.mX; - float directionY = dest.mY - start.mY; - float directionResult = sqrt(directionX * directionX + directionY * directionY); - - zAngle = Ogre::Radian( acos(directionY / directionResult) * sgn(asin(directionX / directionResult)) ).valueDegrees(); - MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false); - - mPathFinder.clearPath(); - - if(mTimer == 0) - { - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false); - //mTimer = mTimer + duration; - } - if( mTimer > 1) - { - MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); - mTimer = 0; - } - else - { - mTimer = mTimer + duration; - } - - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(!MWWorld::Class::get(actor).getCreatureStats(actor).getAttackingOrSpell()); - } + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(!MWWorld::Class::get(actor).getCreatureStats(actor).getAttackingOrSpell()); } return false; } int AiCombat::getTypeId() const { - return 2; + return 5; + } + + unsigned int AiCombat::getPriority() const + { + return 1; } AiCombat *MWMechanics::AiCombat::clone() const diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index eed92ef3a..fa71e261f 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -21,6 +21,8 @@ namespace MWMechanics virtual int getTypeId() const; + virtual unsigned int getPriority() const; + private: std::string mTargetId; diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 794708f22..5832198da 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -22,6 +22,9 @@ namespace MWMechanics virtual int getTypeId() const = 0; ///< 0: Wanter, 1 Travel, 2 Escort, 3 Follow, 4 Activate + + virtual unsigned int getPriority() const {return 0;} + ///< higher number is higher priority (0 beeing the lowest) }; } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 994a7a932..d5fb76ede 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -17,19 +17,14 @@ #include "../mwbase/world.hpp" #include "../mwworld/player.hpp" -#include "../mwbase/mechanicsmanager.hpp" - void MWMechanics::AiSequence::copy (const AiSequence& sequence) { for (std::list::const_iterator iter (sequence.mPackages.begin()); iter!=sequence.mPackages.end(); ++iter) mPackages.push_back ((*iter)->clone()); - mCombat = sequence.mCombat; - mCombatPackage = 0; - if(sequence.mCombat) mCombatPackage = sequence.mCombatPackage->clone(); } -MWMechanics::AiSequence::AiSequence() : mDone (false), mCombat (false), mCombatPackage (0) {} +MWMechanics::AiSequence::AiSequence() : mDone (false) {} MWMechanics::AiSequence::AiSequence (const AiSequence& sequence) : mDone (false) { @@ -69,48 +64,15 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) { if(actor != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) { - if(mCombat) + if (!mPackages.empty()) { - mCombatPackage->execute(actor,duration); - } - else - { - if(actor.getTypeName() == typeid(ESM::NPC).name()) + if (mPackages.front()->execute (actor,duration)) { - ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); - ESM::Position actorpos = actor.getRefData().getPosition(); - float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) - +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) - +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); - float fight = actor.getClass().getCreatureStats(actor).getAiSetting(1); - float disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(actor); - bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - if( ( (fight == 100 ) - || (fight >= 95 && d <= 3000) - || (fight >= 90 && d <= 2000) - || (fight >= 80 && d <= 1000) - || (fight >= 80 && disp <= 40) - || (fight >= 70 && disp <= 35 && d <= 1000) - || (fight >= 60 && disp <= 30 && d <= 1000) - || (fight >= 50 && disp == 0) - || (fight >= 40 && disp <= 10 && d <= 500) ) - && LOS - ) - { - mCombat = true; - mCombatPackage = new AiCombat("player"); - } - } - if (!mPackages.empty()) - { - if (mPackages.front()->execute (actor,duration)) - { - mPackages.erase (mPackages.begin()); - mDone = true; - } - else - mDone = false; + mPackages.erase (mPackages.begin()); + mDone = true; } + else + mDone = false; } } } @@ -119,18 +81,20 @@ void MWMechanics::AiSequence::clear() { for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) delete *iter; - - if(mCombatPackage) - { - delete mCombatPackage; - mCombatPackage = 0; - } + mPackages.clear(); } void MWMechanics::AiSequence::stack (const AiPackage& package) { - mPackages.push_front (package.clone()); + for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); it++) + { + if(mPackages.front()->getPriority() <= package.getPriority()) + mPackages.insert(it,package.clone()); + } + + if(mPackages.empty()) + mPackages.push_front (package.clone()); } void MWMechanics::AiSequence::queue (const AiPackage& package) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index ea2a048f1..0976ef099 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -18,8 +18,6 @@ namespace MWMechanics class AiSequence { std::list mPackages; - AiPackage* mCombatPackage; - bool mCombat; bool mDone; @@ -36,7 +34,7 @@ namespace MWMechanics virtual ~AiSequence(); int getTypeId() const; - ///< -1: None, 0: Wanter, 1 Travel, 2 Escort, 3 Follow, 4 Activate + ///< -1: None, 0: Wanter, 1 Travel, 2 Escort, 3 Follow, 4 Activate, 5 Combat bool isPackageDone() const; ///< Has a package been completed during the last update? @@ -46,7 +44,7 @@ namespace MWMechanics void clear(); ///< Remove all packages. - + void stack (const AiPackage& package); ///< Add \a package to the front of the sequence (suspends current package) From dff3cf162dc415ee7d065b8b5f695918b9aad841 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 18 Nov 2013 23:03:44 +0100 Subject: [PATCH 23/23] ToggleAI script instruction --- apps/openmw/mwbase/mechanicsmanager.hpp | 3 + apps/openmw/mwmechanics/actors.cpp | 68 ++++++++++--------- .../mwmechanics/mechanicsmanagerimp.cpp | 12 +++- .../mwmechanics/mechanicsmanagerimp.hpp | 4 ++ apps/openmw/mwscript/aiextensions.cpp | 15 ++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +- components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 2 + 8 files changed, 76 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 7e09f9b4d..a3a60d96e 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -114,6 +114,9 @@ namespace MWBase /// references that are currently not in the scene should be ignored. virtual bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName) = 0; + + virtual void toggleAI() = 0; + virtual bool isAIActive() = 0; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index cbd369a81..bfb037930 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -39,42 +39,48 @@ namespace MWMechanics if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) { // AI - CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); - - //engage combat or not? - if(ptr != MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && !creatureStats.isHostile()) + if(MWBase::Environment::get().getMechanicsManager())//check MechanismsManager is already created { - ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); - ESM::Position actorpos = ptr.getRefData().getPosition(); - float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) - +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) - +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); - float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(1); - float disp = 100; //creatures don't have disposition, so set it to 100 by default - if(ptr.getTypeName() == typeid(ESM::NPC).name()) + if(MWBase::Environment::get().getMechanicsManager()->isAIActive())//MWBase::Environment::get().getMechanicsManager()->isAIActive()) { - disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr); - } - bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - if( ( (fight == 100 ) - || (fight >= 95 && d <= 3000) - || (fight >= 90 && d <= 2000) - || (fight >= 80 && d <= 1000) - || (fight >= 80 && disp <= 40) - || (fight >= 70 && disp <= 35 && d <= 1000) - || (fight >= 60 && disp <= 30 && d <= 1000) - || (fight >= 50 && disp == 0) - || (fight >= 40 && disp <= 10 && d <= 500) ) - && LOS - ) - { - creatureStats.getAiSequence().stack(AiCombat("player")); - creatureStats.setHostile(true); + CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + if(ptr != MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) MWBase::Environment::get().getMechanicsManager()->restoreDynamicStats(); + //engage combat or not? + if(ptr != MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && !creatureStats.isHostile()) + { + ESM::Position playerpos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); + ESM::Position actorpos = ptr.getRefData().getPosition(); + float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) + +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) + +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); + float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(1); + float disp = 100; //creatures don't have disposition, so set it to 100 by default + if(ptr.getTypeName() == typeid(ESM::NPC).name()) + { + disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr); + } + bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + if( ( (fight == 100 ) + || (fight >= 95 && d <= 3000) + || (fight >= 90 && d <= 2000) + || (fight >= 80 && d <= 1000) + || (fight >= 80 && disp <= 40) + || (fight >= 70 && disp <= 35 && d <= 1000) + || (fight >= 60 && disp <= 30 && d <= 1000) + || (fight >= 50 && disp == 0) + || (fight >= 40 && disp <= 10 && d <= 500) ) + && LOS + ) + { + creatureStats.getAiSequence().stack(AiCombat("player")); + creatureStats.setHostile(true); + } + } + + creatureStats.getAiSequence().execute (ptr,duration); } } - creatureStats.getAiSequence().execute (ptr,duration); - // fatigue restoration calculateRestoration(ptr, duration); } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 8c13db790..cfac6541b 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -165,7 +165,7 @@ namespace MWMechanics MechanicsManager::MechanicsManager() : mUpdatePlayer (true), mClassSelected (false), - mRaceSelected (false) + mRaceSelected (false), mAI(true) { buildPlayer(); } @@ -679,4 +679,14 @@ namespace MWMechanics return false; } + void MechanicsManager::toggleAI() + { + mAI = !mAI; + } + + bool MechanicsManager::isAIActive() + { + return mAI; + } + } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index ad07562c7..2cb84bd65 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -29,6 +29,7 @@ namespace MWMechanics bool mUpdatePlayer; bool mClassSelected; bool mRaceSelected; + bool mAI;///< is AI active? Objects mObjects; Actors mActors; @@ -100,6 +101,9 @@ namespace MWMechanics virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number); virtual void skipAnimation(const MWWorld::Ptr& ptr); virtual bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string &groupName); + + virtual void toggleAI(); + virtual bool isAIActive(); }; } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 39ed36ac7..1cdbaa008 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -25,6 +25,8 @@ #include +#include "../mwbase/mechanicsmanager.hpp" + namespace MWScript { namespace Ai @@ -390,6 +392,17 @@ namespace MWScript } }; + template + class OpToggleAI : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::Environment::get().getMechanicsManager()->toggleAI(); + } + }; + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment3 (Compiler::Ai::opcodeAIActivate, new OpAiActivate); @@ -416,6 +429,8 @@ namespace MWScript interpreter.installSegment3 (Compiler::Ai::opcodeGetDetectedExplicit, new OpGetDetected); interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSight, new OpGetLineOfSight); interpreter.installSegment5 (Compiler::Ai::opcodeGetLineOfSightExplicit, new OpGetLineOfSight); + interpreter.installSegment5 (Compiler::Ai::opcodeToggleAI, new OpToggleAI); + interpreter.installSegment5 (Compiler::Ai::opcodeToggleAIExplicit, new OpToggleAI); interpreter.installSegment5 (Compiler::Ai::opcodeSetHello, new OpSetAiSetting(0)); interpreter.installSegment5 (Compiler::Ai::opcodeSetHelloExplicit, new OpSetAiSetting(0)); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 685741db6..9e024f872 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -356,5 +356,7 @@ op 0x2000220: DisableLevitation op 0x2000221: EnableLevitation op 0x2000222: GetLineOfSight op 0x2000223: GetLineOfSightExplicit +op 0x2000224: ToggleAI +op 0x2000225: ToggleAIExplicit -opcodes 0x2000224-0x3ffffff unused +opcodes 0x2000226-0x3ffffff unused diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 2799c90db..01792def9 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -59,6 +59,7 @@ namespace Compiler extensions.registerInstruction ("modfight", "l", opcodeModFight, opcodeModFightExplicit); extensions.registerInstruction ("modflee", "l", opcodeModFlee, opcodeModFleeExplicit); extensions.registerInstruction ("modalarm", "l", opcodeModAlarm, opcodeModAlarmExplicit); + extensions.registerInstruction ("toggleai", "", opcodeToggleAI, opcodeToggleAI); extensions.registerFunction ("gethello", 'l', "", opcodeGetHello, opcodeGetHelloExplicit); extensions.registerFunction ("getfight", 'l', "", opcodeGetFight, opcodeGetFightExplicit); extensions.registerFunction ("getflee", 'l', "", opcodeGetFlee, opcodeGetFleeExplicit); diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 582edcd33..a885a373d 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -51,6 +51,8 @@ namespace Compiler const int opcodeGetAlarmExplicit = 0x20001c6; const int opcodeGetLineOfSight = 0x2000222; const int opcodeGetLineOfSightExplicit = 0x2000223; + const int opcodeToggleAI = 0x2000224; + const int opcodeToggleAIExplicit = 0x2000225; } namespace Animation