Hi again.
After a question once came up on how to do it I tried it myself and I'm actually using this system myself.
Basically what this system does: Pet EXP no longer goes up automatically but instead the player has to kill mobs for pet exp. There's a lot of customization which can be done to change how much exp the pet gets. You can find it in the comments.
DpClient.cpp
Change
PHP Code:
CDPClient::OnPetSetExp
to
PHP Code:
void CDPClient::OnPetSetExp( OBJID objid, CAr & ar )
{
// í»
DWORD dwExp;
ar >> dwExp;
CMover* pMover = prj.GetMover( objid );
if( IsValidObj( pMover ) && pMover->IsActiveMover() )
{
CPet* pPet = pMover->GetPet();
if( pPet )
{
pPet->SetExp( dwExp );
#ifndef __SYS_PETLEVELING_MOBKILL
if (pPet->GetLevel() == PL_EGG)
{
if (pPet->GetExp() == MAX_PET_EGG_EXP)
g_WndMng.OpenMessageBox(_T(prj.GetText(TID_GAME_PETEGG_HATCH)));
}
else
{
if (pPet->GetExp() == MAX_PET_EXP)
g_WndMng.OpenMessageBox(_T(prj.GetText(TID_GAME_PETEGG_HATCH)));
}
#endif // __PET_AUTO_LEVEL_UP
}
}
}
Mover.cpp
In
PHP Code:
CMover::ProcessPetEnergy
Change
PHP Code:
if( HasBuff( BUFF_ITEM, II_SYS_SYS_SCR_PET_TONIC_A )
|| HasBuff( BUFF_ITEM, II_SYS_SYS_SCR_PET_TONIC_B )) // Æê Àü¿ë ¿µ¾çÁ¦(A) // Æê Àü¿ë ¿µ¾çÁ¦(B) »ç¿ë½Ã ±â·Â °¨¼Ò ¾øÀ½.
return;
To
PHP Code:
if( HasBuff( BUFF_ITEM, II_SYS_SYS_SCR_PET_TONIC_A )
|| HasBuff( BUFF_ITEM, II_SYS_SYS_SCR_PET_TONIC_B )
#ifdef __SYS_PETLEVELING_MOBKILL
|| HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_C) // This part requires having the pet tonics added to the game
|| HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_D) // This part requires having the pet tonics added to the game
#endif
) // Æê Àü¿ë ¿µ¾çÁ¦(A) // Æê Àü¿ë ¿µ¾çÁ¦(B) »ç¿ë½Ã ±â·Â °¨¼Ò ¾øÀ½.
return;
In
PHP Code:
CMover::ProcessPetExp
Add
PHP Code:
#ifdef __SYS_PETLEVELING_MOBKILL
return;
#endif
right at the start.
Before
PHP Code:
#endif // __WORLDSERVER
#ifdef __CLIENT
void CMover::CreatePetSfx( void )
Add
PHP Code:
#ifdef __SYS_PETLEVELING_MOBKILL
void CMover::AddPetExpOnKill(DWORD dwMonsterRank, int nMonsterLevel, int nLevel)
{
// Initialize Base Values
float nMulti = 1.0f; //Multiplicator for EXP
float nBaseExp = PET_BASE_EXP; // Base EXP (set in VersionCommon.h)
BOOL bInDungeon = FALSE;
// Switch depending on monster rank
switch (dwMonsterRank)
{
case RANK_SUPER:
nBaseExp = 5000.0f; // Bosses always grant 5% of Pet EXP (10% Egg Exp)
break;
case RANK_BOSS:
nMulti *= 1.25f; // Giants grant 25% more
break;
case RANK_LOW:
case RANK_NORMAL:
case RANK_CAPTAIN:
nMulti *= 1.0f;
break;
}
// Calculating level difference.
if (nLevel - 10 > nMonsterLevel)
nBaseExp = 0; // When the monster is 10 levels below your own level, you get no Pet EXP
if (nMonsterLevel - 10 > nLevel)
nMulti *= 1.2; // When the monster is more than 10 levels above your own level, Pet EXP is increased by 20%
// Check if user is in a dungeon
DWORD UserWorldID = GetWorld()->m_dwWorldID;
if (UserWorldID >= 121 && UserWorldID <= 150)
{
if (dwMonsterRank != RANK_SUPER)
nMulti *= 1.25f; // You will get 25% more EXP when killing monsters in a dungeon (Does not count for bosses)
bInDungeon = TRUE; // Set Dungeon Mode to TRUE
}
if (bInDungeon == TRUE ) // Check if the user is in a dungeon
{
if (CParty* pParty = g_PartyMng.GetParty(this->m_idparty)) // Get User's party
{
for (int i = 0; i < pParty->m_nSizeofMember; ++i) // Cycle through every party member
{
CMover *pMember = (CMover*)g_UserMng.GetUserByPlayerID(pParty->m_aMember[i].m_uPlayerId);
if (IsValidObj(pMember)) // Check if party member is a valid obj
{
// Need to check if the member as a pet active and is in the same world
if (pMember->HasActivatedSystemPet() && pMember->GetWorld()->m_dwWorldID == UserWorldID)
{
float nTempMulti = nMulti;
// Check if user has any buff items up
if (pMember->HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_C))
nTempMulti += 0.25f;
if (pMember->HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_D))
nTempMulti += 0.5f;
// Get Partymember's Pet
CPet* pPartyPet = pMember->GetPet();
if (pPartyPet)
{
// Get Partymember's Pet Level
BYTE PetLevel = pPartyPet->GetLevel();
// Change Experience gained depending on level
switch (PetLevel)
{
case PL_EGG:
case PL_D:
{
nBaseExp *= 12.5;
}
break;
case PL_C:
{
nBaseExp *= 7;
}
break;
case PL_B:
{
nBaseExp *= 3.5;
}
break;
case PL_A:
{
nBaseExp *= 1;
}
break;
case PL_S:
{
nBaseExp = 0;
}
break;
}
// Calculate final EXP
DWORD dwExp = (DWORD)(pPartyPet->GetExp() + (nBaseExp * nTempMulti));
//////////////// AUTOMATED EGG UP ////////////////////
BOOL bHatched = FALSE;
if (dwExp >= MAX_PET_EGG_EXP && PetLevel == PL_EGG)
{
pMember->PetLevelup();
bHatched = TRUE;
}
//////////////// AUTOMATED EGG UP ////////////////////
// Check to see if pet's exp is over the limit
if (dwExp > MAX_PET_EXP)
{
dwExp = MAX_PET_EXP;
if (PetLevel != PL_S)
((CUser*)pMember)->AddText("Your pet is ready for leveling up. Bring it to the pet tamer!"); // Let the user know his pet is ready
}
if (!bHatched)
{
pPartyPet->SetExp(dwExp);
((CUser*)pMember)->AddPetSetExp(dwExp);
}
}
}
}
}
}
} else {
// Check if user has active pet
if (!HasActivatedSystemPet())
return;
// Get User Pet
CPet* pPet = this->GetPet();
// Get User Pet Level
if (pPet)
{
BYTE PetLevel = pPet->GetLevel();
// Change Base EXP according to Pet Level
switch (PetLevel)
{
case PL_EGG:
case PL_D:
{
nBaseExp *= 12.5;
}
break;
case PL_C:
{
nBaseExp *= 7;
}
break;
case PL_B:
{
nBaseExp *= 3.5;
}
break;
case PL_A:
{
nBaseExp *= 1;
}
break;
case PL_S:
{
nBaseExp = 0;
}
break;
}
// Check if user has any buff items up
if (HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_C))
nMulti += 0.25f;
if (HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_D))
nMulti += 0.5f;
// Calculate final EXP
DWORD dwExp = (DWORD)(pPet->GetExp() + (nBaseExp * nMulti));
//////////////// AUTOMATED EGG UP ////////////////////
BOOL bHatched = FALSE;
if (dwExp >= MAX_PET_EGG_EXP && PetLevel == PL_EGG)
{
PetLevelup();
bHatched = TRUE;
}
//////////////// AUTOMATED EGG UP ////////////////////
// Check to see if pet's exp is over the limit
if (dwExp > MAX_PET_EXP)
{
dwExp = MAX_PET_EXP;
if (PetLevel != PL_S)
((CUser*)this)->AddText("Your pet is ready for leveling up. Bring it to the pet tamer!"); // Let the user know his pet is ready
}
// Set the Pet's exp (if it wasnt an egg before)
if (!bHatched)
{
pPet->SetExp(dwExp);
((CUser*)this)->AddPetSetExp(dwExp);
}
}
}
}
#endif
Mover.h
Below
PHP Code:
void ProcessPetExp( void );
Add
PHP Code:
#ifdef __SYS_PETLEVELING_MOBKILL
void AddPetExpOnKill(DWORD dwMobRank, int nMonsterLevel, int nLevel);
#endif
MoverSkill.cpp Only add this if you want to add Pet-Tonics
Before
PHP Code:
#if __VER >= 9 // __PET_0410
case II_SYS_SYS_SCR_PET_TONIC_A:
case II_SYS_SYS_SCR_PET_TONIC_B:
#if __VER >= 12 // __PET_0519
Add
PHP Code:
#ifdef __SYS_PETLEVELING_MOBKILL
case II_SYS_SYS_SCR_PETTONIC_C:
{
if (HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_C))
{
nResult = 2;
break;
}
else if (HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_D))
{
nResult = 3;
break;
}
else {
DoApplySkill((CCtrl*)this, pItemProp, NULL);
}
}
break;
case II_SYS_SYS_SCR_PETTONIC_D:
{
if (HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_D))
{
nResult = 2;
break;
}
else if (HasBuff(BUFF_ITEM, II_SYS_SYS_SCR_PETTONIC_C))
{
nResult = 3;
break;
}
else {
DoApplySkill((CCtrl*)this, pItemProp, NULL);
}
}
break;
#endif
AttackArbiter.cpp
After
PHP Code:
m_pDefender->SubPVP(m_pAttacker, m_nReflect);
m_pAttacker->AddKillRecovery();
OnDiedSchoolEvent();
Add
PHP Code:
#ifdef __SYS_PETLEVELING_MOBKILL
if (m_pDefender->IsPlayer() == FALSE)
{
MoverProp* pMonster = m_pDefender->GetProp();
m_pAttacker->AddPetExpOnKill(pMonster->dwClass, m_pDefender->GetLevel(), m_pAttacker->GetLevel());
}
#endif
DPSrvr.cpp Only implement this, if you dont want eggs to be leveled by using Pet Feed
After
PHP Code:
void CDPSrvr::OnUsePetFeed( CAr & ar, DPID dpidCache, DPID dpidUser, LPBYTE lpBuf, u_long uBufSize )
{
CUser* pUser = g_UserMng.GetUser( dpidCache, dpidUser );
if( IsValidObj( pUser ) )
{
CPet* pPet = pUser->GetPet();
if( pPet == NULL )
{
pUser->AddDefinedText( TID_GAME_PET_NOT_FOUND );
return;
}
add
PHP Code:
#ifdef __SYS_PETLEVELING_MOBKILL
if (pPet->GetLevel() == PL_EGG)
{
pUser->AddText("You can not level eggs with pet feed here. Go kill some monsters!");
return;
}
#endif
VersionCommon.h (Neuz)
PHP Code:
#define __SYS_PETLEVELING_MOBKILL
VersionCommon.h (WorldServer)
PHP Code:
#define __SYS_PETLEVELING_MOBKILL
#ifdef __SYS_PETLEVELING_MOBKILL
#define PET_BASE_EXP 25.0f
#endif
You can add the Tonics yourself, just create items with the following Item Kinds: IK1_SYSTEM IK2_SYSTEM IK3_SCROLL
Explanation on modifiers:
In the VersionCommon.h the Base EXP for the pet is defined. It is 25.0f is 0.025% Pet EXP.
Increase this on your behalf, since there are many multiplicators you can change in the
Mover.cpp
Just go to the function
AddPetExpOnKill and take a look at the values there.
Currently it is set to 5% Pet EXP for a boss kill, x1.2 EXP for a giant kill, x1.2 EXP if the monster is 10 or more levels above the player, x1.25 EXP for dungeon mobs, +25% for the weak Pet Tonics and +50% for the strong Tonic.
All fine and dandy, where you can really make exp explode is what comes next: Differentiating pet levels. Currently Eggs and D-Level get 12.5x Base-EXP, C-Level gets 7x, B-Level 3.5x and A-Level gets base-exp.
Please note that the values for the base-exp can be changed indiviually depending on if the player is in a dungeon or not.
Do whatever you want with this. As always, feedback on how to improve the code is welcome.
I bet there are some flaws or possible optimizations, I'd be glad to hear them.