DWORD GET_ATTACK_SPEED(LPCHARACTER ch) { if (NULL == ch) return 1000; LPITEM item = ch->GetWear(WEAR_WEAPON); DWORD default_bonus = SPEEDHACK_LIMIT_BONUS; // 유두리 공속(기본 80) DWORD riding_bonus = 0; if (ch->IsRiding()) { // 뭔가를 탔으면 추가공속 50 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); // 단검의 경우 공속 2배 if (item && item->GetSubType() == WEAPON_DAGGER) real_speed /= 2; return real_speed; }
DWORD ani_attack_speed(LPCHARACTER ch) { DWORD speed = 1000; if (NULL == ch) return speed; LPITEM item = ch->GetWear(WEAR_WEAPON); if (NULL == item) return speed; if (ITEM_WEAPON != item->GetType()) return speed; int race = ch->GetRaceNum(); int weapon = item->GetSubType(); /* dev_log(LOG_DEB0, "%s : (race,weapon) = (%s,%s) POINT_ATT_SPEED = %d", ch->GetName(), FN_race_name(race), FN_weapon_type(weapon), ch->GetPoint(POINT_ATT_SPEED)); */ /* ЕхЗЪµрµе јТµеАЗ °жїм »пї¬Вь°ш°Э°ъ ЅВё¶ЅГ */ /* їА·щ°Ў ё№ѕЖ ЗСјХ°Л јУµµ·О »э°ўЗПАЪ */ if (weapon == WEAPON_TWO_HANDED) weapon = WEAPON_SWORD; return s_ANI.attack_speed(race, weapon); }
DWORD GET_ATTACK_SPEED(LPCHARACTER ch) { if (NULL == ch) return 1000; LPITEM item = ch->GetWear(WEAR_WEAPON); DWORD default_bonus = SPEEDHACK_LIMIT_BONUS; // АЇµОё® °шјУ(±вє» 80) DWORD riding_bonus = 0; if (ch->IsRiding()) { // №є°Ўё¦ ЕААёёй ГЯ°Ў°шјУ 50 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); // ґЬ°ЛАЗ °жїм °шјУ 2№и if (item && item->GetSubType() == WEAPON_DAGGER) real_speed /= 2; return real_speed; }
int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int & iRetDam) { //PROF_UNIT puHit("Hit"); 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); // 데미지 계산 //iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST)) / 100; 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; } //최종적인 데미지 보정. (2011년 2월 현재 대왕거미에게만 적용.) float attMul = pkAttacker->GetAttMul(); float tempIDam = iDam; iDam = attMul * tempIDam + 0.5f; iRetDam = iDam; //PROF_UNIT puDam("Dam"); if (pkVictim->Damage(pkAttacker, iDam, DAMAGE_TYPE_NORMAL)) return (BATTLE_DEAD); return (BATTLE_DAMAGE); }
DWORD ani_combo_speed(LPCHARACTER ch, BYTE combo) { LPITEM item = ch->GetWear(WEAR_WEAPON); if (NULL == item || combo > 8) return 1000; return s_ANI.attack_speed(ch->GetRaceNum(), item->GetSubType(), combo, ch->IsRiding()); }
void DSManager::RefreshDragonSoulState(LPCHARACTER ch) { if (NULL == ch) return ; for (int i = WEAR_MAX_NUM; i < WEAR_MAX_NUM + DS_SLOT_MAX * DRAGON_SOUL_DECK_MAX_NUM; i++) { LPITEM pItem = ch->GetWear(i); if (pItem != NULL) { if(IsActiveDragonSoul(pItem)) { return; } } } ch->DragonSoul_DeactivateAll(); }
// return false on error state bool CItem::EquipTo(LPCHARACTER ch, BYTE bWearCell) { if (!ch) { sys_err("EquipTo: nil character"); return false; } // ¿ëÈ¥¼® ½½·Ô index´Â WEAR_MAX_NUM º¸´Ù Å. if (IsDragonSoul()) { if (bWearCell < WEAR_MAX_NUM || bWearCell >= WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX) { sys_err("EquipTo: invalid dragon soul cell (this: #%d %s wearflag: %d cell: %d)", GetOriginalVnum(), GetName(), GetSubType(), bWearCell - WEAR_MAX_NUM); return false; } } else { if (bWearCell >= WEAR_MAX_NUM) { sys_err("EquipTo: invalid wear cell (this: #%d %s wearflag: %d cell: %d)", GetOriginalVnum(), GetName(), GetWearFlag(), bWearCell); return false; } } if (ch->GetWear(bWearCell)) { sys_err("EquipTo: item already exist (this: #%d %s cell: %d %s)", GetOriginalVnum(), GetName(), bWearCell, ch->GetWear(bWearCell)->GetName()); return false; } if (GetOwner()) RemoveFromCharacter(); ch->SetWear(bWearCell, this); // ¿©±â¼ ÆÐŶ ³ª°¨ m_pOwner = ch; m_bEquipped = true; m_wCell = INVENTORY_MAX_NUM + bWearCell; DWORD dwImmuneFlag = 0; for (int i = 0; i < WEAR_MAX_NUM; ++i) if (m_pOwner->GetWear(i)) SET_BIT(dwImmuneFlag, m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag); m_pOwner->SetImmuneFlag(dwImmuneFlag); if (IsDragonSoul()) { DSManager::instance().ActivateDragonSoul(this); } else { ModifyPoints(true); StartUniqueExpireEvent(); if (-1 != GetProto()->cLimitTimerBasedOnWearIndex) StartTimerBasedOnWearExpireEvent(); // ACCESSORY_REFINE StartAccessorySocketExpireEvent(); // END_OF_ACCESSORY_REFINE } ch->BuffOnAttr_AddBuffsFromItem(this); m_pOwner->ComputeBattlePoints(); m_pOwner->UpdatePacket(); Save(); return (true); }
int CItem::FindEquipCell(LPCHARACTER ch, int iCandidateCell) { // ÄÚ½ºÃõ ¾ÆÀÌÅÛ(ITEM_COSTUME)Àº WearFlag ¾ø¾îµµ µÊ. (sub typeÀ¸·Î Âø¿ëÀ§Ä¡ ±¸ºÐ. ±ÍÂú°Ô ¶Ç wear flag ÁÙ ÇÊ¿ä°¡ ÀÖ³ª..) // ¿ëÈ¥¼®(ITEM_DS, ITEM_SPECIAL_DS)µµ SUB_TYPEÀ¸·Î ±¸ºÐ. ½Å±Ô ¹ÝÁö, º§Æ®´Â ITEM_TYPEÀ¸·Î ±¸ºÐ -_- if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType()) return -1; // ¿ëÈ¥¼® ½½·ÔÀ» WEAR·Î ó¸®ÇÒ ¼ö°¡ ¾ø¾î¼(WEAR´Â ÃÖ´ë 32°³±îÁö °¡´ÉÇѵ¥ ¿ëÈ¥¼®À» Ãß°¡Çϸé 32°¡ ³Ñ´Â´Ù.) // Àκ¥Å丮ÀÇ Æ¯Á¤ À§Ä¡((INVENTORY_MAX_NUM + WEAR_MAX_NUM)ºÎÅÍ (INVENTORY_MAX_NUM + WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX - 1)±îÁö)¸¦ // ¿ëÈ¥¼® ½½·ÔÀ¸·Î Á¤ÇÔ. // return ÇÒ ¶§¿¡, INVENTORY_MAX_NUMÀ» »« ÀÌÀ¯´Â, // º»·¡ WearCellÀÌ INVENTORY_MAX_NUM¸¦ »©°í return Çϱ⠶§¹®. if (GetType() == ITEM_DS || GetType() == ITEM_SPECIAL_DS) { if (iCandidateCell < 0) { return WEAR_MAX_NUM + GetSubType(); } else { for (int i = 0; i < DRAGON_SOUL_DECK_MAX_NUM; i++) { if (WEAR_MAX_NUM + i * DS_SLOT_MAX + GetSubType() == iCandidateCell) { return iCandidateCell; } } return -1; } } else if (GetType() == ITEM_COSTUME) { if (GetSubType() == COSTUME_BODY) return WEAR_COSTUME_BODY; else if (GetSubType() == COSTUME_HAIR) return WEAR_COSTUME_HAIR; } else if (GetType() == ITEM_RING) { if (ch->GetWear(WEAR_RING1)) return WEAR_RING2; else return WEAR_RING1; } else if (GetType() == ITEM_BELT) return WEAR_BELT; else if (GetWearFlag() & WEARABLE_BODY) return WEAR_BODY; else if (GetWearFlag() & WEARABLE_HEAD) return WEAR_HEAD; else if (GetWearFlag() & WEARABLE_FOOTS) return WEAR_FOOTS; else if (GetWearFlag() & WEARABLE_WRIST) return WEAR_WRIST; else if (GetWearFlag() & WEARABLE_WEAPON) return WEAR_WEAPON; else if (GetWearFlag() & WEARABLE_SHIELD) return WEAR_SHIELD; else if (GetWearFlag() & WEARABLE_NECK) return WEAR_NECK; else if (GetWearFlag() & WEARABLE_EAR) return WEAR_EAR; else if (GetWearFlag() & WEARABLE_ARROW) return WEAR_ARROW; else if (GetWearFlag() & WEARABLE_UNIQUE) { if (ch->GetWear(WEAR_UNIQUE1)) return WEAR_UNIQUE2; else return WEAR_UNIQUE1; } // ¼öÁý Äù½ºÆ®¸¦ À§ÇÑ ¾ÆÀÌÅÛÀÌ ¹ÚÈ÷´Â°÷À¸·Î Çѹø ¹ÚÈ÷¸é Àý´ë –E¼ö ¾ø´Ù. else if (GetWearFlag() & WEARABLE_ABILITY) { if (!ch->GetWear(WEAR_ABILITY1)) { return WEAR_ABILITY1; } else if (!ch->GetWear(WEAR_ABILITY2)) { return WEAR_ABILITY2; } else if (!ch->GetWear(WEAR_ABILITY3)) { return WEAR_ABILITY3; } else if (!ch->GetWear(WEAR_ABILITY4)) { return WEAR_ABILITY4; } else if (!ch->GetWear(WEAR_ABILITY5)) { return WEAR_ABILITY5; } else if (!ch->GetWear(WEAR_ABILITY6)) { return WEAR_ABILITY6; } else if (!ch->GetWear(WEAR_ABILITY7)) { return WEAR_ABILITY7; } else if (!ch->GetWear(WEAR_ABILITY8)) { return WEAR_ABILITY8; } else { return -1; } } return -1; }
int CItem::FindEquipCell(LPCHARACTER ch, int iCandidateCell) { // ДЪЅєГх ѕЖАМЕЫ(ITEM_COSTUME)Ає WearFlag ѕшѕоµµ µК. (sub typeАё·О ВшїлА§ДЎ ±ёєР. ±НВъ°Ф ¶З wear flag БЩ ЗКїд°Ў АЦіЄ..) // їлИҐј®(ITEM_DS, ITEM_SPECIAL_DS)µµ SUB_TYPEАё·О ±ёєР. ЅЕ±Ф №ЭБц, є§Ж®ґВ ITEM_TYPEАё·О ±ёєР -_- if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType()) return -1; // їлИҐј® ЅЅ·ФА» WEAR·О Гіё®ЗТ јц°Ў ѕшѕој(WEARґВ ГЦґл 32°і±оБц °ЎґЙЗСµҐ їлИҐј®А» ГЯ°ЎЗПёй 32°Ў іСґВґЩ.) // АОєҐЕдё®АЗ ЖЇБ¤ А§ДЎ((INVENTORY_MAX_NUM + WEAR_MAX_NUM)єОЕН (INVENTORY_MAX_NUM + WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX - 1)±оБц)ё¦ // їлИҐј® ЅЅ·ФАё·О Б¤ЗФ. // return ЗТ ¶§їЎ, INVENTORY_MAX_NUMА» »« АМАЇґВ, // є»·Ў WearCellАМ INVENTORY_MAX_NUMё¦ »©°н return ЗП±в ¶§№®. if (GetType() == ITEM_DS || GetType() == ITEM_SPECIAL_DS) { if (iCandidateCell < 0) { return WEAR_MAX_NUM + GetSubType(); } else { for (int i = 0; i < DRAGON_SOUL_DECK_MAX_NUM; i++) { if (WEAR_MAX_NUM + i * DS_SLOT_MAX + GetSubType() == iCandidateCell) { return iCandidateCell; } } return -1; } } else if (GetType() == ITEM_COSTUME) { if (GetSubType() == COSTUME_BODY) return WEAR_COSTUME_BODY; else if (GetSubType() == COSTUME_HAIR) return WEAR_COSTUME_HAIR; } else if (GetType() == ITEM_RING) { if (ch->GetWear(WEAR_RING1)) return WEAR_RING2; else return WEAR_RING1; } else if (GetType() == ITEM_BELT) return WEAR_BELT; else if (GetWearFlag() & WEARABLE_BODY) return WEAR_BODY; else if (GetWearFlag() & WEARABLE_HEAD) return WEAR_HEAD; else if (GetWearFlag() & WEARABLE_FOOTS) return WEAR_FOOTS; else if (GetWearFlag() & WEARABLE_WRIST) return WEAR_WRIST; else if (GetWearFlag() & WEARABLE_WEAPON) return WEAR_WEAPON; else if (GetWearFlag() & WEARABLE_SHIELD) return WEAR_SHIELD; else if (GetWearFlag() & WEARABLE_NECK) return WEAR_NECK; else if (GetWearFlag() & WEARABLE_EAR) return WEAR_EAR; else if (GetWearFlag() & WEARABLE_ARROW) return WEAR_ARROW; else if (GetWearFlag() & WEARABLE_UNIQUE) { if (ch->GetWear(WEAR_UNIQUE1)) return WEAR_UNIQUE2; else return WEAR_UNIQUE1; } // јцБэ ДщЅєЖ®ё¦ А§ЗС ѕЖАМЕЫАМ №ЪИчґВ°чАё·О ЗС№ш №ЪИчёй Аэґл –Eјц ѕшґЩ. else if (GetWearFlag() & WEARABLE_ABILITY) { if (!ch->GetWear(WEAR_ABILITY1)) { return WEAR_ABILITY1; } else if (!ch->GetWear(WEAR_ABILITY2)) { return WEAR_ABILITY2; } else if (!ch->GetWear(WEAR_ABILITY3)) { return WEAR_ABILITY3; } else if (!ch->GetWear(WEAR_ABILITY4)) { return WEAR_ABILITY4; } else if (!ch->GetWear(WEAR_ABILITY5)) { return WEAR_ABILITY5; } else if (!ch->GetWear(WEAR_ABILITY6)) { return WEAR_ABILITY6; } else if (!ch->GetWear(WEAR_ABILITY7)) { return WEAR_ABILITY7; } else if (!ch->GetWear(WEAR_ABILITY8)) { return WEAR_ABILITY8; } else { return -1; } } return -1; }
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: 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()) { // MONKEY_ROD_ATTACK_BUG_FIX Item_GetDamage(pWeapon, &iDamMin, &iDamMax); // END_OF_MONKEY_ROD_ATTACK_BUG_FIX 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) { // MONKEY_ROD_ATTACK_BUG_FIX Item_GetDamage(pWeapon, &iDamMin, &iDamMax); // END_OF_MONKEY_ROD_ATTACK_BUG_FIX } else if (pkAttacker->IsNPC()) { iDamMin = pkAttacker->GetMobDamageMin(); iDamMax = pkAttacker->GetMobDamageMax(); } iDam = number(iDamMin, iDamMax) * 2; // TESTSERVER_SHOW_ATTACKINFO DEBUG_iDamCur = iDam; // END_OF_TESTSERVER_SHOW_ATTACKINFO // int iAtk = 0; // level must be ignored when multiply by fAR, so subtract it before calculation. iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2); iAtk = (int) (iAtk * fAR); iAtk += pkAttacker->GetLevel() * 2; // and add again if (pWeapon) { iAtk += pWeapon->GetValue(5) * 2; // 2004.11.12.myevan.TESTSERVER_SHOW_ATTACKINFO DEBUG_iDamBonus = pWeapon->GetValue(5) * 2; /////////////////////////////////////////////// } iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS); // party attacker role 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()); }