forked from metin2/server
637 lines
15 KiB
C++
637 lines
15 KiB
C++
|
#include "stdafx.h"
|
|||
|
#include "utils.h"
|
|||
|
#include "vector.h"
|
|||
|
#include "char.h"
|
|||
|
#include "sectree_manager.h"
|
|||
|
#include "char_manager.h"
|
|||
|
#include "mob_manager.h"
|
|||
|
#include "PetSystem.h"
|
|||
|
#include "../../common/VnumHelper.h"
|
|||
|
#include "packet.h"
|
|||
|
#include "item_manager.h"
|
|||
|
#include "item.h"
|
|||
|
|
|||
|
|
|||
|
extern int passes_per_sec;
|
|||
|
EVENTINFO(petsystem_event_info)
|
|||
|
{
|
|||
|
CPetSystem* pPetSystem;
|
|||
|
};
|
|||
|
|
|||
|
// PetSystem<65><6D> update <20><><EFBFBD>ִ<EFBFBD> event.
|
|||
|
// PetSystem<65><6D> CHRACTER_MANAGER<45><52><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> FSM<53><4D><EFBFBD><EFBFBD> update <20><><EFBFBD>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> chracters<72><73> <20><EFBFBD>,
|
|||
|
// Owner<65><72> STATE<54><45> update <20><> <20><> _UpdateFollowAI <20>Լ<EFBFBD><D4BC><EFBFBD> update <20><><EFBFBD>ش<EFBFBD>.
|
|||
|
// <20><EFBFBD><D7B7><EFBFBD> owner<65><72> state<74><65> update<74><65> CHRACTER_MANAGER<45><52><EFBFBD><EFBFBD> <20><><EFBFBD>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
|
|||
|
// petsystem<65><6D> update<74>ϴٰ<CFB4> pet<65><74> unsummon<6F>ϴ<EFBFBD> <20>κп<CEBA><D0BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
// (CHRACTER_MANAGER<45><52><EFBFBD><EFBFBD> update <20>ϸ<EFBFBD> chracter destroy<6F><79> pending<6E>Ǿ<EFBFBD>, CPetSystem<65><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD> dangling <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ְ<EFBFBD> <20>ȴ<EFBFBD>.)
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PetSystem<65><6D> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD>ִ<EFBFBD> event<6E><74> <20><EFBFBD><DFBB><EFBFBD>Ŵ.
|
|||
|
EVENTFUNC(petsystem_update_event)
|
|||
|
{
|
|||
|
petsystem_event_info* info = dynamic_cast<petsystem_event_info*>( event->info );
|
|||
|
if ( info == NULL )
|
|||
|
{
|
|||
|
sys_err( "check_speedhack_event> <Factor> Null pointer" );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
CPetSystem* pPetSystem = info->pPetSystem;
|
|||
|
|
|||
|
if (NULL == pPetSystem)
|
|||
|
return 0;
|
|||
|
|
|||
|
|
|||
|
pPetSystem->Update(0);
|
|||
|
// 0.25<EFBFBD>ʸ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
|||
|
return PASSES_PER_SEC(1) / 4;
|
|||
|
}
|
|||
|
|
|||
|
/// NOTE: 1ij<31><C4B3><EFBFBD>Ͱ<EFBFBD> <20><EFBFBD><EEB0B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD><D6B4><EFBFBD> <20><><EFBFBD><EFBFBD>... ij<><C4B3><EFBFBD><EFBFBD><CDB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٸ<EFBFBD><D9B8><EFBFBD> <20>ҰŶ<D2B0><C5B6><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֵ... <20><>..
|
|||
|
/// <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ÿ<EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ʋ<><C6B2> <20><> <20>ִµ<D6B4> <20>̷<EFBFBD><CCB7><EFBFBD> <20><>ȹ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
const float PET_COUNT_LIMIT = 3;
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// CPetActor
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
CPetActor::CPetActor(LPCHARACTER owner, DWORD vnum, DWORD options)
|
|||
|
{
|
|||
|
m_dwVnum = vnum;
|
|||
|
m_dwVID = 0;
|
|||
|
m_dwOptions = options;
|
|||
|
m_dwLastActionTime = 0;
|
|||
|
|
|||
|
m_pkChar = 0;
|
|||
|
m_pkOwner = owner;
|
|||
|
|
|||
|
m_originalMoveSpeed = 0;
|
|||
|
|
|||
|
m_dwSummonItemVID = 0;
|
|||
|
m_dwSummonItemVnum = 0;
|
|||
|
}
|
|||
|
|
|||
|
CPetActor::~CPetActor()
|
|||
|
{
|
|||
|
this->Unsummon();
|
|||
|
|
|||
|
m_pkOwner = 0;
|
|||
|
}
|
|||
|
|
|||
|
void CPetActor::SetName(const char* name)
|
|||
|
{
|
|||
|
std::string petName = m_pkOwner->GetName();
|
|||
|
|
|||
|
if (0 != m_pkOwner &&
|
|||
|
0 == name &&
|
|||
|
0 != m_pkOwner->GetName())
|
|||
|
{
|
|||
|
petName += "'s Pet";
|
|||
|
}
|
|||
|
else
|
|||
|
petName += name;
|
|||
|
|
|||
|
if (true == IsSummoned())
|
|||
|
m_pkChar->SetName(petName);
|
|||
|
|
|||
|
m_name = petName;
|
|||
|
}
|
|||
|
|
|||
|
bool CPetActor::Mount()
|
|||
|
{
|
|||
|
if (0 == m_pkOwner)
|
|||
|
return false;
|
|||
|
|
|||
|
if (true == HasOption(EPetOption_Mountable))
|
|||
|
m_pkOwner->MountVnum(m_dwVnum);
|
|||
|
|
|||
|
return m_pkOwner->GetMountVnum() == m_dwVnum;;
|
|||
|
}
|
|||
|
|
|||
|
void CPetActor::Unmount()
|
|||
|
{
|
|||
|
if (0 == m_pkOwner)
|
|||
|
return;
|
|||
|
|
|||
|
if (m_pkOwner->IsHorseRiding())
|
|||
|
m_pkOwner->StopRiding();
|
|||
|
}
|
|||
|
|
|||
|
void CPetActor::Unsummon()
|
|||
|
{
|
|||
|
if (true == this->IsSummoned())
|
|||
|
{
|
|||
|
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
this->ClearBuff();
|
|||
|
this->SetSummonItem(NULL);
|
|||
|
if (NULL != m_pkOwner)
|
|||
|
m_pkOwner->ComputePoints();
|
|||
|
|
|||
|
if (NULL != m_pkChar)
|
|||
|
M2_DESTROY_CHARACTER(m_pkChar);
|
|||
|
|
|||
|
m_pkChar = 0;
|
|||
|
m_dwVID = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DWORD CPetActor::Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar)
|
|||
|
{
|
|||
|
long x = m_pkOwner->GetX();
|
|||
|
long y = m_pkOwner->GetY();
|
|||
|
long z = m_pkOwner->GetZ();
|
|||
|
|
|||
|
if (true == bSpawnFar)
|
|||
|
{
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
if (0 != m_pkChar)
|
|||
|
{
|
|||
|
m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
|
|||
|
m_dwVID = m_pkChar->GetVID();
|
|||
|
|
|||
|
return m_dwVID;
|
|||
|
}
|
|||
|
|
|||
|
m_pkChar = CHARACTER_MANAGER::instance().SpawnMob(
|
|||
|
m_dwVnum,
|
|||
|
m_pkOwner->GetMapIndex(),
|
|||
|
x, y, z,
|
|||
|
false, (int)(m_pkOwner->GetRotation()+180), false);
|
|||
|
|
|||
|
if (0 == m_pkChar)
|
|||
|
{
|
|||
|
sys_err("[CPetSystem::Summon] Failed to summon the pet. (vnum: %d)", m_dwVnum);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
m_pkChar->SetPet();
|
|||
|
|
|||
|
// m_pkOwner->DetailLog();
|
|||
|
// m_pkChar->DetailLog();
|
|||
|
|
|||
|
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
m_pkChar->SetEmpire(m_pkOwner->GetEmpire());
|
|||
|
|
|||
|
m_dwVID = m_pkChar->GetVID();
|
|||
|
|
|||
|
this->SetName(petName);
|
|||
|
|
|||
|
// SetSummonItem(pSummonItem)<29><> <20>θ<EFBFBD> <20>Ŀ<EFBFBD> ComputePoints<74><73> <20>θ<EFBFBD><CEB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
this->SetSummonItem(pSummonItem);
|
|||
|
m_pkOwner->ComputePoints();
|
|||
|
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
|
|||
|
|
|||
|
return m_dwVID;
|
|||
|
}
|
|||
|
|
|||
|
bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
|
|||
|
{
|
|||
|
float fDist = number(fMinDist, fMaxDist);
|
|||
|
float r = (float)number (0, 359);
|
|||
|
float dest_x = GetOwner()->GetX() + fDist * cos(r);
|
|||
|
float dest_y = GetOwner()->GetY() + fDist * sin(r);
|
|||
|
|
|||
|
//m_pkChar->SetRotation(number(0, 359)); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
//GetDeltaByDegree(m_pkChar->GetRotation(), fDist, &fx, &fy);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD> üũ; <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20>߰<EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
|
|||
|
//if (!(SECTREE_MANAGER::instance().IsMovablePosition(m_pkChar->GetMapIndex(), m_pkChar->GetX() + (int) fx, m_pkChar->GetY() + (int) fy)
|
|||
|
// && SECTREE_MANAGER::instance().IsMovablePosition(m_pkChar->GetMapIndex(), m_pkChar->GetX() + (int) fx/2, m_pkChar->GetY() + (int) fy/2)))
|
|||
|
// return true;
|
|||
|
|
|||
|
m_pkChar->SetNowWalking(true);
|
|||
|
|
|||
|
//if (m_pkChar->Goto(m_pkChar->GetX() + (int) fx, m_pkChar->GetY() + (int) fy))
|
|||
|
// m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
|||
|
if (!m_pkChar->IsStateMove() && m_pkChar->Goto(dest_x, dest_y))
|
|||
|
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
|||
|
|
|||
|
m_dwLastActionTime = get_dword_time();
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
// char_state.cpp StateHorse<73>Լ<EFBFBD> <20>׳<EFBFBD> C&P -_-;
|
|||
|
bool CPetActor::_UpdateFollowAI()
|
|||
|
{
|
|||
|
if (0 == m_pkChar->m_pkMobData)
|
|||
|
{
|
|||
|
//sys_err("[CPetActor::_UpdateFollowAI] m_pkChar->m_pkMobData is NULL");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// NOTE: ij<><C4B3><EFBFBD><EFBFBD>(<28><>)<29><> <20><><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20>ӵ<EFBFBD><D3B5><EFBFBD> <20>˾ƾ<CBBE> <20>ϴµ<CFB4>, <20>ش<EFBFBD> <20><>(m_pkChar->m_pkMobData->m_table.sMovingSpeed)<29><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20>˾Ƴ<CBBE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
// m_pkChar->m_pkMobData <20><><EFBFBD><EFBFBD> invalid<69><64> <20><><EFBFBD>찡 <20><><EFBFBD><EFBFBD> <20><EFBFBD><DFBB><EFBFBD>. <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ľ<EFBFBD><C4BE>ϰ<EFBFBD> <20>ϴ<EFBFBD><CFB4><EFBFBD> m_pkChar->m_pkMobData <20><><EFBFBD><EFBFBD> <20>ƿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> <20><>.
|
|||
|
// <20><><EFBFBD>⼭ <20>Ź<EFBFBD> <20>˻<EFBFBD><CBBB>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>쵵 <20><><EFBFBD><EFBFBD>.. -_-;; <20>ФФФФФФФФ<D0A4>
|
|||
|
if (0 == m_originalMoveSpeed)
|
|||
|
{
|
|||
|
const CMob* mobData = CMobManager::Instance().Get(m_dwVnum);
|
|||
|
|
|||
|
if (0 != mobData)
|
|||
|
m_originalMoveSpeed = mobData->m_table.sMovingSpeed;
|
|||
|
}
|
|||
|
float START_FOLLOW_DISTANCE = 300.0f; // <20><> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿư<D1BE><C6B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
float START_RUN_DISTANCE = 900.0f; // <20><> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>پ <20>Ѿư<D1BE>.
|
|||
|
|
|||
|
float RESPAWN_DISTANCE = 4500.f; // <20><> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF>.
|
|||
|
int APPROACH = 200; // <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD>
|
|||
|
|
|||
|
bool bDoMoveAlone = true; // ij<><C4B3><EFBFBD>Ϳ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> ȥ<><C8A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD><CFB0><EFBFBD> <20><><EFBFBD><EFBFBD> -_-;
|
|||
|
bool bRun = false; // <20>پ<EFBFBD><D9BE><EFBFBD> <20>ϳ<EFBFBD>?
|
|||
|
|
|||
|
DWORD currentTime = get_dword_time();
|
|||
|
|
|||
|
long ownerX = m_pkOwner->GetX(); long ownerY = m_pkOwner->GetY();
|
|||
|
long charX = m_pkChar->GetX(); long charY = m_pkChar->GetY();
|
|||
|
|
|||
|
float fDist = DISTANCE_APPROX(charX - ownerX, charY - ownerY);
|
|||
|
|
|||
|
if (fDist >= RESPAWN_DISTANCE)
|
|||
|
{
|
|||
|
float fOwnerRot = m_pkOwner->GetRotation() * 3.141592f / 180.f;
|
|||
|
float fx = -APPROACH * cos(fOwnerRot);
|
|||
|
float fy = -APPROACH * sin(fOwnerRot);
|
|||
|
if (m_pkChar->Show(m_pkOwner->GetMapIndex(), ownerX + fx, ownerY + fy))
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (fDist >= START_FOLLOW_DISTANCE)
|
|||
|
{
|
|||
|
if( fDist >= START_RUN_DISTANCE)
|
|||
|
{
|
|||
|
bRun = true;
|
|||
|
}
|
|||
|
|
|||
|
m_pkChar->SetNowWalking(!bRun); // NOTE: <20>Լ<EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ߴ°<DFB4><C2B0><EFBFBD> <20>˾Ҵµ<D2B4> SetNowWalking(false) <20>ϸ<EFBFBD> <20>ٴ°<D9B4><C2B0><EFBFBD>.. -_-;
|
|||
|
|
|||
|
Follow(APPROACH);
|
|||
|
|
|||
|
m_pkChar->SetLastAttacked(currentTime);
|
|||
|
m_dwLastActionTime = currentTime;
|
|||
|
}
|
|||
|
//else
|
|||
|
//{
|
|||
|
// if (fabs(m_pkChar->GetRotation() - GetDegreeFromPositionXY(charX, charY, ownerX, ownerX)) > 10.f || fabs(m_pkChar->GetRotation() - GetDegreeFromPositionXY(charX, charY, ownerX, ownerX)) < 350.f)
|
|||
|
// {
|
|||
|
// m_pkChar->Follow(m_pkOwner, APPROACH);
|
|||
|
// m_pkChar->SetLastAttacked(currentTime);
|
|||
|
// m_dwLastActionTime = currentTime;
|
|||
|
// }
|
|||
|
//}
|
|||
|
// Follow <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ΰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD> <20>̳<EFBFBD><CCB3><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
else
|
|||
|
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
|
|||
|
//else if (currentTime - m_dwLastActionTime > number(5000, 12000))
|
|||
|
//{
|
|||
|
// this->_UpdatAloneActionAI(START_FOLLOW_DISTANCE / 2, START_FOLLOW_DISTANCE);
|
|||
|
//}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool CPetActor::Update(DWORD deltaTime)
|
|||
|
{
|
|||
|
bool bResult = true;
|
|||
|
|
|||
|
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><D7BE>ų<EFBFBD>, <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>°<EFBFBD> <20>̻<EFBFBD><CCBB>ϴٸ<CFB4> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. (NOTE: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̷<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> DEAD <20><><EFBFBD>¿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>찡 <20><><EFBFBD><EFBFBD>-_-;)
|
|||
|
// <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ų<EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>°<EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
|||
|
if (m_pkOwner->IsDead() || (IsSummoned() && m_pkChar->IsDead())
|
|||
|
|| NULL == ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())
|
|||
|
|| ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())->GetOwner() != this->GetOwner()
|
|||
|
)
|
|||
|
{
|
|||
|
this->Unsummon();
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (this->IsSummoned() && HasOption(EPetOption_Followable))
|
|||
|
bResult = bResult && this->_UpdateFollowAI();
|
|||
|
|
|||
|
return bResult;
|
|||
|
}
|
|||
|
|
|||
|
//NOTE : <20><><EFBFBD><EFBFBD>!!! MinDistance<63><65> ũ<><C5A9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŭ<EFBFBD><C5AD> <20><>ȭ<EFBFBD><C8AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> follow<6F><77><EFBFBD><EFBFBD> <20>ʴ´<CAB4>,
|
|||
|
bool CPetActor::Follow(float fMinDistance)
|
|||
|
{
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
|
|||
|
if( !m_pkOwner || !m_pkChar)
|
|||
|
return false;
|
|||
|
|
|||
|
float fOwnerX = m_pkOwner->GetX();
|
|||
|
float fOwnerY = m_pkOwner->GetY();
|
|||
|
|
|||
|
float fPetX = m_pkChar->GetX();
|
|||
|
float fPetY = m_pkChar->GetY();
|
|||
|
|
|||
|
float fDist = DISTANCE_SQRT(fOwnerX - fPetX, fOwnerY - fPetY);
|
|||
|
if (fDist <= fMinDistance)
|
|||
|
return false;
|
|||
|
|
|||
|
m_pkChar->SetRotationToXY(fOwnerX, fOwnerY);
|
|||
|
|
|||
|
float fx, fy;
|
|||
|
|
|||
|
float fDistToGo = fDist - fMinDistance;
|
|||
|
GetDeltaByDegree(m_pkChar->GetRotation(), fDistToGo, &fx, &fy);
|
|||
|
|
|||
|
if (!m_pkChar->Goto((int)(fPetX+fx+0.5f), (int)(fPetY+fy+0.5f)) )
|
|||
|
return false;
|
|||
|
|
|||
|
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0, 0);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
void CPetActor::SetSummonItem (LPITEM pItem)
|
|||
|
{
|
|||
|
if (NULL == pItem)
|
|||
|
{
|
|||
|
m_dwSummonItemVID = 0;
|
|||
|
m_dwSummonItemVnum = 0;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
m_dwSummonItemVID = pItem->GetVID();
|
|||
|
m_dwSummonItemVnum = pItem->GetVnum();
|
|||
|
}
|
|||
|
|
|||
|
void CPetActor::GiveBuff()
|
|||
|
{
|
|||
|
// <20><>Ȳ <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><DFBB><EFBFBD>.
|
|||
|
if (34004 == m_dwVnum || 34009 == m_dwVnum)
|
|||
|
{
|
|||
|
if (NULL == m_pkOwner->GetDungeon())
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
LPITEM item = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID);
|
|||
|
if (NULL != item)
|
|||
|
item->ModifyPoints(true);
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
void CPetActor::ClearBuff()
|
|||
|
{
|
|||
|
if (NULL == m_pkOwner)
|
|||
|
return ;
|
|||
|
TItemTable* item_proto = ITEM_MANAGER::instance().GetTable(m_dwSummonItemVnum);
|
|||
|
if (NULL == item_proto)
|
|||
|
return;
|
|||
|
for (int i = 0; i < ITEM_APPLY_MAX_NUM; i++)
|
|||
|
{
|
|||
|
if (item_proto->aApplies[i].bType == APPLY_NONE)
|
|||
|
continue;
|
|||
|
m_pkOwner->ApplyPoint(item_proto->aApplies[i].bType, -item_proto->aApplies[i].lValue);
|
|||
|
}
|
|||
|
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// CPetSystem
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
CPetSystem::CPetSystem(LPCHARACTER owner)
|
|||
|
{
|
|||
|
// assert(0 != owner && "[CPetSystem::CPetSystem] Invalid owner");
|
|||
|
|
|||
|
m_pkOwner = owner;
|
|||
|
m_dwUpdatePeriod = 400;
|
|||
|
|
|||
|
m_dwLastUpdateTime = 0;
|
|||
|
}
|
|||
|
|
|||
|
CPetSystem::~CPetSystem()
|
|||
|
{
|
|||
|
Destroy();
|
|||
|
}
|
|||
|
|
|||
|
void CPetSystem::Destroy()
|
|||
|
{
|
|||
|
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
|||
|
{
|
|||
|
CPetActor* petActor = iter->second;
|
|||
|
|
|||
|
if (0 != petActor)
|
|||
|
{
|
|||
|
delete petActor;
|
|||
|
}
|
|||
|
}
|
|||
|
event_cancel(&m_pkPetSystemUpdateEvent);
|
|||
|
m_petActorMap.clear();
|
|||
|
}
|
|||
|
|
|||
|
/// <20><> <20>ý<EFBFBD><C3BD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ. <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AI ó<><C3B3> <20><><EFBFBD><EFBFBD> <20><>.
|
|||
|
bool CPetSystem::Update(DWORD deltaTime)
|
|||
|
{
|
|||
|
bool bResult = true;
|
|||
|
|
|||
|
DWORD currentTime = get_dword_time();
|
|||
|
|
|||
|
// CHARACTER_MANAGER<45><52><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD>ͷ<EFBFBD> Update<74><65> <20><> <20>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> (Pulse<73><65><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִ<EFBFBD>)<29><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˾Ҵµ<D2B4>
|
|||
|
// <20><><EFBFBD><EFBFBD> <20>ٸ<EFBFBD> <20><><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>-_-; <20><><EFBFBD> <20>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> deltaTime<6D><65> <20>ǹ̰<C7B9> <20><><EFBFBD><EFBFBD><EFBFBD>Ф<EFBFBD>
|
|||
|
|
|||
|
if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime)
|
|||
|
return true;
|
|||
|
|
|||
|
std::vector <CPetActor*> v_garbageActor;
|
|||
|
|
|||
|
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
|||
|
{
|
|||
|
CPetActor* petActor = iter->second;
|
|||
|
|
|||
|
if (0 != petActor && petActor->IsSummoned())
|
|||
|
{
|
|||
|
LPCHARACTER pPet = petActor->GetCharacter();
|
|||
|
|
|||
|
if (NULL == CHARACTER_MANAGER::instance().Find(pPet->GetVID()))
|
|||
|
{
|
|||
|
v_garbageActor.push_back(petActor);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
bResult = bResult && petActor->Update(deltaTime);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
for (std::vector<CPetActor*>::iterator it = v_garbageActor.begin(); it != v_garbageActor.end(); it++)
|
|||
|
DeletePet(*it);
|
|||
|
|
|||
|
m_dwLastUpdateTime = currentTime;
|
|||
|
|
|||
|
return bResult;
|
|||
|
}
|
|||
|
|
|||
|
/// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
void CPetSystem::DeletePet(DWORD mobVnum)
|
|||
|
{
|
|||
|
TPetActorMap::iterator iter = m_petActorMap.find(mobVnum);
|
|||
|
|
|||
|
if (m_petActorMap.end() == iter)
|
|||
|
{
|
|||
|
sys_err("[CPetSystem::DeletePet] Can't find pet on my list (VNUM: %d)", mobVnum);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
CPetActor* petActor = iter->second;
|
|||
|
|
|||
|
if (0 == petActor)
|
|||
|
sys_err("[CPetSystem::DeletePet] Null Pointer (petActor)");
|
|||
|
else
|
|||
|
delete petActor;
|
|||
|
|
|||
|
m_petActorMap.erase(iter);
|
|||
|
}
|
|||
|
|
|||
|
/// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
void CPetSystem::DeletePet(CPetActor* petActor)
|
|||
|
{
|
|||
|
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
|||
|
{
|
|||
|
if (iter->second == petActor)
|
|||
|
{
|
|||
|
delete petActor;
|
|||
|
m_petActorMap.erase(iter);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sys_err("[CPetSystem::DeletePet] Can't find petActor(0x%x) on my list(size: %d) ", petActor, m_petActorMap.size());
|
|||
|
}
|
|||
|
|
|||
|
void CPetSystem::Unsummon(DWORD vnum, bool bDeleteFromList)
|
|||
|
{
|
|||
|
CPetActor* actor = this->GetByVnum(vnum);
|
|||
|
|
|||
|
if (0 == actor)
|
|||
|
{
|
|||
|
sys_err("[CPetSystem::GetByVnum(%d)] Null Pointer (petActor)", vnum);
|
|||
|
return;
|
|||
|
}
|
|||
|
actor->Unsummon();
|
|||
|
|
|||
|
if (true == bDeleteFromList)
|
|||
|
this->DeletePet(actor);
|
|||
|
|
|||
|
bool bActive = false;
|
|||
|
for (TPetActorMap::iterator it = m_petActorMap.begin(); it != m_petActorMap.end(); it++)
|
|||
|
{
|
|||
|
bActive |= it->second->IsSummoned();
|
|||
|
}
|
|||
|
if (false == bActive)
|
|||
|
{
|
|||
|
event_cancel(&m_pkPetSystemUpdateEvent);
|
|||
|
m_pkPetSystemUpdateEvent = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* petName, bool bSpawnFar, DWORD options)
|
|||
|
{
|
|||
|
CPetActor* petActor = this->GetByVnum(mobVnum);
|
|||
|
|
|||
|
// <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
if (0 == petActor)
|
|||
|
{
|
|||
|
petActor = M2_NEW CPetActor(m_pkOwner, mobVnum, options);
|
|||
|
m_petActorMap.insert(std::make_pair(mobVnum, petActor));
|
|||
|
}
|
|||
|
|
|||
|
DWORD petVID = petActor->Summon(petName, pSummonItem, bSpawnFar);
|
|||
|
|
|||
|
if (NULL == m_pkPetSystemUpdateEvent)
|
|||
|
{
|
|||
|
petsystem_event_info* info = AllocEventInfo<petsystem_event_info>();
|
|||
|
|
|||
|
info->pPetSystem = this;
|
|||
|
|
|||
|
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4); // 0.25<EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
|
|||
|
return petActor;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CPetActor* CPetSystem::GetByVID(DWORD vid) const
|
|||
|
{
|
|||
|
CPetActor* petActor = 0;
|
|||
|
|
|||
|
bool bFound = false;
|
|||
|
|
|||
|
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
|||
|
{
|
|||
|
petActor = iter->second;
|
|||
|
|
|||
|
if (0 == petActor)
|
|||
|
{
|
|||
|
sys_err("[CPetSystem::GetByVID(%d)] Null Pointer (petActor)", vid);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
bFound = petActor->GetVID() == vid;
|
|||
|
|
|||
|
if (true == bFound)
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return bFound ? petActor : 0;
|
|||
|
}
|
|||
|
|
|||
|
/// <20><><EFBFBD><EFBFBD> <20><> <20><> <20>߿<EFBFBD><DFBF><EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD> <20><> VNUM<55><4D> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>ϴ<EFBFBD> <20>Լ<EFBFBD>.
|
|||
|
CPetActor* CPetSystem::GetByVnum(DWORD vnum) const
|
|||
|
{
|
|||
|
CPetActor* petActor = 0;
|
|||
|
|
|||
|
TPetActorMap::const_iterator iter = m_petActorMap.find(vnum);
|
|||
|
|
|||
|
if (m_petActorMap.end() != iter)
|
|||
|
petActor = iter->second;
|
|||
|
|
|||
|
return petActor;
|
|||
|
}
|
|||
|
|
|||
|
size_t CPetSystem::CountSummoned() const
|
|||
|
{
|
|||
|
size_t count = 0;
|
|||
|
|
|||
|
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
|||
|
{
|
|||
|
CPetActor* petActor = iter->second;
|
|||
|
|
|||
|
if (0 != petActor)
|
|||
|
{
|
|||
|
if (petActor->IsSummoned())
|
|||
|
++count;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return count;
|
|||
|
}
|
|||
|
|
|||
|
void CPetSystem::RefreshBuff()
|
|||
|
{
|
|||
|
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
|
|||
|
{
|
|||
|
CPetActor* petActor = iter->second;
|
|||
|
|
|||
|
if (0 != petActor)
|
|||
|
{
|
|||
|
if (petActor->IsSummoned())
|
|||
|
{
|
|||
|
petActor->GiveBuff();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|