Luffy Posted December 16, 2017 at 01:49 AM Share Posted December 16, 2017 at 01:49 AM Alguém poderia me ajudar a criar uma função para quest, para que os pets sigam ou não os jogadores, eu até tentei, mas a unica forma que achei seria acessando uma função que está em outra classe, mas não são sei como fazer isso(nem se isso é possível). Eu até procurei algo na web, mas as respostas também não funcionaram. Eu gostaria que vocês dessem uma olhada abaixo e me dessem uma orientação do que fazer.(acredito que os arquivos estejam iguais aos originais). Desde já agradeço. PetSystem.cpp Spoiler #include "stdafx.h" #include "config.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" EVENTINFO (petsystem_event_info) { CPetSystem* pPetSystem; }; EVENTFUNC (petsystem_update_event) { petsystem_event_info* info = dynamic_cast<petsystem_event_info*> (event->info); if (info == NULL) { sys_err ("petsystem_update_event> <Factor> Null pointer"); return 0; } CPetSystem* pPetSystem = info->pPetSystem; if (NULL == pPetSystem) { return 0; } pPetSystem->Update (0); return PASSES_PER_SEC (1) / 4; } const float PET_COUNT_LIMIT = 3; 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()) { 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_pkChar->SetEmpire (m_pkOwner->GetEmpire()); m_dwVID = m_pkChar->GetVID(); this->SetName (petName); 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->SetNowWalking (true); 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; } bool CPetActor::_UpdateFollowAI() { if (0 == m_pkChar->m_pkMobData) { return false; } 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 = 600.0f; float START_RUN_DISTANCE = 7500.0f; float RESPAWN_DISTANCE = 10000.f; int APPROACH = 200; bool bRun = false; 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); Follow (APPROACH); m_pkChar->SetLastAttacked (currentTime); m_dwLastActionTime = currentTime; } else { m_pkChar->SendMovePacket (FUNC_WAIT, 0, 0, 0, 0); } return true; } bool CPetActor::Update (DWORD deltaTime) { bool bResult = true; if ((this->GetSummonItemVID() != 0 && (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; } bool CPetActor::Follow (float fMinDistance) { 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(); } bool __PetCheckBuff (const CPetActor* pPetActor) { bool bMustHaveBuff = true; switch (pPetActor->GetVnum()) { case 34004: case 34009: if (NULL == pPetActor->GetOwner()->GetDungeon()) { bMustHaveBuff = false; } default: break; } return bMustHaveBuff; } void CPetActor::GiveBuff() { if (!__PetCheckBuff (this)) { return; } LPITEM item = ITEM_MANAGER::instance().FindByVID (m_dwSummonItemVID); if (NULL != item) { item->ModifyPoints (true); } return; } void CPetActor::ClearBuff() { TItemTable* item_proto = ITEM_MANAGER::instance().GetTable (m_dwSummonItemVnum); if (NULL == m_pkOwner) { return; } if (NULL == item_proto) { return; } if (!__PetCheckBuff (this)) { return; } for (int i = 0; i < ITEM_APPLY_MAX_NUM; i++) { if (item_proto->aApplies.bType == APPLY_NONE) { continue; } m_pkOwner->ApplyPoint (item_proto->aApplies.bType, -item_proto->aApplies.lValue); } return; } CPetSystem::CPetSystem (LPCHARACTER owner) { m_pkOwner = owner; m_dwUpdatePeriod = 400; m_dwLastUpdateTime = 0; } CPetSystem::~CPetSystem() { Destroy(); } void CPetSystem::Destroy() { for (auto 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(); } bool CPetSystem::Update (DWORD deltaTime) { bool bResult = true; DWORD currentTime = get_dword_time(); if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime) { return true; } std::vector <CPetActor*> v_garbageActor; for (auto 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 (auto it = v_garbageActor.begin(); it != v_garbageActor.end(); it++) { DeletePet (*it); } m_dwLastUpdateTime = currentTime; return bResult; } void CPetSystem::DeletePet (DWORD mobVnum) { auto 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); } void CPetSystem::DeletePet (CPetActor* petActor) { for (auto 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 (auto 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); 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); } return petActor; } CPetActor* CPetSystem::GetByVID (DWORD vid) const { CPetActor* petActor = 0; bool bFound = false; for (auto 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; } CPetActor* CPetSystem::GetByVnum (DWORD vnum) const { CPetActor* petActor = 0; auto 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 (auto 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 (auto iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter) { CPetActor* petActor = iter->second; if (0 != petActor) { if (petActor->IsSummoned()) { petActor->GiveBuff(); } } } } PetSystem.h Spoiler #pragma once class CHARACTER; struct SPetAbility { }; class CPetActor { public: enum EPetOptions { EPetOption_Followable = 1 << 0, EPetOption_Mountable = 1 << 1, EPetOption_Summonable = 1 << 2, EPetOption_Combatable = 1 << 3, }; protected: friend class CPetSystem; CPetActor (LPCHARACTER owner, DWORD vnum, DWORD options = EPetOption_Followable | EPetOption_Summonable); virtual ~CPetActor(); virtual bool Update (DWORD deltaTime); protected: virtual bool _UpdateFollowAI(); virtual bool _UpdatAloneActionAI (float fMinDist, float fMaxDist); private: bool Follow (float fMinDistance = 50.f); public: LPCHARACTER GetCharacter() const { return m_pkChar; } LPCHARACTER GetOwner() const { return m_pkOwner; } DWORD GetVID() const { return m_dwVID; } DWORD GetVnum() const { return m_dwVnum; } bool HasOption (EPetOptions option) const { return m_dwOptions & option; } void SetName (const char* petName); bool Mount(); void Unmount(); DWORD Summon (const char* petName, LPITEM pSummonItem, bool bSpawnFar = false); void Unsummon(); bool IsSummoned() const { return 0 != m_pkChar; } void SetSummonItem (LPITEM pItem); DWORD GetSummonItemVID() { return m_dwSummonItemVID; } bool PetNomove() { return m_petnomove; } void GiveBuff(); void ClearBuff(); private: DWORD m_dwVnum; DWORD m_dwVID; DWORD m_dwOptions; DWORD m_dwLastActionTime; DWORD m_dwSummonItemVID; DWORD m_dwSummonItemVnum; short m_originalMoveSpeed; bool m_petnomove; std::string m_name; LPCHARACTER m_pkChar; LPCHARACTER m_pkOwner; }; class CPetSystem { public: typedef boost::unordered_map<DWORD, CPetActor*> TPetActorMap; public: CPetSystem (LPCHARACTER owner); virtual ~CPetSystem(); CPetActor* GetByVID (DWORD vid) const; CPetActor* GetByVnum (DWORD vnum) const; bool Update (DWORD deltaTime); void Destroy(); size_t CountSummoned() const; public: void SetUpdatePeriod (DWORD ms); CPetActor* Summon (DWORD mobVnum, LPITEM pSummonItem, const char* petName, bool bSpawnFar, DWORD options = CPetActor::EPetOption_Followable | CPetActor::EPetOption_Summonable); void Unsummon (DWORD mobVnum, bool bDeleteFromList = false); void Unsummon (CPetActor* petActor, bool bDeleteFromList = false); CPetActor* AddPet (DWORD mobVnum, const char* petName, const SPetAbility& ability, DWORD options = CPetActor::EPetOption_Followable | CPetActor::EPetOption_Summonable | CPetActor::EPetOption_Combatable); void DeletePet (DWORD mobVnum); void DeletePet (CPetActor* petActor); void RefreshBuff(); private: TPetActorMap m_petActorMap; LPCHARACTER m_pkOwner; DWORD m_dwUpdatePeriod; DWORD m_dwLastUpdateTime; LPEVENT m_pkPetSystemUpdateEvent; }; questlua_pet.cpp Spoiler #include "stdafx.h" #include "questlua.h" #include "questmanager.h" #include "horsename_manager.h" #include "char.h" #include "affect.h" #include "config.h" #include "utils.h" #include "PetSystem.h" #undef sys_err #define sys_err(fmt, args...) quest::CQuestManager::instance().QuestError(__FUNCTION__, __LINE__, fmt, ##args) namespace quest { int pet_is_mine(lua_State* L) { CQuestManager& q = CQuestManager::instance(); LPCHARACTER mch = q.GetCurrentCharacterPtr(); LPCHARACTER tch = q.GetCurrentNPCCharacterPtr(); CPetSystem* petSystem = mch->GetPetSystem(); CPetActor* petActor = petSystem->GetByVID(tch->GetVID()); lua_pushboolean(L, tch && tch->IsPet() && petActor && petActor->GetOwner() == mch); return 1; } int pet_summon (lua_State* L) { LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); CPetSystem* petSystem = ch->GetPetSystem(); LPITEM pItem = CQuestManager::instance().GetCurrentItem(); if (!ch || !petSystem || !pItem) { lua_pushnumber (L, 0); return 1; } if (0 == petSystem) { lua_pushnumber (L, 0); return 1; } DWORD mobVnum = lua_isnumber (L, 1) ? lua_tonumber (L, 1) : 0; const char* petName = lua_isstring (L, 2) ? lua_tostring (L, 2) : 0; bool bFromFar = lua_isboolean (L, 3) ? lua_toboolean (L, 3) : false; CPetActor* pet = petSystem->Summon (mobVnum, pItem, petName, bFromFar); if (pet != NULL) { lua_pushnumber (L, pet->GetVID()); } else { lua_pushnumber (L, 0); } return 1; } int pet_unsummon (lua_State* L) { LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); CPetSystem* petSystem = ch->GetPetSystem(); if (0 == petSystem) { return 0; } DWORD mobVnum = lua_isnumber (L, 1) ? lua_tonumber (L, 1) : 0; petSystem->Unsummon (mobVnum); return 1; } int pet_count_summoned (lua_State* L) { LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); CPetSystem* petSystem = ch->GetPetSystem(); lua_Number count = 0; if (0 != petSystem) { count = (lua_Number) petSystem->CountSummoned(); } lua_pushnumber (L, count); return 1; } int pet_is_summon (lua_State* L) { LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); CPetSystem* petSystem = ch->GetPetSystem(); if (0 == petSystem) { return 0; } DWORD mobVnum = lua_isnumber (L, 1) ? lua_tonumber (L, 1) : 0; CPetActor* petActor = petSystem->GetByVnum (mobVnum); if (NULL == petActor) { lua_pushboolean (L, false); } else { lua_pushboolean (L, petActor->IsSummoned()); } return 1; } int pet_spawn_effect (lua_State* L) { LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); CPetSystem* petSystem = ch->GetPetSystem(); if (0 == petSystem) { return 0; } DWORD mobVnum = lua_isnumber (L, 1) ? lua_tonumber (L, 1) : 0; CPetActor* petActor = petSystem->GetByVnum (mobVnum); if (NULL == petActor) { return 0; } LPCHARACTER pet_ch = petActor->GetCharacter(); if (NULL == pet_ch) { return 0; } if (lua_isstring (L, 2)) { pet_ch->SpecificEffectPacket (lua_tostring (L, 2)); } return 0; } void RegisterPetFunctionTable() { luaL_reg pet_functions[] = { { "summon", pet_summon }, { "unsummon", pet_unsummon }, { "is_summon", pet_is_summon }, { "count_summoned", pet_count_summoned }, { "spawn_effect", pet_spawn_effect }, { "is_mine", pet_is_mine }, { NULL, NULL } }; CQuestManager::instance().AddLuaFunctionTable ("pet", pet_functions); } } Link to comment Share on other sites More sharing options...
PACI Posted December 16, 2017 at 03:55 AM Share Posted December 16, 2017 at 03:55 AM Citar Luffy 15 Dez 17:57 O problema é que eu só consigo acessar métodos da classe CPetSystem. É o que todas as funções do questlua_pet .cpp usam, eu até tentei achar alguma forma de acessar a classe CPetActor que é onde se encontra o método que faz o pet seguir o player, mas não consegui nada. 2 horas atrás, Luffy disse: questlua_pet.cpp CPetSystem* petSystem = ch->GetPetSystem(); if (0 == petSystem) { return 0; } DWORD mobVnum = lua_isnumber (L, 1) ? lua_tonumber (L, 1) : 0; CPetActor* petActor = petSystem->GetByVnum (mobVnum); Link to comment Share on other sites More sharing options...
Luffy Posted December 16, 2017 at 05:36 AM Author Share Posted December 16, 2017 at 05:36 AM @PACI Como eu armazeno ou verifico um valor de uma função executada dentro da classe CPetSystem na CPetActor? Link to comment Share on other sites More sharing options...
trample Posted December 16, 2017 at 11:41 AM Share Posted December 16, 2017 at 11:41 AM estou com o mesmo problema aqui e a qestao do cavalo nao seguir o player e os pet so segem a uma distancia longa sabe algo sobre o segmento? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now