void CUser::Warp(uint16 sPosX, uint16 sPosZ) { ASSERT(GetMap() != nullptr); if (m_bWarp) return; float real_x = sPosX / 10.0f, real_z = sPosZ / 10.0f; if (!GetMap()->IsValidPosition(real_x, real_z, 0.0f)) { TRACE("Invalid position %f,%f\n", real_x, real_z); return; } Packet result(WIZ_WARP); result << sPosX << sPosZ; Send(&result); UserInOut(INOUT_OUT); m_curx = real_x; m_curz = real_z; SetRegion(GetNewRegionX(), GetNewRegionZ()); UserInOut(INOUT_WARP); g_pMain->UserInOutForMe(this); g_pMain->NpcInOutForMe(this); g_pMain->MerchantUserInOutForMe(this); ResetWindows(); }
void CUser::RecvZoneChange(Packet & pkt) { if (isDead()) // we also need to make sure we're actually waiting on this request... return; uint8 opcode = pkt.read<uint8>(); if (opcode == 1) { g_pMain->UserInOutForMe(this); g_pMain->NpcInOutForMe(this); g_pMain->MerchantUserInOutForMe(this); Packet result(WIZ_ZONE_CHANGE, uint8(2)); // finalise the zone change Send(&result); } else if (opcode == 2) { UserInOut(INOUT_RESPAWN); // TO-DO: Fix all this up (it's too messy/confusing) if (!m_bZoneChangeSameZone) { BlinkStart(); RecastSavedMagic(); } m_bZoneChangeFlag = 0; m_bWarp = 0; } }
void CUser::Warp(char *pBuf) { ASSERT(GetMap() != NULL); if( m_bWarp ) return; int index = 0, send_index = 0; WORD warp_x, warp_z; float real_x, real_z; char send_buff[128]; warp_x = GetShort( pBuf, index ); warp_z = GetShort( pBuf, index ); real_x = warp_x/10.0f; real_z = warp_z/10.0f; if (!GetMap()->IsValidPosition(real_x, real_z, 0.0f)) { TRACE("Invalid position %f,%f\n", real_x, real_z); return; } SetByte(send_buff, WIZ_WARP, send_index); SetShort(send_buff, warp_x, send_index); SetShort(send_buff, warp_z, send_index); Send(send_buff, send_index); UserInOut(USER_OUT); m_pUserData->m_curx = m_fWill_x = real_x; m_pUserData->m_curz = m_fWill_z = real_z; m_RegionX = (int)(m_pUserData->m_curx / VIEW_DISTANCE); m_RegionZ = (int)(m_pUserData->m_curz / VIEW_DISTANCE); //TRACE(" Warp ,, name=%s, x=%.2f, z=%.2f\n", m_pUserData->m_id, m_pUserData->m_curx, m_pUserData->m_curz); UserInOut(USER_WARP); m_pMain->UserInOutForMe(this); m_pMain->NpcInOutForMe(this); m_pMain->MerchantUserInOutForMe(this); ResetWindows(); }
// This packet actually contains the char name after the opcode void CUser::GameStart(char *pBuf) { int index = 0; BYTE opcode = GetByte(pBuf, index); if (opcode == 1) { SendMyInfo(); m_pMain->UserInOutForMe(this); m_pMain->NpcInOutForMe(this); SendNotice(); SendTimeStatus(); // SendHackToolList(); char send_buff[] = { WIZ_GAMESTART }; Send(send_buff, sizeof(send_buff)); } else if (opcode == 2) { m_State = STATE_GAMESTART; UserInOut(USER_REGENE); if (!m_pUserData->m_bCity && m_pUserData->m_sHp <= 0) m_pUserData->m_bCity = -1; if (m_pUserData->m_bCity > 0) { int level = m_pUserData->m_bLevel; if (m_pUserData->m_bCity <= 100) level--; // make sure we don't exceed bounds if (level > MAX_LEVEL) level = MAX_LEVEL; else if (level < 1) level = 1; m_iLostExp = (m_pMain->GetExpByLevel(level) * (m_pUserData->m_bCity % 10) / 100); if (((m_pUserData->m_bCity % 10) / 100) == 1) m_iLostExp /= 2; } else { m_iLostExp = 0; } BlinkStart(); SetUserAbility(); // rental // ItemMallMagicRecast(); } }
// This packet actually contains the char name after the opcode void CUser::GameStart(Packet & pkt) { if (isInGame()) return; uint8 opcode = pkt.read<uint8>(); if (opcode == 1) { SendMyInfo(); g_pMain->UserInOutForMe(this); g_pMain->MerchantUserInOutForMe(this); g_pMain->NpcInOutForMe(this); SendNotice(); SendTime(); SendWeather(); // SendHackToolList(); Packet result(WIZ_GAMESTART); Send(&result); } else if (opcode == 2) { m_state = GAME_STATE_INGAME; UserInOut(INOUT_RESPAWN); if (!m_bCity && m_sHp <= 0) m_bCity = -1; if (m_bCity > 0) { int level = GetLevel(); if (m_bCity <= 100) level--; // make sure we don't exceed bounds if (level > MAX_LEVEL) level = MAX_LEVEL; else if (level < 1) level = 1; m_iLostExp = (g_pMain->GetExpByLevel(level) * (m_bCity % 10) / 100); if (((m_bCity % 10) / 100) == 1) m_iLostExp /= 2; } else { m_iLostExp = 0; } CheckSeedQuest(); BlinkStart(); SetUserAbility(); // rental RecastSavedMagic(m_sHp == m_iMaxHp ? true : false); //ItemMallRecast // If we've relogged while dead, we need to make sure the client // is still given the option to revive. if (isDead()) SendDeathAnimation(); g_pMain->TempleEventGetActiveEventTime(this); } m_tHPLastTimeNormal = UNIXTIME; }
void CUser::ZoneChange(int zone, float x, float z) { m_bZoneChangeFlag = true; C3DMap* pMap = nullptr; _ZONE_SERVERINFO *pInfo = nullptr; pMap = g_pMain->GetZoneByID(zone); if (!pMap) return; if( pMap->m_bType == 2 ) { // If Target zone is frontier zone. if( GetLevel() < 20 && g_pMain->m_byBattleOpen != SNOW_BATTLE) return; } if( g_pMain->m_byBattleOpen == NATION_BATTLE ) { // Battle zone open if( m_bZone == BATTLE_ZONE ) { if( pMap->m_bType == 1 && m_bNation != zone && (zone < 10 || zone > 21)) { // ???? ?????? ???? ????.. if( m_bNation == KARUS && !g_pMain->m_byElmoradOpenFlag ) { TRACE("#### ZoneChange Fail ,,, id=%s, nation=%d, flag=%d\n", GetName().c_str(), m_bNation, g_pMain->m_byElmoradOpenFlag); return; } else if( m_bNation == ELMORAD && !g_pMain->m_byKarusOpenFlag ) { TRACE("#### ZoneChange Fail ,,, id=%s, nation=%d, flag=%d\n", GetName().c_str(), m_bNation, g_pMain->m_byKarusOpenFlag); return; } } } else if( pMap->m_bType == 1 && m_bNation != zone && (zone < 10 || zone > 21)) { // ???? ?????? ???? ????.. return; } // else if( pMap->m_bType == 2 && zone == ZONE_RONARK_LAND ) { // You can't go to frontier zone when Battlezone is open. Packet result(WIZ_WARP_LIST, uint8(2)); result << uint8(0); Send(&result); return; } // } else if( g_pMain->m_byBattleOpen == SNOW_BATTLE ) { // Snow Battle zone open if( pMap->m_bType == 1 && m_bNation != zone ) { // ???? ?????? ???? ????.. return; } else if( pMap->m_bType == 2 && (zone == ZONE_RONARK_LAND || zone == ZONE_BATTLE ) ) { // You can't go to frontier zone when Battlezone is open. return; } } else { // Battle zone close if( pMap->m_bType == 1 && m_bNation != zone && (zone < 10 || zone > 21)) return; } m_bWarp = 0x01; UserInOut(INOUT_OUT); if( m_bZone == ZONE_SNOW_BATTLE ) { //TRACE("ZoneChange - name=%s\n", m_id); SetMaxHp( 1 ); } bool bSameZone = (GetZoneID() == zone); m_bZone = zone; m_curx = x; m_curz = z; if (!bSameZone) { SetZoneAbilityChange(); // Reset the user's anger gauge when leaving the zone // Unknown if this is official behaviour, but it's logical. if (GetAngerGauge() > 0) UpdateAngerGauge(0); /* Here we also send a clan packet with subopcode 0x16 (with a byte flag of 2) if war zone/Moradon or subopcode 0x17 (with nWarEnemyID) for all else */ #if 0 if (isInClan()) { CKnights * pKnights = g_pMain->GetClanPtr(GetClanID()); if (pKnights != nullptr && pKnights->bKnightsWarStarted) { Packet clanPacket(WIZ_KNIGHTS_PROCESS); if ((GetZoneID() / 100) == 1 || GetZoneID() == 21) clanPacket << uint8(0x17) << uint8(2); else clanPacket << uint16(0x16) << uint16(0 /*nWarEnemyID*/); Send(&clanPacket); } } #endif if (GetZoneID() == ZONE_SNOW_BATTLE) { SetMaxHp(); } if (isInParty()) PartyRemove(GetSocketID()); ResetWindows(); } m_pMap = pMap; if( g_pMain->m_nServerNo != pMap->m_nServerNo ) { pInfo = g_pMain->m_ServerArray.GetData( pMap->m_nServerNo ); if( !pInfo ) return; UserDataSaveToAgent(); m_bLogout = 2; // server change flag SendServerChange(pInfo->strServerIP, 2); return; } SetRegion(GetNewRegionX(), GetNewRegionZ()); Packet result(WIZ_ZONE_CHANGE, uint8(3)); // magic numbers, sigh. result << uint16(GetZoneID()) << GetSPosX() << GetSPosZ() << GetSPosY() << g_pMain->m_byOldVictory; Send(&result); if (!m_bZoneChangeSameZone) { m_sWhoKilledMe = -1; m_iLostExp = 0; m_bRegeneType = 0; m_tLastRegeneTime = 0; m_sBind = -1; InitType3(); InitType4(); CMagicProcess::CheckExpiredType9Skills(this, true); SetUserAbility(); } result.Initialize(AG_ZONE_CHANGE); result << GetSocketID() << GetZoneID(); Send_AIServer(&result); m_bZoneChangeSameZone = false; m_bZoneChangeFlag = false; }
void CUser::ZoneChange(int zone, float x, float z) { m_bZoneChangeFlag = TRUE; int send_index = 0, zoneindex = 0; char send_buff[128]; C3DMap* pMap = NULL; _ZONE_SERVERINFO *pInfo = NULL; if( g_serverdown_flag ) return; pMap = m_pMain->GetZoneByID(zone); if (!pMap) return; m_pMap = pMap; if( pMap->m_bType == 2 ) { // If Target zone is frontier zone. if( m_pUserData->m_bLevel < 20 && m_pMain->m_byBattleOpen != SNOW_BATTLE) return; } if( m_pMain->m_byBattleOpen == NATION_BATTLE ) { // Battle zone open if( m_pUserData->m_bZone == BATTLE_ZONE ) { if( pMap->m_bType == 1 && m_pUserData->m_bNation != zone ) { // ???? ?????? ???? ????.. if( m_pUserData->m_bNation == KARUS && !m_pMain->m_byElmoradOpenFlag ) { TRACE("#### ZoneChange Fail ,,, id=%s, nation=%d, flag=%d\n", m_pUserData->m_id, m_pUserData->m_bNation, m_pMain->m_byElmoradOpenFlag); return; } else if( m_pUserData->m_bNation == ELMORAD && !m_pMain->m_byKarusOpenFlag ) { TRACE("#### ZoneChange Fail ,,, id=%s, nation=%d, flag=%d\n", m_pUserData->m_id, m_pUserData->m_bNation, m_pMain->m_byKarusOpenFlag); return; } } } else if( pMap->m_bType == 1 && m_pUserData->m_bNation != zone ) { // ???? ?????? ???? ????.. return; } // else if( pMap->m_bType == 2 && zone == ZONE_FRONTIER ) { // You can't go to frontier zone when Battlezone is open. int temp_index = 0; char temp_buff[3]; SetByte( temp_buff, WIZ_WARP_LIST, temp_index ); SetByte( temp_buff, 2, temp_index ); SetByte( temp_buff,0, temp_index ); Send(temp_buff, temp_index); // return; } // } else if( m_pMain->m_byBattleOpen == SNOW_BATTLE ) { // Snow Battle zone open if( pMap->m_bType == 1 && m_pUserData->m_bNation != zone ) { // ???? ?????? ???? ????.. return; } else if( pMap->m_bType == 2 && (zone == ZONE_FRONTIER || zone == ZONE_BATTLE ) ) { // You can't go to frontier zone when Battlezone is open. return; } } else { // Battle zone close if( pMap->m_bType == 1 && m_pUserData->m_bNation != zone && (zone < 10 || zone > 20)) // ???? ?????? ???? ????.. return; } m_bWarp = 0x01; UserInOut( USER_OUT ); if( m_pUserData->m_bZone == ZONE_SNOW_BATTLE ) { //TRACE("ZoneChange - name=%s\n", m_pUserData->m_id); SetMaxHp( 1 ); } m_pUserData->m_bZone = zone; m_pUserData->m_curx = m_fWill_x = x; m_pUserData->m_curz = m_fWill_z = z; if( m_pUserData->m_bZone == ZONE_SNOW_BATTLE ) { //TRACE("ZoneChange - name=%s\n", m_pUserData->m_id); SetMaxHp(); } PartyRemove(m_Sid); // ??????? Z?????? ó?? //TRACE("ZoneChange ,,, id=%s, nation=%d, zone=%d, x=%.2f, z=%.2f\n", m_pUserData->m_id, m_pUserData->m_bNation, zone, x, z); if( m_pMain->m_nServerNo != pMap->m_nServerNo ) { pInfo = m_pMain->m_ServerArray.GetData( pMap->m_nServerNo ); if( !pInfo ) return; UserDataSaveToAgent(); CTime t = CTime::GetCurrentTime(); m_pMain->WriteLog("[ZoneChange : %d-%d-%d] - sid=%d, acname=%s, name=%s, zone=%d, x=%d, z=%d \r\n", t.GetHour(), t.GetMinute(), t.GetSecond(), m_Sid, m_strAccountID, m_pUserData->m_id, zone, (int)x, (int)z); m_pUserData->m_bLogout = 2; // server change flag SendServerChange(pInfo->strServerIP, 2); return; } m_pUserData->m_sBind = -1; // Bind Point Clear... m_RegionX = (int)(m_pUserData->m_curx / VIEW_DISTANCE); m_RegionZ = (int)(m_pUserData->m_curz / VIEW_DISTANCE); SetByte( send_buff, WIZ_ZONE_CHANGE, send_index ); SetByte( send_buff, 0x03, send_index ); SetByte( send_buff, m_pUserData->m_bZone, send_index ); SetShort( send_buff, (WORD)m_pUserData->m_curx*10, send_index ); SetShort( send_buff, (WORD)m_pUserData->m_curz*10, send_index ); SetShort( send_buff, (short)m_pUserData->m_cury*10, send_index ); SetByte( send_buff, m_pMain->m_byOldVictory, send_index ); Send( send_buff, send_index ); if (!m_bZoneChangeSameZone) { m_sWhoKilledMe = -1; m_iLostExp = 0; m_bRegeneType = 0; m_fLastRegeneTime = 0.0f; m_pUserData->m_sBind = -1; InitType3(); InitType4(); } if (m_bZoneChangeSameZone) { m_bZoneChangeSameZone = FALSE; } send_index = 0; SetByte( send_buff, AG_ZONE_CHANGE, send_index ); SetShort( send_buff, m_Sid, send_index ); SetByte( send_buff, getZoneID(), send_index ); m_pMain->Send_AIServer(send_buff, send_index); m_bZoneChangeFlag = FALSE; }
void CUser::Regene(uint8 regene_type, uint32 magicid /*= 0*/) { ASSERT(GetMap() != nullptr); _OBJECT_EVENT* pEvent = nullptr; _HOME_INFO* pHomeInfo = nullptr; float x = 0.0f, z = 0.0f; if (!isDead()) return; if (regene_type != 1 && regene_type != 2) regene_type = 1; if (regene_type == 2) { magicid = 490041; // The Stone of Ressurection magic ID // Is our level high enough to be able to resurrect using this skill? if (GetLevel() <= 5 // Do we have enough resurrection stones? || !RobItem(379006000, 3 * GetLevel())) return; } // If we're in a home zone, we'll want the coordinates from there. Otherwise, assume our own home zone. pHomeInfo = g_pMain->m_HomeArray.GetData(GetZoneID() <= ZONE_ELMORAD ? GetZoneID() : GetNation()); if (pHomeInfo == nullptr) return; UserInOut(INOUT_OUT); pEvent = GetMap()->GetObjectEvent(m_sBind); // If we're not using a spell to resurrect. if (magicid == 0) { // Resurrect at a bind/respawn point if (pEvent != nullptr && pEvent->byLife == 1) { SetPosition(pEvent->fPosX + x, 0.0f, pEvent->fPosZ + z); } // Are we trying to respawn in a home zone? else if (GetZoneID() <= ZONE_ELMORAD) { // Use the proper respawn area for our nation, as the opposite nation can // enter this zone at a war's invasion stage. if (GetNation() == KARUS) { x = (float)(pHomeInfo->KarusZoneX + myrand(0, pHomeInfo->KarusZoneLX)); z = (float)(pHomeInfo->KarusZoneZ + myrand(0, pHomeInfo->KarusZoneLZ)); } else { x = (float)(pHomeInfo->ElmoZoneX + myrand(0, pHomeInfo->ElmoZoneLX)); z = (float)(pHomeInfo->ElmoZoneZ + myrand(0, pHomeInfo->ElmoZoneLZ)); } } else { // If we're in a war zone (aside from snow wars, which apparently use different coords), use BattleZone coordinates. if (GetZoneID() != ZONE_SNOW_BATTLE && GetZoneID() == (ZONE_BATTLE_BASE + g_pMain->m_byBattleZone)) { x = (float)(pHomeInfo->BattleZoneX + myrand(0, pHomeInfo->BattleZoneLX)); z = (float)(pHomeInfo->BattleZoneZ + myrand(0, pHomeInfo->BattleZoneLZ)); } // If we died in the Moradon arena, we need to spawn near the Arena. else if (GetZoneID() == ZONE_MORADON && isInArena()) { x = (float)(MINI_ARENA_RESPAWN_X + myrand(-MINI_ARENA_RESPAWN_RADIUS, MINI_ARENA_RESPAWN_RADIUS)); z = (float)(MINI_ARENA_RESPAWN_Z + myrand(-MINI_ARENA_RESPAWN_RADIUS, MINI_ARENA_RESPAWN_RADIUS)); } // For all else, just grab the start position (/town coordinates) from the START_POSITION table. else { short sx, sz; GetStartPosition(sx, sz); x = sx; z = sz; } } SetPosition(x, 0.0f, z); m_bResHpType = USER_STANDING; m_bRegeneType = REGENE_NORMAL; } else // we're respawning using a resurrect skill. { _MAGIC_TYPE5 * pType = g_pMain->m_Magictype5Array.GetData(magicid); if (pType == nullptr) return; MSpChange(-m_iMaxMp); // reset us to 0 MP. if (m_sWhoKilledMe == -1) ExpChange((m_iLostExp * pType->bExpRecover) / 100); // Restore m_bResHpType = USER_STANDING; m_bRegeneType = REGENE_MAGIC; } Packet result(WIZ_REGENE); result << GetSPosX() << GetSPosZ() << GetSPosY(); Send(&result); HpChange(GetMaxHealth()); m_tLastRegeneTime = UNIXTIME; m_sWhoKilledMe = -1; m_iLostExp = 0; if (magicid == 0) BlinkStart(); if (!isBlinking()) { result.Initialize(AG_USER_REGENE); result << GetSocketID() << m_sHp; Send_AIServer(&result); } SetRegion(GetNewRegionX(), GetNewRegionZ()); UserInOut(INOUT_RESPAWN); g_pMain->RegionUserInOutForMe(this); g_pMain->RegionNpcInfoForMe(this); InitializeStealth(); SendUserStatusUpdate(USER_STATUS_DOT, USER_STATUS_CURE); SendUserStatusUpdate(USER_STATUS_POISON, USER_STATUS_CURE); if (isInArena()) SendUserStatusUpdate(USER_STATUS_SPEED, USER_STATUS_CURE); RecastSavedMagic(); // If we actually respawned (i.e. we weren't resurrected by a skill)... if (magicid == 0) { // In PVP zones (not war zones), we must kick out players if they no longer // have any national points. if (GetMap()->isNationPVPZone() && GetMap()->isWarZone() && GetLoyalty() == 0) KickOutZoneUser(false); } }
void CUser::Regene(uint8 regene_type, uint32 magicid /*= 0*/) { ASSERT(GetMap() != NULL); CUser* pUser = NULL; _OBJECT_EVENT* pEvent = NULL; _HOME_INFO* pHomeInfo = NULL; _MAGIC_TYPE5* pType = NULL; if (!isDead()) return; InitType3(); InitType4(); if (regene_type != 1 && regene_type != 2) { regene_type = 1; } if (regene_type == 2) { magicid = 490041; // The Stone of Ressurection magic ID if (!RobItem(379006000, 3 * GetLevel())) { return; // Subtract resurrection stones. } if (GetLevel() <= 5) { return; // 5 level minimum. } } pHomeInfo = g_pMain->m_HomeArray.GetData(m_pUserData->m_bNation); if (!pHomeInfo) return; UserInOut(INOUT_OUT); float x = 0.0f, z = 0.0f; x = (float)(myrand( 0, 400 )/100.0f); z = (float)(myrand( 0, 400 )/100.0f); if( x < 2.5f ) x = 1.5f + x; if( z < 2.5f ) z = 1.5f + z; pEvent = GetMap()->GetObjectEvent(m_pUserData->m_sBind); // TO-DO: Clean this entire thing up. Wow. if (magicid == 0) { if( pEvent && pEvent->byLife == 1 ) { // Bind Point m_pUserData->m_curx = pEvent->fPosX + x; m_pUserData->m_curz = pEvent->fPosZ + z; m_pUserData->m_cury = 0; } else if( m_pUserData->m_bNation != m_pUserData->m_bZone) { // Free Zone or Opposite Zone if(m_pUserData->m_bZone > 200) { // Frontier Zone... x = (float)(pHomeInfo->FreeZoneX + myrand(0, pHomeInfo->FreeZoneLX)); z = (float)(pHomeInfo->FreeZoneZ + myrand(0, pHomeInfo->FreeZoneLZ)); } // else if(m_pUserData->m_bZone > 100 && m_pUserData->m_bZone < 200) { // Battle Zone... /* m_bResHpType = USER_STANDING; HpChange( m_iMaxHp ); KickOutZoneUser(); // Go back to your own zone! return; */ x = (float)(pHomeInfo->BattleZoneX + myrand(0, pHomeInfo->BattleZoneLX)); z = (float)(pHomeInfo->BattleZoneZ + myrand(0, pHomeInfo->BattleZoneLZ)); if (m_pUserData->m_bZone == ZONE_SNOW_BATTLE) { x = (float)(pHomeInfo->FreeZoneX + myrand(0, pHomeInfo->FreeZoneLX)); z = (float)(pHomeInfo->FreeZoneZ + myrand(0, pHomeInfo->FreeZoneLZ)); } } else if (m_pUserData->m_bZone > 10 && m_pUserData->m_bZone < 20) { x = (float)(527 + myrand(0, 10)); z = (float)(543 + myrand(0, 10)); } else if (m_pUserData->m_bZone < 3) { // Specific Lands... if (m_pUserData->m_bNation == KARUS) { x = (float)(pHomeInfo->ElmoZoneX + myrand(0, pHomeInfo->ElmoZoneLX)); z = (float)(pHomeInfo->ElmoZoneZ + myrand(0, pHomeInfo->ElmoZoneLZ)); } else if (m_pUserData->m_bNation == ELMORAD) { x = (float)(pHomeInfo->KarusZoneX + myrand(0, pHomeInfo->KarusZoneLX)); z = (float)(pHomeInfo->KarusZoneZ + myrand(0, pHomeInfo->KarusZoneLZ)); } else return; } else { short sx, sz; GetStartPosition(sx, sz); x = sx; z = sz; } m_pUserData->m_curx = x; m_pUserData->m_curz = z; } else { if (m_pUserData->m_bNation == KARUS) { x = (float)(pHomeInfo->KarusZoneX + myrand(0, pHomeInfo->KarusZoneLX)); z = (float)(pHomeInfo->KarusZoneZ + myrand(0, pHomeInfo->KarusZoneLZ)); } else if (m_pUserData->m_bNation == ELMORAD) { x = (float)(pHomeInfo->ElmoZoneX + myrand(0, pHomeInfo->ElmoZoneLX)); z = (float)(pHomeInfo->ElmoZoneZ + myrand(0, pHomeInfo->ElmoZoneLZ)); } else return; m_pUserData->m_curx = x; m_pUserData->m_curz = z; } } Packet result(WIZ_REGENE); result << GetSPosX() << GetSPosZ() << GetSPosY(); Send(&result); if (magicid > 0) { // Clerical Resurrection. pType = g_pMain->m_Magictype5Array.GetData(magicid); if ( !pType ) return; m_bResHpType = USER_STANDING; MSpChange(-m_iMaxMp); // Empty out MP. if (m_sWhoKilledMe == -1 && regene_type == 1) { ExpChange((m_iLostExp * pType->bExpRecover) / 100); // Restore Target Experience. } m_bRegeneType = REGENE_MAGIC; } else { // Normal Regene. // m_bAbnormalType = ABNORMAL_BLINKING; // m_bResHpType = USER_STANDING; m_bRegeneType = REGENE_NORMAL; } HpChange(m_iMaxHp); m_fLastRegeneTime = TimeGet(); m_sWhoKilledMe = -1; m_iLostExp = 0; if (!isBlinking()) { result.Initialize(AG_USER_REGENE); result << GetSocketID() << m_pUserData->m_sHp; g_pMain->Send_AIServer(&result); } SetRegion(GetNewRegionX(), GetNewRegionZ()); UserInOut(INOUT_RESPAWN); g_pMain->RegionUserInOutForMe(this); g_pMain->RegionNpcInfoForMe(this); BlinkStart(); if (isInParty()) { // TO-DO: Wrap these up into Party-specific methods (nothing for that yet) // UPDATE: Sticking them in the CUser class for the moment. Need to have them make sense, though. if (!m_bType3Flag) SendPartyStatusUpdate(1); if (!m_bType4Flag) SendPartyStatusUpdate(2); } }
void CUser::ZoneChange(int zone, float x, float z) { m_bZoneChangeFlag = TRUE; C3DMap* pMap = NULL; _ZONE_SERVERINFO *pInfo = NULL; pMap = g_pMain->GetZoneByID(zone); if (!pMap) return; if( pMap->m_bType == 2 ) { // If Target zone is frontier zone. if( GetLevel() < 20 && g_pMain->m_byBattleOpen != SNOW_BATTLE) return; } if( g_pMain->m_byBattleOpen == NATION_BATTLE ) { // Battle zone open if( m_pUserData.m_bZone == BATTLE_ZONE ) { if( pMap->m_bType == 1 && m_pUserData.m_bNation != zone ) { // ???? ?????? ???? ????.. if( m_pUserData.m_bNation == KARUS && !g_pMain->m_byElmoradOpenFlag ) { TRACE("#### ZoneChange Fail ,,, id=%s, nation=%d, flag=%d\n", m_pUserData.m_id, m_pUserData.m_bNation, g_pMain->m_byElmoradOpenFlag); return; } else if( m_pUserData.m_bNation == ELMORAD && !g_pMain->m_byKarusOpenFlag ) { TRACE("#### ZoneChange Fail ,,, id=%s, nation=%d, flag=%d\n", m_pUserData.m_id, m_pUserData.m_bNation, g_pMain->m_byKarusOpenFlag); return; } } } else if( pMap->m_bType == 1 && m_pUserData.m_bNation != zone ) { // ???? ?????? ???? ????.. return; } // else if( pMap->m_bType == 2 && zone == ZONE_FRONTIER ) { // You can't go to frontier zone when Battlezone is open. int temp_index = 0; char temp_buff[3]; SetByte( temp_buff, WIZ_WARP_LIST, temp_index ); SetByte( temp_buff, 2, temp_index ); SetByte( temp_buff,0, temp_index ); Send(temp_buff, temp_index); // return; } // } else if( g_pMain->m_byBattleOpen == SNOW_BATTLE ) { // Snow Battle zone open if( pMap->m_bType == 1 && m_pUserData.m_bNation != zone ) { // ???? ?????? ???? ????.. return; } else if( pMap->m_bType == 2 && (zone == ZONE_FRONTIER || zone == ZONE_BATTLE ) ) { // You can't go to frontier zone when Battlezone is open. return; } } else { // Battle zone close if( pMap->m_bType == 1 && m_pUserData.m_bNation != zone && (zone < 10 || zone > 21)) return; } m_bWarp = 0x01; UserInOut(INOUT_OUT); if( m_pUserData.m_bZone == ZONE_SNOW_BATTLE ) { //TRACE("ZoneChange - name=%s\n", m_pUserData.m_id); SetMaxHp( 1 ); } m_pUserData.m_bZone = zone; m_pUserData.m_curx = x; m_pUserData.m_curz = z; m_pMap = pMap; if( m_pUserData.m_bZone == ZONE_SNOW_BATTLE ) { //TRACE("ZoneChange - name=%s\n", m_pUserData.m_id); SetMaxHp(); } PartyRemove(GetSocketID()); // ??????? Z?????? ó?? //TRACE("ZoneChange ,,, id=%s, nation=%d, zone=%d, x=%.2f, z=%.2f\n", m_pUserData.m_id, m_pUserData.m_bNation, zone, x, z); if( g_pMain->m_nServerNo != pMap->m_nServerNo ) { pInfo = g_pMain->m_ServerArray.GetData( pMap->m_nServerNo ); if( !pInfo ) return; UserDataSaveToAgent(); CTime t = CTime::GetCurrentTime(); g_pMain->WriteLog("[ZoneChange : %d-%d-%d] - sid=%d, acname=%s, name=%s, zone=%d, x=%d, z=%d \r\n", t.GetHour(), t.GetMinute(), t.GetSecond(), GetSocketID(), m_strAccountID, m_pUserData.m_id, zone, (int)x, (int)z); m_pUserData.m_bLogout = 2; // server change flag SendServerChange(pInfo->strServerIP, 2); return; } SetRegion(GetNewRegionX(), GetNewRegionZ()); Packet result(WIZ_ZONE_CHANGE, uint8(3)); // magic numbers, sigh. result << uint16(GetZoneID()) << GetSPosX() << GetSPosZ() << GetSPosY() << g_pMain->m_byOldVictory; Send(&result); if (!m_bZoneChangeSameZone) { m_sWhoKilledMe = -1; m_iLostExp = 0; m_bRegeneType = 0; m_fLastRegeneTime = 0.0f; m_pUserData.m_sBind = -1; InitType3(); InitType4(); } result.Initialize(AG_ZONE_CHANGE); result << GetSocketID() << GetZoneID(); g_pMain->Send_AIServer(&result); m_bZoneChangeSameZone = FALSE; m_bZoneChangeFlag = FALSE; }
void CUser::ZoneChange(uint16 sNewZone, float x, float z) { C3DMap * pMap = g_pMain->GetZoneByID(sNewZone); if (pMap == nullptr) return; ZoneChangeError errorReason; if (!CanChangeZone(pMap, errorReason)) { Packet result; switch (errorReason) { case ZoneChangeErrorWrongLevel: /* this will depend on the zone */ break; case ZoneChangeErrorWarActive: result.Initialize(WIZ_WARP_LIST); result << uint8(2) << uint8(4); Send(&result); break; case ZoneChangeErrorNeedLoyalty: /* does this have an error? */ break; } return; } m_bWarp = true; m_bZoneChangeFlag = true; UserInOut(INOUT_OUT); if (sNewZone == ZONE_SNOW_BATTLE) SetMaxHp(1); if (GetZoneID() != sNewZone) { SetZoneAbilityChange(); // Reset the user's anger gauge when leaving the zone // Unknown if this is official behaviour, but it's logical. if (GetAngerGauge() > 0) UpdateAngerGauge(0); /* Here we also send a clan packet with subopcode 0x16 (with a byte flag of 2) if war zone/Moradon or subopcode 0x17 (with nWarEnemyID) for all else */ #if 0 if (isInClan()) { CKnights * pKnights = g_pMain->GetClanPtr(GetClanID()); if (pKnights != nullptr && pKnights->bKnightsWarStarted) { Packet clanPacket(WIZ_KNIGHTS_PROCESS); if (pMap->isWarZone() || byNewZone == ZONE_MORADON) clanPacket << uint8(0x17) << uint8(2); else clanPacket << uint16(0x16) << uint16(0 /*nWarEnemyID*/); Send(&clanPacket); } } #endif if (sNewZone == ZONE_SNOW_BATTLE) SetMaxHp(); if (isInParty()) PartyRemove(GetSocketID()); ResetWindows(); } m_bZone = (uint8) sNewZone; // this is 2 bytes to support the warp data loaded from SMDs. It should not go above a byte, however. SetPosition(x, 0.0f, z); m_pMap = pMap; if (g_pMain->m_nServerNo != pMap->m_nServerNo) { _ZONE_SERVERINFO *pInfo = g_pMain->m_ServerArray.GetData(pMap->m_nServerNo); if (pInfo == nullptr) return; UserDataSaveToAgent(); m_bLogout = 2; // server change flag SendServerChange(pInfo->strServerIP, 2); return; } SetRegion(GetNewRegionX(), GetNewRegionZ()); Packet result(WIZ_ZONE_CHANGE, uint8(ZoneChangeTeleport)); result << uint16(GetZoneID()) << GetSPosX() << GetSPosZ() << GetSPosY() << g_pMain->m_byOldVictory; Send(&result); if (!m_bZoneChangeSameZone) { m_sWhoKilledMe = -1; m_iLostExp = 0; m_bRegeneType = 0; m_tLastRegeneTime = 0; m_sBind = -1; InitType3(); InitType4(); CMagicProcess::CheckExpiredType9Skills(this, true); SetUserAbility(); } result.Initialize(AG_ZONE_CHANGE); result << GetSocketID() << GetZoneID(); Send_AIServer(&result); m_bZoneChangeSameZone = false; m_bZoneChangeFlag = false; }