//======================================================================= void CWeaponAttachmentManager::CreatePlayerProjectedAttachments() { Vec3 c4FrontPos(-0.0105f,0.2233f,1.297f),c4BackPos(0.00281f,-0.2493f,1.325f); Quat c4FrontRot(-0.0368f,-0.0278f,0.0783f,-0.9958f),c4BackRot(1,0,0,0); //Creates on init c4 face attachments if (ICharacterInstance* pCharInstance = m_pOwner->GetEntity()->GetCharacter(0)) { IAttachmentManager* pAttachmentManager = pCharInstance->GetIAttachmentManager(); IAttachment *pAttachment = NULL; pAttachment = pAttachmentManager->GetInterfaceByName("c4_front"); if(!pAttachment) { //Attachment doesn't exist, create it pAttachment= pAttachmentManager->CreateAttachment("c4_front",CA_FACE,0); if(pAttachment) { pAttachment->SetAttAbsoluteDefault( QuatT(c4FrontRot,c4FrontPos) ); pAttachment->ProjectAttachment(); } } pAttachment = NULL; pAttachment = pAttachmentManager->GetInterfaceByName("c4_back"); if(!pAttachment) { //Attachment doesn't exist, create it pAttachment= pAttachmentManager->CreateAttachment("c4_back",CA_FACE,0); if(pAttachment) { pAttachment->SetAttAbsoluteDefault( QuatT(c4BackRot,c4BackPos) ); pAttachment->ProjectAttachment(); } } } }
//====================================================================== void CWeaponAttachmentManager::CreatePlayerBoneAttachments() { if (ICharacterInstance* pCharInstance = m_pOwner->GetEntity()->GetCharacter(0)) { IAttachmentManager* pAttachmentManager = pCharInstance->GetIAttachmentManager(); IAttachment *pAttachment = NULL; for(int i=0; i<MAX_WEAPON_ATTACHMENTS; i++) { pAttachment = pAttachmentManager->GetInterfaceByName(gAttachmentTable[i]); if(!pAttachment) { //Attachment doesn't exist, create it pAttachment = pAttachmentManager->CreateAttachment(gAttachmentTable[i],CA_BONE,gBoneTable[i]); if(pAttachment) { m_boneAttachmentMap.insert(TBoneAttachmentMap::value_type(gAttachmentTable[i],0)); if(pAttachment && !gOffsetTable[i].IsZero()) { pAttachment->SetAttAbsoluteDefault( QuatT(gRotationTable[i],gOffsetTable[i]) ); pAttachment->ProjectAttachment(); } } } } } }
//------------------------------------------------------------------------ bool CItem::CreateCharacterAttachment(int slot, const char *name, int type, const char *bone) { ICharacterInstance *pCharacter = GetEntity()->GetCharacter(slot); if(!pCharacter) return false; IAttachmentManager *pAttachmentManager = pCharacter->GetIAttachmentManager(); IAttachment *pAttachment = pAttachmentManager->GetInterfaceByName(name); if(pAttachment) { // GameWarning("Item '%s' trying to create attachment '%s' which already exists!", GetEntity()->GetName(), name); return false; } pAttachment = pAttachmentManager->CreateAttachment(name, type, bone); if(!pAttachment) { if(type == CA_BONE) GameWarning("Item '%s' failed to create attachment '%s' on bone '%s'!", GetEntity()->GetName(), name, bone); return false; } return true; }
bool CMFXParticleEffect::AttachToCharacter( IEntity& targetEntity, const SMFXParticleEntry& particleParams, const SMFXRunTimeEffectParams& params, const Vec3& dir, float scale ) { if (params.partID >= 0) { //Assume character is loaded in first slot //We could iterate through all available slots, but first one should be good enough ICharacterInstance* pCharacterInstace = targetEntity.GetCharacter(0); ISkeletonPose* pSkeletonPose = pCharacterInstace ? pCharacterInstace->GetISkeletonPose() : NULL; if (pSkeletonPose) { IDefaultSkeleton& rIDefaultSkeleton = pCharacterInstace->GetIDefaultSkeleton(); //It hit the character, but probably in a physicalized attached part, like armor plates, etc if (params.partID >= rIDefaultSkeleton.GetJointCount()) { return false; } //It hit some valid joint, create an attachment const char* boneName = rIDefaultSkeleton.GetJointNameByID(params.partID); TAttachmentName attachmentName; GetNextCharacterAttachmentName(attachmentName); IAttachmentManager* pAttachmentManager = pCharacterInstace->GetIAttachmentManager(); CRY_ASSERT(pAttachmentManager); //Remove the attachment first (in case was created before) pAttachmentManager->RemoveAttachmentByName(attachmentName.c_str()); //Create attachment on nearest hit bone IAttachment* pAttachment = pAttachmentManager->CreateAttachment(attachmentName.c_str(), CA_BONE, boneName, false); if (pAttachment) { //Apply relative offsets const QuatT boneLocation = pSkeletonPose->GetAbsJointByID(params.partID); Matrix34 inverseJointTM = targetEntity.GetWorldTM() * Matrix34(boneLocation); inverseJointTM.Invert(); Vec3 attachmentOffsetPosition = inverseJointTM * params.pos; Quat attachmentOffsetRotation = Quat(inverseJointTM) * targetEntity.GetRotation(); CRY_ASSERT(attachmentOffsetPosition.IsValid()); //CRY_ASSERT(attachmentOffsetRotation.IsUnit()); pAttachment->SetAttRelativeDefault(QuatT(attachmentOffsetRotation, attachmentOffsetPosition)); //Finally attach the effect CEffectAttachment* pEffectAttachment = new CEffectAttachment(particleParams.name.c_str(), Vec3(0,0,0), dir, scale); pAttachment->AddBinding(pEffectAttachment); return true; } } } return false; }
void CLaserBeam::FixAttachment(IEntity* pLaserEntity) { m_usingEntityAttachment = false; IItemSystem* pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem(); CItem* pOwnerItem = static_cast<CItem*>(pItemSystem->GetItem(m_ownerEntityId)); if (pOwnerItem) { IEntity* pOwnerEntity = pOwnerItem->GetEntity(); IEntity* pAttachedEntity = pOwnerEntity; const char* attach_helper = "laser_term"; Vec3 offset = pOwnerItem->GetSlotHelperPos(m_geometrySlot, attach_helper, false); if(m_geometrySlot == eIGS_FirstPerson) { if(pOwnerItem->IsAccessory()) { EntityId parentId = pOwnerItem->GetParentId(); if(parentId) { if(CItem* pParentItem = static_cast<CItem*>(pItemSystem->GetItem(parentId))) { const SAccessoryParams* pParams = pParentItem->GetAccessoryParams(pAttachedEntity->GetClass()); attach_helper = pParams->attach_helper.c_str(); pAttachedEntity = pParentItem->GetEntity(); } } } if(pAttachedEntity) { ICharacterInstance *pCharacter = pAttachedEntity->GetCharacter(eIGS_FirstPerson); if (pCharacter) { IAttachmentManager *pAttachmentManager = pCharacter->GetIAttachmentManager(); IAttachment *pLaserAttachment = pAttachmentManager->GetInterfaceByName(LASER_ATTACH_NAME); if(!pLaserAttachment) { IAttachment *pAttachment = pAttachmentManager->GetInterfaceByName(attach_helper); if(pAttachment) { const char* pBone = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton()->GetJointNameByID(pAttachment->GetJointID()); pLaserAttachment = pAttachmentManager->CreateAttachment(LASER_ATTACH_NAME, CA_BONE, pBone); if(pLaserAttachment) { QuatT relative = pAttachment->GetAttRelativeDefault(); if(pOwnerItem->GetEntity() != pAttachedEntity) { Matrix34 mtx(relative); relative.t = relative * offset; } pLaserAttachment->SetAttRelativeDefault(relative); } } } if(pLaserAttachment) { CEntityAttachment* pEntAttach = new CEntityAttachment; pEntAttach->SetEntityId(m_laserEntityId); pLaserAttachment->AddBinding(pEntAttach); pLaserAttachment->HideAttachment(0); m_usingEntityAttachment = true; } } } } if(!m_usingEntityAttachment && pOwnerEntity) { pOwnerEntity->AttachChild(pLaserEntity); pLaserEntity->SetLocalTM(Matrix34::CreateTranslationMat(offset)); } } }
//====================================================================== void CWeaponAttachmentManager::CreatePlayerBoneAttachments() { if (ICharacterInstance *pCharInstance = m_pOwner->GetEntity()->GetCharacter(0)) { IAttachmentManager *pAttachmentManager = pCharInstance->GetIAttachmentManager(); if(pAttachmentManager == NULL) { return; } const XmlNodeRef rootNode = gEnv->pSystem->LoadXmlFromFile( WEAPON_ATTACHMENTS_FILE ); if (!rootNode || strcmpi(rootNode->getTag(), "WeaponAttachments")) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Could not load Weapon Attachments data. Invalid XML file '%s'! ", WEAPON_ATTACHMENTS_FILE); return; } IAttachment *pAttachment = NULL; const int childCount = rootNode->getChildCount(); for (int i = 0; i < childCount; ++i) { XmlNodeRef weaponAttachmentNode = rootNode->getChild(i); if(weaponAttachmentNode == (IXmlNode *)NULL) { continue; } const char *attachmentName = ""; weaponAttachmentNode->getAttr("name", &attachmentName); if(!strcmp(attachmentName, "")) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Empty Weapon Attachment name in file: %s! Skipping Weapon Attachment.", WEAPON_ATTACHMENTS_FILE); continue; } pAttachment = pAttachmentManager->GetInterfaceByName(attachmentName); if(pAttachment) { continue; } //Attachment doesn't exist, create it const int weaponAttachmentCount = weaponAttachmentNode->getChildCount(); const char *boneName = ""; Vec3 attachmentOffset(ZERO); Ang3 attachmentRotation(ZERO); for (int a = 0; a < weaponAttachmentCount; ++a) { const XmlNodeRef childNode = weaponAttachmentNode->getChild(a); if(childNode == (IXmlNode *)NULL) { continue; } if(!strcmp(childNode->getTag(), "Bone")) { childNode->getAttr("name", &boneName); } else if(!strcmp(childNode->getTag(), "Offset")) { childNode->getAttr("x", attachmentOffset.x); childNode->getAttr("y", attachmentOffset.y); childNode->getAttr("z", attachmentOffset.z); } else if(!strcmp(childNode->getTag(), "Rotation")) { float value = 0.0f; childNode->getAttr("x", value); attachmentRotation.x = DEG2RAD(value); childNode->getAttr("y", value); attachmentRotation.y = DEG2RAD(value); childNode->getAttr("z", value); attachmentRotation.z = DEG2RAD(value); } } const char *attachmentType = ""; weaponAttachmentNode->getAttr("type", &attachmentType); if(!strcmp(attachmentType, "")) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "No Weapon Attachment type assigned! Skipping Weapon Attachment: %s", attachmentName); continue; } const bool isBoneAttachment = !strcmp(attachmentType, "Bone"); const bool isFaceAttachment = !strcmp(attachmentType, "Face"); //Bone attachment needs the bone name if (!strcmp(boneName, "") && isBoneAttachment) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Bone Attachment with no bone name assigned! Skipping Weapon Attachment: %s", attachmentName); continue; } if(isBoneAttachment) { pAttachment = pAttachmentManager->CreateAttachment(attachmentName, CA_BONE, boneName); } else if(isFaceAttachment) { pAttachment = pAttachmentManager->CreateAttachment(attachmentName, CA_FACE, 0); } if(pAttachment) { if(isBoneAttachment) { m_boneAttachmentMap.insert(TBoneAttachmentMap::value_type(attachmentName, 0)); } if(pAttachment && !attachmentOffset.IsZero()) { QuatT attachmentQuat(IDENTITY); attachmentQuat.SetRotationXYZ(attachmentRotation, attachmentOffset); pAttachment->SetAttAbsoluteDefault( attachmentQuat ); pAttachment->ProjectAttachment(); } } } } }
//------------------------------------------------------------------------ EntityEffects::TAttachedEffectId CItem::AttachEffect(int slot, bool attachToAccessory, const char *effectName, const char *helper, const Vec3 &offset, const Vec3 &dir, float scale, bool prime) { if(!g_pGameCVars->i_particleeffects) { return 0; } Vec3 finalOffset(offset); string helperName(helper); if(attachToAccessory) { SEntitySlotInfo slotInfo; QuatT accessoryOffset; accessoryOffset.SetIdentity(); const char* accessoryHelper = ""; const char* accessoryName = NULL; const int numAccessories = m_accessories.size(); for (int curIndex = 0; curIndex < numAccessories; curIndex++) { IEntity* pAccessory = gEnv->pEntitySystem->GetEntity(m_accessories[curIndex].accessoryId); if(pAccessory && pAccessory->GetSlotInfo(slot, slotInfo)) { if(slotInfo.pStatObj) { accessoryOffset.t = slotInfo.pStatObj->GetHelperPos(helper); if(!accessoryOffset.t.IsZero()) { accessoryOffset.q = pAccessory->GetRotation(); accessoryOffset.t += pAccessory->GetPos(); accessoryName = m_accessories[curIndex].pClass->GetName(); break; } } if(slotInfo.pCharacter) { IAttachmentManager *pAttachmentManager = slotInfo.pCharacter->GetIAttachmentManager(); IAttachment *pAttachment = pAttachmentManager->GetInterfaceByName(helper); if(pAttachment) { accessoryHelper = GetAccessoryParams(m_accessories[curIndex].pClass)->attach_helper.c_str(); accessoryName = m_accessories[curIndex].pClass->GetName(); accessoryOffset = pAttachment->GetAttAbsoluteDefault(); break; } } } } if(accessoryName) { bool validSlot = GetEntity()->GetSlotInfo(slot, slotInfo) && (slotInfo.pCharacter || slotInfo.pStatObj); if (!validSlot || slotInfo.pStatObj) { if (validSlot) { Matrix34 mtx = GetEntity()->GetSlotLocalTM(slot, false) * Matrix34(accessoryOffset); finalOffset += mtx.GetTranslation(); } EntityEffects::SEffectAttachParams attachParams(finalOffset, dir, scale, prime, eIGS_Last); return m_effectsController.AttachParticleEffect(effectName, attachParams); } else if (slotInfo.pCharacter) // bone attachment { ICharacterInstance *pCharacter = slotInfo.pCharacter; IAttachmentManager *pAttachmentManager = pCharacter->GetIAttachmentManager(); IAttachment *pAttachment = NULL; helperName = string().Format("%s_%s", helper, accessoryName); pAttachment = pAttachmentManager->GetInterfaceByName(helperName.c_str()); if(!pAttachment) { IAttachment* pAccessoryAttachment = pAttachmentManager->GetInterfaceByName(accessoryHelper); if(pAccessoryAttachment) { const char* bone = pCharacter->GetIDefaultSkeleton().GetJointNameByID(pAccessoryAttachment->GetJointID()); pAttachment = pAttachmentManager->CreateAttachment(helperName.c_str(), CA_BONE, bone); if (pAttachment) { QuatT relative = pAccessoryAttachment->GetAttRelativeDefault(); relative = relative * accessoryOffset; relative.t = relative * finalOffset; finalOffset.zero(); pAttachment->SetAttRelativeDefault(relative); } } } } } } EntityEffects::SEffectAttachParams attachParams(finalOffset, dir, scale, prime, eIGS_Last); return m_effectsController.AttachParticleEffect(effectName, slot, helperName, attachParams); }