Files
ROSS/Src/World Server/playerstats.cpp
T
2025-08-11 11:09:09 -05:00

1976 lines
73 KiB
C++

/*
Rose Online Server Emulator
Copyright (C) 2006,2007 OSRose Team http://www.osrose.net
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
depeloped with Main erose/hrose source server + some change from the original eich source
*/
#include "player.h"
#include "worldserver.h"
// Return Dodge
unsigned int CPlayer::GetDodge( )
{
UINT Dodge = 0;
Dodge = (UINT)floor(( ((Stats->Level * 0.3) + ((Attr->Dex + Attr->Edex) * 1.9)) + 10 ) * 0.4);
UINT ClothDodge = 0;
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if (i < 7)
ClothDodge += items[i].durability;
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_DODGE)
{
Dodge += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_DODGE)
{
Dodge += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_DODGE)
Dodge += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_DODGE)
Dodge += GServer->StatsList[items[i].stats].value[1];
}
}
}
Dodge += (UINT)floor(ClothDodge*0.3);
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sDodge )
{
if( skill->value2[j] > 0 )
Extra += Dodge * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
Dodge += Extra;
if(Status->Dodge_up!=0xff)
Dodge += MagicStatus[Status->Dodge_up].Value;
if(Status->Dodge_down!=0xff)
Dodge -= MagicStatus[Status->Dodge_down].Value;
if(Dodge<30)
Dodge=30;
return Dodge;
}
// Return Accury
unsigned int CPlayer::GetAccury( )
{
UINT Accury = 0;
if(items[7].count==0 )
Accury = (UINT)floor( (((Attr->Con + Attr->Econ )+10)*0.5) + 15 );
else
Accury = (UINT)floor( ((Attr->Con+Attr->Econ+10)*0.8) + ((GServer->EquipList[WEAPON].Index[items[7].itemnum]->quality*0.6) + (items[7].durability*0.8)) );
UINT extra_refine[10] = { 0, 4, 7, 10, 14, 20, 26, 33, 40, 50};
if( items[7].refine>0 )
{
UINT refine = (UINT)floor((double)(items[7].refine/16));
if(refine<10)
{
Accury += extra_refine[refine];
}
}
for(UINT i=1;i<12;i++)
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_ACCUR)
{
Accury += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_ACCUR)
{
Accury += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_ACCUR)
Accury += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_ACCUR)
Accury += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sAccuracy )
{
if( skill->value2[j] > 0 )
Extra += Accury * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
Accury += Extra;
if(Status->Accury_up!=0xff)
Accury += MagicStatus[Status->Dodge_up].Value;
if(Status->Accury_down!=0xff)
Accury -= MagicStatus[Status->Accury_down].Value;
if(Accury<30)
Accury=30;
return Accury;
}
// Return Critical
unsigned int CPlayer::GetCritical( )
{
UINT Critical = 0;
UINT weapontype = 1;
if(items[7].itemnum!=0 && items[7].count > 0) // weapon equipped
weapontype = GServer->EquipList[WEAPON].Index[items[7].itemnum]->type;
Critical = (UINT)floor(((Attr->Con + Attr->Econ + 20)*0.2) + Attr->Sen + Attr->Esen );
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0)
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_CRITICAL)
{
Critical += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_CRITICAL)
{
Critical += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_CRITICAL)
Critical += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_CRITICAL)
Critical += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
//item specific crit boosts
for(int n=0;n<5;n++)
{
if( skill->weapon[n] == weapontype) // item defined in the skill
{
if( skill->value2[j] > 0 )
Extra += Critical * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
}
Critical += Extra;
if(Fairy)Critical = (unsigned int)floor(Critical*1.2);
if(Status->Critical_up!=0xff)
Critical += MagicStatus[Status->Critical_up].Value;
if(Status->Critical_down!=0xff)
Critical -= MagicStatus[Status->Critical_down].Value;
if(Critical<10)
Critical=10;
return Critical;
}
// Return Magic Attack based on the weapon currently equipped
unsigned int CPlayer::GetMagicAttack( )
{
if(GServer->EquipList[WEAPON].Index[items[7].itemnum]->magicattack == 1)
return 1;
else
return 0;
}
// Return Magic Defense
unsigned int CPlayer::GetMagicDefense( )
{
UINT MagicDefense = 0;
UINT Extra = 0;
switch( CharInfo->Job )
{
case 121:case 122:
case 221:case 222:
case 321:case 322:
case 421:case 422:
Extra += 20;
break;
default:
break;
}
MagicDefense += (UINT)floor(((Attr->Int + Attr->Eint + 5)*0.6) + ((Stats->Level + 15)*0.8));
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if (i < 9 && items[i].itemtype != WEAPON)
MagicDefense += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->magicresistence;
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_MRESIST)
{
MagicDefense += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_MRESIST)
{
MagicDefense += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_MRESIST)
MagicDefense += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_MRESIST)
MagicDefense += GServer->StatsList[items[i].stats].value[1];
}
}
}
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMagicResistance )
{
if( skill->value2[j] > 0 )
Extra += MagicDefense * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
MagicDefense += Extra;
if(Status->Magic_Defense_up!=0xff)
MagicDefense += MagicStatus[Status->Magic_Defense_up].Value;
if(Status->Magic_Defense_down!=0xff)
MagicDefense -= MagicStatus[Status->Magic_Defense_down].Value;
return MagicDefense;
}
// Return Attack
unsigned int CPlayer::GetAttackPower( )
{
UINT attack = 0;
UINT weapontype = 0;
UINT weaponatk = 0;
UINT Extra = 0;
UINT skilltype = 0;
switch(CharInfo->Job)
{
case 121:case 122:
case 221:case 222:
case 321:case 322:
case 421:case 422:
Extra += 30;
break;
default:
break;
}
if( items[7].itemnum!=0 && items[7].count > 0 && items[7].durability > 0 )
{
UINT extra_refine[10] = {0, 7, 14, 21, 31, 41, 51, 65, 80 , 100};
weaponatk = GServer->EquipList[WEAPON].Index[items[7].itemnum]->attackpower;
weapontype = GServer->EquipList[WEAPON].Index[items[7].itemnum]->type;
if( items[7].refine > 0 )
{
UINT refine = (UINT)floor((double)(items[7].refine/16));
if(refine>0 && refine<10)
{
weaponatk += (UINT)floor(extra_refine[refine] * 0.01 * weaponatk);
}
}
if(Session->codedebug)
{
Log( MSG_INFO, "Base AP with weapon equipped (includes refines) %i",attack );
}
}
else
{
attack += (UINT)floor( ((Attr->Dex + Attr->Edex) * 0.3) + ((Attr->Str + Attr->Estr) * 0.5) + (Stats->Level * 0.2));
if(Session->codedebug)
{
Log( MSG_INFO, "AP unarmed %i",attack );
}
}
switch( weapontype )
{
case ONE_HAND_SWORD://one hand sword
{
attack += (UINT)floor( (Attr->Str + Attr->Estr) * 0.75 + Stats->Level * 0.2 + ((Attr->Str + Attr->Estr) * 0.05 + 29) * weaponatk * 0.03333334 );
if(Session->codedebug)
{
Log( MSG_INFO, "AP from sword only is %i",attack );
}
skilltype = 42;
}
break;
case ONE_HAND_BUNT_SWORD://one hand blunt sword
{
attack += (UINT)floor( (Attr->Str + Attr->Estr)*0.75 + Stats->Level*0.2 + ((Attr->Str + Attr->Estr)*0.05 + 29) * weaponatk * 0.03333334 );
skilltype = 42;
}
break;
case TWO_HAND_SWORD://two hand sword
{
attack += (UINT)floor( (Attr->Str + Attr->Estr)*0.75 + Stats->Level*0.2 + ((Attr->Str + Attr->Estr)*0.05 + 29) * weaponatk * 0.03333334 );
skilltype = 43;
}
break;
case SPEAR://spear
{
attack += (UINT)floor( (Attr->Str + Attr->Estr)*0.75 + Stats->Level*0.2 + ((Attr->Str + Attr->Estr)*0.05 + 29) * weaponatk * 0.03333334 );
skilltype = 43;
}
break;
case TWO_HAND_AXE://two hand axe
{
attack += (UINT)floor( (Attr->Str + Attr->Estr)*0.75 + Stats->Level*0.2 + ((Attr->Str + Attr->Estr)*0.05 + 29) * weaponatk * 0.03333334 );
skilltype = 43;
}
break;
case BOW://bow
{
float arrows = 0;
if(items[132].count>0)
arrows = GServer->NaturalList.Index[items[132].itemnum]->quality * 0.5;
attack += (UINT)floor((((Attr->Str + Attr->Estr) + Stats->Level) * 0.1) + ((Attr->Dex + Attr->Edex) * 0.04 + (Attr->Sen + Attr->Esen) * 0.03 + 29) * weaponatk * 0.03333334 + (Attr->Dex+Attr->Edex) * 0.52 + arrows);
if(Session->codedebug)
{
Log( MSG_INFO, "AP from Bow + Arrows only is %i",attack );
}
skilltype = 44; //Bow attack power
}
break;
case GUN://gun
case DUAL_GUN://dual guns
{
float bullets = 0;
if(items[133].count>1)
bullets = GServer->NaturalList.Index[items[133].itemnum]->quality * 0.8;
attack += (UINT)floor( (Attr->Con + Attr->Econ)*0.47 + bullets + Stats->Level*0.1 + (Attr->Dex + Attr->Edex)*0.3 + ((Attr->Con + Attr->Econ)*0.04 + (Attr->Sen + Attr->Esen)*0.05 + 29) * weaponatk * 0.03333334);
skilltype = 45;
}
break;
case LAUNCHER://launcher
{
float cannons = 0;
if(items[134].count>0)
{
cannons = GServer->NaturalList.Index[items[134].itemnum]->quality;
}
attack += (UINT)floor( cannons*0.8 + Stats->Level*0.1 + (Attr->Str + Attr->Estr)*0.32 + (Attr->Con + Attr->Econ)*0.45 + ((Attr->Con + Attr->Econ)*0.04 + (Attr->Sen + Attr->Esen)*0.05 + 29) * weaponatk * 0.03333334 );
skilltype = 45;
}
break;
case STAFF://staff
{
attack += (UINT)floor( Stats->Level*0.2 + ((Attr->Int + Attr->Eint)+(Attr->Str + Attr->Estr))*0.4 + ((Attr->Int + Attr-> Eint)*0.05 + 29) * weaponatk * 0.03333334 );
skilltype = 46;
}
break;
case WAND://wand
{
attack += (UINT)floor( Stats->Level*0.2 + (Attr->Int + Attr->Eint)*0.6 + ( ((Attr->Sen + Attr->Esen)*0.1 +26) * 0.03703704 * weaponatk ) );
skilltype = 46;
}
break;
case KATAR://katar
{
attack += (UINT)floor( Stats->Level*0.2 + (Attr->Str + Attr->Estr)*0.42 + (Attr->Dex + Attr->Edex)*0.55 + ((Attr->Dex + Attr->Edex)*0.05 + 20) * weaponatk * 0.0476190);
skilltype = 48;
}
break;
case DOUBLE_SWORD://double sword
{
attack += (UINT)floor( Stats->Level*0.2 + (Attr->Str + Attr->Estr)*0.63 + (Attr->Dex + Attr->Edex)*0.45 + ((Attr->Dex + Attr->Edex)*0.05 + 25) * weaponatk * 0.03846154);
skilltype = 48;
}
break;
case CROSSBOW://crossbow
{
float arrows = 0;
if(items[132].count>0)
arrows = GServer->NaturalList.Index[items[132].itemnum]->quality*0.5;
attack += (UINT)floor((((Attr->Str + Attr->Estr)+Stats->Level)*0.1) + ((Attr->Dex + Attr->Edex)*0.04 + (Attr->Sen +Attr->Esen)*0.03 + 29) * weaponatk * 0.03333334 + (Attr->Dex + Attr->Edex)*0.52 + arrows);
skilltype = 47; //Crossbow Attack Power
}
break;
default:
break;
}
for(UINT i=1;i<12;i++)//cloth stats
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == 18)
{
attack += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == 18)
{
attack += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == 18)
attack += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == 18)
attack += GServer->StatsList[items[i].stats].value[1];
}
}
}
if(Session->codedebug)
{
Log( MSG_INFO, "AP after cloth stats %i",attack );
}
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
//weapon specific AP boosts
for(int n=0;n<5;n++)
{
if(weapontype == 0) //no weapon equipped
{
if( skill->buff[j] == 41) //unarmed AP
{
if( skill->value2[j] > 0 )
Extra += attack * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
else // some kind of weapon equipped
{
if( skill->weapon[n] == weapontype || skill->buff[j] == 18)
{
int xt1 = 0;
int xt2 = 0;
if(skill->buff[j] == skilltype)
{
xt1 = skill->value1[j];
xt2 = attack * skill->value2[j] / 100;
if(xt1 > xt2)
Extra = xt1;
else
Extra = xt2;
//Extra += attack * skill->value2[j] / 100;
if(Session->codedebug)
{
Log( MSG_INFO, "Extra AP from passive %i",Extra );
}
}
}
}
}
}
}
attack += Extra;
if(Session->codedebug)
{
Log( MSG_INFO, "AP final value before fairy and buff check is %i",attack );
}
if(Fairy)attack = (unsigned int)floor(attack*1.2);
if(Status->Attack_up!=0xff)
attack += MagicStatus[Status->Attack_up].Value;
if(Status->Attack_down!=0xff)
attack -= MagicStatus[Status->Attack_down].Value;
//if(attack<30)
// attack = 30;
return attack;
}
// Return Defense
unsigned int CPlayer::GetDefense( )
{
UINT defense = 0;
UINT Extra = 0;
switch( CharInfo->Job )
{
case 121:case 122:
case 221:case 222:
case 321:case 322:
case 421:case 422:
Extra += 25;
break;
default:
break;
}
defense += (UINT)floor( (( Attr->Estr + Attr->Str + 5) * 0.35) + ((Stats->Level + 15) * 0.7) );
UINT extra_refine[10] = {0, 6, 12, 18, 27, 36, 45, 57, 70 , 85};
for(UINT i=1;i<9;i++)
{
if(i==7)
continue;
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
defense += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->defense;
if(items[i].refine>0)
{
UINT refine = (UINT)floor((double)(items[i].refine/16));
if(refine<10)
{
defense += (UINT)floor(extra_refine[refine] * 0.01 * GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->defense);
}
}
}
}
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_DEFENSE)
{
defense += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_DEFENSE)
{
defense += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats < 500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_DEFENSE)
defense += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_DEFENSE)
defense += GServer->StatsList[items[i].stats].value[1];
}
}
}
// Additional def due to pskills
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0) continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sDefense || skill->buff[j] == sDefense2 )
{
if( skill->value2[j] > 0 )
Extra += defense * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
//Shield specific def boosts. previously not included.
for(int n=0;n<5;n++)
{
if( skill->weapon[n] == items[8].type && items[8].count > 0) // item defined in the skill is currently equipped in the shield slot
{
if( skill->value2[j] > 0 )
Extra += defense * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
// this is BS sShield = 35 and that is "Shield Damage" not defense
//if (items[8].count > 0 && skill->buff[j] == sShield)
//{
// if( skill->value2[j] > 0 )
// Extra += defense * skill->value2[j] / 100;
// if( skill->value1[j] > 0 )
// Extra += skill->value1[j];
//}
}
}
defense += Extra;
if(Fairy) defense = (unsigned int)floor(defense*1.2);
if(Status->Defense_up!=0xff)
defense += MagicStatus[Status->Defense_up].Value;
if(Status->Defense_down!=0xff)
defense -= MagicStatus[Status->Defense_down].Value;
return defense;
}
// Return Attack Speed
unsigned int CPlayer::GetAttackSpeed( )
{
UINT aspeed = 0;
if( items[7].itemnum!=0 && items[7].count > 0 )
{
UINT wpnspd = 0;
wpnspd = GServer->EquipList[WEAPON].Index[items[7].itemnum]->attackspeed;
switch(wpnspd)
{
case 12: //normal
aspeed = 88;
break;
case 11: //+1
aspeed = 93;
break;
case 10: //+2
aspeed = 100;
break;
case 9: //+3
aspeed = 107;
break;
case 8: //+4
aspeed = 115;
break;
case 7: //+5
aspeed = 125;
break;
case 6: //+6
aspeed = 136;
break;
default:
break;
}
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Weapon speed %i. Attack speed so far %i",wpnspd,aspeed);
}
}
else
{
aspeed = 115;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Attack speed with no weapon %i",aspeed);
}
}
UINT weapontype = 0;
UINT skilltype = 0;
weapontype = GServer->EquipList[WEAPON].Index[items[7].itemnum]->type;
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
bool GotWeapon = false; //do I have one of the listed weapons?
bool GotRightWeapon = false; //Do i have the right one though?
if( skill->weapon[0] == 0)
{
GotWeapon = true;
}
else
{
for(int n=0;n<5;n++)
{
if( skill->weapon[n] != 0 && skill->weapon[n] == weapontype) // item defined in the skill
{
GotWeapon = true;
}
}
}
if(GotWeapon) //No point checking if we have the RIGHT weapon when we don't have any of them
{
for(UINT j = 0; j < 2; j++ )
{
GotRightWeapon = false;
switch(skill->buff[j])
{
case 24: //attackspeed
GotRightWeapon = true; //true for all weapons listed
break;
case 49: //bow speed
if(weapontype == 231 || weapontype == 271)
GotRightWeapon = true; //true if we have a bow or crossbow
break;
case 50: //gun speed
if(weapontype == 232 || weapontype == 253)
GotRightWeapon = true; //true if we have a gun or dual guns
break;
case 51: //combat weapon speed
if(weapontype == 251 || weapontype == 252)
GotRightWeapon = true; //true if we have a katar or dual swords
break;
case 118: //one hand sword attack speed
if(weapontype == 211)
GotRightWeapon = true; //true if we have a one hand sword
break;
case 119: //one hand melee weapon attack speed
if(weapontype == 212)
GotRightWeapon = true; //true if we have a one hand melee weapon
break;
case 120: //two hand sword attack speed
if(weapontype == 221)
GotRightWeapon = true; //true if we have a two hand sword
break;
case 121: //spear attack speed
if(weapontype == 222)
GotRightWeapon = true; //true if we have a spear
break;
case 122: //two hand axe attack speed
if(weapontype == 223)
GotRightWeapon = true; //true if we have an axe
break;
default:
break;
}
if(GotRightWeapon)
{
if( skill->value2[j] > 0 )
Extra += aspeed * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Attack speed %i added for weapon type %i. Skill ID %i",Extra,weapontype,skill->id);
}
}
}
}
}
aspeed += Extra;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Attack speed after passives %i",aspeed);
}
//active buffs
if(Status->Haste_up!=0xff)
aspeed += MagicStatus[Status->Haste_up].Value;
if(Status->Haste_down!=0xff)
aspeed -= MagicStatus[Status->Haste_down].Value;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Attack speed after buffs %i",aspeed);
}
//cloth stats
for(UINT i=1;i<12;i++)
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_HASTE)
{
aspeed += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_HASTE)
{
aspeed += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
//don't need gems. Covered by the stats section
if(items[i].stats>0 && items[i].stats < 500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_HASTE)
aspeed += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_HASTE)
aspeed += GServer->StatsList[items[i].stats].value[1];
}
}
}
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Attack speed after cloth stats and gems %i",aspeed);
}
return aspeed;
}
// Return Movement Speed
unsigned int CPlayer::GetMoveSpeed( )
{
UINT mspeed = 425;
if(!Status->CanRun)
Status->Stance = WALKING;
//mspeed += UINT((Attr->Dex)*0.85);
switch(Status->Stance)
{
case WALKING: //walking
mspeed = 200;
break;
case 1:
case RUNNING: // running
{
if( items[6].count != 0 )//Foot
{
UINT tspeed = GServer->EquipList[SHOE].Index[items[6].itemnum]->movespeed;
mspeed += ( tspeed - 65 ) * 5;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed with shoes on %i",mspeed);
}
}
for(UINT i=0;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if(items[i].itemtype > 9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == MOVE_SPEED)
{
mspeed += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == MOVE_SPEED)
{
mspeed += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed %i after equipment stats for item in slot %i",mspeed,i);
}
}
if(items[i].stats > 0 && items[i].stats < 500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_DASH)
{
mspeed += GServer->StatsList[items[i].stats].value[0];
}
if(GServer->StatsList[items[i].stats].stat[1] == A_DASH)
{
mspeed += GServer->StatsList[items[i].stats].value[1];
}
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed %i after adding extra/gem stats for item in slot %i",mspeed,i);
}
}
}
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed %i after adding all equipped items",mspeed);
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0) continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMoveSpeed || skill->buff[j] == sMoveSpeed2 )
{
if( skill->value2[j] > 0 )
Extra += mspeed * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
mspeed += Extra;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed %i after adding passive skills",mspeed);
}
Stats->Mspd_base = mspeed;
if(Fairy)
{
mspeed += 110;
if(Session->codedebug) //Debug code
{
Log( MSG_INFO, "Fairy detected. move speed + 110 %i", mspeed);
}
}
if(Status->Dash_up!=0xff)
{
mspeed += MagicStatus[Status->Dash_up].Value;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Speed buff detected. amount: %i new move speed: %i",MagicStatus[Status->Dash_up].Value, mspeed);
}
}
if(Status->Dash_down!=0xff)
{
mspeed -= MagicStatus[Status->Dash_down].Value;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Speed DE-buff detected. amount: %i new move speed: %i",MagicStatus[Status->Dash_down].Value, mspeed);
}
}
}
break;
case DRIVING: //cart or gear
{
//Log(MSG_INFO, "player is driving");
float m_speed = 0;
int patType = GServer->PatList.Index[items[135].itemnum]->type;
//if(this->items[135].itemnum > 30 && this->items[135].itemnum < 40 ) //Castle gear body
if(patType == 512) //Castle gear body
{
m_speed = 1000;
float mod1 = (float)GServer->PatList.Index[items[136].itemnum]->speed;
mod1 /= 100; //engine
float mod2 = (float)GServer->PatList.Index[items[137].itemnum]->speed;
mod2 /= 100; // legs
m_speed *= mod1;
m_speed *= mod2;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed %i riding a Castle Gear",m_speed);
}
}
else if(patType == 511) //Cart body
{
m_speed = 1000;
float mod1 = (float)GServer->PatList.Index[items[136].itemnum]->speed;
mod1 /= 100; //engine
float mod2 = (float)GServer->PatList.Index[items[137].itemnum]->speed;
mod2 /= 100; //wheels
m_speed *= mod1;
m_speed *= mod2;
// Many accessory items give a speed boost too. Added in after the modifiers
if(GServer->PatList.Index[items[138].itemnum]->condition[0] == 23) // accessory
m_speed += (float)GServer->PatList.Index[items[138].itemnum]->modifier[0];
if(GServer->PatList.Index[items[138].itemnum]->condition[1] == 23) // accessory
m_speed += (float)GServer->PatList.Index[items[138].itemnum]->modifier[1];
// some frames give a speed boost too. Added in after the modifiers
if(GServer->PatList.Index[items[135].itemnum]->condition[0] == 23) // frame
m_speed += (float)GServer->PatList.Index[items[135].itemnum]->modifier[0];
if(GServer->PatList.Index[items[135].itemnum]->condition[1] == 23) // frame
m_speed += (float)GServer->PatList.Index[items[135].itemnum]->modifier[1];
// some engines give a speed boost too. Added in after the modifiers
if(GServer->PatList.Index[items[136].itemnum]->condition[0] == 23) // engine
m_speed += (float)GServer->PatList.Index[items[135].itemnum]->modifier[0];
if(GServer->PatList.Index[items[136].itemnum]->condition[1] == 23) // engine
m_speed += (float)GServer->PatList.Index[items[135].itemnum]->modifier[1];
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Move speed %f riding a Cart",m_speed);
}
}
else
{
Log(MSG_ERROR,"What the heck is this character driving? it is type %i", patType);
}
mspeed = (int)floor(m_speed);
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Final Speed before fairy buffs added: %i", mspeed);
}
Stats->Mspd_base = mspeed;
if(Fairy)
{
//mspeed = (unsigned int)floor(mspeed * 1.2);
mspeed += 110;
if(Session->codedebug) //Debug code
{
GServer->SendPM(this, "Fairy detected. move speed * 1.2 %i", mspeed);
}
}
}
break;
default:
break;
}
return mspeed;
}
// Return Max HP
unsigned int CPlayer::GetMaxHP( )
{
if (Stats->Level<1) Stats->Level=1;
//unsigned int hpmax = (unsigned int)floor(((sqrt(Stats->Level + 20) * (Stats->Level + 5 )) * 3.5) + ((Attr->Str + Attr->Estr) << 1));
//unsigned int hpmax1 = (unsigned int)floor((0.1555 * Stats->Level * Stats->Level) + (13.812 * Stats->Level) + 45 + ((Attr->Str + Attr->Estr) * 2));
// Base stats for Visitor
float multi = 2.36;
int add1 = 26;
int add2 = 4;
// Now change them based on class
switch (CharInfo->Job) {
case jSoldier:
multi = 3.5;
add1 = 20;
add2 = 5;
break;
case jKnight:
multi = 3.5;
add1 = 28;
add2 = 5;
break;
case jChampion:
multi = 3.5;
add1 = 22;
add2 = 5;
break;
case jMuse:
multi = 2.36;
add1 = 26;
add2 = 4;
break;
case jMage:
multi = 2.37;
add1 = 26;
add2 = 5;
break;
case jCleric:
multi = 2.4;
add1 = 26;
add2 = 7;
break;
case jHawker:
multi = 2.7;
add1 = 20;
add2 = 5;
break;
case jRaider:
multi = 3.0;
add1 = 23;
add2 = 5;
break;
case jScout:
multi = 2.7;
add1 = 21;
add2 = 5;
break;
case jDealer:
case jBourgeois:
case jArtisan:
multi = 2.7;
add1 = 20;
add2 = 5;
break;
default:
break;
}
// Max HP calc from client
UINT Extra = 0;
float ModLevel = add1 + Stats->Level;
UINT hpmax = (UINT)floor((( sqrt(ModLevel) * (add2 + Stats->Level) ) * multi) + ((Attr->Str + Attr->Estr) << 1) );
// Stat boost for second jobs
switch( CharInfo->Job )
{
case 121:case 122:
case 221:case 222:
case 321:case 322:
case 421:case 422:
Extra += 300;
break;
default:
break;
}
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_MAX_HP || GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_HP )
{
hpmax += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_MAX_HP || GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_HP )
{
hpmax += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_MAX_HP || GServer->StatsList[items[i].stats].stat[0] == A_HP)
hpmax += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_MAX_HP || GServer->StatsList[items[i].stats].stat[0] == A_HP)
hpmax += GServer->StatsList[items[i].stats].value[1];
}
}
}
// Additional hp due to pskills
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMaxHP || skill->buff[j] == sMaxHP2 )
{
if( skill->value2[j] > 0 )
Extra += hpmax * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
hpmax += Extra;
if(Fairy) hpmax = (unsigned int)floor(hpmax*1.2);
if(Status->HP_up!=0xff)
hpmax += MagicStatus[Status->HP_up].Value;
if(Status->HP_down!=0xff)
hpmax -= MagicStatus[Status->HP_down].Value;
return hpmax;
}
// Return Max MP [fixed by Tomiz] TODO: add cloth stat
unsigned int CPlayer::GetMaxMP( )
{
if( Stats->Level < 0 )
Stats->Level = 1;
UINT maxmp = 0;
float Mult = 0;
int JobValue = (int)CharInfo->Job;
switch(JobValue)
{
case 111:
case 411:
case 421:
Mult = 4;
JobValue = 3;
break;
case 122:
Mult = 5;
JobValue = -6;
break;
case 211:
Mult = 6;
JobValue = 0;
break;
case 221:
Mult = 7;
JobValue = -7;
break;
case 222:
Mult = 6.5;
JobValue = -4;
break;
case 311:
case 321:
Mult = 4;
JobValue = 4; //LMA
break;
case 121:
case 322:
case 422:
Mult = 4.5;
JobValue = 0;
break;
default:
Mult = 3;
JobValue = 4;
break;
}
maxmp = (UINT)floor((Stats->Level + JobValue) * Mult + ((Attr->Int + Attr->Eint) << 2));
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_MAX_MP || GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_MP )
{
maxmp += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_MAX_MP || GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_MP )
{
maxmp += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_MAX_MP || GServer->StatsList[items[i].stats].stat[0] == A_MP)
maxmp += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_MAX_MP || GServer->StatsList[items[i].stats].stat[0] == A_MP)
maxmp += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMaxMP || skill->buff[j] == sMaxMP2 )
{
if( skill->value2[j] > 0 )
Extra += maxmp * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
maxmp += Extra;
if(Fairy) maxmp = (unsigned int)floor(maxmp*1.2);
if(Status->MP_up!=0xff)
maxmp += MagicStatus[Status->MP_up].Value;
if(Status->MP_down!=0xff)
maxmp -= MagicStatus[Status->MP_down].Value;
return maxmp;
}
// Get HP Regeneration Amount
unsigned int CPlayer::GetHPRegenAmount( )
{
UINT amount = (UINT)ceil ( Stats->MaxHP * 0.02 );
if( Status->Stance == 1 )
amount *= 4;
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_HP_REC_RATE)
{
amount += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_HP_REC_RATE)
{
amount += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_HP_REC_RATE )
amount += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_HP_REC_RATE )
amount += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sHPRate || skill->buff[j] == sHPRecovery ) // Not sure on sHPRate
{
if( skill->value2[j] > 0 )
Extra += amount * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
amount += Extra;
return amount;
}
// Get MP Regeneration Amount
unsigned int CPlayer::GetMPRegenAmount( )
{
UINT amount = (UINT)ceil ( Stats->MaxMP * 0.02 );
if( Status->Stance == 1 )
amount *= 4;
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0)
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_MP_REC_RATE)
{
amount += amount * GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1] / 100;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_MP_REC_RATE)
{
amount += amount * GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1] / 100;
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_MP_REC_RATE )
amount += amount * GServer->StatsList[items[i].stats].value[0] / 100;
if(GServer->StatsList[items[i].stats].stat[1] == A_MP_REC_RATE )
amount += amount * GServer->StatsList[items[i].stats].value[1] / 100;
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMPRate || skill->buff[j] == sMPRecovery )
{
if( skill->value2[j] > 0 )
Extra += amount * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
amount += Extra;
return amount;
}
// max weight supported
unsigned int CPlayer::GetMaxWeight( )
{
UINT weight = 0;
//weight = ((Attr->Str + Attr->Estr) + (Attr->Str + Attr->Estr)*2) * 2 + Stats->Level+220 + (Stats->Level+220)*4;
weight = ((Attr->Str + Attr->Estr)*6)+((Stats->Level+220)*5);
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == A_INVENTORY_CAPACITY)
{
weight += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == A_INVENTORY_CAPACITY)
{
weight += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == A_INVENTORY_CAPACITY )
weight += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == A_INVENTORY_CAPACITY )
weight += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMaxWeight || skill->buff[j] == sMaxWeight2 )
{
if( skill->value2[j] > 0 )
Extra += weight * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
weight += Extra;
return weight;
}
// Current weight
unsigned int CPlayer::GetCurrentWeight( )
{
UINT weight = 0;
for(UINT i=0;i<MAX_INVENTORY;i++)
{
if(items[i].itemtype < 10 && items[i].itemtype > 0)
{
weight += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->weight;
}
else
{
switch(items[i].itemtype)
{
case CONSUMIBLE:
weight += GServer->UseList.Index[items[i].itemnum]->weight*items[i].count;
break;
case JEM:
weight += GServer->JemList.Index[items[i].itemnum]->weight*items[i].count;
break;
case NATURAL:
weight += GServer->NaturalList.Index[items[i].itemnum]->weight*items[i].count;
break;
case PAT:
weight += GServer->PatList.Index[items[i].itemnum]->weight;
break;
default:
break;
}
}
}
return weight;
}
// MP Reduction
unsigned int CPlayer::GetMPReduction( )
{
UINT mpreduction = 0;
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if(items[i].count>0)
{
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == MP_COST_RED)
{
mpreduction += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == MP_COST_RED)
{
mpreduction += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == MP_COST_RED )
mpreduction += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == MP_COST_RED )
mpreduction += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sMPSpendDecrease )
{
if( skill->value2[j] > 0 )
Extra += mpreduction * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
mpreduction += Extra;
return mpreduction;
}
// Max summon capacity
unsigned int CPlayer::GetMaxSummonGauge( )
{
UINT gauge = 50;
for(UINT i=1;i<12;i++)//cloth stats [from tomiz]
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if(items[i].count>0)
{
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == SUMMON_GAUGE)
{
gauge += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == SUMMON_GAUGE)
{
gauge += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
}
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == MP_COST_RED )
gauge += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == MP_COST_RED )
gauge += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sExpandSummonGauge )
{
if( skill->value2[j] > 0 )
Extra += gauge * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
gauge += Extra;
return gauge;
}
// Extra attributes [str/dex/con/cha/sen/int]
void CPlayer::GetExtraStats( )
{
Attr->Estr = 0;
Attr->Edex = 0;
Attr->Eint = 0;
Attr->Econ = 0;
Attr->Esen = 0;
Attr->Echa = 0;
for(UINT i=1;i<12;i++)//cloth stats
{
if( items[i].count > 0 )
{
UINT Stat1 = GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0];
UINT Stat2 = GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0];
switch(Stat1)
{
case A_STR: Attr->Estr += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1]; break;
case A_DEX: Attr->Edex += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1]; break;
case A_INT: Attr->Eint += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1]; break;
case A_CON: Attr->Econ += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1]; break;
case A_CHA: Attr->Echa += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1]; break;
case A_SEN: Attr->Esen += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1]; break;
default:
break;
}
switch(Stat2)
{
case A_STR: Attr->Estr += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1]; break;
case A_DEX: Attr->Edex += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1]; break;
case A_INT: Attr->Eint += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1]; break;
case A_CON: Attr->Econ += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1]; break;
case A_CHA: Attr->Echa += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1]; break;
case A_SEN: Attr->Esen += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1]; break;
default:
break;
}
// Why are we doing jems and stats seperately? they are the same thing O.o
/*if(items[i].gem != 0) // jem stats
{
//somehow a player had a negative value in his gem on an item. Put this code in to patch it.
if(items[i].gem < 0 || items[i].stats < 0)
{
items[i].gem = 0;
items[i].stats = 0;
}
UINT Stat1 = GServer->JemList.Index[items[i].gem]!=NULL?GServer->JemList.Index[items[i].gem]->stat1[0]:0;
UINT Stat2 = GServer->JemList.Index[items[i].gem]!=NULL?GServer->JemList.Index[items[i].gem]->stat2[0]:0;
switch(Stat1)
{
case STRENGTH: Attr->Estr += GServer->JemList.Index[items[i].gem]->stat1[1]; break;
case DEXTERY: Attr->Edex += GServer->JemList.Index[items[i].gem]->stat1[1]; break;
case INTELIGENCE: Attr->Eint += GServer->JemList.Index[items[i].gem]->stat1[1]; break;
case CONCENTRATION: Attr->Econ += GServer->JemList.Index[items[i].gem]->stat1[1]; break;
case CHARM: Attr->Echa += GServer->JemList.Index[items[i].gem]->stat1[1]; break;
case SENSE: Attr->Esen += GServer->JemList.Index[items[i].gem]->stat1[1]; break;
}
switch(Stat2)
{
case STRENGTH: Attr->Estr += GServer->JemList.Index[items[i].gem]->stat2[1]; break;
case DEXTERY: Attr->Edex += GServer->JemList.Index[items[i].gem]->stat2[1]; break;
case INTELIGENCE: Attr->Eint += GServer->JemList.Index[items[i].gem]->stat2[1]; break;
case CONCENTRATION: Attr->Econ += GServer->JemList.Index[items[i].gem]->stat2[1]; break;
case CHARM: Attr->Echa += GServer->JemList.Index[items[i].gem]->stat2[1]; break;
case SENSE: Attr->Esen += GServer->JemList.Index[items[i].gem]->stat2[1]; break;
}
} */
if(items[i].stats != 0 && items[i].stats < 500) // this should cover all the gems too
{
Stat1 = GServer->StatsList[items[i].stats].stat[0];
Stat2 = GServer->StatsList[items[i].stats].stat[1];
switch(Stat1)
{
case STRENGTH: Attr->Estr += GServer->StatsList[items[i].stats].value[0]; break;
case DEXTERY: Attr->Edex += GServer->StatsList[items[i].stats].value[0]; break;
case INTELIGENCE: Attr->Eint += GServer->StatsList[items[i].stats].value[0]; break;
case CONCENTRATION: Attr->Econ += GServer->StatsList[items[i].stats].value[0]; break;
case CHARM: Attr->Echa += GServer->StatsList[items[i].stats].value[0]; break;
case SENSE: Attr->Esen += GServer->StatsList[items[i].stats].value[0]; break;
default:
break;
}
switch(Stat2)
{
case STRENGTH: Attr->Estr += GServer->StatsList[items[i].stats].value[1]; break;
case DEXTERY: Attr->Edex += GServer->StatsList[items[i].stats].value[1]; break;
case INTELIGENCE: Attr->Eint += GServer->StatsList[items[i].stats].value[1]; break;
case CONCENTRATION: Attr->Econ += GServer->StatsList[items[i].stats].value[1]; break;
case CHARM: Attr->Echa += GServer->StatsList[items[i].stats].value[1]; break;
case SENSE: Attr->Esen += GServer->StatsList[items[i].stats].value[1]; break;
default:
break;
}
}
}
}
}
float CPlayer::GetAttackDistance( )
{
if(items[7].count==0) return (float)1;
float AttackDistance = 0;
AttackDistance = GServer->EquipList[WEAPON].Index[items[7].itemnum]->attackdistance/100;
return AttackDistance;
}
// Return XPRate
unsigned int CPlayer::GetXPRate( )
{
UINT XPRate = 0;
if(Stats->ItemXPRate == -1)
return 0; // sends back a rate of 0. Used for exp nulification
for(UINT i=1;i<12;i++)
{
if( items[i].count != 0 )
{
if(items[i].itemtype>9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == XP_RATE)
XPRate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == XP_RATE)
XPRate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
if(items[i].stats>0 && items[i].stats<500)
{
if(GServer->StatsList[items[i].stats].stat[0] == XP_RATE)
XPRate += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == XP_RATE)
XPRate += GServer->StatsList[items[i].stats].value[1];
}
}
}
if(Stats->ItemXPRate != 0 && Stats->ItemXPRate != 1 && Stats->ItemXPRate != 2)
Stats->ItemXPRate = 0;
XPRate += Stats->ItemXPRate; // add timed XPRate buffs
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == sEXPRate )
{
if( skill->value2[j] > 0 )
Extra += XPRate * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
CMap* map = GServer->MapList.Index[Position->Map];
XPRate += Extra;
if(XPRate < 1)
XPRate = 1;
XPRate = XPRate * map->mapXPRate;
//Log( MSG_INFO, "XP rate calculated as = %i", XPRate);
Log( MSG_INFO, "XPRate: %i Map XP rate: %i for map %i",XPRate,map->mapXPRate, map->id);
return XPRate;
}
// Return Item Drop Rate
unsigned int CPlayer::GetItemDropRate( )
{
int itemdroprate = 0;
for(UINT i=1;i<12;i++)
{
if( items[i].count != 0 )
{
if(items[i].itemtype > 9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == 79 ) //ITEM_DROP_RATE
itemdroprate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == 79 ) //ITEM_DROP_RATE
itemdroprate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
if(items[i].stats > 0 && items[i].stats < 500)
{
if(GServer->StatsList[items[i].stats].stat[0] == 79 ) //ITEM_DROP_RATE
itemdroprate += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == 79 ) //ITEM_DROP_RATE
itemdroprate += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == 79 ) //sItemDropIncrease
{
if( skill->value2[j] > 0 )
Extra += itemdroprate * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
itemdroprate += Extra;
//Log( MSG_INFO, "item drop rate calculated as = %i", itemdroprate);
if(itemdroprate < 0)
itemdroprate = 0;
//itemdroprate += GServer->Config.DROP_RATE;
//Log( MSG_INFO, "item drop rate calculated as = %i", itemdroprate);
//Log( MSG_INFO, "Server item drop rate = %i", GServer->Config.DROP_RATE);
return itemdroprate;
}
// Return Item Drop count increase
unsigned int CPlayer::GetItemDropCountRate( )
{
int itemdroprate = 0;
for(UINT i=1;i<12;i++)
{
if( items[i].count != 0 )
{
if(items[i].itemtype > 9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == 63 ) //ITEM_DROP_Count RATE
itemdroprate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == 63 ) //ITEM_DROP_Coiunt RATE
itemdroprate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
if(items[i].stats > 0 && items[i].stats < 500)
{
if(GServer->StatsList[items[i].stats].stat[0] == 63 ) //ITEM_DROP_Count RATE
itemdroprate += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == 63 ) //ITEM_DROP_Count RATE
itemdroprate += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == 63 ) //Item drop Count rate
{
if( skill->value2[j] > 0 )
Extra += itemdroprate * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
itemdroprate += Extra;
//Log( MSG_INFO, "item drop rate calculated as = %i", itemdroprate);
if(itemdroprate < 0)
itemdroprate = 0;
//itemdroprate += GServer->Config.DROP_RATE;
//Log( MSG_INFO, "item drop rate calculated as = %i", itemdroprate);
//Log( MSG_INFO, "Server item drop rate = %i", GServer->Config.DROP_RATE);
return itemdroprate;
}
// Return Zuly Drop Rate
unsigned int CPlayer::GetZulyDropRate( )
{
int zulydroprate = 1;
for(UINT i=1;i<12;i++)
{
if( items[i].count != 0 )
{
if(items[i].itemtype > 9)
{
Log(MSG_WARNING, "Char %s have equip invalid item: %i,%i", CharInfo->charname, items[i].itemtype, items[i].itemnum );
continue;
}
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[0] == 64 ) //ZULY_DROP_RATE
zulydroprate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat1[1];
if( GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[0] == 64 ) //ZULY_DROP_RATE
zulydroprate += GServer->EquipList[items[i].itemtype].Index[items[i].itemnum]->stat2[1];
if(items[i].stats > 0 && items[i].stats < 500)
{
if(GServer->StatsList[items[i].stats].stat[0] == 64 ) //ZULY_DROP_RATE
zulydroprate += GServer->StatsList[items[i].stats].value[0];
if(GServer->StatsList[items[i].stats].stat[1] == 64 ) //ZULY_DROP_RATE
zulydroprate += GServer->StatsList[items[i].stats].value[1];
}
}
}
UINT Extra = 0;
for(UINT i=0;i<30;i++)
{
if (pskill[i] == 0)
continue;
CSkills* skill = GServer->GetSkillByID( (pskill[i])+(pskilllvl[i]));
if( skill == NULL )
continue;
for(UINT j = 0; j < 2; j++ )
{
if( skill->buff[j] == 64 ) //sItemZulyIncrease
{
if( skill->value2[j] > 0 )
Extra += zulydroprate * skill->value2[j] / 100;
if( skill->value1[j] > 0 )
Extra += skill->value1[j];
}
}
}
zulydroprate += Extra;
if(zulydroprate < 1)
zulydroprate = 1;
//Log( MSG_INFO, "zuly drop rate calculated as = %i", zulydroprate);
return zulydroprate;
}
// calculate player stats
void CPlayer::SetStats( )
{
GetExtraStats( );
Stats->MaxHP = GetMaxHP( );
Stats->MaxMP = GetMaxMP( );
Stats->Attack_Power = GetAttackPower( );
Stats->Defense = GetDefense( );
Stats->Critical = GetCritical( );
Stats->Move_Speed = GetMoveSpeed( );
//Stats->Mspd_base = GetMoveSpeed(1);
Stats->Magic_Defense = GetMagicDefense( );
Stats->magicattack = GetMagicAttack( );
Stats->Accury = GetAccury( );
Stats->Dodge = GetDodge( );
Stats->Attack_Speed = GetAttackSpeed( );
Stats->Attack_Distance = GetAttackDistance( );
Stats->MaxWeight = GetMaxWeight( );
Stats->MaxSummonGauge = GetMaxSummonGauge( );
Stats->MPReduction = GetMPReduction( );
Stats->xprate = GetXPRate( );
Stats->itemdroprate = GetItemDropRate( );
Stats->itemdropcountrate = GetItemDropCountRate( );
Stats->zulydroprate = GetZulyDropRate( );
}