[CODE title="battle.cpp"]#include "stdafx.h"
#include "utils.h"
#include "config.h"
#include "desc.h"
#include "char.h"
#include "char_manager.h"
#include "battle.h"
#include "item.h"
#include "item_manager.h"
#include "mob_manager.h"
#include "vector.h"
#include "packet.h"
#include "pvp.h"
#include "profiler.h"
#include "guild.h"
#include "affect.h"
#include "unique_item.h"
#include "lua_incl.h"
#include "arena.h"
#include "castle.h"
#include "sectree.h"
#include "ani.h"
#include "locale_service.h"
#include "../../common/service.h"
int battle_hit(LPCHARACTER ch, LPCHARACTER victim, int & iRetDam);
bool battle_distance_valid_by_xy(long x, long y, long tx, long ty)
{
long distance = DISTANCE_APPROX(x - tx, y - ty);
if (distance > 170)
return false;
return true;
}
bool battle_distance_valid(LPCHARACTER ch, LPCHARACTER victim)
{
return battle_distance_valid_by_xy(ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY());
}
bool timed_event_cancel(LPCHARACTER ch)
{
if (ch->m_pkTimedEvent)
{
event_cancel(&ch->m_pkTimedEvent);
return true;
}
/* RECALL_DELAY
차후 전투로 인해 귀환부 딜레이가 취소 되어야 할 경우 주석 해제
if (ch->m_pk_RecallEvent)
{
event_cancel(&ch->m_pkRecallEvent);
return true;
}
END_OF_RECALL_DELAY */
return false;
}
bool battle_is_attackable(LPCHARACTER ch, LPCHARACTER victim)
{
// 상대방이 죽었으면 중단한다.
if (victim->IsDead())
return false;
// 안전지대면 중단
{
SECTREE *sectree = NULL;
sectree = ch->GetSectree();
if (sectree && sectree->IsAttr(ch->GetX(), ch->GetY(), ATTR_BANPK))
return false;
sectree = victim->GetSectree();
if (sectree && sectree->IsAttr(victim->GetX(), victim->GetY(), ATTR_BANPK))
return false;
}
// 내가 죽었으면 중단한다.
if (ch->IsStun() || ch->IsDead())
return false;
if (ch->IsPC() && victim->IsPC())
{
CGuild* g1 = ch->GetGuild();
CGuild* g2 = victim->GetGuild();
if (g1 && g2)
{
if (g1->UnderWar(g2->GetID()))
return true;
}
}
if (IS_CASTLE_MAP(ch->GetMapIndex()) && false==castle_can_attack(ch, victim))
return false;
if (CArenaManager::instance().CanAttack(ch, victim) == true)
return true;
return CPVPManager::instance().CanAttack(ch, victim);
}
int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
{
if (test_server&&ch->IsPC())
sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
if (!victim || ch == victim)
return BATTLE_NONE;
if (test_server&&ch->IsPC())
sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
if (!battle_is_attackable(ch, victim))
return BATTLE_NONE;
if (test_server&&ch->IsPC())
sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
// 거리 체크
int distance = DISTANCE_APPROX(ch->GetX() - victim->GetX(), ch->GetY() - victim->GetY());
if (!victim->IsBuilding())
{
int max = 300;
if (false == ch->IsPC())
{
// 몬스터의 경우 몬스터 공격 거리를 사용
max = (int) (ch->GetMobAttackRange() * 1.15f);
}
else
{
// PC일 경우 상대가 melee 몹일 경우 몹의 공격 거리가 최대 공격 거리
if (false == victim->IsPC() && BATTLE_TYPE_MELEE == victim->GetMobBattleType())
max = MAX(300, (int) (victim->GetMobAttackRange() * 1.15f));
}
if (distance > max)
{
if (test_server)
sys_log(0, "VICTIM_FAR: %s distance: %d max: %d", ch->GetName(), distance, max);
return BATTLE_NONE;
}
}
if (timed_event_cancel(ch))
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("전투가 시작 되어 취소 되었습니다."));
if (timed_event_cancel(victim))
victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("전투가 시작 되어 취소 되었습니다."));
ch->SetPosition(POS_FIGHTING);
ch->SetVictim(victim);
const PIXEL_POSITION & vpos = victim->GetXYZ();
ch->SetRotationToXY(vpos.x, vpos.y);
int dam;
int ret = battle_hit(ch, victim, dam);
return (ret);
}
void battle_end_ex(LPCHARACTER ch)
{
if (ch->IsPosition(POS_FIGHTING))
ch->SetPosition(POS_STANDING);
}
void battle_end(LPCHARACTER ch)
{
battle_end_ex(ch);
}
int CalcBattleDamage(int iDam, int iAttackerLev, int iVictimLev)
{
if (iDam < 3)
iDam = number(1, 5);
return iDam;
}
int CalcMagicDamageWithValue(int iDam, LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
return CalcBattleDamage(iDam, pkAttacker->GetLevel(), pkVictim->GetLevel());
}
int CalcMagicDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
int iDam = 0;
if (pkAttacker->IsNPC())
{
iDam = CalcMeleeDamage(pkAttacker, pkVictim, false, false);
}
iDam += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
return CalcMagicDamageWithValue(iDam, pkAttacker, pkVictim);
}
float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreTargetRating)
{
int iARSrc;
int iERSrc;
if (LC_IsYMIR()) // 천마
{
iARSrc = MIN(90, pkAttacker->GetPolymorphPoint(POINT_DX));
iERSrc = MIN(90, pkVictim->GetPolymorphPoint(POINT_DX));
}
else
{
int attacker_dx = pkAttacker->GetPolymorphPoint(POINT_DX);
int attacker_lv = pkAttacker->GetLevel();
int victim_dx = pkVictim->GetPolymorphPoint(POINT_DX);
int victim_lv = pkAttacker->GetLevel();
iARSrc = MIN(90, (attacker_dx * 4 + attacker_lv * 2) / 6);
iERSrc = MIN(90, (victim_dx * 4 + victim_lv * 2) / 6);
}
float fAR = ((float) iARSrc + 210.0f) / 300.0f; // fAR = 0.7 ~ 1.0
if (bIgnoreTargetRating)
return fAR;
float fER = ((float) (iERSrc * 2 + 5) / (iERSrc + 95)) * 3.0f / 10.0f;
return fAR - fER;
}
int CalcAttBonus(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int iAtk)
{
if (!pkVictim->IsPC())
iAtk += pkAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_ATTACK_BONUS);
if (!pkAttacker->IsPC())
{
int iReduceDamagePct = pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_TRANSFER_DAMAGE);
iAtk = iAtk * (100 + iReduceDamagePct) / 100;
}
if (pkAttacker->IsNPC() && pkVictim->IsPC())
{
iAtk = (iAtk * CHARACTER_MANAGER::instance().GetMobDamageRate(pkAttacker)) / 100;
}
if (pkVictim->IsNPC())
{
if (pkVictim->IsRaceFlag(RACE_FLAG_ANIMAL))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ANIMAL)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_BOSS))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_PATRON)) / 100;
else if (pkVictim->IsStone())
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_METINN) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_UNDEAD))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_UNDEAD)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_DEVIL))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DEVIL)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_HUMAN))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_ORC))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ORC)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_MILGYO))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MILGYO)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_INSECT))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_INSECT)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_FIRE))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_FIRE)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_ICE))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ICE)) / 100;
#ifdef ELEMENT_NEW_BONUSES
else if (pkVictim->IsRaceFlag(RACE_FLAG_ELEC))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ELEC)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_WIND))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_WIND)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_EARTH))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_EARTH)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_DARK))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DARK)) / 100;
#endif
else if (pkVictim->IsRaceFlag(RACE_FLAG_DESERT))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DESERT)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_TREE))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_TREE)) / 100;
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MONSTER)) / 100;
}
else if (pkVictim->IsPC())
{
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100;
switch (pkVictim->GetJob())
{
case JOB_WARRIOR:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_WARRIOR)) / 100;
break;
case JOB_ASSASSIN:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ASSASSIN)) / 100;
break;
case JOB_SURA:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_SURA)) / 100;
break;
case JOB_SHAMAN:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_SHAMAN)) / 100;
break;
#ifdef ENABLE_WOLFMAN_CHARACTER
case JOB_WOLFMAN:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_WOLFMAN)) / 100;
break;
#endif
}
}
if (pkAttacker->IsPC() == true)
{
switch (pkAttacker->GetJob())
{
case JOB_WARRIOR:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_WARRIOR)) / 100;
break;
case JOB_ASSASSIN:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_ASSASSIN)) / 100;
break;
case JOB_SURA:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_SURA)) / 100;
break;
case JOB_SHAMAN:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_SHAMAN)) / 100;
break;
#ifdef ENABLE_WOLFMAN_CHARACTER
case JOB_WOLFMAN:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_WOLFMAN)) / 100;
break;
#endif
}
}
#ifdef ELEMENT_TARGET
if (pkAttacker->IsNPC() && pkVictim->IsPC())
{
if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ELEC))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_ELEC)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_FIRE))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_FIRE)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ICE))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_ICE)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_WIND))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_WIND)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_EARTH))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_EARTH)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_DARK))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_DARK)) / 10000;
}
#endif
return iAtk;
}
void Item_GetDamage(LPITEM pkItem, int* pdamMin, int* pdamMax)
{
*pdamMin = 0;
*pdamMax = 1;
if (!pkItem)
return;
switch (pkItem->GetType())
{
case ITEM_ROD:
case ITEM_PICK:
return;
}
if (pkItem->GetType() != ITEM_WEAPON)
sys_err("Item_GetDamage - !ITEM_WEAPON vnum=%d, type=%d", pkItem->GetOriginalVnum(), pkItem->GetType());
*pdamMin = pkItem->GetValue(3);
*pdamMax = pkItem->GetValue(4);
}
int CalcMeleeDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreDefense, bool bIgnoreTargetRating)
{
LPITEM pWeapon = pkAttacker->GetWear(WEAR_WEAPON);
bool bPolymorphed = pkAttacker->IsPolymorphed();
if (pWeapon && !(bPolymorphed && !pkAttacker->IsPolyMaintainStat()))
{
if (pWeapon->GetType() != ITEM_WEAPON)
return 0;
switch (pWeapon->GetSubType())
{
case WEAPON_SWORD:
case WEAPON_DAGGER:
case WEAPON_TWO_HANDED:
case WEAPON_BELL:
case WEAPON_FAN:
case WEAPON_MOUNT_SPEAR:
#ifdef ENABLE_WOLFMAN_CHARACTER
case WEAPON_CLAW:
#endif
break;
case WEAPON_BOW:
sys_err("CalcMeleeDamage should not handle bows (name: %s)", pkAttacker->GetName());
return 0;
default:
return 0;
}
}
int iDam = 0;
float fAR = CalcAttackRating(pkAttacker, pkVictim, bIgnoreTargetRating);
int iDamMin = 0, iDamMax = 0;
// TESTSERVER_SHOW_ATTACKINFO
int DEBUG_iDamCur = 0;
int DEBUG_iDamBonus = 0;
// END_OF_TESTSERVER_SHOW_ATTACKINFO
if (bPolymorphed && !pkAttacker->IsPolyMaintainStat())
{
Item_GetDamage(pWeapon, &iDamMin, &iDamMax);
DWORD dwMobVnum = pkAttacker->GetPolymorphVnum();
const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
if (pMob)
{
int iPower = pkAttacker->GetPolymorphPower();
iDamMin += pMob->m_table.dwDamageRange[0] * iPower / 100;
iDamMax += pMob->m_table.dwDamageRange[1] * iPower / 100;
}
}
else if (pWeapon)
{
Item_GetDamage(pWeapon, &iDamMin, &iDamMax);
}
else if (pkAttacker->IsNPC())
{
iDamMin = pkAttacker->GetMobDamageMin();
iDamMax = pkAttacker->GetMobDamageMax();
}
iDam = number(iDamMin, iDamMax) * 2;
DEBUG_iDamCur = iDam;
int iAtk = 0;
iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2);
iAtk = (int) (iAtk * fAR);
iAtk += pkAttacker->GetLevel() * 2;
if (pWeapon)
{
iAtk += pWeapon->GetValue(5) * 2;
DEBUG_iDamBonus = pWeapon->GetValue(5) * 2;
}
iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
iAtk = (int) (iAtk * (100 + (pkAttacker->GetPoint(POINT_ATT_BONUS) + pkAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100);
iAtk = CalcAttBonus(pkAttacker, pkVictim, iAtk);
int iDef = 0;
if (!bIgnoreDefense)
{
iDef = (pkVictim->GetPoint(POINT_DEF_GRADE) * (100 + pkVictim->GetPoint(POINT_DEF_BONUS)) / 100);
if (!pkAttacker->IsPC())
iDef += pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_DEFENSE_BONUS);
}
if (pkAttacker->IsNPC())
iAtk = (int) (iAtk * pkAttacker->GetMobDamageMultiply());
iDam = MAX(0, iAtk - iDef);
if (test_server)
{
int DEBUG_iLV = pkAttacker->GetLevel()*2;
int DEBUG_iST = int((pkAttacker->GetPoint(POINT_ATT_GRADE) - DEBUG_iLV) * fAR);
int DEBUG_iPT = pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
int DEBUG_iWP = 0;
int DEBUG_iPureAtk = 0;
int DEBUG_iPureDam = 0;
char szRB[32] = "";
char szGradeAtkBonus[32] = "";
DEBUG_iWP = int(DEBUG_iDamCur * fAR);
DEBUG_iPureAtk = DEBUG_iLV + DEBUG_iST + DEBUG_iWP+DEBUG_iDamBonus;
DEBUG_iPureDam = iAtk - iDef;
if (pkAttacker->IsNPC())
{
snprintf(szGradeAtkBonus, sizeof(szGradeAtkBonus), "=%d*%.1f", DEBUG_iPureAtk, pkAttacker->GetMobDamageMultiply());
DEBUG_iPureAtk = int(DEBUG_iPureAtk * pkAttacker->GetMobDamageMultiply());
}
if (DEBUG_iDamBonus != 0)
snprintf(szRB, sizeof(szRB), "+RB(%d)", DEBUG_iDamBonus);
char szPT[32] = "";
if (DEBUG_iPT != 0)
snprintf(szPT, sizeof(szPT), ", PT=%d", DEBUG_iPT);
char szUnknownAtk[32] = "";
if (iAtk != DEBUG_iPureAtk)
snprintf(szUnknownAtk, sizeof(szUnknownAtk), "+?(%d)", iAtk-DEBUG_iPureAtk);
char szUnknownDam[32] = "";
if (iDam != DEBUG_iPureDam)
snprintf(szUnknownDam, sizeof(szUnknownDam), "+?(%d)", iDam-DEBUG_iPureDam);
char szMeleeAttack[128];
snprintf(szMeleeAttack, sizeof(szMeleeAttack),
"%s(%d)-%s(%d)=%d%s, ATK=LV(%d)+ST(%d)+WP(%d)%s%s%s, AR=%.3g%s",
pkAttacker->GetName(),
iAtk,
pkVictim->GetName(),
iDef,
iDam,
szUnknownDam,
DEBUG_iLV,
DEBUG_iST,
DEBUG_iWP,
szRB,
szUnknownAtk,
szGradeAtkBonus,
fAR,
szPT);
pkAttacker->ChatPacket(CHAT_TYPE_TALKING, "%s", szMeleeAttack);
pkVictim->ChatPacket(CHAT_TYPE_TALKING, "%s", szMeleeAttack);
}
return CalcBattleDamage(iDam, pkAttacker->GetLevel(), pkVictim->GetLevel());
}
int CalcArrowDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, LPITEM pkBow, LPITEM pkArrow, bool bIgnoreDefense)
{
if (!pkBow || pkBow->GetType() != ITEM_WEAPON || pkBow->GetSubType() != WEAPON_BOW)
return 0;
if (!pkArrow)
return 0;
int iDist = (int) (DISTANCE_SQRT(pkAttacker->GetX() - pkVictim->GetX(), pkAttacker->GetY() - pkVictim->GetY()));
int iGap = (iDist / 100) - 5 - pkAttacker->GetPoint(POINT_BOW_DISTANCE);
int iPercent = 100 - (iGap * 5);
#ifdef WJ_QUIVER_SYSTEM
if (pkArrow->GetSubType() == WEAPON_UNLIMITED_ARROW)
{
iPercent = 100;
}
#endif
if(pkArrow->GetValue(5)==1)
{
iPercent = 100;
}
if (iPercent <= 0)
return 0;
else if (iPercent > 100)
iPercent = 100;
int iDam = 0;
float fAR = CalcAttackRating(pkAttacker, pkVictim, false);
iDam = number(pkBow->GetValue(3), pkBow->GetValue(4)) * 2 + pkArrow->GetValue(3);
int iAtk;
iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2);
iAtk = (int) (iAtk * fAR);
iAtk += pkAttacker->GetLevel() * 2;
iAtk += pkBow->GetValue(5) * 2;
iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
iAtk = (int) (iAtk * (100 + (pkAttacker->GetPoint(POINT_ATT_BONUS) + pkAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100);
iAtk = CalcAttBonus(pkAttacker, pkVictim, iAtk);
int iDef = 0;
if (!bIgnoreDefense)
iDef = (pkVictim->GetPoint(POINT_DEF_GRADE) * (100 + pkAttacker->GetPoint(POINT_DEF_BONUS)) / 100);
if (pkAttacker->IsNPC())
iAtk = (int) (iAtk * pkAttacker->GetMobDamageMultiply());
iDam = MAX(0, iAtk - iDef);
int iPureDam = iDam;
iPureDam = (iPureDam * iPercent) / 100;
if (test_server)
{
pkAttacker->ChatPacket(CHAT_TYPE_INFO, "ARROW %s -> %s, DAM %d DIST %d GAP %d %% %d",
pkAttacker->GetName(),
pkVictim->GetName(),
iPureDam,
iDist, iGap, iPercent);
}
return iPureDam;
//return iDam;
}
void NormalAttackAffect(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
// 독 공격은 특이하므로 특수 처리
if (pkAttacker->GetPoint(POINT_POISON_PCT) && !pkVictim->IsAffectFlag(AFF_POISON))
{
if (number(1, 100) <= pkAttacker->GetPoint(POINT_POISON_PCT))
pkVictim->AttackedByPoison(pkAttacker);
}
#ifdef ENABLE_WOLFMAN_CHARACTER
if (pkAttacker->GetPoint(POINT_BLEEDING_PCT) && !pkVictim->IsAffectFlag(AFF_BLEEDING))
{
if (number(1, 100) <= pkAttacker->GetPoint(POINT_BLEEDING_PCT))
pkVictim->AttackedByBleeding(pkAttacker);
}
#endif
int iStunDuration = 2;
if (pkAttacker->IsPC() && !pkVictim->IsPC())
iStunDuration = 4;
AttackAffect(pkAttacker, pkVictim, POINT_STUN_PCT, IMMUNE_STUN, AFFECT_STUN, POINT_NONE, 0, AFF_STUN, iStunDuration, "STUN");
AttackAffect(pkAttacker, pkVictim, POINT_SLOW_PCT, IMMUNE_SLOW, AFFECT_SLOW, POINT_MOV_SPEED, -30, AFF_SLOW, 20, "SLOW");
}
int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int & iRetDam)
{
if (test_server)
sys_log(0, "battle_hit : [%s] attack to [%s] : dam :%d type :%d", pkAttacker->GetName(), pkVictim->GetName(), iRetDam);
int iDam = CalcMeleeDamage(pkAttacker, pkVictim);
if (iDam <= 0)
return (BATTLE_DAMAGE);
NormalAttackAffect(pkAttacker, pkVictim);
LPITEM pkWeapon = pkAttacker->GetWear(WEAR_WEAPON);
if (pkWeapon)
switch (pkWeapon->GetSubType())
{
case WEAPON_SWORD:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_SWORD)) / 100;
break;
case WEAPON_TWO_HANDED:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_TWOHAND)) / 100;
break;
case WEAPON_DAGGER:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_DAGGER)) / 100;
break;
case WEAPON_BELL:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_BELL)) / 100;
break;
case WEAPON_FAN:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_FAN)) / 100;
break;
case WEAPON_BOW:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_BOW)) / 100;
break;
#ifdef ENABLE_WOLFMAN_CHARACTER
case WEAPON_CLAW:
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_CLAW)) / 100;
#if defined(ENABLE_WOLFMAN_CHARACTER) && defined(USE_ITEM_CLAW_AS_DAGGER)
iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_DAGGER)) / 100;
#endif
break;
#endif
}
float attMul = pkAttacker->GetAttMul();
float tempIDam = iDam;
iDam = attMul * tempIDam + 0.5f;
iRetDam = iDam;
if (pkVictim->Damage(pkAttacker, iDam, DAMAGE_TYPE_NORMAL))
return (BATTLE_DEAD);
return (BATTLE_DAMAGE);
}
DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
if (NULL == ch)
return 1000;
LPITEM item = ch->GetWear(WEAR_WEAPON);
DWORD default_bonus = SPEEDHACK_LIMIT_BONUS;
DWORD riding_bonus = 0;
if (ch->IsRiding())
{
riding_bonus = 50;
}
DWORD ani_speed = ani_attack_speed(ch);
DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);
if (item && item->GetSubType() == WEAPON_DAGGER)
real_speed /= 2;
#ifdef ENABLE_WOLFMAN_CHARACTER
else if (item && item->GetSubType() == WEAPON_CLAW)
real_speed /= 2;
#endif
return real_speed;
}
void SET_ATTACK_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
{
if (NULL == ch || NULL == victim)
return;
if (!ch->IsPC())
return;
ch->m_kAttackLog.dwVID = victim->GetVID();
ch->m_kAttackLog.dwTime = current_time;
}
void SET_ATTACKED_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
{
if (NULL == ch || NULL == victim)
return;
if (!ch->IsPC())
return;
victim->m_AttackedLog.dwPID = ch->GetPlayerID();
victim->m_AttackedLog.dwAttackedTime= current_time;
}
bool IS_SPEED_HACK(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
{
if (ch->m_kAttackLog.dwVID == victim->GetVID())
{
if (current_time - ch->m_kAttackLog.dwTime < GET_ATTACK_SPEED(ch))
{
INCREASE_SPEED_HACK_COUNT(ch);
if (test_server)
{
sys_log(0, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d",
ch->GetName(),
current_time - ch->m_kAttackLog.dwTime,
GET_ATTACK_SPEED(ch),
ch->m_speed_hack_count);
ch->ChatPacket(CHAT_TYPE_INFO, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d",
ch->GetName(),
current_time - ch->m_kAttackLog.dwTime,
GET_ATTACK_SPEED(ch),
ch->m_speed_hack_count);
}
SET_ATTACK_TIME(ch, victim, current_time);
SET_ATTACKED_TIME(ch, victim, current_time);
return true;
}
}
SET_ATTACK_TIME(ch, victim, current_time);
if (victim->m_AttackedLog.dwPID == ch->GetPlayerID())
{
if (current_time - victim->m_AttackedLog.dwAttackedTime < GET_ATTACK_SPEED(ch))
{
INCREASE_SPEED_HACK_COUNT(ch);
if (test_server)
{
sys_log(0, "%s Attack Speed HACK! time (delta, limit)=(%u, %u), hack_count = %d",
ch->GetName(),
current_time - victim->m_AttackedLog.dwAttackedTime,
GET_ATTACK_SPEED(ch),
ch->m_speed_hack_count);
ch->ChatPacket(CHAT_TYPE_INFO, "Attack Speed Hack(%s), (delta, limit)=(%u, %u)",
ch->GetName(),
current_time - victim->m_AttackedLog.dwAttackedTime,
GET_ATTACK_SPEED(ch));
}
SET_ATTACKED_TIME(ch, victim, current_time);
return true;
}
}
SET_ATTACKED_TIME(ch, victim, current_time);
return false;
}
[/CODE]
[CODE title="constants.cpp"]#include "stdafx.h"
#include "char.h"
#include "../../common/service.h"
TJobInitialPoints JobInitialPoints[JOB_MAX_NUM] =
/*
{
int st, ht, dx, iq;
int max_hp, max_sp;
int hp_per_ht, sp_per_iq;
int hp_per_lv_begin, hp_per_lv_end;
int sp_per_lv_begin, sp_per_lv_end;
int max_stamina;
int stamina_per_con;
int stamina_per_lv_begin, stamina_per_lv_end;
}
*/
{
// str con dex int 초기HP 초기SP CON/HP INT/SP HP랜덤/lv MP랜덤/lv 초기stam stam/con stam/lv
{ 6, 4, 3, 3, 600, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_WARRIOR 16
{ 4, 3, 6, 3, 650, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_ASSASSIN 16
{ 5, 3, 3, 5, 650, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_SURA 16
{ 3, 4, 3, 6, 700, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_SHAMANa 16
#ifdef ENABLE_WOLFMAN_CHARACTER
{ 2, 6, 6, 2, 600, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_WOLFMAN 16 // TODO: 4개능력치 초기값 외에 다른 스탯 필요 (기획자한테 요청)
#endif
};
const TMobRankStat MobRankStats[MOB_RANK_MAX_NUM] =
/*
{
int iGoldPercent;
}
*/
{
{ 20, }, // MOB_RANK_PAWN,
{ 20, }, // MOB_RANK_S_PAWN,
{ 25, }, // MOB_RANK_KNIGHT,
{ 30, }, // MOB_RANK_S_KNIGHT,
{ 50, }, // MOB_RANK_BOSS,
{ 100, } // MOB_RANK_KING,
};
TBattleTypeStat BattleTypeStats[BATTLE_TYPE_MAX_NUM] =
/*
{
int AttGradeBias;
int DefGradeBias;
int MagicAttGradeBias;
int MagicDefGradeBias;
}
*/
{
{ 0, 0, 0, -10 }, // BATTLE_TYPE_MELEE,
{ 10, -20, -10, -15 }, // BATTLE_TYPE_RANGE,
{ -5, -5, 10, 10 }, // BATTLE_TYPE_MAGIC,
{ 0, 0, 0, 0 }, // BATTLE_TYPE_SPECIAL,
{ 10, -10, 0, -15 }, // BATTLE_TYPE_POWER,
{ -10, 10, -10, 0 }, // BATTLE_TYPE_TANKER,
{ 20, -20, 0, -10 }, // BATTLE_TYPE_SUPER_POWER,
{ -20, 20, -10, 0 }, // BATTLE_TYPE_SUPER_TANKER,
};
#ifdef ENABLE_GROWTH_PET_SYSTEM
DWORD * exppet_table = NULL;
//const DWORD pets = 4;
const DWORD Pet_Table[10][2] =
{
{ 55701, 34041 },
{ 55702, 34045 },
{ 55703, 34049 },
{ 55704, 34053 },
{ 55705, 34036 },
{ 55706, 34061 },
{ 55707, 34073 },
{ 55708, 34075 },
{ 55709, 34080 },
{ 55710, 34082 }
};
const DWORD Pet_Skill_Table[18][23] =
{
//Level Like Index ->> Bonus Value --> typeSkill --> CoolDown -->> Percentage
{ 78, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12 },
{ 80, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12 },
{ 79, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12 },
{ 81, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12 },
{ 95, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12 }, //5
{ 64, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10 },
{ 98, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12 },//fixpet
{ 9, 0, 0, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17 },
{ 16, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9 },
{ 4, 1, 480, 17, 68, 153, 272, 425, 612, 833, 1088, 1377, 1700, 2057, 2448, 2873, 3332, 3825, 4352, 4913, 5508, 6137, 6800 }, //10
{ 23, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5 },
{ 24, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 6 },
{ 27, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11 },
{ 28, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7 },
{ 44, 0, 0, 5, 10, 15, 20, 25, 31, 36, 41, 46, 51, 56, 61, 67, 72, 77, 82, 87, 92, 97, 103 }, //15
{ 52, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6 },
{ 11, 1, 600, 2, 4, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 20, 21, 22, 23, 25, 26, 27 },
{ 6, 1, 480, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
const DWORD Pet_SKill_TablePerc[3][20] =
{
{ 2, 5, 8, 11, 13, 16, 19, 22, 24, 27, 30, 33, 35, 38, 41, 44, 46, 49, 52, 55 },
{ 2, 5, 7, 10, 12, 15, 17, 20, 23, 25, 27, 30, 32, 35, 37, 40, 42, 45, 47, 50 },
{ 2, 5, 8, 11, 13, 16, 19, 22, 25, 27, 30, 33, 36, 38, 41, 44, 47, 50, 52, 55 }
};
DWORD exppet_table_common[120];
#endif
const DWORD * exp_table = NULL;
const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] =
{
0, // 0
100,
150,
260,
380,
600,
1300,
3300,
5700,
8700,
12800, // 10
18000,
25000,
36000,
52000,
73000,
100000,
125000,
160000,
220000,
280000, // 20
370000,
540000,
670000,
880000,
1000000,
1237000,
1418000,
1624000,
1857000,
2122000, // 30
2421000,
2761000,
3145000,
3580000,
4073000,
4632000,
5194000,
5717000,
6264000,
6837000, // 40
7600000,
8274000,
8990000,
9753000,
10560000,
11410000,
12320000,
13270000,
14280000,
15340000, // 50
16870000,
18960000,
19980000,
21420000,
22930000,
24530000,
26200000,
27960000,
29800000,
32780000, // 60
36060000,
39670000,
43640000,
48000000,
52800000,
58080000,
63890000,
70280000,
77310000,
85040000, // 70
93540000,
102900000,
113200000,
124500000,
137000000,
150700000,
165700000,
236990000,
260650000,
286780000, // 80
315380000,
346970000,
381680000,
419770000,
461760000,
508040000,
558740000,
614640000,
676130000,
743730000, // 90
1041222000,
1145344200,
1259878620,
1385866482,
1524453130,
1676898443,
1844588288,
2029047116,
2100000000, // 99 99레벨일 때 필요경험치 (100레벨이 되기 위한)
2100000000, // 100
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 105
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 110
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 115
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 120
};
const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1] =
{
0, // 0
300, //500
800, //700
1500, //1000
2500,
4300,
7200,
11000,
17000,
24000,
33000, // 10
43000,
58000,
76000,
100000,
130000,
169000,
219000,
283000,
365000,
472000, // 20
610000,
705000,
813000,
937000,
1077000,
1237000,
1418000,
1624000,
1857000,
2122000, // 30
2421000,
2761000,
3145000,
3580000,
4073000,
4632000,
5194000,
5717000,
6264000,
6837000, // 40
7600000,
8274000,
8990000,
9753000,
10560000,
11410000,
12320000,
13270000,
14280000,
15340000, // 50
16870000,
18960000,
19980000,
21420000,
22930000,
24530000,
26200000,
27960000,
29800000,
32780000, // 60
36060000,
39670000,
43640000,
48000000,
52800000,
58080000,
63890000,
70280000,
77310000,
85040000, // 70
93540000,
102900000,
113200000,
124500000,
137000000,
150700000,
165700000,
236990000,
260650000,
286780000, // 80
315380000,
346970000,
381680000,
419770000,
461760000,
508040000,
558740000,
614640000,
676130000,
743730000, // 90
1041222000,
1145344200,
1259878620,
1385866482,
1524453130,
1676898443,
1844588288,
1929047116,
2000000000, // 99레벨 일 때 필요경험치 (100레벨이 되기 위한)
2020000000, // 100
2040000000,
2060000000,
2080000000,
2090000000,
2100000000, // 105
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 110
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 115
2100000000,
2100000000,
2100000000,
2100000000,
2100000000, // 120
2251500000,
2253000000,
2254500000,
2256000000,
2257500000, // 125
2259000000,
2260500000,
2262000000,
2263500000,
2265000000, // 130
2266500000,
2268000000,
2269500000,
2271000000,
2272500000, // 135
2274000000,
2275500000,
2277000000,
2278500000,
2280000000, // 140
2281800000,
2283600000,
2285400000,
2287200000,
2289000000, // 145
2290800000,
2292600000,
2294400000,
2296200000,
2298000000, // 150
2299800000,
2301600000,
2303400000,
2305200000,
2307000000, // 155
2308800000,
2310600000,
2312400000,
2314200000,
2316000000, // 160
2317800000,
2319600000,
2321400000,
2323200000,
2325000000, // 165
2326800000,
2328600000,
2330400000,
2332200000,
2334000000, // 170
2335800000,
2337600000,
2339400000,
2341200000,
2343000000, // 175
2344800000,
2346600000,
2348400000,
2350200000,
2352000000, // 180
2353800000,
2355600000,
2357400000,
2359200000,
2361000000, // 185
2362800000,
2364600000,
2366400000,
2368200000,
2370000000, // 190
2371800000,
2373600000,
2375400000,
2377200000,
2379000000, // 195
2380800000,
2382600000,
2384400000,
2386200000,
2388000000, // 200
2389800000,
2391600000,
2393400000,
2395200000,
2397000000, // 205
2398800000,
2400600000,
2402400000,
2404200000,
2406000000, // 210
2407800000,
2409600000,
2411400000,
2413200000,
2415000000, // 215
2416800000,
2418600000,
2420400000,
2422200000,
2424000000, // 220
2425800000,
2427600000,
2429400000,
2431200000,
2433000000, // 225
2434800000,
2436600000,
2438400000,
2440200000,
2442000000, // 230
2443800000,
2445600000,
2447400000,
2449200000,
2451000000, // 235
2452800000,
2454600000,
2456400000,
2458200000,
2460000000, // 240
2461800000,
2463600000,
2465400000,
2467200000,
2469000000, // 245
2470800000,
2472600000,
2474400000,
2478000000,
2500000000, // 250
};
#ifdef ENABLE_SUPPORT_SYSTEM
const DWORD exp_support_table[121] =
{
0,
300,
800,
1500,
2500,
4300,
7200,
11000,
17000,
24000,
33001,
43000,
58000,
76000,
100000,
130000,
169000,
219000,
283000,
365000,
472000,
610000,
705000,
813000,
937000,
1077000,
1237000,
1418000,
1624000,
1857000,
2122000,
2421000,
2761000,
3145000,
3580000,
4073000,
4632000,
5194000,
5717000,
6264000,
6837000,
7600000,
8274000,
8990000,
9753000,
10560000,
11410000,
12320000,
13270000,
14280000,
15340000,
16870000,
18960000,
19980000,
21420000,
22930000,
24530000,
26200000,
27960000,
29800000,
32780000,
36060000,
39670000,
43640000,
48000000,
52800000,
58080000,
63890000,
70280000,
77310000,
85040000,
93540000,
102900000,
113200000,
124500000,
137000000,
150700000,
165700000,
236990000,
260650000,
286780000,
315380000,
346970000,
381680000,
419770000,
461760000,
508040000,
558740000,
614640000,
676130000,
743730000,
1041222000,
1145344200,
1259878620,
1385866482,
1524453130,
1676898443,
1844588288,
2029047116,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
2147483646,
};
#endif
const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] =
{
300, // 0
800, // 1
1500,
2500,
4300,
7200,
11400,
17000,
24000,
33000,
46000, // 10
62000,
83000,
111000,
149000,
200000,
268000,
360000,
482000,
647000,
868000, // 20
996000,
1143000,
1312000,
1506000,
1729000,
1984000,
2277000,
2614000,
3000000,
3443000, // 30
3952000,
4536000,
5206000,
5975000,
6858000,
7730000,
8504000,
9307000,
10140000,
11330000, // 40
12320000,
13370000,
14490000,
15670000,
16920000,
18240000,
19630000,
21090000,
22630000,
24670000, // 50
26890000,
29310000,
31950000,
34820000,
37960000,
41370000,
45100000,
49160000,
53580000,
58400000, // 60
63660000,
69390000,
75630000,
82440000,
89860000,
97950000,
106760000,
136370000,
151800000,
168300000, // 70
250000000,
340000000,
450000000,
570000000,
690000000,
810000000,
912600000,
1004000000,
1094000000,
1182000000, // 80
1269000000,
1354000000,
1438000000,
1521000000,
1603000000,
1684000000,
1764000000,
1844000000,
1922000000,
2000000000, // 90
2000000000,
2000000000,
2000000000,
2000000000,
2000000000,
2000000000,
2000000000,
2000000000,
2000000000, // 99 99레벨일 때 필요경험치 (100레벨이 되기 위한).. 현재 CIBN이 어떻게 운영하고 있는 지 모르니 신규 테이블을 쓰지 않고 기존값 계속 연장 유지
2000000000, // 100
2000000000,
2000000000,
2000000000,
2000000000,
2000000000, // 105
2000000000,
2000000000,
2000000000,
2000000000,
2000000000, // 110
2000000000,
2000000000,
2000000000,
2000000000,
2000000000, // 115
2000000000,
2000000000,
2000000000,
2000000000,
2000000000, // 120
};
const int * aiPercentByDeltaLev = NULL;
const int * aiPercentByDeltaLevForBoss = NULL;
// 적과 나와의 레벨차이에 의한 계산에 사용되는 테이블
// MIN(MAX_EXP_DELTA_OF_LEV - 1, (적렙 + 15) - 내렙))
const int aiPercentByDeltaLevForBoss_euckr[MAX_EXP_DELTA_OF_LEV] =
{
1, // -15 0
3, // -14 1
5, // -13 2
7, // -12 3
15, // -11 4
30, // -10 5
60, // -9 6
90, // -8 7
91, // -7 8
92, // -6 9
93, // -5 10
94, // -4 11
95, // -3 12
97, // -2 13
99, // -1 14
100, // 0 15
105, // 1 16
110, // 2 17
115, // 3 18
120, // 4 19
125, // 5 20
130, // 6 21
135, // 7 22
140, // 8 23
145, // 9 24
150, // 10 25
155, // 11 26
160, // 12 27
165, // 13 28
170, // 14 29
180 // 15 30
};
const int aiPercentByDeltaLev_euckr[MAX_EXP_DELTA_OF_LEV] =
{
1, // -15 0
5, // -14 1
10, // -13 2
20, // -12 3
30, // -11 4
50, // -10 5
70, // -9 6
80, // -8 7
85, // -7 8
90, // -6 9
92, // -5 10
94, // -4 11
96, // -3 12
98, // -2 13
100, // -1 14
100, // 0 15
105, // 1 16
110, // 2 17
115, // 3 18
120, // 4 19
125, // 5 20
130, // 6 21
135, // 7 22
140, // 8 23
145, // 9 24
150, // 10 25
155, // 11 26
160, // 12 27
165, // 13 28
170, // 14 29
180, // 15 30
};
const DWORD party_exp_distribute_table[PLAYER_MAX_LEVEL_CONST + 1] =
{
0,
10, 10, 10, 10, 15, 15, 20, 25, 30, 40, // 1 - 10
50, 60, 80, 100, 120, 140, 160, 184, 210, 240, // 11 - 20
270, 300, 330, 360, 390, 420, 450, 480, 510, 550, // 21 - 30
600, 640, 700, 760, 820, 880, 940, 1000, 1100, 1180, // 31 - 40
1260, 1320, 1380, 1440, 1500, 1560, 1620, 1680, 1740, 1800, // 41 - 50
1860, 1920, 2000, 2100, 2200, 2300, 2450, 2600, 2750, 2900, // 51 - 60
3050, 3200, 3350, 3500, 3650, 3800, 3950, 4100, 4250, 4400, // 61 - 70
4600, 4800, 5000, 5200, 5400, 5600, 5800, 6000, 6200, 6400, // 71 - 80
6600, 6800, 7000, 7200, 7400, 7600, 7800, 8000, 8200, 8400, // 81 - 90
8600, 8800, 9000, 9200, 9400, 9600, 9800, 10000, 10200, 10400, // 91 - 100
10600, 10800, 11000, 11200, 11400, 11600, 11800, 12000, 12200, 12400, // 101 - 110
12600, 12800, 13000, 13200, 13400, 13600, 13800, 14000, 14200, 14400, // 111 - 120
14600, 14800, 15000, 15200, 15400, 15600, 15800, 16000, 16200, 16400, // 121 - 130
16600, 16800, 17000, 17200, 17400, 17600, 17800, 18000, 18200, 18400, // 131 - 140
18600, 18800, 19000, 19200, 19400, 19600, 19800, 20000, 20200, 20400, // 141 - 150
20600, 20800, 21000, 21200, 21400, 21600, 21800, 22000, 22200, 22400, // 151 - 160
22600, 22800, 23000, 23200, 23400, 23600, 23800, 24000, 24200, 24400, // 161 - 170
24600, 24800, 25000, 25200, 25400, 25600, 25800, 26000, 26200, 26400, // 171 - 180
26600, 26800, 27000, 27200, 27400, 27600, 27800, 28000, 28200, 28400, // 181 - 190
28600, 28800, 29000, 29200, 29400, 29600, 29800, 30000, 30200, 30400, // 191 - 200
30600, 30800, 31000, 31200, 31400, 31600, 31800, 32000, 32200, 32400, // 201 - 210
32600, 32800, 33000, 33200, 33400, 33600, 33800, 34000, 34200, 34400, // 211 - 220
34600, 34800, 35000, 35200, 35400, 35600, 35800, 36000, 36200, 36400, // 221 - 230
36600, 36800, 37000, 37200, 37400, 37600, 37800, 38000, 38200, 38400, // 231 - 240
38600, 38800, 39000, 39200, 39400, 39600, 39800, 40000, 40200, 40400, // 241 - 250
};
Coord aArroundCoords[ARROUND_COORD_MAX_NUM] =
{
{ 0, 0 },
{ 0, 50 },
{ 35, 35 },
{ 50, -0 },
{ 35, -35 },
{ 0, -50 },
{ -35, -35 },
{ -50, 0 },
{ -35, 35 },
{ 0, 100 },
{ 71, 71 },
{ 100, -0 },
{ 71, -71 },
{ 0, -100 },
{ -71, -71 },
{ -100, 0 },
{ -71, 71 },
{ 0, 150 },
{ 106, 106 },
{ 150, -0 },
{ 106, -106 },
{ 0, -150 },
{ -106, -106 },
{ -150, 0 },
{ -106, 106 },
{ 0, 200 },
{ 141, 141 },
{ 200, -0 },
{ 141, -141 },
{ 0, -200 },
{ -141, -141 },
{ -200, 0 },
{ -141, 141 },
{ 0, 250 },
{ 177, 177 },
{ 250, -0 },
{ 177, -177 },
{ 0, -250 },
{ -177, -177 },
{ -250, 0 },
{ -177, 177 },
{ 0, 300 },
{ 212, 212 },
{ 300, -0 },
{ 212, -212 },
{ 0, -300 },
{ -212, -212 },
{ -300, 0 },
{ -212, 212 },
{ 0, 350 },
{ 247, 247 },
{ 350, -0 },
{ 247, -247 },
{ 0, -350 },
{ -247, -247 },
{ -350, 0 },
{ -247, 247 },
{ 0, 400 },
{ 283, 283 },
{ 400, -0 },
{ 283, -283 },
{ 0, -400 },
{ -283, -283 },
{ -400, 0 },
{ -283, 283 },
{ 0, 450 },
{ 318, 318 },
{ 450, -0 },
{ 318, -318 },
{ 0, -450 },
{ -318, -318 },
{ -450, 0 },
{ -318, 318 },
{ 0, 500 },
{ 354, 354 },
{ 500, -0 },
{ 354, -354 },
{ 0, -500 },
{ -354, -354 },
{ -500, 0 },
{ -354, 354 },
{ 0, 550 },
{ 389, 389 },
{ 550, -0 },
{ 389, -389 },
{ 0, -550 },
{ -389, -389 },
{ -550, 0 },
{ -389, 389 },
{ 0, 600 },
{ 424, 424 },
{ 600, -0 },
{ 424, -424 },
{ 0, -600 },
{ -424, -424 },
{ -600, 0 },
{ -424, 424 },
{ 0, 650 },
{ 460, 460 },
{ 650, -0 },
{ 460, -460 },
{ 0, -650 },
{ -460, -460 },
{ -650, 0 },
{ -460, 460 },
{ 0, 700 },
{ 495, 495 },
{ 700, -0 },
{ 495, -495 },
{ 0, -700 },
{ -495, -495 },
{ -700, 0 },
{ -495, 495 },
{ 0, 750 },
{ 530, 530 },
{ 750, -0 },
{ 530, -530 },
{ 0, -750 },
{ -530, -530 },
{ -750, 0 },
{ -530, 530 },
{ 0, 800 },
{ 566, 566 },
{ 800, -0 },
{ 566, -566 },
{ 0, -800 },
{ -566, -566 },
{ -800, 0 },
{ -566, 566 },
{ 0, 850 },
{ 601, 601 },
{ 850, -0 },
{ 601, -601 },
{ 0, -850 },
{ -601, -601 },
{ -850, 0 },
{ -601, 601 },
{ 0, 900 },
{ 636, 636 },
{ 900, -0 },
{ 636, -636 },
{ 0, -900 },
{ -636, -636 },
{ -900, 0 },
{ -636, 636 },
{ 0, 950 },
{ 672, 672 },
{ 950, -0 },
{ 672, -672 },
{ 0, -950 },
{ -672, -672 },
{ -950, 0 },
{ -672, 672 },
{ 0, 1000 },
{ 707, 707 },
{ 1000, -0 },
{ 707, -707 },
{ 0, -1000 },
{ -707, -707 },
{ -1000, 0 },
{ -707, 707 },
};
const DWORD guild_exp_table[GUILD_MAX_LEVEL+1] =
{
0,
15000UL,
45000UL,
90000UL,
160000UL,
235000UL,
325000UL,
430000UL,
550000UL,
685000UL,
835000UL,
1000000UL,
1500000UL,
2100000UL,
2800000UL,
3600000UL,
4500000UL,
6500000UL,
8000000UL,
10000000UL,
42000000UL
};
// INTERNATIONAL_VERSION 길드경험치
const DWORD guild_exp_table2[GUILD_MAX_LEVEL+1] =
{
0,
6000UL,
18000UL,
36000UL,
64000UL,
94000UL,
130000UL,
172000UL,
220000UL,
274000UL,
334000UL,
400000UL,
600000UL,
840000UL,
1120000UL,
1440000UL,
1800000UL,
2600000UL,
3200000UL,
4000000UL,
16800000UL
};
// END_OF_INTERNATIONAL_VERSION 길드경험치
const int aiMobEnchantApplyIdx[MOB_ENCHANTS_MAX_NUM] =
{
APPLY_CURSE_PCT,
APPLY_SLOW_PCT,
APPLY_POISON_PCT,
APPLY_STUN_PCT,
APPLY_CRITICAL_PCT,
APPLY_PENETRATE_PCT,
#if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON)
APPLY_BLEEDING_PCT,
#endif
};
const int aiMobResistsApplyIdx[MOB_RESISTS_MAX_NUM] =
{
APPLY_RESIST_SWORD,
APPLY_RESIST_TWOHAND,
APPLY_RESIST_DAGGER,
APPLY_RESIST_BELL,
APPLY_RESIST_FAN,
APPLY_RESIST_BOW,
APPLY_RESIST_FIRE,
APPLY_RESIST_ELEC,
APPLY_RESIST_MAGIC,
APPLY_RESIST_WIND,
APPLY_POISON_REDUCE,
#if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_CLAW_AS_DAGGER)
APPLY_RESIST_CLAW,
#endif
#if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON)
APPLY_BLEEDING_REDUCE,
#endif
};
const int aiSocketPercentByQty[5][4] =
{
{ 0, 0, 0, 0 },
{ 3, 0, 0, 0 },
{ 10, 1, 0, 0 },
{ 15, 10, 1, 0 },
{ 20, 15, 10, 1 }
};
const int aiWeaponSocketQty[WEAPON_NUM_TYPES] =
{
4, // WEAPON_SWORD,
4, // WEAPON_DAGGER,
4, // WEAPON_BOW,
4, // WEAPON_TWO_HANDED,
4, // WEAPON_BELL,
4, // WEAPON_FAN,
0, // WEAPON_ARROW,
0, // WEAPON_MOUNT_SPEAR,
#ifdef ENABLE_WOLFMAN_CHARACTER
4, // WEAPON_CLAW
#endif
#ifdef WJ_QUIVER_SYSTEM
0, // WEAPON_UNLIMITED_ARROW
#endif
};
const int aiArmorSocketQty[ARMOR_NUM_TYPES] =
{
4, // ARMOR_BODY,
1, // ARMOR_HEAD,
1, // ARMOR_SHIELD,
0, // ARMOR_WRIST,
0, // ARMOR_FOOTS,
0 // ARMOR_ACCESSORY
};
TItemAttrMap g_map_itemAttr;
TItemAttrMap g_map_itemRare;
const TApplyInfo aApplyInfo[MAX_APPLY_NUM] =
/*
{
DWORD dwPointType;
}
*/
{
// Point Type
{ POINT_NONE, }, // APPLY_NONE, 0
{ POINT_MAX_HP, }, // APPLY_MAX_HP, 1
{ POINT_MAX_SP, }, // APPLY_MAX_SP, 2
{ POINT_HT, }, // APPLY_CON, 3
{ POINT_IQ, }, // APPLY_INT, 4
{ POINT_ST, }, // APPLY_STR, 5
{ POINT_DX, }, // APPLY_DEX, 6
{ POINT_ATT_SPEED, }, // APPLY_ATT_SPEED, 7
{ POINT_MOV_SPEED, }, // APPLY_MOV_SPEED, 8
{ POINT_CASTING_SPEED, }, // APPLY_CAST_SPEED, 9
{ POINT_HP_REGEN, }, // APPLY_HP_REGEN, 10
{ POINT_SP_REGEN, }, // APPLY_SP_REGEN, 11
{ POINT_POISON_PCT, }, // APPLY_POISON_PCT, 12
{ POINT_STUN_PCT, }, // APPLY_STUN_PCT, 13
{ POINT_SLOW_PCT, }, // APPLY_SLOW_PCT, 14
{ POINT_CRITICAL_PCT, }, // APPLY_CRITICAL_PCT, 15
{ POINT_PENETRATE_PCT, }, // APPLY_PENETRATE_PCT, 16
{ POINT_ATTBONUS_HUMAN, }, // APPLY_ATTBONUS_HUMAN, 17
{ POINT_ATTBONUS_ANIMAL, }, // APPLY_ATTBONUS_ANIMAL, 18
{ POINT_ATTBONUS_ORC, }, // APPLY_ATTBONUS_ORC, 19
{ POINT_ATTBONUS_MILGYO, }, // APPLY_ATTBONUS_MILGYO, 20
{ POINT_ATTBONUS_UNDEAD, }, // APPLY_ATTBONUS_UNDEAD, 21
{ POINT_ATTBONUS_DEVIL, }, // APPLY_ATTBONUS_DEVIL, 22
{ POINT_STEAL_HP, }, // APPLY_STEAL_HP, 23
{ POINT_STEAL_SP, }, // APPLY_STEAL_SP, 24
{ POINT_MANA_BURN_PCT, }, // APPLY_MANA_BURN_PCT, 25
{ POINT_DAMAGE_SP_RECOVER, }, // APPLY_DAMAGE_SP_RECOVER,26
{ POINT_BLOCK, }, // APPLY_BLOCK, 27
{ POINT_DODGE, }, // APPLY_DODGE, 28
{ POINT_RESIST_SWORD, }, // APPLY_RESIST_SWORD, 29
{ POINT_RESIST_TWOHAND, }, // APPLY_RESIST_TWOHAND, 30
{ POINT_RESIST_DAGGER, }, // APPLY_RESIST_DAGGER, 31
{ POINT_RESIST_BELL, }, // APPLY_RESIST_BELL, 32
{ POINT_RESIST_FAN, }, // APPLY_RESIST_FAN, 33
{ POINT_RESIST_BOW, }, // APPLY_RESIST_BOW, 34
{ POINT_RESIST_FIRE, }, // APPLY_RESIST_FIRE, 35
{ POINT_RESIST_ELEC, }, // APPLY_RESIST_ELEC, 36
{ POINT_RESIST_MAGIC, }, // APPLY_RESIST_MAGIC, 37
{ POINT_RESIST_WIND, }, // APPLY_RESIST_WIND, 38
{ POINT_REFLECT_MELEE, }, // APPLY_REFLECT_MELEE, 39
{ POINT_REFLECT_CURSE, }, // APPLY_REFLECT_CURSE, 40
{ POINT_POISON_REDUCE, }, // APPLY_POISON_REDUCE, 41
{ POINT_KILL_SP_RECOVER, }, // APPLY_KILL_SP_RECOVER, 42
{ POINT_EXP_DOUBLE_BONUS, }, // APPLY_EXP_DOUBLE_BONUS, 43
{ POINT_GOLD_DOUBLE_BONUS, }, // APPLY_GOLD_DOUBLE_BONUS,44
{ POINT_ITEM_DROP_BONUS, }, // APPLY_ITEM_DROP_BONUS, 45
{ POINT_POTION_BONUS, }, // APPLY_POTION_BONUS, 46
{ POINT_KILL_HP_RECOVERY, }, // APPLY_KILL_HP_RECOVER, 47
{ POINT_IMMUNE_STUN, }, // APPLY_IMMUNE_STUN, 48
{ POINT_IMMUNE_SLOW, }, // APPLY_IMMUNE_SLOW, 49
{ POINT_IMMUNE_FALL, }, // APPLY_IMMUNE_FALL, 50
{ POINT_NONE, }, // APPLY_SKILL, 51
{ POINT_BOW_DISTANCE, }, // APPLY_BOW_DISTANCE, 52
{ POINT_ATT_GRADE_BONUS, }, // APPLY_ATT_GRADE, 53
{ POINT_DEF_GRADE_BONUS, }, // APPLY_DEF_GRADE, 54
{ POINT_MAGIC_ATT_GRADE_BONUS, }, // APPLY_MAGIC_ATT_GRADE, 55
{ POINT_MAGIC_DEF_GRADE_BONUS, }, // APPLY_MAGIC_DEF_GRADE, 56
{ POINT_CURSE_PCT, }, // APPLY_CURSE_PCT, 57
{ POINT_MAX_STAMINA }, // APPLY_MAX_STAMINA 58
{ POINT_ATTBONUS_WARRIOR }, // APPLY_ATTBONUS_WARRIOR 59
{ POINT_ATTBONUS_ASSASSIN }, // APPLY_ATTBONUS_ASSASSIN 60
{ POINT_ATTBONUS_SURA }, // APPLY_ATTBONUS_SURA 61
{ POINT_ATTBONUS_SHAMAN }, // APPLY_ATTBONUS_SHAMAN 62
{ POINT_ATTBONUS_MONSTER }, // APPLY_ATTBONUS_MONSTER 63
{ POINT_ATT_BONUS }, // 64 // APPLY_MALL_ATTBONUS
{ POINT_MALL_DEFBONUS }, // 65
{ POINT_MALL_EXPBONUS }, // 66 APPLY_MALL_EXPBONUS
{ POINT_MALL_ITEMBONUS }, // 67
{ POINT_MALL_GOLDBONUS }, // 68
{ POINT_MAX_HP_PCT }, // 69
{ POINT_MAX_SP_PCT }, // 70
{ POINT_SKILL_DAMAGE_BONUS }, // 71
{ POINT_NORMAL_HIT_DAMAGE_BONUS }, // 72
// DEFEND_BONUS_ATTRIBUTES
{ POINT_SKILL_DEFEND_BONUS }, // 73
{ POINT_NORMAL_HIT_DEFEND_BONUS }, // 74
// END_OF_DEFEND_BONUS_ATTRIBUTES
// PC_BANG_ITEM_ADD
{ POINT_PC_BANG_EXP_BONUS }, // 75
{ POINT_PC_BANG_DROP_BONUS }, // 76
// END_PC_BANG_ITEM_ADD
{ POINT_NONE, }, // 77 사용시 HP 소모 APPLY_EXTRACT_HP_PCT
{ POINT_RESIST_WARRIOR, }, // 78 무사에게 저항 APPLY_RESIST_WARRIOR
{ POINT_RESIST_ASSASSIN, }, // 79 자객에게 저항 APPLY_RESIST_ASSASSIN
{ POINT_RESIST_SURA, }, // 80 수라에게 저항 APPLY_RESIST_SURA
{ POINT_RESIST_SHAMAN, }, // 81 무당에게 저항 APPLY_RESIST_SHAMAN
{ POINT_ENERGY }, // 82 기력
{ POINT_DEF_GRADE }, // 83 방어력. DEF_GRADE_BONUS는 클라에서 두배로 보여지는 의도된 버그(...)가 있다.
{ POINT_COSTUME_ATTR_BONUS }, // 84 코스튬에 붙은 속성에 대해서만 보너스를 주는 기력
{ POINT_MAGIC_ATT_BONUS_PER }, // 85 마법 공격력 +x%
{ POINT_MELEE_MAGIC_ATT_BONUS_PER }, // 86 APPLY_MELEE_MAGIC_ATTBONUS_PER
{ POINT_RESIST_ICE, }, // APPLY_RESIST_ICE, 87
{ POINT_RESIST_EARTH, }, // APPLY_RESIST_EARTH, 88
{ POINT_RESIST_DARK, }, // APPLY_RESIST_DARK, 89
{ POINT_RESIST_CRITICAL, }, // APPLY_ANTI_CRITICAL_PCT, 90
{ POINT_RESIST_PENETRATE, }, // APPLY_ANTI_PENETRATE_PCT, 91
#ifdef ENABLE_WOLFMAN_CHARACTER
{ POINT_BLEEDING_REDUCE, }, // APPLY_BLEEDING_REDUCE, 92
{ POINT_BLEEDING_PCT, }, // APPLY_BLEEDING_PCT, 93
{ POINT_ATTBONUS_WOLFMAN, }, // APPLY_ATTBONUS_WOLFMAN, 94 수인족에게 강함
{ POINT_RESIST_WOLFMAN, }, // APPLY_RESIST_WOLFMAN, 95 수인족에게 저항
{ POINT_RESIST_CLAW, }, // APPLY_RESIST_CLAW, 96 CLAW에게 저항
#else
{ POINT_NONE, }, // APPLY_BLEEDING_REDUCE, 92
{ POINT_NONE, }, // APPLY_BLEEDING_PCT, 93
{ POINT_NONE, }, // APPLY_ATTBONUS_WOLFMAN, 94 수인족에게 강함
{ POINT_NONE, }, // APPLY_RESIST_WOLFMAN, 95 수인족에게 저항
{ POINT_NONE, }, // APPLY_RESIST_CLAW, 96 CLAW에게 저항
#endif
#ifdef ENABLE_MAGIC_REDUCTION_SYSTEM
{ POINT_RESIST_MAGIC_REDUCTION, }, // APPLY_RESIST_MAGIC_REDUCTION,98
#else
{ POINT_NONE, }, // APPLY_RESIST_MAGIC_REDUCTION,98
#endif
#ifdef ELEMENT_NEW_BONUSES
{POINT_ATTBONUS_ELEC,},
{POINT_ATTBONUS_FIRE,},
{POINT_ATTBONUS_ICE,},
{POINT_ATTBONUS_WIND,},
{POINT_ATTBONUS_EARTH,},
{POINT_ATTBONUS_DARK,},
{POINT_ATTBONUS_PATRON,},
{POINT_ATTBONUS_METINN,},
#endif
};
const int aiItemMagicAttributePercentHigh[ITEM_ATTRIBUTE_MAX_LEVEL] =
{
//25, 25, 40, 8, 2,
30, 40, 20, 8, 2
};
const int aiItemMagicAttributePercentLow[ITEM_ATTRIBUTE_MAX_LEVEL] =
{
//45, 25, 20, 10, 0,
50, 40, 10, 0, 0
};
// ADD_ITEM_ATTRIBUTE
const int aiItemAttributeAddPercent[ITEM_ATTRIBUTE_MAX_NUM] =
{
100, 80, 60, 50, 30, 0, 0,
};
// END_OF_ADD_ITEM_ATTRIBUTE
const int aiExpLossPercents[PLAYER_EXP_TABLE_MAX + 1] =
{
0,
5, 5, 5, 5, 5, 5, 5, 5, 5, 4, // 1 - 10
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 11 - 20
4, 4, 4, 4, 4, 4, 4, 3, 3, 3, // 21 - 30
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 31 - 40
3, 3, 3, 3, 2, 2, 2, 2, 2, 2, // 41 - 50
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 51 - 60
2, 2, 1, 1, 1, 1, 1, 1, 1, 1, // 61 - 70
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 71 - 80
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 81 - 90
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 91 - 100
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 101 - 110
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 111 - 120
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 121 - 130
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 131 - 140
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 141 - 150
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 151 - 160
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 161 - 170
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 171 - 180
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 181 - 190
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 191 - 200
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 201 - 210
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 211 - 220
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 221 - 230
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 231 - 240
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 241 - 250
};
const int aiSkillBookCountForLevelUp[10] =
{
3, 3, 3, 3, 3, 4, 4, 5, 5, 6
};
// ADD_GRANDMASTER_SKILL
const int aiGrandMasterSkillBookCountForLevelUp[10] =
{
3, 3, 5, 5, 7, 7, 10, 10, 10, 20,
};
const int aiGrandMasterSkillBookMinCount[10] =
{
// 1, 1, 3, 5, 10, 15, 20, 30, 40, 50,
// 3, 3, 5, 5, 10, 10, 15, 15, 20, 30
1, 1, 1, 2, 2, 3, 3, 4, 5, 6
};
const int aiGrandMasterSkillBookMaxCount[10] =
{
// 6, 15, 30, 45, 60, 80, 100, 120, 160, 200,
// 6, 10, 15, 20, 30, 40, 50, 60, 70, 80
5, 7, 9, 11, 13, 15, 20, 25, 30, 35
};
// END_OF_ADD_GRANDMASTER_SKILL
const int CHN_aiPartyBonusExpPercentByMemberCount[9] =
{
0, 0, 12, 18, 26, 40, 53, 70, 100
};
// UPGRADE_PARTY_BONUS
const int KOR_aiPartyBonusExpPercentByMemberCount[9] =
{
0,
0,
30, // 66% * 2 - 100
60, // 53% * 3 - 100
75, // 44% * 4 - 100
90, // 38% * 5 - 100
105, // 34% * 6 - 100
110, // 30% * 7 - 100
140, // 30% * 8 - 100
};
const int KOR_aiUniqueItemPartyBonusExpPercentByMemberCount[9] =
{
0,
0,
15*2,
14*3,
13*4,
12*5,
11*6,
10*7,
10*8,
};
// END_OF_UPGRADE_PARTY_BONUS
const int * aiChainLightningCountBySkillLevel = NULL;
const int aiChainLightningCountBySkillLevel_euckr[SKILL_MAX_LEVEL+1] =
{
0, // 0
2, // 1
2, // 2
2, // 3
2, // 4
2, // 5
2, // 6
2, // 7
2, // 8
3, // 9
3, // 10
3, // 11
3, // 12
3, // 13
3, // 14
3, // 15
3, // 16
3, // 17
3, // 18
4, // 19
4, // 20
4, // 21
4, // 22
4, // 23
5, // 24
5, // 25
5, // 26
5, // 27
5, // 28
5, // 29
5, // 30
5, // 31
5, // 32
5, // 33
5, // 34
5, // 35
5, // 36
5, // 37
5, // 38
5, // 39
5, // 40
};
const SStoneDropInfo aStoneDrop[STONE_INFO_MAX_NUM] =
{
// mob pct {+0 +1 +2 +3 +4}
{8001, 60, {30, 30, 30, 9, 1} },
{8002, 60, {30, 30, 30, 9, 1} },
{8003, 60, {30, 30, 30, 9, 1} },
{8004, 60, {30, 30, 30, 9, 1} },
{8005, 60, {30, 30, 30, 9, 1} },
{8006, 60, {28, 29, 31, 11, 1} },
{8007, 60, {24, 29, 32, 13, 2} },
{8008, 60, {22, 28, 33, 15, 2} },
{8009, 60, {21, 27, 33, 17, 2} },
{8010, 60, {18, 26, 34, 20, 2} },
{8011, 60, {14, 26, 35, 22, 3} },
{8012, 60, {10, 26, 37, 24, 3} },
{8013, 60, {2, 26, 40, 29, 3} },
{8014, 60, {0, 26, 41, 30, 3} },
{8024, 60, {0, 26, 41, 30, 3} },
{8025, 60, {0, 26, 41, 30, 3} },
{8026, 60, {0, 26, 41, 30, 3} },
{8027, 60, {0, 26, 41, 30, 3} },
{8051, 60, {0, 26, 41, 30, 3} },
{8052, 60, {0, 26, 41, 30, 3} },
{8053, 60, {0, 26, 41, 30, 3} },
{8054, 60, {0, 26, 41, 30, 3} },
{8055, 60, {0, 26, 41, 30, 3} },
{8056, 60, {0, 26, 41, 30, 3} },
{8057, 60, {0, 26, 41, 30, 3} },
{8058, 60, {0, 26, 41, 30, 3} },
{8059, 60, {0, 26, 41, 30, 3} },
{8061, 60, {0, 26, 41, 30, 3} },
};
const char * c_apszEmpireNames[EMPIRE_MAX_NUM] =
{
"전제국",
"신수국",
"천조국",
"진노국"
};
const char * c_apszPrivNames[MAX_PRIV_NUM] =
{
"",
"아이템이 나올 확률",
"돈이 나올 확률",
"돈 대박이 나올 확률",
"경험치 배율",
};
const int aiPolymorphPowerByLevel[SKILL_MAX_LEVEL + 1] =
{
10, // 1
11, // 2
11, // 3
12, // 4
13, // 5
13, // 6
14, // 7
15, // 8
16, // 9
17, // 10
18, // 11
19, // 12
20, // 13
22, // 14
23, // 15
24, // 16
26, // 17
27, // 18
29, // 19
31, // 20
33, // 21
35, // 22
37, // 23
39, // 24
41, // 25
44, // 26
46, // 27
49, // 28
52, // 29
55, // 30
59, // 31
62, // 32
66, // 33
70, // 34
74, // 35
79, // 36
84, // 37
89, // 38
94, // 39
100, // 40
};
TGuildWarInfo KOR_aGuildWarInfo[GUILD_WAR_TYPE_MAX_NUM] =
/*
{
long lMapIndex;
int iWarPrice;
int iWinnerPotionRewardPctToWinner;
int iLoserPotionRewardPctToWinner;
int iInitialScore;
int iEndScore;
};
*/
{
{ 0, 0, 0, 0, 0, 0 },
{ 110, 0, 100, 50, 0, 100 },
{ 111, 0, 100, 50, 0, 10 },
};
//
// 악세서리 소켓용 수치들
//
// 다이아몬드로 소켓을 추가할 때 확률
const int aiAccessorySocketAddPct[ITEM_ACCESSORY_SOCKET_MAX_NUM] =
{
50, 50, 50
};
// 악세서리 수치 값의 몇%만큼의 성능을 추가하는지
const int aiAccessorySocketEffectivePct[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1] =
{
0, 10, 20, 40
};
// 소켓 지속시간 24, 12, 6
const int aiAccessorySocketDegradeTime[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1] =
{
0, 3600 * 24, 3600 * 12, 3600 * 6
};
// 소켓 장착 성공률
const int aiAccessorySocketPutPct[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1] =
{
90, 80, 70, 0
};
// END_OF_ACCESSORY_REFINE
#include "../../common/length.h"
// from import_item_proto.c
typedef struct SValueName
{
const char * c_pszName;
long lValue;
} TValueName;
TValueName c_aApplyTypeNames[] =
{
{ "STR", APPLY_STR },
{ "DEX", APPLY_DEX },
{ "CON", APPLY_CON },
{ "INT", APPLY_INT },
{ "MAX_HP", APPLY_MAX_HP },
{ "MAX_SP", APPLY_MAX_SP },
{ "MAX_STAMINA", APPLY_MAX_STAMINA },
{ "POISON_REDUCE", APPLY_POISON_REDUCE },
{ "EXP_DOUBLE_BONUS", APPLY_EXP_DOUBLE_BONUS },
{ "GOLD_DOUBLE_BONUS", APPLY_GOLD_DOUBLE_BONUS },
{ "ITEM_DROP_BONUS", APPLY_ITEM_DROP_BONUS },
{ "HP_REGEN", APPLY_HP_REGEN },
{ "SP_REGEN", APPLY_SP_REGEN },
{ "ATTACK_SPEED", APPLY_ATT_SPEED },
{ "MOVE_SPEED", APPLY_MOV_SPEED },
{ "CAST_SPEED", APPLY_CAST_SPEED },
{ "ATT_BONUS", APPLY_ATT_GRADE_BONUS },
{ "DEF_BONUS", APPLY_DEF_GRADE_BONUS },
{ "MAGIC_ATT_GRADE",APPLY_MAGIC_ATT_GRADE },
{ "MAGIC_DEF_GRADE",APPLY_MAGIC_DEF_GRADE },
{ "SKILL", APPLY_SKILL },
{ "ATTBONUS_ANIMAL",APPLY_ATTBONUS_ANIMAL },
{ "ATTBONUS_UNDEAD",APPLY_ATTBONUS_UNDEAD },
{ "ATTBONUS_DEVIL", APPLY_ATTBONUS_DEVIL },
{ "ATTBONUS_HUMAN", APPLY_ATTBONUS_HUMAN },
{ "ADD_BOW_DISTANCE",APPLY_BOW_DISTANCE },
{ "DODGE", APPLY_DODGE },
{ "BLOCK", APPLY_BLOCK },
{ "RESIST_SWORD", APPLY_RESIST_SWORD },
{ "RESIST_TWOHAND", APPLY_RESIST_TWOHAND },
{ "RESIST_DAGGER", APPLY_RESIST_DAGGER },
{ "RESIST_BELL", APPLY_RESIST_BELL },
{ "RESIST_FAN", APPLY_RESIST_FAN },
{ "RESIST_BOW", APPLY_RESIST_BOW },
{ "RESIST_FIRE", APPLY_RESIST_FIRE },
{ "RESIST_ELEC", APPLY_RESIST_ELEC },
{ "RESIST_MAGIC", APPLY_RESIST_MAGIC },
{ "RESIST_WIND", APPLY_RESIST_WIND },
{ "REFLECT_MELEE", APPLY_REFLECT_MELEE },
{ "REFLECT_CURSE", APPLY_REFLECT_CURSE },
{ "RESIST_ICE", APPLY_RESIST_ICE },
{ "RESIST_EARTH", APPLY_RESIST_EARTH },
{ "RESIST_DARK", APPLY_RESIST_DARK },
{ "RESIST_CRITICAL", APPLY_ANTI_CRITICAL_PCT },
{ "RESIST_PENETRATE", APPLY_ANTI_PENETRATE_PCT },
{ "POISON", APPLY_POISON_PCT },
{ "SLOW", APPLY_SLOW_PCT },
{ "STUN", APPLY_STUN_PCT },
{ "STEAL_HP", APPLY_STEAL_HP },
{ "STEAL_SP", APPLY_STEAL_SP },
{ "MANA_BURN_PCT", APPLY_MANA_BURN_PCT },
{ "CRITICAL", APPLY_CRITICAL_PCT },
{ "PENETRATE", APPLY_PENETRATE_PCT },
{ "KILL_SP_RECOVER",APPLY_KILL_SP_RECOVER },
{ "KILL_HP_RECOVER",APPLY_KILL_HP_RECOVER },
{ "PENETRATE_PCT", APPLY_PENETRATE_PCT },
{ "CRITICAL_PCT", APPLY_CRITICAL_PCT },
{ "POISON_PCT", APPLY_POISON_PCT },
{ "STUN_PCT", APPLY_STUN_PCT },
{ "ATT_BONUS_TO_WARRIOR", APPLY_ATTBONUS_WARRIOR },
{ "ATT_BONUS_TO_ASSASSIN", APPLY_ATTBONUS_ASSASSIN },
{ "ATT_BONUS_TO_SURA", APPLY_ATTBONUS_SURA },
{ "ATT_BONUS_TO_SHAMAN", APPLY_ATTBONUS_SHAMAN },
{ "ATT_BONUS_TO_MONSTER", APPLY_ATTBONUS_MONSTER },
{ "ATT_BONUS_TO_MOB", APPLY_ATTBONUS_MONSTER },
{ "MALL_ATTBONUS", APPLY_MALL_ATTBONUS },
{ "MALL_EXPBONUS", APPLY_MALL_EXPBONUS },
{ "MALL_DEFBONUS", APPLY_MALL_DEFBONUS },
{ "MALL_ITEMBONUS", APPLY_MALL_ITEMBONUS },
{ "MALL_GOLDBONUS", APPLY_MALL_GOLDBONUS },
{ "MAX_HP_PCT", APPLY_MAX_HP_PCT },
{ "MAX_SP_PCT", APPLY_MAX_SP_PCT },
{ "SKILL_DAMAGE_BONUS", APPLY_SKILL_DAMAGE_BONUS },
{ "NORMAL_HIT_DAMAGE_BONUS",APPLY_NORMAL_HIT_DAMAGE_BONUS },
{ "SKILL_DEFEND_BONUS", APPLY_SKILL_DEFEND_BONUS },
{ "NORMAL_HIT_DEFEND_BONUS",APPLY_NORMAL_HIT_DEFEND_BONUS },
{ "PCBANG_EXP_BONUS", APPLY_PC_BANG_EXP_BONUS },
{ "PCBANG_DROP_BONUS", APPLY_PC_BANG_DROP_BONUS },
{ "RESIST_WARRIOR", APPLY_RESIST_WARRIOR},
{ "RESIST_ASSASSIN", APPLY_RESIST_ASSASSIN},
{ "RESIST_SURA", APPLY_RESIST_SURA},
{ "RESIST_SHAMAN", APPLY_RESIST_SHAMAN},
// by mhh game/affect.h 정의되어있음. INFINITE_AFFECT_DURATION = 0x1FFFFFFF
{ "INFINITE_AFFECT_DURATION", 0x1FFFFFFF },
{ "ENERGY", APPLY_ENERGY }, // 기력
{ "COSTUME_ATTR_BONUS", APPLY_COSTUME_ATTR_BONUS }, // 기력
{ "MAGIC_ATTBONUS_PER", APPLY_MAGIC_ATTBONUS_PER },
{ "MELEE_MAGIC_ATTBONUS_PER", APPLY_MELEE_MAGIC_ATTBONUS_PER },
#ifdef ENABLE_WOLFMAN_CHARACTER
{ "BLEEDING_REDUCE",APPLY_BLEEDING_REDUCE },
{ "BLEEDING_PCT",APPLY_BLEEDING_PCT },
{ "ATT_BONUS_TO_WOLFMAN",APPLY_ATTBONUS_WOLFMAN },
{ "RESIST_WOLFMAN",APPLY_RESIST_WOLFMAN },
{ "RESIST_CLAW",APPLY_RESIST_CLAW },
#endif
#ifdef ENABLE_MAGIC_REDUCTION_SYSTEM
{ "RESIST_MAGIC_REDUCTION",APPLY_RESIST_MAGIC_REDUCTION },
#endif
#ifdef ELEMENT_NEW_BONUSES
{"ATTBONUS_ELEC", APPLY_ATTBONUS_ELEC},
{"ATTBONUS_FIRE", APPLY_ATTBONUS_FIRE},
{"ATTBONUS_ICE", APPLY_ATTBONUS_ICE},
{"ATTBONUS_WIND", APPLY_ATTBONUS_WIND},
{"ATTBONUS_EARTH", APPLY_ATTBONUS_EARTH},
{"ATTBONUS_DARK", APPLY_ATTBONUS_DARK},
#endif
{ NULL, 0 }
};
// from import_item_proto.c
long FN_get_apply_type(const char *apply_type_string)
{
TValueName *value_name;
for (value_name = c_aApplyTypeNames; value_name->c_pszName; ++value_name)
{
if (0==strcasecmp(value_name->c_pszName, apply_type_string))
return value_name->lValue;
}
return 0;
}
[/CODE]