From 01b3f92f7eac5d792bf910b966b441605c01ea07 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 13 Sep 2018 13:21:38 +0400 Subject: [PATCH] Make coc and fixme console commands close to vanilla (bug #4292, bug #4217) --- apps/openmw/mwscript/cellextensions.cpp | 12 +-- .../mwscript/transformationextensions.cpp | 6 +- apps/openmw/mwworld/worldimp.cpp | 77 +++++++++++++++---- components/compiler/extensions0.cpp | 2 +- components/compiler/opcodes.hpp | 1 - 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 2cb76ef884..f01fed2ce1 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -46,18 +46,19 @@ namespace MWScript ESM::Position pos; MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::Ptr playerPtr = world->getPlayerPtr(); if (world->findExteriorPosition(cell, pos)) { - MWWorld::ActionTeleport("", pos, false).execute(world->getPlayerPtr()); - world->fixPosition(world->getPlayerPtr()); + MWWorld::ActionTeleport("", pos, false).execute(playerPtr); + world->adjustPosition(playerPtr, false); } else { // Change to interior even if findInteriorPosition() // yields false. In this case position will be zero-point. world->findInteriorPosition(cell, pos); - MWWorld::ActionTeleport(cell, pos, false).execute(world->getPlayerPtr()); + MWWorld::ActionTeleport(cell, pos, false).execute(playerPtr); } } }; @@ -76,14 +77,15 @@ namespace MWScript ESM::Position pos; MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::Ptr playerPtr = world->getPlayerPtr(); world->indexToPosition (x, y, pos.pos[0], pos.pos[1], true); pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - MWWorld::ActionTeleport("", pos, false).execute(world->getPlayerPtr()); - world->fixPosition(world->getPlayerPtr()); + MWWorld::ActionTeleport("", pos, false).execute(playerPtr); + world->adjustPosition(playerPtr, false); } }; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 16d7e80364..9d7a5c6edc 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -732,14 +732,13 @@ namespace MWScript } }; - template class OpFixme : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { - MWWorld::Ptr ptr = R()(runtime); + const MWWorld::Ptr ptr = MWMechanics::getPlayer(); MWBase::Environment::get().getWorld()->fixPosition(ptr); } }; @@ -784,8 +783,7 @@ namespace MWScript interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngle, new OpGetStartingAngle); interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngleExplicit, new OpGetStartingAngle); interpreter.installSegment5(Compiler::Transformation::opcodeResetActors, new OpResetActors); - interpreter.installSegment5(Compiler::Transformation::opcodeFixme, new OpFixme); - interpreter.installSegment5(Compiler::Transformation::opcodeFixmeExplicit, new OpFixme); + interpreter.installSegment5(Compiler::Transformation::opcodeFixme, new OpFixme); } } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 2afcdffc8b..29161c2985 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -246,7 +246,7 @@ namespace MWWorld if (findExteriorPosition (mStartCell, pos)) { changeToExteriorCell (pos, true); - fixPosition(getPlayerPtr()); + adjustPosition(getPlayerPtr(), false); } else { @@ -1353,13 +1353,37 @@ namespace MWWorld void World::fixPosition(const Ptr &actor) { - const float dist = 8000; - osg::Vec3f pos (actor.getRefData().getPosition().asVec3()); - pos.z() += dist; + const float distance = 128.f; + ESM::Position esmPos = actor.getRefData().getPosition(); + osg::Quat orientation(esmPos.rot[2], osg::Vec3f(0,0,-1)); + osg::Vec3f pos (esmPos.asVec3()); - osg::Vec3f traced = mPhysics->traceDown(actor, pos, dist*1.1f); + int direction = 0; + int fallbackDirections[4] = {direction, (direction+3)%4, (direction+2)%4, (direction+1)%4}; + + osg::Vec3f targetPos = pos; + for (int i=0; i<4; ++i) + { + direction = fallbackDirections[i]; + if (direction == 0) targetPos = pos + (orientation * osg::Vec3f(0,1,0)) * distance; + else if(direction == 1) targetPos = pos - (orientation * osg::Vec3f(0,1,0)) * distance; + else if(direction == 2) targetPos = pos - (orientation * osg::Vec3f(1,0,0)) * distance; + else if(direction == 3) targetPos = pos + (orientation * osg::Vec3f(1,0,0)) * distance; + + // destination is free + if (!castRay(pos.x(), pos.y(), pos.z(), targetPos.x(), targetPos.y(), targetPos.z())) + break; + } + + targetPos.z() += distance / 2.f; // move up a bit to get out from geometry, will snap down later + osg::Vec3f traced = mPhysics->traceDown(actor, targetPos, Constants::CellSizeInUnits); if (traced != pos) - moveObject(actor, actor.getCell(), traced.x(), traced.y(), traced.z()); + { + esmPos.pos[0] = traced.x(); + esmPos.pos[1] = traced.y(); + esmPos.pos[2] = traced.z(); + MWWorld::ActionTeleport("", esmPos, false).execute(actor); + } } void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) @@ -1429,7 +1453,7 @@ namespace MWWorld ipos.rot[2] = referenceObject.getRefData().getPosition().rot[2]; MWWorld::Ptr placed = copyObjectToCell(ptr, referenceCell, ipos, ptr.getRefData().getCount(), false); - placed.getClass().adjustPosition(placed, true); // snap to ground + adjustPosition(placed, true); // snap to ground return placed; } @@ -2604,31 +2628,52 @@ namespace MWWorld return false; } + std::vector sortedDoors; const DoorList &doors = cellStore->getReadOnlyDoors().mList; - for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) { - if (!it->mRef.getTeleport()) { + for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) + { + if (!it->mRef.getTeleport()) + { continue; } + sortedDoors.push_back(&it->mRef); + } + + // Sort teleporting doors alphabetically, first by ID, then by destination cell to make search consistent + std::sort(sortedDoors.begin(), sortedDoors.end(), [] (const MWWorld::CellRef *lhs, const MWWorld::CellRef *rhs) + { + if (lhs->getRefId() != rhs->getRefId()) + return lhs->getRefId() < rhs->getRefId(); + + return lhs->getDestCell() < rhs->getDestCell(); + }); + + for (std::vector::const_iterator it = sortedDoors.begin(); it != sortedDoors.end(); ++it) + { MWWorld::CellStore *source = 0; // door to exterior - if (it->mRef.getDestCell().empty()) { + if ((*it)->getDestCell().empty()) + { int x, y; - ESM::Position doorDest = it->mRef.getDoorDest(); + ESM::Position doorDest = (*it)->getDoorDest(); positionToIndex(doorDest.pos[0], doorDest.pos[1], x, y); source = getExterior(x, y); } // door to interior - else { - source = getInterior(it->mRef.getDestCell()); + else + { + source = getInterior((*it)->getDestCell()); } - if (0 != source) { + if (0 != source) + { // Find door leading to our current teleport door // and use its destination to position inside cell. const DoorList &destinationDoors = source->getReadOnlyDoors().mList; - for (DoorList::const_iterator jt = destinationDoors.begin(); jt != destinationDoors.end(); ++jt) { - if (it->mRef.getTeleport() && + for (DoorList::const_iterator jt = destinationDoors.begin(); jt != destinationDoors.end(); ++jt) + { + if ((*it)->getTeleport() && Misc::StringUtils::ciEqual(name, jt->mRef.getDestCell())) { /// \note Using _any_ door pointed to the interior, diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 7638d0f784..7979f06b91 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -546,7 +546,7 @@ namespace Compiler extensions.registerInstruction("moveworld","cf",opcodeMoveWorld,opcodeMoveWorldExplicit); extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit); extensions.registerInstruction("resetactors","",opcodeResetActors); - extensions.registerInstruction("fixme","",opcodeFixme, opcodeFixmeExplicit); + extensions.registerInstruction("fixme","",opcodeFixme); extensions.registerInstruction("ra","",opcodeResetActors); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index aef92b311b..c141eec682 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -504,7 +504,6 @@ namespace Compiler const int opcodeMoveWorldExplicit = 0x2000209; const int opcodeResetActors = 0x20002f4; const int opcodeFixme = 0x2000302; - const int opcodeFixmeExplicit = 0x2000303; } namespace User