forked from metin2/server
388 lines
7.7 KiB
C++
388 lines
7.7 KiB
C++
|
#include "stdafx.h"
|
|||
|
#include "config.h"
|
|||
|
#include "char.h"
|
|||
|
#include "char_manager.h"
|
|||
|
#include "packet.h"
|
|||
|
#include "guild.h"
|
|||
|
#include "vector.h"
|
|||
|
#include "questmanager.h"
|
|||
|
#include "item.h"
|
|||
|
#include "horsename_manager.h"
|
|||
|
#include "locale_service.h"
|
|||
|
#include "arena.h"
|
|||
|
|
|||
|
#include "../../common/VnumHelper.h"
|
|||
|
|
|||
|
bool CHARACTER::StartRiding()
|
|||
|
{
|
|||
|
if (IsDead() == true)
|
|||
|
{
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (IsPolymorphed())
|
|||
|
{
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// <20>νõ<CEBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>
|
|||
|
LPITEM armor = GetWear(WEAR_BODY);
|
|||
|
|
|||
|
if (armor && (armor->GetVnum() >= 11901 && armor->GetVnum() <= 11904))
|
|||
|
{
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (LC_IsCanada() == true)
|
|||
|
{
|
|||
|
if (CArenaManager::instance().IsArenaMap(GetMapIndex()) == true)
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD dwMountVnum = m_chHorse ? m_chHorse->GetRaceNum() : GetMyHorseVnum();
|
|||
|
|
|||
|
if (false == CHorseRider::StartRiding())
|
|||
|
{
|
|||
|
if (GetHorseLevel() <= 0)
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʽ<EFBFBD><CABD>ϴ<EFBFBD>."));
|
|||
|
else if (GetHorseHealth() <= 0)
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><D7BE>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Դϴ<D4B4>."));
|
|||
|
else if (GetHorseStamina() <= 0)
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̳ʰ<CCB3> <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// <20><>ȯ<EFBFBD><C8AF> <20><> <20><><EFBFBD>ְ<EFBFBD>
|
|||
|
HorseSummon(false);
|
|||
|
|
|||
|
MountVnum(dwMountVnum);
|
|||
|
|
|||
|
if(test_server)
|
|||
|
sys_log(0, "Ride Horse : %s ", GetName());
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool CHARACTER::StopRiding()
|
|||
|
{
|
|||
|
if (CHorseRider::StopRiding())
|
|||
|
{
|
|||
|
quest::CQuestManager::instance().Unmount(GetPlayerID());
|
|||
|
|
|||
|
if (!IsDead() && !IsStun())
|
|||
|
{
|
|||
|
DWORD dwOldVnum = GetMountVnum();
|
|||
|
MountVnum(0);
|
|||
|
|
|||
|
// [NOTE] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ڱⰡ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
HorseSummon(true, false, dwOldVnum);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_dwMountVnum = 0;
|
|||
|
ComputePoints();
|
|||
|
UpdatePacket();
|
|||
|
}
|
|||
|
|
|||
|
PointChange(POINT_ST, 0);
|
|||
|
PointChange(POINT_DX, 0);
|
|||
|
PointChange(POINT_HT, 0);
|
|||
|
PointChange(POINT_IQ, 0);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
EVENTFUNC(horse_dead_event)
|
|||
|
{
|
|||
|
char_event_info* info = dynamic_cast<char_event_info*>( event->info );
|
|||
|
|
|||
|
if ( info == NULL )
|
|||
|
{
|
|||
|
sys_err( "horse_dead_event> <Factor> Null pointer" );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
// <Factor>
|
|||
|
LPCHARACTER ch = info->ch;
|
|||
|
if (ch == NULL) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
ch->HorseSummon(false);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void CHARACTER::SetRider(LPCHARACTER ch)
|
|||
|
{
|
|||
|
if (m_chRider)
|
|||
|
m_chRider->ClearHorseInfo();
|
|||
|
|
|||
|
m_chRider = ch;
|
|||
|
|
|||
|
if (m_chRider)
|
|||
|
m_chRider->SendHorseInfo();
|
|||
|
}
|
|||
|
|
|||
|
LPCHARACTER CHARACTER::GetRider() const
|
|||
|
{
|
|||
|
return m_chRider;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CHARACTER::HorseSummon(bool bSummon, bool bFromFar, DWORD dwVnum, const char* pPetName)
|
|||
|
{
|
|||
|
if ( bSummon )
|
|||
|
{
|
|||
|
//NOTE : summon<6F>ߴµ<DFB4> <20>̹<EFBFBD> horse<73><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƹ<EFBFBD><C6B9>͵<EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
|||
|
if( m_chHorse != NULL )
|
|||
|
return;
|
|||
|
|
|||
|
if (GetHorseLevel() <= 0)
|
|||
|
return;
|
|||
|
|
|||
|
// <20><><EFBFBD>𰡸<EFBFBD> Ÿ<><C5B8> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD>
|
|||
|
if (IsRiding())
|
|||
|
return;
|
|||
|
|
|||
|
sys_log(0, "HorseSummon : %s lv:%d bSummon:%d fromFar:%d", GetName(), GetLevel(), bSummon, bFromFar);
|
|||
|
|
|||
|
long x = GetX();
|
|||
|
long y = GetY();
|
|||
|
|
|||
|
if (GetHorseHealth() <= 0)
|
|||
|
bFromFar = false;
|
|||
|
|
|||
|
if (bFromFar)
|
|||
|
{
|
|||
|
x += (number(0, 1) * 2 - 1) * number(2000, 2500);
|
|||
|
y += (number(0, 1) * 2 - 1) * number(2000, 2500);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
x += number(-100, 100);
|
|||
|
y += number(-100, 100);
|
|||
|
}
|
|||
|
|
|||
|
m_chHorse = CHARACTER_MANAGER::instance().SpawnMob(
|
|||
|
(0 == dwVnum) ? GetMyHorseVnum() : dwVnum,
|
|||
|
GetMapIndex(),
|
|||
|
x, y,
|
|||
|
GetZ(), false, (int)(GetRotation()+180), false);
|
|||
|
|
|||
|
if (!m_chHorse)
|
|||
|
{
|
|||
|
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (GetHorseHealth() <= 0)
|
|||
|
{
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3> <20>ְ<EFBFBD> <20>ϴ<EFBFBD> ó<><C3B3>
|
|||
|
m_chHorse->SetPosition(POS_DEAD);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD><C3B0>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
|||
|
char_event_info* info = AllocEventInfo<char_event_info>();
|
|||
|
info->ch = this;
|
|||
|
m_chHorse->m_pkDeadEvent = event_create(horse_dead_event, info, PASSES_PER_SEC(60));
|
|||
|
}
|
|||
|
|
|||
|
m_chHorse->SetLevel(GetHorseLevel());
|
|||
|
|
|||
|
const char* pHorseName = CHorseNameManager::instance().GetHorseName(GetPlayerID());
|
|||
|
|
|||
|
if ( pHorseName != NULL && strlen(pHorseName) != 0 )
|
|||
|
{
|
|||
|
m_chHorse->m_stName = pHorseName;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_chHorse->m_stName = GetName();
|
|||
|
m_chHorse->m_stName += LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>");
|
|||
|
}
|
|||
|
|
|||
|
if (!m_chHorse->Show(GetMapIndex(), x, y, GetZ()))
|
|||
|
{
|
|||
|
M2_DESTROY_CHARACTER(m_chHorse);
|
|||
|
sys_err("cannot show monster");
|
|||
|
m_chHorse = NULL;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ((GetHorseHealth() <= 0))
|
|||
|
{
|
|||
|
TPacketGCDead pack;
|
|||
|
pack.header = HEADER_GC_DEAD;
|
|||
|
pack.vid = m_chHorse->GetVID();
|
|||
|
PacketAround(&pack, sizeof(pack));
|
|||
|
}
|
|||
|
|
|||
|
m_chHorse->SetRider(this);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (!m_chHorse)
|
|||
|
return;
|
|||
|
|
|||
|
LPCHARACTER chHorse = m_chHorse;
|
|||
|
|
|||
|
chHorse->SetRider(NULL); // m_chHorse assign to NULL
|
|||
|
|
|||
|
if (!bFromFar)
|
|||
|
{
|
|||
|
M2_DESTROY_CHARACTER(chHorse);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD>鼭 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3> <20>ϱ<EFBFBD>
|
|||
|
chHorse->SetNowWalking(false);
|
|||
|
float fx, fy;
|
|||
|
chHorse->SetRotation(GetDegreeFromPositionXY(chHorse->GetX(), chHorse->GetY(), GetX(), GetY())+180);
|
|||
|
GetDeltaByDegree(chHorse->GetRotation(), 3500, &fx, &fy);
|
|||
|
chHorse->Goto((long)(chHorse->GetX()+fx), (long) (chHorse->GetY()+fy));
|
|||
|
chHorse->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
|||
|
}
|
|||
|
|
|||
|
m_chHorse = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DWORD CHARACTER::GetMyHorseVnum() const
|
|||
|
{
|
|||
|
int delta = 0;
|
|||
|
|
|||
|
if (GetGuild())
|
|||
|
{
|
|||
|
++delta;
|
|||
|
|
|||
|
if (GetGuild()->GetMasterPID() == GetPlayerID())
|
|||
|
++delta;
|
|||
|
}
|
|||
|
|
|||
|
return c_aHorseStat[GetHorseLevel()].iNPCRace + delta;
|
|||
|
}
|
|||
|
|
|||
|
void CHARACTER::HorseDie()
|
|||
|
{
|
|||
|
CHorseRider::HorseDie();
|
|||
|
HorseSummon(false);
|
|||
|
}
|
|||
|
|
|||
|
bool CHARACTER::ReviveHorse()
|
|||
|
{
|
|||
|
if (CHorseRider::ReviveHorse())
|
|||
|
{
|
|||
|
HorseSummon(false);
|
|||
|
HorseSummon(true);
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
void CHARACTER::ClearHorseInfo()
|
|||
|
{
|
|||
|
if (!IsHorseRiding())
|
|||
|
{
|
|||
|
ChatPacket(CHAT_TYPE_COMMAND, "hide_horse_state");
|
|||
|
|
|||
|
m_bSendHorseLevel = 0;
|
|||
|
m_bSendHorseHealthGrade = 0;
|
|||
|
m_bSendHorseStaminaGrade = 0;
|
|||
|
}
|
|||
|
|
|||
|
m_chHorse = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void CHARACTER::SendHorseInfo()
|
|||
|
{
|
|||
|
if (m_chHorse || IsHorseRiding())
|
|||
|
{
|
|||
|
int iHealthGrade;
|
|||
|
int iStaminaGrade;
|
|||
|
/*
|
|||
|
HP
|
|||
|
3: 70% < ~ <= 100%
|
|||
|
2: 30% < ~ <= 70%
|
|||
|
1: 0% < ~ <= 30%
|
|||
|
0: <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
STM
|
|||
|
|
|||
|
3: 71% < ~ <= 100%
|
|||
|
2: 31% < ~ <= 70%
|
|||
|
1: 10% < ~ <= 30%
|
|||
|
0: ~ <= 10%
|
|||
|
*/
|
|||
|
if (GetHorseHealth() == 0)
|
|||
|
iHealthGrade = 0;
|
|||
|
else if (GetHorseHealth() * 10 <= GetHorseMaxHealth() * 3)
|
|||
|
iHealthGrade = 1;
|
|||
|
else if (GetHorseHealth() * 10 <= GetHorseMaxHealth() * 7)
|
|||
|
iHealthGrade = 2;
|
|||
|
else
|
|||
|
iHealthGrade = 3;
|
|||
|
|
|||
|
if (GetHorseStamina() * 10 <= GetHorseMaxStamina())
|
|||
|
iStaminaGrade = 0;
|
|||
|
else if (GetHorseStamina() * 10 <= GetHorseMaxStamina() * 3)
|
|||
|
iStaminaGrade = 1;
|
|||
|
else if (GetHorseStamina() * 10 <= GetHorseMaxStamina() * 7)
|
|||
|
iStaminaGrade = 2;
|
|||
|
else
|
|||
|
iStaminaGrade = 3;
|
|||
|
|
|||
|
if (m_bSendHorseLevel != GetHorseLevel() ||
|
|||
|
m_bSendHorseHealthGrade != iHealthGrade ||
|
|||
|
m_bSendHorseStaminaGrade != iStaminaGrade)
|
|||
|
{
|
|||
|
ChatPacket(CHAT_TYPE_COMMAND, "horse_state %d %d %d", GetHorseLevel(), iHealthGrade, iStaminaGrade);
|
|||
|
|
|||
|
// FIX : Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ǥ<><C7A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Լ<EFBFBD> <20><><EFBFBD>Կ<EFBFBD> return<72><6E><EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD> <20>Ʒ<EFBFBD> <20>ڵ带 <20><><EFBFBD><EFBFBD><EFBFBD>Ѵٸ<D1B4>
|
|||
|
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD><D1B4><EFBFBD> <20><>ȯ<EFBFBD>ϴ<EFBFBD> <20><><EFBFBD>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>װ<EFBFBD> <20><><EFBFBD><EFBFBD>.. <20><>Ȯ<EFBFBD><C8AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ľ<EFBFBD> <20><><EFBFBD>غ<EFBFBD><D8BA><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
|||
|
m_bSendHorseLevel = GetHorseLevel();
|
|||
|
m_bSendHorseHealthGrade = iHealthGrade;
|
|||
|
m_bSendHorseStaminaGrade = iStaminaGrade;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool CHARACTER::CanUseHorseSkill()
|
|||
|
{
|
|||
|
if(IsRiding())
|
|||
|
{
|
|||
|
if (GetHorseGrade() == 3)
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
|
|||
|
if(GetMountVnum())
|
|||
|
{
|
|||
|
if (GetMountVnum() >= 20209 && GetMountVnum() <= 20212)
|
|||
|
return true;
|
|||
|
|
|||
|
//<2F><EFBFBD> <20>渶
|
|||
|
if (CMobVnumHelper::IsRamadanBlackHorse(GetMountVnum()))
|
|||
|
return true;
|
|||
|
}
|
|||
|
else
|
|||
|
return false;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
void CHARACTER::SetHorseLevel(int iLevel)
|
|||
|
{
|
|||
|
CHorseRider::SetHorseLevel(iLevel);
|
|||
|
SetSkillLevel(SKILL_HORSE, GetHorseLevel());
|
|||
|
}
|
|||
|
|