void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId; uint8 cast_count, unk_flags; recvPacket >> cast_count; recvPacket >> spellId; recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) // ignore for remote control state (for player case) Unit* _mover = GetPlayer()->GetMover(); if (_mover != GetPlayer() && _mover->GetTypeId()==TYPEID_PLAYER) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", spellId, cast_count, unk_flags, (uint32)recvPacket.size()); /* process anticheat check */ if (!GetPlayer()->GetAntiCheat()->DoAntiCheatCheck(CHECK_SPELL, spellId, CMSG_CAST_SPELL)) return; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } // Players on vehicles may cast many simple spells (like knock) from self Unit* mover = NULL; if (spellInfo->HasAttribute(SPELL_ATTR_EX6_CASTABLE_ON_VEHICLE) && _mover->IsCharmerOrOwnerPlayerOrPlayerItself()) mover = _mover->GetCharmerOrOwnerPlayerOrPlayerItself(); else mover = _mover; // casting own spells on some vehicles if (mover->IsVehicle() && mover->GetCharmerOrOwnerPlayerOrPlayerItself()) { Player *plr = mover->GetCharmerOrOwnerPlayerOrPlayerItself(); if (mover->GetVehicleKit()->GetSeatInfo(plr) && ((mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_ATTACK) || (mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_CAST) )) mover = plr; } bool triggered = false; SpellEntry const* triggeredBy = NULL; Aura const* triggeredByAura = mover->GetTriggeredByClientAura(spellId); if (triggeredByAura) { triggered = true; triggeredBy = triggeredByAura->GetSpellProto(); cast_count = 0; } if (mover->GetTypeId()==TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client if (((((Player*)mover)->GetUInt16Value(PLAYER_FIELD_BYTES2, 0) == 0 && (!((Player*)mover)->HasActiveSpell(spellId) && !triggered)) || IsPassiveSpell(spellInfo)) && spellId != 1843) { sLog.outError("WorldSession::HandleCastSpellOpcode: %s casts spell %u which he shouldn't have", mover->GetObjectGuid().GetString().c_str(), spellId); //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } else { // not have spell in spellbook or spell passive and not casted by client if ((!((Creature*)mover)->HasSpell(spellId) && !triggered) || IsPassiveSpell(spellInfo)) { sLog.outError("WorldSession::HandleCastSpellOpcode: %s try casts spell %u which he shouldn't have", mover->GetObjectGuid().GetString().c_str(), spellId); //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(mover); // some spell cast packet including more data (for projectiles?) if (unk_flags & 0x02) targets.ReadAdditionalData(recvPacket); // auto-selection buff level base at target level (in spellInfo) if (Unit* target = targets.getUnitTarget()) { // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if (SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, target->getLevel())) spellInfo = actualSpellInfo; } Spell *spell = new Spell(mover, spellInfo, triggered, mover->GetObjectGuid(), triggeredBy); spell->m_cast_count = cast_count; // set count of casts spell->prepare(&targets, triggeredByAura); }
void WorldSession::HandlePetSetAction(WorldPacket & recv_data) { sLog->outDetail("HandlePetSetAction. CMSG_PET_SET_ACTION"); uint64 petguid; uint8 count; recv_data >> petguid; Unit* pet = ObjectAccessor::GetUnit(*_player, petguid); if (!pet || pet != _player->GetFirstControlled()) { sLog->outError("HandlePetSetAction: Unknown pet (GUID: %u) or pet owner (GUID: %u)", GUID_LOPART(petguid), _player->GetGUIDLow()); return; } CharmInfo *charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog->outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } count = (recv_data.size() == 24) ? 2 : 1; uint32 position[2]; uint32 data[2]; bool move_command = false; for (uint8 i = 0; i < count; ++i) { recv_data >> position[i]; recv_data >> data[i]; uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); //ignore invalid position if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX) return; // in the normal case, command and reaction buttons can only be moved, not removed // at moving count == 2, at removing count == 1 // ignore attempt to remove command|reaction buttons (not possible at normal case) if (act_state == ACT_COMMAND || act_state == ACT_REACTION) { if (count == 1) return; move_command = true; } } // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) if (move_command) { uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) { uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || act_state_0 != actionEntry_1->GetType()) return; } uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) { uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || act_state_1 != actionEntry_0->GetType()) return; } } for (uint8 i = 0; i < count; ++i) { uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); sLog->outDetail("Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state)); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if (act_state == ACT_ENABLED && spell_id) { if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) ((Pet*)pet)->ToggleAutocast(spell_id, true); else charmInfo->ToggleCreatureAutocast(spell_id, true); } //sign for no/turn off autocast else if (act_state == ACT_DISABLED && spell_id) { if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) ((Pet*)pet)->ToggleAutocast(spell_id, false); else charmInfo->ToggleCreatureAutocast(spell_id, false); } charmInfo->SetActionBar(position[i], spell_id, ActiveStates(act_state)); } } }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { sLog->outDetail("WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint8 castCount; uint32 spellId; uint8 castFlags; recvPacket >> guid >> castCount >> spellId >> castFlags; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_CAST_SPELL, guid: " UI64FMTD ", castCount: %u, spellId %u, castFlags %u", guid, castCount, spellId, castFlags); // This opcode is also sent from charmed and possessed units (players and creatures) if (!_player->GetGuardianPet() && !_player->GetCharm()) return; Unit* caster = ObjectAccessor::GetUnit(*_player, guid); if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) { sLog->outError("HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); return; } SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) { sLog->outError("WORLD: unknown PET spell id %i", spellId); return; } if (spellInfo->StartRecoveryCategory > 0) // Check if spell is affected by GCD if (caster->GetTypeId() == TYPEID_UNIT && caster->ToCreature()->GetGlobalCooldown() > 0) { caster->SendPetCastFail(spellId, SPELL_FAILED_NOT_READY); return; } // do not cast not learned spells if (!caster->HasSpell(spellId) || IsPassiveSpell(spellId)) return; SpellCastTargets targets; targets.read(recvPacket, caster); HandleClientCastFlags(recvPacket, castFlags, targets); caster->ClearUnitState(UNIT_STAT_FOLLOW); Spell *spell = new Spell(caster, spellInfo, false); spell->m_cast_count = castCount; // probably pending spell cast spell->m_targets = targets; // TODO: need to check victim? SpellCastResult result; if (caster->m_movedPlayer) result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit()); else result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { if (caster->GetTypeId() == TYPEID_UNIT) { Creature* pet = caster->ToCreature(); pet->AddCreatureSpellCooldown(spellId); if (pet->isPet()) { Pet* p = (Pet*)pet; // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } } spell->prepare(&(spell->m_targets)); } else { caster->SendPetCastFail(spellId, result); if (caster->GetTypeId() == TYPEID_PLAYER) { if (!caster->ToPlayer()->HasSpellCooldown(spellId)) GetPlayer()->SendClearCooldown(spellId, caster); } else { if (!caster->ToCreature()->HasSpellCooldown(spellId)) GetPlayer()->SendClearCooldown(spellId, caster); } spell->finish(false); delete spell; } }
void CGame2View::OnDraw(CDC* pDC) { int result; CRect ClientRect; CRect MapSectionRect; CGame2Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here GameMapObserver *GameMap = pDoc->GetMap(); Unit *theUnit; int max_x = pDoc->GetMapWidth(); int max_y = pDoc->GetMapHeight(); int x,y; // clear the memory DC mInMemoryScreenDC.FillSolidRect(mMapRect,RGB(255,255,255)); // Draw box around map... mInMemoryScreenDC.MoveTo(0 ,0 ); mInMemoryScreenDC.LineTo(mMapRect.right - 1 ,0 ); mInMemoryScreenDC.LineTo(mMapRect.right - 1 ,mMapRect.bottom - 1); mInMemoryScreenDC.LineTo(0 ,mMapRect.bottom - 1); mInMemoryScreenDC.LineTo(0 ,0 ); // Draw into it for (x = 0; x < max_x; x++) { for(y = 0; y < max_y; y++) { if( (theUnit = GameMap->RequestLoc(x,y))) { theUnit->DrawUnit(&mInMemoryScreenDC); } } } if(mBoundingBoxIsUp) { DrawBoundingBox(mCurSelectRect); } mFlasher +=20; if(mFlasher>200) mFlasher = 0; mInMemoryScreenDC.FillSolidRect( 60 + mFlasher, 10, 10, 10, RGB(0,0,0)); GetClientRect(&ClientRect); MapSectionRect = ClientRect; // OnPrepareDC(); pDC->DPtoLP(&MapSectionRect); // Blt it to screen result = pDC->BitBlt(MapSectionRect.left, MapSectionRect.top, ClientRect.right, ClientRect.bottom, &mInMemoryScreenDC, MapSectionRect.left, MapSectionRect.top, SRCCOPY); }
double SbmlReader::transformUnits( double mvalue,UnitDefinition * ud,string type, bool hasonlySubUnit ) { double lvalue = mvalue; if (type == "compartment") { for ( unsigned int ut = 0; ut < ud->getNumUnits(); ut++ ) { Unit * unit = ud->getUnit(ut); double exponent = unit->getExponent(); double multiplier = unit->getMultiplier(); int scale = unit->getScale(); double offset = unit->getOffset(); lvalue *= pow( multiplier * pow(10.0,scale), exponent ) + offset; // Need to check if spatial dimension is less than 3 then, // then volume conversion e-3 to convert cubicmeter shd not be done. if ( unit->isLitre() ) { lvalue *= pow(1e-3,exponent); return lvalue; } } } else if(type == "substance") { for ( unsigned int ut = 0; ut < ud->getNumUnits(); ut++ ) { Unit * unit = ud->getUnit(ut); //cout << " :) " << UnitKind_toString(unit->getKind()); if ( unit->isMole() ) { double exponent = unit->getExponent(); double multiplier = unit->getMultiplier(); int scale = unit->getScale(); double offset = unit->getOffset(); lvalue *= pow( multiplier * pow(10.0,scale), exponent ) + offset; if (hasonlySubUnit) // if hasonlySubstanceUnit is true, then unit is subtance // In Moose nInit = no. of molecules( unit is items) // no. of molecules (items) = mole * Avogadro no. // In SBML if initial Amount is set to mole then convert from mole to items (#) lvalue *= pow( NA ,exponent); else // if hasonlySubstanceUnit is false, //Then convert mole to milli Molar for moose as concentration units are in milliMolar // Molar = mole/size lvalue *= pow(1e+3,exponent); return lvalue; } else if(unit->isItem()) return lvalue; else if(unit->isSecond()) return lvalue; else { cout << "check this units type " <<UnitKind_toString(unit->getKind()); return lvalue; } } } return lvalue; }
int Unit::think_stop_chase() { //-----------------------------------------------------// // // Stop the chase if the target is being far away from // its original attacking location. // //-----------------------------------------------------// if( !(action_mode==ACTION_ATTACK_UNIT && ai_original_target_x_loc>=0) ) return 0; if( unit_array.is_deleted(action_para) ) { stop2(); return 1; } Unit* targetUnit = unit_array[action_para]; if( !targetUnit->is_visible() ) { stop2(); return 1; } //----------------------------------------// int aiChaseDistance = 10 + nation_array[nation_recno]->pref_military_courage/20; // chase distance: 10 to 15 int curDistance = m.points_distance( targetUnit->next_x_loc(), targetUnit->next_y_loc(), ai_original_target_x_loc, ai_original_target_y_loc ); if( curDistance <= aiChaseDistance ) return 0; //--------- stop the unit ----------------// stop2(); //--- if this unit leads a troop, stop the action of all troop members as well ---// int leaderUnitRecno; if( leader_unit_recno ) leaderUnitRecno = leader_unit_recno; else leaderUnitRecno = sprite_recno; TeamInfo* teamInfo = unit_array[leaderUnitRecno]->team_info; if( teamInfo ) { for( int i=teamInfo->member_count-1 ; i>=0 ; i-- ) { int unitRecno = teamInfo->member_unit_array[i]; if( unit_array.is_deleted(unitRecno) ) continue; unit_array[unitRecno]->stop2(); } } return 1; }
//---- Begin of function Town::independent_unit_join_nation ----// // // <int> raceId - race id. of the unit // <int> toNationRecno - recno of the nation the unit should turn toward // int Town::independent_unit_join_nation(int raceId, int toNationRecno) { //----- mobilize a villager ----// int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec population after mobilizing the unit, 0-don't mobilize spies if( !unitRecno ) return 0; Unit* unitPtr = unit_array[unitRecno]; //----- set the skills of the unit -----// int skillId, skillLevel, combatLevel; switch( misc.random(3) ) { case 0: // leaders skillId = SKILL_LEADING; if( misc.random(3)==0 ) skillLevel = misc.random(100); else skillLevel = misc.random(50); combatLevel = skillLevel + misc.random(40) - 20; combatLevel = MIN(combatLevel, 100); combatLevel = MAX(combatLevel, 10); break; case 1: // peasants skillId = 0; skillLevel = 0; combatLevel = 10 + misc.random(10); break; case 2: // skilled units skillId = misc.random(MAX_TRAINABLE_SKILL)+1; { int loopCount=0; // no spying skill while( skillId==SKILL_SPYING ) { if( ++skillId > MAX_TRAINABLE_SKILL ) skillId = 1; err_when( ++loopCount > 100 ); } } skillLevel = 10+misc.random(80); combatLevel = 10+misc.random(30); break; } //--------------------------------------// unitPtr->skill.skill_id = skillId; unitPtr->skill.skill_level = skillLevel; unitPtr->set_combat_level( combatLevel ); //------ change nation now --------// if( !unitPtr->betray(toNationRecno) ) return 0; //---- the unit moves close to the newly joined nation ----// unitPtr->ai_move_to_nearby_town(); //-------- set last_independent_unit_join_date --------// nation_array[toNationRecno]->last_independent_unit_join_date = info.game_date; return 1; }
void UpdateAI(const uint32 uiDiff) { //Return since we have no target if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) return; //m_uiEarthquake_Timer if (m_uiEarthquake_Timer < uiDiff) { if (!m_bEarthquake) { DoCast(m_creature->getVictim(), SPELL_EARTHQUAKE); m_bEarthquake = true; m_uiEarthquake_Timer = 5000; } else { DoScriptText(urand(0,1) ? SAY_SUMMON1 : SAY_SUMMON2, m_creature); //north m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A6,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A7,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A8,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A9,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_A10,true); //south m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B6,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B7,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B8,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B9,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_MURLOC_B10,true); DoScriptText(EMOTE_EARTHQUAKE, m_creature); m_bEarthquake = false; m_uiEarthquake_Timer = 40000+rand()%5000; } }else m_uiEarthquake_Timer -= uiDiff; //m_uiTidalWave_Timer if (m_uiTidalWave_Timer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_TIDAL_WAVE); m_uiTidalWave_Timer = 20000; }else m_uiTidalWave_Timer -= uiDiff; if (!m_bPhase2) { //m_uiWateryGrave_Timer if (m_uiWateryGrave_Timer < uiDiff) { //Teleport 4 players under the waterfalls for(uint8 i = 0; i < 4; i++) { Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && !pTarget->HasAuraType(SPELL_AURA_MOD_STUN) && pTarget->IsWithinDistInMap(m_creature, 45.0f)) { switch(i) { case 0: m_creature->CastSpell(pTarget,SPELL_WATERY_GRAVE_1,false); break; case 1: m_creature->CastSpell(pTarget,SPELL_WATERY_GRAVE_2,false); break; case 2: m_creature->CastSpell(pTarget,SPELL_WATERY_GRAVE_3,false); break; case 3: m_creature->CastSpell(pTarget,SPELL_WATERY_GRAVE_4,false); break; } } } DoScriptText(urand(0,1) ? SAY_SUMMON_BUBL1 : SAY_SUMMON_BUBL2, m_creature); DoScriptText(EMOTE_WATERY_GRAVE, m_creature); m_uiWateryGrave_Timer = 30000; }else m_uiWateryGrave_Timer -= uiDiff; //Start Phase2 if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) m_bPhase2 = true; } else { //m_uiWateryGlobules_Timer if (m_uiWateryGlobules_Timer < uiDiff) { DoScriptText(EMOTE_WATERY_GLOBULES, m_creature); m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_1,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_2,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_3,true); m_creature->CastSpell(m_creature,SPELL_SUMMON_GLOBULE_4,false); m_uiWateryGlobules_Timer = 25000; }else m_uiWateryGlobules_Timer -= uiDiff; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { //Check if we have a target if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; //No instance if (!m_pInstance) return; switch (m_pInstance->GetData(TYPE_CTHUN_PHASE)) { case 0: { //BeamTimer if (BeamTimer < diff) { //SPELL_GREEN_BEAM Unit* target = NULL; target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target) { m_creature->InterruptNonMeleeSpells(false); DoCastSpellIfCan(target,SPELL_GREEN_BEAM); //Correctly update our target m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID()); } //Beam every 3 seconds BeamTimer = 3000; }else BeamTimer -= diff; //ClawTentacleTimer if (ClawTentacleTimer < diff) { Unit* target = NULL; target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target) { Creature* Spawned = NULL; //Spawn claw tentacle on the random target Spawned = (Creature*)m_creature->SummonCreature(MOB_CLAW_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500); if (Spawned) Spawned->AI()->AttackStart(target); } //One claw tentacle every 12.5 seconds ClawTentacleTimer = 12500; }else ClawTentacleTimer -= diff; //EyeTentacleTimer if (EyeTentacleTimer < diff) { //Spawn the 8 Eye Tentacles in the corret spots SpawnEyeTentacle(0, 20); //south SpawnEyeTentacle(10, 10); //south west SpawnEyeTentacle(20, 0); //west SpawnEyeTentacle(10, -10); //north west SpawnEyeTentacle(0, -20); //north SpawnEyeTentacle(-10, -10); //north east SpawnEyeTentacle(-20, 0); // east SpawnEyeTentacle(-10, 10); // south east //No point actually putting a timer here since //These shouldn't trigger agian until after phase shifts EyeTentacleTimer = 45000; }else EyeTentacleTimer -= diff; //PhaseTimer if (PhaseTimer < diff) { //Switch to Dark Beam m_pInstance->SetData(TYPE_CTHUN_PHASE, 1); m_creature->InterruptNonMeleeSpells(false); //Select random target for dark beam to start on Unit* target = NULL; target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); if (target) { //Correctly update our target m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID()); //Face our target DarkGlareAngle = m_creature->GetAngle(target); DarkGlareTickTimer = 1000; DarkGlareTick = 0; ClockWise = urand(0, 1); } //Add red coloration to C'thun DoCastSpellIfCan(m_creature,SPELL_RED_COLORATION); //Freeze animation //Darkbeam for 35 seconds PhaseTimer = 35000; }else PhaseTimer -= diff; } break; case 1: { //EyeTentacleTimer if (DarkGlareTick < 35) if (DarkGlareTickTimer < diff) { //Remove any target m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); //Set angle and cast if (ClockWise) m_creature->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35)); else m_creature->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35)); m_creature->StopMoving(); //Actual dark glare cast, maybe something missing here? m_creature->CastSpell(NULL, SPELL_DARK_GLARE, false); //Increase tick ++DarkGlareTick; //1 second per tick DarkGlareTickTimer = 1000; }else DarkGlareTickTimer -= diff; //PhaseTimer if (PhaseTimer < diff) { //Switch to Eye Beam m_pInstance->SetData(TYPE_CTHUN_PHASE, 0); BeamTimer = 3000; EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn durring Dark beam) m_creature->InterruptNonMeleeSpells(false); //Remove Red coloration from c'thun m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION); //Freeze animation m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); //Eye Beam for 50 seconds PhaseTimer = 50000; }else PhaseTimer -= diff; }break; //Transition phase case 2: { //Remove any target m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); m_creature->SetHealth(0); } //Dead phase case 5: { m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); } } }
void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Mortal Wound if (m_uiMortalWoundTimer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_MORTALWOUND); m_uiMortalWoundTimer = 10000; } else m_uiMortalWoundTimer -= uiDiff; //Decimate_Timer if (m_uiDecimateTimer < uiDiff) { DoCast(m_creature->getVictim(),SPELL_DECIMATE); // need core support // workaround below std::list<HostileReference*> t_list = m_creature->getThreatManager().getThreatList(); if (t_list.size()) { //begin + 1 , so we don't target the one with the highest threat std::list<HostileReference*>::iterator itr = t_list.begin(); std::advance(itr, 1); for(; itr!= t_list.end(); ++itr) { Unit *target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); if (target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER && (target->GetHealth() > target->GetMaxHealth() * 0.05)) target->SetHealth(target->GetMaxHealth() * 0.05); } } // Move Zombies if (!m_lZombieGUIDList.empty()) { for(std::list<uint64>::iterator itr = m_lZombieGUIDList.begin(); itr != m_lZombieGUIDList.end(); ++itr) if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) if (pTemp->isAlive()) { ((mob_zombie_chowsAI*)pTemp->AI())->bIsForceMove = true; if (m_creature->GetHealth() > m_creature->GetMaxHealth() * 0.05) // remove when SPELL_DECIMATE is working pTemp->SetHealth(pTemp->GetMaxHealth() * 0.02); pTemp->AddThreat(m_creature, 1000000000.0f); // force move toward to Gluth } } m_uiDecimateTimer = (m_bIsRegularMode ? 100000 : 120000); }else m_uiDecimateTimer -= uiDiff; // Enrage if (m_uiEnrageTimer < uiDiff) { DoCast(m_creature, m_bIsRegularMode ? SPELL_ENRAGE : SPELL_ENRAGE_H); m_uiEnrageTimer = 60000; } else m_uiEnrageTimer -= uiDiff; if (RangeCheck_Timer < uiDiff) { if (!m_lZombieGUIDList.empty()) { for(std::list<uint64>::iterator itr = m_lZombieGUIDList.begin(); itr != m_lZombieGUIDList.end(); ++itr) if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, ATTACK_DISTANCE)) { DoScriptText(EMOTE_ZOMBIE, m_creature); m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth() * 0.05); pTemp->ForcedDespawn(); } } RangeCheck_Timer = 1000; }else RangeCheck_Timer -= uiDiff; //Summon_Timer if (Summon_Timer < uiDiff) { for(uint8 i = 0; i < (m_bIsRegularMode ? 1 : 2); i++) { if (Creature* pZombie = m_creature->SummonCreature(NPC_ZOMBIE_CHOW,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000)) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { pZombie->AddThreat(pTarget); m_lZombieGUIDList.push_back(pZombie->GetGUID()); } } } Summon_Timer = 10000; } else Summon_Timer -= uiDiff; // Berserk if (m_uiBerserkTimer < uiDiff) { DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_TRIGGERED); m_uiBerserkTimer = MINUTE*5*IN_MILLISECONDS; } else m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; //Invisible_Timer if (Invisible_Timer <= diff) { me->InterruptSpell(CURRENT_GENERIC_SPELL); SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); me->SetDisplayId(11686); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = true; Invisible_Timer = urand(15000, 30000); } else Invisible_Timer -= diff; if (Invisible) { if (Ambush_Timer <= diff) { Unit* target = NULL; target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (target) { DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); DoCast(target, SPELL_AMBUSH); } Ambushed = true; Ambush_Timer = 3000; } else Ambush_Timer -= diff; } if (Ambushed) { if (Visible_Timer <= diff) { me->InterruptSpell(CURRENT_GENERIC_SPELL); me->SetDisplayId(15268); SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = false; Visible_Timer = 4000; } else Visible_Timer -= diff; } //Resetting some aggro so he attacks other gamers if (!Invisible) { if (Aggro_Timer <= diff) { Unit* target = NULL; target = SelectTarget(SELECT_TARGET_RANDOM, 1); if (DoGetThreat(me->getVictim())) DoModifyThreatPercent(me->getVictim(), -50); if (target) AttackStart(target); Aggro_Timer = urand(7000, 20000); } else Aggro_Timer -= diff; if (ThousandBlades_Timer <= diff) { DoCast(me->getVictim(), SPELL_THOUSANDBLADES); ThousandBlades_Timer = urand(7000, 12000); } else ThousandBlades_Timer -= diff; } DoMeleeAttackIfReady(); }
uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject const* whisperTarget /*= nullptr*/, ChatMsg msgType /*= CHAT_MSG_ADDON*/, Language language /*= LANG_ADDON*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, uint32 sound /*= 0*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/, Player* srcPlr /*= nullptr*/) { if (!source) return 0; CreatureTextMap::const_iterator sList = mTextMap.find(source->GetEntry()); if (sList == mTextMap.end()) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Could not find Text for Creature %s (%s) in 'creature_text' table. Ignoring.", source->GetName().c_str(), source->GetGUID().ToString().c_str()); return 0; } CreatureTextHolder const& textHolder = sList->second; CreatureTextHolder::const_iterator itr = textHolder.find(textGroup); if (itr == textHolder.end()) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Could not find TextGroup %u for Creature %s (%s) in 'creature_text' table. Ignoring.", uint32(textGroup), source->GetName().c_str(), source->GetGUID().ToString().c_str()); return 0; } CreatureTextGroup const& textGroupContainer = itr->second; //has all texts in the group CreatureTextRepeatIds repeatGroup = GetRepeatGroup(source, textGroup);//has all textIDs from the group that were already said CreatureTextGroup tempGroup;//will use this to talk after sorting repeatGroup for (CreatureTextGroup::const_iterator giter = textGroupContainer.begin(); giter != textGroupContainer.end(); ++giter) if (std::find(repeatGroup.begin(), repeatGroup.end(), giter->id) == repeatGroup.end()) tempGroup.push_back(*giter); if (tempGroup.empty()) { source->ClearTextRepeatGroup(textGroup); tempGroup = textGroupContainer; } auto iter = Trinity::Containers::SelectRandomWeightedContainerElement(tempGroup, [](CreatureTextEntry const& t) -> double { return t.probability; }); ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? iter->type : msgType; Language finalLang = (language == LANG_ADDON) ? iter->lang : language; uint32 finalSound = sound ? sound : iter->sound; if (range == TEXT_RANGE_NORMAL) range = iter->TextRange; if (finalSound) SendSound(source, finalSound, finalType, whisperTarget, range, team, gmOnly); Unit* finalSource = source; if (srcPlr) finalSource = srcPlr; if (iter->emote) SendEmote(finalSource, iter->emote); if (srcPlr) { PlayerTextBuilder builder(source, finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, whisperTarget); SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly); } else { CreatureTextBuilder builder(finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, whisperTarget); SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly); } SetRepeatId(source, textGroup, iter->id); return iter->duration; }
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { uint32 opcode = recv_data.GetOpcode(); sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); Unit *mover = _player->m_mover; Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if(plMover && plMover->IsBeingTeleported()) { // movement anticheat plMover->m_anti_JustTeleported = 1; // end movement anticheat return; } /* extract packet */ MovementInfo movementInfo; ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ if(!(movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) && _player->GetVehicleGUID()) { if(mover->GetGUID() == _player->GetGUID()) { return; } } // we sent a movement packet with MOVEMENTFLAG_ONTRANSPORT and we are on vehicle // this can be moving on vehicle or entering another transport (eg. boat) if((movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) && _player->GetVehicleGUID()) { // we are controlling that vehicle if(mover->GetGUID() == _player->GetVehicleGUID()) { // we sent movement packet, related to movement ON vehicle, // but not WITH vehicle, so mover = player if(_player->GetVehicleGUID() == movementInfo.t_guid) { // this is required to avoid client crash, otherwise it will result // in moving with vehicle on the same vehicle and that = crash mover = _player; plMover = _player; } } if(_player->GetVehicleGUID() == movementInfo.t_guid) { _player->m_SeatData.OffsetX = movementInfo.t_x; _player->m_SeatData.OffsetY = movementInfo.t_y; _player->m_SeatData.OffsetZ = movementInfo.t_z; _player->m_SeatData.Orientation = movementInfo.t_o; } } if(recv_data.size() != recv_data.rpos()) { sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); KickPlayer(); return; } if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) return; /* handle special cases */ if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !mover->GetVehicleGUID()) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if( movementInfo.t_x > 60 || movementInfo.t_y > 60 || movementInfo.t_x < -60 || movementInfo.t_y < -60 ) return; if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y, movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) ) return; if (plMover && plMover->m_anti_TransportGUID == 0 && (movementInfo.t_guid !=0)) { // if we boarded a transport, add us to it if (plMover && !plMover->m_transport) { // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.t_guid) { plMover->m_transport = (*iter); (*iter)->AddPassenger(plMover); break; } } } //movement anticheat; //Correct finding GO guid in DB (thanks to GriffonHeart) GameObject *obj = HashMapHolder<GameObject>::Find(movementInfo.t_guid); if(obj) plMover->m_anti_TransportGUID = obj->GetDBTableGUIDLow(); else plMover->m_anti_TransportGUID = GUID_LOPART(movementInfo.t_guid); // end movement anticheat } } else if (plMover && plMover->m_anti_TransportGUID != 0){ if (plMover && plMover->m_transport) // if we were on a transport, leave { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; } movementInfo.t_x = 0.0f; movementInfo.t_y = 0.0f; movementInfo.t_z = 0.0f; movementInfo.t_o = 0.0f; movementInfo.t_time = 0; movementInfo.t_seat = -1; plMover->m_anti_TransportGUID = 0; } // 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 && plMover && !plMover->isInFlight()) { //movement anticheat plMover->m_anti_JustJumped = 0; plMover->m_anti_JumpBaseZ = 0; //end movement anticheat plMover->HandleFall(movementInfo); } if (plMover && (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING) != plMover->IsInWater())) { // now client not include swimming flag in case jumping under water plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); } if (movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING)) { if(mover->GetTypeId() == TYPEID_UNIT) { if(((Creature*)mover)->isVehicle() && !((Creature*)mover)->canSwim()) { // NOTE : we should enter evade mode here, but... ((Vehicle*)mover)->SetSpawnDuration(1); } } } /*----------------------*/ //---- anti-cheat features -->>> bool check_passed = true; #ifdef MOVEMENT_ANTICHEAT_DEBUG if (plMover){ sLog.outBasic("MA-%s > client-time:%d fall-time:%d | xyzo: %f,%f,%fo(%f) flags[%X] opcode[%s]| transport (xyzo): %f,%f,%fo(%f)", plMover->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o, movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o); sLog.outBasic("MA-%s Transport > server GUID: %d | client GUID: (lo)%d - (hi)%d", plMover->GetName(),plMover->m_anti_TransportGUID, GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid)); } else { sLog.outBasic("MA > client-time:%d fall-time:%d | xyzo: %f,%f,%fo(%f) flags[%X] opcode[%s]| transport (xyzo): %f,%f,%fo(%f)", movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o, movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o); sLog.outBasic("MA Transport > server GUID: | client GUID: (lo)%d - (hi)%d", GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid)); } #endif if (plMover && World::GetEnableMvAnticheat()) { //calc time deltas int32 cClientTimeDelta = 1500; if (plMover->m_anti_LastClientTime !=0){ cClientTimeDelta = movementInfo.time - plMover->m_anti_LastClientTime; plMover->m_anti_DeltaClientTime += cClientTimeDelta; plMover->m_anti_LastClientTime = movementInfo.time; } else { plMover->m_anti_LastClientTime = movementInfo.time; } uint32 cServerTime=getMSTime(); uint32 cServerTimeDelta = 1500; if (plMover->m_anti_LastServerTime != 0){ cServerTimeDelta = cServerTime - plMover->m_anti_LastServerTime; plMover->m_anti_DeltaServerTime += cServerTimeDelta; plMover->m_anti_LastServerTime = cServerTime; } else { plMover->m_anti_LastServerTime = cServerTime; } //resync times on client login (first 15 sec for heavy areas) if (plMover->m_anti_DeltaServerTime < 15000 && plMover->m_anti_DeltaClientTime < 15000) plMover->m_anti_DeltaClientTime = plMover->m_anti_DeltaServerTime; int32 sync_time = plMover->m_anti_DeltaClientTime - plMover->m_anti_DeltaServerTime; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outBasic("MA-%s Time > cClientTimeDelta: %d, cServerTime: %d || deltaC: %d - deltaS: %d || SyncTime: %d", plMover->GetName(),cClientTimeDelta, cServerTime, plMover->m_anti_DeltaClientTime, plMover->m_anti_DeltaServerTime, sync_time); #endif //mistiming checks int32 gmd = World::GetMistimingDelta(); if (sync_time > gmd || sync_time < -gmd){ cClientTimeDelta = cServerTimeDelta; plMover->m_anti_MistimingCount++; sLog.outError("MA-%s, mistiming exception. #:%d, mistiming: %dms ", plMover->GetName(), plMover->m_anti_MistimingCount, sync_time); if (plMover->m_anti_MistimingCount > World::GetMistimingAlarms()) { sWorld.SendWorldText(3,"Bye Cheto! ",plMover->GetName()); plMover->GetSession()->KickPlayer(); return; } check_passed = false; } // end mistiming checks uint32 curDest = plMover->m_taxi.GetTaxiDestination(); //check taxi flight if ((plMover->m_anti_TransportGUID == 0) && !curDest) { UnitMoveType move_type; // calculating section --------------------- //current speed if (movementInfo.flags & MOVEMENTFLAG_FLYING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_FLIGHT_BACK : MOVE_FLIGHT; else if (movementInfo.flags & MOVEMENTFLAG_SWIMMING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_SWIM; else if (movementInfo.flags & MOVEMENTFLAG_WALK_MODE) move_type = MOVE_WALK; //hmm... in first time after login player has MOVE_SWIMBACK instead MOVE_WALKBACK else move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_RUN; float current_speed = plMover->GetSpeed(move_type); // end current speed // movement distance float allowed_delta= 0; float delta_x = plMover->GetPositionX() - movementInfo.x; float delta_y = plMover->GetPositionY() - movementInfo.y; float delta_z = plMover->GetPositionZ() - movementInfo.z; float real_delta = delta_x * delta_x + delta_y * delta_y; float tg_z = -99999; //tangens // end movement distance if (cClientTimeDelta < 0) {cClientTimeDelta = 0;} float time_delta = (cClientTimeDelta < 1500) ? (float)cClientTimeDelta/1000 : 1.5f; //normalize time - 1.5 second allowed for heavy loaded server if (!(movementInfo.flags & (MOVEMENTFLAG_FLYING | MOVEMENTFLAG_SWIMMING))) tg_z = (real_delta !=0) ? (delta_z*delta_z / real_delta) : -99999; if (current_speed < plMover->m_anti_Last_HSpeed) { allowed_delta = plMover->m_anti_Last_HSpeed; if (plMover->m_anti_LastSpeedChangeTime == 0 ) plMover->m_anti_LastSpeedChangeTime = movementInfo.time + (uint32)floor(((plMover->m_anti_Last_HSpeed / current_speed) * 1500)) + 100; //100ms above for random fluctuating =))) } else { allowed_delta = current_speed; } allowed_delta = allowed_delta * time_delta; allowed_delta = allowed_delta * allowed_delta + 2; if (tg_z > 2.2) allowed_delta = allowed_delta + (delta_z*delta_z)/2.37; // mountain fall allowed speed if (movementInfo.time>plMover->m_anti_LastSpeedChangeTime) { plMover->m_anti_Last_HSpeed = current_speed; // store current speed plMover->m_anti_Last_VSpeed = -2.3f; if (plMover->m_anti_LastSpeedChangeTime != 0) plMover->m_anti_LastSpeedChangeTime = 0; } // end calculating section --------------------- //AntiGravitation (thanks to Meekro) float JumpHeight = plMover->m_anti_JumpBaseZ - movementInfo.z; if ((plMover->m_anti_JumpBaseZ != 0) && !(movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) && (JumpHeight < plMover->m_anti_Last_VSpeed)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, GraviJump exception. JumpHeight = %f, Allowed Veritcal Speed = %f", plMover->GetName(), JumpHeight, plMover->m_anti_Last_VSpeed); #endif check_passed = false; } //multi jump checks if (opcode == MSG_MOVE_JUMP && !plMover->IsInWater()) { if (plMover->m_anti_JustJumped >= 1){ check_passed = false; //don't process new jump packet } else { plMover->m_anti_JustJumped += 1; plMover->m_anti_JumpBaseZ = movementInfo.z; } } else if (plMover->IsInWater()) { plMover->m_anti_JustJumped = 0; } //speed hack checks if ((real_delta > allowed_delta)) // && (delta_z < 0)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, speed exception | cDelta=%f aDelta=%f | cSpeed=%f lSpeed=%f deltaTime=%f", plMover->GetName(), real_delta, allowed_delta, current_speed, plMover->m_anti_Last_HSpeed,time_delta); #endif check_passed = false; } //teleport hack checks if ((real_delta>4900.0f) && !(real_delta < allowed_delta)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, is teleport exception | cDelta=%f aDelta=%f | cSpeed=%f lSpeed=%f deltaToime=%f", plMover->GetName(),real_delta, allowed_delta, current_speed, plMover->m_anti_Last_HSpeed,time_delta); #endif check_passed = false; } //mountian hack checks // 1.56f (delta_z < GetPlayer()->m_anti_Last_VSpeed)) if ((delta_z < plMover->m_anti_Last_VSpeed) && (plMover->m_anti_JustJumped == 0) && (tg_z > 2.37f)) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, mountain exception | tg_z=%f", plMover->GetName(),tg_z); #endif check_passed = false; } //Fly hack checks if (((movementInfo.flags & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) != 0) && !plMover->isGameMaster() && !(plMover->HasAuraType(SPELL_AURA_FLY) || plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, flight exception. {SPELL_AURA_FLY=[%X]} {SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED=[%X]} {SPELL_AURA_MOD_SPEED_FLIGHT=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK=[%X]}", plMover->GetName(), plMover->HasAuraType(SPELL_AURA_FLY), plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED), plMover->HasAuraType(SPELL_AURA_MOD_SPEED_FLIGHT), plMover->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS), plMover->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK)); #endif check_passed = false; } //Water-Walk checks if (((movementInfo.flags & MOVEMENTFLAG_WATERWALKING) != 0) && !plMover->isGameMaster() && !(plMover->HasAuraType(SPELL_AURA_WATER_WALK) | plMover->HasAuraType(SPELL_AURA_GHOST))) { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, water-walk exception. [%X]{SPELL_AURA_WATER_WALK=[%X]}", plMover->GetName(), movementInfo.flags, plMover->HasAuraType(SPELL_AURA_WATER_WALK)); #endif check_passed = false; } //Teleport To Plane checks if (movementInfo.z < 0.0001f && movementInfo.z > -0.0001f && ((movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) == 0) && !plMover->isGameMaster()) { // Prevent using TeleportToPlan. Map *map = plMover->GetMap(); if (map){ float plane_z = map->GetHeight(movementInfo.x, movementInfo.y, MAX_HEIGHT) - movementInfo.z; plane_z = (plane_z < -500.0f) ? 0 : plane_z; //check holes in heigth map if(plane_z > 0.1f || plane_z < -0.1f) { plMover->m_anti_TeleToPlane_Count++; check_passed = false; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outDebug("MA-%s, teleport to plan exception. plane_z: %f ", plMover->GetName(), plane_z); #endif if (plMover->m_anti_TeleToPlane_Count > World::GetTeleportToPlaneAlarms()) { sLog.outError("MA-%s, teleport to plan exception. Exception count: %d ", plMover->GetName(), plMover->m_anti_TeleToPlane_Count); sWorld.SendWorldText(3,"Bye Cheto! ",plMover->GetName()); plMover->GetSession()->KickPlayer(); return; } } } } else { if (plMover->m_anti_TeleToPlane_Count != 0) plMover->m_anti_TeleToPlane_Count = 0; } } else if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) { //antiwrap checks if (plMover->m_transport) { float trans_rad = movementInfo.t_x*movementInfo.t_x + movementInfo.t_y*movementInfo.t_y + movementInfo.t_z*movementInfo.t_z; if (trans_rad > 3600.0f){ check_passed = false; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, leave transport.", plMover->GetName()); #endif } } else { if (GameObjectData const* go_data = objmgr.GetGOData(plMover->m_anti_TransportGUID)) { float delta_gox = go_data->posX - movementInfo.x; float delta_goy = go_data->posY - movementInfo.y; float delta_goz = go_data->posZ - movementInfo.z; int mapid = go_data->mapid; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outDebug("MA-%s, transport movement. GO xyzo: %f,%f,%f", plMover->GetName(), go_data->posX,go_data->posY,go_data->posZ); #endif if (plMover->GetMapId() != mapid){ check_passed = false; } else if (mapid !=369) { float delta_go = delta_gox*delta_gox + delta_goy*delta_goy; if (delta_go > 3600.0f) { check_passed = false; #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outError("MA-%s, leave transport. GO xyzo: %f,%f,%f", plMover->GetName(), go_data->posX,go_data->posY,go_data->posZ); #endif } } } else { #ifdef MOVEMENT_ANTICHEAT_DEBUG sLog.outDebug("MA-%s, undefined transport.", plMover->GetName()); #endif check_passed = false; } } if (!check_passed){ if (plMover->m_transport) { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; } movementInfo.t_x = 0.0f; movementInfo.t_y = 0.0f; movementInfo.t_z = 0.0f; movementInfo.t_o = 0.0f; movementInfo.t_time = 0; plMover->m_anti_TransportGUID = 0; } } } /* process position-change */ if (check_passed) { recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2) WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size())); data.append(mover->GetPackGUID()); // use mover guid data.append(recv_data.contents(), recv_data.size()); GetPlayer()->SendMessageToSet(&data, false); if(plMover) // nothing is charmed, or player charmed { plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); plMover->m_movementInfo = movementInfo; plMover->UpdateFallInformationIfNeed(movementInfo, recv_data.GetOpcode()); if(plMover->isMovingOrTurning()) plMover->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if(movementInfo.z < -500.0f) { if(plMover->InBattleGround() && plMover->GetBattleGround() && plMover->GetBattleGround()->HandlePlayerUnderMap(_player)) { // do nothing, the handle already did if returned true } else { // 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(plMover->isAlive()) { plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // pl can be alive if GM/etc if(!plMover->isAlive()) { // change the death state to CORPSE to prevent the death timer from // starting in the next player update plMover->KillPlayer(); plMover->BuildPlayerRepop(); } } // cancel the death timer here if started plMover->RepopAtGraveyard(); } } //movement anticheat >>> if (plMover->m_anti_AlarmCount > 0){ sLog.outError("MA-%s produce %d anticheat alarms",plMover->GetName(),plMover->m_anti_AlarmCount); plMover->m_anti_AlarmCount = 0; } // end movement anticheat } else // creature charmed { if(mover->IsInWorld()) { mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); if(((Creature*)mover)->isVehicle()) ((Vehicle*)mover)->RellocatePassengers(mover->GetMap()); } } } else if (plMover) { plMover->m_anti_AlarmCount++; WorldPacket data; //GetPlayer()->m_movementInfo.SetMovementFlags(MovementFlags(MOVEMENTFLAG_NONE)); plMover->m_movementInfo.SetMovementFlags(MovementFlags(MOVEMENTFLAG_NONE)); plMover->BuildTeleportAckMsg(&data, plMover->GetPositionX(), plMover->GetPositionY(), plMover->GetPositionZ(), plMover->GetOrientation()); plMover->GetSession()->SendPacket(&data); plMover->BuildHeartBeatMsg(&data); plMover->SendMessageToSet(&data, true); } }
void WorldSession::HandleGetMirrorimageData(WorldPacket& recv_data) { DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "WORLD: CMSG_GET_MIRRORIMAGE_DATA"); ObjectGuid guid; recv_data >> guid; Creature* pCreature = _player->GetMap()->GetAnyTypeCreature(guid); if (!pCreature) return; Unit::AuraList const& images = pCreature->GetAurasByType(SPELL_AURA_MIRROR_IMAGE); if (images.empty()) return; Unit* pCaster = images.front()->GetCaster(); WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68); data << guid; data << (uint32)pCreature->GetDisplayId(); data << (uint8)pCreature->getRace(); data << (uint8)pCreature->getGender(); data << (uint8)pCreature->getClass(); if (pCaster && pCaster->GetTypeId() == TYPEID_PLAYER) { Player* pPlayer = (Player*)pCaster; // skin, face, hair, haircolor data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 0); data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 1); data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 2); data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 3); // facial hair data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES_2, 0); // guild id data << (uint32)pPlayer->GetGuildId(); if (pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) data << (uint32)0; else data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_HEAD); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_SHOULDERS); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_BODY); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_CHEST); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_WAIST); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_LEGS); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_FEET); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_WRISTS); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_HANDS); if (pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) data << (uint32)0; else data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_BACK); data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TABARD); } else { // pCaster may have been NULL (usually not expected, but may happen at disconnect, etc) // OR // pCaster is not player, data is taken from CreatureDisplayInfoExtraEntry by model already data << (uint8)0; data << (uint8)0; data << (uint8)0; data << (uint8)0; data << (uint8)0; data << (uint32)0; for (int i = 0; i < 11; ++i) data << (uint32)0; } SendPacket(&data); }
void UpdateAI(const uint32 uiDiff) { Creature * Valiona = GetValiona(); if (!UpdateVictim()) return; if (uiPhaseTimer <= uiDiff) { uiPhaseTimer = 900000; switch (uiPhase) { case 1: uiPhase = 2; Valiona->AI()->DoAction(ACTION_VALIONA_AIRBORNE); Valiona->SetHealth(me->GetHealth()); break; case 3: uiPhase = 1; me->SetHealth(Valiona->GetHealth()); break; } } else uiPhaseTimer -= uiDiff; switch (uiPhase) { case 1: if (uiEngulfingMagicTimer <= uiDiff && uiEngulfingMagicTimer <=2) { uiEngulfingMagicTimer = 180000; uiEngulfingMagicCount++; Unit * Target = SelectTarget(SELECT_TARGET_RANDOM); DoCast(Target,SPELL_ENGULFING_MAGIC); } else uiEngulfingMagicTimer -= uiDiff; if (uiFabulousFlamesTimer <= uiDiff) { DoCast(SPELL_FABILOUS_FLAMES); } else uiFabulousFlamesTimer -= uiDiff; DoMeleeAttackIfReady(); case 2: if (uiDazzlingDestructionTimer <= uiDiff && uiDazzlingDestructionCount <= MAX_DAZZLIN_DESTRUCTION) { Unit * Target = SelectTarget(SELECT_TARGET_RANDOM); me->CastSpell(Target->GetPositionX(),Target->GetPositionY(),Target->GetPositionZ(),SPELL_DAZZLING_DESTRUCTION_SUMMON,false); uiDazzlingDestructionTimer = 2000; uiDazzlingDestructionCount++; } else uiDazzlingDestructionTimer -= uiDiff; if (uiDazzlingDestructionCount == MAX_DAZZLIN_DESTRUCTION) { std::list<uint64>::iterator itr; for (itr=summons.begin();itr!=summons.end();++itr) { if (Creature * Destruction = ObjectAccessor::GetCreature(*me,*itr)) DoCast(Destruction,SPELL_DAZZLING_DESTRUCTION_MISSILE); } } case 3: if (uiTwilightBlastTimer <= uiDiff) { uiTwilightBlastTimer = 3000; me->SummonCreature(NPC_THERALION_FLIGHT_TARGET_STALKER,me->getVictim()->GetPositionX(),me->getVictim()->GetPositionY(),me->getVictim()->GetPositionZ(),0.0f,TEMPSUMMON_MANUAL_DESPAWN); } else uiTwilightBlastTimer -= uiDiff; } }
Unit * DockToSavedBases( int playernum, QVector &safevec ) { string str = game_options.startDockedTo; Unit *plr = _Universe->AccessCockpit( playernum )->GetParent(); if ( !plr || !plr->getStarSystem() ) { safevec = QVector( 0, 0, 0 ); return NULL; } vector< string >strs = loadStringList( playernum, mission_key ); if ( strs.size() ) str = strs[0]; Unit *closestUnit = NULL; float lastdist = 0; float dist = 0; Unit *un; QVector dock_position( plr->curr_physical_state.position ); for (un_iter iter = plr->getStarSystem()->getUnitList().createIterator(); (un = *iter); ++iter) if (un->name == str || un->getFullname() == str) { dist = UnitUtil::getSignificantDistance( plr, un ); if (closestUnit == NULL || dist < lastdist) { lastdist = dist; closestUnit = un; } } if (closestUnit) { if (UnitUtil::getSignificantDistance( plr, closestUnit ) > 0 && closestUnit->isUnit() != PLANETPTR) dock_position = closestUnit->Position(); dock_position = UniverseUtil::SafeEntrancePoint( dock_position, plr->rSize() ); plr->SetPosAndCumPos( dock_position ); vector< DockingPorts >dprt = closestUnit->pImage->dockingports; unsigned int i; for (i = 0;; i++) { if ( i >= dprt.size() ) { safevec = QVector( 0, 0, 0 ); return NULL; } if (!dprt[i].IsOccupied()) break; } plr->ForceDock( closestUnit, i ); closestUnit->pImage->clearedunits.push_back( plr ); closestUnit->RequestPhysics(); _Universe->AccessCockpit( playernum )->retry_dock = 0; } else { if (_Universe->AccessCockpit( playernum )->retry_dock == 0) _Universe->AccessCockpit( playernum )->retry_dock = 128; else _Universe->AccessCockpit( playernum )->retry_dock -= 1; } safevec = dock_position; return ( closestUnit && closestUnit->isDocked( plr ) ) ? closestUnit : NULL; }
void hyjalAI::UpdateAI(uint32 diff) { if (IsDummy) { if (MassTeleportTimer < diff && DoMassTeleport) { DoCast(me, SPELL_MASS_TELEPORT, false); DoMassTeleport = false; } else MassTeleportTimer -= diff; return; } if (DoHide) { DoHide = false; switch (me->GetEntry()) { case JAINA: if (instance->GetData(DATA_ALLIANCE_RETREAT)) { me->SetVisible(false); HideNearPos(me->GetPositionX(), me->GetPositionY()); HideNearPos(5037.76f, -1889.71f); for (uint8 i = 0; i < 92; ++i)//summon fires me->SummonGameObject(GO_ROARING_FLAME, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7], 0); } else me->SetVisible(true); break; case THRALL: //thrall if (instance->GetData(DATA_HORDE_RETREAT)) { me->SetVisible(false); HideNearPos(me->GetPositionX(), me->GetPositionY()); HideNearPos(5563, -2763.19f); HideNearPos(5542.2f, -2629.36f); for (uint8 i = 0; i < 65; ++i)//summon fires me->SummonGameObject(GO_ROARING_FLAME, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7], 0); } else me->SetVisible(true); break; } } if (DoRespawn) { if (RespawnTimer <= diff) { DoRespawn = false; RespawnNearPos(me->GetPositionX(), me->GetPositionY()); if (Faction == 0) { RespawnNearPos(5037.76f, -1889.71f); } else if (Faction == 1) { RespawnNearPos(5563, -2763.19f); RespawnNearPos(5542.2f, -2629.36f); } me->SetVisible(true); }else{ RespawnTimer -= diff; me->SetVisible(false); } return; } if (Overrun) DoOverrun(Faction, diff); if (bRetreat) { if (RetreatTimer <= diff) { IsDummy = true; bRetreat = false; HideNearPos(me->GetPositionX(), me->GetPositionY()); switch (me->GetEntry()) { case JAINA://jaina HideNearPos(5037.76f, -1889.71f); break; case THRALL://thrall HideNearPos(5563, -2763.19f); HideNearPos(5542.2f, -2629.36f); HideNearPos(5603.75f, -2853.12f); break; } me->SetVisible(false); } else RetreatTimer -= diff; } if (!EventBegun) return; if (Summon) { if (EnemyCount) { EnemyCount = instance->GetData(DATA_TRASH); if (!EnemyCount) NextWaveTimer = 5000; } if (NextWaveTimer <= diff) { if (Faction == 0) SummonNextWave(AllianceWaves, WaveCount, AllianceBase); else if (Faction == 1) SummonNextWave(HordeWaves, WaveCount, HordeBase); ++WaveCount; } else NextWaveTimer -= diff; } if (CheckTimer <= diff) { for (uint8 i = 0; i < 2; ++i) { if (BossGUID[i]) { Unit* unit = ObjectAccessor::GetUnit(*me, BossGUID[i]); if (unit && (!unit->IsAlive())) { if (BossGUID[i] == BossGUID[0]) { Talk(INCOMING); FirstBossDead = true; } else if (BossGUID[i] == BossGUID[1]) { Talk(SUCCESS); SecondBossDead = true; } EventBegun = false; CheckTimer = 0; me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); BossGUID[i].Clear(); instance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it } } } CheckTimer = 5000; } else CheckTimer -= diff; if (!UpdateVictim()) return; for (uint8 i = 0; i < HYJAL_AI_MAX_SPELLS; ++i) { if (Spells[i].SpellId) { if (SpellTimer[i] <= diff) { if (me->IsNonMeleeSpellCast(false)) me->InterruptNonMeleeSpells(false); Unit* target = NULL; switch (Spells[i].TargetType) { case TARGETTYPE_SELF: target = me; break; case TARGETTYPE_RANDOM: target = SelectTarget(SELECT_TARGET_RANDOM, 0); break; case TARGETTYPE_VICTIM: target = me->GetVictim(); break; } if (target && target->IsAlive()) { DoCast(target, Spells[i].SpellId); SpellTimer[i] = Spells[i].Cooldown; } } else SpellTimer[i] -= diff; } } DoMeleeAttackIfReady(); }
/// Process queued scripts void Map::ScriptsProcess() { if (m_scriptSchedule.empty()) return; ///- Process overdue queued scripts ScriptScheduleMap::iterator iter = m_scriptSchedule.begin(); // ok as multimap is a *sorted* associative container while (!m_scriptSchedule.empty() && (iter->first <= sWorld->GetGameTime())) { ScriptAction const& step = iter->second; Object* source = NULL; if (step.sourceGUID) { switch (GUID_HIPART(step.sourceGUID)) { case HIGHGUID_ITEM: // as well as HIGHGUID_CONTAINER if (Player* player = HashMapHolder<Player>::Find(step.ownerGUID)) source = player->GetItemByGuid(step.sourceGUID); break; case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: source = HashMapHolder<Creature>::Find(step.sourceGUID); break; case HIGHGUID_PET: source = HashMapHolder<Pet>::Find(step.sourceGUID); break; case HIGHGUID_PLAYER: source = HashMapHolder<Player>::Find(step.sourceGUID); break; case HIGHGUID_GAMEOBJECT: source = HashMapHolder<GameObject>::Find(step.sourceGUID); break; case HIGHGUID_CORPSE: source = HashMapHolder<Corpse>::Find(step.sourceGUID); break; case HIGHGUID_MO_TRANSPORT: for (MapManager::TransportSet::iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == step.sourceGUID) { source = *iter; break; } } break; default: sLog->outError("%s source with unsupported high guid (GUID: " UI64FMTD ", high guid: %u).", step.script->GetDebugInfo().c_str(), step.sourceGUID, GUID_HIPART(step.sourceGUID)); break; } } Object* target = NULL; if (step.targetGUID) { switch (GUID_HIPART(step.targetGUID)) { case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: target = HashMapHolder<Creature>::Find(step.targetGUID); break; case HIGHGUID_PET: target = HashMapHolder<Pet>::Find(step.targetGUID); break; case HIGHGUID_PLAYER: // empty GUID case also target = HashMapHolder<Player>::Find(step.targetGUID); break; case HIGHGUID_GAMEOBJECT: target = HashMapHolder<GameObject>::Find(step.targetGUID); break; case HIGHGUID_CORPSE: target = HashMapHolder<Corpse>::Find(step.targetGUID); break; default: sLog->outError("%s target with unsupported high guid (GUID: " UI64FMTD ", high guid: %u).", step.script->GetDebugInfo().c_str(), step.targetGUID, GUID_HIPART(step.targetGUID)); break; } } switch (step.script->command) { case SCRIPT_COMMAND_TALK: if (step.script->Talk.ChatType > CHAT_TYPE_WHISPER && step.script->Talk.ChatType != CHAT_MSG_RAID_BOSS_WHISPER) { sLog->outError("%s invalid chat type (%u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->Talk.ChatType); break; } if (step.script->Talk.Flags & SF_TALK_USE_PLAYER) { if (Player* pSource = _GetScriptPlayerSourceOrTarget(source, target, step.script)) { LocaleConstant loc_idx = pSource->GetSession()->GetSessionDbLocaleIndex(); std::string text(sObjectMgr->GetTrinityString(step.script->Talk.TextID, loc_idx)); switch (step.script->Talk.ChatType) { case CHAT_TYPE_SAY: pSource->Say(text, LANG_UNIVERSAL); break; case CHAT_TYPE_YELL: pSource->Yell(text, LANG_UNIVERSAL); break; case CHAT_TYPE_TEXT_EMOTE: case CHAT_TYPE_BOSS_EMOTE: pSource->TextEmote(text); break; case CHAT_TYPE_WHISPER: case CHAT_MSG_RAID_BOSS_WHISPER: { uint64 targetGUID = target ? target->GetGUID() : 0; if (!targetGUID || !IS_PLAYER_GUID(targetGUID)) sLog->outError("%s attempt to whisper to non-player unit, skipping.", step.script->GetDebugInfo().c_str()); else pSource->Whisper(text, LANG_UNIVERSAL, targetGUID); break; } default: break; // must be already checked at load } } } else { // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { uint64 targetGUID = target ? target->GetGUID() : 0; switch (step.script->Talk.ChatType) { case CHAT_TYPE_SAY: cSource->Say(step.script->Talk.TextID, LANG_UNIVERSAL, targetGUID); break; case CHAT_TYPE_YELL: cSource->Yell(step.script->Talk.TextID, LANG_UNIVERSAL, targetGUID); break; case CHAT_TYPE_TEXT_EMOTE: cSource->TextEmote(step.script->Talk.TextID, targetGUID); break; case CHAT_TYPE_BOSS_EMOTE: cSource->MonsterTextEmote(step.script->Talk.TextID, targetGUID, true); break; case CHAT_TYPE_WHISPER: if (!targetGUID || !IS_PLAYER_GUID(targetGUID)) sLog->outError("%s attempt to whisper to non-player unit, skipping.", step.script->GetDebugInfo().c_str()); else cSource->Whisper(step.script->Talk.TextID, targetGUID); break; case CHAT_MSG_RAID_BOSS_WHISPER: if (!targetGUID || !IS_PLAYER_GUID(targetGUID)) sLog->outError("%s attempt to raidbosswhisper to non-player unit, skipping.", step.script->GetDebugInfo().c_str()); else cSource->MonsterWhisper(step.script->Talk.TextID, targetGUID, true); break; default: break; // must be already checked at load } } } break; case SCRIPT_COMMAND_EMOTE: // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { if (step.script->Emote.Flags & SF_EMOTE_USE_STATE) cSource->SetUInt32Value(UNIT_NPC_EMOTESTATE, step.script->Emote.EmoteID); else cSource->HandleEmoteCommand(step.script->Emote.EmoteID); } break; case SCRIPT_COMMAND_FIELD_SET: // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { // Validate field number. if (step.script->FieldSet.FieldID <= OBJECT_FIELD_ENTRY || step.script->FieldSet.FieldID >= cSource->GetValuesCount()) sLog->outError("%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->FieldSet.FieldID, cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUIDLow()); else cSource->SetUInt32Value(step.script->FieldSet.FieldID, step.script->FieldSet.FieldValue); } break; case SCRIPT_COMMAND_MOVE_TO: // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { cSource->SendMonsterMoveWithSpeed(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, step.script->MoveTo.TravelTime); cSource->GetMap()->CreatureRelocation(cSource, step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, 0); } break; case SCRIPT_COMMAND_FLAG_SET: // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { // Validate field number. if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount()) sLog->outError("%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID, source->GetValuesCount(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); else cSource->SetFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue); } break; case SCRIPT_COMMAND_FLAG_REMOVE: // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { // Validate field number. if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount()) sLog->outError("%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID, source->GetValuesCount(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); else cSource->RemoveFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue); } break; case SCRIPT_COMMAND_TELEPORT_TO: if (step.script->TeleportTo.Flags & SF_TELEPORT_USE_CREATURE) { // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script, true)) cSource->NearTeleportTo(step.script->TeleportTo.DestX, step.script->TeleportTo.DestY, step.script->TeleportTo.DestZ, step.script->TeleportTo.Orientation); } else { // Source or target must be Player. if (Player* pSource = _GetScriptPlayerSourceOrTarget(source, target, step.script)) pSource->TeleportTo(step.script->TeleportTo.MapID, step.script->TeleportTo.DestX, step.script->TeleportTo.DestY, step.script->TeleportTo.DestZ, step.script->TeleportTo.Orientation); } break; case SCRIPT_COMMAND_QUEST_EXPLORED: { if (!source) { sLog->outError("%s source object is NULL.", step.script->GetDebugInfo().c_str()); break; } if (!target) { sLog->outError("%s target object is NULL.", step.script->GetDebugInfo().c_str()); break; } // when script called for item spell casting then target == (unit or GO) and source is player WorldObject* worldObject; Player* plrTarget = target->ToPlayer(); if (plrTarget) { if (source->GetTypeId() != TYPEID_UNIT && source->GetTypeId() != TYPEID_GAMEOBJECT && source->GetTypeId() != TYPEID_PLAYER) { sLog->outError("%s source is not unit, gameobject or player (TypeId: %u, Entry: %u, GUID: %u), skipping.", step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); break; } worldObject = dynamic_cast<WorldObject*>(source); } else { plrTarget = source->ToPlayer(); if (plrTarget) { if (target->GetTypeId() != TYPEID_UNIT && target->GetTypeId() != TYPEID_GAMEOBJECT && target->GetTypeId() != TYPEID_PLAYER) { sLog->outError("%s target is not unit, gameobject or player (TypeId: %u, Entry: %u, GUID: %u), skipping.", step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow()); break; } worldObject = dynamic_cast<WorldObject*>(target); } else { sLog->outError("%s neither source nor target is player (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.", step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow()); break; } } // quest id and flags checked at script loading if ((worldObject->GetTypeId() != TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) && (step.script->QuestExplored.Distance == 0 || worldObject->IsWithinDistInMap(plrTarget, float(step.script->QuestExplored.Distance)))) plrTarget->AreaExploredOrEventHappens(step.script->QuestExplored.QuestID); else plrTarget->FailQuest(step.script->QuestExplored.QuestID); break; } case SCRIPT_COMMAND_KILL_CREDIT: // Source or target must be Player. if (Player* pSource = _GetScriptPlayerSourceOrTarget(source, target, step.script)) { if (step.script->KillCredit.Flags & SF_KILLCREDIT_REWARD_GROUP) pSource->RewardPlayerAndGroupAtEvent(step.script->KillCredit.CreatureEntry, pSource); else pSource->KilledMonsterCredit(step.script->KillCredit.CreatureEntry, 0); } break; case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: if (!step.script->RespawnGameobject.GOGuid) { sLog->outError("%s gameobject guid (datalong) is not specified.", step.script->GetDebugInfo().c_str()); break; } // Source or target must be WorldObject. if (WorldObject* pSummoner = _GetScriptWorldObject(source, true, step.script)) { GameObject* pGO = _FindGameObject(pSummoner, step.script->RespawnGameobject.GOGuid); if (!pGO) { sLog->outError("%s gameobject was not found (guid: %u).", step.script->GetDebugInfo().c_str(), step.script->RespawnGameobject.GOGuid); break; } if (pGO->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE || pGO->GetGoType() == GAMEOBJECT_TYPE_DOOR || pGO->GetGoType() == GAMEOBJECT_TYPE_BUTTON || pGO->GetGoType() == GAMEOBJECT_TYPE_TRAP) { sLog->outError("%s can not be used with gameobject of type %u (guid: %u).", step.script->GetDebugInfo().c_str(), uint32(pGO->GetGoType()), step.script->RespawnGameobject.GOGuid); break; } // Check that GO is not spawned if (!pGO->isSpawned()) { int32 nTimeToDespawn = std::max(5, int32(step.script->RespawnGameobject.DespawnDelay)); pGO->SetLootState(GO_READY); pGO->SetRespawnTime(nTimeToDespawn); pGO->GetMap()->AddToMap(pGO); } } break; case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: { // Source must be WorldObject. if (WorldObject* pSummoner = _GetScriptWorldObject(source, true, step.script)) { if (!step.script->TempSummonCreature.CreatureEntry) sLog->outError("%s creature entry (datalong) is not specified.", step.script->GetDebugInfo().c_str()); else { float x = step.script->TempSummonCreature.PosX; float y = step.script->TempSummonCreature.PosY; float z = step.script->TempSummonCreature.PosZ; float o = step.script->TempSummonCreature.Orientation; if (!pSummoner->SummonCreature(step.script->TempSummonCreature.CreatureEntry, x, y, z, o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, step.script->TempSummonCreature.DespawnDelay)) sLog->outError("%s creature was not spawned (entry: %u).", step.script->GetDebugInfo().c_str(), step.script->TempSummonCreature.CreatureEntry); } } break; } case SCRIPT_COMMAND_OPEN_DOOR: case SCRIPT_COMMAND_CLOSE_DOOR: _ScriptProcessDoor(source, target, step.script); break; case SCRIPT_COMMAND_ACTIVATE_OBJECT: // Source must be Unit. if (Unit* pSource = _GetScriptUnit(source, true, step.script)) { // Target must be GameObject. if (!target) { sLog->outError("%s target object is NULL.", step.script->GetDebugInfo().c_str()); break; } if (target->GetTypeId() != TYPEID_GAMEOBJECT) { sLog->outError("%s target object is not gameobject (TypeId: %u, Entry: %u, GUID: %u), skipping.", step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow()); break; } if (GameObject* pGO = target->ToGameObject()) pGO->Use(pSource); } break; case SCRIPT_COMMAND_REMOVE_AURA: { // Source (datalong2 != 0) or target (datalong2 == 0) must be Unit. bool bReverse = step.script->RemoveAura.Flags & SF_REMOVEAURA_REVERSE; if (Unit* pTarget = _GetScriptUnit(bReverse ? source : target, bReverse, step.script)) pTarget->RemoveAurasDueToSpell(step.script->RemoveAura.SpellID); break; } case SCRIPT_COMMAND_CAST_SPELL: { // TODO: Allow gameobjects to be targets and casters if (!source && !target) { sLog->outError("%s source and target objects are NULL.", step.script->GetDebugInfo().c_str()); break; } Unit* uSource = NULL; Unit* uTarget = NULL; // source/target cast spell at target/source (script->datalong2: 0: s->t 1: s->s 2: t->t 3: t->s switch (step.script->CastSpell.Flags) { case SF_CASTSPELL_SOURCE_TO_TARGET: // source -> target uSource = source ? source->ToUnit() : NULL; uTarget = target ? target->ToUnit() : NULL; break; case SF_CASTSPELL_SOURCE_TO_SOURCE: // source -> source uSource = source ? source->ToUnit() : NULL; uTarget = uSource; break; case SF_CASTSPELL_TARGET_TO_TARGET: // target -> target uSource = target ? target->ToUnit() : NULL; uTarget = uSource; break; case SF_CASTSPELL_TARGET_TO_SOURCE: // target -> source uSource = target ? target->ToUnit() : NULL; uTarget = source ? source->ToUnit() : NULL; break; case SF_CASTSPELL_SEARCH_CREATURE: // source -> creature with entry uSource = source ? source->ToUnit() : NULL; uTarget = uSource ? GetClosestCreatureWithEntry(uSource, abs(step.script->CastSpell.CreatureEntry), step.script->CastSpell.SearchRadius) : NULL; break; } if (!uSource || !uSource->isType(TYPEMASK_UNIT)) { sLog->outError("%s no source unit found for spell %u", step.script->GetDebugInfo().c_str(), step.script->CastSpell.SpellID); break; } if (!uTarget || !uTarget->isType(TYPEMASK_UNIT)) { sLog->outError("%s no target unit found for spell %u", step.script->GetDebugInfo().c_str(), step.script->CastSpell.SpellID); break; } bool triggered = (step.script->CastSpell.Flags != 4) ? step.script->CastSpell.CreatureEntry & SF_CASTSPELL_TRIGGERED : step.script->CastSpell.CreatureEntry < 0; uSource->CastSpell(uTarget, step.script->CastSpell.SpellID, triggered); break; } case SCRIPT_COMMAND_PLAY_SOUND: // Source must be WorldObject. if (WorldObject* pSource = _GetScriptWorldObject(source, true, step.script)) { // PlaySound.Flags bitmask: 0/1=anyone/target Player* pTarget = NULL; if (step.script->PlaySound.Flags & SF_PLAYSOUND_TARGET_PLAYER) { // Target must be Player. pTarget = _GetScriptPlayer(target, false, step.script); if (!pTarget) break; } // PlaySound.Flags bitmask: 0/2=without/with distance dependent if (step.script->PlaySound.Flags & SF_PLAYSOUND_DISTANCE_SOUND) pSource->PlayDistanceSound(step.script->PlaySound.SoundID, pTarget); else pSource->PlayDirectSound(step.script->PlaySound.SoundID, pTarget); } break; case SCRIPT_COMMAND_CREATE_ITEM: // Target or source must be Player. if (Player* pReceiver = _GetScriptPlayerSourceOrTarget(source, target, step.script)) { ItemPosCountVec dest; InventoryResult msg = pReceiver->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, step.script->CreateItem.ItemEntry, step.script->CreateItem.Amount); if (msg == EQUIP_ERR_OK) { if (Item* item = pReceiver->StoreNewItem(dest, step.script->CreateItem.ItemEntry, true)) pReceiver->SendNewItem(item, step.script->CreateItem.Amount, false, true); } else pReceiver->SendEquipError(msg, NULL, NULL, step.script->CreateItem.ItemEntry); } break; case SCRIPT_COMMAND_DESPAWN_SELF: // Target or source must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script, true)) cSource->DespawnOrUnsummon(step.script->DespawnSelf.DespawnDelay); break; case SCRIPT_COMMAND_LOAD_PATH: // Source must be Unit. if (Unit* pSource = _GetScriptUnit(source, true, step.script)) { if (!sWaypointMgr->GetPath(step.script->LoadPath.PathID)) sLog->outError("%s source object has an invalid path (%u), skipping.", step.script->GetDebugInfo().c_str(), step.script->LoadPath.PathID); else pSource->GetMotionMaster()->MovePath(step.script->LoadPath.PathID, step.script->LoadPath.IsRepeatable); } break; case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT: { if (!step.script->CallScript.CreatureEntry) { sLog->outError("%s creature entry is not specified, skipping.", step.script->GetDebugInfo().c_str()); break; } if (!step.script->CallScript.ScriptID) { sLog->outError("%s script id is not specified, skipping.", step.script->GetDebugInfo().c_str()); break; } Creature* cTarget = NULL; if (source) //using grid searcher { WorldObject* wSource = dynamic_cast <WorldObject*> (source); CellCoord p(Trinity::ComputeCellCoord(wSource->GetPositionX(), wSource->GetPositionY())); Cell cell(p); Trinity::CreatureWithDbGUIDCheck target_check(wSource, step.script->CallScript.CreatureEntry); Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(wSource, cTarget, target_check); TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker); cell.Visit(p, unit_checker, *wSource->GetMap(), *wSource, wSource->GetGridActivationRange()); } else //check hashmap holders { if (CreatureData const* data = sObjectMgr->GetCreatureData(step.script->CallScript.CreatureEntry)) cTarget = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->CallScript.CreatureEntry, data->id, HIGHGUID_UNIT), cTarget); } if (!cTarget) { sLog->outError("%s target was not found (entry: %u)", step.script->GetDebugInfo().c_str(), step.script->CallScript.CreatureEntry); break; } //Lets choose our ScriptMap map ScriptMapMap* datamap = GetScriptsMapByType(ScriptsType(step.script->CallScript.ScriptType)); //if no scriptmap present... if (!datamap) { sLog->outError("%s unknown scriptmap (%u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->CallScript.ScriptType); break; } // Insert script into schedule but do not start it ScriptsStart(*datamap, step.script->CallScript.ScriptID, cTarget, NULL); break; } case SCRIPT_COMMAND_KILL: // Source or target must be Creature. if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script)) { if (cSource->isDead()) sLog->outError("%s creature is already dead (Entry: %u, GUID: %u)", step.script->GetDebugInfo().c_str(), cSource->GetEntry(), cSource->GetGUIDLow()); else { cSource->setDeathState(JUST_DIED); if (step.script->Kill.RemoveCorpse == 1) cSource->RemoveCorpse(); } } break; case SCRIPT_COMMAND_ORIENTATION: // Source must be Unit. if (Unit* pSource = _GetScriptUnit(source, true, step.script)) { if (step.script->Orientation.Flags& SF_ORIENTATION_FACE_TARGET) { // Target must be Unit. Unit* pTarget = _GetScriptUnit(target, false, step.script); if (!pTarget) break; pSource->SetInFront(pTarget); } else pSource->SetOrientation(step.script->Orientation.Orientation); pSource->SendMovementFlagUpdate(); } break; case SCRIPT_COMMAND_EQUIP: // Source must be Creature. if (Creature* cSource = _GetScriptCreature(source, true, step.script)) cSource->LoadEquipment(step.script->Equip.EquipmentID); break; case SCRIPT_COMMAND_MODEL: // Source must be Creature. if (Creature* cSource = _GetScriptCreature(source, true, step.script)) cSource->SetDisplayId(step.script->Model.ModelID); break; case SCRIPT_COMMAND_CLOSE_GOSSIP: // Source must be Player. if (Player* pSource = _GetScriptPlayer(source, true, step.script)) pSource->PlayerTalkClass->SendCloseGossip(); break; case SCRIPT_COMMAND_PLAYMOVIE: // Source must be Player. if (Player* pSource = _GetScriptPlayer(source, true, step.script)) pSource->SendMovieStart(step.script->PlayMovie.MovieID); break; default: sLog->outError("Unknown script command %s.", step.script->GetDebugInfo().c_str()); break; } m_scriptSchedule.erase(iter); iter = m_scriptSchedule.begin(); sScriptMgr->DecreaseScheduledScriptCount(); } }
//--------- Begin of function Town::form_new_nation ---------// // // This independent town forms a new nation. // // Return: <int> // int Town::form_new_nation() { err_when( nation_recno ); if( !nation_array.can_form_new_ai_nation() ) return 0; //----- determine the race with most population -----// int maxPop=0, raceId=0; int i; for( i=0 ; i<MAX_RACE ; i++ ) { if( race_pop_array[i] > maxPop ) { maxPop = race_pop_array[i]; raceId = i+1; } } err_when( !raceId ); //---- create the king of the new nation ----// int unitId = race_res[raceId]->basic_unit_id; int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id]; if( !world.locate_space( xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height ) ) return 0; //--------- create a new nation ---------// int nationRecno = nation_array.new_nation( NATION_AI, raceId, nation_array.random_unused_color() ); err_when( !nationRecno ); //-------- create the king --------// int kingUnitRecno = unit_array.add_unit( unitId, nationRecno, RANK_KING, 100, xLoc, yLoc ); Unit* kingUnit = unit_array[kingUnitRecno]; kingUnit->skill.skill_id = SKILL_LEADING; kingUnit->skill.skill_level = 50+misc.random(51); kingUnit->set_combat_level(70+misc.random(31)); nation_array[nationRecno]->set_king(kingUnitRecno, 1); // 1-this is the first king of the nation dec_pop(raceId, 0); // 0-the unit doesn't have a job //------ set the nation of the rebel town -----// err_when( rebel_recno ); // rebel has its own function in Rebel, this shouldn't be called set_nation(nationRecno); // set the town at last because set_nation() will delete the Town object //------ increase the loyalty of the town -----// for( i=0 ; i<MAX_RACE ; i++ ) race_loyalty_array[i] = (float) 70 + misc.random(20); // 70 to 90 initial loyalty //--------- add news ----------// news_array.new_nation(nationRecno); //--- random extra beginning advantages -----// int mobileCount; Nation* nationPtr = nation_array[nationRecno]; switch( misc.random(10) ) { case 1: // knowledge of weapon in the beginning. tech_res[ misc.random(tech_res.tech_count)+1 ]->set_nation_tech_level(nationRecno, 1); break; case 2: // random additional cash nationPtr->cash += misc.random(5000); break; case 3: // random additional food nationPtr->food += misc.random(5000); break; case 4: // random additional skilled units mobileCount = misc.random(5)+1; for( i=0 ; i<mobileCount && recruitable_race_pop(raceId,0)>0 ; i++ ) // 0-don't recruit spies { int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec pop, 0-don't mobilize spies if( unitRecno ) { Unit* unitPtr = unit_array[unitRecno]; //------- randomly set a skill -------// int skillId = misc.random(MAX_TRAINABLE_SKILL)+1; int loopCount=0; // no spying skill while( skillId==SKILL_SPYING ) // no spy skill as skill_id can't be set as SKILL_SPY, for spies, spy_recno must be set instead { if( ++skillId > MAX_TRAINABLE_SKILL ) skillId = 1; err_when( ++loopCount > 100 ); } unitPtr->skill.skill_id = skillId; unitPtr->skill.skill_level = 50 + misc.random(50); unitPtr->set_combat_level( 50 + misc.random(50) ); } else break; } break; } return nationRecno; }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (BerserkTimer <= diff) { me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, 0); DoPlaySoundToSet(me, SOUND_BERSERK); DoCast(me, SPELL_BERSERK, true); BerserkTimer = 60000; } else BerserkTimer -= diff; if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE) { if (SaberlashTimer <= diff) { // A tank with more than 490 defense skills should receive no critical hit //DoCast(me, 41296, true); DoCast(me->getVictim(), SPELL_SABER_LASH, true); //me->RemoveAurasDueToSpell(41296); SaberlashTimer = 30000; } else SaberlashTimer -= diff; if (FrenzyTimer <= diff) { DoCast(me, SPELL_FRENZY); FrenzyTimer = urand(10000, 15000); } else FrenzyTimer -= diff; if (Phase == PHASE_LYNX) { if (CheckTimer <= diff) { if (HealthBelowPct(25 * (3 - TransformCount))) EnterPhase(PHASE_SPLIT); CheckTimer = 1000; } else CheckTimer -= diff; } } if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE) { if (TotemTimer <= diff) { DoCast(me, SPELL_SUMMON_TOTEM); TotemTimer = 20000; } else TotemTimer -= diff; if (ShockTimer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { if (target->IsNonMeleeSpellCasted(false)) DoCast(target, SPELL_EARTHSHOCK); else DoCast(target, SPELL_FLAMESHOCK); ShockTimer = 10000 + rand()%5000; } } else ShockTimer -= diff; if (Phase == PHASE_HUMAN) { if (CheckTimer <= diff) { if (!HealthAbovePct(20) /*HealthBelowPct(10)*/) EnterPhase(PHASE_MERGE); else { Unit* Lynx = Unit::GetUnit(*me, LynxGUID); if (Lynx && !Lynx->HealthAbovePct(20) /*Lynx->HealthBelowPct(10)*/) EnterPhase(PHASE_MERGE); } CheckTimer = 1000; } else CheckTimer -= diff; } } if (Phase == PHASE_MERGE) { if (CheckTimer <= diff) { Unit* Lynx = Unit::GetUnit(*me, LynxGUID); if (Lynx) { Lynx->GetMotionMaster()->MoveFollow(me, 0, 0); me->GetMotionMaster()->MoveFollow(Lynx, 0, 0); if (me->IsWithinDistInMap(Lynx, 6.0f)) { if (TransformCount < 3) EnterPhase(PHASE_LYNX); else EnterPhase(PHASE_ENRAGE); } } CheckTimer = 1000; } else CheckTimer -= diff; } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_SHADOW_WORD_PAIN: DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); break; case EVENT_GOUGE: DoCastVictim(SPELL_GOUGE, true); break; case EVENT_SUMMON_PROWLERS: if (_summonCountA < MAX_PROWLERS_PER_SIDE) { if (Unit* trigger = me->GetUnit(*me, _triggersSideAGUID[urand(0, 4)])) { trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); ++_summonCountA; } } if (_summonCountB < MAX_PROWLERS_PER_SIDE) { if (Unit* trigger = me->GetUnit(*me, _triggersSideBGUID[urand(0, 4)])) { trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); ++_summonCountB; } } events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); break; case EVENT_MARK_OF_ARLOKK: { Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1, 3), 0.0f, false, -SPELL_MARK_OF_ARLOKK); if (!target) target = me->getVictim(); if (target) { DoCast(target, SPELL_MARK_OF_ARLOKK, true); Talk(SAY_FEAST_PROWLER, target->GetGUID()); } events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); break; } case EVENT_TRANSFORM: { DoCast(me, SPELL_PANTHER_TRANSFORM); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP)); const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); me->UpdateDamagePhysical(BASE_ATTACK); me->AttackStop(); DoResetThreat(); me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_VANISH_VISUAL); DoCast(me, SPELL_VANISH); events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); break; } case EVENT_VANISH: DoCast(me, SPELL_SUPER_INVIS); me->SetWalk(false); if (instance) me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ()); events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); break; case EVENT_VANISH_2: DoCast(me, SPELL_VANISH); DoCast(me, SPELL_SUPER_INVIS); events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); break; case EVENT_VISIBLE: me->SetReactState(REACT_AGGRESSIVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) AttackStart(target); me->RemoveAura(SPELL_SUPER_INVIS); me->RemoveAura(SPELL_VANISH); events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); events.SetPhase(PHASE_TWO); break; case EVENT_RAVAGE: DoCastVictim(SPELL_RAVAGE, true); events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); break; case EVENT_TRANSFORM_BACK: { me->RemoveAura(SPELL_PANTHER_TRANSFORM); DoCast(me, SPELL_VANISH_VISUAL); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg)); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg)); me->UpdateDamagePhysical(BASE_ATTACK); events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); events.SetPhase(PHASE_ONE); break; } default: break; } } DoMeleeAttackIfReady(); }
void UpdateFollowerAI(const uint32 Diff) { if (!UpdateVictim()) { //we are doing the post-event, or... if (HasFollowState(STATE_FOLLOW_POSTEVENT)) { if (PostEventTimer <= Diff) { PostEventTimer = 5000; Unit* pTorta = Unit::GetUnit(*me, TortaGUID); if (!pTorta || !pTorta->isAlive()) { //something happened, so just complete SetFollowComplete(); return; } switch (PhasePostEvent) { case 1: DoScriptText(SAY_TOOG_POST_1, me); break; case 2: DoScriptText(SAY_TORT_POST_2, pTorta); break; case 3: DoScriptText(SAY_TOOG_POST_3, me); break; case 4: DoScriptText(SAY_TORT_POST_4, pTorta); break; case 5: DoScriptText(SAY_TOOG_POST_5, me); break; case 6: DoScriptText(SAY_TORT_POST_6, pTorta); me->GetMotionMaster()->MovePoint(POINT_ID_TO_WATER, ToWaterLoc); break; } ++PhasePostEvent; } else PostEventTimer -= Diff; } //...we are doing regular speech check else if (HasFollowState(STATE_FOLLOW_INPROGRESS)) { if (CheckSpeechTimer <= Diff) { CheckSpeechTimer = 5000; if (urand(0, 9) > 8) DoScriptText(RAND(SAY_TOOG_THIRST, SAY_TOOG_WORRIED), me); } else CheckSpeechTimer -= Diff; } return; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (Delay_Timer <= diff) { Delay_Timer = 3500; Unit* pLeftHead = Unit::GetUnit(*me, LeftHeadGUID); Unit* pRightHead = Unit::GetUnit(*me, RightHeadGUID); if (!pLeftHead || !pRightHead) return; if (AggroYell) { DoScriptText(GoCombatDelay[iaggro].id, pRightHead); AggroYell = false; } if (ThreatYell2) { Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); DoScriptText(ThreatDelay2[ithreat].id, source); ThreatYell2 = false; } if (ThreatYell) { Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); DoScriptText(ThreatDelay1[ithreat].id, source); ThreatYell = false; ThreatYell2 = true; } if (KillingYell) { Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); DoScriptText(KillingDelay[ikilling].id, source); KillingYell = false; } } else Delay_Timer -= diff; if (!UpdateVictim()) return; if (BlastCount && BlastWave_Timer <= diff) { DoCast(me, SPELL_BLAST_WAVE); BlastWave_Timer = 5000; ++BlastCount; if (BlastCount == 3) BlastCount = 0; } else BlastWave_Timer -= diff; if (BurningMaul_Timer <= diff) { DoScriptText(EMOTE_ENRAGE, me); DoCast(me, SPELL_BURNING_MAUL); BurningMaul_Timer = 40000; BlastWave_Timer = 16000; BlastCount = 1; } else BurningMaul_Timer -= diff; if (ResetThreat_Timer <= diff) { if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) { DoYellForThreat(); DoResetThreat(); me->AddThreat(pTarget, 0.0f); } ResetThreat_Timer = 25000+rand()%15000; } else ResetThreat_Timer -= diff; if (Fear_Timer <= diff) { DoCast(me, SPELL_FEAR); Fear_Timer = 15000+rand()%20000; } else Fear_Timer -= diff; if (ThunderClap_Timer <= diff) { DoCast(me, SPELL_THUNDERCLAP); ThunderClap_Timer = 15000+rand()%15000; } else ThunderClap_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; //only two may be wrong, perhaps increase timer and spawn periodically instead. if (SummonedCount < 2) { if (Summon_Timer < diff) { m_creature->InterruptNonMeleeSpells(false); DoCastSpellIfCan(m_creature,SPELL_SUMMON_FIENDISH_HOUND); Summon_Timer = urand(15000, 30000); }else Summon_Timer -= diff; } if (CanPullBack) { if (ShadowWhip_Timer < diff) { if (Player* pPlayer = (Player*)Unit::GetUnit(*m_creature,playerGUID)) { //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) if (pPlayer->HasMovementFlag(MOVEFLAG_FALLING)) { m_creature->InterruptNonMeleeSpells(false); DoCastSpellIfCan(pPlayer,SPELL_SHADOW_WHIP); } } playerGUID = 0; ShadowWhip_Timer = 2000; CanPullBack = false; }else ShadowWhip_Timer -= diff; } else if (OrbitalStrike_Timer < diff) { Unit* temp = NULL; if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) temp = m_creature->getVictim(); else temp = SelectUnit(SELECT_TARGET_RANDOM,0); if (temp && temp->GetTypeId() == TYPEID_PLAYER) { DoCastSpellIfCan(temp,SPELL_ORBITAL_STRIKE); OrbitalStrike_Timer = urand(14000, 16000); playerGUID = temp->GetGUID(); if (playerGUID) CanPullBack = true; } }else OrbitalStrike_Timer -= diff; if ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 20) { if (DemonicShield_Timer < diff) { DoCastSpellIfCan(m_creature,SPELL_DEMONIC_SHIELD); DemonicShield_Timer = 15000; }else DemonicShield_Timer -= diff; } if (Aura_Timer < diff) { DoScriptText(SAY_CURSE, m_creature); if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) { DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_TREACHEROUS_AURA : H_SPELL_BANE_OF_TREACHERY); Aura_Timer = urand(8000, 16000); } }else Aura_Timer -= diff; if (Shadowbolt_Timer < diff) { if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) { if (target) target = m_creature->getVictim(); DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_SHADOW_BOLT : H_SPELL_SHADOW_BOLT); Shadowbolt_Timer = urand(4000, 6500); } }else Shadowbolt_Timer -= diff; DoMeleeAttackIfReady(); }
void WorldSession::HandleTextEmoteOpcode(WorldPacket & recvData) { if (!GetPlayer()->IsAlive()) return; GetPlayer()->UpdateSpeakTime(); if (!GetPlayer()->CanSpeak()) { std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); return; } if (GetPlayer()->IsSpectator()) return; uint32 text_emote, emoteNum; uint64 guid; recvData >> text_emote; recvData >> emoteNum; recvData >> guid; sScriptMgr->OnPlayerTextEmote(GetPlayer(), text_emote, emoteNum, guid); EmotesTextEntry const* em = sEmotesTextStore.LookupEntry(text_emote); if (!em) return; uint32 emote_anim = em->textid; switch (emote_anim) { case EMOTE_STATE_SLEEP: case EMOTE_STATE_SIT: case EMOTE_STATE_KNEEL: case EMOTE_ONESHOT_NONE: break; default: // Only allow text-emotes for "dead" entities (feign death included) if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) break; GetPlayer()->HandleEmoteCommand(emote_anim); break; } Unit* unit = ObjectAccessor::GetUnit(*_player, guid); CellCoord p = Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); Cell cell(p); cell.SetNoCreate(); Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > emote_do(emote_builder); Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker); cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); //Send scripted event call if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); }
void UpdateAI(const uint32 diff) { //Return since we have no target if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) return; //HatefullStrike_Timer if (HatefullStrike_Timer < diff) { //Cast Hateful strike on the player with the highest //amount of HP within melee distance uint32 MostHP = 0; Unit* pMostHPTarget = NULL; Unit* pTemp = NULL; std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin(); for (i = m_creature->getThreatManager().getThreatList().begin(); i!=m_creature->getThreatManager().getThreatList().end(); ++i) { pTemp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid()); if (pTemp && pTemp->isAlive() && pTemp->GetHealth() > MostHP && m_creature->GetDistance2d(pTemp) < 25) { MostHP = pTemp->GetHealth(); pMostHPTarget = pTemp; } } if (pMostHPTarget) DoCast(pMostHPTarget, SPELL_HATEFULSTRIKE); HatefullStrike_Timer = 3000; }else HatefullStrike_Timer -= diff; //Enrage_Timer if (Enrage_Timer < diff) { //Cast Berserker Rage DoCast(m_creature, SPELL_BERSERK); DoTextEmote(EMOTE_BERSERK, m_creature->getVictim()); //5 minutes until we should cast this agian Enrage_Timer = 300000; }else Enrage_Timer -= diff; //Slimebolt_Timer if (Slimebolt_Timer < diff) { //Cast Slime bolt DoCast(m_creature->getVictim(),SPELL_SLIMEBOLT); //5 seconds until we should cast this agian Slimebolt_Timer = 5000; }else Slimebolt_Timer -= diff; //Enrage if not already enraged and below 5% if (!Enraged && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 5) { DoCast(m_creature,SPELL_ENRAGE); DoTextEmote(EMOTE_ENRAGE,NULL); Enraged = true; } DoMeleeAttackIfReady(); }
void WorldSession::HandlePetRename(WorldPacket & recv_data) { sLog->outDetail("HandlePetRename. CMSG_PET_RENAME"); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petguid; recv_data >> name; recv_data >> isdeclined; Pet* pet = ObjectAccessor::FindPet(petguid); // check it! if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if (sObjectMgr->IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Unit *owner = pet->GetOwner(); if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.EscapeString(declinedname.name[i]); trans->PAppend("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); trans->PAppend("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u', '%u', '%s', '%s', '%s', '%s', '%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.EscapeString(name); trans->PAppend("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(trans); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped }
void PlayerbotShamanAI::DoNextCombatManeuver(Unit *pTarget) { if (!pTarget || pTarget->isDead()) return; PlayerbotAI *ai = GetAI(); if (!ai) return; Player *m_bot = GetPlayerBot(); if (!m_bot || m_bot->isDead()) return; Unit *pVictim = pTarget->getVictim(); Unit *m_tank = FindMainTankInRaid(GetMaster()); if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); } if (!m_tank) { m_tank = m_bot; } uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth(); float pDist = m_bot->GetDistance(pTarget); uint8 pThreat = GetThreatPercent(pTarget); uint8 reqHeal = 0; uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal); switch(ai->GetScenarioType()) { case SCENARIO_DUEL: ((ai->GetHealthPercent() < 80 && CastSpell(LESSER_HEAL)) || CastSpell(LIGHTNING_BOLT, pTarget)); return; } // Cast CC breakers if any match found (include any dispels first) does not work yet //uint32 ccSpells[4] = { R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM }; //if (ai->GetManaPercent() < 35) { ccSpells[0] = 0; ccSpells[1] = 0; } //We dont have any mana to waste... //if (castSelfCCBreakers(ccSpells)) { } // Most of them don't trigger gcd #pragma region Choose Actions // Choose actions accoring to talents if (m_tank->GetGUID() == m_bot->GetGUID()) { m_role=BOT_ROLE_TANK; } // Hey! I am Main Tank else if (TALENT_ENHANCEMENT) { m_role = BOT_ROLE_DPS_MELEE; } else if (TALENT_ELEMENTAL) { m_role = BOT_ROLE_DPS_RANGED; } else if (TALENT_RESTO) { m_role = BOT_ROLE_SUPPORT; } else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack // if i am under attack and if i am not tank or offtank: change target if needed if (m_tank->GetGUID() != m_bot->GetGUID() && isUnderAttack() ) { if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) { } // My target is almost up to me, no need to search else //Have to select nearest target { Unit *curAtt = GetNearestAttackerOf(m_bot); if (curAtt && curAtt->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(curAtt->GetGUID()); //ai->AddLootGUID(curAtt->GetGUID()); DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed.. return; } } //my target is attacking me } #pragma endregion // Choose Weapon Enchant if (ChangeWeaponEnchants()) return; if (TALENT_ELEMENTAL){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }} if (TALENT_ENHANCEMENT){ if (!m_bot->HasAura(LIGHTNING_SHIELD) && CastSpell(LIGHTNING_SHIELD,m_bot)) { return; }} if (TALENT_RESTO){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }} // Choose shield /* if (EARTH_SHIELD && ai->GetHealthPercent() < 80 && isUnderAttack()) { if (CastSpell(EARTH_SHIELD,m_bot)) { return; } } else if (WATER_SHIELD && ai->GetManaPercent() < 40) { if (CastSpell(WATER_SHIELD,m_bot)) { return; } } else if (LIGHTNING_SHIELD && ( isUnderAttack() || m_tank->GetGUID() == m_bot->GetGUID() ) && !(m_bot->HasAura(WATER_SHIELD) && ai->GetManaPercent() < 80) ) { if (CastSpell(LIGHTNING_SHIELD,m_bot)) { return; } } else if (CastSpell(WATER_SHIELD,m_bot)) { return; } */ // If there's a cast stop if(m_bot->HasUnitState(UNIT_STATE_CASTING)) return; switch(m_role) { #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK case BOT_ROLE_TANK: case BOT_ROLE_OFFTANK: if (!TALENT_ELEMENTAL && !TALENT_RESTO) { TakePosition(pTarget); } else { TakePosition(pTarget,BOT_ROLE_DPS_RANGED); } // mob will come to you sooner or later no need to hurry // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (ai->GetManaPercent() > 70 && DoSupportRaid(m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_DPS_MELEE case BOT_ROLE_DPS_MELEE: TakePosition(pTarget); // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_DPS_RANGED case BOT_ROLE_DPS_RANGED: TakePosition(pTarget); // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_SUPPORT case BOT_ROLE_SUPPORT: TakePosition(pTarget); // Do support stuff if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; } if (DoSupportRaid(m_bot)) { return; } //heal pets and bots Unit *target = DoSelectLowestHpFriendly(40, 1000); if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; } break; #pragma endregion } #pragma region ShamanCommon //Defensive Stuff if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() ) { if (pDist > 5 && CastSpell(FROST_SHOCK, pTarget)) { return; } if ((pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST || pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID) && CastSpell(HEX, pTarget)) { return; } // no gcd if (CastSpell(WIND_SHEAR, pTarget)) { } // no gcd } if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(WIND_SHEAR, pTarget)) { } //no gcd if (m_bot->getRace() == (uint8) RACE_TAUREN && pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //Catch if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING)) { if (CastSpell(FROST_SHOCK,pTarget)) return; } //Buff and restores if ( ( (ai->GetHealthPercent() < 60 && isUnderAttack()) || (ai->GetManaPercent() < 30) ) && CastSpell(SHAMANISTIC_RAGE, m_bot)) { return; } if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} // no GCD if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} // no GCD if (!m_bot->HasAura(HEROISM) && !m_bot->HasAura(EXHAUSTION) && !m_bot->HasAura(SATED) && CastSpell(HEROISM,m_bot)) { return; } if (m_role != BOT_ROLE_SUPPORT && CastSpell(NATURES_SWIFTNESS, m_bot)) { } //healers keep it for healing no gcd else if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd // If at threat limit, use WIND_SHEAR to reduce threat if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack()) { if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!! { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); return; } else { if (CastSpell(WIND_SHEAR,pTarget)) { return; } //Lets see if we can manage else { return; } //use no spells and wait threat to be reduced } } if (TALENT_ELEMENTAL) { if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd if (!pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(FLAME_SHOCK,pTarget)) { return; } if (CastSpell(LAVA_BURST,pTarget)) { return; } if (CastSpell(CHAIN_LIGHTNING,pTarget)) { return; } if (CastSpell(LIGHTNING_BOLT,pTarget)) { return; } } //dps if (MAELSTROM_WEAPON) { Aura *maelaura = m_bot->GetAura(MAELSTROM_WEAPON); if (maelaura && maelaura->GetStackAmount() == 5) { if ((isUnderAttack(m_tank,3) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(CHAIN_LIGHTNING,pTarget,true,true)) { return; } if (CastSpell(LIGHTNING_BOLT,pTarget,true,true)) { return; } } } if (CastSpell(FLAME_SHOCK,pTarget)) { return; } if (CastSpell(STORMSTRIKE,pTarget,true,true)) { return; } //if (!TALENT_ENHANCEMENT && CanCast(LAVA_BURST,pTarget,true) && pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(LAVA_BURST,pTarget,false)) { return; } if (CastSpell(FERAL_SPIRIT,m_bot)) { return; } if (CanCast(EARTH_SHOCK,pTarget,true) && (pTarget->HasAura(STORMSTRIKE,m_bot->GetGUID()) || pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) ) && CastSpell(EARTH_SHOCK,pTarget)) { return; } //if (CanCast(FLAME_SHOCK,pTarget) && CastSpell(FLAME_SHOCK,pTarget)) { return; } if (CastSpell(LAVA_LASH,pTarget,true,true)) { return; } if (CastSpell(FIRE_NOVA,pTarget)) { return; } //if ((isUnderAttack(m_tank,4) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(FIRE_NOVA,pTarget)) { return; } if (ai->GetManaPercent() > 60 && castDispel(PURGE,pTarget)) { return; } //PURGE but dont overpurge #pragma endregion // drink potion if support / healer (Other builds simply overuse mana and waste mana pots) if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) ) { Item *pItem = ai->FindPotion(); if(pItem != NULL) { if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown ai->UseItem(*pItem); } } } //end DoNextCombatManeuver
void UpdateAI(const uint32 diff) { //Is event even running? if (!isEvent) return; //Phase timing if (Phase_Timer >= diff) { Phase_Timer -= diff; return; } Unit *ardonis = Unit::GetUnit(*me,ardonisGUID); Unit *pathaleon = Unit::GetUnit(*me,pathaleonGUID); Player *player = Unit::GetPlayer(*me, playerGUID); if (!ardonis || !player) { Reset(); return; } if (Phase > 4 && !pathaleon) { Reset(); return; } //Phase 1 Dawnforge say switch (Phase) { case 1: DoScriptText(SAY_COMMANDER_DAWNFORGE_1, me); ++Phase; Phase_Timer = 16000; break; //Phase 2 Ardonis say case 2: DoScriptText(SAY_ARCANIST_ARDONIS_1, ardonis); ++Phase; Phase_Timer = 16000; break; //Phase 3 Dawnforge say case 3: DoScriptText(SAY_COMMANDER_DAWNFORGE_2, me); ++Phase; Phase_Timer = 16000; break; //Phase 4 Pathaleon spawns up to phase 9 case 4: //spawn pathaleon's image me->SummonCreature(CreatureEntry[2][0], 2325.851563f, 2799.534668f, 133.084229f, 6.038996f, TEMPSUMMON_TIMED_DESPAWN, 90000); ++Phase; Phase_Timer = 500; break; //Phase 5 Pathaleon say case 5: DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_1, pathaleon); ++Phase; Phase_Timer = 6000; break; //Phase 6 case 6: switch(PhaseSubphase) { //Subphase 1: Turn Dawnforge and Ardonis case 0: Turn_to_Pathaleons_Image(); ++PhaseSubphase; Phase_Timer = 8000; break; //Subphase 2 Dawnforge say case 1: DoScriptText(SAY_COMMANDER_DAWNFORGE_3, me); PhaseSubphase = 0; ++Phase; Phase_Timer = 8000; break; } break; //Phase 7 Pathaleons say 3 Sentence, every sentence need a subphase case 7: switch(PhaseSubphase) { //Subphase 1 case 0: DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2, pathaleon); ++PhaseSubphase; Phase_Timer = 12000; break; //Subphase 2 case 1: DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2_1, pathaleon); ++PhaseSubphase; Phase_Timer = 16000; break; //Subphase 3 case 2: DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2_2, pathaleon); PhaseSubphase = 0; ++Phase; Phase_Timer = 10000; break; } break; //Phase 8 Dawnforge & Ardonis say case 8: DoScriptText(SAY_COMMANDER_DAWNFORGE_4, me); DoScriptText(SAY_ARCANIST_ARDONIS_2, ardonis); ++Phase; Phase_Timer = 4000; break; //Phase 9 Pathaleons Despawn, Reset Dawnforge & Ardonis angle case 9: Turn_to_eachother(); //hide pathaleon, unit will despawn shortly pathaleon->SetVisibility(VISIBILITY_OFF); PhaseSubphase = 0; ++Phase; Phase_Timer = 3000; break; //Phase 10 Dawnforge say case 10: DoScriptText(SAY_COMMANDER_DAWNFORGE_5, me); player->AreaExploredOrEventHappens(QUEST_INFO_GATHERING); Reset(); break; } }
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { uint32 opcode = recv_data.GetOpcode(); DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); recv_data.hexlike(); Unit *mover = _player->GetMover(); Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if(plMover && plMover->IsBeingTeleported()) { recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; } /* extract packet */ ObjectGuid guid; MovementInfo movementInfo; recv_data >> guid.ReadAsPacked(); recv_data >> movementInfo; /*----------------*/ if (!MaNGOS::IsValidMapCoord(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o)) { recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; } /* handle special cases */ if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT)) { // transports size limited // (also received at zeppelin/lift leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if( movementInfo.GetTransportPos()->x > 50 || movementInfo.GetTransportPos()->y > 50 || movementInfo.GetTransportPos()->z > 100 ) { recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; } if( !MaNGOS::IsValidMapCoord(movementInfo.GetPos()->x + movementInfo.GetTransportPos()->x, movementInfo.GetPos()->y + movementInfo.GetTransportPos()->y, movementInfo.GetPos()->z + movementInfo.GetTransportPos()->z, movementInfo.GetPos()->o + movementInfo.GetTransportPos()->o) ) { recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; } // if we boarded a transport, add us to it if (plMover && !plMover->m_transport) { float trans_rad = movementInfo.GetTransportPos()->x*movementInfo.GetTransportPos()->x + movementInfo.GetTransportPos()->y*movementInfo.GetTransportPos()->y + movementInfo.GetTransportPos()->z*movementInfo.GetTransportPos()->z; if (trans_rad > 3600.0f) // transport radius = 60 yards //cheater with on_transport_flag { return; } // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount 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)->GetObjectGuid() == movementInfo.GetTransportGuid()) { plMover->m_transport = (*iter); (*iter)->AddPassenger(plMover); break; } } } } else if (plMover && plMover->m_transport) // if we were on a transport, leave { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; movementInfo.ClearTransportData(); } // 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 && plMover && !plMover->isInFlight()) plMover->HandleFall(movementInfo); if (plMover && (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING) != plMover->IsInWater())) { // now client not include swimming flag in case jumping under water plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z) ); if(plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z-7.0f)) { plMover->m_anti_BeginFallZ=INVALID_HEIGHT; } } // ---- anti-cheat features -->>> uint32 Anti_TeleTimeDiff=plMover ? time(NULL) - plMover->Anti__GetLastTeleTime() : time(NULL); static const uint32 Anti_TeleTimeIgnoreDiff=sWorld.GetMvAnticheatIgnoreAfterTeleport(); if (plMover && (plMover->m_transport == 0) && sWorld.GetMvAnticheatEnable() && GetPlayer()->GetSession()->GetSecurity() <= sWorld.GetMvAnticheatGmLevel() && GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()!=FLIGHT_MOTION_TYPE && Anti_TeleTimeDiff>Anti_TeleTimeIgnoreDiff) { const uint32 CurTime=getMSTime(); if (getMSTimeDiff(GetPlayer()->m_anti_lastalarmtime,CurTime) > sWorld.GetMvAnticheatAlarmPeriod()) { GetPlayer()->m_anti_alarmcount = 0; } /* I really don't care about movement-type yet (todo) UnitMoveType move_type; if (movementInfo.flags & MOVEMENTFLAG_FLYING) move_type = MOVE_FLY; else if (movementInfo.flags & MOVEMENTFLAG_SWIMMING) move_type = MOVE_SWIM; else if (movementInfo.flags & MOVEMENTFLAG_WALK_MODE) move_type = MOVE_WALK; else move_type = MOVE_RUN;*/ float delta_x = GetPlayer()->GetPositionX() - movementInfo.GetPos()->x; float delta_y = GetPlayer()->GetPositionY() - movementInfo.GetPos()->y; float delta_z = GetPlayer()->GetPositionZ() - movementInfo.GetPos()->z; float delta = sqrt(delta_x * delta_x + delta_y * delta_y); // Len of movement-vector via Pythagoras (a^2+b^2=Len^2) float tg_z = 0.0f; //tangens float delta_t = getMSTimeDiff(GetPlayer()->m_anti_lastmovetime,CurTime); GetPlayer()->m_anti_lastmovetime = CurTime; GetPlayer()->m_anti_MovedLen += delta; if (delta_t > 15000.0f) { delta_t = 15000.0f; } // Tangens of walking angel if (!(movementInfo.GetMovementFlags() & (MOVEFLAG_FLYING | MOVEFLAG_SWIMMING))) { tg_z = ((delta !=0.0f) && (delta_z > 0.0f)) ? (atan((delta_z*delta_z) / delta) * 180.0f / M_PI) : 0.0f; } //antiOFF fall-damage, MOVEMENTFLAG_UNK4 seted by client if player try movement when falling and unset in this case the MOVEMENTFLAG_FALLING flag. if ((!GetPlayer()->CanFly() && GetPlayer()->m_anti_BeginFallZ == INVALID_HEIGHT) && (movementInfo.GetMovementFlags() & (MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR)) != 0) { GetPlayer()->m_anti_BeginFallZ=(float)(movementInfo.GetPos()->z); } if (GetPlayer()->m_anti_NextLenCheck <= CurTime) { // Check every 500ms is a lot more advisable then 1000ms, because normal movment packet arrives every 500ms uint32 OldNextLenCheck=GetPlayer()->m_anti_NextLenCheck; float delta_xyt=GetPlayer()->m_anti_MovedLen/(float)(getMSTimeDiff(OldNextLenCheck-500,CurTime)); GetPlayer()->m_anti_NextLenCheck = CurTime+500; GetPlayer()->m_anti_MovedLen = 0.0f; static const float MaxDeltaXYT = sWorld.GetMvAnticheatMaxXYT(); if (delta_xyt > MaxDeltaXYT && delta<=100.0f && GetPlayer()->GetZoneId() != 2257) { if (sWorld.GetMvAnticheatSpeedCheck()) Anti__CheatOccurred(CurTime,"Speed hack",delta_xyt,LookupOpcodeName(opcode), (float)(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()), (float)(getMSTimeDiff(OldNextLenCheck-500,CurTime))); } } if (delta > 100.0f && GetPlayer()->GetZoneId() != 2257) { if (sWorld.GetMvAnticheatTeleportCheck()) Anti__ReportCheat("Tele hack",delta,LookupOpcodeName(opcode)); } // Check for waterwalking . Fix new way of checking for waterwalking by Darky88 if (movementInfo.HasMovementFlag(MOVEFLAG_WATERWALKING) && !(GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK) || GetPlayer()->HasAuraType(SPELL_AURA_GHOST))) { if(sWorld.GetMvAnticheatWaterCheck()) Anti__CheatOccurred(CurTime,"Water walking",0.0f,NULL,0.0f,(uint32)(movementInfo.GetMovementFlags())); } // Check for walking upwards a mountain while not beeing able to do that, New check by Darky88 if ((delta_z < -2.3f) && (tg_z > 2.37f)) { if (sWorld.GetMvAnticheatMountainCheck()) Anti__CheatOccurred(CurTime,"Mountain hack",tg_z,NULL,delta,delta_z); } static const float DIFF_OVERGROUND = 10.0f; float Anti__GroundZ = GetPlayer()->GetMap()->GetHeight(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),MAX_HEIGHT); float Anti__FloorZ = GetPlayer()->GetMap()->GetHeight(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ()); float Anti__MapZ = ((Anti__FloorZ <= (INVALID_HEIGHT+5.0f)) ? Anti__GroundZ : Anti__FloorZ) + DIFF_OVERGROUND; if (!GetPlayer()->CanFly() && !GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z-7.0f) && Anti__MapZ < GetPlayer()->GetPositionZ() && Anti__MapZ > (INVALID_HEIGHT+DIFF_OVERGROUND + 5.0f)) { static const float DIFF_AIRJUMP=25.0f; // 25 is realy high, but to many false positives... // Air-Jump-Detection definitively needs a better way to be detected... if ((movementInfo.GetMovementFlags() & (MOVEFLAG_CAN_FLY | MOVEFLAG_FLYING | MOVEFLAG_ROOT)) != 0) // Fly Hack { // Fix Aura 55164 if (!GetPlayer()->HasAura(55164) || !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL)) if (sWorld.GetMvAnticheatFlyCheck()) Anti__CheatOccurred(CurTime,"Fly hack", ((uint8)(GetPlayer()->HasAuraType(SPELL_AURA_FLY))) + ((uint8)(GetPlayer()->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED))*2), NULL,GetPlayer()->GetPositionZ()-Anti__MapZ); } // Need a better way to do that - currently a lot of fake alarms else if ((Anti__MapZ+DIFF_AIRJUMP < GetPlayer()->GetPositionZ() && (movementInfo.GetMovementFlags() & (MOVEFLAG_FALLINGFAR | MOVEFLAG_PENDINGSTOP))==0) || (Anti__MapZ < GetPlayer()->GetPositionZ() && opcode==MSG_MOVE_JUMP) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL)) { if (sWorld.GetMvAnticheatJumpCheck()) Anti__CheatOccurred(CurTime,"Possible Air Jump Hack",0.0f,LookupOpcodeName(opcode),0.0f,movementInfo.GetMovementFlags()); } } /*if(Anti__FloorZ < -199900.0f && Anti__GroundZ >= -199900.0f && GetPlayer()->GetPositionZ()+5.0f < Anti__GroundZ) { Anti__CheatOccurred(CurTime,"Teleport2Plane hack", GetPlayer()->GetPositionZ(),NULL,Anti__GroundZ); }*/ //Teleport To Plane checks if (movementInfo.GetPos()->z < 0.0001f && movementInfo.GetPos()->z > -0.0001f && (!movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_SWIMMING | MOVEFLAG_CAN_FLY | MOVEFLAG_FLYING)))) { if(sWorld.GetMvAnticheatTeleport2PlaneCheck()) { // Prevent using TeleportToPlan. Map *map = GetPlayer()->GetMap(); if (map) { float plane_z = map->GetHeight(movementInfo.GetPos()->x, movementInfo.GetPos()->y, MAX_HEIGHT) - movementInfo.GetPos()->z; plane_z = (plane_z < -500.0f) ? 0 : plane_z; //check holes in heigth map if(plane_z > 0.1f || plane_z < -0.1f) { if(sWorld.GetMvAnticheatTeleport2PlaneCheck()) Anti__CheatOccurred(CurTime,"Teleport2Plane hack",GetPlayer()->GetPositionZ(),NULL,plane_z); } } } } } // <<---- anti-cheat features /* process position-change */ movementInfo.UpdateTime(getMSTime()); WorldPacket data(opcode, recv_data.size()); data.appendPackGUID(mover->GetGUID()); // write guid movementInfo.Write(data); // write data mover->SendMessageToSetExcept(&data, _player); if(plMover) // nothing is charmed, or player charmed { plMover->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); plMover->m_movementInfo = movementInfo; plMover->UpdateFallInformationIfNeed(movementInfo, opcode); // after move info set if ((opcode == MSG_MOVE_SET_WALK_MODE || opcode == MSG_MOVE_SET_RUN_MODE)) plMover->UpdateWalkMode(plMover, false); if(plMover->isMovingOrTurning()) plMover->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if(movementInfo.GetPos()->z < -500.0f) { if(plMover->InBattleGround() && plMover->GetBattleGround() && plMover->GetBattleGround()->HandlePlayerUnderMap(_player)) { // do nothing, the handle already did if returned true } else { // 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(plMover->isAlive()) { plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, plMover->GetMaxHealth()); // pl can be alive if GM/etc if(!plMover->isAlive()) { // change the death state to CORPSE to prevent the death timer from // starting in the next player update plMover->KillPlayer(); plMover->BuildPlayerRepop(); } } // cancel the death timer here if started plMover->RepopAtGraveyard(); } } } else // creature charmed { if(mover->IsInWorld()) mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); } }