void render_ortho(SDL_Renderer* renderer) { const int offset = input_offset; const float scale = input_scale; const int tileSizeX = 128; const int tileSizeY = 64; //draw draw space if (input_draw_space) { SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); int w = worldMap.GetWidth()*tileSizeX*scale + (worldMap.GetWidth() - 1)*offset; int h = worldMap.GetHeight()*tileSizeY*scale + (worldMap.GetHeight() - 1)*offset; DRect rect(-camX, -camY, w, h); SDL_RenderFillRect(renderer, rect.get()); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); } //draw map for (int y = 0; y < worldMap.GetHeight(); y++) { for (int x = 0; x < worldMap.GetWidth(); x++) { const int tileId = 0; SDL_Rect tileRect; //in tileset coords tileRect.x = tileId*tileSizeX; tileRect.y = tileId*tileSizeY; tileRect.w = tileSizeX; tileRect.h = tileSizeY; SDL_Rect rect; //in world coords rect.x = x*tileSizeX*scale + x*offset - camX; rect.y = y*tileSizeY*scale + y*offset - camY; rect.w = tileSizeX*scale; rect.h = tileSizeY*scale; SDL_RenderCopy(renderer, tileset, &tileRect, &rect); } } //draw debug rect if (input_show_debug_rect) { SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); for (int y = 0; y < worldMap.GetHeight(); y++) { for (int x = 0; x < worldMap.GetWidth(); x++) { SDL_Rect rect; //in world coords rect.x = x*tileSizeX*scale + x*offset - camX; rect.y = y*tileSizeY*scale + y*offset - camY; rect.w = tileSizeX*scale; rect.h = tileSizeY*scale; SDL_RenderDrawRect(renderer, &rect); } } SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); } }
void RandomMovementGenerator<Creature>::Initialize(Creature &creature) { float x,y,z,z2, wander_distance; creature.GetRespawnCoord(x, y, z); creature.GetRespawnDist(wander_distance); uint32 mapid=creature.GetMapId(); Map* map = MapManager::Instance().GetMap(mapid, &creature); // Initialization is done in bulk. Don’t use vamps for that (4. parameter = false). It is too costly when entering a new map grid z2 = map->GetHeight(x,y,z, false); if( fabs( z2 - z ) < 5 ) z = z2; i_nextMove = 1; i_waypoints[0][0] = x; i_waypoints[0][1] = y; i_waypoints[0][2] = z; bool is_water_ok = creature.isCanSwimOrFly(); bool is_land_ok = creature.isCanWalkOrFly(); for(unsigned int idx=1; idx < MAX_RAND_WAYPOINTS+1; ++idx) { const float angle = 2*M_PI*rand_norm(); const float range = wander_distance*rand_norm(); i_waypoints[idx][0] = x+ range * cos(angle); i_waypoints[idx][1] = y+ range * sin(angle); // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]); MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]); bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z); // if generated wrong path just ignore if( is_water && !is_water_ok || !is_water && !is_land_ok ) { i_waypoints[idx][0] = i_waypoints[idx-1][0]; i_waypoints[idx][1] = i_waypoints[idx-1][1]; i_waypoints[idx][2] = i_waypoints[idx-1][2]; continue; } // Initialization is done in bulk. Don’t use vamps for that (4. parameter = false). It is too costly when entering a new map grid z2 = map->GetHeight(i_waypoints[idx][0],i_waypoints[idx][1],z, false); if( fabs( z2 - z ) < 5 ) z = z2; i_waypoints[idx][2] = z; } i_nextMoveTime.Reset(urand(0, 10000-1)); // TODO: check the lower bound (it is probably too small) creature.StopMoving(); }
void RandomMovementGenerator::Initialize(Creature &creature) { float x,y,z,z2, wander_distance; creature.GetRespawnCoord(x, y, z); creature.GetRespawnDist(wander_distance); uint32 mapid=creature.GetMapId(); Map* map = MapManager::Instance().GetMap(mapid); z2 = map->GetHeight(x,y); if( abs( z2 - z ) < 5 ) z = z2; i_nextMove = 1; i_waypoints[0][0] = x; i_waypoints[0][1] = y; i_waypoints[0][2] = z; bool is_water_ok = creature.isCanSwimOrFly(); bool is_land_ok = creature.isCanWalkOrFly(); for(unsigned int idx=1; idx < MAX_RAND_WAYPOINTS+1; ++idx) { const float angle = (2*M_PI*rand())/RAND_MAX; const float range = (wander_distance*rand())/RAND_MAX; i_waypoints[idx][0] = x+ range * cos(angle); i_waypoints[idx][1] = y+ range * sin(angle); // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]); MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]); bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1]); // if generated wrong path just ignore if( is_water && !is_water_ok || !is_water && !is_land_ok ) { i_waypoints[idx][0] = i_waypoints[idx-1][0]; i_waypoints[idx][1] = i_waypoints[idx-1][1]; i_waypoints[idx][2] = i_waypoints[idx-1][2]; continue; } z2 = map->GetHeight(i_waypoints[idx][0],i_waypoints[idx][1]); if( abs( z2 - z ) < 5 ) z = z2; i_waypoints[idx][2] = z; } i_nextMoveTime.Reset((rand() % 10000)); creature.StopMoving(); }
void mouseClick(MOUSE_EVENT event) { if (event == MOUSE_LEFT) { if (inEditorBar()) { std::cout << "editor!\n"; int editorTileIndex = getTileEditor(mouse_x, mouse_y); if(editorTileIndex >= 0 && editorTileIndex < NB_TILES_EDITOR) { std::cout << "id= " << editorTileIndex << "\n"; selectedTileEditor = editorTileIndex; } } else { //write tile to map int mapX; int mapY; getSelectedTileXY(mouse_x, mouse_y, mapX, mapY); if (mapX >= 0 && mapX < worldMap.GetWidth() && mapY >= 0 && mapY < worldMap.GetHeight()) { int tileId = TILES_EDITOR[selectedTileEditor]; Terrain& terrain = worldMap.Get(mapX, mapY); if (EDITOR_SELECTED_LAYER == 0) { terrain.terrainId = tileId; } else if (EDITOR_SELECTED_LAYER == 1) { terrain.objectId = tileId; } std::cout << "set tile " << tileId << " at " << mapX << "," << mapY << "\n"; } } } else if (event == MOUSE_RIGHT) { //erase tile from map int mapX; int mapY; getSelectedTileXY(mouse_x, mouse_y, mapX, mapY); if (mapX >= 0 && mapX <= worldMap.GetWidth() && mapY >= 0 && mapY < worldMap.GetHeight()) { int tileId = TILES_EDITOR[0]; Terrain& terrain = worldMap.Get(mapX, mapY); if (EDITOR_SELECTED_LAYER == 0) { terrain.terrainId = -1; } else if (EDITOR_SELECTED_LAYER == 1) { terrain.objectId = -1; } std::cout << "set tile " << tileId << " at " << mapX << "," << mapY << "\n"; } } }
void ConfusedMovementGenerator::Initialize(Creature &creature) { const float wander_distance=11; float x,y,z,z2; x = creature.GetPositionX(); y = creature.GetPositionY(); z = creature.GetPositionZ(); uint32 mapid=creature.GetMapId(); Map* map = MapManager::Instance().GetMap(mapid); z2 = map->GetHeight(x,y); if( abs( z2 - z ) < 5 ) z = z2; i_nextMove = 1; bool is_water_ok = creature.isCanSwimOrFly(); bool is_land_ok = creature.isCanWalkOrFly(); for(unsigned int idx=0; idx < MAX_CONF_WAYPOINTS+1; ++idx) { const float wanderX=((wander_distance*rand())/RAND_MAX)-wander_distance/2; const float wanderY=((wander_distance*rand())/RAND_MAX)-wander_distance/2; i_waypoints[idx][0] = x + wanderX; i_waypoints[idx][1] = y + wanderY; // prevent invalid coordinates generation MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]); MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]); bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1]); // if generated wrong path just ignore if( is_water && !is_water_ok || !is_water && !is_land_ok ) { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; } z2 = map->GetHeight(i_waypoints[idx][0],i_waypoints[idx][1]); if( abs( z2 - z ) < 5 ) z = z2; i_waypoints[idx][2] = z; } creature.StopMoving(); }
void reset_view() { camX = -(tileSizeX / 2) * (worldMap.GetHeight() - 1); camY = 0; input_offset = 0; input_scale = 1; }
void RandomPlayerbotMgr::RandomTeleport(Player* bot, vector<WorldLocation> &locs) { if (bot->IsBeingTeleported()) return; if (locs.empty()) { sLog->outMessage("playerbot", LOG_LEVEL_ERROR, "Cannot teleport bot %s - no locations available", bot->GetName().c_str()); return; } for (int attemtps = 0; attemtps < 10; ++attemtps) { int index = urand(0, locs.size() - 1); WorldLocation loc = locs[index]; float x = loc.m_positionX + urand(0, sPlayerbotAIConfig.grindDistance) - sPlayerbotAIConfig.grindDistance / 2; float y = loc.m_positionY + urand(0, sPlayerbotAIConfig.grindDistance) - sPlayerbotAIConfig.grindDistance / 2; float z = loc.m_positionZ; Map* map = sMapMgr->FindMap(loc.GetMapId(), 0); if (!map) continue; if (!map->IsOutdoors(x, y, z) || map->IsInWater(x, y, z)) continue; uint32 areaId = map->GetAreaId(x, y, z); if (!areaId) continue; AreaTableEntry const* area = sAreaStore.LookupEntry(areaId); if (!area) continue; float ground = map->GetHeight(x, y, z + 0.5f); if (ground <= INVALID_HEIGHT) continue; z = 0.05f + ground; sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Random teleporting bot %s to %s %f,%f,%f", bot->GetName().c_str(), area->area_name[0], x, y, z); bot->GetMotionMaster()->Clear(); bot->TeleportTo(loc.GetMapId(), x, y, z, 0); return; } sLog->outMessage("playerbot", LOG_LEVEL_ERROR, "Cannot teleport bot %s - no locations available", bot->GetName().c_str()); }
/** layerToImage * * Converts a layer into an ImageMagick Image */ int HandlerUtils::LayerToImage(const Map& map, const Layer& layer, std::vector<Magick::Image>& tiles, Magick::Image& image) { for (unsigned int i = 0; i < map.GetHeight(); i++) { for (unsigned int j = 0; j < map.GetWidth(); j++) { int index = i * map.GetWidth() + j; int tile = layer[index]; if (tile == -1) continue; image.composite(tiles[tile], j * map.GetTileWidth(), i * map.GetTileHeight(), Magick::AtopCompositeOp); } } return 0; }
/** layerToImage * * Converts a layer into an ImageMagick Image */ int HandlerUtils::LayerToImage(const Map& map, const Layer& layer, Magick::Image& image) { std::vector<Magick::Image> tiles; if (HandlerUtils::GetTiles(map, tiles)) return -1; Magick::Color color = Magick::ColorRGB(0, 0, 0); color.alpha(0); int width = map.GetWidth() * map.GetTileWidth(); int height = map.GetHeight() * map.GetTileHeight(); image.matte(true); image.resize(Magick::Geometry(width, height)); image.backgroundColor(color); image.erase(); return HandlerUtils::LayerToImage(map, layer, tiles, image); }
int main() { // Read the configuration file ConfigManager::ReadParameters(); // Read and inflate map const char* mapurl = ConfigManager::GetMapUrl().erase(ConfigManager::GetMapUrl().size() - 1).c_str(); Map* currMap = LoadMap(mapurl); int robotSize = MAX(ConfigManager::GetRobotHeight(),ConfigManager::GetRobotWidth()); double mapResulotion = ConfigManager::GetMapResolution(); int InflateAddition = ceil((robotSize / 2) / mapResulotion); Map* inflateMap = currMap->Inflate(InflateAddition); Map* Maparticle = currMap->Inflate(5); // Calculate the ratio between the grid resolution and map resolution int res = ConfigManager::GetGridResolution() / ConfigManager::GetMapResolution(); Grid* grid = new Grid(inflateMap->GetMatrix(),inflateMap->GetWidth(),inflateMap->GetHeight(), res); // A* PathPlanner* p = new PathPlanner(); Point* start = ConfigManager::GetStartLocationMapResolution(); Point* end = ConfigManager::GetGoalMapResolution(); int startGridPointX,startGridPointY, endGridPointX, endGridPointY; startGridPointX = start->GetRow() / res; startGridPointY = start->GetCol() / res; endGridPointX = end->GetRow() / res; endGridPointY = end->GetCol() / res; std::string route = p->pathFind(startGridPointX ,startGridPointY,endGridPointX,endGridPointY,grid); // WayPoint calculation Point* startWithRes = new Point(start->GetRow() / 4, start->GetCol() / 4); vector<Point *> waypointsArr = WayPoints::CalculateByDirectionalPath(route, startWithRes); Robot robot("localhost",6665); PlnObstacleAvoid plnOA(&robot); Manager manager(&robot, &plnOA, waypointsArr, Maparticle); manager.run(); }
/** MapToImage * * Converts a map into an ImageMagick Image */ int HandlerUtils::MapToImage(const Map& map, Magick::Image& image) { std::vector<Magick::Image> tiles; if (HandlerUtils::GetTiles(map, tiles)) return -1; Magick::Color color = Magick::ColorRGB(0, 0, 0); color.alpha(0); const Tileset& tileset = map.GetTileset(); uint32_t tile_width, tile_height; tileset.GetTileDimensions(tile_width, tile_height); int width = map.GetWidth() * tile_width; int height = map.GetHeight() * tile_height; image.matte(true); image.resize(Magick::Geometry(width, height)); image.backgroundColor(color); image.erase(); try { for (const auto& layer : map.GetLayers()) { if (HandlerUtils::LayerToImage(map, layer, tiles, image)) return -1; } } catch (Magick::Exception& error_) { return -1; } return 0; }
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 (!Diamond::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 ( !Diamond::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); if (plMover->GetVehicleKit()) plMover->GetVehicleKit()->RemoveAllPassengers(); 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->IsTaxiFlying()) 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); mover->m_movementInfo = movementInfo; mover->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); if (plMover) // nothing is charmed, or player charmed { 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(); } } } }
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(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)) { // 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) ); } /*----------------------*/ //---- 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()) { 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); 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); } } else if (plMover) { plMover->m_anti_AlarmCount++; WorldPacket data; 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 render(SDL_Renderer* renderer) { //draw draw space // if (input_draw_space) { // SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // // SDL_Rect rect; // rect.x = 0; // rect.y = 0; // mapToOrtho(worldMap.GetWidth(), worldMap.GetHeight(), rect.w, rect.h); // zoom(rect); // worldToScreen(rect.x, rect.y); // // SDL_RenderFillRect(renderer, &rect); // SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // } //draw map for (int y = 0; y < worldMap.GetHeight(); y++) { for (int x = 0; x < worldMap.GetWidth(); x++) { SDL_Rect rect; //in world coords rect.w = tileSizeX; rect.h = tileSizeY; mapToIso(x, y, rect.x, rect.y); zoom(rect); rect.y -= (tileSizeY*input_scale - tileWidth*input_scale); worldToScreen(rect.x, rect.y); SDL_Rect tileRect; //in tileset coords tileRect.w = tileSizeX; tileRect.h = tileSizeY; //layer terrain const int tileId = worldMap.Get(x,y).terrainId; if (tileId != -1) { int tileX; int tileY; getTileXY(tileId, &tileX, &tileY, TILESET_WIDTH); tileRect.x = tileX * tileSizeX; tileRect.y = tileY * tileSizeY; SDL_RenderCopy(renderer, tileset, &tileRect, &rect); } //layer object const int tileId2 = worldMap.Get(x, y).objectId; if (tileId2 != -1) { int tileObjX; int tileObjY; getTileXY(tileId2, &tileObjX, &tileObjY, TILESET_WIDTH); tileRect.x = tileObjX * tileSizeX; tileRect.y = tileObjY * tileSizeY; SDL_RenderCopy(renderer, tileset, &tileRect, &rect); } } } // //draw debug rect // if (input_show_debug_rect) { // SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); // for (int y = 0; y < worldMap.GetHeight(); y++) { // for (int x = 0; x < worldMap.GetWidth(); x++) { // SDL_Rect rect; // rect.w = tileSizeX; // rect.h = tileWidth; // // mapToOrtho(x,y,rect.x, rect.y); // zoom(rect); // worldToScreen(rect.x, rect.y); // // SDL_RenderDrawRect(renderer, &rect); // } // } // SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // } //show editor bar for (int i = 0; i < NB_TILES_EDITOR; i++) { SDL_Rect tileRect; //in tileset coords tileRect.w = tileSizeX; tileRect.h = tileSizeY; const int tileId = TILES_EDITOR[i]; int tileX; int tileY; getTileXY(tileId, &tileX, &tileY, TILESET_WIDTH); tileRect.x = tileX * tileSizeX; tileRect.y = tileY * tileSizeY; SDL_Rect rect; //in world coords rect.w = tileSizeX; rect.h = tileSizeY; rect.x = i * tileSizeX; rect.y = WIN_HEIGHT - tileSizeY; SDL_RenderCopy(renderer, tileset, &tileRect, &rect); } if (input_show_debug_rect) { SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); for (int x = 0; x < worldMap.GetWidth() + 1; x++) { int x1 = x; int y1 = 0; int x2 = x; int y2 = worldMap.GetHeight(); int tx1; int tx2; int ty1; int ty2; mapToIso(x1, y1, tx1, ty1); mapToIso(x2, y2, tx2, ty2); x1 = tx1; x2 = tx2; y1 = ty1; y2 = ty2; x1 += tileSizeX / 2; x2 += tileSizeX / 2; x1 *= input_scale; x2 *= input_scale; y1 *= input_scale; y2 *= input_scale; worldToScreen(x1, y1); worldToScreen(x2, y2); SDL_RenderDrawLine(renderer, x1, y1, x2, y2); } for (int y = 0; y < worldMap.GetHeight() + 1; y++) { int x1 = 0; int y1 = y; int x2 = worldMap.GetWidth(); int y2 = y; int tx1; int tx2; int ty1; int ty2; mapToIso(x1, y1, tx1, ty1); mapToIso(x2, y2, tx2, ty2); x1 = tx1; x2 = tx2; y1 = ty1; y2 = ty2; x1 += tileSizeX / 2; x2 += tileSizeX / 2; x1 *= input_scale; x2 *= input_scale; y1 *= input_scale; y2 *= input_scale; worldToScreen(x1, y1); worldToScreen(x2, y2); SDL_RenderDrawLine(renderer, x1, y1, x2, y2); } SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); } }