Coders Chit-Chat

A long time ago on the kalmax server there was a (bug) in which you could fly with a panther and a assassin mask on.
My Question, is it possible to create a addon which gives the option for players to fly?

If this is not what you meant for this thread i will move the question :)
If it is, could someone show a example for this? Curious if it is even possible.
 
@Bloodx did you ever do anything else with your KalOnline Engine Lua project?

I was wondering if you would consider (or if it is even possible) making a dll plugin of it for the files r3vo released for free (2016 engine) so that we can use lua scripts within a scripts folder like you had it in your project?

So a lua dll addon to give us the ability to use lua scripting with this setup.

Its not a "needed" addon i just think it would be a cool one and i would use it for sure !!
 
A long time ago on the kalmax server there was a (bug) in which you could fly with a panther and a assassin mask on.
My Question, is it possible to create a addon which gives the option for players to fly?

If this is not what you meant for this thread i will move the question :)
If it is, could someone show a example for this? Curious if it is even possible.

hmmm.. maybe this is possible if you Change Player Z Value and Syncro with the Client...

@Bloodx did you ever do anything else with your KalOnline Engine Lua project?

I was wondering if you would consider (or if it is even possible) making a dll plugin of it for the files r3vo released for free (2016 engine) so that we can use lua scripts within a scripts folder like you had it in your project?

So a lua dll addon to give us the ability to use lua scripting with this setup.

Its not a "needed" addon i just think it would be a cool one and i would use it for sure !!

I never continued the work on it, because no one really asked for it.. I think I still have the Source. should be possible to implement a scripting for ppl...

The Question is what kind of scripting is needed ? Changing values with memory editing ? or ? because for all kind of script functions you need to implement them at first..
 
I never continued the work on it, because no one really asked for it.. I think I still have the Source. should be possible to implement a scripting for ppl...

The Question is what kind of scripting is needed ? Changing values with memory editing ? or ? because for all kind of script functions you need to implement them at first..

Changing values with memory editing was why i wanted it.

also i had an old addon i got from someone years ago that used to give starter items in lua

so this may be a cool feature to add too

Code:
-- function Item(Pid,Index,Prefix,Info,Amount,MaxEnd,CurEnd)-- function ItemEx(Pid,Index,Prefix,Info,Amount,MaxEnd,CurEnd,Atk,Mag,Otp,Def,Eva,Eb)
-- function Buff(pid,buffid,bufftimeinminutes)
-- function Screen(...)
-- function State(...)
-- function Timestamp(minutes,addtime) -> addtime true/false



function Main(PID,Class)
    Screen("StarterItem PID: ",PID," Class: ",Class)
    if Class == 0 then -- knight
        ItemEx(PID,2606,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,2607,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,2608,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,790,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,791,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,1128,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,621,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,622,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,623,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,624,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,625,0,0,1,15,15,0,0,0,0,0,0)
    elseif Class == 1 then -- mage
        ItemEx(PID,2606,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,2607,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,2608,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,793,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,631,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,632,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,633,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,634,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,635,0,0,1,15,15,0,0,0,0,0,0)
    elseif Class == 2 then -- archer
        ItemEx(PID,2606,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,2607,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,2608,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,792,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,626,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,627,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,628,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,629,0,0,1,15,15,0,0,0,0,0,0)
        ItemEx(PID,630,0,0,1,15,15,0,0,0,0,0,0)
        


    end



    --for all classes
    Item(PID,337,0,0,1,1,1)
    Item(PID,338,0,0,1,1,1)
    Item(PID,339,0,0,1,1,1)
    Item(PID,559,0,0,1,20,20)


    
end
 
Last edited:
I would like to somehow rewrite the CCastle__WarDeclare from a txt editor where I can edit war time, start, ending, rewards given etc..
but for some reason I've got no clue what parameter should be given in:
static int(__cdecl *CCastle__WarBegin)(char a1, int Time) = (int(__cdecl*)(char a1, int Time))0x00419E10;
for example (char 1, int Time) what values should I insert there in order to get my command to work without server crashing
 
I would like to somehow rewrite the CCastle__WarDeclare from a txt editor where I can edit war time, start, ending, rewards given etc..
but for some reason I've got no clue what parameter should be given in:
static int(__cdecl *CCastle__WarBegin)(char a1, int Time) = (int(__cdecl*)(char a1, int Time))0x00419E10;
for example (char 1, int Time) what values should I insert there in order to get my command to work without server crashing

time_t is what you looking for.
Check void __cdecl CGuild::MinuteProcess(unsigned int dwTick); in there it is getting called.
Code:
  if ( g_CWState != CWState )
  {
    if ( CWState == 4 )
    {
      if ( *g_nSystem & 256 )
      {
        if ( g_nSystem[0] & 2 )
          pTime += 60 * (30 - pLocalTime->tm_min);
        else
          pTime += 3600;
      }
      else if ( pLocalTime->tm_hour == 21 )
      {
        pTime += 7200;
      }
      else
      {
        pTime += 3600;
      }
      CCastle::WarBegin(pTime);
    }
    if ( g_CWState != 4 || !CCastle::IsWarDeclared() )
      g_CWState = CWState;
  }
whole CGuild::MinuteProcess:
Code:
void __cdecl CGuild::MinuteProcess(unsigned int dwTick)
{
  int GuildMapEndIterator; // eax
  int v2; // [esp+0h] [ebp-28h]
  int v3; // [esp+4h] [ebp-24h]
  char v4; // [esp+8h] [ebp-20h]
  char a2; // [esp+Ch] [ebp-1Ch]
  CGuild *pGuild; // [esp+14h] [ebp-14h]
  int GuildMapBeginIterator; // [esp+18h] [ebp-10h]
  int CWState; // [esp+1Ch] [ebp-Ch]
  time_t pTime; // [esp+20h] [ebp-8h] MAPDST
  struct tm *pLocalTime; // [esp+24h] [ebp-4h]

  CRWLock::WriteLock(&pCRWLock);
  sub_40F070(g_GuildMap, &GuildMapBeginIterator);
  while ( 1 )
  {
    GuildMapEndIterator = sub_430C20(g_GuildMap, &a2);
    if ( !sub_47D070(&GuildMapBeginIterator, GuildMapEndIterator) )
      break;
    pGuild = sub_420250(&GuildMapBeginIterator, v2)[1];
    if ( pGuild->m_dwDeleteTick && pGuild->m_dwDeleteTick < dwTick )
    {
      if ( pGuild->m_nPlayerRef )
      {
        pGuild->m_dwDeleteTick = 0;
        sub_446090(&GuildMapBeginIterator, &v4, 0);
      }
      else
      {
        CBase::Delete(pGuild);
        GuildMapBeginIterator = *sub_44AF50(g_GuildMap, &v3, GuildMapBeginIterator);
      }
    }
    else
    {
      sub_446090(&GuildMapBeginIterator, &v2, 0);
    }
  }
  pTime = time(0);
  pLocalTime = localtime(&pTime);
  CWState = 0;
  if ( *g_nSystem & 256 )
  {
    if ( g_nSystem[0] & 2 )
    {
      if ( pLocalTime->tm_min >= 5 )
      {
        if ( pLocalTime->tm_min >= 15 )
        {
          if ( pLocalTime->tm_min >= 16 )
          {
            if ( pLocalTime->tm_min < 50 )
              CWState = 4;
          }
          else
          {
            CWState = 2;
          }
        }
        else
        {
          CWState = 1;
        }
      }
      else
      {
        CWState = 0;
      }
    }
    else if ( pLocalTime->tm_hour >= 17 )
    {
      if ( pLocalTime->tm_hour >= 18 )
      {
        if ( pLocalTime->tm_hour < 19 )
          CWState = 4;
      }
      else if ( pLocalTime->tm_min >= 30 )
      {
        CWState = 2;
      }
      else
      {
        CWState = 1;
      }
    }
    else
    {
      CWState = 0;
    }
  }
  else
  {
    switch ( pLocalTime->tm_wday )
    {
      case 4:
        if ( pLocalTime->tm_hour >= 21 )
          CWState = 1;
        break;
      case 5:
        if ( pLocalTime->tm_hour >= 21 )
          CWState = 2;
        else
          CWState = 1;
        break;
      case 6:
        if ( pLocalTime->tm_hour >= 21 )
        {
          if ( pLocalTime->tm_hour < 23 )
            CWState = 4;
        }
        else
        {
          CWState = 2;
        }
        break;
    }
  }
  if ( g_CWState != CWState )
  {
    if ( CWState == 4 )
    {
      if ( *g_nSystem & 256 )
      {
        if ( g_nSystem[0] & 2 )
          pTime += 60 * (30 - pLocalTime->tm_min);
        else
          pTime += 3600;
      }
      else if ( pLocalTime->tm_hour == 21 )
      {
        pTime += 7200;
      }
      else
      {
        pTime += 3600;
      }
      CCastle::WarBegin(pTime);
    }
    if ( g_CWState != 4 || !CCastle::IsWarDeclared() )
      g_CWState = CWState;
  }
  if ( g_CWState )
    CAlliance::PostponeExpire();
  else
    CAlliance::Expire(pTime);
  CRWLock::WriteUnlock(&pCRWLock);
  CCastle::TaxSave();
}
 
Player::_FindItem(Player *player, int index, int amount) 0x0045D1E0 should it be..

returns Item Object.


Code:
int* item = Player::FindItem(player,index,amount);
						if(item)
						{
							int state = item[12];
							if(state == 1 || state == 9 || state == 129)
							{
								// item is weared..
							}
						}
 
Last edited:
I posted my item class long time ago which should help.
http://forum.ragezone.com/f389/source-code-collection-917296-post8081460/#post8081460

you could use it like this:
Code:
static int(__thiscall *FindItem)(int Player, WORD ItemIndex, int Amount) = (int(__thiscall*)(int, WORD, int))0x0045D190;


auto_ptr<KItem> pItem(new KItem(FindItem(pPlayer, nIndex, nNum)));

 if (pItem->IsState(ITEM_MIX_ICE | ITEM_MIX_LEVEL2 | ITEM_OWN | ITEM_PUTON)){
  //do something if the item is g2 ice mix bound and equipped
  pItem->SetAttack(20); //update attack to 20
  pItem->SetEB(20); //update eb to 20
  pItem->SendItemInfo(); //send item info to client
 }


// Item Info​
Code:
#define ITEM_PUTON   0x00000001
#define ITEM_SETGEM   0x00000002
#define ITEM_ONTRADE  0x00000004
#define ITEM_CHEAT   0x00000008
#define ITEM_STORAGE  0x00000010
#define ITEM_TRANSFORM  0x00000020
#define ITEM_PROTECTED  0x00000040
#define ITEM_OWN   0x00000080
#define ITEM_MIX_DARK  0x00000100
#define ITEM_MIX_SAINT  0x00000200
#define ITEM_MIX_FLAME  0x00000400
#define ITEM_MIX_ICE  0x00000800
#define ITEM_MIX_LIGHT  0x00001000
#define ITEM_MIX_POISON  0x00002000
#define ITEM_MIX_PARAL  0x00004000
#define ITEM_MIX_POWER  0x00008000
#define ITEM_MIX_TECH  0x00010000
#define ITEM_MIX_FANTA  0x00020000
#define ITEM_MIX_BLOOD  0x00040000
#define ITEM_MIX_LEVEL1  0x00080000
#define ITEM_MIX_LEVEL2  0x00100000
#define ITEM_MIX_FIREBALL 0x00200000

#define ITEM_LOCKSYSTEM  0x00400000
#define ITEM_OWNMASK  ( ITEM_CHEAT | ITEM_OWN)
#define ITEM_NOTMOVEMASK ( ITEM_PUTON | ITEM_OWNMASK)
#define ITEM_STORAGEMASK ( ITEM_OWNMASK | ITEM_TRANSFORM | ITEM_PROTECTED)
#define ITEM_MIX   ( ITEM_MIX_DARK | ITEM_MIX_SAINT | ITEM_MIX_FLAME | ITEM_MIX_ICE | ITEM_MIX_LIGHT | ITEM_MIX_POISON | ITEM_MIX_PARAL | ITEM_MIX_POWER | ITEM_MIX_TECH | ITEM_MIX_FANTA | ITEM_MIX_BLOOD | ITEM_MIX_FIREBALL)
 
Well, I've tried hooking up Life absorption in order to make it OTP based..
Unfortunately I couldn't find the address of the LA function itself,
I've tried applying it through ExcuteSkill() unfortunately it started acting weird as i didn't provide the proper variables required for damage calculation, any hint would be appreciated.
Thanks you.
 
Well, I've tried hooking up Life absorption in order to make it OTP based..
Unfortunately I couldn't find the address of the LA function itself,
I've tried applying it through ExcuteSkill() unfortunately it started acting weird as i didn't provide the proper variables required for damage calculation, any hint would be appreciated.
Thanks you.
Here some code from my script engine project.
change CPlayerSkillEx* and CSkillEx* to void* or any type you like and use pointer offsets as everyone does.
Code:
int __fastcall PreSkill(CPlayerSkillEx *PlayerSkill, void *edx, int nSkill, int nTargetId);
void __fastcall ExcuteSkill(CPlayerSkillEx *PlayerSkill, void *_edx, signed int nSkill, char* packet, char *packetend);
void __fastcall SetSkill(CPlayerSkillEx *PlayerSkill, void *_edx, int nSkill, int nLevel);
void __fastcall SkillUp(CPlayerSkillEx *CPlayerSkill, void *_edx, int nSkill);
void __fastcall LearnSkill(CPlayerSkillEx *PlayerSkill, void* _edx, int nSkill);
void __fastcall ExcutePassiveSkill(CPlayerSkillEx *PlayerSkill, void *edx);
void __fastcall ExcutePassiveSkillV(CPlayerSkillEx *PlayerSkill, void*edx, int nSkill, ...);

Memory->Intercept(IMemory::_I_CALL, (void*)0x457077, _CPlayerSkillEx::SetSkill, 5);
Memory->HookAPI(0x47F7A0, _CPlayerSkillEx::LearnSkill);
Memory->HookAPI(0x47F970, _CPlayerSkillEx::SkillUp);
Memory->HookAPI(0x47FBB0, _CPlayerSkillEx::ExcuteSkill);
Memory->HookAPI(0x480390, _CPlayerSkillEx::PreSkill);

void __fastcall _CPlayerSkillEx::ExcuteSkill(CPlayerSkillEx *PlayerSkill, void *_edx, signed int nSkill, char* data, char *dataEnd){
 PlayerSkill->m_pOwner->Write(S2C_CHATTING, "ss", "CPlayerSkillEx::ExcuteSkill", format("Skill Index: %d", nSkill).c_str());
 if (nSkill < 84){
  CSkillEx *pSkill = PlayerSkill->m_pSkill[nSkill];
  if (pSkill)
   pSkill->Excute(PlayerSkill->m_pOwner, data, dataEnd);
 }
}

int __fastcall _CPlayerSkillEx::PreSkill(CPlayerSkillEx *PlayerSkill, void *edx, int nSkill, int nTargetId){
 PlayerSkill->m_pOwner->Write(S2C_CHATTING, "ss", "CPlayerSkillEx::PreSkill", format("nSkill: %d", nSkill).c_str());
 if (nSkill >= 64)
  return 1;
 CSkillEx *pSkill = PlayerSkill->m_pSkill[nSkill];
 if (pSkill)
  return pSkill->PreExcute(PlayerSkill->m_pOwner, nTargetId);
 return 0;
}

void __fastcall _CPlayerSkillEx::ExcutePassiveSkill(CPlayerSkillEx *PlayerSkill, void *edx){
 for (signed int i = 0; i < 84; ++i){
  CSkillEx *pSkill = PlayerSkill->m_pSkill[i];
  if (pSkill)
   pSkill->ExcutePassive(PlayerSkill->m_pOwner, 0, 0);
 }
}

void __fastcall ExcutePassiveSkillV(CPlayerSkillEx *PlayerSkill, void*edx, int nSkill, ...){
 va_list va;
 va_start(va, nSkill);
 CSkillEx *pSkill = PlayerSkill->m_pSkill[nSkill];
 if (pSkill)
  pSkill->ExcutePassiveV(PlayerSkill->m_pOwner, va);
 va_end(va);
}

  
void __fastcall _CPlayerSkillEx::LearnSkill(CPlayerSkillEx *PlayerSkill, void* _edx, int nSkill){
 if (nSkill < MAX_SKILL_INDEX && !PlayerSkill->IsSkill(nSkill)){
  CSkillEx *pSkill = PlayerSkill->FindSkillEx(nSkill);
  if (pSkill != NULL){
   if (pSkill->CanLearn(PlayerSkill->m_pOwner->m_nLevel, PlayerSkill->m_pOwner->m_dwSpecialty)){
    if (PlayerSkill->IsLearnSkill(pSkill->m_nLmtSkill, pSkill->m_nLmtSkillLevel)){
     pSkill = _CSkillEx::Copy(pSkill);
     _CSkillEx::Init(pSkill, nSkill, 1);
     pSkill->ExcutePassive(PlayerSkill->m_pOwner, 0, 0);
     PlayerSkill->m_pSkill[nSkill] = pSkill;
     if (PlayerSkill->IsSpendSUPointSkill(nSkill))
      PlayerSkill->m_pOwner->vPlayer->UpdateProperty(PlayerSkill->m_pOwner, P_SUPOINT, FALSE, 1);
     PlayerSkill->m_pOwner->Write(S2C_SKILLUP, "bb", nSkill, 1);
     MainServer::_CDBSocket::Write(S2D_INSERTSKILL, "dbw", PlayerSkill->m_pOwner->m_nPID, nSkill, PlayerSkill->m_pOwner->m_nSUPoint);
    }
   }
  }
  else
   CLog::Write(RED, "CPlayerSkillEx::LearnSkill() Can't find Skill(Class:%d, Skill:%d)", PlayerSkill->m_nClass, nSkill);
 }
}

void __fastcall _CPlayerSkillEx::SkillUp(CPlayerSkillEx *PlayerSkill, void *edx, int nSkill){
 if (nSkill < MAX_SKILL_INDEX){
  CSkillEx *pSkill = PlayerSkill->m_pSkill[nSkill];
  if (pSkill != NULL){
   if (pSkill->CanSkillUp(PlayerSkill->m_pOwner)){
    int NewLevel = pSkill->m_nLevel + 1;
    pSkill->ExcutePassive(PlayerSkill->m_pOwner, NewLevel, TRUE);
    pSkill->m_nLevel = NewLevel;
    if (PlayerSkill->IsSpendSUPointSkill(nSkill))
     PlayerSkill->m_pOwner->vPlayer->UpdateProperty(PlayerSkill->m_pOwner, P_SUPOINT, FALSE, 1);
    PlayerSkill->m_pOwner->Write(S2C_SKILLUP, "bb", nSkill, NewLevel);
    MainServer::_CDBSocket::Write(S2D_SKILLUP, "dbbw", PlayerSkill->m_pOwner->m_nPID, nSkill, NewLevel, PlayerSkill->m_pOwner->m_nSUPoint);
   }
  }else
   CLog::Write(RED, "CPlayerSkillEx::SkillUp() Can't find Skill(Class:%d, Skill:%d)", PlayerSkill->m_nClass, nSkill);
 }
}

void __fastcall _CPlayerSkillEx::SetSkill(CPlayerSkillEx *PlayerSkill, void *_edx, int nSkill, int nLevel){
 if (nSkill > MAX_SKILL_INDEX)
  return;
 CSkillEx *pSkill = NULL;
 CSkillEx *pSkillCopy = NULL;
 if (PlayerSkill->m_nClass <= PC_ARCHER){
  pSkill = (CSkillEx *)PlayerSkill->FindSkill(nSkill);
  if (pSkill != NULL){
   pSkillCopy = _CSkillEx::Copy(pSkill);
   _CSkillEx::Init(pSkillCopy, nSkill, nLevel);
   PlayerSkill->m_pSkill[nSkill] = pSkillCopy;
   return;
  }
  else
   CLog::Write(RED, "CPlayerSkillEx::SetSkill() Can't find Skill(Class:%d, Skill:%d)", PlayerSkill->m_nClass, nSkill);
 }else//Thief or Shamman Skill Test
 {
  CSkillEx *pSkillEx = NULL;
  CSkillEx *pSkillCopyEx = NULL;
  pSkillEx = PlayerSkill->FindSkillEx(nSkill);
  if (pSkillEx != NULL){
   pSkillCopyEx = (CSkillEx *)CopyEx(pSkillEx);
   InitEx(pSkillCopyEx, nSkill, nLevel);
   PlayerSkill->m_pSkill[nSkill] = pSkillCopyEx;
   return;
  }
  else
   CLog::Write(RED, "CPlayerSkillEx::SetSkill() Can't find Skill(Class:%d, Skill:%d)", PlayerSkill->m_nClass, nSkill);
 }
}
any questions?
 
Brilliant, I've got it sorted out apparently all I was missing was the proper function to hook..
Well, one more issue is that I can't get to rewrite AllotEXP__Party in order to apply exp events or fixes for exp calculation
A code snippet or AllotEXP__Party rewritten would be highly appreciated,
As always, Thank you for practicing into pumping life in Kal section once more.
 
well, i have barely touched it but here is what i've got so far.

Code:
void __thiscall CParty::AllotExp(CParty *pParty, int *nAllExp, int nMonsterLevel, tagPOINT *ptPMonster)
{
  void *EndIt; // eax MAPDST
  char *Pair; // eax
  char v11; // [esp+3Ch] [ebp-68h]
  int a2; // [esp+40h] [ebp-64h]
  char v13; // [esp+48h] [ebp-5Ch]
  char v14; // [esp+50h] [ebp-54h]
  char v15; // [esp+54h] [ebp-50h]
  char v16; // [esp+58h] [ebp-4Ch]
  char v17; // [esp+5Ch] [ebp-48h]
  int nBonusExp; // [esp+60h] [ebp-44h]
  int beginit; // [esp+64h] [ebp-40h]
  char BeginIt; // [esp+6Ch] [ebp-38h] MAPDST
  int nCount; // [esp+70h] [ebp-34h]
  int nLevelDiff; // [esp+74h] [ebp-30h] MAPDST
  int nTopLevel; // [esp+78h] [ebp-2Ch]
  CChar *pPartyMember; // [esp+7Ch] [ebp-28h]
  int nLevelAdd; // [esp+80h] [ebp-24h]
  void *v27; // [esp+84h] [ebp-20h]
  int Exp; // [esp+94h] [ebp-10h]
  std::map varC; // [esp+98h] [ebp-Ch]




  CIOCriticalSection::Enter(&pParty->m_lock);
  nLevelDiff = nMonsterLevel - pParty->m_nTopLevel;
  if ( nLevelDiff < 0 )
  {
    if ( abs(nLevelDiff) >= 20 )
      nLevelDiff = 20;
    else
      nLevelDiff = abs(nLevelDiff);
    *nAllExp = (*nAllExp - *nAllExp * (g_nReviseExpB[(pParty->m_nTopLevel - 1) / 10][nLevelDiff] / 100.0));
  }
  else
  {
    if ( nLevelDiff >= 20 )
      nLevelDiff = 20;
    *nAllExp = (*nAllExp * (g_nReviseExpA[(pParty->m_nTopLevel - 1) / 10][nLevelDiff] / 100.0) + *nAllExp);
  }
  if ( *nAllExp > 0 )
  {
    sub_41C7D0(&v27);
    nLevelAdd = 0;
    nCount = 0;
    Container::Find(pParty->m_vecParty);
    while ( 1 )
    {
      EndIt = Container::End(pParty->m_vecParty, &v16);
      if ( !Container::iterator::not_equal(&BeginIt, EndIt) )
        break;
      pPartyMember = Container::GetObject(&BeginIt)->vfptr;
      if ( CChar::IsNormal(pPartyMember) && PowDistance(&pPartyMember->m_ptPixel, ptPMonster) <= 640 )
      {
        if ( pParty->m_nTopLevel - pPartyMember->m_nLevel <= 20 )
          ++nCount;
        nLevelAdd += pPartyMember->m_nLevel;
        sub_41C840(&v27, &pPartyMember);
      }
      sub_420030(&v17, 0);
    }
    if ( nCount > 1 )
      *nAllExp = (*nAllExp * ((nCount - 1) / 10.0) + *nAllExp);
    sub_445C80(&varC);
    nTopLevel = pParty->m_nTopLevel;
    Container::Find(&v27);
    while ( 1 )
    {
      EndIt = Container::End(&v27, &v14);
      if ( !Container::iterator::not_equal(&BeginIt, EndIt) )
        break;
      pPartyMember = Container::GetObject(&BeginIt)->vfptr;
      Exp = (*nAllExp * (pPartyMember->m_nLevel / nLevelAdd));
      nLevelDiff = nTopLevel - pPartyMember->m_nLevel;
      if ( nLevelDiff <= 28 )
      {
        if ( nLevelDiff > 0 )
          Exp = (Exp - Exp * (g_nRevisePartyExp[nLevelDiff] / 100.0));
      }
      else
      {
        Exp = 0;
      }
      if ( Exp )
      {
        CIOObject::AddRef(&pPartyMember->ParantClass.vfptr, &pPartyMember->m_nFindRef);
        Pair = PairStdMap(&v13, &pPartyMember, &Exp);
        STLMap_Insert(&varC, &a2, Pair);
      }
      sub_420030(&v15, 0);
    }
    CIOCriticalSection::Leave(&pParty->m_lock);
    *nAllExp = 0;
    std::map::begin(&varC, &beginit);
    while ( 1 )
    {
      EndIt = Container::Find(&varC);
      if ( !Container::iterator::not_equal(&beginit, EndIt) )
        break;
      pPartyMember = *std::map::iterator::value(&beginit);
      Exp = *(std::map::iterator::value(&beginit) + 4);
      *nAllExp += Exp;
      nBonusExp = (CMainConfig::s_nEvent & 1) != 0 ? 0x64 : 0;
      if ( CChar::IsBState(pPartyMember, 0x8000000000i64)
        || CChar::IsBState(pPartyMember, 0x10000000000i64)
        || CChar::IsBState(pPartyMember, 0x20000000000i64) )
      {
        nBonusExp += 10;
      }
      if ( CChar::IsBState(pPartyMember, 2i64) )
      {
        nBonusExp += 30;
      }
      else if ( CChar::IsBState(pPartyMember, 1i64) )
      {
        nBonusExp += 30;
      }
      pPartyMember->ParantClass.vfptr->UpdateProperty(pPartyMember, P_EXP, P_INCREASE, (Exp + nBonusExp * Exp / 100));
      CIOObject::_Release(&pPartyMember->ParantClass.vfptr, &pPartyMember->m_nFindRef);
      sub_446090(&beginit, &v11, 0);
    }
    sub_4398F0(&varC);
    sub_44F580(&v27);
  }
  else
  {
    CIOCriticalSection::Leave(&pParty->m_lock);
  }
}


Code:
int GetColorLevel(int nMonsterLevel, int nPlayerLevel){
 int nDiffLevel = (nMonsterLevel - nPlayerLevel);
 if (nDiffLevel < 0){
  if (abs(nDiffLevel) >= 20)
   nDiffLevel = 20;
  else
   nDiffLevel = abs(nDiffLevel);
  return g_nDLvB[(nPlayerLevel - 1) / 10][nDiffLevel];
 }else{
  if (nDiffLevel >= 20)
   nDiffLevel = 20;
  else
   nDiffLevel = nMonsterLevel - nPlayerLevel;
  return g_nDLvA[(nPlayerLevel - 1) / 10][nDiffLevel];
 }
 return 0;
}




void CMonsterReal::AllotTransformExp(int bParty, int nID){
 CPlayer *pPlayer;
 CParty *pParty;
 if (bParty){
  pParty = CParty::FindParty(nID);
  if (pParty){
   pParty->AllotTransformExp(this->m_nLevel, &this->m_ptPixel);
   pParty->Release();
  }
 }else{
  pPlayer = CPlayer::FindPlayer(nID);
  if (pPlayer){
   if (GetColorLevel(this->m_nLevel, pPlayer->m_nLevel) >= 3)
    pPlayer->UpdateTransformExp(0);
   pPlayer->Release(&pPlayer->m_nFindRef);
  }
 }
}




void CMonsterReal::Die(CChar *pChar, int bFatal, int *bParty, int *nKeyID){
 this->m_nCurHP = 0;
 pChar->InfoDie(this->m_nId, bFatal);
 int nBestID = 0;
 this->AllotExp(bParty, nKeyID, &nBestID);
 this->m_pInit->DropItem(this, *bParty, *nKeyID, nBestID, pChar->GetDropItemMask());
 this->CancelAllBuff();
 this->WriteInSight(S2C_ACTION, "db", this->m_nId, AT_DIE);
}
 
Last edited:
Where can I find/track passive skills?
Well, excuteskill can track these attackable skills.. but how about passive/buff skills that can be called on player's login for a boost or something, where does it get handled?
 
Code:
.text:0047FC00    ; public: void __thiscall CPlayerSkill::ExcutePassiveSkill(void)
.text:0047FC50;public: void __cdecl CPlayerSkill::ExcutePassiveSkill(int, ...)




void __thiscall CPlayerSkill::ExcutePassiveSkill(CPlayerSkill *this)
{
 CSkill *pSkill; // [esp+4h] [ebp-8h]
 int i; // [esp+8h] [ebp-4h]
 for (i = 0; i < 84; ++i)
 {
  pSkill = this->m_pSkill[i];
  if (pSkill)
   pSkill->vfptr->ExcutePassive(this->m_pOwner, 0, 0);
 }
}




void CPlayerSkill::ExcutePassiveSkill(CPlayerSkill *this, ...)
{
 CSkill *pSkill; // [esp+4h] [ebp-4h]
 int nSkill; // [esp+14h] [ebp+Ch]
 va_list vaList; // [esp+18h] [ebp+10h]
 va_start(vaList, this);
 nSkill = va_arg(vaList, _DWORD);
 pSkill = this->m_pSkill[nSkill];  if (pSkill)
  pSkill->vfptr->ExcutePassiveV(this->m_pOwner, vaList);
}
 
Thanks, talking about skills.. here are 2 useful functions i found (i think you already know them but i'll show them anyways)
Check if a player doesnt have a skill:
PHP:
static int(__thiscall *CPlayerSkill__IsSkill)( int thispointer, int a2) = (int(__thiscall*)(int thispointerpointer, int a2))0x0044A940;
if (!Server::CPlayer::CPlayerSkill__IsSkill(((int)PlayerPointer) + 624, SkillID))
----
Skill reading on player login (so incase you want to call off a skill while player is logging in):
PHP:
static void(__thiscall *SetSkill)(int Player, int SkillID, int a3) = (void(__thiscall*)(int Player, int SkillID, int a3))0x0047F6B0;
 
Last edited:
Back