void CScriptSurfaceTypesLoader::UnloadSurfaceTypes() { ISurfaceTypeManager *pSurfaceManager = NULL; I3DEngine *pEngine = gEnv->p3DEngine; if (pEngine) { pSurfaceManager = pEngine->GetMaterialManager()->GetSurfaceTypeManager(); } for (unsigned int i = 0; i < m_surfaceTypes.size(); i++) { if (pSurfaceManager) pSurfaceManager->UnregisterSurfaceType(m_surfaceTypes[i]); m_surfaceTypes[i]->Release(); } m_surfaceTypes.clear(); }
//------------------------------------------------------------------------ void CMelee::Impulse(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, int partId, int ipart, int surfaceIdx, float impulseScale) { if(m_noImpulse) { m_noImpulse = false; return; } if (pCollider && m_pShared->meleeparams.impulse > 0.001f) { bool strengthMode = false; CPlayer *pPlayer = (CPlayer *)m_pWeapon->GetOwnerActor(); pe_status_dynamics dyn; if (!pCollider->GetStatus(&dyn)) { if(strengthMode) { impulseScale *= 3.0f; } } else { impulseScale *= clamp((dyn.mass * 0.01f), 1.0f, 15.0f); } //[kirill] add impulse to phys proxy - to make sure it's applied to cylinder as well (not only skeleton) - so that entity gets pushed // if no pEntity - do it old way IEntity *pEntity = (IEntity *) pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY); if(gEnv->bMultiplayer && pEntity) { if(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()) == NULL) { impulseScale *= 0.33f; } } if(pEntity) { bool crapDollFilter = false; #ifdef CRAPDOLLS static IEntityClass *pDeadBodyClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DeadBody"); if (pEntity->GetClass() == pDeadBodyClass) { crapDollFilter = true; } #endif //CRAPDOLLS if (!crapDollFilter) { IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy *)pEntity->GetProxy(ENTITY_PROXY_PHYSICS); CActor *pActor = (CActor *)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()); if (pActor) { SActorStats *pAS = pActor->GetActorStats(); if (pAS && pAS->isRagDoll) { //marcok: talk to me before touching this impulseScale = 1.0f; //jan: melee impulses were scaled down, I made sure it still "barely moves" #ifdef CRAPDOLLS crapDollFilter = true; #endif //CRAPDOLLS } } // scale impulse up a bit for player if (!crapDollFilter) { pPhysicsProxy->AddImpulse(partId, pt, dir * m_pShared->meleeparams.impulse * impulseScale * m_meleeScale, true, 1.f); } } } else { pe_action_impulse ai; ai.partid = partId; ai.ipart = ipart; ai.point = pt; ai.iApplyTime = 0; ai.impulse = dir * (m_pShared->meleeparams.impulse * impulseScale * m_meleeScale); pCollider->Action(&ai); } ISurfaceTypeManager *pSurfaceTypeManager = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); int invId = pSurfaceTypeManager->GetSurfaceTypeByName("mat_invulnerable")->GetId(); // create a physical collision to break trees pe_action_register_coll_event collision; collision.collMass = 0.005f; // this is actually ignored collision.partid[1] = partId; // collisions involving partId<-1 are to be ignored by game's damage calculations // usually created articially to make stuff break. collision.partid[0] = -2; collision.idmat[1] = surfaceIdx; collision.idmat[0] = invId; collision.n = normal; collision.pt = pt; // scar bullet // m = 0.0125 // v = 800 // energy: 4000 // in this case the mass of the active collider is a player part // so we must solve for v given the same energy as a scar bullet Vec3 v = dir; float speed = cry_sqrtf(4000.0f / (80.0f * 0.5f)); // 80.0f is the mass of the player // [marco] Check if an object. Should take lots of time to break stuff if not in nanosuit strength mode; // and still creates a very low impulse for stuff that might depend on receiving an impulse. IRenderNode *pBrush = (IRenderNode *)pCollider->GetForeignData(PHYS_FOREIGN_ID_STATIC); collision.vSelf = (v.normalized() * speed * m_meleeScale); collision.v = Vec3(0, 0, 0); collision.pCollider = pCollider; IEntity *pOwner = m_pWeapon->GetOwner(); if (pOwner && pOwner->GetCharacter(0) && pOwner->GetCharacter(0)->GetISkeletonPose()->GetCharacterPhysics()) { if (ISkeletonPose *pSkeletonPose = pOwner->GetCharacter(0)->GetISkeletonPose()) { if (pSkeletonPose && pSkeletonPose->GetCharacterPhysics()) { pSkeletonPose->GetCharacterPhysics()->Action(&collision); } } } } }
//------------------------------------------------------------------------ void CVehiclePartAnimated::SetDrivingProxy(bool bDrive) { IVehicleMovement* pMovement = m_pVehicle->GetMovement(); if (!(pMovement && pMovement->UseDrivingProxy())) return; if (0 == m_hullMatId[bDrive]) // 0 means, nothin to do return; if (!m_pCharInstance) return; ISkeletonPose* pSkeletonPose = m_pCharInstance->GetISkeletonPose(); if (!pSkeletonPose) return; IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton(); IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics(); if (!pPhysics) return; int id = rIDefaultSkeleton.GetJointIDByName("hull_proxy"); if (id < 0) { m_hullMatId[0] = m_hullMatId[1] = 0; return; } int partid = pSkeletonPose->GetPhysIdOnJoint(id); if (partid == -1) return; pe_params_part params; params.partid = partid; params.ipart = -1; if (!pPhysics->GetParams(¶ms) || !params.nMats) return; phys_geometry* pGeom = params.pPhysGeom; if (pGeom && pGeom->surface_idx < pGeom->nMats) { ISurfaceTypeManager* pSurfaceMan = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); // initialize once if (m_hullMatId[0] < 0) { int idDriving = 0; int idOrig = pGeom->pMatMapping[pGeom->surface_idx]; const char* matOrig = pSurfaceMan->GetSurfaceType(idOrig)->GetName(); if (strstr(matOrig, "mat_metal")) idDriving = pSurfaceMan->GetSurfaceTypeByName("mat_metal_nofric")->GetId(); else { string mat(matOrig); mat.append("_nofric"); idDriving = pSurfaceMan->GetSurfaceTypeByName(mat.c_str(), NULL, false)->GetId(); } //if (pDebug->GetIVal()) //CryLog("%s looking up driving surface replacement for %s (id %i) -> got id %i", m_pVehicle->GetEntity()->GetName(), matOrig, idOrig, idDriving); if (idDriving > 0) { // store old and new id m_hullMatId[0] = idOrig; m_hullMatId[1] = idDriving; /*if (pDebug->GetIVal()) { const char* matDriving = pSurfaceMan->GetSurfaceType(idDriving)->GetName(); CryLog("%s storing hull matId for swapping: %i (%s) -> %i (%s)", m_pVehicle->GetEntity()->GetName(), m_hullMatId[0], matOrig, m_hullMatId[1], matDriving); }*/ } else m_hullMatId[0] = m_hullMatId[1] = 0; } // only swap if materials available if (m_hullMatId[bDrive] > 0) { #if ENABLE_VEHICLE_DEBUG if (VehicleCVars().v_debugdraw == eVDB_Parts) CryLog("%s swapping hull proxy from %i (%s) to matId %i (%s)", m_pVehicle->GetEntity()->GetName(), m_hullMatId[bDrive ^ 1], pSurfaceMan->GetSurfaceType(m_hullMatId[bDrive ^ 1])->GetName(), m_hullMatId[bDrive], pSurfaceMan->GetSurfaceType(m_hullMatId[bDrive])->GetName()); #endif for (int n = 0; n < pGeom->nMats; ++n) { pGeom->pMatMapping[n] = m_hullMatId[bDrive]; } } } }
//-------------------------------------------------------------------------------------------------- // Name: BreakGlassObject // Desc: Replaces a physical StatObj with a glass node where supported // Note: We're currently duplicating some work done in CryAction, so should be reading that in. // Similarly, we should also be accepting the SProcessImpactIn struct instead of the event //-------------------------------------------------------------------------------------------------- bool CBreakableGlassSystem::BreakGlassObject(const EventPhysCollision& physEvent, const bool forceGlassBreak) { bool bSuccess = false; SBreakableGlassInitParams initParams; // Get surface type's breaking effect ISurfaceTypeManager* pSurfaceTypeManager = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); initParams.surfaceTypeId = physEvent.idmat[PHYSEVENT_COLLIDEE]; if (ISurfaceType* pMat = pSurfaceTypeManager->GetSurfaceType(initParams.surfaceTypeId)) { if (ISurfaceType::SBreakable2DParams* pBreakableParams = pMat->GetBreakable2DParams()) { initParams.pShatterEffect = pBreakableParams->full_fracture_fx ? gEnv->pParticleManager->FindEffect(pBreakableParams->full_fracture_fx) : NULL; } } // Calculate glass data SBreakableGlassPhysData physData; if (ExtractPhysDataFromEvent(physEvent, physData, initParams) && ValidateExtractedOutline(physData, initParams)) { Vec3 size; Matrix34 transMat; CalculateGlassBounds(physData.pPhysGeom, size, transMat); // Update initialisation parameters if (!physData.defaultFrag.empty()) { initParams.pInitialFrag = physData.defaultFrag.begin(); initParams.numInitialFragPts = physData.defaultFrag.size(); } else { initParams.pInitialFrag = NULL; initParams.numInitialFragPts = 0; } initParams.size.set(size.x, size.y); initParams.thickness = size.z; // Fix-up mesh and calculate anchors CalculateGlassAnchors(physData, initParams); // Calculate UV coords at axis-aligned points Vec2 origin = InterpolateUVCoords(physData.uvBasis[0], physData.uvBasis[1], physData.uvBasis[2], Vec2Constants<f32>::fVec2_Zero); Vec2 xAxisPt = InterpolateUVCoords(physData.uvBasis[0], physData.uvBasis[1], physData.uvBasis[2], Vec2Constants<f32>::fVec2_OneX); Vec2 yAxisPt = InterpolateUVCoords(physData.uvBasis[0], physData.uvBasis[1], physData.uvBasis[2], Vec2Constants<f32>::fVec2_OneY); // Convert the UV basis to X and Y axes w/ an offset initParams.uvOrigin = origin; initParams.uvXAxis = xAxisPt - origin; initParams.uvYAxis = yAxisPt - origin; // Create a replacement glass node IBreakableGlassRenderNode* pRenderNode = InitGlassNode(physData, initParams, transMat); // Duplicate the collision event and patch it up for the new node EventPhysCollision dupeEvent = physEvent; dupeEvent.pEntity[PHYSEVENT_COLLIDEE] = pRenderNode->GetPhysics(); dupeEvent.pForeignData[PHYSEVENT_COLLIDEE] = (void*)pRenderNode; dupeEvent.iForeignData[PHYSEVENT_COLLIDEE] = PHYS_FOREIGN_ID_BREAKABLE_GLASS; pe_params_part partParams; if (dupeEvent.pEntity[PHYSEVENT_COLLIDEE]->GetParams(&partParams) && partParams.nMats > 0) { dupeEvent.idmat[PHYSEVENT_COLLIDEE] = partParams.pMatMapping[0]; } if (forceGlassBreak) { ModifyEventToForceBreak(&dupeEvent); } // Send it directly to the new node PassImpactToNode(pRenderNode, &dupeEvent); bSuccess = true; } return bSuccess; }//-------------------------------------------------------------------------------------------------
bool CScriptSurfaceTypesLoader::LoadSurfaceTypes( const char *sFolder,bool bReload ) { { if (!gEnv->p3DEngine) return false; I3DEngine *pEngine = gEnv->p3DEngine; ISurfaceTypeEnumerator *pEnum = pEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetEnumerator(); if (pEnum) { for (ISurfaceType *pSurfaceType = pEnum->GetFirst(); pSurfaceType; pSurfaceType = pEnum->GetNext()) { SmartScriptTable mtlTable(gEnv->pScriptSystem); gEnv->pScriptSystem->SetGlobalValue( pSurfaceType->GetName(),mtlTable ); SmartScriptTable aiTable(gEnv->pScriptSystem); mtlTable->SetValue("AI",aiTable); aiTable->SetValue( "fImpactRadius",5.0f ); aiTable->SetValue( "fFootStepRadius",15.0f ); aiTable->SetValue( "proneMult",0.2f ); aiTable->SetValue( "crouchMult",0.5f ); aiTable->SetValue( "movingMult",2.5f ); } pEnum->Release(); } } return true; // Do not load surface types from script anymore. m_root = GetISystem()->CreateXmlNode("SurfaceTypes"); IScriptSystem *pScriptSystem = gEnv->pScriptSystem; ////////////////////////////////////////////////////////////////////////// // Make sure Materials table exist. ////////////////////////////////////////////////////////////////////////// SmartScriptTable mtlTable; if (!pScriptSystem->GetGlobalValue("Materials", mtlTable) || bReload) { mtlTable = pScriptSystem->CreateTable(); pScriptSystem->SetGlobalValue("Materials", mtlTable); } ICryPak *pIPak = gEnv->pCryPak; ISurfaceTypeManager *pSurfaceManager = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); if (!bReload) stl::push_back_unique( m_folders,sFolder ); string searchFolder = string(sFolder) + "/";; string searchFilter = searchFolder + "mat_*.lua"; gEnv->pScriptSystem->ExecuteFile(searchFolder+"common.lua", false, bReload); _finddata_t fd; intptr_t fhandle; fhandle = pIPak->FindFirst( searchFilter,&fd ); if (fhandle != -1) { do { // Skip back folders. if (fd.attrib & _A_SUBDIR) // skip if directory. continue; char name[_MAX_PATH]; _splitpath( fd.name,NULL,NULL,name,NULL ); if (strlen(name) == 0) continue; if (bReload) { ISurfaceType *pSurfaceType = pSurfaceManager->GetSurfaceTypeByName(name); if (pSurfaceType) { pSurfaceType->Load( pSurfaceType->GetId() ); continue; } } ISurfaceType *pSurfaceType = new CScriptSurfaceType( this,name,searchFolder+fd.name,0 ); if (pSurfaceManager->RegisterSurfaceType( pSurfaceType )) m_surfaceTypes.push_back(pSurfaceType); else pSurfaceType->Release(); } while (pIPak->FindNext( fhandle,&fd ) == 0); pIPak->FindClose(fhandle); } if (m_root) { m_root->saveToFile( "SurfaceTypes.xml" ); } return true; }