forked from mirror/openmw-tes3mp
Merged pull request #1572
This commit is contained in:
commit
f62df90960
9 changed files with 108 additions and 64 deletions
42
.gitlab-ci.yml
Normal file
42
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# use the official gcc image, based on debian
|
||||||
|
# can use verions as well, like gcc:5.2
|
||||||
|
# see https://hub.docker.com/_/gcc/
|
||||||
|
image: gcc
|
||||||
|
|
||||||
|
cache:
|
||||||
|
key: apt-cache
|
||||||
|
paths:
|
||||||
|
- apt-cache/
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR
|
||||||
|
- apt-get update -yq
|
||||||
|
- apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt4-dev libopenal-dev libopenscenegraph-3.4-dev libunshield-dev libtinyxml-dev
|
||||||
|
# - apt-get install -y libmygui-dev libbullet-dev # to be updated to latest below because stretch is too old
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet-dev_2.87+dfsg-2_amd64.deb -o libbullet-dev_2.87+dfsg-2_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet2.87_2.87+dfsg-2_amd64.deb -o libbullet2.87_2.87+dfsg-2_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb -o libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb -o libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmygui-dev_3.2.2+dfsg-1_amd64.deb -o libmygui-dev_3.2.2+dfsg-1_amd64.deb
|
||||||
|
- dpkg --ignore-depends=libmygui.ogreplatform0debian1v5 -i *.deb
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- nproc
|
||||||
|
- mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../
|
||||||
|
- make -j2
|
||||||
|
- DESTDIR=artifacts make install
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/artifacts/
|
||||||
|
# depending on your build setup it's most likely a good idea to cache outputs to reduce the build time
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- "*.o"
|
||||||
|
|
||||||
|
# run tests using the binary built before
|
||||||
|
test:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- ls
|
|
@ -24,6 +24,7 @@
|
||||||
Bug #4429: [Windows] Error on build INSTALL.vcxproj project (debug) with cmake 3.7.2
|
Bug #4429: [Windows] Error on build INSTALL.vcxproj project (debug) with cmake 3.7.2
|
||||||
Bug #4432: Guards behaviour is incorrect if they do not have AI packages
|
Bug #4432: Guards behaviour is incorrect if they do not have AI packages
|
||||||
Bug #4433: Guard behaviour is incorrect with Alarm = 0
|
Bug #4433: Guard behaviour is incorrect with Alarm = 0
|
||||||
|
Bug #4454: AI opens doors too slow
|
||||||
Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results
|
Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results
|
||||||
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts
|
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts
|
||||||
Feature #4345: Add equivalents for the command line commands to Launcher
|
Feature #4345: Add equivalents for the command line commands to Launcher
|
||||||
|
|
|
@ -139,24 +139,21 @@ namespace MWClass
|
||||||
const std::string trapActivationSound = "Disarm Trap Fail";
|
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||||
|
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
const MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player);
|
MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player);
|
||||||
|
|
||||||
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
||||||
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
||||||
bool hasKey = false;
|
bool hasKey = false;
|
||||||
std::string keyName;
|
std::string keyName;
|
||||||
|
|
||||||
// make key id lowercase
|
const std::string keyId = ptr.getCellRef().getKey();
|
||||||
std::string keyId = ptr.getCellRef().getKey();
|
if (!keyId.empty())
|
||||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
|
||||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
|
||||||
{
|
{
|
||||||
std::string refId = it->getCellRef().getRefId();
|
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
if (!keyPtr.isEmpty())
|
||||||
if (refId == keyId)
|
|
||||||
{
|
{
|
||||||
hasKey = true;
|
hasKey = true;
|
||||||
keyName = it->getClass().getName(*it);
|
keyName = keyPtr.getClass().getName(keyPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace MWClass
|
||||||
const std::string lockedSound = "LockedDoor";
|
const std::string lockedSound = "LockedDoor";
|
||||||
const std::string trapActivationSound = "Disarm Trap Fail";
|
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||||
|
|
||||||
const MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
|
MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
|
||||||
|
|
||||||
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
||||||
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
||||||
|
@ -135,21 +135,14 @@ namespace MWClass
|
||||||
animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing
|
animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing
|
||||||
}
|
}
|
||||||
|
|
||||||
// make key id lowercase
|
const std::string keyId = ptr.getCellRef().getKey();
|
||||||
std::string keyId = ptr.getCellRef().getKey();
|
|
||||||
if (!keyId.empty())
|
if (!keyId.empty())
|
||||||
{
|
{
|
||||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
if (!keyPtr.isEmpty())
|
||||||
{
|
{
|
||||||
std::string refId = it->getCellRef().getRefId();
|
hasKey = true;
|
||||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
keyName = keyPtr.getClass().getName(keyPtr);
|
||||||
if (refId == keyId)
|
|
||||||
{
|
|
||||||
hasKey = true;
|
|
||||||
keyName = it->getClass().getName(*it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,9 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const ESM::Pathgr
|
||||||
|
|
||||||
if (!isDestReached && mTimer > AI_REACTION_TIME)
|
if (!isDestReached && mTimer > AI_REACTION_TIME)
|
||||||
{
|
{
|
||||||
|
if (actor.getClass().isBipedal(actor))
|
||||||
|
openDoors(actor);
|
||||||
|
|
||||||
bool wasShortcutting = mIsShortcutting;
|
bool wasShortcutting = mIsShortcutting;
|
||||||
bool destInLOS = false;
|
bool destInLOS = false;
|
||||||
|
|
||||||
|
@ -209,41 +212,10 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur
|
||||||
// first check if obstacle is a door
|
// first check if obstacle is a door
|
||||||
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||||
|
|
||||||
MWWorld::Ptr door = getNearbyDoor(actor, distance);
|
const MWWorld::Ptr door = getNearbyDoor(actor, distance);
|
||||||
if (door != MWWorld::Ptr() && actor.getClass().isBipedal(actor))
|
if (!door.isEmpty() && actor.getClass().isBipedal(actor))
|
||||||
{
|
{
|
||||||
// note: AiWander currently does not open doors
|
openDoors(actor);
|
||||||
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0)
|
|
||||||
{
|
|
||||||
if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 ))
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWorld()->activate(door, actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string keyId = door.getCellRef().getKey();
|
|
||||||
if (keyId.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool hasKey = false;
|
|
||||||
const MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
|
|
||||||
|
|
||||||
// make key id lowercase
|
|
||||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
|
||||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
|
||||||
{
|
|
||||||
std::string refId = it->getCellRef().getRefId();
|
|
||||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
|
||||||
if (refId == keyId)
|
|
||||||
{
|
|
||||||
hasKey = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasKey)
|
|
||||||
MWBase::Environment::get().getWorld()->activate(door, actor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -251,6 +223,35 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
|
||||||
|
|
||||||
|
const MWWorld::Ptr door = getNearbyDoor(actor, distance);
|
||||||
|
if (door == MWWorld::Ptr())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// note: AiWander currently does not open doors
|
||||||
|
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0)
|
||||||
|
{
|
||||||
|
if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 ))
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->activate(door, actor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string keyId = door.getCellRef().getKey();
|
||||||
|
if (keyId.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
|
||||||
|
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||||
|
|
||||||
|
if (!keyPtr.isEmpty())
|
||||||
|
MWBase::Environment::get().getWorld()->activate(door, actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const MWWorld::CellStore *cell)
|
const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const MWWorld::CellStore *cell)
|
||||||
{
|
{
|
||||||
const ESM::CellId& id = cell->getCell()->getCellId();
|
const ESM::CellId& id = cell->getCell()->getCellId();
|
||||||
|
|
|
@ -123,6 +123,7 @@ namespace MWMechanics
|
||||||
virtual bool doesPathNeedRecalc(const ESM::Pathgrid::Point& newDest, const MWWorld::CellStore* currentCell);
|
virtual bool doesPathNeedRecalc(const ESM::Pathgrid::Point& newDest, const MWWorld::CellStore* currentCell);
|
||||||
|
|
||||||
void evadeObstacles(const MWWorld::Ptr& actor, float duration, const ESM::Position& pos);
|
void evadeObstacles(const MWWorld::Ptr& actor, float duration, const ESM::Position& pos);
|
||||||
|
void openDoors(const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
const PathgridGraph& getPathGridGraph(const MWWorld::CellStore* cell);
|
const PathgridGraph& getPathGridGraph(const MWWorld::CellStore* cell);
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,13 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool proximityToDoor(const MWWorld::Ptr& actor, float minDist)
|
bool proximityToDoor(const MWWorld::Ptr& actor, float minDist)
|
||||||
{
|
{
|
||||||
if(getNearbyDoor(actor, minDist)!=MWWorld::Ptr())
|
if(getNearbyDoor(actor, minDist).isEmpty())
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist)
|
const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist)
|
||||||
{
|
{
|
||||||
MWWorld::CellStore *cell = actor.getCell();
|
MWWorld::CellStore *cell = actor.getCell();
|
||||||
|
|
||||||
|
@ -50,6 +50,16 @@ namespace MWMechanics
|
||||||
const MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
const MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
||||||
|
|
||||||
osg::Vec3f doorPos(ref.mData.getPosition().asVec3());
|
osg::Vec3f doorPos(ref.mData.getPosition().asVec3());
|
||||||
|
|
||||||
|
// FIXME: cast
|
||||||
|
const MWWorld::Ptr doorPtr = MWWorld::Ptr(&const_cast<MWWorld::LiveCellRef<ESM::Door> &>(ref), actor.getCell());
|
||||||
|
|
||||||
|
int doorState = doorPtr.getClass().getDoorState(doorPtr);
|
||||||
|
float doorRot = ref.mData.getPosition().rot[2] - doorPtr.getCellRef().getPosition().rot[2];
|
||||||
|
|
||||||
|
if (doorState != 0 || doorRot != 0)
|
||||||
|
continue; // the door is already opened/opening
|
||||||
|
|
||||||
doorPos.z() = 0;
|
doorPos.z() = 0;
|
||||||
|
|
||||||
float angle = std::acos(actorDir * (doorPos - pos) / (actorDir.length() * (doorPos - pos).length()));
|
float angle = std::acos(actorDir * (doorPos - pos) / (actorDir.length() * (doorPos - pos).length()));
|
||||||
|
@ -62,8 +72,7 @@ namespace MWMechanics
|
||||||
if ((pos - doorPos).length2() > minDist*minDist)
|
if ((pos - doorPos).length2() > minDist*minDist)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// FIXME cast
|
return doorPtr; // found, stop searching
|
||||||
return MWWorld::Ptr(&const_cast<MWWorld::LiveCellRef<ESM::Door> &>(ref), actor.getCell()); // found, stop searching
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MWWorld::Ptr(); // none found
|
return MWWorld::Ptr(); // none found
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
/// Returns door pointer within range. No guarantee is given as to which one
|
/// Returns door pointer within range. No guarantee is given as to which one
|
||||||
/** \return Pointer to the door, or NULL if none exists **/
|
/** \return Pointer to the door, or NULL if none exists **/
|
||||||
MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist);
|
const MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist);
|
||||||
|
|
||||||
class ObstacleCheck
|
class ObstacleCheck
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace
|
||||||
for (typename MWWorld::CellRefList<T>::List::iterator iter (list.mList.begin());
|
for (typename MWWorld::CellRefList<T>::List::iterator iter (list.mList.begin());
|
||||||
iter!=list.mList.end(); ++iter)
|
iter!=list.mList.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (Misc::StringUtils::ciEqual(iter->mBase->mId, id2))
|
if (Misc::StringUtils::ciEqual(iter->mBase->mId, id2) && iter->mData.getCount())
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr (&*iter, 0);
|
MWWorld::Ptr ptr (&*iter, 0);
|
||||||
ptr.setContainerStore (store);
|
ptr.setContainerStore (store);
|
||||||
|
|
Loading…
Reference in a new issue