#include "stdafx.h" #include #include #include #include #include "GameZoneCommon.h" #include "CharacterFormula.h" #include "Player.h" #include "StatusManager.h" #include "ItemManager.h" #include "PVPInfo.h" #include "Summoned.h" #include "ChaoState.h" #include "DragonTransStatus.h" #include "WarehouseSlotContainer.h" #include "StateInfoParser.h" #include "./PlayerRider.h" #include "GameZone.h" //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ BOOL Player::CanAttack() { // (WAVERIX)(080907)(NOTE) // - ÀÌ°Í ¾îij ¾ÈµÇ³ª? ±×¶§ ±×¶§ ÀÌ·± ½ÄÀ¸·Î ¿¹¿Ü󸮰¡ ¼öÇàµÇ´Ùº¸´Ï ±¸Á¶»ó ¶Ç´Â À¯Áöº¸¼öµµ Èûµç // ¿¹¿ÜµéÀÌ ¾Æ·¡¿Í °°ÀÌ Ãß°¡µÇ°í ÀÖ´Ù. ÀÏ´Ü, SSQ°ü·Ã ÀÛ¾÷ ÀÌÀü¿¡ ·ÎÁ÷ ó¸® ¼ø¼­¸¦ º¯°æÇؼ­ // µð¹ö±ëµµ ´õ ½±°í, ´õ °¡º±µµ·Ï ¸¸µé±â·Î ÇÑ´Ù. const BOOL bCanAttack = Character::CanAttack(); if( !bCanAttack ) return FALSE; // Ç÷¹À̾îÀÇ »óŰ¡ ±âº»»óŰ¡ ¾Æ´Ï¸é( ¿¹:ÇöÀç °³ÀλóÁ¡À» °³¼³ÇÑ »óŵî ) °ø°ÝÇÒ ¼ö ¾ø´Ù. const ePLAYER_BEHAVE_STATE state_of_behave = GetBehave(); #ifdef _NA_006699_20130506_DONOT_ATTACK_WHILE_BATTLE_GROUND_RESERVATION if( state_of_behave != PLAYER_BEHAVE_IDLE_STATE && state_of_behave != PLAYER_BEHAVE_RESERVATION_BATTLE_GROUND_ZONE) #else if( state_of_behave != PLAYER_BEHAVE_IDLE_STATE ) #endif // _NA_006699_20130506_DONOT_ATTACK_WHILE_BATTLE_GROUND_RESERVATION return FALSE; // (WAVERIX)(080907)(NOTE) // - ¾Æ·¡¿Í °°Àº »óȲÀÌ ¾´¿ôÀ½ÀÌ ³ª¿À°Ô ÇÏ´Â ³»¿ë... ÀÛ¾÷ ´Ü°è°¡ ¼­·Î Ʋ¸®´Ï °¢°¢ ±¸ÇöÇØ¹ö¸®´Â (±×°Ô ´õ ÀÛ¾÷ÇÒ ¶§´Â ÆíÇϴϱî...) // »óȲ¿¡ ÀÇÇÑ °ÍÀ̶ó »ý°¢µÈ´Ù. Á» ´õ °í¹ÎµÇ´õ¶óµµ ¾Õ¼± ePLAYER_BEHAVE_STATE¿Í °°Àº ÅëÇÕ Àϰýü°è¸¦ °®Ãß´Â ÆíÀÌ ³ªÀ» °Å¶ó // »ý°¢µÈ´Ù. Àû¾îµµ ÀÛ¾÷ÇÒ ¶§, ¼±ÇàÀÛ¾÷(ºÐ¼®´Ü°è)¸¦ °¡Áö°í ±âÁ¸¿¡ ÀÖ´Â ±â´ÉÀÇ È°¿ë¹æ¾È(¶Ç´Â È®À广¾È)À» °í¹ÎÇØº¸¸é ÁÁÀ» °ÍÀÌ´Ù. // ±×·± °ÍÀÌ Á¶±Ý °í¹Î½º·´´õ¶óµµ Àڱ⠹ßÀü¿¡µµ À̵æÀÏ °Å¶ó »ý°¢µÈ´Ù. ¹¹... ÀÛ¾÷ÀÏÁ¤ ¾Ð¹ÚÀ̳ª ȸ»ç´Ï±î ¶Ç´Â Àß µ¹¾Æ°¡°í ÀÖ´Â // °ÍÀ» °Çµå·Á¼­ ¹¹ÇÒ·Á±¸? ¶ó°í ÇÑ´Ù¸é ¾¹¾µÇÏÁö¸¸ ¹«½ÃÇÒ ¼ö´Â ¾ø´Â ºÎºÐÀÌ°í ³ª ¿ª½Ã ¿¹¿ÜÀÏ ¼ö´Â ¾øÀ¸¹Ç·Î º°·Î Ç׺¯ÇÏ°í ½ÍÁö ¾Ê´Ù. // ´ÜÁö ±×·± »ý°¢ÀÌ ¸¸¿¬µÇ´Â °ÍÀÌ ¹«¼­¿ï »ÓÀÌ´Ù. // PVP »óÅ üũ const ePVP_USER_STATE state_of_pvp = m_pPVPInfo->GetPVPState(); if( !( state_of_pvp == ePVP_USER_NONE || state_of_pvp == ePVP_USER_MATCH ) ) return FALSE; // (WAVERIX)(080907)(NOTE) // - »óµ¿ÀÇ ÀÌÀ¯·Î ¾´¿ôÀ½ÀÌ ³ª¿Â´Ù. ±×·¸´Ù¸é... ±æµå â°í Ãß°¡µÈ Çö ½ÃÁ¡¿¡¼­ ±æµå â°í¿¡ ´ëÇØ¼­´Â °Ë»çÇÏÁö ¾Ê¾Æµµ µÇ´Â°¡ // ÇÏ´Â ¹®Á¦°¡ »ý±ä´Ù. ±×°Ô ¹®Á¦¶ó¸é ¿©±â¿¡ ¶Ç Ãß°¡ÇÒ °ÍÀΰ¡? ¾ÆÀÌ·¯´Ï´Ù... // - ºÐ¼®ÀûÀÎ ¹®Á¦, pWarehouse Æ÷ÀÎÅÍ »óŸ¦ °Ë»çÇÏ´Â °ÍÀº Ÿ´çÇϳª pWarehouse°¡ nullÀÌ µÇ´Â »óȲÀº // GameServer°¡ Á¾·áµÉ ¶§ »ÓÀÌ´Ù. ¹¹... Æ÷ÀÎÅÍ ¹®Á¦³ª ¸Þ¸ð¸® ÇÒ´ç ¹æ¹ýÀ» ´Þ¸®Çϰųª, ÇÏ¸é º°°³ÀÇ ¹®Á¦°¡ µÇ±â´Â ÇÏÁö¸¸, ±×·± // °æ¿ì¶ó¸é, ÀϰýÀûÀ¸·Î ÇØ´ç Ç÷¹À̾îÀÇ Action Çã¿ë ¿©ºÎ¶ó´Â ´Ü¼øÇÑ Æò°¡·Î ÀÌ·ïÁö´Â °Ô ´õ °£´ÜÇØ Áú °ÍÀÌ´Ù. // ÈçÈ÷ ÇÏÁö ¾Ê´Â°¡? pPlayer->GetField() °Ë»ç... // ÇöÀç â°í°¡ ¿­·Á ÀÖ´Â »óÅÂ¸é °ø°ÝÇÒ ¼ö ¾ø´Ù. CWarehouseSlotContainer* const pWareHouse = GetWarehouseContainer(); if( !pWareHouse || pWareHouse->IsStarted() ) //â°í°¡ ¿­·Á ÀÖÀ¸¸é.. < (WAVERIX) ¤»¤» »óÅ ÇÑ °¡Áö°¡ ´õ ÀÖ´Ù. ¾Æ·¡ ÷»èÇßÀ½. return FALSE; // (WAVERIX)(080907)(NOTE) // if( !pWareHouse || pWareHouse->IsStarted() ) // - ¾Ë°í ÀÌ·¸°Ô Çß´ÂÁö ¾Æ´ÑÁö´Â ÆÄ¾ÇÇÒ ¼ö ¾øÁö¸¸ ±× ³í¸® °á°ú¿¡´Â Àç¹ÌÀÖ´Â ºÎºÐÀÌ ÀÖ´Ù. ÀÌ´Â ´ÙÀ½°ú °°ÀÌ Ç®À̵ȴÙ. // if( !pWareHouse || (pWareHouse && pWareHouse->IsStarted()) ) // pWareHouseÀÌ 0À̰ųª pWareHouse->IsStarted()À̶ó¸é... ==> (0À̰ųª 0ÀÌ ¾Æ´Ï°í started¶ó¸é...) // - °á°úÀûÀ¸·Î À§ ³í¸®¿¡¼­ Ÿ´çÇϱâ´Â ÇÏÁö¸¸, CanAttackÀÇ ¸ñÀû°ú´Â ´Ù¸¥ ºÎºÐÀÌ »ý°Ü³­´Ù. // - Âü°í·Î º» ÀÛ¼ºÀÚÀÇ °æ¿ì´Â ±»ÀÌ Ç¥ÇöÇÑ´Ù¸é ¾Æ·¡Ã³·³ ÇÑ´Ù. // if( pWareHouse && pWareHouse->IsStarted() ) // À§ÀÇ »óź¸´Ù´Â Á¶°ÇÀÌ Çϳª ºüÁ® ÀÖ´Ù. ÀÌ´Â pWareHouse°¡ 0ÀÌ³Ä ¾Æ´Ï³Ä´Â ¿©±â¼­ °í·ÁÇÒ ´ë»óÀÌ ¾Æ´Ï±â ¶§¹®ÀÌ´Ù. ±×·±°ÍÀ» // °í¹ÎÇϸé ÇÁ·Î±×·¥ÀÇ º¹Àâµµ´Â ¿¹ÃøÇϱâ Èûµé´Ù. Àû¾îµµ pWareHouse¸¦ °Ë»çÇÑ ´ÜÀÏÇÑ ¸ñÀû(â°í°¡ ¿­·Á ÀÖÀ¸¸é)¿¡´Â ºÎÇÕÇÏ°Ô µÈ´Ù. // â°íÀÇ ¹«°á¼ºÀº â°í °ü·Ã 󸮽ÿ¡ ÇØ°áÇÏ¸é µÈ´Ù. // ÀÏ´Ü ÀÌ¿Í °°Àº 󸮷Π´Ù¸¥ °÷¿¡ ¿µÇâÀ» ÁÖ¾úÀ» °¡´É¼ºµµ ÀÖ°í, â°í°¡ ¾øÀ» ¸®µµ ¾øÀ¸´Ï ³í¸® ºí·ÏÀº ±×´ë·Î À¯ÁöÇÑ´Ù. // // °á·ÐÀûÀ¸·Î À§ÀÇ »óȲÀ» Á÷¼³ÀûÀ¸·Î Ç¥ÇöÇÏ¸é ´ÙÀ½°ú °°´Ù. // "°ø°ÝÀº â°í¸¦ °¡Áö°í ÀÖ´Â »ç¶÷¸¸ÀÇ Æ¯±ÇÀÌ´Ù!" ... ¾ÆÀÌ·¯´Ï´Ù. ¿Ö? return TRUE; } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ BOOL Player::CanBeAttacked() const { const BOOL bCanBeAttacked = Character::CanBeAttacked(); if( !bCanBeAttacked ) return FALSE; // PVP »óÅ üũ const ePVP_USER_STATE state_of_pvp = m_pPVPInfo->GetPVPState(); if( !( state_of_pvp == ePVP_USER_NONE || state_of_pvp == ePVP_USER_MATCH ) ) return FALSE; return TRUE; } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // CHANGES, f100830.4L, replace an arguement block for a skill to a SkillInfo RC::eBATTLE_RESULT Player::CanNormalAttack(SkillInfo* preparing_skill_info_data) { const SkillInfo& skill_info_data = *preparing_skill_info_data; // safe-control // (WAVERIX)(080907)(NOTE) ³Ê¹« º¹ÀâÇØÁ³À¸¹Ç·Î Çö ½ÃÁ¡ Àû¿ëµÇ´Â ±â´ÉÀ» ÃßÃâÇÑ´Ù. ////////////////////////////////////////////////////////////////////////// // FlowControl flow; FLOWCONTROL_START() { // Ç÷¹À̾ Çʵ忡 ¾øÀ¸¸é ¸®ÅÏ GameField* const pField = GetField(); if (!(pField && pField->IsReady())) { return RC::RC_BATTLE_PLAYER_NOTEXIST_TO_FIELD; } // (WAVERIX)(080907)(NOTE) ... ÀÌ »óÅ ã±â (ƯÈ÷ eCHAR_STATE_TRANSFORMATION)³ªÁß¿¡ °³¼± ¹æ¾È °­±¸ÇÏÀÚ. StatusManager* const status_manager = GetStatusManager(); // °ø°Ý Ÿ¼ö üũ(ÀÏ´Ü Æ²·Áµµ ³Ñ¾î°¡ ÁØ´Ù...) ... ±×·±µ¥ ¿Ö? StatusField& rStatus = status_manager->Status; const bool isCheck_AtkSeq = !(rStatus.IsDragonTransforming()); if (isCheck_AtkSeq) { const BYTE last_atkseq = GetLastAttackSeq(); if (eATTACK_SEQUENCE_SECOND == skill_info_data.attack_sequence_) { if (last_atkseq != eATTACK_SEQUENCE_FIRST) { SECURELOG(SECURELOG_PLAYERINFO(this, \ eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_SEQUENCE), _T("["__FUNCTION__"] Attack Logic Violation, received 2nd, except 1st")); } } else if (eATTACK_SEQUENCE_THIRD == skill_info_data.attack_sequence_) { if (last_atkseq != eATTACK_SEQUENCE_SECOND) { SECURELOG(SECURELOG_PLAYERINFO(this, \ eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_SEQUENCE), _T("["__FUNCTION__"] Attack Logic Violation, received 3rd, except 2nd")); } } } // sequence update´Â field check ÀÌÀü¿¡ ÇØÁà¾ß Çϴ°¡? Á»´õ µûÁ®º¼ ÇÊ¿ä´Â ÀÖ´Ù. SetLastAttackSeq(skill_info_data.attack_sequence_); // Ç÷¹À̾ °ø°ÝÇÒ ¼ö ¾ø´Â »óÅÂÀÌ¸é ¸®ÅÏ < atk seq´Â ¸ÂÃçÁà¾ß ÇÑ´Ù. if (!CanAttack()) { return RC::RC_BATTLE_PLAYER_STATE_WHERE_CANNOT_ATTACK_ENEMY; } if (!rStatus.IsPassConstraint(this, (SkillScriptInfo*)0)) { return RC::RC_BATTLE_PLAYER_STATE_WHERE_CANNOT_ATTACK_ENEMY; } // ¾ÆÁ÷ ¾×¼Ç µµÁßÀÎ °æ¿ì ÀÌ ÆÐŶÀº ÇØÅ·À¸·Î °£ÁÖÇØµµ ¹«¹æÇÔ IfFailThenBreak(!IsDoingAction(), RC::RC_BATTLE_ALREADY_DOING_ACTION); // ÇöÀç ÁÂÇ¥°¡ À¯È¿ÇÑÁö üũ IfFailThenBreak(WzVector_FiniteCheck(&skill_info_data.cur_pos_), RC::RC_BATTLE_INVLIDPOS); // ¸ñÀûÁö ÁÂÇ¥°¡ À¯È¿ÇÑÁö üũ IfFailThenBreak(WzVector_FiniteCheck(&skill_info_data.dest_pos_), RC::RC_BATTLE_INVLIDPOS); // (WAVERIX)(080907)(NOTE) ÀÌÈÄ µô·¹ÀÌ Ã³¸®°¡ °í·ÁµÇ¸é ÀÌ ¹®Á¦µµ Á» ´õ °í¹ÎÇØºÁ¾ß ÇÑ´Ù. // ¹Ð¸®´Â °Å¸®(¾îÅýÃÀÛÁ¡-¾îÅó¡Á¡)°¡ ³Ê¹« ±æ¸é Á¢¼ÓÀ» ²÷´Â´Ù. const float fDiffBetween_Cur_With_Dest_Q2 = 3.0f * 3.0f; ;{ WzVector diff = skill_info_data.cur_pos_; ; diff -= skill_info_data.dest_pos_; IfFailThenBreak(Math_Vector2DLength2(&diff) <= fDiffBetween_Cur_With_Dest_Q2, RC::RC_BATTLE_THRUST_DIST_OVER); }; // (NOTE) to support a shadow control, __NA_S00015_20080828_NEW_HOPE_SHADOW ;{ // °ø°Ý½Ã »ç¶óÁö´Â »óŵé...... Player_TransOff(); //_NA001385_20090924_DOMINATION_SHADOW #if !defined(_NA_005159_20120807_DISABLE_REMOVE_RUSH_STATE) //·¯½¬»óÅÂÀÌ¸é »ç¶óÁø´Ù. BaseStatus* status = status_manager->FindStatus(eCHAR_STATE_RUSH); if (status) { status->StopStatus(); } #endif //_NA_005159_20120807_DISABLE_REMOVE_RUSH_STATE }; return RC::RC_BATTLE_SUCCESS; } FLOWCONTROL_END; ////////////////////////////////////////////////////////////////////////// // switch (flow.GetErrorCode()) { case RC::RC_BATTLE_INVLIDPOS: { const WzVector& cur_pos = skill_info_data.cur_pos_; const WzVector& dest_pos = skill_info_data.dest_pos_; SECURELOG(SECURELOG_PLAYERINFO(this, \ eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_INVALID_POSITION), _T("["__FUNCTION__"] Invalid Position! ") _T("CurPos={%.2f,%.2f,%.2f} DestPos={%.2f,%.2f,%.2f}"), cur_pos.x, cur_pos.y, cur_pos.z, dest_pos.x, dest_pos.y, dest_pos.z); } return RC::RC_BATTLE_INVLIDPOS; case RC::RC_BATTLE_THRUST_DIST_OVER: { SECURELOG(SECURELOG_PLAYERINFO(this, \ eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_RANGE), _T("["__FUNCTION__"] Coordinates Hack, End to End Attck Distance is too long")); } return RC::RC_BATTLE_THRUST_DIST_OVER; case RC::RC_BATTLE_ALREADY_DOING_ACTION: { SECURELOG(SECURELOG_PLAYERINFO(this, \ eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_SPEED), _T("["__FUNCTION__"] Already Doing Action! TimeInterval [%d] ProgressRatio [%f]"), m_ActionTimer.GetIntervalTime() , m_ActionTimer.GetProgressRatio()); } return RC::RC_BATTLE_ALREADY_DOING_ACTION; } SUNLOG(eCRITICAL_LOG, _T("["__FUNCTION__"] ½ºÅµÀÌ ¹ß»ýÇÏ´Â »óȲÀº ¹«¾ùÀΰ¡?|Error=%d|"), flow.GetErrorCode()); return RC::RC_BATTLE_FAILED; } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // CHANGES, f100830.4L, replace an arguement block for a skill to a SkillInfo RC::eBATTLE_RESULT Player::CanStyleAttack(SkillInfo* preparing_skill_info_data) { // for safe-control. if you want modify a SkillInfo, do access to preparing_skill_info_data. const SkillInfo& skill_info_data = *preparing_skill_info_data; ////////////////////////////////////////////////////////////////////////// // FlowControl flow; FLOWCONTROL_START() { // °ø°Ý °¡´ÉÇÑÁö ±âº»ÀûÀÎ »çÇ×À» üũÇÑ´Ù. const RC::eBATTLE_RESULT result = CanNormalAttack(preparing_skill_info_data); if (result != RC::RC_BATTLE_SUCCESS) { return result; }; const SkillInfoParser* const skill_parser = SkillInfoParser::Instance(); const SLOTCODE style_code = GetSelectedStyle(); const BASE_STYLEINFO* const style_info = skill_parser->GetStyleInfo(style_code); if (style_info == NULL) { return RC::RC_BATTLE_BASEINFO_NOTEXIST; // ÀÌ°Å¾ß ¸»·Î abusingÀÌ ¾Æ´Ñ°¡? } StatusManager* const status_manager = GetStatusManager(); // (WAVERIX)(080907)(NOTE) // - ... ¶Ç µå·¡°ïº¯½ÅÀÌ´Ù... -.-;;; // - Ŭ·¡½º ŸÀÔ °ü·ÃÀº ƯÁ¤ À§Ä¡¿¡¼­ ÇØ°áÀÌ °¡´ÉÇÏ´Ù. ±×ÂÊÀ» ´Ù½Ã Çѹø »ìÆìº¸°í °³¼± ¹æ¾ÈÀ» °­±¸ÇÏÀÚ. // Ŭ·¡½º Á¦ÇÑ¿¡ °É¸®´ÂÁö üũ DWORD current_class_type = (DWORD)GetCharType(); // eCHAR_TYPE | eCHAREX_TYPE //StatusField& rStatus = pStatusManager->Status; if (status_manager->Status.IsDragonTransforming()) { DragonTransStatus* const status = static_cast(\ status_manager->FindStatus(eCHAR_STATE_TRANSFORMATION)); current_class_type = (DWORD)status->GetCharType(); } IfFailThenBreak((DWORD)style_info->m_byClassDefine == current_class_type, RC::RC_BATTLE_CHAR_CLASS_LIMIT); // ¹«±âÁ¦ÇÑ¿¡ °É¸®´ÂÁö üũ const DWORD weapon_kind_by_script = (DWORD)style_info->m_iWeaponDefine; if (weapon_kind_by_script != ULONG_MAX) { const DWORD weapon_kind = GetWeaponKind(); IfFailThenBreak(weapon_kind == weapon_kind_by_script, RC::RC_BATTLE_WEAPON_LIMIT); } ;{ // CHANGES, f100830.5L, update a skill_info_data. preparing_skill_info_data->skill_code_ = style_code; preparing_skill_info_data->root_skill_info_ = style_info; }; // return RC::RC_BATTLE_SUCCESS; } FLOWCONTROL_END; ////////////////////////////////////////////////////////////////////////// // switch (const RC::eBATTLE_RESULT result = (RC::eBATTLE_RESULT)flow.GetErrorCode()) { case RC::RC_BATTLE_CHAR_CLASS_LIMIT: { SECURELOG(SECURELOG_PLAYERINFO(this, eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_TYPE), _T("["__FUNCTION__"] The Type Of Character is Invalid! Style[%d] CharType[%d]"), GetSelectedStyle(), GetCharType()); // µå·¡°ï º¯½ÅÀº °í·ÁµÇÁö ¾ÊÀº ·Î±×´Ù... } return result; case RC::RC_BATTLE_WEAPON_LIMIT: { SECURELOG(SECURELOG_PLAYERINFO(this, \ eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_TYPE), _T("["__FUNCTION__"] The Weapon Type is Invalid! Style[%d] Weapon[%d]"), GetSelectedStyle(), GetWeaponKind()); } return result; } return RC::RC_BATTLE_FAILED; } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ VOID Player::SetAttackDelay( BYTE byAttackSequence, SLOTCODE StyleCode ) { BASE_STYLEINFO *pBaseStyleInfo = SkillInfoParser::Instance()->GetStyleInfo( StyleCode ); // ¾×¼Ç µô·¹ÀÌ ¼³Á¤ DWORD dwActionDelay; switch( byAttackSequence ) { case eATTACK_SEQUENCE_FIRST: dwActionDelay = pBaseStyleInfo->m_wTimeFirst; break; case eATTACK_SEQUENCE_SECOND: dwActionDelay = pBaseStyleInfo->m_wTimeSecond; break; case eATTACK_SEQUENCE_THIRD: dwActionDelay = pBaseStyleInfo->m_wTimeThird; break; default: SECURELOG( SECURELOG_PLAYERINFO(this, eABUSE_LOGIC_VIOLATION, eABUSE_SUB_LOGIC_VIOLATION_ATTACK_SEQUENCE), _T("[Player::SetAttackDelay] Invalid attack sequence! Style[%d] byAttackSequence[%d]"), StyleCode, byAttackSequence ); ForceDisconnect( RC::RC_DISCONNECT_INVALID_ATTACK_SEQUENCE ); return; } // ¼­¹öÃø ¾×¼Ç µô·¹À̸¦ ¾à°£ ¿©À¯ÀÖ°Ô Àâ´Â´Ù. dwActionDelay = (DWORD)(dwActionDelay * 0.9f); if( 0 != GetPhysicalAttackSpeed() ) { SetActionDelay( (DWORD)( dwActionDelay / GetPhysicalAttackSpeed() ) ); } else { SUNLOG( eCRITICAL_LOG, _T("[Player::SetAttackDelay] GetPhysicalAttackSpeed() = 0!") ); return; } } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ VOID Player::OnAttack( Character *pTarget, SLOTCODE skillcode, DAMAGETYPE damage ) { // °ø°ÝÀÚÀÇ ¹«±â ³»±¸µµ °¨¼Ò //¹Ð¸®°ø°ÝÀÌ¸é ¸íÁß·ü Àû¿ë ÇÏ¿© ³»±¸µµ °¨¼Ò DWORD dwDecreaseDuraVal = CalcDecreaseItemDuraValue( m_Attr.GetDecreaseItemDuraRatio() ); bool apply_decrease_durability = false; if (skillcode == SKILLCODE_NORMAL_ATTACK) { //¸íÁßÇßÀ¸´Ï ³»±¸µµ °¨¼Ò if (damage != 0) { apply_decrease_durability = true; } } //¸¶¹ý°ø°ÝÀÌ¸é ¸íÁß·ü Àû¿ë ¾øÀÌ ³»±¸µµ °¨¼Ò else { apply_decrease_durability = true; }; // CHANGES: f110405.1L if (apply_decrease_durability) { if (nsSlot::DurabilityImpl* const impl = this->GetItemManager()->GetDurabilityImpl()) { impl->DecreaseDurability(dwDecreaseDuraVal, eEQUIPCONTAINER_WEAPON); }; }; Character::OnAttack( pTarget, skillcode, damage ); DWORD skillRecoverPercent = 100; DWORD skillRequireMP = 0; SkillScriptInfo *pSkillInfo = SkillInfoParser::Instance()->GetSkillInfo( skillcode ); if( pSkillInfo ) { skillRequireMP = pSkillInfo->m_wMPSpend; } // °ø°ÝÇÒ¶§ ȸº¹·® DWORD recoverMP = CalcMPRecoverByAttack( GetCharType(), m_Attr.GetSPR(), skillRecoverPercent, skillRequireMP ); OnRecover( 0, recoverMP ); #ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE if (GetCharType() == eCHAR_WITCHBLADE && damage > 0) // ÆòŸ·Î ÇÇÇØ¸¦ ÁÖ¸é Àû¿ë { PLAYERFP recoverFP = CalcFPRecoverByAttack(GetCharType()); OnRecoverFP(recoverFP); } #endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ void Player::_Damaged(DamageArgs* damage_arg) { Character* pAttacker = damage_arg->actor_; // (WAVERIX) (081013) (NOTE) ³Ê¹« ±æ°í Áߺ¹ÀÌ ¸¹´Ù. µðÆÄÀÎ Á¦°Å ÀÛ¾÷ÀÌ ³¡³ª¸é Á¤¸®Çϱâ·Î ÇÑ´Ù. if (Policyment.FIELD & Policyment.PCC_IN_SSQ_FIELD) { int damage = damage_arg->damage_; if (damage) { damage = (damage >> 1); if (damage == 0) { damage = 1; } damage_arg->damage_ = damage; } /* // (WAVERIX) (090824) (CHANGES) 3Ç× ¿¬»êÀº 2ȸ Áߺ¹ Á¶°ÇÀ» true °è»ê ¹æ½ÄÀ¸·Î Ç®¾î³»¸é // ³­ÇØÇØÁö´Â ¹®Á¦Á¡¶§¹®¿¡ ´ÙÀ½°ú °°ÀÌ ¼öÁ¤. if(damage) { damage = (damage >> 1) ? damage >> 1 : 1; } // (NOTE) ¾Õ¿¡¼­ ¸»ÇÑ ³»¿ëÀ» ´ÙÀ½°ú °°ÀÌ º¯È¯Çϸé Á» ´õ °¡µ¶¼ºÀÌ ÁÁ¾ÆÁø´Ù. // ÇÏÁö¸¸ ÀÌ·² ÇÊ¿ä ÀÖ³ª? »ó¼öÈ­ ¸ñÀûÀÌ ¾Æ´Ñ ÀÌ»ó ÀÌ·¸°Ô ¹«¸®ÇÏ°Ô ÇÏÁö´Â ¸»ÀÚ. // (advanced) | (original code) //damage = (damage == 0) ? 0 | damage = damage // : (damage >> 1) ? damage >> 1 | ? (damage >> 1) ? damage >> 1 // : 1; | : 1 // | : 0; */ } // || ÀÌ¹Ì Á×Àº À¯Àú¿¡°Ô µ¥¹ÌÁö¸¦ Á־ ¼Ò¿ë¾ø´Ù... if (damage_arg->damage_ == 0 || IsDead()) { return; } if (damage_arg->damage_) // ... ÀÌ ¾Õ´ÜÀ¸·Î Ãß°¡ ·ÎÁ÷ÀÌ »ðÀԵǴ °æ¿ì¸¦ °¨¾ÈÇØ¼­ Á¦°ÅÇÏÁö ¾Ê´Â´Ù. { #if !defined(_NA_000000_20121015_DISABLE_REMOVE_HIDE_STATE) Player_TransOff(); #endif //_NA_000000_20121015_DISABLE_REMOVE_HIDE_STATE // ¹æ¾îÀÚÀÇ ¹æ¾î±¸ ³»±¸µµ °¨¼Ò //POSTYPE RandomPos = random(eEQUIPCONTAINER_ARMOR, eEQUIPCONTAINER_SHIRTS); // unused // (CHANGES) (091212) (WAVERIX) to support simple debugging facility, \ // more reduce overhead and code arrangement const int iDuraRatio = m_Attr.GetDecreaseItemDuraRatio(); const DWORD duraVal = CalcDecreaseItemDuraValue(iDuraRatio); // CHANGES: f110404.2L if (nsSlot::DurabilityImpl* const impl = this->GetItemManager()->GetDurabilityImpl()) { impl->DecreaseDurabilityWithRanges(duraVal, eEQUIPCONTAINER_ARMOR, eEQUIPCONTAINER_SHIRTS); }; } { // Recover MP DWORD recoverMP = CalcMPRecoverByAttacked(GetCharType(), m_Attr.GetSPR(), damage_arg->damage_); OnRecover(0, recoverMP); }; // Character Damage Process Character::_Damaged(damage_arg); //¿©±â¼­ ½ÇÁ¦ µ¥¹ÌÁö °¨¼Ò°¡ ÀϾ´Ù. if(damage_arg->damage_ > 0 && IsAlive()) { // (WAVERIX) (090821) (BUG-FIX) HP Recovery±â´É °ü·Ã ¹ö±× ¼öÁ¤ // (ÇØ´ç ȸº¹·üÀº ÃÖÁ¾ °è»ê °á°ú °ªÀÌ ¾Æ´Ñ ºñÀ²)¸¸À¸·Î »ç¿ëÇØ¾ß ÇÒ µí, HPÀÇ °ªÀº Attribute¿¡ // º¯µ¿Ä¡¸¦ ¹Ý¿µÇÒ ¼ö ¾øÀ¸¸ç, (¼³»ç ¹Ý¿µÇÏ´õ¶óµµ º¹ÀâÇØÁö°Å³ª, ¸Å¹ø update¼öÇàÇØ¾ß ÇÑ´Ù.) // °á°úÀûÀ¸·Î Çö ½ÃÁ¡, value(0) * ratio·Î ¿¬»êµÇ¾î Ç×»ó 0ÀÌ ³ª¿À°Ô µÈ´Ù. // (Addin Note) // Ãʱ⠱¸ÇöÀÚ¿Í ±â´É Ãß°¡ÀÚ°¡ µ¿ÀÏÇÏÁö¸¸, ÀÌ »ç¶÷Àº Å×½ºÆ®´Â °³»Ô·Î »ý°¢ÇÏ´Â »ç¶÷À̶ó // ´ÜÁ¤Áö¾î¾ß(°ÅÁþÀº ¾Æ´Ï´Ï ¹¹...) ÀÌÈÄ ÇØ´ç ÀÛ¾÷ÀÚ°¡ ¹ß»ý½ÃŲ (ÇöÀç ½ºÅ³ °ü·Ã ¹ö±×µé // ³»°¡ °¡Áö°í ÀÖ´Â) ¹ö±×µéÀ» ¼öÁ¤Çϸ鼭 ½ºÆ®·¹½º ´ú ¹ÞÀ» °Í °°´Ù. ÇöÀç À§µµ ¾ÆÆÄ¿À´Âµ¥... ¤¶x! // ¸®Ä¿¹ö¸®·® Áõ°¡ ÆÐ½Ãºê ½ºÅ³ÀÌ ÀÖÀ¸¸é.. int reserveHp_Addin = (damage_arg->damage_ >> 1); if(reserveHp_Addin) { //'+Ratio' (ADD-IN) int reserveHp_Ratio = m_Attr.GetRatioIncreaseReserveHPRatio(); if(reserveHp_Ratio) // = (src * percent) / 100 reserveHp_Addin = int((reserveHp_Addin * (100 + reserveHp_Ratio)) / 100.0f); } DWORD reserveHP = GetReserveHP() + reserveHp_Addin; //// old code backup //int nReserveHPRatio = GetAttr().GetIncreaseReserveHPRatio(); // ¸®Ä¿¹ö¸®·® Áõ°¡ ÆÐ½Ãºê ½ºÅ³ÀÌ ÀÖÀ¸¸é.. //double dbTempReserveHP = (double)damage / 2; //double dbCalcReserveHPRatio = (double)(nReserveHPRatio/100.0f)*dbTempReserveHP; // //DWORD reserveHP = GetReserveHP() + dbTempReserveHP + dbCalcReserveHPRatio; {// (WAVERIX) (090821) (CHANGES) ÄÚµå °ËÁõ ÈÄ ¼öÁ¤ DWORD calcHP = GetHP() + reserveHP; const DWORD maxHP = GetMaxHP(); // (NOTE) curHP + reserveHP > maxHP »óȲÀÌ ¹ß»ýÇÏÁö¸¸, ½ÇÁ¦ ȸº¹ ½ÃÁ¡¿¡ À׿© °ªÀÌ °í·ÁµÈ´Ù. if(maxHP < calcHP) reserveHP = calcHP - maxHP; } SetReserveHP(reserveHP); } if(pAttacker) { if(IsDead()) // Ç÷¹À̾ °­Á¦°ø°Ý(PK)À» ¹Þ¾Æ¼­ Á×¾úÀ» °æ¿ì { Player* pPlayer = pAttacker->GetPlayerOwner(); if(pPlayer) { #ifdef _NA_008706_20160229_TEXTLOG_PK pPlayer->KillPlayer(this, FALSE, damage_arg->damage_first_); #else pPlayer->KillPlayer(this); #endif //_NA_008706_20160229_TEXTLOG_PK } } else if(damage_arg->option_.is_mirror_ == false && GetReflectDamageRatio()) { // f100908.1L DamageArgs mirror_damage_args(this, damage_arg->attack_type_); ;{ //mirror_damage_args.option_.is_normal_; //mirror_damage_args.option_.is_critical_; mirror_damage_args.option_.is_mirror_ = true; //mirror_damage_args.target_; //mirror_damage_args.limit_hp_; mirror_damage_args.attack_regist_kind_ = damage_arg->attack_regist_kind_; // ÀÌ ºÎºÐÀº ¿É¼Ç¿¡ ´ëÇÑ Ã³¸® À̳ª, »óÅÂÀÇ SDApply °ªÀ» µû¸¥´Ù. BASE_STATEINFO* pStateInfo = \ StateInfoParser::Instance()->GetStateInfo(eCHAR_STATE_REFLECT_DAMAGE); if (pStateInfo) { mirror_damage_args.sd_apply_ = (eSD_APPLY)pStateInfo->m_bySDApply; } mirror_damage_args.damage_ = damage_arg->damage_ * GetReflectDamageRatio(); //mirror_damage_args.damage_sd_; }; pAttacker->Damaged(&mirror_damage_args); // µ¥¹ÌÁö ¹Ý»ç ¼Ó¼º üũ DWORD dwAttackerReserveHP = pAttacker->GetReserveHP(); if(dwAttackerReserveHP > 0) dwAttackerReserveHP = dwAttackerReserveHP / 10 + mirror_damage_args.damage_ / 2; //±âº»ÀÇ Àû¸³HP 10% + DamageÀÇ 50%¸¦ Àû¸³ÇÑ´Ù. else dwAttackerReserveHP = mirror_damage_args.damage_ / 2; //±âº»ÀÇ Àû¸³HP 10% + DamageÀÇ 50%¸¦ Àû¸³ÇÑ´Ù. pAttacker->SetReserveHP(dwAttackerReserveHP); //¹Ý»ç µ¥¹ÌÁö´Â ³»°¡ °ø°Ý ¹Þ¾Ò´Âµ¥, ¹Ý»çÀûÀ¸·Î ³ª¸¦ °ø°ÝÇÑ ³ð¿¡°Ô µ¥¹ÌÁö¸¦ ÁÖ´Â °ÍÀÌ´Ù. //µû¶ó¼­ °ø°Ý ÁÖü°¡ "³»"°¡ µÈ´Ù. ;{ MSGSUB_SKILL_REFLECT_DAMAGE_BRD msg_brd; msg_brd.Clear(); msg_brd.m_dwAttackerKey = GetObjectKey(); msg_brd.m_dwTargetKey = pAttacker->GetObjectKey(); msg_brd.m_wDamage = mirror_damage_args.damage_; msg_brd.m_dwTargetHP = pAttacker->GetHP(); msg_brd.m_dwTargetResrveHP = pAttacker->GetReserveHP(); msg_brd.m_SkillCode = 0; msg_brd.m_wAbilityCode = 0; #ifdef _NA_008804_20160502_COMBAT_LOG time_t t; util::TimeSync::time(&t); msg_brd.m_SvrTime = t; #endif //(_NA_008804_20160502_COMBAT_LOG) this->SendPacketAroundForSync(&msg_brd); }; } } #if !defined(_NA_005159_20120807_DISABLE_REMOVE_RUSH_STATE) ;{ // (NOTE) to support a shadow control, __NA_S00015_20080828_NEW_HOPE_SHADOW // Ç÷¹À̾ °ø°Ý ´çÇßÀ»¶§ »ç¶óÁö´Â »óŵé.. //·¯½¬»óÅÂÀÌ¸é »ç¶óÁø´Ù. BaseStatus* pStatus = GetStatusManager()->FindStatus(eCHAR_STATE_RUSH); if (pStatus) { pStatus->StopStatus(); } }; #endif //_NA_005159_20120807_DISABLE_REMOVE_RUSH_STATE IVehicleEvent::OnEvent(this, IVehicleEvent::Hit()); // for vehicles 'Hit' event processing #ifdef _NA_007667_20141001_WITCHBLADE_SKILL //À§Ä¡ºí·¹À̵å, ¶óÀÌ¡Æ÷½ºÀÇ Ã³¸® ProcessRisingForce(); #endif //_NA_007667_20141001_WITCHBLADE_SKILL } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ VOID Player::ForcedAttack( Character *pTarget ) { if( !pTarget ) return; if( !pTarget || !pTarget->GetPlayerOwner() ) return; const BOOLEAN bApplyGeneralForcedAtkRule = !( Policyment.FIELD & Policyment.PCC_IN_SSQ_FIELD ); if( !bApplyGeneralForcedAtkRule ) return; #if defined(_CHINA) //CHINA_PK_RULE if( m_ForceAttack || pTarget->GetPlayerOwner()->GetChaoState().IsChaoState() ) #else if( m_ForceAttack ) #endif m_pChaoState->StartBoradoriState( pTarget->GetPlayerOwner() ); } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ BOOL Player::CanResurrection( Character *pTarget ) { if( !pTarget ) return FALSE; //ÆÄƼ¿øÀÌ ¾Æ´Ï¸é ÀڽŸ¸ ºÎȰ if( !GetPartyState().IsPartyMember() ) { if( GetObjectKey() == pTarget->GetObjectKey() ) return TRUE; #ifdef _NA_006826_20130722_DOMINATION_RENEWAL GameZone* pZone = GetGameZonePtr(); if (pZone && pZone->GetZoneType() == eZONETYPE_DOMINATION_FIELD) { if (pTarget->IsEqualObjectKind(PLAYER_OBJECT)) { Player* target_player = static_cast(pTarget); if (pZone->IsFriendPVP(this, target_player) == USER_RELATION_FRIEND) { return TRUE; } } } #endif //_NA_006826_20130722_DOMINATION_RENEWAL return FALSE; } //ÆÄƼ¿øÀÌ¸é ÆÄÆ¼¿øµé ºÎȰ else { if( GetPartyState().GetPartyKey() != pTarget->GetPartyState().GetPartyKey() ) return FALSE; } return TRUE; }