Player* FollowerAI::GetLeaderForFollower() { if (Player* player = ObjectAccessor::GetPlayer(*me, m_uiLeaderGUID)) { if (player->IsAlive()) return player; else { if (Group* group = player->GetGroup()) { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) { Player* member = groupRef->GetSource(); if (member && member->IsAlive() && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE)) { TC_LOG_DEBUG("scripts", "FollowerAI GetLeader changed and returned new leader."); m_uiLeaderGUID = member->GetGUID(); return member; } } } } } TC_LOG_DEBUG("scripts", "FollowerAI GetLeader can not find suitable leader."); return NULL; }
uint32 NextStep(uint32 uiStep) { Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid); if (!pPlayer) { SetRuffies(m_creepjackGuid, false, true); SetRuffies(m_maloneGuid, false, true); EnterEvadeMode(); return 0; } switch (uiStep) { case 1: DoScriptText(SAY_START, m_creature, pPlayer); SetRuffies(m_creepjackGuid, false, false); SetRuffies(m_maloneGuid, false, false); return 3000; case 2: DoScriptText(SAY_COUNT, m_creature, pPlayer); return 5000; case 3: DoScriptText(SAY_COUNT_1, m_creature, pPlayer); return 3000; case 4: DoScriptText(SAY_COUNT_2, m_creature, pPlayer); return 3000; case 5: DoScriptText(SAY_ATTACK, m_creature, pPlayer); return 3000; case 6: if (!m_creature->IsInCombat() && pPlayer->IsAlive()) { AttackStart(pPlayer); } SetRuffies(m_creepjackGuid, true, false); SetRuffies(m_maloneGuid, true, false); bActiveAttack = true; return 2000; default: return 0; } }
Player* FollowerAI::GetLeaderForFollower() { if (Player* pLeader = Unit::GetPlayer(*me, m_uiLeaderGUID)) { if (pLeader->IsAlive()) return pLeader; else { if (Group* pGroup = pLeader->GetGroup()) { for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next()) { Player* pMember = pRef->GetSource(); if (pMember && pMember->IsAlive() && me->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE)) { sLog.outDebug("OSCR: FollowerAI GetLeader changed and returned new leader."); m_uiLeaderGUID = pMember->GetGUID(); return pMember; break; } } } } } sLog.outDebug("OSCR: FollowerAI GetLeader can not find suitable leader."); return NULL; }
uint8 AoeHealValue::Calculate() { Group* group = bot->GetGroup(); if (!group) return 0; float range = 0; if (qualifier == "low") range = sPlayerbotAIConfig.lowHealth; else if (qualifier == "medium") range = sPlayerbotAIConfig.mediumHealth; else if (qualifier == "critical") range = sPlayerbotAIConfig.criticalHealth; uint8 count = 0; Group::MemberSlotList const& groupSlot = group->GetMemberSlots(); for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) { Player *player = sObjectMgr->GetPlayerByLowGUID(itr->guid); if( !player || !player->IsAlive()) continue; float percent = (static_cast<float> (player->GetHealth()) / player->GetMaxHealth()) * 100; if (percent <= range) count++; } return count; }
Unit* PartyMemberToHeal::Calculate() { IsTargetOfHealingSpell predicate; Group* group = bot->GetGroup(); if (!group) return NULL; bool isRaid = bot->GetGroup()->isRaidGroup(); MinValueCalculator calc(100); for (GroupReference *gref = group->GetFirstMember(); gref; gref = gref->next()) { Player* player = gref->getSource(); if (!Check(player) || !player->IsAlive()) continue; uint8 health = player->GetHealthPercent(); if (isRaid || health < sPlayerbotAIConfig.mediumHealth || !IsTargetOfSpellCast(player, predicate)) calc.probe(health, player); Pet* pet = player->GetPet(); if (pet && CanHealPet(pet)) { health = pet->GetHealthPercent(); if (isRaid || health < sPlayerbotAIConfig.mediumHealth || !IsTargetOfSpellCast(player, predicate)) calc.probe(health, player); } } return (Unit*)calc.param; }
static bool HandleBotHelperCommand(ChatHandler* handler, const char* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); handler->SetSentErrorMessage(true); if (/*player->IsInCombat() ||*/ player->isDead() || !player->IsAlive() || player->IsInFlight() || player->IsCharmed() || bot_ai::CCed(player)) { handler->SendSysMessage("You cannot do this right now"); return false; } //close current menu player->PlayerTalkClass->SendCloseGossip(); if (player->GetTrader()) player->GetSession()->SendCancelTrade(); BotHelper* hlpr = player->GetBotHelper(); if (!hlpr) { hlpr = new BotHelper(player); player->SetBotHelper(hlpr); } return hlpr->OnGossipHello(player); }
void UpdateAI(uint32 diff) override { events.Update(diff); while (uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_CHECK_PLAYER: { bool checkPassed = true; Player* player = ObjectAccessor::FindPlayer(playerGuid); if (!player) { me->DespawnOrUnsummon(1000); playerGuid = 0; break; } if (!player->IsAlive()) { me->DespawnOrUnsummon(1000); playerGuid = 0; break; } if (player->GetQuestStatus(QUEST_PARCHEMIN_VOLANT) != QUEST_STATUS_INCOMPLETE) { me->DespawnOrUnsummon(1000); playerGuid = 0; break; } events.ScheduleEvent(EVENT_CHECK_PLAYER, 2500); break; } case EVENT_FEET_OF_FURY: if (me->GetVictim()) me->CastSpell(me->GetVictim(), 108958); events.ScheduleEvent(EVENT_FEET_OF_FURY, 5000); break; case EVENT_SHADOW_KICK: if (me->GetVictim()) me->CastSpell(me->GetVictim(), 108936); events.ScheduleEvent(EVENT_SHADOW_KICK_STUN, 2500); events.ScheduleEvent(EVENT_SHADOW_KICK, 30000); break; case 4: if (me->GetVictim()) me->CastSpell(me->GetVictim(), 108944); break; } } DoMeleeAttackIfReady(); }
void UpdatePortals() // Here we handle the beams' behavior { for (int j=0; j<3; ++j) // j = color if (Creature* portal = Unit::GetCreature(*me, PortalGUID[j])) { // the one who's been casted upon before Unit* current = Unit::GetUnit(*portal, BeamTarget[j]); // temporary store for the best suitable beam reciever Unit* target = me; if (Map* map = me->GetMap()) { Map::PlayerList const& players = map->GetPlayers(); // get the best suitable target for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { Player* p = i->GetSource(); if (p && p->IsAlive() // alive && (!target || target->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best && !p->HasAura(PlayerDebuff[j], 0) // not exhausted && !p->HasAura(PlayerBuff[(j+1)%3], 0) // not on another beam && !p->HasAura(PlayerBuff[(j+2)%3], 0) && IsBetween(me, p, portal)) // on the beam target = p; } } // buff the target if (target->GetTypeId() == TYPEID_PLAYER) target->AddAura(PlayerBuff[j], target); else target->AddAura(NetherBuff[j], target); // cast visual beam on the chosen target if switched // simple target switching isn't working -> using BeamerGUID to cast (workaround) if (!current || target != current) { BeamTarget[j] = target->GetGUID(); // remove currently beaming portal if (Creature* beamer = Unit::GetCreature(*portal, BeamerGUID[j])) { beamer->CastSpell(target, PortalBeam[j], false); beamer->DisappearAndDie(); BeamerGUID[j] = 0; } // create new one and start beaming on the target if (Creature* beamer = portal->SummonCreature(PortalID[j], portal->GetPositionX(), portal->GetPositionY(), portal->GetPositionZ(), portal->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 60000)) { beamer->CastSpell(target, PortalBeam[j], false); BeamerGUID[j] = beamer->GetGUID(); } } // aggro target if Red Beam if (j == RED_PORTAL && me->GetVictim() != target && target->GetTypeId() == TYPEID_PLAYER) me->getThreatManager().addThreat(target, 100000.0f+DoGetThreat(me->GetVictim())); } }
bool Client::IsFollowing() { if(!world) return false; if(!world->GetLocalPlayer()) return false; Player *p = world->GetLocalPlayer(); if(p->GetTeamId() >= 2) return true; if(p->IsAlive()) return false; else return true; }
void AttackersValue::AddAttackersOf(Group* group, set<Unit*>& targets) { Group::MemberSlotList const& groupSlot = group->GetMemberSlots(); for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) { Player *member = sObjectMgr.GetPlayer(itr->guid); if (!member || !member->IsAlive() || member == bot) continue; AddAttackersOf(member, targets); } }
void MovementInform(uint32 uiType, uint32 uiPointId) override { if (!m_pInstance) { return; } if (uiType == WAYPOINT_MOTION_TYPE) { if (m_uiMovementTimer || m_bIsEventInProgress) { return; } if (m_pInstance->GetData(TYPE_NAZAN) == SPECIAL) { m_creature->SetCombatStartPosition(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); m_uiMovementTimer = 1000; m_bIsEventInProgress = true; } } if (uiType == POINT_MOTION_TYPE) { switch (uiPointId) { case POINT_ID_CENTER: DoSplit(); break; case POINT_ID_COMBAT: { m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_pInstance->SetData(TYPE_NAZAN, IN_PROGRESS); // Landing // undo flying m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); m_creature->SetLevitate(false); Player* pPlayer = m_creature->GetMap()->GetPlayer(m_lastSeenPlayerGuid); if (pPlayer && pPlayer->IsAlive()) { AttackStart(pPlayer); } // Initialize for combat m_uiFireballTimer = urand(5200, 16500); break; } case POINT_ID_FLYING: if (m_bIsEventInProgress) // Additional check for wipe case, while nazan is flying to this point { m_uiFireballTimer = 1; } break; } } }
void HurtRingView::Draw(){ SPADES_MARK_FUNCTION(); Vector3 playerFront; World *w = client->GetWorld(); if(!w){ ClearAll(); return; } Player *p = w->GetLocalPlayer(); if(p == NULL || !p->IsAlive()){ ClearAll(); return; } playerFront = p->GetFront2D(); float hurtRingSize = renderer->ScreenHeight() * .3f; float cx = renderer->ScreenWidth() * .5f; float cy = renderer->ScreenHeight() * .5f; static const float coords[][2]={ {-1,-1},{1,-1},{-1,1} }; std::list<Item>::iterator it; for(it = items.begin(); it != items.end(); it++){ Item& item = *it; float fade = item.fade * 2.f; if(fade > 1.f)fade = 1.f; Vector4 color = {1,1,1,fade}; renderer->SetColor(color); Vector3 dir = -item.dir; float c = dir.x * playerFront.x + dir.y * playerFront.y; float s = dir.y * playerFront.x - dir.x * playerFront.y; Vector2 verts[3]; for(int i = 0; i < 3; i++){ verts[i] = MakeVector2(coords[i][0] * c - coords[i][1] * s, coords[i][0] * s + coords[i][1] * c); verts[i] = verts[i] * hurtRingSize + MakeVector2(cx, cy); } renderer->DrawImage(image, verts[0], verts[1], verts[2], AABB2(0, 0, image->GetWidth(), image->GetHeight())); } }
void JustDied(Unit* /*killer*/) { Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID); if (!target || target->IsAlive()) return; if (Creature* mandokir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MANDOKIR))) { mandokir->GetAI()->SetGUID(target->GetGUID()); mandokir->GetAI()->DoAction(ACTION_START_REVIVE); } me->DespawnOrUnsummon(); }
bool CheckWipe() { Map::PlayerList const &players = instance->GetPlayers(); for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = itr->GetSource(); if (player->IsGameMaster()) continue; if (player->IsAlive()) return false; } return true; }
void SpellHitTarget(Unit* pTarget, const SpellInfo *spell) { if (spell->Id == SPELL_INSANITY) { // Not good target or too many players if (pTarget->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) return; // First target - start channel visual and set self as unnattackable if (!insanityHandled) { me->RemoveAllAuras(); me->CastSpell(me, INSANITY_VISUAL, true); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(true, UNIT_STATE_STUNNED); } // phase mask pTarget->CastSpell(pTarget, SPELL_INSANITY_TARGET+insanityHandled, true); // summon twisted party members for this target Map::PlayerList const &players = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { Player *plr = i->GetSource(); if (!plr || !plr->IsAlive() || pTarget->GetGUID() == plr->GetGUID()) continue; // Summon clone if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0)) { summon->AddThreat(pTarget, 0.0f); summon->SetInCombatWith(pTarget); pTarget->SetInCombatWith(summon); plr->CastSpell(summon, SPELL_CLONE_PLAYER, true); summon->SetPhaseMask(1|(1<<(4+insanityHandled)), true); summon->SetUInt32Value(UNIT_FIELD_MINDAMAGE, plr->GetUInt32Value(UNIT_FIELD_MINDAMAGE)); summon->SetUInt32Value(UNIT_FIELD_MAXDAMAGE, plr->GetUInt32Value(UNIT_FIELD_MAXDAMAGE)); } } ++insanityHandled; } }
void SpellHitTarget(Unit* target, const SpellInfo* spell) override { if (spell->Id == SPELL_INSANITY) { // Not good target or too many players if (target->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) return; // First target - start channel visual and set self as unnattackable if (!insanityHandled) { // Channel visual DoCast(me, INSANITY_VISUAL, true); // Unattackable me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(true, UNIT_STATE_STUNNED); } // phase the player target->CastSpell(target, SPELL_INSANITY_TARGET + insanityHandled, true); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_INSANITY_TARGET + insanityHandled); if (!spellInfo) return; // summon twisted party members for this target Map::PlayerList const &players = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { Player* player = i->GetSource(); if (!player || !player->IsAlive()) continue; // Summon clone if (Unit* summon = me->SummonCreature(NPC_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0)) { // clone player->CastSpell(summon, SPELL_CLONE_PLAYER, true); // phase the summon summon->SetInPhase(spellInfo->Effects[EFFECT_0].MiscValueB, true, true); } } ++insanityHandled; } }
void AttackersValue::AddAttackersOf(Group* group, set<Unit*>& targets) { Group::MemberSlotList const& groupSlot = group->GetMemberSlots(); for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) { Player *member = sObjectMgr->GetPlayerByLowGUID(itr->guid); if (!member || !member->IsAlive() || member == bot) continue; if (member->IsBeingTeleported()) return; AddAttackersOf(member, targets); Pet* pet = member->GetPet(); if (pet) AddAttackersOf(pet, targets); } }
bool InstanceScript::IsWipe() { Map::PlayerList const& PlayerList = instance->GetPlayers(); if (PlayerList.isEmpty()) return true; for (Map::PlayerList::const_iterator Itr = PlayerList.begin(); Itr != PlayerList.end(); ++Itr) { Player* player = Itr->GetSource(); if (!player) continue; if (player->IsAlive() && !player->IsGameMaster()) return false; } return true; }
void CreatureAI::DoAttackerGroupInCombat(Player* attacker) { if(attacker) { if( Group *pGroup = attacker->GetGroup() ) { for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *pGroupGuy = itr->GetSource(); if(pGroupGuy && pGroupGuy->IsAlive() && pGroupGuy->GetMapId() == me->GetMapId()) { me->SetInCombatWith(pGroupGuy); pGroupGuy->SetInCombatWith(me); me->AddThreat(pGroupGuy, 0.0f); } } } } }
void instance_uldaman::Update(uint32 uiDiff) { if (GetData(TYPE_ALTAR_EVENT) != IN_PROGRESS) return; if (!m_uiKeeperCooldown) return; if (m_uiKeeperCooldown <= uiDiff) { for (GuidList::const_iterator itr = m_lKeepers.begin(); itr != m_lKeepers.end(); ++itr) { // Get Keeper which is alive and out of combat Creature* pKeeper = instance->GetCreature(*itr); if (!pKeeper || !pKeeper->IsAlive() || pKeeper->getVictim()) continue; // Get starter player for attack Player* pPlayer = pKeeper->GetMap()->GetPlayer(m_playerGuid); if (!pPlayer || !pPlayer->IsAlive()) { // If he's not available, then get a random player, within a reasonamble distance in map pPlayer = GetPlayerInMap(true, false); if (!pPlayer || !pPlayer->IsWithinDistInMap(pKeeper, 50.0f)) { SetData(TYPE_ALTAR_EVENT, NOT_STARTED); return; } } // Attack the player pKeeper->RemoveAurasDueToSpell(SPELL_STONED); pKeeper->AI()->AttackStart(pPlayer); break; } m_uiKeeperCooldown = 0; } else m_uiKeeperCooldown -= uiDiff; }
void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) { uint16 opcode = recvData.GetOpcode(); Unit* mover = _player->m_mover; ASSERT(mover != NULL); // there must always be a mover Player* plrMover = mover->ToPlayer(); // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plrMover && plrMover->IsBeingTeleported()) { recvData.rfinish(); // prevent warnings spam return; } /* extract packet */ uint64 guid; recvData.readPackGUID(guid); MovementInfo movementInfo; movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); recvData.rfinish(); // prevent warnings spam // pussywizard: typical check for incomming movement packets if (!mover || !mover->IsInWorld() || mover->IsDuringRemoveFromWorld() || guid != mover->GetGUID()) return; if (!movementInfo.pos.IsPositionValid()) { recvData.rfinish(); // prevent warnings spam return; } if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) { // T_POS ON VEHICLES! if (mover->GetVehicle()) movementInfo.transport.pos = mover->m_movementInfo.transport.pos; // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if (movementInfo.transport.pos.GetPositionX() > 75.0f || movementInfo.transport.pos.GetPositionY() > 75.0f || movementInfo.transport.pos.GetPositionZ() > 75.0f || movementInfo.transport.pos.GetPositionX() < -75.0f || movementInfo.transport.pos.GetPositionY() < -75.0f || movementInfo.transport.pos.GetPositionZ() < -75.0f) { recvData.rfinish(); // prevent warnings spam return; } if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) { recvData.rfinish(); // prevent warnings spam return; } // if we boarded a transport, add us to it if (plrMover) { if (!plrMover->GetTransport()) { if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid)) { plrMover->m_transport = transport; transport->AddPassenger(plrMover); } } else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid) { bool foundNewTransport = false; plrMover->m_transport->RemovePassenger(plrMover); if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid)) { foundNewTransport = true; plrMover->m_transport = transport; transport->AddPassenger(plrMover); } if (!foundNewTransport) { plrMover->m_transport = NULL; movementInfo.transport.Reset(); } } } if (!mover->GetTransport() && !mover->GetVehicle()) movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave { plrMover->m_transport->RemovePassenger(plrMover); plrMover->m_transport = NULL; movementInfo.transport.Reset(); } if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } // Dont allow to turn on walking if charming other player if (mover->GetGUID() != _player->GetGUID()) movementInfo.flags &= ~MOVEMENTFLAG_WALKING; uint32 mstime = World::GetGameTimeMS(); /*----------------------*/ if(m_clientTimeDelay == 0) m_clientTimeDelay = mstime > movementInfo.time ? std::min(mstime - movementInfo.time, (uint32)100) : 0; // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE if (mover->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) { // Xinef: skip moving packets if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) return; movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ()); if (mover->GetTypeId() == TYPEID_UNIT) { movementInfo.transport.guid = mover->m_movementInfo.transport.guid; movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ()); movementInfo.transport.seat = mover->m_movementInfo.transport.seat; } } /* process position-change */ WorldPacket data(opcode, recvData.size()); //movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY; movementInfo.time = mstime; // pussywizard: set to time of relocation (server time), constant addition may smoothen movement clientside, but client sees target on different position than the real serverside position movementInfo.guid = mover->GetGUID(); WriteMovementInfo(&data, &movementInfo); mover->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; // this is almost never true (pussywizard: only one packet when entering vehicle), normally use mover->IsVehicle() if (mover->GetVehicle()) { mover->SetOrientation(movementInfo.pos.GetOrientation()); mover->UpdatePosition(movementInfo.pos); return; } // pussywizard: previously always mover->UpdatePosition(movementInfo.pos); if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT && mover->GetTransport()) { float x, y, z, o; movementInfo.transport.pos.GetPosition(x, y, z, o); mover->GetTransport()->CalculatePassengerPosition(x, y, z, &o); mover->UpdatePosition(x, y, z, o); } else mover->UpdatePosition(movementInfo.pos); // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). // Xinef: moved it here, previously StopMoving function called when player died relocated him to last saved coordinates (which were in air) if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight() && (!plrMover->GetTransport() || plrMover->GetTransport()->IsStaticTransport())) plrMover->HandleFall(movementInfo); // Xinef: interrupt parachutes upon falling or landing in water if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM) mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes if (plrMover) // nothing is charmed, or player charmed { if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING))) plrMover->SetStandState(UNIT_STAND_STATE_STAND); plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.pos.GetPositionZ() < -500.0f) if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player)) { if (plrMover->IsAlive()) { plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // player can be alive if GM if (plrMover->IsAlive()) plrMover->KillPlayer(); } plrMover->StopMovingOnCurrentPos(); // pussywizard: moving corpse can't release spirit } } }
void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) { uint16 opcode = recvData.GetOpcode(); Unit* mover = _player->m_mover; ASSERT(mover != NULL); // there must always be a mover Player* plrMover = mover->ToPlayer(); // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plrMover && plrMover->IsBeingTeleported()) { recvData.rfinish(); // prevent warnings spam return; } /* extract packet */ uint64 guid; recvData.readPackGUID(guid); MovementInfo movementInfo; movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); recvData.rfinish(); // prevent warnings spam // prevent tampered movement data if (guid != mover->GetGUID()) return; if (!movementInfo.pos.IsPositionValid()) { recvData.rfinish(); // prevent warnings spam return; } /* handle special cases */ if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if (movementInfo.transport.pos.GetPositionX() > 50 || movementInfo.transport.pos.GetPositionY() > 50 || movementInfo.transport.pos.GetPositionZ() > 50) { recvData.rfinish(); // prevent warnings spam return; } if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) { recvData.rfinish(); // prevent warnings spam return; } // if we boarded a transport, add us to it if (plrMover) { if (!plrMover->GetTransport()) { // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.transport.guid) { plrMover->m_transport = *iter; (*iter)->AddPassenger(plrMover); break; } } } else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid) { bool foundNewTransport = false; plrMover->m_transport->RemovePassenger(plrMover); for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.transport.guid) { foundNewTransport = true; plrMover->m_transport = *iter; (*iter)->AddPassenger(plrMover); break; } } if (!foundNewTransport) { plrMover->m_transport = NULL; movementInfo.transport.Reset(); } } } if (!mover->GetTransport() && !mover->GetVehicle()) { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave { plrMover->m_transport->RemovePassenger(plrMover); plrMover->m_transport = NULL; movementInfo.transport.Reset(); } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) plrMover->HandleFall(movementInfo); if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } if (plrMover) sAnticheatMgr->StartHackDetection(plrMover, movementInfo, opcode); /*----------------------*/ /* process position-change */ WorldPacket data(opcode, recvData.size()); movementInfo.time = getMSTime(); movementInfo.guid = mover->GetGUID(); WriteMovementInfo(&data, &movementInfo); mover->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() if (mover->GetVehicle()) { mover->SetOrientation(movementInfo.pos.GetOrientation()); return; } mover->UpdatePosition(movementInfo.pos); if (plrMover) // nothing is charmed, or player charmed { plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.pos.GetPositionZ() < -500.0f) { if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { // NOTE: this is actually called many times while falling // even after the player has been teleported away /// @todo discard movement packets after the player is rooted if (plrMover->IsAlive()) { plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // player can be alive if GM/etc // change the death state to CORPSE to prevent the death timer from // starting in the next player update if (!plrMover->IsAlive()) plrMover->KillPlayer(); } } } } }
void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; if( me->GetPositionX() < 490.0f || me->GetPositionX() > 690.0f || me->GetPositionY() < 130.0f || me->GetPositionY() > 410.0f ) { EnterEvadeMode(); return; } events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; switch (events.GetEvent()) { case 0: break; case EVENT_ACTIVATE_CONSTRUCT: me->CastCustomSpell(SPELL_ACTIVATE_CONSTRUCT, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, false); if (++counter >= 20) { me->MonsterYell(TEXT_BERSERK, LANG_UNIVERSAL, 0); me->PlayDirectSound(SOUND_BERSERK); me->CastSpell(me, SPELL_BERSERK, true); events.PopEvent(); break; } events.RepeatEvent(RAID_MODE(40000,30000)); break; case EVENT_SPELL_SCORCH: if( rand()%2 ) { me->MonsterYell(TEXT_SCORCH_1, LANG_UNIVERSAL, 0); me->PlayDirectSound(SOUND_SCORCH_1); } else { me->MonsterYell(TEXT_SCORCH_2, LANG_UNIVERSAL, 0); me->PlayDirectSound(SOUND_SCORCH_2); } me->SetControlled(true, UNIT_STATE_ROOT); me->DisableRotate(true); me->SendMovementFlagUpdate(); me->CastSpell(me->GetVictim(), S_SCORCH, false); events.RepeatEvent(20000); events.RescheduleEvent(EVENT_ENABLE_ROTATE, 3001); break; case EVENT_ENABLE_ROTATE: me->SetControlled(false, UNIT_STATE_ROOT); me->DisableRotate(false); events.PopEvent(); break; case EVENT_SPELL_FLAME_JETS: me->MonsterTextEmote(TEXT_FLAME_JETS, 0, true); me->CastSpell(me->GetVictim(), S_FLAME_JETS, false); events.RepeatEvent(25000); break; case EVENT_GRAB: { std::list<Creature*> icl; me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT); std::vector<uint64> playerGUIDs; Map::PlayerList const& pl = me->GetMap()->GetPlayers(); Player* temp = NULL; for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr ) { temp = itr->GetSource(); if( !temp->IsAlive() || temp->GetExactDist2d(me) > 90.0f ) continue; if( me->GetVictim() && temp->GetGUID() == me->GetVictim()->GetGUID() ) continue; bool found = false; for( std::list<Creature*>::iterator itr = icl.begin(); itr != icl.end(); ++itr ) if( (*itr)->GetVictim() && (*itr)->GetVictim()->GetGUID() == temp->GetGUID() ) { found = true; break; } if( !found ) playerGUIDs.push_back(temp->GetGUID()); } if( !playerGUIDs.empty() ) { int8 pos = urand(0, playerGUIDs.size()-1); if( Player* pTarget = ObjectAccessor::GetPlayer(*me,playerGUIDs.at(pos)) ) { me->MonsterYell(TEXT_SLAG_POT, LANG_UNIVERSAL, 0); me->PlayDirectSound(SOUND_SLAG_POT); me->CastSpell(pTarget, SPELL_GRAB, false); } } events.RepeatEvent(24000); // +6000 below events.DelayEvents(6000); } break; } DoMeleeAttackIfReady(); }
void MapView::Draw(){ World *world = client->GetWorld(); if(!world) return; Player *player = world->GetLocalPlayer(); if(client->IsFollowing()){ player = world->GetPlayer(client->followingPlayerId); } if(!player) return; if(largeMap) if(zoomState < .0001f) return; GameMap *map = world->GetMap(); Vector2 mapSize = MakeVector2(map->Width(), map->Height()); Vector3 pos = player->GetPosition();; if(player->GetTeamId() >= 2){ pos = client->followPos; } Vector2 center = {pos.x, pos.y}; float cfgMapSize = cg_minimapSize; if(cfgMapSize < 32) cfgMapSize = 32; if(cfgMapSize > 256) cfgMapSize = 256; Vector2 mapWndSize = {cfgMapSize, cfgMapSize}; float scale = actualScale; center = Mix(center, mapSize * .5f, zoomState); Vector2 zoomedSize = {512, 512}; if(renderer->ScreenWidth() < 512.f || renderer->ScreenHeight() < 512.f) zoomedSize = MakeVector2(256, 256); if(largeMap){ float per = zoomState; per = 1.f - per; per *= per; per = 1.f - per; per = Mix(.7f, 1.f, per); zoomedSize = Mix(MakeVector2(0, 0), zoomedSize, per); mapWndSize = zoomedSize; } Vector2 inRange = mapWndSize * .5f * scale; AABB2 inRect(center - inRange, center + inRange); if(largeMap){ inRect.min = MakeVector2(0, 0); inRect.max = mapSize; }else{ if(inRect.GetMinX() < 0.f) inRect = inRect.Translated(-inRect.GetMinX(), 0.f); if(inRect.GetMinY() < 0.f) inRect = inRect.Translated(0, -inRect.GetMinY()); if(inRect.GetMaxX() > mapSize.x) inRect = inRect.Translated(mapSize.x - inRect.GetMaxX(), 0.f); if(inRect.GetMaxY() > mapSize.y) inRect = inRect.Translated(0, mapSize.y - inRect.GetMaxY()); } AABB2 outRect(renderer->ScreenWidth() - mapWndSize.x - 16.f, 16.f, mapWndSize.x, mapWndSize.y); if(largeMap){ outRect.min = MakeVector2((renderer->ScreenWidth() - zoomedSize.x) * .5f, (renderer->ScreenHeight() - zoomedSize.y) * .5f); outRect.max =MakeVector2((renderer->ScreenWidth() + zoomedSize.x) * .5f, (renderer->ScreenHeight() + zoomedSize.y) * .5f); } float alpha = 1.f; if(largeMap){ alpha = zoomState; } // fades bg if(largeMap) { Handle<IImage> bg = renderer->RegisterImage("Gfx/MapBg.png"); Vector2 scrSize = {renderer->ScreenWidth(), renderer->ScreenHeight()}; float size = std::max(scrSize.x, scrSize.y); renderer->SetColorAlphaPremultiplied(MakeVector4(0, 0, 0,alpha * .5f)); renderer->DrawImage(bg, AABB2((scrSize.x - size) * .5f, (scrSize.y - size) * .5f, size, size)); } // draw border Handle<IImage> border; float borderWidth; AABB2 borderRect = outRect; if(largeMap) { border = renderer->RegisterImage("Gfx/MapBorder.png"); borderWidth = 3.f * outRect.GetHeight() / zoomedSize.y; }else{ border = renderer->RegisterImage("Gfx/MinimapBorder.png"); borderWidth = 2.f; } borderRect = borderRect.Inflate(borderWidth - 8.f); renderer->SetColorAlphaPremultiplied(MakeVector4(alpha,alpha,alpha,alpha)); renderer->DrawImage(border, AABB2(borderRect.GetMinX()-16, borderRect.GetMinY()-16, 16, 16), AABB2(0, 0, 16, 16)); renderer->DrawImage(border, AABB2(borderRect.GetMaxX(), borderRect.GetMinY()-16, 16, 16), AABB2(16, 0, 16, 16)); renderer->DrawImage(border, AABB2(borderRect.GetMinX()-16, borderRect.GetMaxY(), 16, 16), AABB2(0, 16, 16, 16)); renderer->DrawImage(border, AABB2(borderRect.GetMaxX(), borderRect.GetMaxY(), 16, 16), AABB2(16, 16, 16, 16)); renderer->DrawImage(border, AABB2(borderRect.GetMinX(), borderRect.GetMinY()-16, borderRect.GetWidth(), 16), AABB2(16, 0, 0, 16)); renderer->DrawImage(border, AABB2(borderRect.GetMinX(), borderRect.GetMaxY(), borderRect.GetWidth(), 16), AABB2(16, 16, 0, 16)); renderer->DrawImage(border, AABB2(borderRect.GetMinX()-16, borderRect.GetMinY(), 16, borderRect.GetHeight()), AABB2(0, 16, 16, 0)); renderer->DrawImage(border, AABB2(borderRect.GetMaxX(), borderRect.GetMinY(), 16, borderRect.GetHeight()), AABB2(16, 16, 16, 0)); // draw map renderer->SetColorAlphaPremultiplied(MakeVector4(alpha,alpha,alpha,alpha)); renderer->DrawFlatGameMap(outRect, inRect); this->inRect = inRect; this->outRect = outRect; // draw grid renderer->SetColorAlphaPremultiplied(MakeVector4(0,0,0,0.8f*alpha)); Handle<IImage> dashLine = renderer->RegisterImage("Gfx/DashLine.tga"); for(float x = 64.f; x < map->Width(); x += 64.f){ float wx = (x - inRect.GetMinX()) / inRect.GetWidth(); if(wx < 0.f || wx >= 1.f) continue; wx = (wx * outRect.GetWidth()) + outRect.GetMinX(); wx = roundf(wx); renderer->DrawImage(dashLine, MakeVector2(wx, outRect.GetMinY()), AABB2(0, 0, 1.f, outRect.GetHeight())); } for(float y = 64.f; y < map->Height(); y += 64.f){ float wy = (y - inRect.GetMinY()) / inRect.GetHeight(); if(wy < 0.f || wy >= 1.f) continue; wy = (wy * outRect.GetHeight()) + outRect.GetMinY(); wy = roundf(wy); renderer->DrawImage(dashLine, MakeVector2(outRect.GetMinX(), wy), AABB2(0, 0, outRect.GetWidth(), 1.f)); } // draw grid label renderer->SetColorAlphaPremultiplied(MakeVector4(1,1,1,1)*(0.8f*alpha)); Handle<IImage> mapFont = renderer->RegisterImage("Gfx/Fonts/MapFont.tga"); for(int i = 0; i < 8; i++){ float startX = (float)i * 64.f; float endX = startX + 64.f; if(startX > inRect.GetMaxX() || endX < inRect.GetMinX()) continue; float fade = std::min((std::min(endX, inRect.GetMaxX()) - std::max(startX, inRect.GetMinX())) / (endX - startX) * 2.f, 1.f); renderer->SetColorAlphaPremultiplied(MakeVector4(1,1,1,1)*(fade * .8f * alpha)); float center = std::max(startX, inRect.GetMinX()); center = .5f * (center + std::min(endX, inRect.GetMaxX())); float wx = (center - inRect.GetMinX()) / inRect.GetWidth(); wx = (wx * outRect.GetWidth()) + outRect.GetMinX(); wx = roundf(wx); float fntX = static_cast<float>((i & 3) * 8); float fntY = static_cast<float>((i >> 2) * 8); renderer->DrawImage(mapFont, MakeVector2(wx - 4.f, outRect.GetMinY() + 4), AABB2(fntX, fntY, 8, 8)); } for(int i = 0; i < 8; i++){ float startY = (float)i * 64.f; float endY = startY + 64.f; if(startY > inRect.GetMaxY() || endY < inRect.GetMinY()) continue; float fade = std::min((std::min(endY, inRect.GetMaxY()) - std::max(startY, inRect.GetMinY())) / (endY - startY) * 2.f, 1.f); renderer->SetColorAlphaPremultiplied(MakeVector4(1,1,1,1)*(fade * .8f * alpha)); float center = std::max(startY, inRect.GetMinY()); center = .5f * (center + std::min(endY, inRect.GetMaxY())); float wy = (center - inRect.GetMinY()) / inRect.GetHeight(); wy = (wy * outRect.GetHeight()) + outRect.GetMinY(); wy = roundf(wy); int fntX = (i & 3) * 8; int fntY = (i >> 2) * 8 + 16; renderer->DrawImage(mapFont, MakeVector2(outRect.GetMinX() + 4, wy - 4.f), AABB2(fntX, fntY, 8, 8)); } //draw objects std::string iconmode = cg_Minimap_Player_Icon;//import variable from configuration file std::string colormode = cg_Minimap_Player_Color;//import variable from configuration file Handle<IImage> playerSMG = renderer->RegisterImage("Gfx/Map/SMG.png"); Handle<IImage> playerRifle = renderer->RegisterImage("Gfx/Map/Rifle.png"); Handle<IImage> playerShotgun = renderer->RegisterImage("Gfx/Map/Shotgun.png"); Handle<IImage> playerIcon = renderer->RegisterImage("Gfx/Map/Player.png"); { IntVector3 teamColor = world->GetLocalPlayer()->GetTeamId() >= 2 ? IntVector3::Make(200, 200, 200) : world->GetTeam(world->GetLocalPlayer()->GetTeamId()).color; Vector4 teamColorF = ModifyColor(teamColor); teamColorF *= alpha; // draw local player's view { Player *p = player; Handle<IImage> viewIcon = renderer->RegisterImage("Gfx/Map/View.png"); if(p->IsAlive()) { Vector3 front = p->GetFront2D(); float ang = atan2(front.x, -front.y); if(player->GetTeamId() >= 2){ ang = client->followYaw - static_cast<float>(M_PI) * .5f; } renderer->SetColorAlphaPremultiplied(teamColorF * 0.9f); DrawIcon(player->GetTeamId() >= 2 ? client->followPos : p->GetPosition(), viewIcon, ang); } } // draw player's icon for(int i = 0; i < world->GetNumPlayerSlots(); i++){ Player * p = world->GetPlayer(i); if(p == nullptr || p->GetTeamId() != world->GetLocalPlayer()->GetTeamId() || !p->IsAlive()) continue; Vector3 front = p->GetFront2D(); float ang = atan2(front.x, -front.y); if(player->GetTeamId() >= 2){ ang = client->followYaw - static_cast<float>(M_PI) * .5f; } //use a spec color for each player if ( colormode=="1"){ IntVector3 Colorplayer=IntVector3::Make(palette[i][0],palette[i][1],palette[i][2]); Vector4 ColorplayerF = ModifyColor(Colorplayer); ColorplayerF *=1.0f; renderer->SetColorAlphaPremultiplied(ColorplayerF); } else { renderer->SetColorAlphaPremultiplied(teamColorF); } //use a different icon in minimap according to weapon of player if( iconmode=="1"){ WeaponType weapon=world->GetPlayer(i)->GetWeaponType(); if (weapon == WeaponType::SMG_WEAPON){ DrawIcon(player->GetTeamId() >= 2 ? client->followPos : p->GetPosition(),playerSMG , ang); } else if (weapon == WeaponType::RIFLE_WEAPON){ DrawIcon(player->GetTeamId() >= 2 ? client->followPos : p->GetPosition(), playerRifle, ang); } else if (weapon == WeaponType::SHOTGUN_WEAPON){ DrawIcon(player->GetTeamId() >= 2 ? client->followPos : p->GetPosition(), playerShotgun, ang); } } else{//draw normal color DrawIcon(player->GetTeamId() >= 2 ? client->followPos : p->GetPosition(), playerIcon, ang); } } } IGameMode* mode = world->GetMode(); if( mode && IGameMode::m_CTF == mode->ModeType() ) { CTFGameMode *ctf = static_cast<CTFGameMode *>(mode); Handle<IImage> intelIcon = renderer->RegisterImage("Gfx/Map/Intel.png"); Handle<IImage> baseIcon = renderer->RegisterImage("Gfx/Map/CommandPost.png"); for(int tId = 0; tId < 2; tId++){ CTFGameMode::Team& team = ctf->GetTeam(tId); IntVector3 teamColor = world->GetTeam(tId).color; Vector4 teamColorF = ModifyColor(teamColor); teamColorF *= alpha; // draw base renderer->SetColorAlphaPremultiplied(teamColorF); DrawIcon(team.basePos, baseIcon, 0.f); // draw flag if(!ctf->GetTeam(1-tId).hasIntel){ renderer->SetColorAlphaPremultiplied(teamColorF); DrawIcon(team.flagPos, intelIcon, 0.f); }else if(world->GetLocalPlayer()->GetTeamId() == 1-tId){ // local player's team is carrying int cId = ctf->GetTeam(1-tId).carrier; // in some game modes, carrier becomes invalid if(cId < world->GetNumPlayerSlots()){ Player * carrier= world->GetPlayer(cId); if(carrier && carrier->GetTeamId() == world->GetLocalPlayer()->GetTeamId()){ Vector4 col = teamColorF; col *= fabsf(sinf(world->GetTime() * 4.f)); renderer->SetColorAlphaPremultiplied(col); DrawIcon(carrier->GetPosition(), intelIcon, 0.f); } } } } } else if( mode && IGameMode::m_TC == mode->ModeType() ) { TCGameMode *tc = static_cast<TCGameMode *>(mode); Handle<IImage> icon = renderer->RegisterImage("Gfx/Map/CommandPost.png"); int cnt = tc->GetNumTerritories(); for(int i = 0; i < cnt; i++){ TCGameMode::Territory *t = tc->GetTerritory(i); IntVector3 teamColor = {128,128,128}; if(t->ownerTeamId < 2){ teamColor = world->GetTeam(t->ownerTeamId).color; } Vector4 teamColorF = ModifyColor(teamColor); teamColorF *= alpha; // draw base renderer->SetColorAlphaPremultiplied(teamColorF); DrawIcon(t->pos, icon, 0.f); } } }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid Guid; recvData >> Guid; Player* player = ObjectAccessor::FindConnectedPlayer(Guid); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << Guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); Powers powerType = player->getPowerType(); std::set<uint32> const& phases = player->GetPhases(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS; if (powerType != POWER_MANA) updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE; if (pet) updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER; if (player->GetVehicle()) updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT; if (!phases.empty()) updateFlags |= GROUP_UPDATE_FLAG_PHASE; uint16 playerStatus = MEMBER_STATUS_ONLINE; if (player->IsPvP()) playerStatus |= MEMBER_STATUS_PVP; if (!player->IsAlive()) { if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) playerStatus |= MEMBER_STATUS_GHOST; else playerStatus |= MEMBER_STATUS_DEAD; } if (player->IsFFAPvP()) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) playerStatus |= MEMBER_STATUS_AFK; if (player->isDND()) playerStatus |= MEMBER_STATUS_DND; data << uint32(updateFlags); data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE) data << uint8(powerType); data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION // GROUP_UPDATE_FLAG_AURAS data << uint8(1); uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder data << uint32(MAX_AURAS); // count for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(aurApp->GetBase()->GetId()); data << uint16(aurApp->GetFlags()); if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i)) data << int32(eff->GetAmount()); else data << int32(0); } } } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID) data << uint64(pet->GetGUID()); data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP) data << uint32(pet->GetHealth()); if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP) data << uint32(pet->GetMaxHealth()); if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE) data << (uint8)pet->getPowerType(); if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER) data << uint16(pet->GetPower(pet->getPowerType())); if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER) data << uint16(pet->GetMaxPower(pet->getPowerType())); // GROUP_UPDATE_FLAG_PET_AURAS uint64 petAuraMask = 0; data << uint8(1); maskPos = data.wpos(); data << uint64(petAuraMask); // placeholder data << uint32(MAX_AURAS); // count if (pet) { for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = pet->GetVisibleAura(i)) { petAuraMask |= (uint64(1) << i); data << uint32(aurApp->GetBase()->GetId()); data << uint16(aurApp->GetFlags()); if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i)) data << int32(eff->GetAmount()); else data << int32(0); } } } } } data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT) data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); if (updateFlags & GROUP_UPDATE_FLAG_PHASE) { data << uint32(phases.empty() ? 8 : 0); data << uint32(phases.size()); for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) data << uint16(*itr); } SendPacket(&data); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { if (events.IsInPhase(PHASE_NORMAL)) { case EVENT_BLOODTHIRST: DoCast(me, SPELL_BLOODTHIRST); events.ScheduleEvent(EVENT_BLOODTHIRST, 10000); break; case EVENT_FLAME_SPHERE: DoCastVictim(SPELL_CONJURE_FLAME_SPHERE); events.SetPhase(PHASE_SPECIAL); events.ScheduleEvent(EVENT_CASTING_FLAME_SPHERES, 3000); events.ScheduleEvent(EVENT_FLAME_SPHERE, 15000); break; case EVENT_VANISH: { Map::PlayerList const& players = me->GetMap()->GetPlayers(); uint32 targets = 0; for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { Player* player = i->GetSource(); if (player && player->IsAlive()) ++targets; } if (targets > 2) { Talk(SAY_VANISH); DoCast(me, SPELL_VANISH); events.SetPhase(PHASE_SPECIAL); events.ScheduleEvent(EVENT_JUST_VANISHED, 500); if (Unit* embraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) _embraceTargetGUID = embraceTarget->GetGUID(); } events.ScheduleEvent(EVENT_VANISH, urand(25000, 35000)); break; } } case EVENT_CASTING_FLAME_SPHERES: { events.SetPhase(PHASE_NORMAL); Unit* sphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); if (!sphereTarget) break; float angle, x, y; //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1); if (Creature* sphere = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10 * IN_MILLISECONDS)) { angle = sphere->GetAngle(sphereTarget); x = sphere->GetPositionX() + DATA_SPHERE_DISTANCE * std::cos(angle); y = sphere->GetPositionY() + DATA_SPHERE_DISTANCE * std::sin(angle); sphere->GetMotionMaster()->MovePoint(0, x, y, sphere->GetPositionZ()); } if (IsHeroic()) { //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1); if (Creature* sphere = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10 * IN_MILLISECONDS)) { angle = sphere->GetAngle(sphereTarget) + DATA_SPHERE_ANGLE_OFFSET; x = sphere->GetPositionX() + DATA_SPHERE_DISTANCE/2 * std::cos(angle); y = sphere->GetPositionY() + DATA_SPHERE_DISTANCE/2 * std::sin(angle); sphere->GetMotionMaster()->MovePoint(0, x, y, sphere->GetPositionZ()); } //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2); if (Creature* sphere = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10 * IN_MILLISECONDS)) { angle = sphere->GetAngle(sphereTarget) - DATA_SPHERE_ANGLE_OFFSET; x = sphere->GetPositionX() + DATA_SPHERE_DISTANCE/2 * std::cos(angle); y = sphere->GetPositionY() + DATA_SPHERE_DISTANCE/2 * std::sin(angle); sphere->GetMotionMaster()->MovePoint(0, x, y, sphere->GetPositionZ()); } } break; } case EVENT_JUST_VANISHED: if (Unit* embraceTarget = GetEmbraceTarget()) { me->GetMotionMaster()->Clear(); me->SetSpeed(MOVE_WALK, 2.0f, true); me->GetMotionMaster()->MoveChase(embraceTarget); } events.ScheduleEvent(EVENT_VANISHED, 1300); break; case EVENT_VANISHED: if (Unit* embraceTarget = GetEmbraceTarget()) DoCast(embraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); Talk(SAY_FEED); me->GetMotionMaster()->Clear(); me->SetSpeed(MOVE_WALK, 1.0f, true); me->GetMotionMaster()->MoveChase(me->GetVictim()); events.ScheduleEvent(EVENT_FEEDING, 20000); break; case EVENT_FEEDING: _embraceTargetGUID = 0; events.SetPhase(PHASE_NORMAL); break; default: break; } } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { if (EventInProgress) { Player* warrior = NULL; if (!PlayerGUID.IsEmpty()) warrior = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!warrior) return; if (!warrior->IsAlive() && warrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { Talk(SAY_TWIGGY_FLATHEAD_DOWN); warrior->FailQuest(1719); for (uint8 i = 0; i < 6; ++i) // unsummon challengers { if (!AffrayChallenger[i].IsEmpty()) { Creature* creature = ObjectAccessor::GetCreature((*me), AffrayChallenger[i]); if (creature && creature->IsAlive()) creature->DisappearAndDie(); } } if (!BigWill.IsEmpty()) // unsummon bigWill { Creature* creature = ObjectAccessor::GetCreature((*me), BigWill); if (creature && creature->IsAlive()) creature->DisappearAndDie(); } Reset(); } if (!EventGrate && EventInProgress) { float x, y, z; warrior->GetPosition(x, y, z); if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) { warrior->AreaExploredOrEventHappens(1719); Talk(SAY_TWIGGY_FLATHEAD_BEGIN, warrior); for (uint8 i = 0; i < 6; ++i) { Creature* creature = me->SummonCreature(NPC_AFFRAY_CHALLENGER, AffrayChallengerLoc[i], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); if (!creature) continue; creature->setFaction(35); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); AffrayChallenger[i] = creature->GetGUID(); } WaveTimer = 5000; ChallengerChecker = 1000; EventGrate = true; } } else if (EventInProgress) { if (ChallengerChecker <= diff) { for (uint8 i = 0; i < 6; ++i) { if (!AffrayChallenger[i].IsEmpty()) { Creature* creature = ObjectAccessor::GetCreature((*me), AffrayChallenger[i]); if ((!creature || (!creature->IsAlive())) && !ChallengerDown[i]) { Talk(SAY_TWIGGY_FLATHEAD_DOWN); ChallengerDown[i] = true; } } } ChallengerChecker = 1000; } else ChallengerChecker -= diff; if (WaveTimer <= diff) { if (Wave < 6 && !AffrayChallenger[Wave].IsEmpty() && !EventBigWill) { Talk(SAY_TWIGGY_FLATHEAD_FRAY); Creature* creature = ObjectAccessor::GetCreature(*me, AffrayChallenger[Wave]); if (creature && (creature->IsAlive())) { creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); creature->setFaction(14); creature->AI()->AttackStart(warrior); ++Wave; WaveTimer = 20000; } } else if (Wave >= 6 && !EventBigWill) { if (Creature* creature = me->SummonCreature(NPC_BIG_WILL, -1722, -4341, 6.12f, 6.26f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 480000)) { BigWill = creature->GetGUID(); //creature->GetMotionMaster()->MovePoint(0, -1693, -4343, 4.32f); //creature->GetMotionMaster()->MovePoint(1, -1684, -4333, 2.78f); creature->GetMotionMaster()->MovePoint(2, -1682, -4329, 2.79f); creature->HandleEmoteCommand(EMOTE_STATE_READY_UNARMED); EventBigWill = true; WaveTimer = 1000; } } else if (Wave >= 6 && EventBigWill && !BigWill.IsEmpty()) { Creature* creature = ObjectAccessor::GetCreature(*me, BigWill); if (!creature || !creature->IsAlive()) { Talk(SAY_TWIGGY_FLATHEAD_OVER); Reset(); } else if (creature) // Makes BIG WILL attackable. { creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); creature->setFaction(14); creature->AI()->AttackStart(warrior); } } } else WaveTimer -= diff; } } }
void WorldSession::HandleInitiateTradeOpcode(WorldPackets::Trade::InitiateTrade& initiateTrade) { if (GetPlayer()->m_trade) return; WorldPackets::Trade::TradeStatus info; if (!GetPlayer()->IsAlive()) { info.Status = TRADE_STATUS_DEAD; SendTradeStatus(info); return; } if (GetPlayer()->HasUnitState(UNIT_STATE_STUNNED)) { info.Status = TRADE_STATUS_STUNNED; SendTradeStatus(info); return; } if (isLogingOut()) { info.Status = TRADE_STATUS_LOGGING_OUT; SendTradeStatus(info); return; } if (GetPlayer()->IsInFlight()) { info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); return; } if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_TRADE_REQ), sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)); return; } Player* pOther = ObjectAccessor::FindPlayer(initiateTrade.Guid); if (!pOther) { info.Status = TRADE_STATUS_NO_TARGET; SendTradeStatus(info); return; } if (pOther == GetPlayer() || pOther->m_trade) { info.Status = TRADE_STATUS_PLAYER_BUSY; SendTradeStatus(info); return; } if (!pOther->IsAlive()) { info.Status = TRADE_STATUS_TARGET_DEAD; SendTradeStatus(info); return; } if (pOther->IsInFlight()) { info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); return; } if (pOther->HasUnitState(UNIT_STATE_STUNNED)) { info.Status = TRADE_STATUS_TARGET_STUNNED; SendTradeStatus(info); return; } if (pOther->GetSession()->isLogingOut()) { info.Status = TRADE_STATUS_TARGET_LOGGING_OUT; SendTradeStatus(info); return; } if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUID())) { info.Status = TRADE_STATUS_PLAYER_IGNORED; SendTradeStatus(info); return; } if ((pOther->GetTeam() != _player->GetTeam() || pOther->HasFlag(PLAYER_FLAGS_EX, PLAYER_FLAGS_EX_MERCENARY_MODE) || _player->HasFlag(PLAYER_FLAGS_EX, PLAYER_FLAGS_EX_MERCENARY_MODE)) && (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && !HasPermission(rbac::RBAC_PERM_ALLOW_TWO_SIDE_TRADE))) { info.Status = TRADE_STATUS_WRONG_FACTION; SendTradeStatus(info); return; } if (!pOther->IsWithinDistInMap(_player, TRADE_DISTANCE, false)) { info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); return; } if (pOther->getLevel() < sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_TRADE_OTHER_REQ), sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)); return; } // OK start trade _player->m_trade = new TradeData(_player, pOther); pOther->m_trade = new TradeData(pOther, _player); info.Status = TRADE_STATUS_PROPOSED; info.Partner = _player->GetGUID(); pOther->GetSession()->SendTradeStatus(info); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); uint64 guid; recvData >> guid; Player* player = HashMapHolder<Player>::Find(guid); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(guid); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); Powers powerType = player->getPowerType(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS; if (powerType != POWER_MANA) updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE; if (pet) updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER; if (player->GetVehicle()) updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT; uint16 playerStatus = MEMBER_STATUS_ONLINE; if (player->IsPvP()) playerStatus |= MEMBER_STATUS_PVP; if (!player->IsAlive()) { if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) playerStatus |= MEMBER_STATUS_GHOST; else playerStatus |= MEMBER_STATUS_DEAD; } if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) playerStatus |= MEMBER_STATUS_AFK; if (player->isDND()) playerStatus |= MEMBER_STATUS_DND; data << uint32(updateFlags); data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE) data << uint8(powerType); data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION // GROUP_UPDATE_FLAG_AURAS data << uint8(1); uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder data << uint32(MAX_AURAS); // count for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(aurApp->GetBase()->GetId()); data << uint16(aurApp->GetFlags()); if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i)) data << int32(eff->GetAmount()); else data << int32(0); } } } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID) data << uint64(pet->GetGUID()); data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP) data << uint32(pet->GetHealth()); if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP) data << uint32(pet->GetMaxHealth()); if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE) data << (uint8)pet->getPowerType(); if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER) data << uint16(pet->GetPower(pet->getPowerType())); if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER) data << uint16(pet->GetMaxPower(pet->getPowerType())); uint64 petAuraMask = 0; maskPos = data.wpos(); data << uint64(petAuraMask); // placeholder if (pet) { // GROUP_UPDATE_FLAG_PET_AURAS data << uint8(1); uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder data << uint32(MAX_AURAS); // count for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(aurApp->GetBase()->GetId()); data << uint16(aurApp->GetFlags()); if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i)) data << int32(eff->GetAmount()); else data << int32(0); } } } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } // else not needed, flags do not include any PET_ update // GROUP_UPDATE_FLAG_PHASE data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT data << uint32(0); // count // for (count) *data << uint16(phaseId) data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT) data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); SendPacket(&data); }
void Player::FireWeapon() { SPADES_MARK_FUNCTION(); Vector3 muzzle = GetEye(); muzzle += GetFront() * 0.01f; // for hit-test debugging std::map<int, HitTestDebugger::PlayerHit> playerHits; std::vector<Vector3> bulletVectors; //Vector3 right = GetRight(); //Vector3 up = GetUp(); int pellets = weapon->GetPelletSize(); float spread = weapon->GetSpread(); GameMap *map = world->GetMap(); // pyspades takes destroying more than one block as a // speed hack (shotgun does this) bool blockDestroyed = false; Vector3 dir2 = GetFront(); for(int i =0 ; i < pellets; i++){ // AoS 0.75's way (dir2 shouldn't be normalized!) dir2.x += (GetRandom() - GetRandom()) * spread; dir2.y += (GetRandom() - GetRandom()) * spread; dir2.z += (GetRandom() - GetRandom()) * spread; Vector3 dir = dir2.Normalize(); bulletVectors.push_back(dir); // first do map raycast GameMap::RayCastResult mapResult; mapResult = map->CastRay2(muzzle, dir, 500); Player *hitPlayer = NULL; float hitPlayerDistance = 0.f; HitBodyPart hitPart = HitBodyPart::None; for(int i = 0; i < world->GetNumPlayerSlots(); i++){ Player *other = world->GetPlayer(i); if(other == this || other == NULL) continue; if(other == this || !other->IsAlive() || other->GetTeamId() >= 2) continue; // quickly reject players unlikely to be hit if(!other->RayCastApprox(muzzle, dir)) continue; HitBoxes hb = other->GetHitBoxes(); Vector3 hitPos; if(hb.head.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; hitPart = HitBodyPart::Head; } } if(hb.torso.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; hitPart = HitBodyPart::Torso; } } for(int j = 0; j < 3 ;j++){ if(hb.limbs[j].RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; switch(j) { case 0: hitPart = HitBodyPart::Limb1; break; case 1: hitPart = HitBodyPart::Limb2; break; case 2: hitPart = HitBodyPart::Arms; break; } } } } } Vector3 finalHitPos; finalHitPos = muzzle + dir * 128.f; if(hitPlayer == nullptr && !mapResult.hit) { // might hit water surface. } if(mapResult.hit && (mapResult.hitPos - muzzle).GetLength() < 128.f && (hitPlayer == NULL || (mapResult.hitPos - muzzle).GetLength() < hitPlayerDistance)){ IntVector3 outBlockCoord = mapResult.hitBlock; // TODO: set correct ray distance // FIXME: why ray casting twice? finalHitPos = mapResult.hitPos; if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 && outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() && outBlockCoord.z < map->Depth()){ if(outBlockCoord.z == 63) { if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); }else if(outBlockCoord.z == 62) { // blocks at this level cannot be damaged if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); }else{ int x = outBlockCoord.x; int y = outBlockCoord.y; int z = outBlockCoord.z; SPAssert(map->IsSolid(x, y, z)); Vector3 blockF = {x + .5f, y + .5f, z + .5f}; float distance = (blockF - muzzle).GetLength(); uint32_t color = map->GetColor(x, y, z); int health = color >> 24; health -= weapon->GetDamage(HitTypeBlock, distance); if(health <= 0 && !blockDestroyed){ health = 0; blockDestroyed = true; //send destroy cmd if(world->GetListener() && world->GetLocalPlayer() == this) world->GetListener()->LocalPlayerBlockAction (outBlockCoord, BlockActionTool); } color = (color & 0xffffff) | ((uint32_t)health << 24); if(map->IsSolid(x, y, z)) map->Set(x, y, z, true, color); if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } } }else if(hitPlayer != NULL){