2022-03-05 12:44:06 +02:00
# include "stdafx.h"
# include "utils.h"
# include "config.h"
# include "desc.h"
# include "desc_manager.h"
# include "char_manager.h"
# include "item.h"
# include "item_manager.h"
# include "mob_manager.h"
# include "battle.h"
# include "pvp.h"
# include "skill.h"
# include "start_position.h"
# include "profiler.h"
# include "cmd.h"
# include "dungeon.h"
# include "log.h"
# include "unique_item.h"
# include "priv_manager.h"
# include "db.h"
# include "vector.h"
# include "marriage.h"
# include "arena.h"
# include "regen.h"
# include "monarch.h"
# include "exchange.h"
# include "shop_manager.h"
# include "castle.h"
# include "dev_log.h"
# include "ani.h"
# include "BattleArena.h"
# include "packet.h"
# include "party.h"
# include "affect.h"
# include "guild.h"
# include "guild_manager.h"
# include "questmanager.h"
# include "questlua.h"
# include "threeway_war.h"
# include "BlueDragon.h"
# include "DragonLair.h"
DWORD AdjustExpByLevel ( const LPCHARACTER ch , const DWORD exp )
{
if ( PLAYER_EXP_TABLE_MAX < ch - > GetLevel ( ) )
{
double ret = 0.95 ;
double factor = 0.1 ;
for ( ssize_t i = 0 ; i < ch - > GetLevel ( ) - 100 ; + + i )
{
if ( ( i % 10 ) = = 0 )
factor / = 2.0 ;
ret * = 1.0 - factor ;
}
ret = ret * static_cast < double > ( exp ) ;
if ( ret < 1.0 )
return 1 ;
return static_cast < DWORD > ( ret ) ;
}
return exp ;
}
bool CHARACTER : : CanBeginFight ( ) const
{
if ( ! CanMove ( ) )
return false ;
return m_pointsInstant . position = = POS_STANDING & & ! IsDead ( ) & & ! IsStun ( ) ;
}
void CHARACTER : : BeginFight ( LPCHARACTER pkVictim )
{
SetVictim ( pkVictim ) ;
SetPosition ( POS_FIGHTING ) ;
SetNextStatePulse ( 1 ) ;
}
bool CHARACTER : : CanFight ( ) const
{
return m_pointsInstant . position > = POS_FIGHTING ? true : false ;
}
void CHARACTER : : CreateFly ( BYTE bType , LPCHARACTER pkVictim )
{
TPacketGCCreateFly packFly ;
packFly . bHeader = HEADER_GC_CREATE_FLY ;
packFly . bType = bType ;
packFly . dwStartVID = GetVID ( ) ;
packFly . dwEndVID = pkVictim - > GetVID ( ) ;
PacketAround ( & packFly , sizeof ( TPacketGCCreateFly ) ) ;
}
void CHARACTER : : DistributeSP ( LPCHARACTER pkKiller , int iMethod )
{
if ( pkKiller - > GetSP ( ) > = pkKiller - > GetMaxSP ( ) )
return ;
bool bAttacking = ( get_dword_time ( ) - GetLastAttackTime ( ) ) < 3000 ;
bool bMoving = ( get_dword_time ( ) - GetLastMoveTime ( ) ) < 3000 ;
if ( iMethod = = 1 )
{
int num = number ( 0 , 3 ) ;
if ( ! num )
{
int iLvDelta = GetLevel ( ) - pkKiller - > GetLevel ( ) ;
int iAmount = 0 ;
if ( iLvDelta > = 5 )
iAmount = 10 ;
else if ( iLvDelta > = 0 )
iAmount = 6 ;
else if ( iLvDelta > = - 3 )
iAmount = 2 ;
if ( iAmount ! = 0 )
{
iAmount + = ( iAmount * pkKiller - > GetPoint ( POINT_SP_REGEN ) ) / 100 ;
if ( iAmount > = 11 )
CreateFly ( FLY_SP_BIG , pkKiller ) ;
else if ( iAmount > = 7 )
CreateFly ( FLY_SP_MEDIUM , pkKiller ) ;
else
CreateFly ( FLY_SP_SMALL , pkKiller ) ;
pkKiller - > PointChange ( POINT_SP , iAmount ) ;
}
}
}
else
{
if ( pkKiller - > GetJob ( ) = = JOB_SHAMAN | | ( pkKiller - > GetJob ( ) = = JOB_SURA & & pkKiller - > GetSkillGroup ( ) = = 2 ) )
{
int iAmount ;
if ( bAttacking )
iAmount = 2 + GetMaxSP ( ) / 100 ;
else if ( bMoving )
iAmount = 3 + GetMaxSP ( ) * 2 / 100 ;
else
iAmount = 10 + GetMaxSP ( ) * 3 / 100 ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
iAmount + = ( iAmount * pkKiller - > GetPoint ( POINT_SP_REGEN ) ) / 100 ;
pkKiller - > PointChange ( POINT_SP , iAmount ) ;
}
else
{
int iAmount ;
if ( bAttacking )
iAmount = 2 + pkKiller - > GetMaxSP ( ) / 200 ;
else if ( bMoving )
iAmount = 2 + pkKiller - > GetMaxSP ( ) / 100 ;
else
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
if ( pkKiller - > GetHP ( ) < pkKiller - > GetMaxHP ( ) )
iAmount = 2 + ( pkKiller - > GetMaxSP ( ) / 100 ) ; // <20> <> <20> <> <20> <> á<EFBFBD> <C3A1> <EFBFBD> <EFBFBD>
else
iAmount = 9 + ( pkKiller - > GetMaxSP ( ) / 100 ) ; // <20> ⺻
}
iAmount + = ( iAmount * pkKiller - > GetPoint ( POINT_SP_REGEN ) ) / 100 ;
pkKiller - > PointChange ( POINT_SP , iAmount ) ;
}
}
}
bool CHARACTER : : Attack ( LPCHARACTER pkVictim , BYTE bType )
{
if ( test_server )
sys_log ( 0 , " [TEST_SERVER] Attack : %s type %d, MobBattleType %d " , GetName ( ) , bType , ! GetMobBattleType ( ) ? 0 : GetMobAttackRange ( ) ) ;
//PROF_UNIT puAttack("Attack");
if ( ! CanMove ( ) )
return false ;
// CASTLE
if ( IS_CASTLE_MAP ( GetMapIndex ( ) ) & & false = = castle_can_attack ( this , pkVictim ) )
return false ;
// CASTLE
DWORD dwCurrentTime = get_dword_time ( ) ;
if ( IsPC ( ) )
{
if ( IS_SPEED_HACK ( this , pkVictim , dwCurrentTime ) )
return false ;
if ( bType = = 0 & & dwCurrentTime < GetSkipComboAttackByTime ( ) )
return false ;
}
else
{
MonsterChat ( MONSTER_CHAT_ATTACK ) ;
}
pkVictim - > SetSyncOwner ( this ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( this ) ;
int iRet ;
if ( bType = = 0 )
{
//
// <20> Ϲ <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
//
switch ( GetMobBattleType ( ) )
{
case BATTLE_TYPE_MELEE :
case BATTLE_TYPE_POWER :
case BATTLE_TYPE_TANKER :
case BATTLE_TYPE_SUPER_POWER :
case BATTLE_TYPE_SUPER_TANKER :
iRet = battle_melee_attack ( this , pkVictim ) ;
break ;
case BATTLE_TYPE_RANGE :
FlyTarget ( pkVictim - > GetVID ( ) , pkVictim - > GetX ( ) , pkVictim - > GetY ( ) , HEADER_CG_FLY_TARGETING ) ;
iRet = Shoot ( 0 ) ? BATTLE_DAMAGE : BATTLE_NONE ;
break ;
case BATTLE_TYPE_MAGIC :
FlyTarget ( pkVictim - > GetVID ( ) , pkVictim - > GetX ( ) , pkVictim - > GetY ( ) , HEADER_CG_FLY_TARGETING ) ;
iRet = Shoot ( 1 ) ? BATTLE_DAMAGE : BATTLE_NONE ;
break ;
default :
sys_err ( " Unhandled battle type %d " , GetMobBattleType ( ) ) ;
iRet = BATTLE_NONE ;
break ;
}
}
else
{
if ( IsPC ( ) = = true )
{
if ( dwCurrentTime - m_dwLastSkillTime > 1500 )
{
sys_log ( 1 , " HACK: Too long skill using term. Name(%s) PID(%u) delta(%u) " ,
GetName ( ) , GetPlayerID ( ) , ( dwCurrentTime - m_dwLastSkillTime ) ) ;
return false ;
}
}
sys_log ( 1 , " Attack call ComputeSkill %d %s " , bType , pkVictim ? pkVictim - > GetName ( ) : " " ) ;
iRet = ComputeSkill ( bType , pkVictim ) ;
}
//if (test_server && IsPC())
// sys_log(0, "%s Attack %s type %u ret %d", GetName(), pkVictim->GetName(), bType, iRet);
if ( iRet = = BATTLE_DAMAGE | | iRet = = BATTLE_DEAD )
{
OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
// only pc sets victim null. For npc, state machine will reset this.
if ( BATTLE_DEAD = = iRet & & IsPC ( ) )
SetVictim ( NULL ) ;
return true ;
}
return false ;
}
void CHARACTER : : DeathPenalty ( BYTE bTown )
{
sys_log ( 1 , " DEATH_PERNALY_CHECK(%s) town(%d) " , GetName ( ) , bTown ) ;
Cube_close ( this ) ;
if ( CBattleArena : : instance ( ) . IsBattleArenaMap ( GetMapIndex ( ) ) = = true )
{
return ;
}
if ( GetLevel ( ) < 10 )
{
sys_log ( 0 , " NO_DEATH_PENALTY_LESS_LV10(%s) " , GetName ( ) ) ;
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <EFBFBD> <C8A3> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʾ ҽ <CABE> <D2BD> ϴ<EFBFBD> ." ) ) ;
return ;
}
if ( number ( 0 , 2 ) )
{
sys_log ( 0 , " NO_DEATH_PENALTY_LUCK(%s) " , GetName ( ) ) ;
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <EFBFBD> <C8A3> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʾ ҽ <CABE> <D2BD> ϴ<EFBFBD> ." ) ) ;
return ;
}
if ( IS_SET ( m_pointsInstant . instant_flag , INSTANT_FLAG_DEATH_PENALTY ) )
{
REMOVE_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_DEATH_PENALTY ) ;
// NO_DEATH_PENALTY_BUG_FIX
if ( LC_IsYMIR ( ) ) // õ<> <C3B5> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> üũ<C3BC> Ѵ <EFBFBD> .
{
if ( FindAffect ( AFFECT_NO_DEATH_PENALTY ) )
{
sys_log ( 0 , " NO_DEATH_PENALTY_AFFECT(%s) " , GetName ( ) ) ;
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <EFBFBD> <C8A3> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʾ ҽ <CABE> <D2BD> ϴ<EFBFBD> ." ) ) ;
RemoveAffect ( AFFECT_NO_DEATH_PENALTY ) ;
return ;
}
}
else if ( ! bTown ) // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ڸ<EFBFBD> <20> <> Ȱ<EFBFBD> ø<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <EFBFBD> <C8A3> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ѵ <EFBFBD> . (<28> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ͽô<CDBD> <20> <> <EFBFBD> <EFBFBD> ġ <20> г <EFBFBD> Ƽ <20> <> <EFBFBD> <EFBFBD> )
{
if ( FindAffect ( AFFECT_NO_DEATH_PENALTY ) )
{
sys_log ( 0 , " NO_DEATH_PENALTY_AFFECT(%s) " , GetName ( ) ) ;
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <EFBFBD> <C8A3> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʾ ҽ <CABE> <D2BD> ϴ<EFBFBD> ." ) ) ;
RemoveAffect ( AFFECT_NO_DEATH_PENALTY ) ;
return ;
}
}
// END_OF_NO_DEATH_PENALTY_BUG_FIX
int iLoss = ( ( GetNextExp ( ) * aiExpLossPercents [ MINMAX ( 1 , GetLevel ( ) , PLAYER_EXP_TABLE_MAX ) ] ) / 100 ) ;
if ( true = = LC_IsYMIR ( ) )
{
if ( PLAYER_EXP_TABLE_MAX < GetLevel ( ) )
{
iLoss = MIN ( 500000 , iLoss ) ;
}
else
{
iLoss = MIN ( 200000 , iLoss ) ;
}
}
else if ( true = = LC_IsEurope ( ) )
{
iLoss = MIN ( 800000 , iLoss ) ;
}
if ( bTown )
{
if ( g_iUseLocale )
{
iLoss = 0 ;
}
else
{
iLoss - = iLoss / 3 ;
}
}
if ( IsEquipUniqueItem ( UNIQUE_ITEM_TEARDROP_OF_GODNESS ) )
iLoss / = 2 ;
sys_log ( 0 , " DEATH_PENALTY(%s) EXP_LOSS: %d percent %d%% " , GetName ( ) , iLoss , aiExpLossPercents [ MIN ( gPlayerMaxLevel , GetLevel ( ) ) ] ) ;
PointChange ( POINT_EXP , - iLoss , true ) ;
}
}
bool CHARACTER : : IsStun ( ) const
{
if ( IS_SET ( m_pointsInstant . instant_flag , INSTANT_FLAG_STUN ) )
return true ;
return false ;
}
EVENTFUNC ( StunEvent )
{
char_event_info * info = dynamic_cast < char_event_info * > ( event - > info ) ;
if ( info = = NULL )
{
sys_err ( " StunEvent> <Factor> Null pointer " ) ;
return 0 ;
}
LPCHARACTER ch = info - > ch ;
if ( ch = = NULL ) { // <Factor>
return 0 ;
}
ch - > m_pkStunEvent = NULL ;
ch - > Dead ( ) ;
return 0 ;
}
void CHARACTER : : Stun ( )
{
if ( IsStun ( ) )
return ;
if ( IsDead ( ) )
return ;
if ( ! IsPC ( ) & & m_pkParty )
{
m_pkParty - > SendMessage ( this , PM_ATTACKED_BY , 0 , 0 ) ;
}
sys_log ( 1 , " %s: Stun %p " , GetName ( ) , this ) ;
PointChange ( POINT_HP_RECOVERY , - GetPoint ( POINT_HP_RECOVERY ) ) ;
PointChange ( POINT_SP_RECOVERY , - GetPoint ( POINT_SP_RECOVERY ) ) ;
CloseMyShop ( ) ;
event_cancel ( & m_pkRecoveryEvent ) ; // ȸ<> <C8B8> <20> ̺<EFBFBD> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> δ<EFBFBD> .
TPacketGCStun pack ;
pack . header = HEADER_GC_STUN ;
pack . vid = m_vid ;
PacketAround ( & pack , sizeof ( pack ) ) ;
SET_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_STUN ) ;
if ( m_pkStunEvent )
return ;
char_event_info * info = AllocEventInfo < char_event_info > ( ) ;
info - > ch = this ;
m_pkStunEvent = event_create ( StunEvent , info , PASSES_PER_SEC ( 3 ) ) ;
}
EVENTINFO ( SCharDeadEventInfo )
{
bool isPC ;
uint32_t dwID ;
SCharDeadEventInfo ( )
: isPC ( 0 )
, dwID ( 0 )
{
}
} ;
EVENTFUNC ( dead_event )
{
const SCharDeadEventInfo * info = dynamic_cast < SCharDeadEventInfo * > ( event - > info ) ;
if ( info = = NULL )
{
sys_err ( " dead_event> <Factor> Null pointer " ) ;
return 0 ;
}
LPCHARACTER ch = NULL ;
if ( true = = info - > isPC )
{
ch = CHARACTER_MANAGER : : instance ( ) . FindByPID ( info - > dwID ) ;
}
else
{
ch = CHARACTER_MANAGER : : instance ( ) . Find ( info - > dwID ) ;
}
if ( NULL = = ch )
{
sys_err ( " DEAD_EVENT: cannot find char pointer with %s id(%d) " , info - > isPC ? " PC " : " MOB " , info - > dwID ) ;
return 0 ;
}
ch - > m_pkDeadEvent = NULL ;
if ( ch - > GetDesc ( ) )
{
ch - > GetDesc ( ) - > SetPhase ( PHASE_GAME ) ;
ch - > SetPosition ( POS_STANDING ) ;
PIXEL_POSITION pos ;
if ( SECTREE_MANAGER : : instance ( ) . GetRecallPositionByEmpire ( ch - > GetMapIndex ( ) , ch - > GetEmpire ( ) , pos ) )
ch - > WarpSet ( pos . x , pos . y ) ;
else
{
sys_err ( " cannot find spawn position (name %s) " , ch - > GetName ( ) ) ;
ch - > WarpSet ( EMPIRE_START_X ( ch - > GetEmpire ( ) ) , EMPIRE_START_Y ( ch - > GetEmpire ( ) ) ) ;
}
ch - > PointChange ( POINT_HP , ( ch - > GetMaxHP ( ) / 2 ) - ch - > GetHP ( ) , true ) ;
ch - > DeathPenalty ( 0 ) ;
ch - > StartRecoveryEvent ( ) ;
ch - > ChatPacket ( CHAT_TYPE_COMMAND , " CloseRestartWindow " ) ;
}
else
{
if ( ch - > IsMonster ( ) = = true )
{
if ( ch - > IsRevive ( ) = = false & & ch - > HasReviverInParty ( ) = = true )
{
ch - > SetPosition ( POS_STANDING ) ;
ch - > SetHP ( ch - > GetMaxHP ( ) ) ;
ch - > ViewReencode ( ) ;
ch - > SetAggressive ( ) ;
ch - > SetRevive ( true ) ;
return 0 ;
}
}
M2_DESTROY_CHARACTER ( ch ) ;
}
return 0 ;
}
bool CHARACTER : : IsDead ( ) const
{
if ( m_pointsInstant . position = = POS_DEAD )
return true ;
return false ;
}
# define GetGoldMultipler() (distribution_test_server ? 3 : 1)
void CHARACTER : : RewardGold ( LPCHARACTER pkAttacker )
{
// ADD_PREMIUM
bool isAutoLoot =
( pkAttacker - > GetPremiumRemainSeconds ( PREMIUM_AUTOLOOT ) > 0 | |
pkAttacker - > IsEquipUniqueGroup ( UNIQUE_GROUP_AUTOLOOT ) )
? true : false ; // <20> <> 3<EFBFBD> <33> <20> <>
// END_OF_ADD_PREMIUM
PIXEL_POSITION pos ;
if ( ! isAutoLoot )
if ( ! SECTREE_MANAGER : : instance ( ) . GetMovablePosition ( GetMapIndex ( ) , GetX ( ) , GetY ( ) , pos ) )
return ;
int iTotalGold = 0 ;
//
// --------- <20> <> <20> <> <EFBFBD> <EFBFBD> Ȯ<> <C8AE> <20> <> <EFBFBD> <EFBFBD> ----------
//
int iGoldPercent = MobRankStats [ GetMobRank ( ) ] . iGoldPercent ;
if ( pkAttacker - > IsPC ( ) )
iGoldPercent = iGoldPercent * ( 100 + CPrivManager : : instance ( ) . GetPriv ( pkAttacker , PRIV_GOLD_DROP ) ) / 100 ;
if ( pkAttacker - > GetPoint ( POINT_MALL_GOLDBONUS ) )
iGoldPercent + = ( iGoldPercent * pkAttacker - > GetPoint ( POINT_MALL_GOLDBONUS ) / 100 ) ;
iGoldPercent = iGoldPercent * CHARACTER_MANAGER : : instance ( ) . GetMobGoldDropRate ( pkAttacker ) / 100 ;
// ADD_PREMIUM
if ( pkAttacker - > GetPremiumRemainSeconds ( PREMIUM_GOLD ) > 0 | |
pkAttacker - > IsEquipUniqueGroup ( UNIQUE_GROUP_LUCKY_GOLD ) )
iGoldPercent + = iGoldPercent ;
// END_OF_ADD_PREMIUM
if ( iGoldPercent > 100 )
iGoldPercent = 100 ;
int iPercent ;
if ( GetMobRank ( ) > = MOB_RANK_BOSS )
iPercent = ( ( iGoldPercent * PERCENT_LVDELTA_BOSS ( pkAttacker - > GetLevel ( ) , GetLevel ( ) ) ) / 100 ) ;
else
iPercent = ( ( iGoldPercent * PERCENT_LVDELTA ( pkAttacker - > GetLevel ( ) , GetLevel ( ) ) ) / 100 ) ;
//int iPercent = CALCULATE_VALUE_LVDELTA(pkAttacker->GetLevel(), GetLevel(), iGoldPercent);
if ( number ( 1 , 100 ) > iPercent )
return ;
int iGoldMultipler = GetGoldMultipler ( ) ;
if ( 1 = = number ( 1 , 50000 ) ) // 1/50000 Ȯ<> <C8AE> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> 10<31> <30>
iGoldMultipler * = 10 ;
else if ( 1 = = number ( 1 , 10000 ) ) // 1/10000 Ȯ<> <C8AE> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> 5<> <35>
iGoldMultipler * = 5 ;
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
if ( pkAttacker - > GetPoint ( POINT_GOLD_DOUBLE_BONUS ) )
if ( number ( 1 , 100 ) < = pkAttacker - > GetPoint ( POINT_GOLD_DOUBLE_BONUS ) )
iGoldMultipler * = 2 ;
//
// --------- <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ----------
//
if ( test_server )
pkAttacker - > ChatPacket ( CHAT_TYPE_PARTY , " gold_mul %d rate %d " , iGoldMultipler , CHARACTER_MANAGER : : instance ( ) . GetMobGoldAmountRate ( pkAttacker ) ) ;
//
// --------- <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ó<> <C3B3> -------------
//
LPITEM item ;
int iGold10DropPct = 100 ;
iGold10DropPct = ( iGold10DropPct * 100 ) / ( 100 + CPrivManager : : instance ( ) . GetPriv ( pkAttacker , PRIV_GOLD10_DROP ) ) ;
// MOB_RANK<4E> <4B> BOSS<53> <53> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ź
if ( GetMobRank ( ) > = MOB_RANK_BOSS & & ! IsStone ( ) & & GetMobTable ( ) . dwGoldMax ! = 0 )
{
if ( 1 = = number ( 1 , iGold10DropPct ) )
iGoldMultipler * = 10 ; // 1% Ȯ<> <C8AE> <EFBFBD> <EFBFBD> <20> <> 10<31> <30>
int iSplitCount = number ( 25 , 35 ) ;
for ( int i = 0 ; i < iSplitCount ; + + i )
{
int iGold = number ( GetMobTable ( ) . dwGoldMin , GetMobTable ( ) . dwGoldMax ) / iSplitCount ;
if ( test_server )
sys_log ( 0 , " iGold %d " , iGold ) ;
iGold = iGold * CHARACTER_MANAGER : : instance ( ) . GetMobGoldAmountRate ( pkAttacker ) / 100 ;
iGold * = iGoldMultipler ;
if ( iGold = = 0 )
{
continue ;
}
if ( test_server )
{
sys_log ( 0 , " Drop Moeny MobGoldAmountRate %d %d " , CHARACTER_MANAGER : : instance ( ) . GetMobGoldAmountRate ( pkAttacker ) , iGoldMultipler ) ;
sys_log ( 0 , " Drop Money gold %d GoldMin %d GoldMax %d " , iGold , GetMobTable ( ) . dwGoldMax , GetMobTable ( ) . dwGoldMax ) ;
}
// NOTE: <20> <> <20> <> ź<EFBFBD> <C5BA> <20> <> 3<> <33> <20> <> ó<> <C3B3> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
if ( ( item = ITEM_MANAGER : : instance ( ) . CreateItem ( 1 , iGold ) ) )
{
pos . x = GetX ( ) + ( ( number ( - 14 , 14 ) + number ( - 14 , 14 ) ) * 23 ) ;
pos . y = GetY ( ) + ( ( number ( - 14 , 14 ) + number ( - 14 , 14 ) ) * 23 ) ;
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
item - > StartDestroyEvent ( ) ;
iTotalGold + = iGold ; // Total gold
}
}
}
// 1% Ȯ<> <C8AE> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> 10<31> <30> <20> <> <EFBFBD> <EFBFBD> <20> ߸<EFBFBD> <DFB8> <EFBFBD> . (10<31> <30> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> )
else if ( 1 = = number ( 1 , iGold10DropPct ) )
{
//
// <20> <> <20> <> ź<EFBFBD> <C5BA> <20> <> <EFBFBD> <EFBFBD>
//
for ( int i = 0 ; i < 10 ; + + i )
{
int iGold = number ( GetMobTable ( ) . dwGoldMin , GetMobTable ( ) . dwGoldMax ) ;
iGold = iGold * CHARACTER_MANAGER : : instance ( ) . GetMobGoldAmountRate ( pkAttacker ) / 100 ;
iGold * = iGoldMultipler ;
if ( iGold = = 0 )
{
continue ;
}
// NOTE: <20> <> <20> <> ź<EFBFBD> <C5BA> <20> <> 3<> <33> <20> <> ó<> <C3B3> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
if ( ( item = ITEM_MANAGER : : instance ( ) . CreateItem ( 1 , iGold ) ) )
{
pos . x = GetX ( ) + ( number ( - 7 , 7 ) * 20 ) ;
pos . y = GetY ( ) + ( number ( - 7 , 7 ) * 20 ) ;
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
item - > StartDestroyEvent ( ) ;
iTotalGold + = iGold ; // Total gold
}
}
}
else
{
//
// <20> Ϲ <EFBFBD> <CFB9> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD>
//
int iGold = number ( GetMobTable ( ) . dwGoldMin , GetMobTable ( ) . dwGoldMax ) ;
iGold = iGold * CHARACTER_MANAGER : : instance ( ) . GetMobGoldAmountRate ( pkAttacker ) / 100 ;
iGold * = iGoldMultipler ;
int iSplitCount ;
if ( iGold > = 3 & & ! LC_IsYMIR ( ) )
iSplitCount = number ( 1 , 3 ) ;
else if ( GetMobRank ( ) > = MOB_RANK_BOSS )
{
iSplitCount = number ( 3 , 10 ) ;
if ( ( iGold / iSplitCount ) = = 0 )
iSplitCount = 1 ;
}
else
iSplitCount = 1 ;
if ( iGold ! = 0 )
{
iTotalGold + = iGold ; // Total gold
for ( int i = 0 ; i < iSplitCount ; + + i )
{
if ( isAutoLoot )
{
pkAttacker - > GiveGold ( iGold / iSplitCount ) ;
}
else if ( ( item = ITEM_MANAGER : : instance ( ) . CreateItem ( 1 , iGold / iSplitCount ) ) )
{
pos . x = GetX ( ) + ( number ( - 7 , 7 ) * 20 ) ;
pos . y = GetY ( ) + ( number ( - 7 , 7 ) * 20 ) ;
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
item - > StartDestroyEvent ( ) ;
}
}
}
}
DBManager : : instance ( ) . SendMoneyLog ( MONEY_LOG_MONSTER , GetRaceNum ( ) , iTotalGold ) ;
}
void CHARACTER : : Reward ( bool bItemDrop )
{
if ( GetRaceNum ( ) = = 5001 ) // <20> ֱ<EFBFBD> <D6B1> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
{
PIXEL_POSITION pos ;
if ( ! SECTREE_MANAGER : : instance ( ) . GetMovablePosition ( GetMapIndex ( ) , GetX ( ) , GetY ( ) , pos ) )
return ;
LPITEM item ;
int iGold = number ( GetMobTable ( ) . dwGoldMin , GetMobTable ( ) . dwGoldMax ) ;
iGold = iGold * CHARACTER_MANAGER : : instance ( ) . GetMobGoldAmountRate ( NULL ) / 100 ;
iGold * = GetGoldMultipler ( ) ;
int iSplitCount = number ( 25 , 35 ) ;
sys_log ( 0 , " WAEGU Dead gold %d split %d " , iGold , iSplitCount ) ;
for ( int i = 1 ; i < = iSplitCount ; + + i )
{
if ( ( item = ITEM_MANAGER : : instance ( ) . CreateItem ( 1 , iGold / iSplitCount ) ) )
{
if ( i ! = 0 )
{
pos . x = number ( - 7 , 7 ) * 20 ;
pos . y = number ( - 7 , 7 ) * 20 ;
pos . x + = GetX ( ) ;
pos . y + = GetY ( ) ;
}
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
item - > StartDestroyEvent ( ) ;
}
}
return ;
}
//PROF_UNIT puReward("Reward");
LPCHARACTER pkAttacker = DistributeExp ( ) ;
if ( ! pkAttacker )
return ;
//PROF_UNIT pu1("r1");
if ( pkAttacker - > IsPC ( ) )
{
if ( GetLevel ( ) - pkAttacker - > GetLevel ( ) > = - 10 )
if ( pkAttacker - > GetRealAlignment ( ) < 0 )
{
if ( pkAttacker - > IsEquipUniqueItem ( UNIQUE_ITEM_FASTER_ALIGNMENT_UP_BY_KILL ) )
pkAttacker - > UpdateAlignment ( 14 ) ;
else
pkAttacker - > UpdateAlignment ( 7 ) ;
}
else
pkAttacker - > UpdateAlignment ( 2 ) ;
pkAttacker - > SetQuestNPCID ( GetVID ( ) ) ;
quest : : CQuestManager : : instance ( ) . Kill ( pkAttacker - > GetPlayerID ( ) , GetRaceNum ( ) ) ;
CHARACTER_MANAGER : : instance ( ) . KillLog ( GetRaceNum ( ) ) ;
if ( ! number ( 0 , 9 ) )
{
if ( pkAttacker - > GetPoint ( POINT_KILL_HP_RECOVERY ) )
{
int iHP = pkAttacker - > GetMaxHP ( ) * pkAttacker - > GetPoint ( POINT_KILL_HP_RECOVERY ) / 100 ;
pkAttacker - > PointChange ( POINT_HP , iHP ) ;
CreateFly ( FLY_HP_SMALL , pkAttacker ) ;
}
if ( pkAttacker - > GetPoint ( POINT_KILL_SP_RECOVER ) )
{
int iSP = pkAttacker - > GetMaxSP ( ) * pkAttacker - > GetPoint ( POINT_KILL_SP_RECOVER ) / 100 ;
pkAttacker - > PointChange ( POINT_SP , iSP ) ;
CreateFly ( FLY_SP_SMALL , pkAttacker ) ;
}
}
}
//pu1.Pop();
if ( ! bItemDrop )
return ;
PIXEL_POSITION pos = GetXYZ ( ) ;
if ( ! SECTREE_MANAGER : : instance ( ) . GetMovablePosition ( GetMapIndex ( ) , pos . x , pos . y , pos ) )
return ;
//
// <20> <> <20> <> <EFBFBD> <EFBFBD>
//
//PROF_UNIT pu2("r2");
if ( test_server )
sys_log ( 0 , " Drop money : Attacker %s " , pkAttacker - > GetName ( ) ) ;
RewardGold ( pkAttacker ) ;
//pu2.Pop();
//
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
//
//PROF_UNIT pu3("r3");
LPITEM item ;
static std : : vector < LPITEM > s_vec_item ;
s_vec_item . clear ( ) ;
if ( ITEM_MANAGER : : instance ( ) . CreateDropItem ( this , pkAttacker , s_vec_item ) )
{
if ( s_vec_item . size ( ) = = 0 ) ;
else if ( s_vec_item . size ( ) = = 1 )
{
item = s_vec_item [ 0 ] ;
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
if ( CBattleArena : : instance ( ) . IsBattleArenaMap ( pkAttacker - > GetMapIndex ( ) ) = = false )
{
item - > SetOwnership ( pkAttacker ) ;
}
item - > StartDestroyEvent ( ) ;
pos . x = number ( - 7 , 7 ) * 20 ;
pos . y = number ( - 7 , 7 ) * 20 ;
pos . x + = GetX ( ) ;
pos . y + = GetY ( ) ;
sys_log ( 0 , " DROP_ITEM: %s %d %d from %s " , item - > GetName ( ) , pos . x , pos . y , GetName ( ) ) ;
}
else
{
int iItemIdx = s_vec_item . size ( ) - 1 ;
std : : priority_queue < std : : pair < int , LPCHARACTER > > pq ;
int total_dam = 0 ;
for ( TDamageMap : : iterator it = m_map_kDamage . begin ( ) ; it ! = m_map_kDamage . end ( ) ; + + it )
{
int iDamage = it - > second . iTotalDamage ;
if ( iDamage > 0 )
{
LPCHARACTER ch = CHARACTER_MANAGER : : instance ( ) . Find ( it - > first ) ;
if ( ch )
{
pq . push ( std : : make_pair ( iDamage , ch ) ) ;
total_dam + = iDamage ;
}
}
}
std : : vector < LPCHARACTER > v ;
while ( ! pq . empty ( ) & & pq . top ( ) . first * 10 > = total_dam )
{
v . push_back ( pq . top ( ) . second ) ;
pq . pop ( ) ;
}
if ( v . empty ( ) )
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ư<> <C6AF> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
while ( iItemIdx > = 0 )
{
item = s_vec_item [ iItemIdx - - ] ;
if ( ! item )
{
sys_err ( " item null in vector idx %d " , iItemIdx + 1 ) ;
continue ;
}
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
// 10% <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ǿ<EFBFBD> <C7BE> <EFBFBD>
//item->SetOwnership(pkAttacker);
item - > StartDestroyEvent ( ) ;
pos . x = number ( - 7 , 7 ) * 20 ;
pos . y = number ( - 7 , 7 ) * 20 ;
pos . x + = GetX ( ) ;
pos . y + = GetY ( ) ;
sys_log ( 0 , " DROP_ITEM: %s %d %d by %s " , item - > GetName ( ) , pos . x , pos . y , GetName ( ) ) ;
}
}
else
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
std : : vector < LPCHARACTER > : : iterator it = v . begin ( ) ;
while ( iItemIdx > = 0 )
{
item = s_vec_item [ iItemIdx - - ] ;
if ( ! item )
{
sys_err ( " item null in vector idx %d " , iItemIdx + 1 ) ;
continue ;
}
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
LPCHARACTER ch = * it ;
if ( ch - > GetParty ( ) )
ch = ch - > GetParty ( ) - > GetNextOwnership ( ch , GetX ( ) , GetY ( ) ) ;
+ + it ;
if ( it = = v . end ( ) )
it = v . begin ( ) ;
if ( CBattleArena : : instance ( ) . IsBattleArenaMap ( ch - > GetMapIndex ( ) ) = = false )
{
item - > SetOwnership ( ch ) ;
}
item - > StartDestroyEvent ( ) ;
pos . x = number ( - 7 , 7 ) * 20 ;
pos . y = number ( - 7 , 7 ) * 20 ;
pos . x + = GetX ( ) ;
pos . y + = GetY ( ) ;
sys_log ( 0 , " DROP_ITEM: %s %d %d by %s " , item - > GetName ( ) , pos . x , pos . y , GetName ( ) ) ;
}
}
}
}
m_map_kDamage . clear ( ) ;
}
struct TItemDropPenalty
{
int iInventoryPct ; // Range: 1 ~ 1000
int iInventoryQty ; // Range: --
int iEquipmentPct ; // Range: 1 ~ 100
int iEquipmentQty ; // Range: --
} ;
TItemDropPenalty aItemDropPenalty_kor [ 9 ] =
{
{ 0 , 0 , 0 , 0 } , // <20> <> <EFBFBD> <EFBFBD>
{ 0 , 0 , 0 , 0 } , // <20> <> <EFBFBD> <EFBFBD>
{ 0 , 0 , 0 , 0 } , // <20> <> <EFBFBD> <EFBFBD>
{ 0 , 0 , 0 , 0 } , // <20> <> <EFBFBD> <EFBFBD>
{ 0 , 0 , 0 , 0 } , // <20> <> <EFBFBD> <EFBFBD>
{ 25 , 1 , 5 , 1 } , // <20> <> <EFBFBD> <EFBFBD>
{ 50 , 2 , 10 , 1 } , // <20> <> <EFBFBD> <EFBFBD>
{ 75 , 4 , 15 , 1 } , // <20> <> <EFBFBD> <EFBFBD>
{ 100 , 8 , 20 , 1 } , // <20> п<EFBFBD>
} ;
void CHARACTER : : ItemDropPenalty ( LPCHARACTER pkKiller )
{
// <20> <> <EFBFBD> λ<EFBFBD> <CEBB> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> ¿<EFBFBD> <C2BF> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʴ´ <CAB4> .
if ( GetMyShop ( ) )
return ;
if ( false = = LC_IsYMIR ( ) )
{
if ( GetLevel ( ) < 50 )
return ;
}
if ( CBattleArena : : instance ( ) . IsBattleArenaMap ( GetMapIndex ( ) ) = = true )
{
return ;
}
struct TItemDropPenalty * table = & aItemDropPenalty_kor [ 0 ] ;
if ( GetLevel ( ) < 10 )
return ;
int iAlignIndex ;
if ( GetRealAlignment ( ) > = 120000 )
iAlignIndex = 0 ;
else if ( GetRealAlignment ( ) > = 80000 )
iAlignIndex = 1 ;
else if ( GetRealAlignment ( ) > = 40000 )
iAlignIndex = 2 ;
else if ( GetRealAlignment ( ) > = 10000 )
iAlignIndex = 3 ;
else if ( GetRealAlignment ( ) > = 0 )
iAlignIndex = 4 ;
else if ( GetRealAlignment ( ) > - 40000 )
iAlignIndex = 5 ;
else if ( GetRealAlignment ( ) > - 80000 )
iAlignIndex = 6 ;
else if ( GetRealAlignment ( ) > - 120000 )
iAlignIndex = 7 ;
else
iAlignIndex = 8 ;
std : : vector < std : : pair < LPITEM , int > > vec_item ;
LPITEM pkItem ;
int i ;
bool isDropAllEquipments = false ;
TItemDropPenalty & r = table [ iAlignIndex ] ;
sys_log ( 0 , " %s align %d inven_pct %d equip_pct %d " , GetName ( ) , iAlignIndex , r . iInventoryPct , r . iEquipmentPct ) ;
bool bDropInventory = r . iInventoryPct > = number ( 1 , 1000 ) ;
bool bDropEquipment = r . iEquipmentPct > = number ( 1 , 100 ) ;
bool bDropAntiDropUniqueItem = false ;
if ( ( bDropInventory | | bDropEquipment ) & & IsEquipUniqueItem ( UNIQUE_ITEM_SKIP_ITEM_DROP_PENALTY ) )
{
bDropInventory = false ;
bDropEquipment = false ;
bDropAntiDropUniqueItem = true ;
}
if ( bDropInventory ) // Drop Inventory
{
std : : vector < BYTE > vec_bSlots ;
for ( i = 0 ; i < INVENTORY_MAX_NUM ; + + i )
if ( GetInventoryItem ( i ) )
vec_bSlots . push_back ( i ) ;
if ( ! vec_bSlots . empty ( ) )
{
random_shuffle ( vec_bSlots . begin ( ) , vec_bSlots . end ( ) ) ;
int iQty = MIN ( vec_bSlots . size ( ) , r . iInventoryQty ) ;
if ( iQty )
iQty = number ( 1 , iQty ) ;
for ( i = 0 ; i < iQty ; + + i )
{
pkItem = GetInventoryItem ( vec_bSlots [ i ] ) ;
if ( IS_SET ( pkItem - > GetAntiFlag ( ) , ITEM_ANTIFLAG_GIVE | ITEM_ANTIFLAG_PKDROP ) )
continue ;
SyncQuickslot ( QUICKSLOT_TYPE_ITEM , vec_bSlots [ i ] , 255 ) ;
vec_item . push_back ( std : : make_pair ( pkItem - > RemoveFromCharacter ( ) , INVENTORY ) ) ;
}
}
else if ( iAlignIndex = = 8 )
isDropAllEquipments = true ;
}
if ( bDropEquipment ) // Drop Equipment
{
std : : vector < BYTE > vec_bSlots ;
for ( i = 0 ; i < WEAR_MAX_NUM ; + + i )
if ( GetWear ( i ) )
vec_bSlots . push_back ( i ) ;
if ( ! vec_bSlots . empty ( ) )
{
random_shuffle ( vec_bSlots . begin ( ) , vec_bSlots . end ( ) ) ;
int iQty ;
if ( isDropAllEquipments )
iQty = vec_bSlots . size ( ) ;
else
iQty = MIN ( vec_bSlots . size ( ) , number ( 1 , r . iEquipmentQty ) ) ;
if ( iQty )
iQty = number ( 1 , iQty ) ;
for ( i = 0 ; i < iQty ; + + i )
{
pkItem = GetWear ( vec_bSlots [ i ] ) ;
if ( IS_SET ( pkItem - > GetAntiFlag ( ) , ITEM_ANTIFLAG_GIVE | ITEM_ANTIFLAG_PKDROP ) )
continue ;
SyncQuickslot ( QUICKSLOT_TYPE_ITEM , vec_bSlots [ i ] , 255 ) ;
vec_item . push_back ( std : : make_pair ( pkItem - > RemoveFromCharacter ( ) , EQUIPMENT ) ) ;
}
}
}
if ( bDropAntiDropUniqueItem )
{
LPITEM pkItem ;
pkItem = GetWear ( WEAR_UNIQUE1 ) ;
if ( pkItem & & pkItem - > GetVnum ( ) = = UNIQUE_ITEM_SKIP_ITEM_DROP_PENALTY )
{
SyncQuickslot ( QUICKSLOT_TYPE_ITEM , WEAR_UNIQUE1 , 255 ) ;
vec_item . push_back ( std : : make_pair ( pkItem - > RemoveFromCharacter ( ) , EQUIPMENT ) ) ;
}
pkItem = GetWear ( WEAR_UNIQUE2 ) ;
if ( pkItem & & pkItem - > GetVnum ( ) = = UNIQUE_ITEM_SKIP_ITEM_DROP_PENALTY )
{
SyncQuickslot ( QUICKSLOT_TYPE_ITEM , WEAR_UNIQUE2 , 255 ) ;
vec_item . push_back ( std : : make_pair ( pkItem - > RemoveFromCharacter ( ) , EQUIPMENT ) ) ;
}
}
{
PIXEL_POSITION pos ;
pos . x = GetX ( ) ;
pos . y = GetY ( ) ;
unsigned int i ;
for ( i = 0 ; i < vec_item . size ( ) ; + + i )
{
LPITEM item = vec_item [ i ] . first ;
int window = vec_item [ i ] . second ;
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
item - > StartDestroyEvent ( ) ;
sys_log ( 0 , " DROP_ITEM_PK: %s %d %d from %s " , item - > GetName ( ) , pos . x , pos . y , GetName ( ) ) ;
LogManager : : instance ( ) . ItemLog ( this , item , " DEAD_DROP " , ( window = = INVENTORY ) ? " INVENTORY " : ( ( window = = EQUIPMENT ) ? " EQUIPMENT " : " " ) ) ;
pos . x = GetX ( ) + number ( - 7 , 7 ) * 20 ;
pos . y = GetY ( ) + number ( - 7 , 7 ) * 20 ;
}
}
}
class FPartyAlignmentCompute
{
public :
FPartyAlignmentCompute ( int iAmount , int x , int y )
{
m_iAmount = iAmount ;
m_iCount = 0 ;
m_iStep = 0 ;
m_iKillerX = x ;
m_iKillerY = y ;
}
void operator ( ) ( LPCHARACTER pkChr )
{
if ( DISTANCE_APPROX ( pkChr - > GetX ( ) - m_iKillerX , pkChr - > GetY ( ) - m_iKillerY ) < PARTY_DEFAULT_RANGE )
{
if ( m_iStep = = 0 )
{
+ + m_iCount ;
}
else
{
pkChr - > UpdateAlignment ( m_iAmount / m_iCount ) ;
}
}
}
int m_iAmount ;
int m_iCount ;
int m_iStep ;
int m_iKillerX ;
int m_iKillerY ;
} ;
void CHARACTER : : Dead ( LPCHARACTER pkKiller , bool bImmediateDead )
{
if ( IsDead ( ) )
return ;
{
if ( IsHorseRiding ( ) )
{
StopRiding ( ) ;
}
else if ( GetMountVnum ( ) )
{
RemoveAffect ( AFFECT_MOUNT_BONUS ) ;
m_dwMountVnum = 0 ;
UnEquipSpecialRideUniqueItem ( ) ;
UpdatePacket ( ) ;
}
}
if ( ! pkKiller & & m_dwKillerPID )
pkKiller = CHARACTER_MANAGER : : instance ( ) . FindByPID ( m_dwKillerPID ) ;
m_dwKillerPID = 0 ; // <20> ݵ<EFBFBD> <DDB5> <EFBFBD> <20> ʱ<EFBFBD> ȭ <20> ؾ<EFBFBD> <D8BE> <EFBFBD> DO NOT DELETE THIS LINE UNLESS YOU ARE 1000000% SURE
bool isAgreedPVP = false ;
bool isUnderGuildWar = false ;
bool isDuel = false ;
bool isForked = false ;
if ( pkKiller & & pkKiller - > IsPC ( ) )
{
if ( pkKiller - > m_pkChrTarget = = this )
pkKiller - > SetTarget ( NULL ) ;
if ( ! IsPC ( ) & & pkKiller - > GetDungeon ( ) )
pkKiller - > GetDungeon ( ) - > IncKillCount ( pkKiller , this ) ;
isAgreedPVP = CPVPManager : : instance ( ) . Dead ( this , pkKiller - > GetPlayerID ( ) ) ;
isDuel = CArenaManager : : instance ( ) . OnDead ( pkKiller , this ) ;
if ( IsPC ( ) )
{
CGuild * g1 = GetGuild ( ) ;
CGuild * g2 = pkKiller - > GetGuild ( ) ;
if ( g1 & & g2 )
if ( g1 - > UnderWar ( g2 - > GetID ( ) ) )
isUnderGuildWar = true ;
pkKiller - > SetQuestNPCID ( GetVID ( ) ) ;
quest : : CQuestManager : : instance ( ) . Kill ( pkKiller - > GetPlayerID ( ) , quest : : QUEST_NO_NPC ) ;
CGuildManager : : instance ( ) . Kill ( pkKiller , this ) ;
}
}
//CHECK_FORKEDROAD_WAR
if ( IsPC ( ) )
{
if ( CThreeWayWar : : instance ( ) . IsThreeWayWarMapIndex ( GetMapIndex ( ) ) )
isForked = true ;
}
//END_CHECK_FORKEDROAD_WAR
if ( pkKiller & &
! isAgreedPVP & &
! isUnderGuildWar & &
IsPC ( ) & &
! isDuel & &
! isForked & &
! IS_CASTLE_MAP ( GetMapIndex ( ) ) )
{
if ( GetGMLevel ( ) = = GM_PLAYER | | test_server )
{
ItemDropPenalty ( pkKiller ) ;
}
}
// CASTLE_SIEGE
if ( IS_CASTLE_MAP ( GetMapIndex ( ) ) )
{
if ( CASTLE_FROG_VNUM = = GetRaceNum ( ) )
castle_frog_die ( this , pkKiller ) ;
else if ( castle_is_guard_vnum ( GetRaceNum ( ) ) )
castle_guard_die ( this , pkKiller ) ;
else if ( castle_is_tower_vnum ( GetRaceNum ( ) ) )
castle_tower_die ( this , pkKiller ) ;
}
// CASTLE_SIEGE
if ( true = = isForked )
{
CThreeWayWar : : instance ( ) . onDead ( this , pkKiller ) ;
}
SetPosition ( POS_DEAD ) ;
ClearAffect ( true ) ;
if ( pkKiller & & IsPC ( ) )
{
if ( ! pkKiller - > IsPC ( ) )
{
if ( ! isForked )
{
sys_log ( 1 , " DEAD: %s %p WITH PENALTY " , GetName ( ) , this ) ;
SET_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_DEATH_PENALTY ) ;
LogManager : : instance ( ) . CharLog ( this , pkKiller - > GetRaceNum ( ) , " DEAD_BY_NPC " , pkKiller - > GetName ( ) ) ;
}
}
else
{
sys_log ( 1 , " DEAD_BY_PC: %s %p KILLER %s %p " , GetName ( ) , this , pkKiller - > GetName ( ) , get_pointer ( pkKiller ) ) ;
REMOVE_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_DEATH_PENALTY ) ;
if ( GetEmpire ( ) ! = pkKiller - > GetEmpire ( ) )
{
int iEP = MIN ( GetPoint ( POINT_EMPIRE_POINT ) , pkKiller - > GetPoint ( POINT_EMPIRE_POINT ) ) ;
PointChange ( POINT_EMPIRE_POINT , - ( iEP / 10 ) ) ;
pkKiller - > PointChange ( POINT_EMPIRE_POINT , iEP / 5 ) ;
if ( GetPoint ( POINT_EMPIRE_POINT ) < 10 )
{
// TODO : <20> Ա<EFBFBD> <D4B1> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ڵ带 <20> ־<EFBFBD> <D6BE> <EFBFBD> <20> Ѵ <EFBFBD> .
}
char buf [ 256 ] ;
snprintf ( buf , sizeof ( buf ) ,
" %d %d %d %s %d %d %d %s " ,
GetEmpire ( ) , GetAlignment ( ) , GetPKMode ( ) , GetName ( ) ,
pkKiller - > GetEmpire ( ) , pkKiller - > GetAlignment ( ) , pkKiller - > GetPKMode ( ) , pkKiller - > GetName ( ) ) ;
LogManager : : instance ( ) . CharLog ( this , pkKiller - > GetPlayerID ( ) , " DEAD_BY_PC " , buf ) ;
}
else
{
if ( ! isAgreedPVP & & ! isUnderGuildWar & & ! IsKillerMode ( ) & & GetAlignment ( ) > = 0 & & ! isDuel & & ! isForked )
{
int iNoPenaltyProb = 0 ;
if ( g_iUseLocale )
{
if ( pkKiller - > GetAlignment ( ) > = 0 ) // 1/3 percent down
iNoPenaltyProb = 33 ;
else // 4/5 percent down
iNoPenaltyProb = 20 ;
}
if ( number ( 1 , 100 ) < iNoPenaltyProb )
pkKiller - > ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ȣ <EFBFBD> <C8A3> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʾ ҽ <CABE> <D2BD> ϴ<EFBFBD> ." ) ) ;
else
{
if ( g_iUseLocale & & pkKiller - > GetParty ( ) )
{
FPartyAlignmentCompute f ( - 20000 , pkKiller - > GetX ( ) , pkKiller - > GetY ( ) ) ;
pkKiller - > GetParty ( ) - > ForEachOnlineMember ( f ) ;
if ( f . m_iCount = = 0 )
pkKiller - > UpdateAlignment ( - 20000 ) ;
else
{
sys_log ( 0 , " ALIGNMENT PARTY count %d amount %d " , f . m_iCount , f . m_iAmount ) ;
f . m_iStep = 1 ;
pkKiller - > GetParty ( ) - > ForEachOnlineMember ( f ) ;
}
}
else
pkKiller - > UpdateAlignment ( - 20000 ) ;
}
}
char buf [ 256 ] ;
snprintf ( buf , sizeof ( buf ) ,
" %d %d %d %s %d %d %d %s " ,
GetEmpire ( ) , GetAlignment ( ) , GetPKMode ( ) , GetName ( ) ,
pkKiller - > GetEmpire ( ) , pkKiller - > GetAlignment ( ) , pkKiller - > GetPKMode ( ) , pkKiller - > GetName ( ) ) ;
LogManager : : instance ( ) . CharLog ( this , pkKiller - > GetPlayerID ( ) , " DEAD_BY_PC " , buf ) ;
}
}
}
else
{
sys_log ( 1 , " DEAD: %s %p " , GetName ( ) , this ) ;
REMOVE_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_DEATH_PENALTY ) ;
}
ClearSync ( ) ;
//sys_log(1, "stun cancel %s[%d]", GetName(), (DWORD)GetVID());
event_cancel ( & m_pkStunEvent ) ; // <20> <> <EFBFBD> <EFBFBD> <20> ̺<EFBFBD> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> δ<EFBFBD> .
if ( IsPC ( ) )
{
m_dwLastDeadTime = get_dword_time ( ) ;
SetKillerMode ( false ) ;
GetDesc ( ) - > SetPhase ( PHASE_DEAD ) ;
}
else
{
// <20> <> <EFBFBD> 忡<EFBFBD> <E5BFA1> <20> <> <EFBFBD> ݹ<EFBFBD> <DDB9> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ʹ <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> Ѵ <EFBFBD> .
if ( ! IS_SET ( m_pointsInstant . instant_flag , INSTANT_FLAG_NO_REWARD ) )
{
if ( ! ( pkKiller & & pkKiller - > IsPC ( ) & & pkKiller - > GetGuild ( ) & & pkKiller - > GetGuild ( ) - > UnderAnyWar ( GUILD_WAR_TYPE_FIELD ) ) )
{
// <20> <> Ȱ<EFBFBD> ϴ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ʹ <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ʴ´ <CAB4> .
if ( GetMobTable ( ) . dwResurrectionVnum )
{
// DUNGEON_MONSTER_REBIRTH_BUG_FIX
LPCHARACTER chResurrect = CHARACTER_MANAGER : : instance ( ) . SpawnMob ( GetMobTable ( ) . dwResurrectionVnum , GetMapIndex ( ) , GetX ( ) , GetY ( ) , GetZ ( ) , true , ( int ) GetRotation ( ) ) ;
if ( GetDungeon ( ) & & chResurrect )
{
chResurrect - > SetDungeon ( GetDungeon ( ) ) ;
}
// END_OF_DUNGEON_MONSTER_REBIRTH_BUG_FIX
Reward ( false ) ;
}
else if ( IsRevive ( ) = = true )
{
Reward ( false ) ;
}
else
{
Reward ( true ) ; // Drops gold, item, etc..
}
}
else
{
if ( pkKiller - > m_dwUnderGuildWarInfoMessageTime < get_dword_time ( ) )
{
pkKiller - > m_dwUnderGuildWarInfoMessageTime = get_dword_time ( ) + 60000 ;
pkKiller - > ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <<3C> <> <EFBFBD> <EFBFBD> > <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ߿<EFBFBD> <DFBF> <EFBFBD> <20> <> <EFBFBD> ɿ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . " ) ) ;
}
}
}
}
// BOSS_KILL_LOG
if ( GetMobRank ( ) > = MOB_RANK_BOSS & & pkKiller & & pkKiller - > IsPC ( ) )
{
char buf [ 51 ] ;
2022-03-12 11:39:41 +02:00
snprintf ( buf , sizeof ( buf ) , " %d %d " , g_bChannel , pkKiller - > GetMapIndex ( ) ) ;
2022-03-05 12:44:06 +02:00
if ( IsStone ( ) )
LogManager : : instance ( ) . CharLog ( pkKiller , GetRaceNum ( ) , " STONE_KILL " , buf ) ;
else
LogManager : : instance ( ) . CharLog ( pkKiller , GetRaceNum ( ) , " BOSS_KILL " , buf ) ;
}
// END_OF_BOSS_KILL_LOG
TPacketGCDead pack ;
pack . header = HEADER_GC_DEAD ;
pack . vid = m_vid ;
PacketAround ( & pack , sizeof ( pack ) ) ;
REMOVE_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_STUN ) ;
// <20> ÷<EFBFBD> <C3B7> ̾<EFBFBD> ij<> <C4B3> <EFBFBD> <EFBFBD> <EFBFBD> ̸<EFBFBD>
if ( GetDesc ( ) ! = NULL ) {
//
// Ŭ<> <C5AC> <EFBFBD> ̾<EFBFBD> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> <EFBFBD> Ʈ <20> <> Ŷ<EFBFBD> <C5B6> <20> ٽ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> .
//
itertype ( m_list_pkAffect ) it = m_list_pkAffect . begin ( ) ;
while ( it ! = m_list_pkAffect . end ( ) )
SendAffectAddPacket ( GetDesc ( ) , * it + + ) ;
}
//
// Dead <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD> ,
//
// Dead <20> ̺<EFBFBD> Ʈ<EFBFBD> <C6AE> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> Ŀ<EFBFBD> Destroy <20> ǵ<EFBFBD> <C7B5> <EFBFBD> <20> <> <EFBFBD> ָ<EFBFBD> ,
// PC<50> <43> <20> <> <EFBFBD> <EFBFBD> 3<> <33> <20> ִٰ<D6B4> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> ش<EFBFBD> . 3<> <33> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> κ<EFBFBD> <CEBA> <EFBFBD>
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> , <20> <> <EFBFBD> ⼭ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ´ <DEB4> .
if ( isDuel = = false )
{
if ( m_pkDeadEvent )
{
sys_log ( 1 , " DEAD_EVENT_CANCEL: %s %p %p " , GetName ( ) , this , get_pointer ( m_pkDeadEvent ) ) ;
event_cancel ( & m_pkDeadEvent ) ;
}
if ( IsStone ( ) )
ClearStone ( ) ;
if ( GetDungeon ( ) )
{
GetDungeon ( ) - > DeadCharacter ( this ) ;
}
SCharDeadEventInfo * pEventInfo = AllocEventInfo < SCharDeadEventInfo > ( ) ;
if ( IsPC ( ) )
{
pEventInfo - > isPC = true ;
pEventInfo - > dwID = this - > GetPlayerID ( ) ;
m_pkDeadEvent = event_create ( dead_event , pEventInfo , PASSES_PER_SEC ( 180 ) ) ;
}
else
{
pEventInfo - > isPC = false ;
pEventInfo - > dwID = this - > GetVID ( ) ;
if ( IsRevive ( ) = = false & & HasReviverInParty ( ) = = true )
{
m_pkDeadEvent = event_create ( dead_event , pEventInfo , bImmediateDead ? 1 : PASSES_PER_SEC ( 3 ) ) ;
}
else
{
m_pkDeadEvent = event_create ( dead_event , pEventInfo , bImmediateDead ? 1 : PASSES_PER_SEC ( 10 ) ) ;
}
}
sys_log ( 1 , " DEAD_EVENT_CREATE: %s %p %p " , GetName ( ) , this , get_pointer ( m_pkDeadEvent ) ) ;
}
if ( m_pkExchange ! = NULL )
{
m_pkExchange - > Cancel ( ) ;
}
if ( IsCubeOpen ( ) = = true )
{
Cube_close ( this ) ;
}
CShopManager : : instance ( ) . StopShopping ( this ) ;
CloseMyShop ( ) ;
CloseSafebox ( ) ;
if ( true = = IsMonster ( ) & & 2493 = = GetMobTable ( ) . dwVnum )
{
if ( NULL ! = pkKiller & & NULL ! = pkKiller - > GetGuild ( ) )
{
CDragonLairManager : : instance ( ) . OnDragonDead ( this , pkKiller - > GetGuild ( ) - > GetID ( ) ) ;
}
else
{
sys_err ( " DragonLair: Dragon killed by nobody " ) ;
}
}
}
struct FuncSetLastAttacked
{
FuncSetLastAttacked ( DWORD dwTime ) : m_dwTime ( dwTime )
{
}
void operator ( ) ( LPCHARACTER ch )
{
ch - > SetLastAttacked ( m_dwTime ) ;
}
DWORD m_dwTime ;
} ;
void CHARACTER : : SetLastAttacked ( DWORD dwTime )
{
assert ( m_pkMobInst ! = NULL ) ;
m_pkMobInst - > m_dwLastAttackedTime = dwTime ;
m_pkMobInst - > m_posLastAttacked = GetXYZ ( ) ;
}
void CHARACTER : : SendDamagePacket ( LPCHARACTER pAttacker , int Damage , BYTE DamageFlag )
{
if ( IsPC ( ) = = true | | ( pAttacker - > IsPC ( ) = = true & & pAttacker - > GetTarget ( ) = = this ) )
{
TPacketGCDamageInfo damageInfo ;
memset ( & damageInfo , 0 , sizeof ( TPacketGCDamageInfo ) ) ;
damageInfo . header = HEADER_GC_DAMAGE_INFO ;
damageInfo . dwVID = ( DWORD ) GetVID ( ) ;
damageInfo . flag = DamageFlag ;
damageInfo . damage = Damage ;
if ( GetDesc ( ) ! = NULL )
{
GetDesc ( ) - > Packet ( & damageInfo , sizeof ( TPacketGCDamageInfo ) ) ;
}
if ( pAttacker - > GetDesc ( ) ! = NULL )
{
pAttacker - > GetDesc ( ) - > Packet ( & damageInfo , sizeof ( TPacketGCDamageInfo ) ) ;
}
/*
if ( GetArenaObserverMode ( ) = = false & & GetArena ( ) ! = NULL )
{
GetArena ( ) - > SendPacketToObserver ( & damageInfo , sizeof ( TPacketGCDamageInfo ) ) ;
}
*/
}
}
//
// CHARACTER::Damage <20> ҵ<DEBC> <D2B5> <EFBFBD> this<69> <73> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <EFBFBD> <20> Ѵ <EFBFBD> .
//
// Arguments
// pAttacker : <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// dam : <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// EDamageType : <20> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ΰ<EFBFBD> ?
//
// Return value
// true : dead
// false : not dead yet
//
bool CHARACTER : : Damage ( LPCHARACTER pAttacker , int dam , EDamageType type ) // returns true if dead
{
if ( DAMAGE_TYPE_MAGIC = = type )
{
dam = ( int ) ( ( float ) dam * ( 100 + ( pAttacker - > GetPoint ( POINT_MAGIC_ATT_BONUS_PER ) + pAttacker - > GetPoint ( POINT_MELEE_MAGIC_ATT_BONUS_PER ) ) ) / 100.f + 0.5f ) ;
}
if ( GetRaceNum ( ) = = 5001 )
{
bool bDropMoney = false ;
int iPercent = ( GetHP ( ) * 100 ) / GetMaxHP ( ) ;
if ( iPercent < = 10 & & GetMaxSP ( ) < 5 )
{
SetMaxSP ( 5 ) ;
bDropMoney = true ;
}
else if ( iPercent < = 20 & & GetMaxSP ( ) < 4 )
{
SetMaxSP ( 4 ) ;
bDropMoney = true ;
}
else if ( iPercent < = 40 & & GetMaxSP ( ) < 3 )
{
SetMaxSP ( 3 ) ;
bDropMoney = true ;
}
else if ( iPercent < = 60 & & GetMaxSP ( ) < 2 )
{
SetMaxSP ( 2 ) ;
bDropMoney = true ;
}
else if ( iPercent < = 80 & & GetMaxSP ( ) < 1 )
{
SetMaxSP ( 1 ) ;
bDropMoney = true ;
}
if ( bDropMoney )
{
DWORD dwGold = 1000 ;
int iSplitCount = number ( 10 , 13 ) ;
sys_log ( 0 , " WAEGU DropGoldOnHit %d times " , GetMaxSP ( ) ) ;
for ( int i = 1 ; i < = iSplitCount ; + + i )
{
PIXEL_POSITION pos ;
LPITEM item ;
if ( ( item = ITEM_MANAGER : : instance ( ) . CreateItem ( 1 , dwGold / iSplitCount ) ) )
{
if ( i ! = 0 )
{
pos . x = ( number ( - 14 , 14 ) + number ( - 14 , 14 ) ) * 20 ;
pos . y = ( number ( - 14 , 14 ) + number ( - 14 , 14 ) ) * 20 ;
pos . x + = GetX ( ) ;
pos . y + = GetY ( ) ;
}
item - > AddToGround ( GetMapIndex ( ) , pos ) ;
item - > StartDestroyEvent ( ) ;
}
}
}
}
// <20> <> Ÿ<EFBFBD> <C5B8> <20> ƴ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ó<> <C3B3>
if ( type ! = DAMAGE_TYPE_NORMAL & & type ! = DAMAGE_TYPE_NORMAL_RANGE )
{
if ( IsAffectFlag ( AFF_TERROR ) )
{
int pct = GetSkillPower ( SKILL_TERROR ) / 400 ;
if ( number ( 1 , 100 ) < = pct )
return false ;
}
}
int iCurHP = GetHP ( ) ;
int iCurSP = GetSP ( ) ;
bool IsCritical = false ;
bool IsPenetrate = false ;
bool IsDeathBlow = false ;
enum DamageFlag
{
DAMAGE_NORMAL = ( 1 < < 0 ) ,
DAMAGE_POISON = ( 1 < < 1 ) ,
DAMAGE_DODGE = ( 1 < < 2 ) ,
DAMAGE_BLOCK = ( 1 < < 3 ) ,
DAMAGE_PENETRATE = ( 1 < < 4 ) ,
DAMAGE_CRITICAL = ( 1 < < 5 ) ,
} ;
//PROF_UNIT puAttr("Attr");
//
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ų<EFBFBD> <C5B3> , <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ų<EFBFBD> <C5B3> (<28> <> <EFBFBD> ڰ<EFBFBD> ) ũ<> <C5A9> Ƽ <EFBFBD> ð<EFBFBD> , <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> Ѵ <EFBFBD> .
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ʾ ƾ<CABE> <20> ϴµ<CFB4> Nerf(<28> ٿ<EFBFBD> <D9BF> 뷱<EFBFBD> <EBB7B1> )<29> <> ġ<EFBFBD> <C4A1> <20> <> <20> <> <20> <> <EFBFBD> ũ<> <C5A9> Ƽ <EFBFBD> ð<EFBFBD>
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ʰ<EFBFBD> , /2 <20> ̻<EFBFBD> <CCBB> Ͽ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ѵ <EFBFBD> .
//
// <20> <> <EFBFBD> <EFBFBD> <20> ̾߱Ⱑ <20> <> <EFBFBD> Ƽ <EFBFBD> <20> и<EFBFBD> <20> <> ų<EFBFBD> <C5B3> <20> ߰<EFBFBD>
//
// 20091109 : <20> <> <EFBFBD> 簡 <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> û<EFBFBD> <C3BB> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> г <EFBFBD> , <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> 70% <20> <> <EFBFBD> <EFBFBD>
//
if ( type = = DAMAGE_TYPE_MELEE | | type = = DAMAGE_TYPE_RANGE | | type = = DAMAGE_TYPE_MAGIC )
{
if ( pAttacker )
{
// ũ<> <C5A9> Ƽ <EFBFBD> <C6BC>
int iCriticalPct = pAttacker - > GetPoint ( POINT_CRITICAL_PCT ) ;
if ( ! IsPC ( ) )
iCriticalPct + = pAttacker - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_CRITICAL_BONUS ) ;
if ( iCriticalPct )
{
if ( iCriticalPct > = 10 ) // 10<31> <30> <EFBFBD> <EFBFBD> ũ<> <C5A9> 5% + (4<> <34> <EFBFBD> <EFBFBD> 1%<25> <> <20> <> <EFBFBD> <EFBFBD> ), <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ġ<EFBFBD> <C4A1> 50<35> ̸<EFBFBD> 20%
iCriticalPct = 5 + ( iCriticalPct - 10 ) / 4 ;
else // 10<31> <30> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ܼ<EFBFBD> <DCBC> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> , 10 = 5%
iCriticalPct / = 2 ;
//ũ<> <C5A9> Ƽ <EFBFBD> <C6BC> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> .
iCriticalPct - = GetPoint ( POINT_RESIST_CRITICAL ) ;
if ( number ( 1 , 100 ) < = iCriticalPct )
{
IsCritical = true ;
dam * = 2 ;
EffectPacket ( SE_CRITICAL ) ;
if ( IsAffectFlag ( AFF_MANASHIELD ) )
{
RemoveAffect ( AFF_MANASHIELD ) ;
}
}
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
int iPenetratePct = pAttacker - > GetPoint ( POINT_PENETRATE_PCT ) ;
if ( ! IsPC ( ) )
iPenetratePct + = pAttacker - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_PENETRATE_BONUS ) ;
if ( iPenetratePct )
{
{
CSkillProto * pkSk = CSkillManager : : instance ( ) . Get ( SKILL_RESIST_PENETRATE ) ;
if ( NULL ! = pkSk )
{
pkSk - > SetPointVar ( " k " , 1.0f * GetSkillPower ( SKILL_RESIST_PENETRATE ) / 100.0f ) ;
iPenetratePct - = static_cast < int > ( pkSk - > kPointPoly . Eval ( ) ) ;
}
}
if ( iPenetratePct > = 10 )
{
// 10<31> <30> <EFBFBD> <EFBFBD> ũ<> <C5A9> 5% + (4<> <34> <EFBFBD> <EFBFBD> 1%<25> <> <20> <> <EFBFBD> <EFBFBD> ), <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ġ<EFBFBD> <C4A1> 50<35> ̸<EFBFBD> 20%
iPenetratePct = 5 + ( iPenetratePct - 10 ) / 4 ;
}
else
{
// 10<31> <30> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ܼ<EFBFBD> <DCBC> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> , 10 = 5%
iPenetratePct / = 2 ;
}
//<2F> <> <EFBFBD> <EFBFBD> Ÿ<EFBFBD> <C5B8> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> .
iPenetratePct - = GetPoint ( POINT_RESIST_PENETRATE ) ;
if ( number ( 1 , 100 ) < = iPenetratePct )
{
IsPenetrate = true ;
if ( test_server )
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ߰<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> %d" ) , GetPoint ( POINT_DEF_GRADE ) * ( 100 + GetPoint ( POINT_DEF_BONUS ) ) / 100 ) ;
dam + = GetPoint ( POINT_DEF_GRADE ) * ( 100 + GetPoint ( POINT_DEF_BONUS ) ) / 100 ;
if ( IsAffectFlag ( AFF_MANASHIELD ) )
{
RemoveAffect ( AFF_MANASHIELD ) ;
}
}
}
}
}
//
// <20> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> , Ȱ <20> <> <EFBFBD> <EFBFBD> , <20> <> <20> <> Ÿ <20> <> <20> <> <EFBFBD> <EFBFBD> <20> Ӽ<EFBFBD> <D3BC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> Ѵ <EFBFBD> .
//
else if ( type = = DAMAGE_TYPE_NORMAL | | type = = DAMAGE_TYPE_NORMAL_RANGE )
{
if ( type = = DAMAGE_TYPE_NORMAL )
{
// <20> <> <EFBFBD> <EFBFBD> <20> <> Ÿ<EFBFBD> <C5B8> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD>
if ( GetPoint ( POINT_BLOCK ) & & number ( 1 , 100 ) < = GetPoint ( POINT_BLOCK ) )
{
if ( test_server )
{
pAttacker - > ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " %s <20> <> <EFBFBD> <EFBFBD> ! (%d%%) " ) , GetName ( ) , GetPoint ( POINT_BLOCK ) ) ;
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " %s <20> <> <EFBFBD> <EFBFBD> ! (%d%%) " ) , GetName ( ) , GetPoint ( POINT_BLOCK ) ) ;
}
SendDamagePacket ( pAttacker , 0 , DAMAGE_BLOCK ) ;
return false ;
}
}
else if ( type = = DAMAGE_TYPE_NORMAL_RANGE )
{
// <20> <> <EFBFBD> Ÿ<EFBFBD> <20> <> Ÿ<EFBFBD> <C5B8> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD>
if ( GetPoint ( POINT_DODGE ) & & number ( 1 , 100 ) < = GetPoint ( POINT_DODGE ) )
{
if ( test_server )
{
pAttacker - > ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " %s ȸ<> <C8B8> ! (%d%%) " ) , GetName ( ) , GetPoint ( POINT_DODGE ) ) ;
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " %s ȸ<> <C8B8> ! (%d%%) " ) , GetName ( ) , GetPoint ( POINT_DODGE ) ) ;
}
SendDamagePacket ( pAttacker , 0 , DAMAGE_DODGE ) ;
return false ;
}
}
if ( IsAffectFlag ( AFF_JEONGWIHON ) )
dam = ( int ) ( dam * ( 100 + GetSkillPower ( SKILL_JEONGWI ) * 25 / 100 ) / 100 ) ;
if ( IsAffectFlag ( AFF_TERROR ) )
dam = ( int ) ( dam * ( 95 - GetSkillPower ( SKILL_TERROR ) / 5 ) / 100 ) ;
if ( IsAffectFlag ( AFF_HOSIN ) )
dam = dam * ( 100 - GetPoint ( POINT_RESIST_NORMAL_DAMAGE ) ) / 100 ;
//
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> Ӽ<EFBFBD> <20> <> <EFBFBD> <EFBFBD>
//
if ( pAttacker )
{
if ( type = = DAMAGE_TYPE_NORMAL )
{
// <20> ݻ<EFBFBD>
if ( GetPoint ( POINT_REFLECT_MELEE ) )
{
int reflectDamage = dam * GetPoint ( POINT_REFLECT_MELEE ) / 100 ;
// NOTE: <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ڰ<EFBFBD> IMMUNE_REFLECT <20> Ӽ<EFBFBD> <D3BC> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ִٸ<D6B4> <20> ݻ縦 <20> <> <20> ϴ<EFBFBD> <20> <>
// <20> ƴ϶<C6B4> 1/3 <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ؼ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EEB0A1> <EFBFBD> <EFBFBD> <20> <> ȹ<EFBFBD> <C8B9> <EFBFBD> <EFBFBD> <20> <> û.
if ( pAttacker - > IsImmune ( IMMUNE_REFLECT ) )
reflectDamage = int ( reflectDamage / 3.0f + 0.5f ) ;
pAttacker - > Damage ( this , reflectDamage , DAMAGE_TYPE_SPECIAL ) ;
}
}
// ũ<> <C5A9> Ƽ <EFBFBD> <C6BC>
int iCriticalPct = pAttacker - > GetPoint ( POINT_CRITICAL_PCT ) ;
if ( ! IsPC ( ) )
iCriticalPct + = pAttacker - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_CRITICAL_BONUS ) ;
if ( iCriticalPct )
{
//ũ<> <C5A9> Ƽ <EFBFBD> <C6BC> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> .
iCriticalPct - = GetPoint ( POINT_RESIST_CRITICAL ) ;
if ( number ( 1 , 100 ) < = iCriticalPct )
{
IsCritical = true ;
dam * = 2 ;
EffectPacket ( SE_CRITICAL ) ;
}
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
int iPenetratePct = pAttacker - > GetPoint ( POINT_PENETRATE_PCT ) ;
if ( ! IsPC ( ) )
iPenetratePct + = pAttacker - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_PENETRATE_BONUS ) ;
{
CSkillProto * pkSk = CSkillManager : : instance ( ) . Get ( SKILL_RESIST_PENETRATE ) ;
if ( NULL ! = pkSk )
{
pkSk - > SetPointVar ( " k " , 1.0f * GetSkillPower ( SKILL_RESIST_PENETRATE ) / 100.0f ) ;
iPenetratePct - = static_cast < int > ( pkSk - > kPointPoly . Eval ( ) ) ;
}
}
if ( iPenetratePct )
{
//<2F> <> <EFBFBD> <EFBFBD> Ÿ<EFBFBD> <C5B8> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> .
iPenetratePct - = GetPoint ( POINT_RESIST_PENETRATE ) ;
if ( number ( 1 , 100 ) < = iPenetratePct )
{
IsPenetrate = true ;
if ( test_server )
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ߰<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> %d" ) , GetPoint ( POINT_DEF_GRADE ) * ( 100 + GetPoint ( POINT_DEF_BONUS ) ) / 100 ) ;
dam + = GetPoint ( POINT_DEF_GRADE ) * ( 100 + GetPoint ( POINT_DEF_BONUS ) ) / 100 ;
}
}
// HP <20> <> ƿ
if ( pAttacker - > GetPoint ( POINT_STEAL_HP ) )
{
int pct = 1 ;
if ( number ( 1 , 10 ) < = pct )
{
int iHP = MIN ( dam , MAX ( 0 , iCurHP ) ) * pAttacker - > GetPoint ( POINT_STEAL_HP ) / 100 ;
if ( iHP > 0 & & GetHP ( ) > = iHP )
{
CreateFly ( FLY_HP_SMALL , pAttacker ) ;
pAttacker - > PointChange ( POINT_HP , iHP ) ;
PointChange ( POINT_HP , - iHP ) ;
}
}
}
// SP <20> <> ƿ
if ( pAttacker - > GetPoint ( POINT_STEAL_SP ) )
{
int pct = 1 ;
if ( number ( 1 , 10 ) < = pct )
{
int iCur ;
if ( IsPC ( ) )
iCur = iCurSP ;
else
iCur = iCurHP ;
int iSP = MIN ( dam , MAX ( 0 , iCur ) ) * pAttacker - > GetPoint ( POINT_STEAL_SP ) / 100 ;
if ( iSP > 0 & & iCur > = iSP )
{
CreateFly ( FLY_SP_SMALL , pAttacker ) ;
pAttacker - > PointChange ( POINT_SP , iSP ) ;
if ( IsPC ( ) )
PointChange ( POINT_SP , - iSP ) ;
}
}
}
// <20> <> <20> <> ƿ
if ( pAttacker - > GetPoint ( POINT_STEAL_GOLD ) )
{
if ( number ( 1 , 100 ) < = pAttacker - > GetPoint ( POINT_STEAL_GOLD ) )
{
int iAmount = number ( 1 , GetLevel ( ) ) ;
pAttacker - > PointChange ( POINT_GOLD , iAmount ) ;
DBManager : : instance ( ) . SendMoneyLog ( MONEY_LOG_MISC , 1 , iAmount ) ;
}
}
// ĥ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> HPȸ<50> <C8B8>
if ( pAttacker - > GetPoint ( POINT_HIT_HP_RECOVERY ) & & number ( 0 , 4 ) > 0 ) // 80% Ȯ<> <C8AE>
{
int i = MIN ( dam , iCurHP ) * pAttacker - > GetPoint ( POINT_HIT_HP_RECOVERY ) / 100 ;
if ( i )
{
CreateFly ( FLY_HP_SMALL , pAttacker ) ;
pAttacker - > PointChange ( POINT_HP , i ) ;
}
}
// ĥ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> SPȸ<50> <C8B8>
if ( pAttacker - > GetPoint ( POINT_HIT_SP_RECOVERY ) & & number ( 0 , 4 ) > 0 ) // 80% Ȯ<> <C8AE>
{
int i = MIN ( dam , iCurHP ) * pAttacker - > GetPoint ( POINT_HIT_SP_RECOVERY ) / 100 ;
if ( i )
{
CreateFly ( FLY_SP_SMALL , pAttacker ) ;
pAttacker - > PointChange ( POINT_SP , i ) ;
}
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ش<EFBFBD> .
if ( pAttacker - > GetPoint ( POINT_MANA_BURN_PCT ) )
{
if ( number ( 1 , 100 ) < = pAttacker - > GetPoint ( POINT_MANA_BURN_PCT ) )
PointChange ( POINT_SP , - 50 ) ;
}
}
}
//
// <20> <> Ÿ <20> Ǵ<EFBFBD> <20> <> ų<EFBFBD> <C5B3> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ʽ <EFBFBD> <20> <> <EFBFBD> <EFBFBD> /<2F> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
//
switch ( type )
{
case DAMAGE_TYPE_NORMAL :
case DAMAGE_TYPE_NORMAL_RANGE :
if ( pAttacker )
if ( pAttacker - > GetPoint ( POINT_NORMAL_HIT_DAMAGE_BONUS ) )
dam = dam * ( 100 + pAttacker - > GetPoint ( POINT_NORMAL_HIT_DAMAGE_BONUS ) ) / 100 ;
dam = dam * ( 100 - MIN ( 99 , GetPoint ( POINT_NORMAL_HIT_DEFEND_BONUS ) ) ) / 100 ;
break ;
case DAMAGE_TYPE_MELEE :
case DAMAGE_TYPE_RANGE :
case DAMAGE_TYPE_FIRE :
case DAMAGE_TYPE_ICE :
case DAMAGE_TYPE_ELEC :
case DAMAGE_TYPE_MAGIC :
if ( pAttacker )
if ( pAttacker - > GetPoint ( POINT_SKILL_DAMAGE_BONUS ) )
dam = dam * ( 100 + pAttacker - > GetPoint ( POINT_SKILL_DAMAGE_BONUS ) ) / 100 ;
dam = dam * ( 100 - MIN ( 99 , GetPoint ( POINT_SKILL_DEFEND_BONUS ) ) ) / 100 ;
break ;
default :
break ;
}
//
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> (<28> <> <EFBFBD> ż<EFBFBD> ȣ )
//
if ( IsAffectFlag ( AFF_MANASHIELD ) )
{
// POINT_MANASHIELD <20> <> <20> ۾<EFBFBD> <DBBE> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
int iDamageSPPart = dam / 3 ;
int iDamageToSP = iDamageSPPart * GetPoint ( POINT_MANASHIELD ) / 100 ;
int iSP = GetSP ( ) ;
// SP<53> <50> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
if ( iDamageToSP < = iSP )
{
PointChange ( POINT_SP , - iDamageToSP ) ;
dam - = iDamageSPPart ;
}
else
{
2022-03-09 21:30:51 +02:00
// <20> <> <EFBFBD> ŷ<EFBFBD> <C5B7> <EFBFBD> <20> <> <EFBFBD> ڶ<EFBFBD> <DAB6> <EFBFBD> <20> ǰ<EFBFBD> <20> <> <20> ←<EFBFBD> <EFBFA9> <EFBFBD> <EFBFBD> ??
2022-03-05 12:44:06 +02:00
PointChange ( POINT_SP , - GetSP ( ) ) ;
dam - = iSP * 100 / MAX ( GetPoint ( POINT_MANASHIELD ) , 1 ) ;
}
}
//
// <20> <> ü <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> (<28> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> )
//
if ( GetPoint ( POINT_MALL_DEFBONUS ) > 0 )
{
int dec_dam = MIN ( 200 , dam * GetPoint ( POINT_MALL_DEFBONUS ) / 100 ) ;
dam - = dec_dam ;
}
if ( pAttacker )
{
//
// <20> <> ü <20> <> <EFBFBD> ݷ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> (<28> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> )
//
if ( pAttacker - > GetPoint ( POINT_MALL_ATTBONUS ) > 0 )
{
int add_dam = MIN ( 300 , dam * pAttacker - > GetLimitPoint ( POINT_MALL_ATTBONUS ) / 100 ) ;
dam + = add_dam ;
}
//
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ʽ <EFBFBD> (<28> ѱ<EFBFBD> <20> õ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> )
//
int iEmpire = GetEmpire ( ) ;
2022-03-12 11:39:41 +02:00
int lMapIndex = GetMapIndex ( ) ;
2022-03-05 12:44:06 +02:00
int iMapEmpire = SECTREE_MANAGER : : instance ( ) . GetEmpireFromMapIndex ( lMapIndex ) ;
if ( LC_IsYMIR ( ) = = true )
{
if ( iEmpire & & iMapEmpire & & iEmpire ! = iMapEmpire )
{
dam + = ( dam * 30 ) / 100 ;
}
}
if ( pAttacker - > IsPC ( ) )
{
iEmpire = pAttacker - > GetEmpire ( ) ;
lMapIndex = pAttacker - > GetMapIndex ( ) ;
iMapEmpire = SECTREE_MANAGER : : instance ( ) . GetEmpireFromMapIndex ( lMapIndex ) ;
// <20> ٸ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 10% <20> <> <EFBFBD> <EFBFBD>
if ( iEmpire & & iMapEmpire & & iEmpire ! = iMapEmpire )
{
int percent = 10 ;
if ( 184 < = lMapIndex & & lMapIndex < = 189 )
{
if ( LC_IsYMIR ( ) = = true )
percent = 7 ;
else
percent = 9 ;
}
else
{
if ( LC_IsYMIR ( ) = = true )
percent = 8 ;
else
percent = 9 ;
}
dam = dam * percent / 10 ;
}
if ( ! IsPC ( ) & & GetMonsterDrainSPPoint ( ) )
{
int iDrain = GetMonsterDrainSPPoint ( ) ;
if ( iDrain < = pAttacker - > GetSP ( ) )
pAttacker - > PointChange ( POINT_SP , - iDrain ) ;
else
{
int iSP = pAttacker - > GetSP ( ) ;
pAttacker - > PointChange ( POINT_SP , - iSP ) ;
}
}
}
else if ( pAttacker - > IsGuardNPC ( ) )
{
SET_BIT ( m_pointsInstant . instant_flag , INSTANT_FLAG_NO_REWARD ) ;
Stun ( ) ;
return true ;
}
//
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ݰ<EFBFBD> <DDB0> <EFBFBD> & <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
//
if ( pAttacker - > IsPC ( ) & & CMonarch : : instance ( ) . IsPowerUp ( pAttacker - > GetEmpire ( ) ) )
{
// 10% <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
dam + = dam / 10 ;
}
if ( IsPC ( ) & & CMonarch : : instance ( ) . IsDefenceUp ( GetEmpire ( ) ) )
{
// 10% <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
dam - = dam / 10 ;
}
}
//puAttr.Pop();
if ( ! GetSectree ( ) | | GetSectree ( ) - > IsAttr ( GetX ( ) , GetY ( ) , ATTR_BANPK ) )
return false ;
if ( ! IsPC ( ) )
{
if ( m_pkParty & & m_pkParty - > GetLeader ( ) )
m_pkParty - > GetLeader ( ) - > SetLastAttacked ( get_dword_time ( ) ) ;
else
SetLastAttacked ( get_dword_time ( ) ) ;
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> : <20> <> <EFBFBD> <EFBFBD> <20> <>
MonsterChat ( MONSTER_CHAT_ATTACKED ) ;
}
if ( IsStun ( ) )
{
Dead ( pAttacker ) ;
return true ;
}
if ( IsDead ( ) )
return true ;
// <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ʵ<EFBFBD> <CAB5> <EFBFBD> <20> <> .
if ( type = = DAMAGE_TYPE_POISON )
{
if ( GetHP ( ) - dam < = 0 )
{
dam = GetHP ( ) - 1 ;
}
}
// ------------------------
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ̾<EFBFBD> <20> <> <EFBFBD> <EFBFBD>
// -----------------------
if ( LC_IsGermany ( ) & & pAttacker & & pAttacker - > IsPC ( ) )
{
int iDmgPct = CHARACTER_MANAGER : : instance ( ) . GetUserDamageRate ( pAttacker ) ;
dam = dam * iDmgPct / 100 ;
}
// STONE SKIN : <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
if ( IsMonster ( ) & & IsStoneSkinner ( ) )
{
if ( GetHPPct ( ) < GetMobTable ( ) . bStoneSkinPoint )
dam / = 2 ;
}
//PROF_UNIT puRest1("Rest1");
if ( pAttacker )
{
// DEATH BLOW : Ȯ<> <C8AE> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 4<> <34> <20> <> <EFBFBD> <EFBFBD> (!? <20> <> <EFBFBD> <EFBFBD> <20> ̺<EFBFBD> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> )
if ( pAttacker - > IsMonster ( ) & & pAttacker - > IsDeathBlower ( ) )
{
if ( pAttacker - > IsDeathBlow ( ) )
{
if ( number ( 1 , 4 ) = = GetJob ( ) )
{
IsDeathBlow = true ;
dam = dam * 4 ;
}
}
}
dam = BlueDragon_Damage ( this , pAttacker , dam ) ;
BYTE damageFlag = 0 ;
if ( type = = DAMAGE_TYPE_POISON )
damageFlag = DAMAGE_POISON ;
else
damageFlag = DAMAGE_NORMAL ;
if ( IsCritical = = true )
damageFlag | = DAMAGE_CRITICAL ;
if ( IsPenetrate = = true )
damageFlag | = DAMAGE_PENETRATE ;
//<2F> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
float damMul = this - > GetDamMul ( ) ;
float tempDam = dam ;
dam = tempDam * damMul + 0.5f ;
if ( pAttacker )
SendDamagePacket ( pAttacker , dam , damageFlag ) ;
if ( test_server )
{
if ( pAttacker )
{
pAttacker - > ChatPacket ( CHAT_TYPE_INFO , " -> %s, DAM %d HP %d(%d%%) %s%s " ,
GetName ( ) ,
dam ,
GetHP ( ) ,
( GetHP ( ) * 100 ) / GetMaxHP ( ) ,
IsCritical ? " crit " : " " ,
IsPenetrate ? " pene " : " " ,
IsDeathBlow ? " deathblow " : " " ) ;
}
ChatPacket ( CHAT_TYPE_PARTY , " <- %s, DAM %d HP %d(%d%%) %s%s " ,
pAttacker ? pAttacker - > GetName ( ) : 0 ,
dam ,
GetHP ( ) ,
( GetHP ( ) * 100 ) / GetMaxHP ( ) ,
IsCritical ? " crit " : " " ,
IsPenetrate ? " pene " : " " ,
IsDeathBlow ? " deathblow " : " " ) ;
}
if ( m_bDetailLog )
{
ChatPacket ( CHAT_TYPE_INFO , LC_TEXT ( " %s[%d]<5D> <> <20> <> <EFBFBD> <EFBFBD> <20> <> ġ: %d %d " ) , pAttacker - > GetName ( ) , ( DWORD ) pAttacker - > GetVID ( ) , pAttacker - > GetX ( ) , pAttacker - > GetY ( ) ) ;
}
}
//
// !!!!!!!!! <20> <> <EFBFBD> <EFBFBD> HP<48> <50> <20> <> <EFBFBD> ̴<EFBFBD> <20> κ<EFBFBD> !!!!!!!!!
//
if ( ! cannot_dead )
{
PointChange ( POINT_HP , - dam , false ) ;
}
//puRest1.Pop();
//PROF_UNIT puRest2("Rest2");
if ( pAttacker & & dam > 0 & & IsNPC ( ) )
{
//PROF_UNIT puRest20("Rest20");
TDamageMap : : iterator it = m_map_kDamage . find ( pAttacker - > GetVID ( ) ) ;
if ( it = = m_map_kDamage . end ( ) )
{
m_map_kDamage . insert ( TDamageMap : : value_type ( pAttacker - > GetVID ( ) , TBattleInfo ( dam , 0 ) ) ) ;
it = m_map_kDamage . find ( pAttacker - > GetVID ( ) ) ;
}
else
{
it - > second . iTotalDamage + = dam ;
}
//puRest20.Pop();
//PROF_UNIT puRest21("Rest21");
StartRecoveryEvent ( ) ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ʹ <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ȸ<> <C8B8> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ѵ <EFBFBD> .
//puRest21.Pop();
//PROF_UNIT puRest22("Rest22");
UpdateAggrPointEx ( pAttacker , type , dam , it - > second ) ;
//puRest22.Pop();
}
//puRest2.Pop();
//PROF_UNIT puRest3("Rest3");
if ( GetHP ( ) < = 0 )
{
Stun ( ) ;
if ( pAttacker & & ! pAttacker - > IsNPC ( ) )
m_dwKillerPID = pAttacker - > GetPlayerID ( ) ;
else
m_dwKillerPID = 0 ;
}
return false ;
}
void CHARACTER : : DistributeHP ( LPCHARACTER pkKiller )
{
if ( pkKiller - > GetDungeon ( ) ) // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ΰ<EFBFBD> <CEB0> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ʴ´ <CAB4>
return ;
}
static void GiveExp ( LPCHARACTER from , LPCHARACTER to , int iExp )
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
iExp = CALCULATE_VALUE_LVDELTA ( to - > GetLevel ( ) , from - > GetLevel ( ) , iExp ) ;
// <20> ܺ<EFBFBD> <20> <EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ 3<> <33> <20> <> <EFBFBD> ʽ <EFBFBD>
if ( distribution_test_server )
iExp * = 3 ;
int iBaseExp = iExp ;
// <20> <> <EFBFBD> <EFBFBD> , ȸ<> <C8B8> <20> <> <EFBFBD> <EFBFBD> ġ <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD>
iExp = iExp * ( 100 + CPrivManager : : instance ( ) . GetPriv ( to , PRIV_EXP_PCT ) ) / 100 ;
// <20> <> <EFBFBD> ӳ<EFBFBD> <20> ⺻ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ǵ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
{
// <20> 뵿<EFBFBD> <EBB5BF> <20> <EFBFBD>
if ( to - > IsEquipUniqueItem ( UNIQUE_ITEM_LARBOR_MEDAL ) )
iExp + = iExp * 20 / 100 ;
// <20> <> <EFBFBD> <EFBFBD> Ÿ<EFBFBD> <C5B8> <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
if ( to - > GetMapIndex ( ) > = 660000 & & to - > GetMapIndex ( ) < 670000 )
iExp + = iExp * 20 / 100 ; // 1.2<EFBFBD> <EFBFBD> (20%)
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ <20> ι <EFBFBD> <20> Ӽ<EFBFBD>
if ( to - > GetPoint ( POINT_EXP_DOUBLE_BONUS ) )
if ( number ( 1 , 100 ) < = to - > GetPoint ( POINT_EXP_DOUBLE_BONUS ) )
iExp + = iExp * 30 / 100 ; // 1.3<EFBFBD> <EFBFBD> (30%)
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> (2<> ð<EFBFBD> ¥<EFBFBD> <C2A5> )
if ( to - > IsEquipUniqueItem ( UNIQUE_ITEM_DOUBLE_EXP ) )
iExp + = iExp * 50 / 100 ;
switch ( to - > GetMountVnum ( ) )
{
case 20110 :
case 20111 :
case 20112 :
case 20113 :
if ( to - > IsEquipUniqueItem ( 71115 ) | | to - > IsEquipUniqueItem ( 71117 ) | | to - > IsEquipUniqueItem ( 71119 ) | |
to - > IsEquipUniqueItem ( 71121 ) )
{
iExp + = iExp * 10 / 100 ;
}
break ;
case 20114 :
case 20120 :
case 20121 :
case 20122 :
case 20123 :
case 20124 :
case 20125 :
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
iExp + = iExp * 30 / 100 ;
break ;
}
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> Ǹ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
if ( LC_IsHongKong ( ) | | LC_IsEurope ( ) | | LC_IsCanada ( ) )
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> : <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> <EFBFBD>
if ( to - > GetPremiumRemainSeconds ( PREMIUM_EXP ) > 0 )
{
iExp + = ( iExp * 50 / 100 ) ;
}
if ( to - > IsEquipUniqueGroup ( UNIQUE_GROUP_RING_OF_EXP ) = = true )
{
iExp + = ( iExp * 50 / 100 ) ;
}
// PC<50> <43> <20> <> <EFBFBD> <EFBFBD> <20> <> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
if ( to - > GetPoint ( POINT_PC_BANG_EXP_BONUS ) > 0 )
{
if ( to - > IsPCBang ( ) = = true )
iExp + = ( iExp * to - > GetPoint ( POINT_PC_BANG_EXP_BONUS ) / 100 ) ;
}
// <20> <> ȥ <20> <> <EFBFBD> ʽ <EFBFBD>
iExp + = iExp * to - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_EXP_BONUS ) / 100 ;
}
else if ( /*LC_IsNewCIBN() || */ LC_IsBrazil ( ) )
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> : <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> <EFBFBD>
if ( to - > GetPremiumRemainSeconds ( PREMIUM_EXP ) > 0 )
{
iExp + = iExp ;
}
if ( to - > IsEquipUniqueGroup ( UNIQUE_GROUP_RING_OF_EXP ) = = true )
{
iExp + = iExp ;
}
// PC<50> <43> <20> <> <EFBFBD> <EFBFBD> <20> <> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
if ( to - > GetPoint ( POINT_PC_BANG_EXP_BONUS ) > 0 )
{
if ( to - > IsPCBang ( ) = = true )
iExp + = ( iExp * to - > GetPoint ( POINT_PC_BANG_EXP_BONUS ) / 100 ) ;
}
// <20> <> ȥ <20> <> <EFBFBD> ʽ <EFBFBD>
iExp + = iExp * to - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_EXP_BONUS ) / 100 ;
}
else
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> : <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> <EFBFBD>
if ( to - > GetPremiumRemainSeconds ( PREMIUM_EXP ) > 0 )
{
iExp + = ( iExp * 20 / 100 ) ;
}
if ( to - > IsEquipUniqueGroup ( UNIQUE_GROUP_RING_OF_EXP ) = = true )
{
iExp + = ( iExp * 20 / 100 ) ;
}
// PC<50> <43> <20> <> <EFBFBD> <EFBFBD> <20> <> ġ <20> <> <EFBFBD> ʽ <EFBFBD>
if ( to - > GetPoint ( POINT_PC_BANG_EXP_BONUS ) > 0 )
{
if ( to - > IsPCBang ( ) = = true )
iExp + = ( iExp * to - > GetPoint ( POINT_PC_BANG_EXP_BONUS ) / 100 ) ;
}
// <20> <> ȥ <20> <> <EFBFBD> ʽ <EFBFBD>
iExp + = iExp * to - > GetMarriageBonus ( UNIQUE_ITEM_MARRIAGE_EXP_BONUS ) / 100 ;
}
iExp + = ( iExp * to - > GetPoint ( POINT_RAMADAN_CANDY_BONUS_EXP ) / 100 ) ;
iExp + = ( iExp * to - > GetPoint ( POINT_MALL_EXPBONUS ) / 100 ) ;
iExp + = ( iExp * to - > GetPoint ( POINT_EXP ) / 100 ) ;
/* if (speed_server)
{
iExp + = iExp * CSpeedServerManager : : ExpBonus ( ) ;
}
*/
if ( test_server )
{
sys_log ( 0 , " Bonus Exp : Ramadan Candy: %d MallExp: %d PointExp: %d " ,
to - > GetPoint ( POINT_RAMADAN_CANDY_BONUS_EXP ) ,
to - > GetPoint ( POINT_MALL_EXPBONUS ) ,
to - > GetPoint ( POINT_EXP )
) ;
}
// <20> <> ȹ<EFBFBD> <C8B9> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 2005.04.21 <20> <> <EFBFBD> <EFBFBD> 85%
iExp = iExp * CHARACTER_MANAGER : : instance ( ) . GetMobExpRate ( to ) / 100 ;
// <20> <> <EFBFBD> <EFBFBD> ġ <20> ѹ<EFBFBD> ȹ<> 淮 <20> <> <EFBFBD> <EFBFBD>
iExp = MIN ( to - > GetNextExp ( ) / 10 , iExp ) ;
if ( test_server )
{
if ( quest : : CQuestManager : : instance ( ) . GetEventFlag ( " exp_bonus_log " ) & & iBaseExp > 0 )
to - > ChatPacket ( CHAT_TYPE_INFO , " exp bonus %d%% " , ( iExp - iBaseExp ) * 100 / iBaseExp ) ;
}
iExp = AdjustExpByLevel ( to , iExp ) ;
to - > PointChange ( POINT_EXP , iExp , true ) ;
from - > CreateFly ( FLY_EXP , to ) ;
{
LPCHARACTER you = to - > GetMarryPartner ( ) ;
// <20> κΰ<CEBA> <20> <> <EFBFBD> <EFBFBD> <20> <> Ƽ <EFBFBD> <C6BC> <EFBFBD> ̸<EFBFBD> <20> ݽ<EFBFBD> <DDBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
if ( you )
{
// 1<> <31> <EFBFBD> <EFBFBD> 100%
DWORD dwUpdatePoint = 2000 * iExp / to - > GetLevel ( ) / to - > GetLevel ( ) / 3 ;
if ( to - > GetPremiumRemainSeconds ( PREMIUM_MARRIAGE_FAST ) > 0 | |
you - > GetPremiumRemainSeconds ( PREMIUM_MARRIAGE_FAST ) > 0 )
dwUpdatePoint = ( DWORD ) ( dwUpdatePoint * 3 ) ;
marriage : : TMarriage * pMarriage = marriage : : CManager : : instance ( ) . Get ( to - > GetPlayerID ( ) ) ;
// DIVORCE_NULL_BUG_FIX
if ( pMarriage & & pMarriage - > IsNear ( ) )
pMarriage - > Update ( dwUpdatePoint ) ;
// END_OF_DIVORCE_NULL_BUG_FIX
}
}
}
namespace NPartyExpDistribute
{
struct FPartyTotaler
{
int total ;
int member_count ;
int x , y ;
FPartyTotaler ( LPCHARACTER center )
: total ( 0 ) , member_count ( 0 ) , x ( center - > GetX ( ) ) , y ( center - > GetY ( ) )
{ } ;
void operator ( ) ( LPCHARACTER ch )
{
if ( DISTANCE_APPROX ( ch - > GetX ( ) - x , ch - > GetY ( ) - y ) < = PARTY_DEFAULT_RANGE )
{
if ( LC_IsYMIR ( ) )
total + = ch - > GetLevel ( ) ;
else
total + = party_exp_distribute_table [ ch - > GetLevel ( ) ] ;
+ + member_count ;
}
}
} ;
struct FPartyDistributor
{
int total ;
LPCHARACTER c ;
int x , y ;
DWORD _iExp ;
int m_iMode ;
int m_iMemberCount ;
FPartyDistributor ( LPCHARACTER center , int member_count , int total , DWORD iExp , int iMode )
: total ( total ) , c ( center ) , x ( center - > GetX ( ) ) , y ( center - > GetY ( ) ) , _iExp ( iExp ) , m_iMode ( iMode ) , m_iMemberCount ( member_count )
{
if ( m_iMemberCount = = 0 )
m_iMemberCount = 1 ;
} ;
void operator ( ) ( LPCHARACTER ch )
{
if ( DISTANCE_APPROX ( ch - > GetX ( ) - x , ch - > GetY ( ) - y ) < = PARTY_DEFAULT_RANGE )
{
DWORD iExp2 = 0 ;
switch ( m_iMode )
{
case PARTY_EXP_DISTRIBUTION_NON_PARITY :
if ( LC_IsYMIR ( ) )
iExp2 = ( DWORD ) ( ( _iExp * ch - > GetLevel ( ) ) / total ) ;
else
iExp2 = ( DWORD ) ( _iExp * ( float ) party_exp_distribute_table [ ch - > GetLevel ( ) ] / total ) ;
break ;
case PARTY_EXP_DISTRIBUTION_PARITY :
iExp2 = _iExp / m_iMemberCount ;
break ;
default :
sys_err ( " Unknown party exp distribution mode %d " , m_iMode ) ;
return ;
}
GiveExp ( c , ch , iExp2 ) ;
}
}
} ;
}
typedef struct SDamageInfo
{
int iDam ;
LPCHARACTER pAttacker ;
LPPARTY pParty ;
void Clear ( )
{
pAttacker = NULL ;
pParty = NULL ;
}
inline void Distribute ( LPCHARACTER ch , int iExp )
{
if ( pAttacker )
GiveExp ( ch , pAttacker , iExp ) ;
else if ( pParty )
{
NPartyExpDistribute : : FPartyTotaler f ( ch ) ;
pParty - > ForEachOnlineMember ( f ) ;
if ( pParty - > IsPositionNearLeader ( ch ) )
iExp = iExp * ( 100 + pParty - > GetExpBonusPercent ( ) ) / 100 ;
if ( test_server )
{
if ( quest : : CQuestManager : : instance ( ) . GetEventFlag ( " exp_bonus_log " ) & & pParty - > GetExpBonusPercent ( ) )
pParty - > ChatPacketToAllMember ( CHAT_TYPE_INFO , " exp party bonus %d%% " , pParty - > GetExpBonusPercent ( ) ) ;
}
// <20> <> <EFBFBD> <EFBFBD> ġ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ֱ<EFBFBD> (<28> <> Ƽ <EFBFBD> <C6BC> ȹ<> <C8B9> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> 5% <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> )
if ( pParty - > GetExpCentralizeCharacter ( ) )
{
LPCHARACTER tch = pParty - > GetExpCentralizeCharacter ( ) ;
if ( DISTANCE_APPROX ( ch - > GetX ( ) - tch - > GetX ( ) , ch - > GetY ( ) - tch - > GetY ( ) ) < = PARTY_DEFAULT_RANGE )
{
int iExpCenteralize = ( int ) ( iExp * 0.05f ) ;
iExp - = iExpCenteralize ;
GiveExp ( ch , pParty - > GetExpCentralizeCharacter ( ) , iExpCenteralize ) ;
}
}
NPartyExpDistribute : : FPartyDistributor fDist ( ch , f . member_count , f . total , iExp , pParty - > GetExpDistributionMode ( ) ) ;
pParty - > ForEachOnlineMember ( fDist ) ;
}
}
} TDamageInfo ;
LPCHARACTER CHARACTER : : DistributeExp ( )
{
int iExpToDistribute = GetExp ( ) ;
if ( iExpToDistribute < = 0 )
return NULL ;
int iTotalDam = 0 ;
LPCHARACTER pkChrMostAttacked = NULL ;
int iMostDam = 0 ;
typedef std : : vector < TDamageInfo > TDamageInfoTable ;
TDamageInfoTable damage_info_table ;
std : : map < LPPARTY , TDamageInfo > map_party_damage ;
damage_info_table . reserve ( m_map_kDamage . size ( ) ) ;
TDamageMap : : iterator it = m_map_kDamage . begin ( ) ;
// <20> ϴ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ɷ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> . (50m)
while ( it ! = m_map_kDamage . end ( ) )
{
const VID & c_VID = it - > first ;
int iDam = it - > second . iTotalDamage ;
+ + it ;
LPCHARACTER pAttacker = CHARACTER_MANAGER : : instance ( ) . Find ( c_VID ) ;
// NPC<50> <43> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <20> ϳ <EFBFBD> ? -.-;
if ( ! pAttacker | | pAttacker - > IsNPC ( ) | | DISTANCE_APPROX ( GetX ( ) - pAttacker - > GetX ( ) , GetY ( ) - pAttacker - > GetY ( ) ) > 5000 )
continue ;
iTotalDam + = iDam ;
if ( ! pkChrMostAttacked | | iDam > iMostDam )
{
pkChrMostAttacked = pAttacker ;
iMostDam = iDam ;
}
if ( pAttacker - > GetParty ( ) )
{
std : : map < LPPARTY , TDamageInfo > : : iterator it = map_party_damage . find ( pAttacker - > GetParty ( ) ) ;
if ( it = = map_party_damage . end ( ) )
{
TDamageInfo di ;
di . iDam = iDam ;
di . pAttacker = NULL ;
di . pParty = pAttacker - > GetParty ( ) ;
map_party_damage . insert ( std : : make_pair ( di . pParty , di ) ) ;
}
else
{
it - > second . iDam + = iDam ;
}
}
else
{
TDamageInfo di ;
di . iDam = iDam ;
di . pAttacker = pAttacker ;
di . pParty = NULL ;
//sys_log(0, "__ pq_damage %s %d", pAttacker->GetName(), iDam);
//pq_damage.push(di);
damage_info_table . push_back ( di ) ;
}
}
for ( std : : map < LPPARTY , TDamageInfo > : : iterator it = map_party_damage . begin ( ) ; it ! = map_party_damage . end ( ) ; + + it )
{
damage_info_table . push_back ( it - > second ) ;
//sys_log(0, "__ pq_damage_party [%u] %d", it->second.pParty->GetLeaderPID(), it->second.iDam);
}
SetExp ( 0 ) ;
//m_map_kDamage.clear();
if ( iTotalDam = = 0 ) // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ذ<EFBFBD> 0<> ̸<EFBFBD> <20> <> <EFBFBD> <EFBFBD>
return NULL ;
if ( m_pkChrStone ) // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ѱ<EFBFBD> <D1B1> <EFBFBD> .
{
//sys_log(0, "__ Give half to Stone : %d", iExpToDistribute>>1);
int iExp = iExpToDistribute > > 1 ;
m_pkChrStone - > SetExp ( m_pkChrStone - > GetExp ( ) + iExp ) ;
iExpToDistribute - = iExp ;
}
sys_log ( 1 , " %s total exp: %d, damage_info_table.size() == %d, TotalDam %d " ,
GetName ( ) , iExpToDistribute , damage_info_table . size ( ) , iTotalDam ) ;
//sys_log(1, "%s total exp: %d, pq_damage.size() == %d, TotalDam %d",
//GetName(), iExpToDistribute, pq_damage.size(), iTotalDam);
if ( damage_info_table . empty ( ) )
return NULL ;
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> HP ȸ<> <C8B8> <EFBFBD> <EFBFBD> <20> Ѵ <EFBFBD> .
DistributeHP ( pkChrMostAttacked ) ; // <20> <> <EFBFBD> <EFBFBD> <20> ý<EFBFBD> <C3BD> <EFBFBD>
{
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ̳<EFBFBD> <20> <> Ƽ <EFBFBD> <C6BC> <20> <> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> 20% + <20> ڱⰡ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ŭ<EFBFBD> <C5AD> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> Դ´ <D4B4> .
TDamageInfoTable : : iterator di = damage_info_table . begin ( ) ;
{
TDamageInfoTable : : iterator it ;
for ( it = damage_info_table . begin ( ) ; it ! = damage_info_table . end ( ) ; + + it )
{
if ( it - > iDam > di - > iDam )
di = it ;
}
}
int iExp = iExpToDistribute / 5 ;
iExpToDistribute - = iExp ;
float fPercent = ( float ) di - > iDam / iTotalDam ;
if ( fPercent > 1.0f )
{
sys_err ( " DistributeExp percent over 1.0 (fPercent %f name %s) " , fPercent , di - > pAttacker - > GetName ( ) ) ;
fPercent = 1.0f ;
}
iExp + = ( int ) ( iExpToDistribute * fPercent ) ;
//sys_log(0, "%s given exp percent %.1f + 20 dam %d", GetName(), fPercent * 100.0f, di.iDam);
di - > Distribute ( this , iExp ) ;
// 100% <20> <> <20> Ծ<EFBFBD> <D4BE> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ѵ <EFBFBD> .
if ( fPercent = = 1.0f )
return pkChrMostAttacked ;
di - > Clear ( ) ;
}
{
// <20> <> <EFBFBD> <EFBFBD> 80%<25> <> <20> <> <EFBFBD> <EFBFBD> ġ<EFBFBD> <C4A1> <20> й<EFBFBD> <D0B9> Ѵ <EFBFBD> .
TDamageInfoTable : : iterator it ;
for ( it = damage_info_table . begin ( ) ; it ! = damage_info_table . end ( ) ; + + it )
{
TDamageInfo & di = * it ;
float fPercent = ( float ) di . iDam / iTotalDam ;
if ( fPercent > 1.0f )
{
sys_err ( " DistributeExp percent over 1.0 (fPercent %f name %s) " , fPercent , di . pAttacker - > GetName ( ) ) ;
fPercent = 1.0f ;
}
//sys_log(0, "%s given exp percent %.1f dam %d", GetName(), fPercent * 100.0f, di.iDam);
di . Distribute ( this , ( int ) ( iExpToDistribute * fPercent ) ) ;
}
}
return pkChrMostAttacked ;
}
// ȭ<> <C8AD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <>
int CHARACTER : : GetArrowAndBow ( LPITEM * ppkBow , LPITEM * ppkArrow , int iArrowCount /* = 1 */ )
{
LPITEM pkBow ;
if ( ! ( pkBow = GetWear ( WEAR_WEAPON ) ) | | pkBow - > GetProto ( ) - > bSubType ! = WEAPON_BOW )
{
return 0 ;
}
LPITEM pkArrow ;
if ( ! ( pkArrow = GetWear ( WEAR_ARROW ) ) | | pkArrow - > GetType ( ) ! = ITEM_WEAPON | |
pkArrow - > GetProto ( ) - > bSubType ! = WEAPON_ARROW )
{
return 0 ;
}
iArrowCount = MIN ( iArrowCount , pkArrow - > GetCount ( ) ) ;
* ppkBow = pkBow ;
* ppkArrow = pkArrow ;
return iArrowCount ;
}
void CHARACTER : : UseArrow ( LPITEM pkArrow , DWORD dwArrowCount )
{
int iCount = pkArrow - > GetCount ( ) ;
DWORD dwVnum = pkArrow - > GetVnum ( ) ;
iCount = iCount - MIN ( iCount , dwArrowCount ) ;
pkArrow - > SetCount ( iCount ) ;
if ( iCount = = 0 )
{
LPITEM pkNewArrow = FindSpecifyItem ( dwVnum ) ;
sys_log ( 0 , " UseArrow : FindSpecifyItem %u %p " , dwVnum , get_pointer ( pkNewArrow ) ) ;
if ( pkNewArrow )
EquipItem ( pkNewArrow ) ;
}
}
class CFuncShoot
{
public :
LPCHARACTER m_me ;
BYTE m_bType ;
bool m_bSucceed ;
2022-03-12 11:39:41 +02:00
CFuncShoot ( LPCHARACTER ch , BYTE bType ) : m_me ( ch ) , m_bType ( bType ) , m_bSucceed ( false )
2022-03-05 12:44:06 +02:00
{
}
void operator ( ) ( DWORD dwTargetVID )
{
if ( m_bType > 1 )
{
if ( g_bSkillDisable )
return ;
m_me - > m_SkillUseInfo [ m_bType ] . SetMainTargetVID ( dwTargetVID ) ;
/*if (m_bType == SKILL_BIPABU || m_bType == SKILL_KWANKYEOK)
m_me - > m_SkillUseInfo [ m_bType ] . ResetHitCount ( ) ; */
}
LPCHARACTER pkVictim = CHARACTER_MANAGER : : instance ( ) . Find ( dwTargetVID ) ;
if ( ! pkVictim )
return ;
// <20> <> <EFBFBD> <EFBFBD> <20> Ұ<EFBFBD>
if ( ! battle_is_attackable ( m_me , pkVictim ) )
return ;
if ( m_me - > IsNPC ( ) )
{
if ( DISTANCE_APPROX ( m_me - > GetX ( ) - pkVictim - > GetX ( ) , m_me - > GetY ( ) - pkVictim - > GetY ( ) ) > 5000 )
return ;
}
LPITEM pkBow , pkArrow ;
switch ( m_bType )
{
case 0 : // <20> Ϲ <EFBFBD> Ȱ
{
int iDam = 0 ;
if ( m_me - > IsPC ( ) )
{
if ( m_me - > GetJob ( ) ! = JOB_ASSASSIN )
return ;
if ( 0 = = m_me - > GetArrowAndBow ( & pkBow , & pkArrow ) )
return ;
if ( m_me - > GetSkillGroup ( ) ! = 0 )
if ( ! m_me - > IsNPC ( ) & & m_me - > GetSkillGroup ( ) ! = 2 )
{
if ( m_me - > GetSP ( ) < 5 )
return ;
m_me - > PointChange ( POINT_SP , - 5 ) ;
}
iDam = CalcArrowDamage ( m_me , pkVictim , pkBow , pkArrow ) ;
m_me - > UseArrow ( pkArrow , 1 ) ;
// check speed hack
DWORD dwCurrentTime = get_dword_time ( ) ;
if ( IS_SPEED_HACK ( m_me , pkVictim , dwCurrentTime ) )
iDam = 0 ;
}
else
iDam = CalcMeleeDamage ( m_me , pkVictim ) ;
NormalAttackAffect ( m_me , pkVictim ) ;
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
iDam = iDam * ( 100 - pkVictim - > GetPoint ( POINT_RESIST_BOW ) ) / 100 ;
//sys_log(0, "%s arrow %s dam %d", m_me->GetName(), pkVictim->GetName(), iDam);
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
pkVictim - > Damage ( m_me , iDam , DAMAGE_TYPE_NORMAL_RANGE ) ;
// Ÿ<> <C5B8> ġ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <>
}
break ;
case 1 : // <20> Ϲ <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
{
int iDam ;
if ( m_me - > IsPC ( ) )
return ;
iDam = CalcMagicDamage ( m_me , pkVictim ) ;
NormalAttackAffect ( m_me , pkVictim ) ;
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
iDam = iDam * ( 100 - pkVictim - > GetPoint ( POINT_RESIST_MAGIC ) ) / 100 ;
//sys_log(0, "%s arrow %s dam %d", m_me->GetName(), pkVictim->GetName(), iDam);
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
pkVictim - > Damage ( m_me , iDam , DAMAGE_TYPE_MAGIC ) ;
// Ÿ<> <C5B8> ġ <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <>
}
break ;
case SKILL_YEONSA : // <20> <> <EFBFBD> <EFBFBD>
{
//int iUseArrow = 2 + (m_me->GetSkillPower(SKILL_YEONSA) *6/100);
int iUseArrow = 1 ;
// <20> <> Ż<EFBFBD> <C5BB> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ°<CFB4> <C2B0> <EFBFBD>
{
if ( iUseArrow = = m_me - > GetArrowAndBow ( & pkBow , & pkArrow , iUseArrow ) )
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
m_me - > UseArrow ( pkArrow , iUseArrow ) ;
if ( pkVictim - > IsDead ( ) )
break ;
}
else
break ;
}
}
break ;
case SKILL_KWANKYEOK :
{
int iUseArrow = 1 ;
if ( iUseArrow = = m_me - > GetArrowAndBow ( & pkBow , & pkArrow , iUseArrow ) )
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
sys_log ( 0 , " %s kwankeyok %s " , m_me - > GetName ( ) , pkVictim - > GetName ( ) ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
m_me - > UseArrow ( pkArrow , iUseArrow ) ;
}
}
break ;
case SKILL_GIGUNG :
{
int iUseArrow = 1 ;
if ( iUseArrow = = m_me - > GetArrowAndBow ( & pkBow , & pkArrow , iUseArrow ) )
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
sys_log ( 0 , " %s gigung %s " , m_me - > GetName ( ) , pkVictim - > GetName ( ) ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
m_me - > UseArrow ( pkArrow , iUseArrow ) ;
}
}
break ;
case SKILL_HWAJO :
{
int iUseArrow = 1 ;
if ( iUseArrow = = m_me - > GetArrowAndBow ( & pkBow , & pkArrow , iUseArrow ) )
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
sys_log ( 0 , " %s hwajo %s " , m_me - > GetName ( ) , pkVictim - > GetName ( ) ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
m_me - > UseArrow ( pkArrow , iUseArrow ) ;
}
}
break ;
case SKILL_HORSE_WILDATTACK_RANGE :
{
int iUseArrow = 1 ;
if ( iUseArrow = = m_me - > GetArrowAndBow ( & pkBow , & pkArrow , iUseArrow ) )
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
sys_log ( 0 , " %s horse_wildattack %s " , m_me - > GetName ( ) , pkVictim - > GetName ( ) ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
m_me - > UseArrow ( pkArrow , iUseArrow ) ;
}
}
break ;
case SKILL_MARYUNG :
//case SKILL_GUMHWAN:
case SKILL_TUSOK :
case SKILL_BIPABU :
case SKILL_NOEJEON :
case SKILL_GEOMPUNG :
case SKILL_SANGONG :
case SKILL_MAHWAN :
case SKILL_PABEOB :
//case SKILL_CURSE:
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
sys_log ( 0 , " %s - Skill %d -> %s " , m_me - > GetName ( ) , m_bType , pkVictim - > GetName ( ) ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
}
break ;
case SKILL_CHAIN :
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
if ( pkVictim - > CanBeginFight ( ) )
pkVictim - > BeginFight ( m_me ) ;
sys_log ( 0 , " %s - Skill %d -> %s " , m_me - > GetName ( ) , m_bType , pkVictim - > GetName ( ) ) ;
m_me - > ComputeSkill ( m_bType , pkVictim ) ;
// TODO <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> <> <20> <> <20> ϱ <EFBFBD>
}
break ;
case SKILL_YONGBI :
{
m_me - > OnMove ( true ) ;
}
break ;
/*case SKILL_BUDONG:
{
m_me - > OnMove ( true ) ;
pkVictim - > OnMove ( ) ;
DWORD * pdw ;
DWORD dwEI = AllocEventInfo ( sizeof ( DWORD ) * 2 , & pdw ) ;
pdw [ 0 ] = m_me - > GetVID ( ) ;
pdw [ 1 ] = pkVictim - > GetVID ( ) ;
event_create ( budong_event_func , dwEI , PASSES_PER_SEC ( 1 ) ) ;
}
break ; */
default :
sys_err ( " CFuncShoot: I don't know this type [%d] of range attack. " , ( int ) m_bType ) ;
break ;
}
2022-03-09 21:30:51 +02:00
m_bSucceed = true ;
2022-03-05 12:44:06 +02:00
}
} ;
bool CHARACTER : : Shoot ( BYTE bType )
{
sys_log ( 1 , " Shoot %s type %u flyTargets.size %zu " , GetName ( ) , bType , m_vec_dwFlyTargets . size ( ) ) ;
if ( ! CanMove ( ) )
{
return false ;
}
CFuncShoot f ( this , bType ) ;
if ( m_dwFlyTargetID ! = 0 )
{
f ( m_dwFlyTargetID ) ;
m_dwFlyTargetID = 0 ;
}
f = std : : for_each ( m_vec_dwFlyTargets . begin ( ) , m_vec_dwFlyTargets . end ( ) , f ) ;
m_vec_dwFlyTargets . clear ( ) ;
return f . m_bSucceed ;
}
2022-03-12 11:39:41 +02:00
void CHARACTER : : FlyTarget ( DWORD dwTargetVID , int x , int y , BYTE bHeader )
2022-03-05 12:44:06 +02:00
{
LPCHARACTER pkVictim = CHARACTER_MANAGER : : instance ( ) . Find ( dwTargetVID ) ;
TPacketGCFlyTargeting pack ;
//pack.bHeader = HEADER_GC_FLY_TARGETING;
pack . bHeader = ( bHeader = = HEADER_CG_FLY_TARGETING ) ? HEADER_GC_FLY_TARGETING : HEADER_GC_ADD_FLY_TARGETING ;
pack . dwShooterVID = GetVID ( ) ;
if ( pkVictim )
{
pack . dwTargetVID = pkVictim - > GetVID ( ) ;
pack . x = pkVictim - > GetX ( ) ;
pack . y = pkVictim - > GetY ( ) ;
if ( bHeader = = HEADER_CG_FLY_TARGETING )
m_dwFlyTargetID = dwTargetVID ;
else
m_vec_dwFlyTargets . push_back ( dwTargetVID ) ;
}
else
{
pack . dwTargetVID = 0 ;
pack . x = x ;
pack . y = y ;
}
sys_log ( 1 , " FlyTarget %s vid %d x %d y %d " , GetName ( ) , pack . dwTargetVID , pack . x , pack . y ) ;
PacketAround ( & pack , sizeof ( pack ) , this ) ;
}
LPCHARACTER CHARACTER : : GetNearestVictim ( LPCHARACTER pkChr )
{
if ( NULL = = pkChr )
pkChr = this ;
float fMinDist = 99999.0f ;
LPCHARACTER pkVictim = NULL ;
TDamageMap : : iterator it = m_map_kDamage . begin ( ) ;
// <20> ϴ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ɷ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> .
while ( it ! = m_map_kDamage . end ( ) )
{
const VID & c_VID = it - > first ;
+ + it ;
LPCHARACTER pAttacker = CHARACTER_MANAGER : : instance ( ) . Find ( c_VID ) ;
if ( ! pAttacker )
continue ;
if ( pAttacker - > IsAffectFlag ( AFF_EUNHYUNG ) | |
pAttacker - > IsAffectFlag ( AFF_INVISIBILITY ) | |
pAttacker - > IsAffectFlag ( AFF_REVIVE_INVISIBLE ) )
continue ;
float fDist = DISTANCE_APPROX ( pAttacker - > GetX ( ) - pkChr - > GetX ( ) , pAttacker - > GetY ( ) - pkChr - > GetY ( ) ) ;
if ( fDist < fMinDist )
{
pkVictim = pAttacker ;
fMinDist = fDist ;
}
}
return pkVictim ;
}
void CHARACTER : : SetVictim ( LPCHARACTER pkVictim )
{
if ( ! pkVictim )
{
if ( 0 ! = ( DWORD ) m_kVIDVictim )
MonsterLog ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> " ) ;
m_kVIDVictim . Reset ( ) ;
battle_end ( this ) ;
}
else
{
if ( m_kVIDVictim ! = pkVictim - > GetVID ( ) )
MonsterLog ( " <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> : %s" , pkVictim - > GetName ( ) ) ;
m_kVIDVictim = pkVictim - > GetVID ( ) ;
m_dwLastVictimSetTime = get_dword_time ( ) ;
}
}
LPCHARACTER CHARACTER : : GetVictim ( ) const
{
return CHARACTER_MANAGER : : instance ( ) . Find ( m_kVIDVictim ) ;
}
LPCHARACTER CHARACTER : : GetProtege ( ) const // <20> <> ȣ <EFBFBD> ؾ<EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
{
if ( m_pkChrStone )
return m_pkChrStone ;
if ( m_pkParty )
return m_pkParty - > GetLeader ( ) ;
return NULL ;
}
int CHARACTER : : GetAlignment ( ) const
{
return m_iAlignment ;
}
int CHARACTER : : GetRealAlignment ( ) const
{
return m_iRealAlignment ;
}
void CHARACTER : : ShowAlignment ( bool bShow )
{
if ( bShow )
{
if ( m_iAlignment ! = m_iRealAlignment )
{
m_iAlignment = m_iRealAlignment ;
UpdatePacket ( ) ;
}
}
else
{
if ( m_iAlignment ! = 0 )
{
m_iAlignment = 0 ;
UpdatePacket ( ) ;
}
}
}
void CHARACTER : : UpdateAlignment ( int iAmount )
{
bool bShow = false ;
if ( m_iAlignment = = m_iRealAlignment )
bShow = true ;
int i = m_iAlignment / 10 ;
m_iRealAlignment = MINMAX ( - 200000 , m_iRealAlignment + iAmount , 200000 ) ;
if ( bShow )
{
m_iAlignment = m_iRealAlignment ;
if ( i ! = m_iAlignment / 10 )
UpdatePacket ( ) ;
}
}
void CHARACTER : : SetKillerMode ( bool isOn )
{
if ( ( isOn ? ADD_CHARACTER_STATE_KILLER : 0 ) = = IS_SET ( m_bAddChrState , ADD_CHARACTER_STATE_KILLER ) )
return ;
if ( isOn )
SET_BIT ( m_bAddChrState , ADD_CHARACTER_STATE_KILLER ) ;
else
REMOVE_BIT ( m_bAddChrState , ADD_CHARACTER_STATE_KILLER ) ;
m_iKillerModePulse = thecore_pulse ( ) ;
UpdatePacket ( ) ;
sys_log ( 0 , " SetKillerMode Update %s[%d] " , GetName ( ) , GetPlayerID ( ) ) ;
}
bool CHARACTER : : IsKillerMode ( ) const
{
return IS_SET ( m_bAddChrState , ADD_CHARACTER_STATE_KILLER ) ;
}
void CHARACTER : : UpdateKillerMode ( )
{
if ( ! IsKillerMode ( ) )
return ;
int iKillerSeconds = ! LC_IsYMIR ( ) ? 30 : 60 ;
if ( thecore_pulse ( ) - m_iKillerModePulse > = PASSES_PER_SEC ( iKillerSeconds ) )
SetKillerMode ( false ) ;
}
void CHARACTER : : SetPKMode ( BYTE bPKMode )
{
if ( bPKMode > = PK_MODE_MAX_NUM )
return ;
if ( m_bPKMode = = bPKMode )
return ;
if ( bPKMode = = PK_MODE_GUILD & & ! GetGuild ( ) )
bPKMode = PK_MODE_FREE ;
m_bPKMode = bPKMode ;
UpdatePacket ( ) ;
sys_log ( 0 , " PK_MODE: %s %d " , GetName ( ) , m_bPKMode ) ;
}
BYTE CHARACTER : : GetPKMode ( ) const
{
return m_bPKMode ;
}
struct FuncForgetMyAttacker
{
LPCHARACTER m_ch ;
FuncForgetMyAttacker ( LPCHARACTER ch )
{
m_ch = ch ;
}
void operator ( ) ( LPENTITY ent )
{
if ( ent - > IsType ( ENTITY_CHARACTER ) )
{
LPCHARACTER ch = ( LPCHARACTER ) ent ;
if ( ch - > IsPC ( ) )
return ;
if ( ch - > m_kVIDVictim = = m_ch - > GetVID ( ) )
ch - > SetVictim ( NULL ) ;
}
}
} ;
struct FuncAggregateMonster
{
LPCHARACTER m_ch ;
FuncAggregateMonster ( LPCHARACTER ch )
{
m_ch = ch ;
}
void operator ( ) ( LPENTITY ent )
{
if ( ent - > IsType ( ENTITY_CHARACTER ) )
{
LPCHARACTER ch = ( LPCHARACTER ) ent ;
if ( ch - > IsPC ( ) )
return ;
if ( ! ch - > IsMonster ( ) )
return ;
if ( ch - > GetVictim ( ) )
return ;
if ( number ( 1 , 100 ) < = 50 ) // <20> ӽ÷<D3BD> 50% Ȯ<> <C8AE> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ´ <EFBFBD>
if ( DISTANCE_APPROX ( ch - > GetX ( ) - m_ch - > GetX ( ) , ch - > GetY ( ) - m_ch - > GetY ( ) ) < 5000 )
if ( ch - > CanBeginFight ( ) )
ch - > BeginFight ( m_ch ) ;
}
}
} ;
struct FuncAttractRanger
{
LPCHARACTER m_ch ;
FuncAttractRanger ( LPCHARACTER ch )
{
m_ch = ch ;
}
void operator ( ) ( LPENTITY ent )
{
if ( ent - > IsType ( ENTITY_CHARACTER ) )
{
LPCHARACTER ch = ( LPCHARACTER ) ent ;
if ( ch - > IsPC ( ) )
return ;
if ( ! ch - > IsMonster ( ) )
return ;
if ( ch - > GetVictim ( ) & & ch - > GetVictim ( ) ! = m_ch )
return ;
if ( ch - > GetMobAttackRange ( ) > 150 )
{
int iNewRange = 150 ; //(int)(ch->GetMobAttackRange() * 0.2);
if ( iNewRange < 150 )
iNewRange = 150 ;
ch - > AddAffect ( AFFECT_BOW_DISTANCE , POINT_BOW_DISTANCE , iNewRange - ch - > GetMobAttackRange ( ) , AFF_NONE , 3 * 60 , 0 , false ) ;
}
}
}
} ;
struct FuncPullMonster
{
LPCHARACTER m_ch ;
int m_iLength ;
FuncPullMonster ( LPCHARACTER ch , int iLength = 300 )
{
m_ch = ch ;
m_iLength = iLength ;
}
void operator ( ) ( LPENTITY ent )
{
if ( ent - > IsType ( ENTITY_CHARACTER ) )
{
LPCHARACTER ch = ( LPCHARACTER ) ent ;
if ( ch - > IsPC ( ) )
return ;
if ( ! ch - > IsMonster ( ) )
return ;
//if (ch->GetVictim() && ch->GetVictim() != m_ch)
//return;
float fDist = DISTANCE_APPROX ( m_ch - > GetX ( ) - ch - > GetX ( ) , m_ch - > GetY ( ) - ch - > GetY ( ) ) ;
if ( fDist > 3000 | | fDist < 100 )
return ;
float fNewDist = fDist - m_iLength ;
if ( fNewDist < 100 )
fNewDist = 100 ;
float degree = GetDegreeFromPositionXY ( ch - > GetX ( ) , ch - > GetY ( ) , m_ch - > GetX ( ) , m_ch - > GetY ( ) ) ;
float fx ;
float fy ;
GetDeltaByDegree ( degree , fDist - fNewDist , & fx , & fy ) ;
2022-03-12 11:39:41 +02:00
int tx = ( int ) ( ch - > GetX ( ) + fx ) ;
int ty = ( int ) ( ch - > GetY ( ) + fy ) ;
2022-03-05 12:44:06 +02:00
ch - > Sync ( tx , ty ) ;
ch - > Goto ( tx , ty ) ;
ch - > CalculateMoveDuration ( ) ;
ch - > SyncPacket ( ) ;
}
}
} ;
void CHARACTER : : ForgetMyAttacker ( )
{
LPSECTREE pSec = GetSectree ( ) ;
if ( pSec )
{
FuncForgetMyAttacker f ( this ) ;
pSec - > ForEachAround ( f ) ;
}
ReviveInvisible ( 5 ) ;
}
void CHARACTER : : AggregateMonster ( )
{
LPSECTREE pSec = GetSectree ( ) ;
if ( pSec )
{
FuncAggregateMonster f ( this ) ;
pSec - > ForEachAround ( f ) ;
}
}
void CHARACTER : : AttractRanger ( )
{
LPSECTREE pSec = GetSectree ( ) ;
if ( pSec )
{
FuncAttractRanger f ( this ) ;
pSec - > ForEachAround ( f ) ;
}
}
void CHARACTER : : PullMonster ( )
{
LPSECTREE pSec = GetSectree ( ) ;
if ( pSec )
{
FuncPullMonster f ( this ) ;
pSec - > ForEachAround ( f ) ;
}
}
void CHARACTER : : UpdateAggrPointEx ( LPCHARACTER pAttacker , EDamageType type , int dam , CHARACTER : : TBattleInfo & info )
{
// Ư<> <C6AF> <20> <> <EFBFBD> <EFBFBD> Ÿ<EFBFBD> Կ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> ö<C3B6>
switch ( type )
{
case DAMAGE_TYPE_NORMAL_RANGE :
dam = ( int ) ( dam * 1.2f ) ;
break ;
case DAMAGE_TYPE_RANGE :
dam = ( int ) ( dam * 1.5f ) ;
break ;
case DAMAGE_TYPE_MAGIC :
dam = ( int ) ( dam * 1.2f ) ;
break ;
default :
break ;
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ڰ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ʽ <EFBFBD> <CABD> <EFBFBD> <20> ش<EFBFBD> .
if ( pAttacker = = GetVictim ( ) )
dam = ( int ) ( dam * 1.2f ) ;
info . iAggro + = dam ;
if ( info . iAggro < 0 )
info . iAggro = 0 ;
//sys_log(0, "UpdateAggrPointEx for %s by %s dam %d total %d", GetName(), pAttacker->GetName(), dam, total);
if ( GetParty ( ) & & dam > 0 & & type ! = DAMAGE_TYPE_SPECIAL )
{
LPPARTY pParty = GetParty ( ) ;
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ϴ<EFBFBD>
int iPartyAggroDist = dam ;
if ( pParty - > GetLeaderPID ( ) = = GetVID ( ) )
iPartyAggroDist / = 2 ;
else
iPartyAggroDist / = 3 ;
pParty - > SendMessage ( this , PM_AGGRO_INCREASE , iPartyAggroDist , pAttacker - > GetVID ( ) ) ;
}
ChangeVictimByAggro ( info . iAggro , pAttacker ) ;
}
void CHARACTER : : UpdateAggrPoint ( LPCHARACTER pAttacker , EDamageType type , int dam )
{
if ( IsDead ( ) | | IsStun ( ) )
return ;
TDamageMap : : iterator it = m_map_kDamage . find ( pAttacker - > GetVID ( ) ) ;
if ( it = = m_map_kDamage . end ( ) )
{
m_map_kDamage . insert ( TDamageMap : : value_type ( pAttacker - > GetVID ( ) , TBattleInfo ( 0 , dam ) ) ) ;
it = m_map_kDamage . find ( pAttacker - > GetVID ( ) ) ;
}
UpdateAggrPointEx ( pAttacker , type , dam , it - > second ) ;
}
void CHARACTER : : ChangeVictimByAggro ( int iNewAggro , LPCHARACTER pNewVictim )
{
if ( get_dword_time ( ) - m_dwLastVictimSetTime < 3000 ) // 3<> ʴ<EFBFBD> <20> <> <EFBFBD> ٷ<EFBFBD> <D9B7> <EFBFBD> <EFBFBD> Ѵ <EFBFBD>
return ;
if ( pNewVictim = = GetVictim ( ) )
{
if ( m_iMaxAggro < iNewAggro )
{
m_iMaxAggro = iNewAggro ;
return ;
}
// Aggro<72> <6F> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
TDamageMap : : iterator it ;
TDamageMap : : iterator itFind = m_map_kDamage . end ( ) ;
for ( it = m_map_kDamage . begin ( ) ; it ! = m_map_kDamage . end ( ) ; + + it )
{
if ( it - > second . iAggro > iNewAggro )
{
LPCHARACTER ch = CHARACTER_MANAGER : : instance ( ) . Find ( it - > first ) ;
if ( ch & & ! ch - > IsDead ( ) & & DISTANCE_APPROX ( ch - > GetX ( ) - GetX ( ) , ch - > GetY ( ) - GetY ( ) ) < 5000 )
{
itFind = it ;
iNewAggro = it - > second . iAggro ;
}
}
}
if ( itFind ! = m_map_kDamage . end ( ) )
{
m_iMaxAggro = iNewAggro ;
SetVictim ( CHARACTER_MANAGER : : instance ( ) . Find ( itFind - > first ) ) ;
m_dwStateDuration = 1 ;
}
}
else
{
if ( m_iMaxAggro < iNewAggro )
{
m_iMaxAggro = iNewAggro ;
SetVictim ( pNewVictim ) ;
m_dwStateDuration = 1 ;
}
}
}