diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index 60d7d7512b..1fdd52cb7f 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -154,23 +154,23 @@ namespace MWLua return !keep; }); }; - selfAPI["_startAiCombat"] = [](SelfObject& self, const LObject& target) { + selfAPI["_startAiCombat"] = [](SelfObject& self, const LObject& target, bool cancelOther) { const MWWorld::Ptr& ptr = self.ptr(); MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - ai.stack(MWMechanics::AiCombat(target.ptr()), ptr); + ai.stack(MWMechanics::AiCombat(target.ptr()), ptr, cancelOther); }; - selfAPI["_startAiPursue"] = [](SelfObject& self, const LObject& target) { + selfAPI["_startAiPursue"] = [](SelfObject& self, const LObject& target, bool cancelOther) { const MWWorld::Ptr& ptr = self.ptr(); MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - ai.stack(MWMechanics::AiPursue(target.ptr()), ptr); + ai.stack(MWMechanics::AiPursue(target.ptr()), ptr, cancelOther); }; - selfAPI["_startAiFollow"] = [](SelfObject& self, const LObject& target) { + selfAPI["_startAiFollow"] = [](SelfObject& self, const LObject& target, bool cancelOther) { const MWWorld::Ptr& ptr = self.ptr(); MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - ai.stack(MWMechanics::AiFollow(target.ptr()), ptr); + ai.stack(MWMechanics::AiFollow(target.ptr()), ptr, cancelOther); }; selfAPI["_startAiEscort"] = [](SelfObject& self, const LObject& target, LCell cell, float duration, - const osg::Vec3f& dest) { + const osg::Vec3f& dest, bool cancelOther) { const MWWorld::Ptr& ptr = self.ptr(); MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence(); // TODO: change AiEscort implementation to accept ptr instead of a non-unique refId. @@ -178,22 +178,23 @@ namespace MWLua int gameHoursDuration = static_cast(std::ceil(duration / 3600.0)); auto* esmCell = cell.mStore->getCell(); if (esmCell->isExterior()) - ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), false), ptr); + ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), false), ptr, + cancelOther); else ai.stack(MWMechanics::AiEscort( refId, esmCell->getNameId(), gameHoursDuration, dest.x(), dest.y(), dest.z(), false), - ptr); + ptr, cancelOther); }; - selfAPI["_startAiWander"] = [](SelfObject& self, int distance, float duration) { + selfAPI["_startAiWander"] = [](SelfObject& self, int distance, float duration, bool cancelOther) { const MWWorld::Ptr& ptr = self.ptr(); MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence(); int gameHoursDuration = static_cast(std::ceil(duration / 3600.0)); - ai.stack(MWMechanics::AiWander(distance, gameHoursDuration, 0, {}, false), ptr); + ai.stack(MWMechanics::AiWander(distance, gameHoursDuration, 0, {}, false), ptr, cancelOther); }; - selfAPI["_startAiTravel"] = [](SelfObject& self, const osg::Vec3f& target) { + selfAPI["_startAiTravel"] = [](SelfObject& self, const osg::Vec3f& target, bool cancelOther) { const MWWorld::Ptr& ptr = self.ptr(); MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - ai.stack(MWMechanics::AiTravel(target.x(), target.y(), target.z(), false), ptr); + ai.stack(MWMechanics::AiTravel(target.x(), target.y(), target.z(), false), ptr, cancelOther); }; } diff --git a/docs/source/reference/lua-scripting/aipackages.rst b/docs/source/reference/lua-scripting/aipackages.rst index 4570be712e..39f973c65d 100644 --- a/docs/source/reference/lua-scripting/aipackages.rst +++ b/docs/source/reference/lua-scripting/aipackages.rst @@ -1,6 +1,38 @@ Built-in AI packages ==================== +Starting an AI package +---------------------- + +There are two ways to start AI package: + +.. code-block:: Lua + + -- from local script add package to self + local AI = require('openmw.interfaces').AI + AI.startPackage(options) + + -- via event to any actor + actor:sendEvent('StartAIPackage', options) + +``options`` is Lua table with arguments of the AI package. + +**Common arguments that can be used with any AI package** + +.. list-table:: + :header-rows: 1 + :widths: 20 20 60 + + * - name + - type + - description + * - type + - string [required] + - the name of the package (see packages listed below) + * - cancelOther + - boolean [default=true] + - whether to cancel all other AI packages + Combat ------ diff --git a/files/data/scripts/omw/ai.lua b/files/data/scripts/omw/ai.lua index b20c927c8a..0bf9e1bbec 100644 --- a/files/data/scripts/omw/ai.lua +++ b/files/data/scripts/omw/ai.lua @@ -2,24 +2,26 @@ local self = require('openmw.self') local interfaces = require('openmw.interfaces') local function startPackage(args) + local cancelOther = args.cancelOther + if cancelOther == nil then cancelOther = true end if args.type == 'Combat' then if not args.target then error("target required") end - self:_startAiCombat(args.target) + self:_startAiCombat(args.target, cancelOther) elseif args.type == 'Pursue' then if not args.target then error("target required") end - self:_startAiPursue(args.target) + self:_startAiPursue(args.target, cancelOther) elseif args.type == 'Follow' then if not args.target then error("target required") end - self:_startAiFollow(args.target) + self:_startAiFollow(args.target, cancelOther) elseif args.type == 'Escort' then if not args.target then error("target required") end if not args.destPosition then error("destPosition required") end - self:_startAiEscort(args.target, args.destCell or self.cell, args.duration or 0, args.destPosition) + self:_startAiEscort(args.target, args.destCell or self.cell, args.duration or 0, args.destPosition, cancelOther) elseif args.type == 'Wander' then - self:_startAiWander(args.distance or 0, args.duration or 0) + self:_startAiWander(args.distance or 0, args.duration or 0, cancelOther) elseif args.type == 'Travel' then if not args.destPosition then error("destPosition required") end - self:_startAiTravel(args.destPosition) + self:_startAiTravel(args.destPosition, cancelOther) else error('Unsupported AI Package: ' .. args.type) end