bool Group::AddMember(ObjectGuid guid, const char* name) { if (!_addMember(guid, name)) return false; SendUpdate(); if (Player* player = sObjectMgr.GetPlayer(guid)) { if (!IsLeader(player->GetObjectGuid()) && !isBGGroup()) { // reset the new member's instances, unless he is currently in one of them // including raid/heroic instances that they are not permanently bound to! player->ResetInstances(INSTANCE_RESET_GROUP_JOIN); if (player->getLevel() >= LEVELREQUIREMENT_HEROIC && player->GetDifficulty() != GetDifficulty()) { player->SetDifficulty(GetDifficulty()); player->SendDungeonDifficulty(true); } } player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); UpdatePlayerOutOfRange(player); // used by eluna GlobalEluna(OnAddMember(this, player->GetObjectGuid())); // quest related GO state dependent from raid membership if (isRaidGroup()) player->UpdateForQuestWorldObjects(); } return true; }
//========================================================= // Start - player enters the pvs, so get things going. //========================================================= void CFlockingFlyer :: Start( void ) { pev->nextthink = gpGlobals->time + 0.1; if ( IsLeader() ) { SetThink( &CFlockingFlyer::FlockLeaderThink ); } else { SetThink( &CFlockingFlyer::FlockFollowerThink ); } /* Vector vecTakeOff; vecTakeOff = Vector ( 0 , 0 , 0 ); vecTakeOff.z = 50 + RANDOM_FLOAT ( 0, 100 ); vecTakeOff.x = 20 - RANDOM_FLOAT ( 0, 40); vecTakeOff.y = 20 - RANDOM_FLOAT ( 0, 40); pev->velocity = vecTakeOff; pev->speed = pev->velocity.Length(); pev->sequence = 0; */ SetActivity ( ACT_FLY ); ResetSequenceInfo( ); BoidAdvanceFrame( ); pev->speed = AFLOCK_FLY_SPEED;// no delay! }
//========================================================= // StartMonster //========================================================= void CSquadMonster :: StartMonster( void ) { CBaseMonster :: StartMonster(); if ( ( m_afCapability & bits_CAP_SQUAD ) && !InSquad() ) { if ( !FStringNull( pev->netname ) ) { // if I have a groupname, I can only recruit if I'm flagged as leader if ( !( pev->spawnflags & SF_SQUADMONSTER_LEADER ) ) { return; } } // try to form squads now. int iSquadSize = SquadRecruit( 1024, 4 ); if ( iSquadSize ) { ALERT ( at_aiconsole, "Squad of %d %s formed\n", iSquadSize, STRING( pev->classname ) ); } if ( IsLeader() && FClassnameIs ( pev, "monster_human_grunt" ) ) { SetBodygroup( 1, 1 ); // UNDONE: truly ugly hack pev->skin = 0; } } }
bool Group::AddMember(ObjectGuid guid, const char* name) { if (!_addMember(guid, name)) return false; SendUpdate(); if (Player* player = sObjectMgr.GetPlayer(guid)) { if (!IsLeader(player->GetObjectGuid()) && !isBGGroup()) { // reset the new member's instances, unless he is currently in one of them // including raid instances that they are not permanently bound to! player->ResetInstances(INSTANCE_RESET_GROUP_JOIN); } player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); UpdatePlayerOutOfRange(player); // quest related GO state dependent from raid membership if (isRaidGroup()) player->UpdateForQuestWorldObjects(); } return true; }
void BulkRound::ShuffleFinished() { if(!_shuffle_round->Successful()) { _bad_members = _shuffle_round->GetBadMembers(); _state = Finished; Stop("ShuffleRound failed"); return; } if(0 == _shuffle_sink.Count()) { _state = Finished; SetSuccessful(true); Stop("Round successfully finished -- no bulk messages"); return; } PrepareBlameShuffle(); GenerateXorMessages(); if(_app_broadcast && !IsLeader()) { _state = ReceivingLeaderData; } else { _state = DataSharing; } for(int idx = 0; idx < _offline_log.Count(); idx++) { QPair<QByteArray, Id> entry = _offline_log.At(idx); ProcessData(entry.second, entry.first); } _offline_log.Clear(); }
void BulkRound::HandleBulkData(QDataStream &stream, const Id &from) { qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString(); if(IsLeader() || !_app_broadcast) { if(_state != DataSharing) { throw QRunTimeError("Received a misordered BulkData message"); } } else if(_app_broadcast && _state != ProcessingLeaderData) { throw QRunTimeError("Waiting for data from leader, received something else."); } int idx = GetGroup().GetIndex(from); if(!_messages[idx].isEmpty()) { throw QRunTimeError("Already have bulk data."); } QByteArray payload; stream >> payload; if(payload.size() != _expected_bulk_size) { throw QRunTimeError("Incorrect bulk message length"); } _messages[idx] = payload; if(++_received_messages == GetGroup().Count()) { ProcessMessages(); Finish(); } }
void Group::SendUpdate(uint32 type, Mob* member) { if(!member->IsClient()) return; EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; gu->action = type; strcpy(gu->yourname,member->GetName()); int x = 0; for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) if((members[i] != nullptr) && IsLeader(members[i])) { strcpy(gu->leadersname, members[i]->GetName()); break; } for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) if (members[i] != nullptr && members[i] != member) strcpy(gu->membername[x++], members[i]->GetName()); member->CastToClient()->QueuePacket(outapp); safe_delete(outapp); }
//========================================================= // StartMonster //========================================================= void CSquadMonster :: StartMonster( void ) { CBaseMonster :: StartMonster(); if ( ( m_afCapability & bits_CAP_SQUAD ) && !InSquad() ) { if ( HasNetName() ) { // if I have a groupname, I can only recruit if I'm flagged as leader if ( !GetSpawnFlags().Any( SF_SQUADMONSTER_LEADER ) ) { return; } } // try to form squads now. int iSquadSize = SquadRecruit( 1024, 4 ); if ( iSquadSize ) { ALERT ( at_aiconsole, "Squad of %d %s formed\n", iSquadSize, GetClassname() ); } if ( IsLeader() && ClassnameIs( "monster_human_grunt" ) ) { SetBodygroup( 1, 1 ); // UNDONE: truly ugly hack SetSkin( 0 ); } } }
void Group::BroadcastReadyCheck(WorldPacket* packet) { for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pl = itr->getSource(); if (pl && pl->GetSession()) if (IsLeader(pl->GetObjectGuid()) || IsAssistant(pl->GetObjectGuid())) pl->GetSession()->SendPacket(packet); } }
void Group::BroadcastReadyCheck(WorldPacket const& packet) const { for (auto itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* pl = itr->getSource(); if (pl && pl->GetSession()) if (IsLeader(pl->GetObjectGuid()) || IsAssistant(pl->GetObjectGuid())) pl->GetSession()->SendPacket(packet); } }
void BulkRound::Finish() { if(_bad_message_hash.isEmpty()) { if(_app_broadcast && IsLeader()) { QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << AggregatedBulkData << GetRoundId() << _cleartexts; VerifiableBroadcast(msg); } _state = Finished; SetSuccessful(true); Stop("Round successfully finished"); } else { if(_app_broadcast && IsLeader()) { QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << LoggedBulkData << GetRoundId() << _log.Serialize(); VerifiableBroadcast(msg); } BeginBlame(); } }
void Group::DisbandGroup() { EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; gu->action = groupActDisband; Client *Leader = nullptr; uint32 i; for (i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == nullptr) { continue; } if (members[i]->IsClient()) { if(IsLeader(members[i])) { Leader = members[i]->CastToClient(); } strcpy(gu->yourname, members[i]->GetName()); database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID()); members[i]->CastToClient()->QueuePacket(outapp); } members[i]->SetGrouped(false); members[i] = nullptr; membername[i][0] = '\0'; } ServerPacket* pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct)); ServerDisbandGroup_Struct* dg = (ServerDisbandGroup_Struct*)pack->pBuffer; dg->zoneid = zone->GetZoneID(); dg->groupid = GetID(); dg->instance_id = zone->GetInstanceID(); worldserver.SendPacket(pack); safe_delete(pack); entity_list.RemoveGroup(GetID()); if(GetID() != 0) { database.ClearGroup(GetID()); } safe_delete(outapp); }
void Group::UpdatePlayerOnlineStatus(Player* player, bool online /*= true*/) { if (!player) return; const ObjectGuid guid = player->GetObjectGuid(); if (!IsMember(guid)) return; SendUpdate(); if (online) { player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); UpdatePlayerOutOfRange(player); } else if (IsLeader(guid)) m_leaderLastOnline = time(nullptr); }
//========================================================= // PrescheduleThink //========================================================= void CHoundeye::PrescheduleThink ( void ) { // if the hound is mad and is running, make hunt noises. if ( m_MonsterState == MONSTERSTATE_COMBAT && m_Activity == ACT_RUN && RANDOM_FLOAT( 0, 1 ) < 0.2 ) { WarnSound(); } // at random, initiate a blink if not already blinking or sleeping if ( !m_fDontBlink ) { if ( ( pev->skin == 0 ) && RANDOM_LONG(0,0x7F) == 0 ) {// start blinking! pev->skin = HOUNDEYE_EYE_FRAMES - 1; } else if ( pev->skin != 0 ) {// already blinking pev->skin--; } } // if you are the leader, average the origins of each pack member to get an approximate center. if ( IsLeader() ) { CSquadMonster *pSquadMember; int iSquadCount = 0; for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { pSquadMember = MySquadMember(i); if (pSquadMember) { iSquadCount++; m_vecPackCenter = m_vecPackCenter + pSquadMember->pev->origin; } } m_vecPackCenter = m_vecPackCenter / iSquadCount; } }
//========================================================= // AlertSound //========================================================= void CHoundeye :: AlertSound ( void ) { if ( InSquad() && !IsLeader() ) { return; // only leader makes ALERT sound. } switch ( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "houndeye/he_alert1.wav", 1, ATTN_NORM ); break; case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "houndeye/he_alert2.wav", 1, ATTN_NORM ); break; case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "houndeye/he_alert3.wav", 1, ATTN_NORM ); break; } }
void CParty::DoUsePartySkill( u_long uPartyId, u_long uLeaderid, int nSkill ) { #ifdef __WORLDSERVER CUser* pMember = NULL; int i; if( IsLeader( uLeaderid ) && m_nKindTroup == 1 ) { ItemProp* pItemProp = prj.GetPartySkill( nSkill ); if( pItemProp ) { #ifndef __PARTYDEBUG if( int( GetLevel() - pItemProp->dwReqDisLV ) >= 0 ) #endif // __PARTYDEBUG { #ifndef __PARTYDEBUG #if __VER >= 12 // __JHMA_VER12_1 //12차 극단유료아이템 CUser *pLeadertmp = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeadertmp ) == FALSE ) return; int nHasCashSkill = 0,nFPoint = 0; if( pLeadertmp->HasBuff( BUFF_ITEM2, II_SYS_SYS_SCR_PARTYSKILLUP01 ) || pLeadertmp->HasBuff( BUFF_ITEM2, II_SYS_SYS_SCR_PARTYSKILLUP02 ) || pLeadertmp->HasBuff( BUFF_ITEM2, II_SYS_SYS_SCR_PARTYSKILLUP01_01 ) ) { if( nSkill == ST_LINKATTACK || nSkill == ST_FORTUNECIRCLE || nSkill == ST_STRETCHING || nSkill == ST_GIFTBOX ) nHasCashSkill = 1; } DWORD dwSkillTime = pItemProp->dwSkillTime; int nRemovePoint = pItemProp->dwExp; nFPoint = int( GetPoint() - pItemProp->dwExp); #if __VER >= 12 // __LORD // 군주의 극단 // 군주가 극단장 으로써 극단스킬 사용 시, // 지속시간 4배 증가(소모 포인트는 동일) if( CSLord::Instance()->IsLord( uLeaderid ) ) dwSkillTime *= 4; #endif // __LORD if( nFPoint >= 0 ) #else if( int( GetPoint() - pItemProp->dwExp) >= 0 ) #endif // //12차 극단유료아이템 #endif // __PARTYDEBUG { switch( nSkill ) { case ST_CALL: { g_DPCoreClient.SendRemovePartyPoint( uPartyId, pItemProp->dwExp ); CUser *pLeader = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeader ) == FALSE ) break; // 단장 중심으로 모여달라는 표시 for( i = 0; i < m_nSizeofMember; i ++ ) // 단장(0)에게는 보낼필요 없다. { pMember = g_UserMng.GetUserByPlayerID( m_aMember[i].m_uPlayerId ); // 단장 어라운드 지역에 있는 사람에게만 보낸다 if( IsValidObj( (CObj*)pMember ) ) pMember->AddPartySkillCall( pLeader->GetPos() ); // 각 멤버들에게 단장이 좌표를 전송함. } } break; case ST_BLITZ: { CUser *pLeader = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeader ) == FALSE ) break; if( pLeader->m_idSetTarget != NULL_ID ) { CMover *pT = prj.GetMover( pLeader->m_idSetTarget ); if( pT && !pT->IsPlayer() ) { g_DPCoreClient.SendRemovePartyPoint( uPartyId, pItemProp->dwExp ); // 단장이 타겟으로 집중공격 표시 for( i = 0; i < m_nSizeofMember; i ++ ) { pMember = g_UserMng.GetUserByPlayerID( m_aMember[i].m_uPlayerId ); if( IsValidObj( (CObj*)pMember ) ) { if( m_nModeTime[PARTY_GIFTBOX_MODE] || m_nModeTime[PARTY_FORTUNECIRCLE_MODE] ) { pMember->AddPartySkillBlitz( pLeader->m_idSetTarget ); // 각 멤버들에게 단장타겟으로 잡은 무버의 아이디를 보냄. } else { if( pLeader->IsNearPC( pMember ) ) pMember->AddPartySkillBlitz( pLeader->m_idSetTarget ); // 각 멤버들에게 단장타겟으로 잡은 무버의 아이디를 보냄. } } } } else { pLeader->AddSendErrorParty( ERROR_NOTTARGET, ST_BLITZ ); } } else { pLeader->AddSendErrorParty( ERROR_NOTTARGET, ST_BLITZ ); // 타겟을 안잡았다. } } break; case ST_RETREAT: { g_DPCoreClient.SendRemovePartyPoint( uPartyId, pItemProp->dwExp ); // 후퇴 표시 CUser *pLeader = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeader ) == FALSE ) break; for( i = 0; i < m_nSizeofMember; i ++ ) { pMember = g_UserMng.GetUserByPlayerID( m_aMember[i].m_uPlayerId ); if( IsValidObj( (CObj*)pMember ) ) { if( m_nModeTime[PARTY_GIFTBOX_MODE] || m_nModeTime[PARTY_FORTUNECIRCLE_MODE] ) { pMember->AddHdr( pMember->GetId(), SNAPSHOTTYPE_PARTYSKILL_RETREAT ); } else { if( pLeader->IsNearPC( pMember ) ) pMember->AddHdr( pMember->GetId(), SNAPSHOTTYPE_PARTYSKILL_RETREAT ); } } } } break; case ST_SPHERECIRCLE: { // 크리티컬 확률 CUser *pLeader = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeader ) == FALSE ) break; if( pLeader->m_idSetTarget != NULL_ID ) { CMover * pT = prj.GetMover( pLeader->m_idSetTarget ); if( pT && !pT->IsPlayer() ) { g_DPCoreClient.SendRemovePartyPoint( uPartyId, pItemProp->dwExp ); for( i = 0; i < m_nSizeofMember; i ++ ) { pMember = g_UserMng.GetUserByPlayerID( m_aMember[i].m_uPlayerId ); if( IsValidObj( (CObj*)pMember ) ) { if( m_nModeTime[PARTY_GIFTBOX_MODE] || m_nModeTime[PARTY_FORTUNECIRCLE_MODE] ) { pMember->AddHdr( pLeader->m_idSetTarget, SNAPSHOTTYPE_PARTYSKILL_SPHERECIRCLE ); pMember->m_dwFlag |= MVRF_CRITICAL; } else { if( pLeader->IsNearPC( pMember ) ) { pMember->AddHdr( pLeader->m_idSetTarget, SNAPSHOTTYPE_PARTYSKILL_SPHERECIRCLE ); pMember->m_dwFlag |= MVRF_CRITICAL; } } } } } else { pLeader->AddSendErrorParty( ERROR_NOTTARGET, ST_SPHERECIRCLE ); // 타겟이 몬스터가 아니다 } } else { pLeader->AddSendErrorParty( ERROR_NOTTARGET, ST_SPHERECIRCLE ); // 타겟을 안잡았다. } // g_DPCoreClient.SendSetPartyExp( uLeaderid, m_nPoint ); } break; #if __VER >= 12 // __JHMA_VER12_1 //12차 극단유료아이템 case ST_LINKATTACK: { // 데미지 증가 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_LINKATTACK_MODE, dwSkillTime, nRemovePoint, nHasCashSkill ); } break; case ST_FORTUNECIRCLE: { // 유니크 아이템 발생확률 증가 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_FORTUNECIRCLE_MODE, dwSkillTime, nRemovePoint, nHasCashSkill ); } break; case ST_STRETCHING: { // 쉬는경우 회복속도 높여줌 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_STRETCHING_MODE, dwSkillTime, nRemovePoint, nHasCashSkill ); } break; case ST_GIFTBOX: { // 아이템 양이 두배 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_GIFTBOX_MODE, dwSkillTime, nRemovePoint, nHasCashSkill ); } break; #else //12차 극단유료아이템 case ST_LINKATTACK: { // 데미지 증가 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_LINKATTACK_MODE, dwSkillTime, nRemovePoint ); } break; case ST_FORTUNECIRCLE: { // 유니크 아이템 발생확률 증가 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_FORTUNECIRCLE_MODE, dwSkillTime, nRemovePoint ); } break; case ST_STRETCHING: { // 쉬는경우 회복속도 높여줌 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_STRETCHING_MODE, dwSkillTime, nRemovePoint ); } break; case ST_GIFTBOX: { // 아이템 양이 두배 g_DPCoreClient.SendUserPartySkill( uLeaderid, PARTY_GIFTBOX_MODE, dwSkillTime, nRemovePoint ); } break; #endif // //12차 극단유료아이템 default: break; } } #ifndef __PARTYDEBUG else { CUser *pLeader = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeader ) ) { pLeader->AddSendErrorParty( ERROR_NOTPARTYPOINT ); } //포인트가 모자라 스킬을사용할수 없습니다. } #endif // __PARTYDEBUG } #ifndef __PARTYDEBUG else { CUser *pLeader = g_UserMng.GetUserByPlayerID( m_aMember[0].m_uPlayerId ); // 리더의 포인터 if( IsValidObj( pLeader ) ) { pLeader->AddSendErrorParty( ERROR_NOTPARTYSKILL ); } //이 스킬은 배우지를 못했습니다. } #endif // __PARTYDEBUG } } else { // 리더가 아니거나 순회극단이 아닌경우 } #endif // __WORLDSERVER }
bool ON_Annotation::IsDimension() const { if( IsText() || IsLeader()) return false; return true; }
bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID) { bool InZone = true; // This method should either be passed a Mob*, if the new member is in this zone, or a nullptr Mob* // and the name and CharacterID of the new member, if they are out of zone. // if(!newmember && !NewMemberName) return false; if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together. return false; if(!newmember) InZone = false; else { NewMemberName = newmember->GetCleanName(); if(newmember->IsClient()) CharacterID = newmember->CastToClient()->CharacterID(); } uint32 i = 0; // See if they are already in the group // for (i = 0; i < MAX_GROUP_MEMBERS; ++i) if(!strcasecmp(membername[i], NewMemberName)) return false; // Put them in the group for (i = 0; i < MAX_GROUP_MEMBERS; ++i) { if (membername[i][0] == '\0') { if(InZone) members[i] = newmember; break; } } if (i == MAX_GROUP_MEMBERS) return false; strcpy(membername[i], NewMemberName); MemberRoles[i] = 0; int x=1; //build the template join packet EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; strcpy(gj->membername, NewMemberName); gj->action = groupActJoin; for (i = 0;i < MAX_GROUP_MEMBERS; i++) { if (members[i] != nullptr && members[i] != newmember) { //fill in group join & send it strcpy(gj->yourname, members[i]->GetCleanName()); if(members[i]->IsClient()) { members[i]->CastToClient()->QueuePacket(outapp); //put new member into existing person's list strcpy(members[i]->CastToClient()->GetPP().groupMembers[this->GroupCount()-1], NewMemberName); } //put this existing person into the new member's list if(InZone && newmember->IsClient()) { if(IsLeader(members[i])) strcpy(newmember->CastToClient()->GetPP().groupMembers[0], members[i]->GetCleanName()); else { strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName()); x++; } } } } if(InZone) { //put new member in his own list. newmember->SetGrouped(true); if(newmember->IsClient()) { strcpy(newmember->CastToClient()->GetPP().groupMembers[x], NewMemberName); newmember->CastToClient()->Save(); database.SetGroupID(NewMemberName, GetID(), newmember->CastToClient()->CharacterID()); } } else database.SetGroupID(NewMemberName, GetID(), CharacterID); safe_delete(outapp); return true; }
bool ON_Annotation::IsDimension() const { if( IsText() || IsLeader()) return FALSE; return TRUE; }
//========================================================= // follower boids execute this code when flocking //========================================================= void CFlockingFlyer :: FlockFollowerThink( void ) { TraceResult tr; Vector vecDist; Vector vecDir; Vector vecDirToLeader; float flDistToLeader; pev->nextthink = gpGlobals->time + 0.1; if ( IsLeader() || !InSquad() ) { // the leader has been killed and this flyer suddenly finds himself the leader. SetThink ( &CFlockingFlyer::FlockLeaderThink ); return; } vecDirToLeader = ( m_pSquadLeader->pev->origin - pev->origin ); flDistToLeader = vecDirToLeader.Length(); // match heading with leader pev->angles = m_pSquadLeader->pev->angles; // // We can see the leader, so try to catch up to it // if ( FInViewCone ( m_pSquadLeader ) ) { // if we're too far away, speed up if ( flDistToLeader > AFLOCK_TOO_FAR ) { m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 1.5; } // if we're too close, slow down else if ( flDistToLeader < AFLOCK_TOO_CLOSE ) { m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5; } } else { // wait up! the leader isn't out in front, so we slow down to let him pass m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5; } SpreadFlock2(); pev->speed = pev->velocity.Length(); pev->velocity = pev->velocity.Normalize(); // if we are too far from leader, average a vector towards it into our current velocity if ( flDistToLeader > AFLOCK_TOO_FAR ) { vecDirToLeader = vecDirToLeader.Normalize(); pev->velocity = (pev->velocity + vecDirToLeader) * 0.5; } // clamp speeds and handle acceleration if ( m_flGoalSpeed > AFLOCK_FLY_SPEED * 2 ) { m_flGoalSpeed = AFLOCK_FLY_SPEED * 2; } if ( pev->speed < m_flGoalSpeed ) { pev->speed += AFLOCK_ACCELERATE; } else if ( pev->speed > m_flGoalSpeed ) { pev->speed -= AFLOCK_ACCELERATE; } pev->velocity = pev->velocity * pev->speed; BoidAdvanceFrame( ); }
//========================================================= // GetScheduleOfType //========================================================= Schedule_t* CHoundeye :: GetScheduleOfType ( int Type ) { if ( m_fAsleep ) { // if the hound is sleeping, must wake and stand! if ( HasConditions( bits_COND_HEAR_SOUND ) ) { CSound *pWakeSound; pWakeSound = PBestSound(); ASSERT( pWakeSound != NULL ); if ( pWakeSound ) { MakeIdealYaw ( pWakeSound->m_vecOrigin ); if ( FLSoundVolume ( pWakeSound ) >= HOUNDEYE_SOUND_STARTLE_VOLUME ) { // awakened by a loud sound return &slHoundWakeUrgent[ 0 ]; } } // sound was not loud enough to scare the bejesus out of houndeye return &slHoundWakeLazy[ 0 ]; } else if ( HasConditions( bits_COND_NEW_ENEMY ) ) { // get up fast, to fight. return &slHoundWakeUrgent[ 0 ]; } else { // hound is waking up on its own return &slHoundWakeLazy[ 0 ]; } } switch ( Type ) { case SCHED_IDLE_STAND: { // we may want to sleep instead of stand! if ( InSquad() && !IsLeader() && !m_fAsleep && RANDOM_LONG(0,29) < 1 ) { return &slHoundSleep[ 0 ]; } else { return CSquadMonster :: GetScheduleOfType( Type ); } } case SCHED_RANGE_ATTACK1: { return &slHoundRangeAttack[ 0 ]; /* if ( InSquad() ) { return &slHoundRangeAttack[ RANDOM_LONG( 0, 1 ) ]; } return &slHoundRangeAttack[ 1 ]; */ } case SCHED_SPECIAL_ATTACK1: { return &slHoundSpecialAttack1[ 0 ]; } case SCHED_GUARD: { return &slHoundGuardPack[ 0 ]; } case SCHED_HOUND_AGITATED: { return &slHoundAgitated[ 0 ]; } case SCHED_HOUND_HOP_RETREAT: { return &slHoundHopRetreat[ 0 ]; } case SCHED_FAIL: { if ( m_MonsterState == MONSTERSTATE_COMBAT ) { if ( !FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) ) { // client in PVS return &slHoundCombatFailPVS[ 0 ]; } else { // client has taken off! return &slHoundCombatFailNoPVS[ 0 ]; } } else { return CSquadMonster :: GetScheduleOfType ( Type ); } } default: { return CSquadMonster :: GetScheduleOfType ( Type ); } } }
bool Track::IsSelectedLeader() const { return IsSelected() && IsLeader(); }