From 8ea4ff53cbde3ce66d9f05fbd47a13c3c983fea8 Mon Sep 17 00:00:00 2001 From: Nuno Date: Thu, 25 Nov 2021 09:36:43 +0100 Subject: [PATCH 1/3] Added stairs collisions --- nel/include/nel/pacs/move_container.h | 2 +- nel/include/nel/pacs/move_primitive.h | 25 ++++++ nel/include/nel/pacs/u_move_primitive.h | 14 +++ nel/src/pacs/move_container.cpp | 30 +++++-- nel/src/pacs/move_primitive.cpp | 7 ++ ryzom/client/src/entities.cpp | 114 +++++++++++++----------- ryzom/client/src/entity_cl.cpp | 15 +++- ryzom/client/src/main_loop.cpp | 51 +++++++++-- 8 files changed, 193 insertions(+), 65 deletions(-) diff --git a/nel/include/nel/pacs/move_container.h b/nel/include/nel/pacs/move_container.h index 5193e8386..f368dd5e9 100644 --- a/nel/include/nel/pacs/move_container.h +++ b/nel/include/nel/pacs/move_container.h @@ -244,7 +244,7 @@ private: CCollisionOTStaticInfo *staticColInfo); // Add a trigger in the trigger array - void newTrigger (CMovePrimitive* first, CMovePrimitive* second, const CCollisionDesc& desc, uint triggerType); + bool newTrigger (CMovePrimitive* first, CMovePrimitive* second, const CCollisionDesc& desc, uint triggerType); // Clear modified primitive list void clearModifiedList (uint8 worldImage); diff --git a/nel/include/nel/pacs/move_primitive.h b/nel/include/nel/pacs/move_primitive.h index aa153c076..d77517a7d 100644 --- a/nel/include/nel/pacs/move_primitive.h +++ b/nel/include/nel/pacs/move_primitive.h @@ -251,6 +251,27 @@ public: _Height=height; } + void setZOffset(float offset) + { + _ZOffset = offset; + } + + float getZOffset() + { + return _ZOffset; + } + + bool haveZOffset() + { + return _HaveZOffset; + } + + void enableZOffset(bool enabled) + { + _HaveZOffset = enabled; + } + + /** * Set the cylinder size. Only for cylinder. * @@ -466,6 +487,10 @@ private: // Iteration count sint32 _IterationCount; + + float _ZOffset; + bool _HaveZOffset; + }; } // NLPACS diff --git a/nel/include/nel/pacs/u_move_primitive.h b/nel/include/nel/pacs/u_move_primitive.h index 5a021daa8..e067c3e6b 100644 --- a/nel/include/nel/pacs/u_move_primitive.h +++ b/nel/include/nel/pacs/u_move_primitive.h @@ -114,6 +114,12 @@ public: * This is an overlap trigger. This trigger is actived each time the object overlap the trigger. */ OverlapTrigger=0x400, + + /** + * This is an stairs trigger. This trigger is actived each time the object overlap the trigger and change Z position. + */ + OverlapStairsTrigger=0x800, + }; /** @@ -274,6 +280,14 @@ public: */ virtual float getHeight () const =0; + virtual void setZOffset(float offset) =0; + + virtual float getZOffset() =0; + + virtual bool haveZOffset() =0; + + virtual void enableZOffset(bool enabled) =0; + /** * Set the cylinder size. Only for cylinder. * diff --git a/nel/src/pacs/move_container.cpp b/nel/src/pacs/move_container.cpp index 35b7ddcd6..424f7d8b9 100644 --- a/nel/src/pacs/move_container.cpp +++ b/nel/src/pacs/move_container.cpp @@ -918,8 +918,10 @@ bool CMoveContainer::evalPrimAgainstPrimCollision (double beginTime, CMovePrimit || (otherPrimitive->getTriggerType()&UMovePrimitive::EnterTrigger)); bool exit = (beginTime<=lastTime) && (lastTime<_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::ExitTrigger) || (otherPrimitive->getTriggerType()&UMovePrimitive::ExitTrigger)); - bool overlap = (firstTime<=beginTime) && (lastTime>_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::OverlapTrigger) - || (otherPrimitive->getTriggerType()&UMovePrimitive::OverlapTrigger)); + bool overlap = ((firstTime<=beginTime) && (lastTime>_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::OverlapTrigger) + || (otherPrimitive->getTriggerType()&UMovePrimitive::OverlapTrigger)) || + (firstTime<=beginTime) && (lastTime>_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::OverlapStairsTrigger) + || (otherPrimitive->getTriggerType()&UMovePrimitive::OverlapStairsTrigger))); bool contact = ( beginTime<((firstTime+lastTime)/2) ) && (firstTime<=_DeltaTime); bool collision = contact && (primitive->isObstacle() && otherPrimitive->isObstacle ()); @@ -1211,7 +1213,7 @@ void CMoveContainer::newCollision (CMovePrimitive* first, const CCollisionSurfac // *************************************************************************** -void CMoveContainer::newTrigger (CMovePrimitive* first, CMovePrimitive* second, const CCollisionDesc& desc, uint triggerType) +bool CMoveContainer::newTrigger (CMovePrimitive* first, CMovePrimitive* second, const CCollisionDesc& desc, uint triggerType) { // Element index uint index=(uint)_Triggers.size(); @@ -1224,6 +1226,14 @@ void CMoveContainer::newTrigger (CMovePrimitive* first, CMovePrimitive* second, _Triggers[index].Object1=second->UserData; _Triggers[index].CollisionDesc=desc; _Triggers[index].CollisionType = uint8(triggerType); + + + if (second->_StaticFlags&UMovePrimitive::OverlapStairsTrigger) { + nlinfo("Col Stairs height %f", second->getHeight()); + return true; + } + + return false; } // *************************************************************************** @@ -1659,8 +1669,18 @@ void CMoveContainer::reaction (const CCollisionOTInfo& first) newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::In); if (dynInfo->isExit()) newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::Out); - if (dynInfo->isInside()) - newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::Inside); + if (dynInfo->isInside()) { + if (newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::Inside)) + { + dynInfo->getFirstPrimitive()->enableZOffset(true); + CVectorD first_pos = dynInfo->getFirstPrimitive()->getFinalPosition(dynInfo->getFirstWorldImage()); + CVectorD second_pos = dynInfo->getSecondPrimitive()->getFinalPosition(dynInfo->getSecondWorldImage()); + nlinfo("P = %f, C = %f, H = %f, D = %f", first_pos.z, second_pos.z, dynInfo->getSecondPrimitive()->getHeight(), second_pos.z-first_pos.z); + dynInfo->getFirstPrimitive()->setZOffset(second_pos.z+dynInfo->getSecondPrimitive()->getHeight()-1.0f); + } + } + if (dynInfo->isExit()) + newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::Out); } } } diff --git a/nel/src/pacs/move_primitive.cpp b/nel/src/pacs/move_primitive.cpp index 039fa0c7b..261d7bbf8 100644 --- a/nel/src/pacs/move_primitive.cpp +++ b/nel/src/pacs/move_primitive.cpp @@ -49,6 +49,8 @@ CMovePrimitive::CMovePrimitive (CMoveContainer* container, uint8 firstWorldImage _StaticFlags=0; _RootOTInfo=NULL; _LastTestTime=0xffffffff; + _ZOffset = 0; + _HaveZOffset = false; // Ptr table alloc _WorldImages=_Container->allocateWorldImagesPtrs (numWorldImage); @@ -149,6 +151,11 @@ bool CMovePrimitive::isTriggered (CMovePrimitive& second, bool enter, bool exit) { // Generate a trigger ? + + // Is one of them is a stairs trigger ? + if ( second._StaticFlags&OverlapStairsTrigger ) + return true; + // Is the two are not triggers ? if ( ( (_StaticFlags&TriggerMask) == NotATrigger ) && ( (second._StaticFlags&TriggerMask) == NotATrigger ) ) return false; diff --git a/ryzom/client/src/entities.cpp b/ryzom/client/src/entities.cpp index 6a64ea449..a17a49e4f 100644 --- a/ryzom/client/src/entities.cpp +++ b/ryzom/client/src/entities.cpp @@ -461,7 +461,7 @@ void CEntityManager::initialize(uint nbMaxEntity) NLGUI::CDBManager::getInstance()->getDB()->addObserver(&TeamUIDObserver, textId ); _GroupMemberUidDB[i] = NLGUI::CDBManager::getInstance()->getDbProp(text, false); nlassert(_GroupMemberUidDB[i]); - + text = toString(TEAM_DB_PATH ":%d:NAME", i); textId = ICDBNode::CTextId(text); NLGUI::CDBManager::getInstance()->getDB()->addObserver(&TeamPresentObserver, textId ); @@ -477,13 +477,13 @@ void CEntityManager::initialize(uint nbMaxEntity) NLGUI::CDBManager::getInstance()->getDB()->addObserver(&AnimalUIDObserver, textId); _BeastUidDB[i] = NLGUI::CDBManager::getInstance()->getDbProp(text, false); nlassert(_BeastUidDB[i]); - + text = toString("SERVER:PACK_ANIMAL:BEAST%d:STATUS", i); textId = ICDBNode::CTextId(text); NLGUI::CDBManager::getInstance()->getDB()->addObserver(&AnimalStatusObserver, textId); _BeastStatusDB[i] = NLGUI::CDBManager::getInstance()->getDbProp(text, false); nlassert(_BeastStatusDB[i]); - + text = toString("SERVER:PACK_ANIMAL:BEAST%d:TYPE", i); _BeastTypeDB[i] = NLGUI::CDBManager::getInstance()->getDbProp(text, false); nlassert(_BeastTypeDB[i]); @@ -550,7 +550,7 @@ CShapeInstanceReference CEntityManager::createInstance(const string& shape, cons primitive = PACS->addCollisionablePrimitive(dynamicWI, 1); primitive->setDontSnapToGround(false); } - + // Put instance in last deleted position if found if (_LastRemovedInstance != -1) { @@ -562,7 +562,7 @@ CShapeInstanceReference CEntityManager::createInstance(const string& shape, cons _ShapeInstances[idx].BboxActive = !text.empty() || !url.empty(); _ShapeInstances[idx].Deleted = false; _ShapeInstances[idx].InIGZone = inIgZone > 0; - + _LastRemovedInstance = _ShapeInstances[idx].LastDeleted; _ShapeInstances[idx].LastDeleted = -1; TIGZoneShapes::iterator it = _IgZoneShapes.find(inIgZone); @@ -613,7 +613,7 @@ bool CEntityManager::deleteInstance(uint32 idx) UMovePrimitive *primitive = _ShapeInstances[idx].Primitive; if (primitive) PACS->removePrimitive(primitive); - + if (!_ShapeInstances[idx].Deleted) { _ShapeInstances[idx].Primitive = NULL; @@ -649,7 +649,7 @@ CVector CEntityManager::getInstancePos(uint32 idx) UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return CVector(0,0,0); - + return instance.getPos(); } @@ -657,17 +657,17 @@ bool CEntityManager::setInstancePos(uint32 idx, CVector pos) { if (!Scene || idx >= _ShapeInstances.size() || _ShapeInstances[idx].Deleted) return false; - + UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return false; - + UMovePrimitive *primitive = _ShapeInstances[idx].Primitive; if (primitive) { primitive->setGlobalPosition(_ShapeInstances[idx].PrimRelativePos + pos, dynamicWI); } - + instance.setPos(pos); return true; } @@ -676,11 +676,11 @@ CVector CEntityManager::getInstanceRot(uint32 idx) { if (!Scene || idx >= _ShapeInstances.size() || _ShapeInstances[idx].Deleted) return CVector(0,0,0); - + UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return CVector(0,0,0); - + return instance.getRotEuler(); } @@ -688,13 +688,13 @@ bool CEntityManager::setInstanceRot(uint32 idx, CVector rot) { if (!Scene || idx >= _ShapeInstances.size() || _ShapeInstances[idx].Deleted) return false; - + UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return false; - + instance.setRotEuler(rot); - + return true; } @@ -706,7 +706,7 @@ CVector CEntityManager::getInstanceScale(uint32 idx) UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return CVector(0,0,0); - + return instance.getScale(); } @@ -714,7 +714,7 @@ CVector CEntityManager::getInstanceColPos(uint32 idx) { if (!Scene || idx >= _ShapeInstances.size() || _ShapeInstances[idx].Deleted) return CVector(0,0,0); - + return _ShapeInstances[idx].PrimRelativePos; } @@ -726,11 +726,11 @@ CVector CEntityManager::getInstanceColScale(uint32 idx) UMovePrimitive *primitive = _ShapeInstances[idx].Primitive; if (!primitive) return CVector(0,0,0); - + float width, depth; primitive->getSize(width, depth); float height = primitive->getHeight(); - + return CVector(width, depth, height); } @@ -738,11 +738,11 @@ double CEntityManager::getInstanceColOrient(uint32 idx) { if (!Scene || idx >= _ShapeInstances.size() || _ShapeInstances[idx].Deleted) return 0.f; - + UMovePrimitive *primitive = _ShapeInstances[idx].Primitive; if (!primitive) return 0.f; - + return primitive->getOrientation(dynamicWI); } @@ -754,21 +754,21 @@ CVector CEntityManager::getInstanceBBoxMin(uint32 idx) UInstance instance = _ShapeInstances[idx].Instance; if (instance.empty()) return CVector(0,0,0); - + NLMISC::CAABBox bbox; _ShapeInstances[idx].Instance.getShapeAABBox(bbox); - + CVector bbox_min; - + if (bbox.getCenter() == CVector::Null) bbox_min = CVector(-0.5f, -0.5f, -0.5f); else bbox_min = bbox.getMin(); - + bbox_min.x *= _ShapeInstances[idx].Instance.getScale().x; bbox_min.y *= _ShapeInstances[idx].Instance.getScale().y; bbox_min.z *= _ShapeInstances[idx].Instance.getScale().z; - + return bbox_min+_ShapeInstances[idx].Instance.getPos(); } @@ -780,28 +780,28 @@ CVector CEntityManager::getInstanceBBoxMax(uint32 idx) UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return CVector(0,0,0); - + NLMISC::CAABBox bbox; _ShapeInstances[idx].Instance.getShapeAABBox(bbox); - + CVector bbox_max; - + if (bbox.getCenter() == CVector::Null) bbox_max = CVector(-0.5f, -0.5f, -0.5f); else bbox_max = bbox.getMax(); - + bbox_max.x *= _ShapeInstances[idx].Instance.getScale().x; bbox_max.y *= _ShapeInstances[idx].Instance.getScale().y; bbox_max.z *= _ShapeInstances[idx].Instance.getScale().z; - + return bbox_max+_ShapeInstances[idx].Instance.getPos(); } bool CEntityManager::removeInstances() { if (!Scene) return false; - + for(uint i=0; i<_ShapeInstances.size(); ++i) { if (!_ShapeInstances[i].InIGZone) @@ -814,13 +814,13 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { if (!Scene || idx >= _ShapeInstances.size() || _ShapeInstances[idx].Deleted) return false; - + UInstance instance = _ShapeInstances[idx].Instance; if(instance.empty()) return false; - + UMovePrimitive *primitive = _ShapeInstances[idx].Primitive; - + for (uint32 i=0; i < keys.size(); i++) { string param = keys[i]; @@ -891,7 +891,7 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { float v; CVector pos = getInstancePos(idx); - + if (getRelativeFloatFromString(values[i], v)) { updateVector(param, pos, v, true); @@ -904,10 +904,10 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const } else if (param == "rot x" || param == "rot y" || param == "rot z") { - + float v; CVector rot = getInstanceRot(idx); - + if (getRelativeFloatFromString(values[i], v)) { updateVector(param, rot, v, true); @@ -922,7 +922,7 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { float v; CVector scale = instance.getScale(); - + if (getRelativeFloatFromString(values[i], v)) { updateVector(param, scale, v, true); @@ -933,17 +933,17 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const } instance.setScale(scale); } - + // Primitive colissions setups - + if (!primitive) continue; - + if (param == "col size x" || param == "col size y" || param == "col size z") { float width, depth; primitive->getSize(width, depth); float height = primitive->getHeight(); - + CVector size = CVector(width, depth, height); float v; if (getRelativeFloatFromString(values[i], v)) @@ -961,7 +961,7 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { CVector pos = instance.getPos(); float v; - + if (getRelativeFloatFromString(values[i], v)) { updateVector(param, _ShapeInstances[idx].PrimRelativePos, v, false); @@ -981,10 +981,10 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { double orient = primitive->getOrientation(dynamicWI); double v = 0.f; - + if (values[i].empty()) continue; - + if (values[i][0] == '+') { fromString(values[i].substr(1), v); @@ -995,7 +995,7 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const fromString(values[i], v); orient = v; } - + primitive->setOrientation(orient, dynamicWI); } else if (param == "col mask player") @@ -1024,9 +1024,23 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const fromString(values[i], active); primitive->setObstacle(active); } - else if (param == "col obstacle") + else if (param == "col stairs") { - + bool active; + fromString(values[i], active); + primitive->setObstacle(active); + if (active) + { + primitive->setReactionType(UMovePrimitive::DoNothing); + primitive->setTriggerType(UMovePrimitive::OverlapStairsTrigger); + primitive->setGlobalPosition(instance.getPos()+CVector(0, 0, 0.5f), dynamicWI); + } + else + { + primitive->setReactionType(UMovePrimitive::Slide); + primitive->setTriggerType(UMovePrimitive::NotATrigger); + primitive->setGlobalPosition(instance.getPos(), dynamicWI); + } } } @@ -1039,7 +1053,7 @@ CShapeInstanceReference CEntityManager::getShapeInstanceUnderPos(float x, float CShapeInstanceReference selectedInstance(UInstance(), string(""), string("")); _LastInstanceUnderPos= NULL; idx = -1; - + // If not initialised, return if (_ShapeInstances.empty()) return selectedInstance; diff --git a/ryzom/client/src/entity_cl.cpp b/ryzom/client/src/entity_cl.cpp index 9b7ca340e..c523449a1 100644 --- a/ryzom/client/src/entity_cl.cpp +++ b/ryzom/client/src/entity_cl.cpp @@ -1478,6 +1478,7 @@ void CEntityCL::pacsMove(const CVectorD &vect) if ((fabs (deltaPos.x) > 0.05) || (fabs (deltaPos.y) > 0.05)) { _HasMoved = true; + _Primitive->enableZOffset(false); _Primitive->move (deltaPos, dynamicWI); } } @@ -1657,7 +1658,7 @@ void CEntityCL::snapToGround() { if ( isUser() || isPlayer() || isNPC()) { - + float waterOffset = ClientCfg.WaterOffset; switch(people()) { @@ -1713,6 +1714,12 @@ void CEntityCL::snapToGround() pos().z = vect.z; } + if (_Primitive->haveZOffset()) { + //CVectorD prim_pos = _Primitive->getFinalPosition(dynamicWI); + pos().z = _Primitive->getZOffset(); + } + + // Set the box position. posBox(pos()); }// snapToGround // @@ -2294,7 +2301,7 @@ void CEntityCL::onStringAvailable(uint /* stringId */, const std::string &value) { womanTitle = ( c->getGender() == GSGENDER::female ); } - + string replacement = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(_TitleRaw, womanTitle); // Sometimes translation contains another title @@ -2792,7 +2799,7 @@ void CEntityCL::setOpacityMin(uint32 value) bool CEntityCL::mustShowInsceneInterface( bool enabledInSheet ) const { return ( - (enabledInSheet /*&& !CNPCIconCache::getInstance().getNPCIcon(this).getTextureMain().empty()*/) && + (enabledInSheet /*&& !CNPCIconCache::getInstance().getNPCIcon(this).getTextureMain().empty()*/) && (_InSceneInterfaceEnabled) && ( ClientCfg.Names || isUser () || @@ -3137,7 +3144,7 @@ void CEntityCL::updateVisiblePostPos(const NLMISC::TTime &/* currentTimeInMs */, if (skeleton()) _StateFX.setClusterSystem(skeleton()->getClusterSystem()); } - + if (!_SelectionFX.empty() || !_MouseOverFX.empty()) { // Build a matrix for the fx diff --git a/ryzom/client/src/main_loop.cpp b/ryzom/client/src/main_loop.cpp index 492d54623..bb9a29d4d 100644 --- a/ryzom/client/src/main_loop.cpp +++ b/ryzom/client/src/main_loop.cpp @@ -1421,7 +1421,7 @@ bool mainLoop() MainCam.setTransformMode(UTransformable::RotQuat); CVector cameraMoves = UserEntity->getCameraMoves(); - + currViewPos.z += cameraMoves.z; MainCam.setPos(currViewPos); MainCam.setRotQuat(View.currentViewQuat()); @@ -1435,7 +1435,7 @@ bool mainLoop() } UserEntity->setCameraMoves(CVector(0, 0, 0)); - + if (StereoHMD) { CMatrix camMatrix; @@ -2982,15 +2982,41 @@ CVector PacsBox[PacsBoxPointCount] = CVector( 0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 0), CVector( -0.5f, -0.5f, 0), + CVector( -0.5f, -0.5f, 0), CVector( -0.5f, -0.5f, 1), + CVector( 0.5f, -0.5f, 0), CVector( 0.5f, -0.5f, 1), + CVector( 0.5f, 0.5f, 0), CVector( 0.5f, 0.5f, 1), + CVector( -0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 1), + CVector( -0.5f, -0.5f, 1), CVector( 0.5f, -0.5f, 1), CVector( 0.5f, -0.5f, 1), CVector( 0.5f, 0.5f, 1), CVector( 0.5f, 0.5f, 1), CVector( -0.5f, 0.5f, 1), CVector( -0.5f, 0.5f, 1), CVector( -0.5f, -0.5f, 1), +}; + +const uint PacsStairPointCount = 32; + +CVector PacsStair[PacsStairPointCount] = +{ + CVector( -0.5f, -0.5f, 0), CVector( 0.5f, -0.5f, 0), + CVector( 0.5f, -0.5f, 0), CVector( 0.5f, 0.5f, 0), + CVector( 0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 0), + CVector( -0.5f, 0.5f, 0), CVector( -0.5f, -0.5f, 0), CVector( -0.5f, -0.5f, 0), CVector( -0.5f, -0.5f, 1), CVector( 0.5f, -0.5f, 0), CVector( 0.5f, -0.5f, 1), CVector( 0.5f, 0.5f, 0), CVector( 0.5f, 0.5f, 1), CVector( -0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 1), + + CVector( -0.5f, -0.5f, 1), CVector( 0.5f, -0.5f, 1), + CVector( 0.5f, -0.5f, 1), CVector( 0.5f, 0.5f, 1), + CVector( 0.5f, 0.5f, 1), CVector( -0.5f, 0.5f, 1), + CVector( -0.5f, 0.5f, 1), CVector( -0.5f, -0.5f, 1), + + CVector( -0.5f, -0.5f, 1), CVector( 0.5f, 0.5f, 1), + CVector( -0.5f, 0.5f, 1), CVector( 0.5f, -0.5f, 1), + CVector( -0.5f, 0, 1), CVector( 0.5f, 0, 1), + CVector( 0, - 0.5f, 1), CVector( 0, 0.5f, 1), + }; const uint PacsCylPointCount = 48; @@ -3044,6 +3070,7 @@ void displayPACSPrimitive() // Distance CVector position = prim->getFinalPosition(wI); + bool isStairs = false; if ((position-UserEntity->pos()).sqrnorm() < (200*200)) { // Choose a color @@ -3051,8 +3078,14 @@ void displayPACSPrimitive() if (prim->isCollisionable()) { // Static collision - if (prim->getReactionType() == UMovePrimitive::DoNothing) + if (prim->getTriggerType() == UMovePrimitive::OverlapStairsTrigger) { + line.Color0 = CRGBA::Blue; + isStairs = true; + position.z -= 1.0f; + } + else if (prim->getReactionType() == UMovePrimitive::DoNothing) + { line.Color0 = CRGBA::Red; } else @@ -3082,8 +3115,16 @@ void displayPACSPrimitive() // Draw the primitive if (prim->getPrimitiveType() == UMovePrimitive::_2DOrientedBox) { - lines = PacsBox; - linecount = PacsBoxPointCount/2; + if (isStairs) + { + lines = PacsStair; + linecount = PacsStairPointCount/2; + } + else + { + lines = PacsBox; + linecount = PacsBoxPointCount/2; + } float width; float depth; prim->getSize (width, depth); From f0b74071ad981c1d00a6ea9f1d2d412005454244 Mon Sep 17 00:00:00 2001 From: Nuno Date: Thu, 25 Nov 2021 18:25:41 +0100 Subject: [PATCH 2/3] Npcs and mobs climb in stairs too --- nel/src/pacs/move_container.cpp | 2 +- ryzom/client/src/character_cl.cpp | 16 ++++++++-------- ryzom/client/src/entities.cpp | 8 ++++++-- ryzom/client/src/main_loop.cpp | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/nel/src/pacs/move_container.cpp b/nel/src/pacs/move_container.cpp index 424f7d8b9..4d093ae6a 100644 --- a/nel/src/pacs/move_container.cpp +++ b/nel/src/pacs/move_container.cpp @@ -1676,7 +1676,7 @@ void CMoveContainer::reaction (const CCollisionOTInfo& first) CVectorD first_pos = dynInfo->getFirstPrimitive()->getFinalPosition(dynInfo->getFirstWorldImage()); CVectorD second_pos = dynInfo->getSecondPrimitive()->getFinalPosition(dynInfo->getSecondWorldImage()); nlinfo("P = %f, C = %f, H = %f, D = %f", first_pos.z, second_pos.z, dynInfo->getSecondPrimitive()->getHeight(), second_pos.z-first_pos.z); - dynInfo->getFirstPrimitive()->setZOffset(second_pos.z+dynInfo->getSecondPrimitive()->getHeight()-1.0f); + dynInfo->getFirstPrimitive()->setZOffset(second_pos.z+dynInfo->getSecondPrimitive()->getHeight()-10.0f); } } if (dynInfo->isExit()) diff --git a/ryzom/client/src/character_cl.cpp b/ryzom/client/src/character_cl.cpp index 68f8acfcb..47b1ad4a2 100644 --- a/ryzom/client/src/character_cl.cpp +++ b/ryzom/client/src/character_cl.cpp @@ -426,7 +426,7 @@ void CCharacterCL::computePrimitive() // Initialize the primitive. if (_Sheet) { - initPrimitive(_Sheet->ColRadius*getScale(), _Sheet->ColHeight*getScale(), _Sheet->ColLength, _Sheet->ColWidth, UMovePrimitive::DoNothing, UMovePrimitive::NotATrigger, MaskColNpc, MaskColNone, _Sheet->ClipRadius, _Sheet->ClipHeight); + initPrimitive(_Sheet->ColRadius*getScale(), _Sheet->ColHeight*getScale(), _Sheet->ColLength, _Sheet->ColWidth, UMovePrimitive::DoNothing, (UMovePrimitive::TTrigger)(UMovePrimitive::OverlapTrigger | UMovePrimitive::EnterTrigger), MaskColNpc, MaskColDoor, _Sheet->ClipRadius, _Sheet->ClipHeight); } else { @@ -976,7 +976,7 @@ bool CCharacterCL::build(const CEntitySheet *sheet) // virtual _CustomScalePos *= getScale(); // Create PACS Primitive. - initPrimitive(_Sheet->ColRadius*getScale(), _Sheet->ColHeight*getScale(), _Sheet->ColLength, _Sheet->ColWidth, UMovePrimitive::DoNothing, UMovePrimitive::NotATrigger, MaskColNpc, MaskColNone, _Sheet->ClipRadius, _Sheet->ClipHeight); + initPrimitive(_Sheet->ColRadius*getScale(), _Sheet->ColHeight*getScale(), _Sheet->ColLength, _Sheet->ColWidth, UMovePrimitive::DoNothing, (UMovePrimitive::TTrigger)(UMovePrimitive::OverlapTrigger | UMovePrimitive::EnterTrigger), MaskColNpc, MaskColDoor, _Sheet->ClipRadius, _Sheet->ClipHeight); // Compute the element to be able to snap the entity to the ground. computeCollisionEntity(); @@ -6678,7 +6678,7 @@ ADD_METHOD(void CCharacterCL::updatePos(const TTime ¤tTimeInMs, CEntityCL updatePosCombatFloat(frameTimeRemaining, target); } // Compute the average speed to the destination. - // double spd = + // double spd = computeSpeed(); @@ -8232,14 +8232,14 @@ float CCharacterCL::getSheetScale() const // virtual // getColRadius : // Return the entity collision radius. (return 0.5 if there is any problem). //--------------------------------------------------- -float CCharacterCL::getSheetColRadius() const +float CCharacterCL::getSheetColRadius() const { - if(!_Sheet) + if(!_Sheet) return 0.5f; else return _Sheet->ColRadius; } - + //--------------------------------------------------- // getScale : @@ -8358,7 +8358,7 @@ std::string CCharacterCL::shapeFromItem(const CItemSheet &itemSheet) const sheet = itemSheet.getShape(); return sheet; - + }// shapeFromItem // @@ -9146,7 +9146,7 @@ void CCharacterCL::setAuraFX(uint index, const CAnimationFX *sheet) bi.DelayBeforeStart = 11.5f; _AttachedFXListToStart.push_front(bi); } - else + else { CAttachedFX::TSmartPtr fx = new CAttachedFX; fx->create(*this, bi, CAttachedFX::CTargeterInfo()); diff --git a/ryzom/client/src/entities.cpp b/ryzom/client/src/entities.cpp index a17a49e4f..3a13e0f30 100644 --- a/ryzom/client/src/entities.cpp +++ b/ryzom/client/src/entities.cpp @@ -945,6 +945,8 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const float height = primitive->getHeight(); CVector size = CVector(width, depth, height); + if (primitive->getTriggerType() == UMovePrimitive::OverlapStairsTrigger) + size.z -= 10.0f; float v; if (getRelativeFloatFromString(values[i], v)) { @@ -954,6 +956,8 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { updateVector(param, size, v, false); } + if (primitive->getTriggerType() == UMovePrimitive::OverlapStairsTrigger) + size.z += 10.0f; primitive->setSize(size.x, size.y); primitive->setHeight(size.z); } @@ -1028,12 +1032,12 @@ bool CEntityManager::setupInstance(uint32 idx, const vector &keys, const { bool active; fromString(values[i], active); - primitive->setObstacle(active); + primitive->setObstacle(!active); if (active) { primitive->setReactionType(UMovePrimitive::DoNothing); primitive->setTriggerType(UMovePrimitive::OverlapStairsTrigger); - primitive->setGlobalPosition(instance.getPos()+CVector(0, 0, 0.5f), dynamicWI); + primitive->setGlobalPosition(instance.getPos(), dynamicWI); } else { diff --git a/ryzom/client/src/main_loop.cpp b/ryzom/client/src/main_loop.cpp index bb9a29d4d..7ce8b79fe 100644 --- a/ryzom/client/src/main_loop.cpp +++ b/ryzom/client/src/main_loop.cpp @@ -3080,9 +3080,9 @@ void displayPACSPrimitive() // Static collision if (prim->getTriggerType() == UMovePrimitive::OverlapStairsTrigger) { - line.Color0 = CRGBA::Blue; + line.Color0 = CRGBA::Green; isStairs = true; - position.z -= 1.0f; + position.z -= 10.0f; } else if (prim->getReactionType() == UMovePrimitive::DoNothing) { From 85c80ab0f2bb7ed7fcc20dba668bdcb1c3fb4786 Mon Sep 17 00:00:00 2001 From: Nuno Date: Fri, 26 Nov 2021 19:13:53 +0100 Subject: [PATCH 3/3] Smooth the z displacement of entities --- nel/include/nel/pacs/move_primitive.h | 10 +++-- nel/include/nel/pacs/u_move_primitive.h | 4 +- nel/src/pacs/move_container.cpp | 3 +- ryzom/client/src/entity_cl.cpp | 50 +++++++++++++++++++++++-- ryzom/client/src/entity_cl.h | 8 +++- 5 files changed, 62 insertions(+), 13 deletions(-) diff --git a/nel/include/nel/pacs/move_primitive.h b/nel/include/nel/pacs/move_primitive.h index d77517a7d..928ed10fc 100644 --- a/nel/include/nel/pacs/move_primitive.h +++ b/nel/include/nel/pacs/move_primitive.h @@ -251,16 +251,17 @@ public: _Height=height; } - void setZOffset(float offset) + void setZFinalPosition(float pos) { - _ZOffset = offset; + _ZFinalPosition = pos; } - float getZOffset() + float getZFinalPosition() { - return _ZOffset; + return _ZFinalPosition; } + bool haveZOffset() { return _HaveZOffset; @@ -489,6 +490,7 @@ private: sint32 _IterationCount; float _ZOffset; + float _ZFinalPosition; bool _HaveZOffset; }; diff --git a/nel/include/nel/pacs/u_move_primitive.h b/nel/include/nel/pacs/u_move_primitive.h index e067c3e6b..cba266174 100644 --- a/nel/include/nel/pacs/u_move_primitive.h +++ b/nel/include/nel/pacs/u_move_primitive.h @@ -280,9 +280,9 @@ public: */ virtual float getHeight () const =0; - virtual void setZOffset(float offset) =0; + virtual void setZFinalPosition(float pos) =0; - virtual float getZOffset() =0; + virtual float getZFinalPosition() =0; virtual bool haveZOffset() =0; diff --git a/nel/src/pacs/move_container.cpp b/nel/src/pacs/move_container.cpp index 4d093ae6a..c313fefb9 100644 --- a/nel/src/pacs/move_container.cpp +++ b/nel/src/pacs/move_container.cpp @@ -1675,8 +1675,7 @@ void CMoveContainer::reaction (const CCollisionOTInfo& first) dynInfo->getFirstPrimitive()->enableZOffset(true); CVectorD first_pos = dynInfo->getFirstPrimitive()->getFinalPosition(dynInfo->getFirstWorldImage()); CVectorD second_pos = dynInfo->getSecondPrimitive()->getFinalPosition(dynInfo->getSecondWorldImage()); - nlinfo("P = %f, C = %f, H = %f, D = %f", first_pos.z, second_pos.z, dynInfo->getSecondPrimitive()->getHeight(), second_pos.z-first_pos.z); - dynInfo->getFirstPrimitive()->setZOffset(second_pos.z+dynInfo->getSecondPrimitive()->getHeight()-10.0f); + dynInfo->getFirstPrimitive()->setZFinalPosition(second_pos.z+dynInfo->getSecondPrimitive()->getHeight()-10.0f); } } if (dynInfo->isExit()) diff --git a/ryzom/client/src/entity_cl.cpp b/ryzom/client/src/entity_cl.cpp index c523449a1..616363f0b 100644 --- a/ryzom/client/src/entity_cl.cpp +++ b/ryzom/client/src/entity_cl.cpp @@ -740,6 +740,8 @@ void CEntityCL::init() _EntityName = "Name"; } _NameId = 0; + _LastSnapToGroup = 0; + _CurrentZOffset = 0; _PermanentStatutIcon.clear(); @@ -1481,6 +1483,17 @@ void CEntityCL::pacsMove(const CVectorD &vect) _Primitive->enableZOffset(false); _Primitive->move (deltaPos, dynamicWI); } + else + { + // This code force the player to move even when not moving, it's used to trigger special collissions + if (isUser()) + { + _HasMoved = true; + deltaPos.x = 0.0001; + _Primitive->move (deltaPos, dynamicWI); + } + + } } else { @@ -1714,11 +1727,42 @@ void CEntityCL::snapToGround() pos().z = vect.z; } - if (_Primitive->haveZOffset()) { - //CVectorD prim_pos = _Primitive->getFinalPosition(dynamicWI); - pos().z = _Primitive->getZOffset(); + if (_Primitive->haveZOffset()) + { + + if (_LastSnapToGroup > 0) + { + if (pos().z + _CurrentZOffset < _Primitive->getZFinalPosition()) + { + _CurrentZOffset += (ryzomGetLocalTime() - _LastSnapToGroup)/100.0f; + + if (pos().z + _CurrentZOffset > _Primitive->getZFinalPosition()) + _CurrentZOffset = _Primitive->getZFinalPosition() - pos().z; + } + + if (pos().z + _CurrentZOffset > _Primitive->getZFinalPosition()) + { + _CurrentZOffset -= (ryzomGetLocalTime() - _LastSnapToGroup)/100.0f; + + if (pos().z + _CurrentZOffset < _Primitive->getZFinalPosition()) + _CurrentZOffset = _Primitive->getZFinalPosition() - pos().z; + } + + pos().z += _CurrentZOffset; + } } + else + { + if (_CurrentZOffset > 0) + { + _CurrentZOffset -= (ryzomGetLocalTime() - _LastSnapToGroup)/100.0f; + if (_CurrentZOffset < 0) + _CurrentZOffset = 0; + pos().z += _CurrentZOffset; + } + } + _LastSnapToGroup = ryzomGetLocalTime(); // Set the box position. posBox(pos()); diff --git a/ryzom/client/src/entity_cl.h b/ryzom/client/src/entity_cl.h index f2f99b347..092a85dd3 100644 --- a/ryzom/client/src/entity_cl.h +++ b/ryzom/client/src/entity_cl.h @@ -241,7 +241,7 @@ public: /// Return the persistent NPC alias of entity (0 if N/A). uint32 npcAlias() const {return _NPCAlias; } - /// Set the persistent NPC alias of the entity. + /// Set the persistent NPC alias of the entity. void npcAlias(uint32 alias) {_NPCAlias = alias; } /// Method to call to initialize all members of the right class. @@ -702,7 +702,7 @@ public: // todo handle NPC entities // Return true if this entity is a NPC (not a fauna) bool isNPC () const { return Type == NPC; } - + // Return true if this entity can have missions icons (humanoid NPCs (including Karavan), Kami or Bot Object) bool canHaveMissionIcon() const { return isNPC() || isKami() || isUnknownRace(); } @@ -949,6 +949,10 @@ protected: uint32 _NameId; // Primitive used for the collision in PACS NLPACS::UMovePrimitive *_Primitive; + + uint64 _LastSnapToGroup; + float _CurrentZOffset; + // 3D Logic info for light request. CEntityLogicInfo3D _LogicInfo3D; // Box around the entity.