@@ -552,6 +552,103 @@ void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int i
552552 Vector vecOrigin, vecForward, vecRight, vecUp;
553553
554554 float flOffset = 0 .0f ;
555+ #ifdef BDSBASE
556+ bool bUsingUnusual = false ;
557+
558+ #ifdef TF_CLIENT_DLL
559+
560+ CBaseEntity* pWearable = (CBaseEntity*)pPoint->hEntity .Get ();
561+ if (pWearable && GetAttribInterface (pWearable) && !pWearable->IsPlayer () && V_strcmp (pWearable->GetClassname (), " tf_wearable" ) == 0 )
562+ {
563+ C_BaseAnimating* pAnimating = pPoint->hEntity ->GetBaseAnimating ();
564+ if (pAnimating)
565+ {
566+ // Do not use this now. It asks players to use particle from head attachment.
567+ // But unusual particles for wearables are made for head attachment already.
568+ // CALL_ATTRIB_HOOK_INT_ON_OTHER( pAnimating, bUseHeadOrigin, particle_effect_use_head_origin );
569+
570+ // Reference from bone_merge_cache
571+ CUtlVector<CUtlString> BoneNames;
572+ CUtlVector<unsigned short > ParentBones;
573+
574+ int nFollowBoneSetupMask = 0 ;
575+ CStudioHdr* pWearableHdr = pAnimating->GetModelPtr ();
576+ C_BaseAnimating* pFollow = pAnimating->FindFollowedEntity ();
577+ CStudioHdr* pFollowHdr = (pFollow ? pFollow->GetModelPtr () : NULL );
578+
579+ bool bIsUnusual = false ;
580+ bool bIsUnusualStatic = false ;
581+ CALL_ATTRIB_HOOK_INT_ON_OTHER (pAnimating, bIsUnusual, set_attached_particle);
582+ CALL_ATTRIB_HOOK_INT_ON_OTHER (pAnimating, bIsUnusualStatic, set_attached_particle_static);
583+ if (pWearableHdr && pFollowHdr && (bIsUnusual || bIsUnusualStatic))
584+ {
585+ CUtlVector<unsigned char > BoneMergeBits; // One bit for each bone. The bit is set if the bone gets merged.
586+ BoneMergeBits.SetSize (pWearableHdr->numbones () / 8 + 1 );
587+ memset (BoneMergeBits.Base (), 0 , BoneMergeBits.Count ());
588+
589+ mstudiobone_t * pWearableBones = pWearableHdr->pBone (0 );
590+
591+ nFollowBoneSetupMask = BONE_USED_BY_BONE_MERGE;
592+ for (int i = 0 ; i < pWearableHdr->numbones (); i++)
593+ {
594+ const CUtlString sBoneName = pWearableBones[i].pszName ();
595+ const int parentBoneIndex = Studio_BoneIndexByName (pFollowHdr, sBoneName );
596+ if (parentBoneIndex < 0 )
597+ continue ;
598+
599+ BoneNames.AddToTail (sBoneName );
600+ ParentBones.AddToTail (parentBoneIndex);
601+
602+ BoneMergeBits[i >> 3 ] |= (1 << (i & 7 ));
603+
604+ if ((pFollowHdr->boneFlags (parentBoneIndex) & BONE_USED_BY_BONE_MERGE) == 0 )
605+ {
606+ nFollowBoneSetupMask = BONE_USED_BY_ANYTHING;
607+ }
608+ }
609+
610+ if (!ParentBones.Count ())
611+ {
612+ nFollowBoneSetupMask = 0 ;
613+ }
614+ }
615+ else
616+ {
617+ nFollowBoneSetupMask = 0 ;
618+ }
619+
620+ if (pWearableHdr && BoneNames.Count ())
621+ {
622+ pFollow->SetupBones (NULL , -1 , nFollowBoneSetupMask, gpGlobals->curtime );
623+ const char * const pPriorityBones[] = { " bip_head" , " prp_helmet" , " prp_hat" };
624+ int iBone = -1 ;
625+ bool bFound = false ;
626+ for (int j = 0 ; j < ARRAYSIZE (pPriorityBones) && !bFound; j++)
627+ {
628+ for (int i = 0 ; i < BoneNames.Count (); i++)
629+ {
630+ if (BoneNames[i] == pPriorityBones[j])
631+ {
632+ iBone = i;
633+ bFound = true ;
634+ break ;
635+ }
636+ }
637+ }
638+
639+ bUsingUnusual = true ;
640+ const matrix3x4_t rootBone = iBone >= 0 ? pFollow->GetBone (ParentBones[iBone]) : pFollow->GetBone (ParentBones[0 ]);
641+ MatrixVectors (rootBone, &vecForward, &vecRight, &vecUp);
642+ MatrixPosition (rootBone, vecOrigin);
643+
644+ CALL_ATTRIB_HOOK_FLOAT_ON_OTHER (pAnimating, flOffset, particle_effect_vertical_offset);
645+ }
646+ }
647+ }
648+ #endif
649+
650+ if (!bUsingUnusual)
651+ #else
555652 bool bUsingHeadOrigin = false ;
556653
557654#ifdef TF_CLIENT_DLL
@@ -592,6 +689,7 @@ void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int i
592689#endif
593690
594691 if ( !bUsingHeadOrigin )
692+ #endif
595693 {
596694 switch ( pPoint->iAttachType )
597695 {
0 commit comments