[R C++]Támadó pet

Indította isolator05, 2016-10-27, 08:48:56

Űdv nektek fórumozók.
Deven találtam egy kis érdekességet:
https://metin2dev.org/board/index.php?/topic/5674-rcattacking-pets/
Leírom magyarul is, mit hogyan kell csinálni.
Felhívom a figyelmet hogy csak forrással rendelkezők tudják ezt alkalmazni!!!!!!!!

Első lépés.
Nyisd meg a Petsystem.h -t
Keresd meg ezt a részt:
void Unmount();
Alá tedd be ezt:
bool Attack(LPCHARACTER pkVictim = NULL);

Keresd meg ezt:
CPetActor* GetByVnum(DWORD vnum) const;
Alá tedd be ezt:
void        LaunchAttack(LPCHARACTER pkVictim = NULL);
Ez kész.
Most nyisd meg a Petsystem.cpp -t
Keresd ezt:
bool CPetActor::Update(DWORD deltaTime)
Cseréld le erre:
bool CPetActor::Update(DWORD deltaTime)
{
bool bResult = false;

if ((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->GetCharacter()->GetVictim())
{
bResult = this->Attack();
}

if (!bResult)
{
if (this->IsSummoned() && HasOption(EPetOption_Followable))
bResult = this->_UpdateFollowAI();
}

return bResult;
}

Most keresd ezt:
void CPetActor::ClearBuff()
Ez alá a funkció alá tedd be ezt:
bool CPetActor::Attack(LPCHARACTER pkVictim)
{
if (pkVictim)
{
if (!pkVictim->IsMonster() || pkVictim->IsDead())
return false;

if (m_pkChar->GetVictim())
return false;
}
else
{
pkVictim = m_pkChar->GetVictim();

if (!pkVictim)
return false;
}

m_pkChar->SetVictim(pkVictim);

const PIXEL_POSITION& rkPetPos = m_pkChar->GetXYZ();
const PIXEL_POSITION& rkVictimPos = pkVictim->GetXYZ();

int iDistance = DISTANCE_APPROX(rkPetPos.x - rkVictimPos.x, rkPetPos.y - rkVictimPos.y);

if (iDistance >= m_pkChar->GetMobAttackRange())
{
m_pkChar->Follow(pkVictim, m_pkChar->GetMobAttackRange());
}
else
{
if (get_dword_time() - m_pkChar->GetLastAttackTime() >= 3000)
{
if (m_pkChar->Attack(pkVictim))
{
m_pkChar->SendMovePacket(FUNC_ATTACK, 0, rkPetPos.x, rkPetPos.y, 0, get_dword_time());
m_pkChar->SetLastAttacked(get_dword_time());
}
}

}
}

Így nézzen ki:
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 ;
}

bool CPetActor::Attack(LPCHARACTER pkVictim)
{
if (pkVictim)
{
if (!pkVictim->IsMonster() || pkVictim->IsDead())
return false;

if (m_pkChar->GetVictim())
return false;
}
else
{
pkVictim = m_pkChar->GetVictim();

if (!pkVictim)
return false;
}

m_pkChar->SetVictim(pkVictim);

const PIXEL_POSITION& rkPetPos = m_pkChar->GetXYZ();
const PIXEL_POSITION& rkVictimPos = pkVictim->GetXYZ();

int iDistance = DISTANCE_APPROX(rkPetPos.x - rkVictimPos.x, rkPetPos.y - rkVictimPos.y);

if (iDistance >= m_pkChar->GetMobAttackRange())
{
m_pkChar->Follow(pkVictim, m_pkChar->GetMobAttackRange());
}
else
{
if (get_dword_time() - m_pkChar->GetLastAttackTime() >= 3000)
{
if (m_pkChar->Attack(pkVictim))
{
m_pkChar->SendMovePacket(FUNC_ATTACK, 0, rkPetPos.x, rkPetPos.y, 0, get_dword_time());
m_pkChar->SetLastAttacked(get_dword_time());
}
}

}
}

///////////////////////////////////////////////////////////////////////////////////////
//  CPetSystem
///////////////////////////////////////////////////////////////////////////////////////


Keresd meg ezt:
void CPetSystem::Destroy()
A funkció alá tedd be ezt:
void CPetSystem::LaunchAttack(LPCHARACTER pkVictim)
{
if (!pkVictim)
return;

for (itertype(m_petActorMap) it = m_petActorMap.begin(); it != m_petActorMap.end(); ++it)
{
CPetActor* pkPetActor = it->second;
if (pkPetActor->IsSummoned())
pkPetActor->Attack(pkVictim);
}
}

Így nézzen ki:
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();
}

void CPetSystem::LaunchAttack(LPCHARACTER pkVictim)
{
if (!pkVictim)
return;

for (itertype(m_petActorMap) it = m_petActorMap.begin(); it != m_petActorMap.end(); ++it)
{
CPetActor* pkPetActor = it->second;
if (pkPetActor->IsSummoned())
pkPetActor->Attack(pkVictim);
}
}

Ez is kész.

Most nyisd meg a char_battle.cpp -t
Keress rá erre:
bool CHARACTER::Attack(LPCHARACTER pkVictim, BYTE bType)
Ebben a funkcióban kerres erre a részre:
// only pc sets victim null. For npc, state machine will reset this.
if (BATTLE_DEAD == iRet && IsPC())
SetVictim(NULL);


Alá illeszt be ezt:
if (BATTLE_DEAD != iRet && IsPC())
        {
            if (m_petSystem && m_petSystem->CountSummoned() > 0)
                m_petSystem->LaunchAttack(pkVictim);
        }

Így nézzen ki:
// only pc sets victim null. For npc, state machine will reset this.
if (BATTLE_DEAD == iRet && IsPC())
SetVictim(NULL);

if (BATTLE_DEAD != iRet && IsPC())
        {
            if (m_petSystem && m_petSystem->CountSummoned() > 0)
                m_petSystem->LaunchAttack(pkVictim);
        }

return true;
}

return false;
}

Ez is kész.

Nyisd meg a pvp.cpp -t
Keress rá erre:
bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
Illeszd be a switch (pkVictim->GetCharType()) fölé ezt:
if (pkChr->IsPet() && pkVictim->IsMonster())
    {
        return true;
    }

    if (pkChr->IsMonster() && pkVictim->IsPet())
    {
        return true;
    }

Így:
bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
{
if (pkChr->IsPet() && pkVictim->IsMonster())
    {
        return true;
    }

    if (pkChr->IsMonster() && pkVictim->IsPet())
    {
        return true;
    }
switch (pkVictim->GetCharType())

Kész is.
A mob_proto.txt-ben csak "AGGR" kell beírni a kiválasztott mobnak.
Megjegyzés. A meglévő peteknél nem látványos a támadás, mivel nincs támadó mozgásuk. Célszerübb egy mob-ot megírni petnek Pl.: Vadkutya. Ha nem elég a támadó értéke akkor növeld és nem fog 1 órán át gyilkolni  ;)
Ha segítettem ne sajnáld a + t.