MrP0wers

char.cpp

Nov 4th, 2025
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 188.32 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "char.h"
  3. #include "config.h"
  4. #include "utils.h"
  5. #include "crc32.h"
  6. #include "char_manager.h"
  7. #include "desc_client.h"
  8. #include "desc_manager.h"
  9. #include "buffer_manager.h"
  10. #include "item_manager.h"
  11. #include "motion.h"
  12. #include "vector.h"
  13. #include "packet.h"
  14. #include "cmd.h"
  15. #include "fishing.h"
  16. #include "exchange.h"
  17. #include "battle.h"
  18. #include "affect.h"
  19. #include "shop.h"
  20. #include "shop_manager.h"
  21. #include "safebox.h"
  22. #include "regen.h"
  23. #include "pvp.h"
  24. #include "party.h"
  25. #include "start_position.h"
  26. #include "questmanager.h"
  27. #include "log.h"
  28. #include "p2p.h"
  29. #include "guild.h"
  30. #include "guild_manager.h"
  31. #include "dungeon.h"
  32. #include "messenger_manager.h"
  33. #include "unique_item.h"
  34. #include "priv_manager.h"
  35. #include "war_map.h"
  36. #include "xmas_event.h"
  37. #include "banword.h"
  38. #include "target.h"
  39. #include "wedding.h"
  40. #include "mob_manager.h"
  41. #include "mining.h"
  42. #include "arena.h"
  43. #include "dev_log.h"
  44. #include "horsename_manager.h"
  45. #include "gm.h"
  46. #include "map_location.h"
  47. #include "BlueDragon_Binder.h"
  48. #include "DragonSoul.h"
  49. #include "OXEvent.h"
  50. #include "skill_power.h"
  51. #include "buff_on_attributes.h"
  52.  
  53. #include "../../common/VnumHelper.h"
  54.  
  55. #include <boost/algorithm/string/classification.hpp>
  56. #include <boost/algorithm/string/split.hpp>
  57.  
  58. #ifdef __PET_SYSTEM__
  59. #include "PetSystem.h"
  60. #endif
  61.  
  62. #ifdef __SWITCHBOT__
  63. #include "new_switchbot.h"
  64. #endif
  65.  
  66. #ifdef __SEND_TARGET_INFO__
  67. #include <algorithm>
  68. #include <iterator>
  69. using namespace std;
  70. #endif
  71.  
  72. extern const BYTE g_aBuffOnAttrPoints;
  73. extern bool RaceToJob(unsigned race, unsigned *ret_job);
  74.  
  75. extern int g_nPortalLimitTime;
  76. extern int test_server;
  77.  
  78. extern bool IS_SUMMONABLE_ZONE(int map_index);
  79. extern long long yang_max;
  80.  
  81. bool CAN_ENTER_ZONE(const LPCHARACTER& ch, int map_index);
  82.  
  83. bool CAN_ENTER_ZONE(const LPCHARACTER& ch, int map_index)
  84. {
  85. switch (map_index)
  86. {
  87. case 301:
  88. case 302:
  89. case 303:
  90. case 304:
  91. if (ch->GetLevel() < 90)
  92. return false;
  93. }
  94.  
  95. return true;
  96. }
  97.  
  98. LPCHARACTER DynamicCharacterPtr::Get() const
  99. {
  100. LPCHARACTER p = NULL;
  101.  
  102. if (is_pc)
  103. {
  104. p = CHARACTER_MANAGER::instance().FindByPID(id);
  105. }
  106.  
  107. else
  108. {
  109. p = CHARACTER_MANAGER::instance().Find(id);
  110. }
  111.  
  112. return p;
  113. }
  114.  
  115. DynamicCharacterPtr& DynamicCharacterPtr::operator=(LPCHARACTER character)
  116. {
  117. if (character == NULL)
  118. {
  119. Reset();
  120. return *this;
  121. }
  122.  
  123. if (character->IsPC())
  124. {
  125. is_pc = true;
  126. id = character->GetPlayerID();
  127. }
  128.  
  129. else
  130. {
  131. is_pc = false;
  132. id = character->GetVID();
  133. }
  134.  
  135. return *this;
  136. }
  137.  
  138. CHARACTER::CHARACTER()
  139. {
  140. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateIdle, &CHARACTER::EndStateEmpty);
  141. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateMove, &CHARACTER::EndStateEmpty);
  142. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateBattle, &CHARACTER::EndStateEmpty);
  143.  
  144. Initialize();
  145. }
  146.  
  147. CHARACTER::~CHARACTER()
  148. {
  149. Destroy();
  150. }
  151.  
  152. void CHARACTER::Initialize()
  153. {
  154. CEntity::Initialize(ENTITY_CHARACTER);
  155.  
  156. m_bNoOpenedShop = true;
  157.  
  158. m_bOpeningSafebox = false;
  159.  
  160. m_fSyncTime = get_float_time()-3;
  161. m_dwPlayerID = 0;
  162. m_dwKillerPID = 0;
  163.  
  164. #ifdef __SEND_TARGET_INFO__
  165. dwLastTargetInfoPulse = 0;
  166. #endif
  167.  
  168. m_iMoveCount = 0;
  169.  
  170. m_pkRegen = NULL;
  171. regen_id_ = 0;
  172. m_posRegen.x = m_posRegen.y = m_posRegen.z = 0;
  173. m_posStart.x = m_posStart.y = 0;
  174. m_posDest.x = m_posDest.y = 0;
  175. m_fRegenAngle = 0.0f;
  176.  
  177. m_pkMobData = NULL;
  178. m_pkMobInst = NULL;
  179.  
  180. m_pkShop = NULL;
  181. m_pkChrShopOwner = NULL;
  182. m_pkMyShop = NULL;
  183. m_pkExchange = NULL;
  184. m_pkParty = NULL;
  185. m_pkPartyRequestEvent = NULL;
  186.  
  187. m_pGuild = NULL;
  188.  
  189. m_pkChrTarget = NULL;
  190.  
  191. m_pkMuyeongEvent = NULL;
  192.  
  193. m_pkWarpNPCEvent = NULL;
  194. m_pkDeadEvent = NULL;
  195. m_pkStunEvent = NULL;
  196. m_pkSaveEvent = NULL;
  197. m_pkRecoveryEvent = NULL;
  198. m_pkTimedEvent = NULL;
  199. m_pkFishingEvent = NULL;
  200. m_pkWarpEvent = NULL;
  201.  
  202. m_pkMiningEvent = NULL;
  203.  
  204. m_pkPoisonEvent = NULL;
  205. m_pkFireEvent = NULL;
  206. m_pkCheckSpeedHackEvent = NULL;
  207. m_speed_hack_count = 0;
  208.  
  209. m_pkAffectEvent = NULL;
  210. m_afAffectFlag = TAffectFlag(0, 0);
  211.  
  212. m_pkDestroyWhenIdleEvent = NULL;
  213.  
  214. m_pkChrSyncOwner = NULL;
  215.  
  216. memset(&m_points, 0, sizeof(m_points));
  217. memset(&m_pointsInstant, 0, sizeof(m_pointsInstant));
  218. memset(&m_quickslot, 0, sizeof(m_quickslot));
  219.  
  220. m_bCharType = CHAR_TYPE_MONSTER;
  221.  
  222. SetPosition(POS_STANDING);
  223.  
  224. m_dwPlayStartTime = m_dwLastMoveTime = get_dword_time();
  225.  
  226. GotoState(m_stateIdle);
  227. m_dwStateDuration = 1;
  228.  
  229. m_dwLastAttackTime = get_dword_time() - 20000;
  230.  
  231. m_bAddChrState = 0;
  232.  
  233. m_pkChrStone = NULL;
  234.  
  235. m_pkSafebox = NULL;
  236. m_iSafeboxSize = -1;
  237. m_iSafeboxLoadTime = 0;
  238.  
  239. m_pkMall = NULL;
  240. m_iMallLoadTime = 0;
  241.  
  242. m_posWarp.x = m_posWarp.y = m_posWarp.z = 0;
  243. m_lWarpMapIndex = 0;
  244.  
  245. m_posExit.x = m_posExit.y = m_posExit.z = 0;
  246. m_lExitMapIndex = 0;
  247.  
  248. m_pSkillLevels = NULL;
  249.  
  250. m_dwMoveStartTime = 0;
  251. m_dwMoveDuration = 0;
  252.  
  253. m_dwFlyTargetID = 0;
  254.  
  255. m_dwNextStatePulse = 0;
  256.  
  257. m_dwLastDeadTime = get_dword_time()-180000;
  258.  
  259. m_bSkipSave = false;
  260.  
  261. m_bItemLoaded = false;
  262.  
  263. m_bHasPoisoned = false;
  264.  
  265. m_pkDungeon = NULL;
  266. m_iEventAttr = 0;
  267.  
  268. m_kAttackLog.dwVID = 0;
  269. m_kAttackLog.dwTime = 0;
  270.  
  271. m_bNowWalking = m_bWalking = false;
  272. ResetChangeAttackPositionTime();
  273.  
  274. m_bDetailLog = false;
  275. m_bMonsterLog = false;
  276.  
  277. m_bDisableCooltime = false;
  278.  
  279. m_iAlignment = 0;
  280. m_iRealAlignment = 0;
  281.  
  282. m_iKillerModePulse = 0;
  283. m_bPKMode = PK_MODE_PEACE;
  284.  
  285. m_dwQuestNPCVID = 0;
  286. m_dwQuestByVnum = 0;
  287. m_pQuestItem = NULL;
  288.  
  289. m_dwUnderGuildWarInfoMessageTime = get_dword_time()-60000;
  290.  
  291. m_bUnderRefine = false;
  292.  
  293. m_dwRefineNPCVID = 0;
  294.  
  295. m_dwPolymorphRace = 0;
  296.  
  297. m_bStaminaConsume = false;
  298.  
  299. #ifdef ENABLE_LIDER_SYSTEM
  300. m_dwLonAktifLastTime = 0;
  301. #endif
  302.  
  303. ResetChainLightningIndex();
  304.  
  305. m_dwMountVnum = 0;
  306. m_chHorse = NULL;
  307. m_chRider = NULL;
  308.  
  309. m_pWarMap = NULL;
  310. m_pWeddingMap = NULL;
  311. m_bChatCounter = 0;
  312.  
  313. ResetStopTime();
  314.  
  315. m_dwLastVictimSetTime = get_dword_time() - 3000;
  316. m_iMaxAggro = -100;
  317.  
  318. m_bSendHorseLevel = 0;
  319. m_bSendHorseHealthGrade = 0;
  320. m_bSendHorseStaminaGrade = 0;
  321.  
  322. m_dwLoginPlayTime = 0;
  323.  
  324. m_pkChrMarried = NULL;
  325.  
  326. m_posSafeboxOpen.x = -1000;
  327. m_posSafeboxOpen.y = -1000;
  328.  
  329. m_dwLastSkillTime = get_dword_time();
  330.  
  331. memset(m_adwMobSkillCooltime, 0, sizeof(m_adwMobSkillCooltime));
  332.  
  333. m_pArena = NULL;
  334. m_nPotionLimit = quest::CQuestManager::instance().GetEventFlag("arena_potion_limit_count");
  335.  
  336. m_isOpenSafebox = 0;
  337.  
  338. m_iRefineTime = 0;
  339.  
  340. m_iSeedTime = 0;
  341.  
  342. m_iExchangeTime = 0;
  343.  
  344. m_iSafeboxLoadTime = 0;
  345.  
  346. m_iMyShopTime = 0;
  347.  
  348. m_deposit_pulse = 0;
  349.  
  350. SET_OVER_TIME(this, OT_NONE);
  351.  
  352. m_strNewName = "";
  353.  
  354. m_known_guild.clear();
  355.  
  356. m_dwLogOffInterval = 0;
  357.  
  358. m_bComboSequence = 0;
  359. m_dwLastComboTime = 0;
  360. m_bComboIndex = 0;
  361. m_iComboHackCount = 0;
  362. m_dwSkipComboAttackByTime = 0;
  363.  
  364. m_dwMountTime = 0;
  365.  
  366. m_dwLastGoldDropTime = 0;
  367.  
  368. m_bIsLoadedAffect = false;
  369. cannot_dead = false;
  370.  
  371. #ifdef __PET_SYSTEM__
  372. m_petSystem = 0;
  373. m_bIsPet = false;
  374. #endif
  375.  
  376. m_fAttMul = 1.0f;
  377. m_fDamMul = 1.0f;
  378.  
  379. m_pointsInstant.iDragonSoulActiveDeck = -1;
  380.  
  381. #ifdef __CUSTOM_TITLE_SYSTEM__
  382. m_stTitle = "";
  383. memset(m_bTitleColor, 0, sizeof(m_bTitleColor));
  384.  
  385. m_stTitle2 = "";
  386. memset(m_bTitle2Color, 0, sizeof(m_bTitle2Color));
  387. #endif
  388.  
  389. memset(&m_tvLastSyncTime, 0, sizeof(m_tvLastSyncTime));
  390. m_iSyncHackCount = 0;
  391.  
  392. #ifdef ENABLE_ANTI_CMD_FLOOD
  393. m_dwCmdAntiFloodCount = 0;
  394. m_dwCmdAntiFloodPulse = 0;
  395. #endif
  396.  
  397. #ifdef ENABLE_ANTI_FLOOD_SPAM_PACKET
  398. analyze_protect = 0;
  399. analyze_protect_count = 0;
  400. ap_pickup = 0;
  401. apc_pickup = 0;
  402. ap_open_items = 0;
  403. apc_open_items = 0;
  404. ap_attack = 0;
  405. apc_attack = 0;
  406. ap_move = 0;
  407. apc_move = 0;
  408. ap_click_target = 0;
  409. apc_click_target = 0;
  410. ap_drop_target = 0;
  411. apc_drop_target = 0;
  412. #endif
  413.  
  414. #ifdef ENABLE_SPAM_ECHIPAMENT
  415. m_dwEquipAntiFloodCount = 0;
  416. m_dwEquipAntiFloodPulse = 0;
  417. m_dwShopAntiFloodCount = 0;
  418. m_dwShopAntiFloodPulse = 0;
  419. #endif
  420.  
  421. }
  422.  
  423. void CHARACTER::Create(const char * c_pszName, DWORD vid, bool isPC)
  424. {
  425. static int s_crc = 172814;
  426.  
  427. char crc_string[128+1];
  428.  
  429. snprintf(crc_string, sizeof(crc_string), "%s%p%d", c_pszName, this, ++s_crc);
  430. m_vid = VID(vid, GetCRC32(crc_string, strlen(crc_string)));
  431.  
  432. if (isPC)
  433. m_stName = c_pszName;
  434. }
  435.  
  436. void CHARACTER::Destroy()
  437. {
  438. CloseMyShop();
  439.  
  440. if (m_pkRegen)
  441. {
  442. if (m_pkDungeon)
  443. {
  444. if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_))
  445. {
  446. --m_pkRegen->count;
  447. }
  448. }
  449.  
  450. else
  451. {
  452. --m_pkRegen->count;
  453. }
  454.  
  455. m_pkRegen = NULL;
  456. }
  457.  
  458. if (m_pkDungeon)
  459. {
  460. SetDungeon(NULL);
  461. }
  462.  
  463. #ifdef __PET_SYSTEM__
  464. if (m_petSystem)
  465. {
  466. m_petSystem->Destroy();
  467. delete m_petSystem;
  468.  
  469. m_petSystem = 0;
  470. }
  471. #endif
  472.  
  473. HorseSummon(false);
  474.  
  475. if (GetRider())
  476. GetRider()->ClearHorseInfo();
  477.  
  478. if (GetDesc())
  479. {
  480. GetDesc()->BindCharacter(NULL);
  481. }
  482.  
  483. if (m_pkExchange)
  484. m_pkExchange->Cancel();
  485.  
  486. SetVictim(NULL);
  487.  
  488. if (GetShop())
  489. {
  490. GetShop()->RemoveGuest(this);
  491. SetShop(NULL);
  492. }
  493.  
  494. ClearStone();
  495. ClearSync();
  496. ClearTarget();
  497.  
  498. if (NULL == m_pkMobData)
  499. {
  500. DragonSoul_CleanUp();
  501. ClearItem();
  502. }
  503.  
  504. LPPARTY party = m_pkParty;
  505.  
  506. if (party)
  507. {
  508. if (party->GetLeaderPID() == GetVID() && !IsPC())
  509. {
  510. M2_DELETE(party);
  511. }
  512.  
  513. else
  514. {
  515. party->Unlink(this);
  516.  
  517. if (!IsPC())
  518. party->Quit(GetVID());
  519. }
  520.  
  521. SetParty(NULL);
  522. }
  523.  
  524. if (m_pkMobInst)
  525. {
  526. M2_DELETE(m_pkMobInst);
  527. m_pkMobInst = NULL;
  528. }
  529.  
  530. m_pkMobData = NULL;
  531.  
  532. if (m_pkSafebox)
  533. {
  534. M2_DELETE(m_pkSafebox);
  535. m_pkSafebox = NULL;
  536. }
  537.  
  538. if (m_pkMall)
  539. {
  540. M2_DELETE(m_pkMall);
  541. m_pkMall = NULL;
  542. }
  543.  
  544. for (TMapBuffOnAttrs::iterator it = m_map_buff_on_attrs.begin(); it != m_map_buff_on_attrs.end(); it++)
  545. {
  546. if (NULL != it->second)
  547. {
  548. M2_DELETE(it->second);
  549. }
  550. }
  551.  
  552. m_map_buff_on_attrs.clear();
  553.  
  554. m_set_pkChrSpawnedBy.clear();
  555.  
  556. StopMuyeongEvent();
  557. event_cancel(&m_pkWarpNPCEvent);
  558. event_cancel(&m_pkRecoveryEvent);
  559. event_cancel(&m_pkDeadEvent);
  560. event_cancel(&m_pkSaveEvent);
  561. event_cancel(&m_pkTimedEvent);
  562. event_cancel(&m_pkStunEvent);
  563. event_cancel(&m_pkFishingEvent);
  564. event_cancel(&m_pkPoisonEvent);
  565. event_cancel(&m_pkFireEvent);
  566. event_cancel(&m_pkPartyRequestEvent);
  567.  
  568. event_cancel(&m_pkWarpEvent);
  569. event_cancel(&m_pkCheckSpeedHackEvent);
  570.  
  571. //event_cancel(&m_pkRecallEvent);
  572.  
  573. event_cancel(&m_pkMiningEvent);
  574.  
  575. for (itertype(m_mapMobSkillEvent) it = m_mapMobSkillEvent.begin(); it != m_mapMobSkillEvent.end(); ++it)
  576. {
  577. LPEVENT pkEvent = it->second;
  578. event_cancel(&pkEvent);
  579. }
  580.  
  581. m_mapMobSkillEvent.clear();
  582.  
  583. //event_cancel(&m_pkAffectEvent);
  584.  
  585. ClearAffect();
  586.  
  587. event_cancel(&m_pkDestroyWhenIdleEvent);
  588.  
  589. if (m_pSkillLevels)
  590. {
  591. M2_DELETE_ARRAY(m_pSkillLevels);
  592. m_pSkillLevels = NULL;
  593. }
  594.  
  595. CEntity::Destroy();
  596.  
  597. if (GetSectree())
  598. GetSectree()->RemoveEntity(this);
  599.  
  600. if (m_bMonsterLog)
  601. CHARACTER_MANAGER::instance().UnregisterForMonsterLog(this);
  602.  
  603. #ifdef ENABLE_ANTI_FLOOD_SPAM_PACKET
  604. analyze_protect = 0;
  605. analyze_protect_count = 0;
  606. ap_pickup = 0;
  607. apc_pickup = 0;
  608. ap_open_items = 0;
  609. apc_open_items = 0;
  610. ap_attack = 0;
  611. apc_attack = 0;
  612. ap_move = 0;
  613. apc_move = 0;
  614. ap_click_target = 0;
  615. apc_click_target = 0;
  616. ap_drop_target = 0;
  617. apc_drop_target = 0;
  618. #endif
  619.  
  620. }
  621.  
  622. const char * CHARACTER::GetName() const
  623. {
  624. return m_stName.empty() ? (m_pkMobData ? m_pkMobData->m_table.szLocaleName : "") : m_stName.c_str();
  625. }
  626.  
  627. void CHARACTER::OpenMyShop(const char * c_pszSign, TShopItemTable * pTable, BYTE bItemCount)
  628. {
  629. if (!CanHandleItem())
  630. {
  631. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 개인상점을 사용할 수 없습니다."));
  632. return;
  633. }
  634. if (GetPart(PART_MAIN) > 2)
  635. {
  636. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("갑옷을 벗어야 개인 상점을 열 수 있습니다."));
  637. return;
  638. }
  639.  
  640. if (GetMyShop())
  641. {
  642. CloseMyShop();
  643. return;
  644. }
  645.  
  646. #ifdef __INVENTORY_PROTECT_SYSTEM__
  647. if (GetQuestFlag("abs.INVENTORY_LOCK") == 1)
  648. {
  649. ChatPacket(CHAT_TYPE_INFO, "|cFF00ff33[Info] > |h|r Inventarul este blocat .");
  650. return;
  651. }
  652. #endif
  653.  
  654. quest::PC * pPC = quest::CQuestManager::instance().GetPCForce(GetPlayerID());
  655.  
  656. if (pPC->IsRunning())
  657. return;
  658.  
  659. if (bItemCount == 0)
  660. return;
  661.  
  662. long long nTotalMoney = 0;
  663.  
  664. for (int n = 0; n < bItemCount; ++n)
  665. {
  666. nTotalMoney += static_cast<long long>((pTable + n)->price);
  667. }
  668.  
  669. nTotalMoney += static_cast<long long>(GetGold());
  670.  
  671. if (yang_max <= nTotalMoney)
  672. {
  673. sys_err("[OVERFLOW_GOLD] Overflow (GOLD_MAX) id %u name %s", GetPlayerID(), GetName());
  674. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("20? ?? ???? ??? ??? ????"));
  675. return;
  676. }
  677.  
  678. char szSign[SHOP_SIGN_MAX_LEN+1];
  679. strlcpy(szSign, c_pszSign, sizeof(szSign));
  680.  
  681. m_stShopSign = szSign;
  682.  
  683. if (m_stShopSign.length() == 0)
  684. return;
  685.  
  686. if (CBanwordManager::instance().CheckString(m_stShopSign.c_str(), m_stShopSign.length()))
  687. {
  688. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("비속어나 은어가 포함된 상점 이름으로 상점을 열 수 없습니다."));
  689. return;
  690. }
  691.  
  692. std::map<DWORD, DWORD> itemkind;
  693.  
  694. std::set<TItemPos> cont;
  695. for (BYTE i = 0; i < bItemCount; ++i)
  696. {
  697. if (cont.find((pTable + i)->pos) != cont.end())
  698. {
  699. sys_err("MYSHOP: duplicate shop item detected! (name: %s)", GetName());
  700. return;
  701. }
  702.  
  703. LPITEM pkItem = GetItem((pTable + i)->pos);
  704.  
  705. if (pkItem)
  706. {
  707. const TItemTable * item_table = pkItem->GetProto();
  708.  
  709. if (item_table && (IS_SET(item_table->dwAntiFlags, ITEM_ANTIFLAG_GIVE | ITEM_ANTIFLAG_MYSHOP)))
  710. {
  711. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("유료화 아이템은 개인상점에서 판매할 수 없습니다."));
  712. return;
  713. }
  714.  
  715. if (pkItem->IsEquipped() == true)
  716. {
  717. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("장비중인 아이템은 개인상점에서 판매할 수 없습니다."));
  718. return;
  719. }
  720.  
  721. if (true == pkItem->isLocked())
  722. {
  723. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("사용중인 아이템은 개인상점에서 판매할 수 없습니다."));
  724. return;
  725. }
  726.  
  727. itemkind[pkItem->GetVnum()] = (pTable + i)->price / pkItem->GetCount();
  728. }
  729.  
  730. cont.insert((pTable + i)->pos);
  731. }
  732.  
  733. if (CountSpecifyItem(71049))
  734. {
  735. TItemPriceListTable header;
  736. memset(&header, 0, sizeof(TItemPriceListTable));
  737.  
  738. header.dwOwnerID = GetPlayerID();
  739. header.byCount = itemkind.size();
  740.  
  741. size_t idx=0;
  742. for (itertype(itemkind) it = itemkind.begin(); it != itemkind.end(); ++it)
  743. {
  744. header.aPriceInfo[idx].dwVnum = it->first;
  745. header.aPriceInfo[idx].dwPrice = it->second;
  746. idx++;
  747. }
  748.  
  749. db_clientdesc->DBPacket(HEADER_GD_MYSHOP_PRICELIST_UPDATE, GetDesc()->GetHandle(), &header, sizeof(TItemPriceListTable));
  750. }
  751.  
  752.  
  753. else if (CountSpecifyItem(50200))
  754. RemoveSpecifyItem(50200, 1);
  755.  
  756. else
  757. return;
  758.  
  759. if (m_pkExchange)
  760. m_pkExchange->Cancel();
  761.  
  762. TPacketGCShopSign p;
  763.  
  764. p.bHeader = HEADER_GC_SHOP_SIGN;
  765. p.dwVID = GetVID();
  766. strlcpy(p.szSign, c_pszSign, sizeof(p.szSign));
  767.  
  768. PacketAround(&p, sizeof(TPacketGCShopSign));
  769.  
  770. m_pkMyShop = CShopManager::instance().CreatePCShop(this, pTable, bItemCount);
  771.  
  772. if (IsPolymorphed() == true)
  773. {
  774. RemoveAffect(AFFECT_POLYMORPH);
  775. }
  776.  
  777. if (GetHorse())
  778. {
  779. HorseSummon( false, true );
  780. }
  781.  
  782. else if (GetMountVnum())
  783. {
  784. RemoveAffect(AFFECT_MOUNT);
  785. RemoveAffect(AFFECT_MOUNT_BONUS);
  786. }
  787.  
  788. SetPolymorph(30000, true);
  789. }
  790.  
  791. void CHARACTER::CloseMyShop()
  792. {
  793. if (GetMyShop())
  794. {
  795. m_stShopSign.clear();
  796. CShopManager::instance().DestroyPCShop(this);
  797. m_pkMyShop = NULL;
  798.  
  799. TPacketGCShopSign p;
  800.  
  801. p.bHeader = HEADER_GC_SHOP_SIGN;
  802. p.dwVID = GetVID();
  803. p.szSign[0] = '\0';
  804.  
  805. PacketAround(&p, sizeof(p));
  806.  
  807. SetPolymorph(GetJob(), true);
  808. }
  809. }
  810.  
  811. void EncodeMovePacket(TPacketGCMove & pack, DWORD dwVID, BYTE bFunc, BYTE bArg, DWORD x, DWORD y, DWORD dwDuration, DWORD dwTime, BYTE bRot)
  812. {
  813. pack.bHeader = HEADER_GC_CHARACTER_MOVE;
  814. pack.bFunc = bFunc;
  815. pack.bArg = bArg;
  816. pack.dwVID = dwVID;
  817. pack.dwTime = dwTime ? dwTime : get_dword_time();
  818. pack.bRot = bRot;
  819. pack.lX = x;
  820. pack.lY = y;
  821. pack.dwDuration = dwDuration;
  822. }
  823.  
  824. void CHARACTER::RestartAtSamePos()
  825. {
  826. if (m_bIsObserver)
  827. return;
  828.  
  829. EncodeRemovePacket(this);
  830. EncodeInsertPacket(this);
  831.  
  832. ENTITY_MAP::iterator it = m_map_view.begin();
  833.  
  834. while (it != m_map_view.end())
  835. {
  836. LPENTITY entity = (it++)->first;
  837.  
  838. EncodeRemovePacket(entity);
  839. if (!m_bIsObserver)
  840. EncodeInsertPacket(entity);
  841.  
  842. if( entity->IsType(ENTITY_CHARACTER) )
  843. {
  844. LPCHARACTER lpChar = (LPCHARACTER)entity;
  845. if( lpChar->IsPC() || lpChar->IsNPC() || lpChar->IsMonster() )
  846. {
  847. if (!entity->IsObserverMode())
  848. entity->EncodeInsertPacket(this);
  849. }
  850. }
  851.  
  852. else
  853. {
  854. if( !entity->IsObserverMode())
  855. {
  856. entity->EncodeInsertPacket(this);
  857. }
  858. }
  859. }
  860. }
  861.  
  862. void CHARACTER::EncodeInsertPacket(LPENTITY entity)
  863. {
  864. LPDESC d;
  865.  
  866. if (!(d = entity->GetDesc()))
  867. return;
  868.  
  869. LPCHARACTER ch = (LPCHARACTER) entity;
  870. ch->SendGuildName(GetGuild());
  871.  
  872. TPacketGCCharacterAdd pack;
  873.  
  874. pack.header = HEADER_GC_CHARACTER_ADD;
  875.  
  876. pack.dwVID = m_vid;
  877. pack.bType = GetCharType();
  878. pack.angle = GetRotation();
  879.  
  880. pack.x = GetX();
  881. pack.y = GetY();
  882. pack.z = GetZ();
  883.  
  884. pack.wRaceNum = GetRaceNum();
  885.  
  886. if (IsPet())
  887. {
  888. pack.bMovingSpeed = 150;
  889. }
  890.  
  891. else
  892. {
  893. pack.bMovingSpeed = GetLimitPoint(POINT_MOV_SPEED);
  894. }
  895.  
  896. #if defined(__WJ_SHOW_MOB_INFO__)
  897. if (IsMonster() || IsStone())
  898. {
  899. pack.dwLevel = GetLevel();
  900. pack.dwAIFlag = IsMonster() ? GetAIFlag() : 0;
  901. }
  902.  
  903. else
  904. {
  905. pack.dwLevel = 0;
  906. pack.dwAIFlag = 0;
  907. }
  908. #endif
  909.  
  910. pack.bAttackSpeed = GetLimitPoint(POINT_ATT_SPEED);
  911. pack.dwAffectFlag[0] = m_afAffectFlag.bits[0];
  912. pack.dwAffectFlag[1] = m_afAffectFlag.bits[1];
  913.  
  914. pack.bStateFlag = m_bAddChrState;
  915.  
  916. int iDur = 0;
  917.  
  918. if (m_posDest.x != pack.x || m_posDest.y != pack.y)
  919. {
  920. iDur = (m_dwMoveStartTime + m_dwMoveDuration) - get_dword_time();
  921.  
  922. if (iDur <= 0)
  923. {
  924. pack.x = m_posDest.x;
  925. pack.y = m_posDest.y;
  926. }
  927. }
  928.  
  929. d->Packet(&pack, sizeof(pack));
  930.  
  931. if (IsPC() == true || m_bCharType == CHAR_TYPE_NPC)
  932. {
  933. TPacketGCCharacterAdditionalInfo addPacket;
  934. memset(&addPacket, 0, sizeof(TPacketGCCharacterAdditionalInfo));
  935.  
  936. addPacket.header = HEADER_GC_CHAR_ADDITIONAL_INFO;
  937. addPacket.dwVID = m_vid;
  938.  
  939. addPacket.awPart[CHR_EQUIPPART_ARMOR] = GetPart(PART_MAIN);
  940.  
  941. #ifdef ENABLE_HIDE_COSTUME_SYSTEM
  942. SetHideCostumeUpdate();
  943. #endif
  944. addPacket.awPart[CHR_EQUIPPART_WEAPON] = GetPart(PART_WEAPON);
  945. addPacket.awPart[CHR_EQUIPPART_HEAD] = GetPart(PART_HEAD);
  946. addPacket.awPart[CHR_EQUIPPART_HAIR] = GetPart(PART_HAIR);
  947.  
  948. #ifdef __EFFECT_SYSTEM__
  949. addPacket.awPart[CHR_BODY_EFFECT] = GetPart(BODY_EFFECT);
  950. addPacket.awPart[CHR_WEAPON_RIGHT_EFFECT] = GetPart(WEAPON_RIGHT_EFFECT);
  951. addPacket.awPart[CHR_WEAPON_LEFT_EFFECT] = GetPart(WEAPON_LEFT_EFFECT);
  952. #endif
  953. addPacket.bPKMode = m_bPKMode;
  954. addPacket.dwMountVnum = GetMountVnum();
  955. addPacket.bEmpire = m_bEmpire;
  956.  
  957. #ifdef ENABLE_EXTENDED_ALIGNMENT_SYSTEM
  958. addPacket.bJob = IsPC() ? m_points.job : 0;
  959. #endif
  960.  
  961. if (IsPC())
  962. {
  963. addPacket.dwLevel = GetLevel();
  964.  
  965. #ifdef __CUSTOM_TITLE_SYSTEM__
  966. strlcpy(addPacket.title.szName, GetTitle(), sizeof(addPacket.title.szName));
  967. memcpy(addPacket.title.bColours, GetTitleColors(), sizeof(addPacket.title.bColours));
  968.  
  969. strlcpy(addPacket.title2.szName, GetTitle2(), sizeof(addPacket.title2.szName));
  970. memcpy(addPacket.title2.bColours2, GetTitle2Colors(), sizeof(addPacket.title2.bColours2));
  971. #endif
  972. }
  973.  
  974. else
  975. {
  976. addPacket.dwLevel = 0;
  977. }
  978.  
  979. if (false)
  980. {
  981. LPCHARACTER ch = (LPCHARACTER) entity;
  982.  
  983. if (GetEmpire() == ch->GetEmpire() || ch->GetGMLevel() > GM_PLAYER || m_bCharType == CHAR_TYPE_NPC)
  984. {
  985. goto show_all_info;
  986. }
  987.  
  988. else
  989. {
  990. memset(addPacket.name, 0, CHARACTER_NAME_MAX_LEN);
  991. addPacket.dwGuildID = 0;
  992. addPacket.sAlignment = 0;
  993.  
  994. #ifdef __TITLE_SYSTEM__
  995. addPacket.iTitleID = 0;
  996. #endif
  997. }
  998. }
  999.  
  1000. else
  1001. {
  1002. show_all_info:
  1003. strlcpy(addPacket.name, GetName(), sizeof(addPacket.name));
  1004.  
  1005. if (GetGuild() != NULL)
  1006. {
  1007. addPacket.dwGuildID = GetGuild()->GetID();
  1008. }
  1009. else
  1010. {
  1011. addPacket.dwGuildID = 0;
  1012. }
  1013.  
  1014. addPacket.sAlignment = m_iAlignment / 10;
  1015.  
  1016. #ifdef __TITLE_SYSTEM__
  1017. addPacket.iTitleID = GetPoint(POINT_TITLE);
  1018. #endif
  1019. }
  1020.  
  1021. d->Packet(&addPacket, sizeof(TPacketGCCharacterAdditionalInfo));
  1022. }
  1023.  
  1024. if (iDur)
  1025. {
  1026. TPacketGCMove pack;
  1027. EncodeMovePacket(pack, GetVID(), FUNC_MOVE, 0, m_posDest.x, m_posDest.y, iDur, 0, (BYTE) (GetRotation() / 5));
  1028. d->Packet(&pack, sizeof(pack));
  1029.  
  1030. TPacketGCWalkMode p;
  1031. p.vid = GetVID();
  1032. p.header = HEADER_GC_WALK_MODE;
  1033. p.mode = m_bNowWalking ? WALKMODE_WALK : WALKMODE_RUN;
  1034.  
  1035. d->Packet(&p, sizeof(p));
  1036. }
  1037.  
  1038. if (entity->IsType(ENTITY_CHARACTER) && GetDesc())
  1039. {
  1040. LPCHARACTER ch = (LPCHARACTER) entity;
  1041. if (ch->IsWalking())
  1042. {
  1043. TPacketGCWalkMode p;
  1044. p.vid = ch->GetVID();
  1045. p.header = HEADER_GC_WALK_MODE;
  1046. p.mode = ch->m_bNowWalking ? WALKMODE_WALK : WALKMODE_RUN;
  1047. GetDesc()->Packet(&p, sizeof(p));
  1048. }
  1049. }
  1050.  
  1051. if (GetMyShop())
  1052. {
  1053. TPacketGCShopSign p;
  1054.  
  1055. p.bHeader = HEADER_GC_SHOP_SIGN;
  1056. p.dwVID = GetVID();
  1057. strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
  1058.  
  1059. d->Packet(&p, sizeof(TPacketGCShopSign));
  1060. }
  1061.  
  1062. if (entity->IsType(ENTITY_CHARACTER))
  1063. {
  1064. sys_log(3, "EntityInsert %s (RaceNum %d) (%d %d) TO %s", GetName(), GetRaceNum(), GetX() / SECTREE_SIZE, GetY() / SECTREE_SIZE, ((LPCHARACTER)entity)->GetName());
  1065. }
  1066. }
  1067.  
  1068. void CHARACTER::EncodeRemovePacket(LPENTITY entity)
  1069. {
  1070. if (entity->GetType() != ENTITY_CHARACTER)
  1071. return;
  1072.  
  1073. LPDESC d;
  1074.  
  1075. if (!(d = entity->GetDesc()))
  1076. return;
  1077.  
  1078. TPacketGCCharacterDelete pack;
  1079.  
  1080. pack.header = HEADER_GC_CHARACTER_DEL;
  1081. pack.id = m_vid;
  1082.  
  1083. d->Packet(&pack, sizeof(TPacketGCCharacterDelete));
  1084.  
  1085. if (entity->IsType(ENTITY_CHARACTER))
  1086. sys_log(3, "EntityRemove %s(%d) FROM %s", GetName(), (DWORD) m_vid, ((LPCHARACTER) entity)->GetName());
  1087. }
  1088.  
  1089. void CHARACTER::UpdatePacket()
  1090. {
  1091. if (GetSectree() == NULL) return;
  1092.  
  1093. if (IsPC() && (!GetDesc() || !GetDesc()->GetCharacter()))
  1094. return;
  1095.  
  1096. TPacketGCCharacterUpdate pack;
  1097. TPacketGCCharacterUpdate pack2;
  1098.  
  1099. pack.header = HEADER_GC_CHARACTER_UPDATE;
  1100. pack.dwVID = m_vid;
  1101.  
  1102. pack.awPart[CHR_EQUIPPART_ARMOR] = GetPart(PART_MAIN);
  1103.  
  1104. #ifdef ENABLE_HIDE_COSTUME_SYSTEM
  1105. SetHideCostumeUpdate();
  1106. #endif
  1107.  
  1108. pack.awPart[CHR_EQUIPPART_WEAPON] = GetPart(PART_WEAPON);
  1109. pack.awPart[CHR_EQUIPPART_HEAD] = GetPart(PART_HEAD);
  1110. pack.awPart[CHR_EQUIPPART_HAIR] = GetPart(PART_HAIR);
  1111.  
  1112. #ifdef __EFFECT_SYSTEM__
  1113. pack.awPart[CHR_BODY_EFFECT] = GetPart(BODY_EFFECT);
  1114. pack.awPart[CHR_WEAPON_RIGHT_EFFECT] = GetPart(WEAPON_RIGHT_EFFECT);
  1115. pack.awPart[CHR_WEAPON_LEFT_EFFECT] = GetPart(WEAPON_LEFT_EFFECT);
  1116. #endif
  1117.  
  1118. pack.bMovingSpeed = GetLimitPoint(POINT_MOV_SPEED);
  1119. pack.bAttackSpeed = GetLimitPoint(POINT_ATT_SPEED);
  1120. pack.bStateFlag = m_bAddChrState;
  1121.  
  1122. pack.dwAffectFlag[0] = m_afAffectFlag.bits[0];
  1123. pack.dwAffectFlag[1] = m_afAffectFlag.bits[1];
  1124. pack.dwGuildID = 0;
  1125.  
  1126. pack.sAlignment = m_iAlignment / 10;
  1127. pack.bPKMode = m_bPKMode;
  1128.  
  1129. #ifdef __TITLE_SYSTEM__
  1130. pack.iTitleID = GetPoint(POINT_TITLE);
  1131. #endif
  1132.  
  1133. if (GetGuild())
  1134. pack.dwGuildID = GetGuild()->GetID();
  1135.  
  1136. pack.dwMountVnum = GetMountVnum();
  1137.  
  1138. pack2 = pack;
  1139. pack2.dwGuildID = 0;
  1140. pack2.sAlignment = 0;
  1141.  
  1142. #ifdef __TITLE_SYSTEM__
  1143. pack.iTitleID = GetPoint(POINT_TITLE);
  1144. #endif
  1145.  
  1146. if (false)
  1147. {
  1148. if (m_bIsObserver != true)
  1149. {
  1150. for (ENTITY_MAP::iterator iter = m_map_view.begin(); iter != m_map_view.end(); iter++)
  1151. {
  1152. LPENTITY pEntity = iter->first;
  1153.  
  1154. if (pEntity != NULL)
  1155. {
  1156. if (pEntity->IsType(ENTITY_CHARACTER) == true)
  1157. {
  1158. if (pEntity->GetDesc() != NULL)
  1159. {
  1160. LPCHARACTER pChar = (LPCHARACTER)pEntity;
  1161.  
  1162. if (GetEmpire() == pChar->GetEmpire() || pChar->GetGMLevel() > GM_PLAYER)
  1163. {
  1164. pEntity->GetDesc()->Packet(&pack, sizeof(pack));
  1165. }
  1166.  
  1167. else
  1168. {
  1169. pEntity->GetDesc()->Packet(&pack2, sizeof(pack2));
  1170. }
  1171. }
  1172. }
  1173.  
  1174. else
  1175. {
  1176. if (pEntity->GetDesc() != NULL)
  1177. {
  1178. pEntity->GetDesc()->Packet(&pack, sizeof(pack));
  1179. }
  1180. }
  1181. }
  1182. }
  1183. }
  1184.  
  1185. if (GetDesc() != NULL)
  1186. {
  1187. GetDesc()->Packet(&pack, sizeof(pack));
  1188. }
  1189. }
  1190.  
  1191. else
  1192. {
  1193. PacketAround(&pack, sizeof(pack));
  1194. }
  1195. }
  1196.  
  1197. LPCHARACTER CHARACTER::FindCharacterInView(const char * c_pszName, bool bFindPCOnly)
  1198. {
  1199. ENTITY_MAP::iterator it = m_map_view.begin();
  1200.  
  1201. for (; it != m_map_view.end(); ++it)
  1202. {
  1203. if (!it->first->IsType(ENTITY_CHARACTER))
  1204. continue;
  1205.  
  1206. LPCHARACTER tch = (LPCHARACTER) it->first;
  1207.  
  1208. if (bFindPCOnly && tch->IsNPC())
  1209. continue;
  1210.  
  1211. if (!strcasecmp(tch->GetName(), c_pszName))
  1212. return (tch);
  1213. }
  1214.  
  1215. return NULL;
  1216. }
  1217.  
  1218. void CHARACTER::SetPosition(int pos)
  1219. {
  1220. if (pos == POS_STANDING)
  1221. {
  1222. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_DEAD);
  1223. REMOVE_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_STUN);
  1224.  
  1225. event_cancel(&m_pkDeadEvent);
  1226. event_cancel(&m_pkStunEvent);
  1227. }
  1228.  
  1229. else if (pos == POS_DEAD)
  1230. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_DEAD);
  1231.  
  1232. if (!IsStone())
  1233. {
  1234. switch (pos)
  1235. {
  1236. case POS_FIGHTING:
  1237. if (!IsState(m_stateBattle))
  1238. MonsterLog("[BATTLE] 싸우는 상태");
  1239.  
  1240. GotoState(m_stateBattle);
  1241. break;
  1242.  
  1243. default:
  1244. if (!IsState(m_stateIdle))
  1245. MonsterLog("[IDLE] 쉬는 상태");
  1246.  
  1247. GotoState(m_stateIdle);
  1248. break;
  1249. }
  1250. }
  1251.  
  1252. m_pointsInstant.position = pos;
  1253. }
  1254.  
  1255. void CHARACTER::Save()
  1256. {
  1257. if (!m_bSkipSave)
  1258. CHARACTER_MANAGER::instance().DelayedSave(this);
  1259. }
  1260.  
  1261. void CHARACTER::CreatePlayerProto(TPlayerTable & tab)
  1262. {
  1263. memset(&tab, 0, sizeof(TPlayerTable));
  1264.  
  1265. if (GetNewName().empty())
  1266. {
  1267. strlcpy(tab.name, GetName(), sizeof(tab.name));
  1268. }
  1269.  
  1270. else
  1271. {
  1272. strlcpy(tab.name, GetNewName().c_str(), sizeof(tab.name));
  1273. }
  1274.  
  1275. strlcpy(tab.ip, GetDesc()->GetHostName(), sizeof(tab.ip));
  1276.  
  1277. tab.id = m_dwPlayerID;
  1278. tab.voice = GetPoint(POINT_VOICE);
  1279. tab.level = GetLevel();
  1280. tab.level_step = GetPoint(POINT_LEVEL_STEP);
  1281. tab.exp = GetExp();
  1282. tab.gold = GetGold();
  1283. tab.job = m_points.job;
  1284. tab.part_base = m_pointsInstant.bBasePart;
  1285. tab.skill_group = m_points.skill_group;
  1286.  
  1287. DWORD dwPlayedTime = (get_dword_time() - m_dwPlayStartTime);
  1288.  
  1289. if (dwPlayedTime > 60000)
  1290. {
  1291. if (GetSectree() && !GetSectree()->IsAttr(GetX(), GetY(), ATTR_BANPK))
  1292. {
  1293. if (GetRealAlignment() < 0)
  1294. {
  1295. if (IsEquipUniqueItem(UNIQUE_ITEM_FASTER_ALIGNMENT_UP_BY_TIME))
  1296. UpdateAlignment(120 * (dwPlayedTime / 60000));
  1297. else
  1298. UpdateAlignment(60 * (dwPlayedTime / 60000));
  1299. }
  1300.  
  1301. else
  1302. UpdateAlignment(5 * (dwPlayedTime / 60000));
  1303. }
  1304.  
  1305. SetRealPoint(POINT_PLAYTIME, GetRealPoint(POINT_PLAYTIME) + dwPlayedTime / 60000);
  1306. ResetPlayTime(dwPlayedTime % 60000);
  1307. }
  1308.  
  1309. tab.playtime = GetRealPoint(POINT_PLAYTIME);
  1310. tab.lAlignment = m_iRealAlignment;
  1311.  
  1312. if (m_posWarp.x != 0 || m_posWarp.y != 0)
  1313. {
  1314. tab.x = m_posWarp.x;
  1315. tab.y = m_posWarp.y;
  1316. tab.z = 0;
  1317. tab.lMapIndex = m_lWarpMapIndex;
  1318. }
  1319.  
  1320. else
  1321. {
  1322. tab.x = GetX();
  1323. tab.y = GetY();
  1324. tab.z = GetZ();
  1325. tab.lMapIndex = GetMapIndex();
  1326. }
  1327.  
  1328. if (m_lExitMapIndex == 0)
  1329. {
  1330. tab.lExitMapIndex = tab.lMapIndex;
  1331. tab.lExitX = tab.x;
  1332. tab.lExitY = tab.y;
  1333. }
  1334.  
  1335. else
  1336. {
  1337. tab.lExitMapIndex = m_lExitMapIndex;
  1338. tab.lExitX = m_posExit.x;
  1339. tab.lExitY = m_posExit.y;
  1340. }
  1341.  
  1342. sys_log(0, "SAVE: %s %dx%d", GetName(), tab.x, tab.y);
  1343.  
  1344. tab.st = GetRealPoint(POINT_ST);
  1345. tab.ht = GetRealPoint(POINT_HT);
  1346. tab.dx = GetRealPoint(POINT_DX);
  1347. tab.iq = GetRealPoint(POINT_IQ);
  1348.  
  1349. tab.stat_point = GetPoint(POINT_STAT);
  1350. tab.skill_point = GetPoint(POINT_SKILL);
  1351. tab.sub_skill_point = GetPoint(POINT_SUB_SKILL);
  1352. tab.horse_skill_point = GetPoint(POINT_HORSE_SKILL);
  1353.  
  1354. tab.stat_reset_count = GetPoint(POINT_STAT_RESET_COUNT);
  1355.  
  1356. tab.hp = GetHP();
  1357. tab.sp = GetSP();
  1358.  
  1359. tab.stamina = GetStamina();
  1360.  
  1361. tab.sRandomHP = m_points.iRandomHP;
  1362. tab.sRandomSP = m_points.iRandomSP;
  1363.  
  1364. for (int i = 0; i < QUICKSLOT_MAX_NUM; ++i)
  1365. tab.quickslot[i] = m_quickslot[i];
  1366.  
  1367. thecore_memcpy(tab.parts, m_pointsInstant.parts, sizeof(tab.parts));
  1368.  
  1369. thecore_memcpy(tab.skills, m_pSkillLevels, sizeof(TPlayerSkill) * SKILL_MAX_NUM);
  1370.  
  1371. #ifdef __CUSTOM_TITLE_SYSTEM__
  1372. strlcpy(tab.title.szName, GetTitle(), sizeof(tab.title.szName));
  1373. memcpy(tab.title.bColours, GetTitleColors(), sizeof(tab.title.bColours));
  1374.  
  1375. strlcpy(tab.title2.szName, GetTitle2(), sizeof(tab.title2.szName));
  1376. memcpy(tab.title2.bColours2, GetTitle2Colors(), sizeof(tab.title2.bColours2));
  1377. #endif
  1378.  
  1379. tab.horse = GetHorseData();
  1380.  
  1381. #ifdef __TITLE_SYSTEM__
  1382. tab.iTChoosed = GetPoint(POINT_TITLE);
  1383. #endif
  1384.  
  1385. }
  1386.  
  1387. void CHARACTER::SaveReal()
  1388. {
  1389. if (m_bSkipSave)
  1390. return;
  1391.  
  1392. if (!GetDesc())
  1393. {
  1394. sys_err("Character::Save : no descriptor when saving (name: %s)", GetName());
  1395. return;
  1396. }
  1397.  
  1398. TPlayerTable table;
  1399. CreatePlayerProto(table);
  1400.  
  1401. db_clientdesc->DBPacket(HEADER_GD_PLAYER_SAVE, GetDesc()->GetHandle(), &table, sizeof(TPlayerTable));
  1402.  
  1403. quest::PC * pkQuestPC = quest::CQuestManager::instance().GetPCForce(GetPlayerID());
  1404.  
  1405. if (!pkQuestPC)
  1406. sys_err("CHARACTER::Save : null quest::PC pointer! (name %s)", GetName());
  1407.  
  1408. else
  1409. {
  1410. pkQuestPC->Save();
  1411. }
  1412.  
  1413. marriage::TMarriage* pMarriage = marriage::CManager::instance().Get(GetPlayerID());
  1414. if (pMarriage)
  1415. pMarriage->Save();
  1416. }
  1417.  
  1418. void CHARACTER::FlushDelayedSaveItem()
  1419. {
  1420. LPITEM item;
  1421.  
  1422. for (int i = 0; i < INVENTORY_AND_EQUIP_SLOT_MAX; ++i)
  1423. if ((item = GetInventoryItem(i)))
  1424. ITEM_MANAGER::instance().FlushDelayedSave(item);
  1425. }
  1426.  
  1427. void CHARACTER::Disconnect(const char * c_pszReason)
  1428. {
  1429. assert(GetDesc() != NULL);
  1430.  
  1431. sys_log(0, "DISCONNECT: %s (%s)", GetName(), c_pszReason ? c_pszReason : "unset" );
  1432.  
  1433. if (GetShop())
  1434. {
  1435. GetShop()->RemoveGuest(this);
  1436. SetShop(NULL);
  1437. }
  1438.  
  1439. if (GetArena() != NULL)
  1440. {
  1441. GetArena()->OnDisconnect(GetPlayerID());
  1442. }
  1443.  
  1444. if (GetParty() != NULL)
  1445. {
  1446. GetParty()->UpdateOfflineState(GetPlayerID());
  1447. }
  1448.  
  1449. marriage::CManager::instance().Logout(this);
  1450.  
  1451. TPacketGGLogout p;
  1452. p.bHeader = HEADER_GG_LOGOUT;
  1453.  
  1454. strlcpy(p.szName, GetName(), sizeof(p.szName));
  1455. P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGLogout));
  1456.  
  1457. char buf[51];
  1458.  
  1459. snprintf(buf, sizeof(buf), "%s %lld %d %ld %d", inet_ntoa(GetDesc()->GetAddr().sin_addr), GetGold(), g_bChannel, GetMapIndex(), GetAlignment());
  1460.  
  1461. LogManager::instance().CharLog(this, 0, "LOGOUT", buf);
  1462.  
  1463. if (m_pWarMap)
  1464. SetWarMap(NULL);
  1465.  
  1466. if (m_pWeddingMap)
  1467. {
  1468. SetWeddingMap(NULL);
  1469. }
  1470.  
  1471. if (GetGuild())
  1472. GetGuild()->LogoutMember(this);
  1473.  
  1474. quest::CQuestManager::instance().LogoutPC(this);
  1475.  
  1476. if (GetParty())
  1477. GetParty()->Unlink(this);
  1478.  
  1479. if (IsStun() || IsDead())
  1480. {
  1481. DeathPenalty(0);
  1482. PointChange(POINT_HP, 50 - GetHP());
  1483. }
  1484.  
  1485. if (!CHARACTER_MANAGER::instance().FlushDelayedSave(this))
  1486. {
  1487. SaveReal();
  1488. }
  1489.  
  1490. FlushDelayedSaveItem();
  1491.  
  1492. DestroyPvP();
  1493.  
  1494. SaveAffect();
  1495. m_bIsLoadedAffect = false;
  1496.  
  1497. m_bSkipSave = true;
  1498.  
  1499. quest::CQuestManager::instance().DisconnectPC(this);
  1500.  
  1501. CloseSafebox();
  1502.  
  1503. CloseMall();
  1504.  
  1505. CPVPManager::instance().Disconnect(this);
  1506.  
  1507. CTargetManager::instance().Logout(GetPlayerID());
  1508.  
  1509. MessengerManager::instance().Logout(GetName());
  1510.  
  1511. #ifdef __OX_RESTRICTION_IP__
  1512. if (GetMapIndex() == OXEVENT_MAP_INDEX)
  1513. COXEventManager::Instance().RemoveFromAttenderList(GetPlayerID());
  1514. #endif
  1515.  
  1516. packet_point_change pack;
  1517. pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
  1518. pack.dwVID = m_vid;
  1519. pack.type = POINT_PLAYTIME;
  1520. pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
  1521. pack.amount = 0;
  1522.  
  1523. GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
  1524.  
  1525. if (GetDesc())
  1526. {
  1527. GetDesc()->BindCharacter(NULL);
  1528. }
  1529.  
  1530. M2_DESTROY_CHARACTER(this);
  1531. }
  1532.  
  1533. bool CHARACTER::Show(long lMapIndex, long x, long y, long z, bool bShowSpawnMotion, bool bAggressive)
  1534. {
  1535. LPSECTREE sectree = SECTREE_MANAGER::instance().Get(lMapIndex, x, y);
  1536.  
  1537. if (!sectree)
  1538. {
  1539. sys_log(0, "cannot find sectree by %dx%d mapindex %d", x, y, lMapIndex);
  1540. return false;
  1541. }
  1542.  
  1543. SetMapIndex(lMapIndex);
  1544.  
  1545. bool bChangeTree = false;
  1546.  
  1547. if (!GetSectree() || GetSectree() != sectree)
  1548. bChangeTree = true;
  1549.  
  1550. if (bChangeTree)
  1551. {
  1552. if (GetSectree())
  1553. GetSectree()->RemoveEntity(this);
  1554.  
  1555. ViewCleanup();
  1556. }
  1557.  
  1558. if (!IsNPC())
  1559. {
  1560. sys_log(0, "SHOW: %s %dx%dx%d", GetName(), x, y, z);
  1561.  
  1562. if (GetStamina() < GetMaxStamina())
  1563. StartAffectEvent();
  1564. }
  1565.  
  1566. else if (m_pkMobData)
  1567. {
  1568. m_pkMobInst->m_posLastAttacked.x = x;
  1569. m_pkMobInst->m_posLastAttacked.y = y;
  1570. m_pkMobInst->m_posLastAttacked.z = z;
  1571. }
  1572.  
  1573. if (bShowSpawnMotion)
  1574. {
  1575. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  1576. m_afAffectFlag.Set(AFF_SPAWN);
  1577. }
  1578.  
  1579. if (bAggressive)
  1580. SetAggressive();
  1581.  
  1582. SetXYZ(x, y, z);
  1583.  
  1584. m_posDest.x = x;
  1585. m_posDest.y = y;
  1586. m_posDest.z = z;
  1587.  
  1588. m_posStart.x = x;
  1589. m_posStart.y = y;
  1590. m_posStart.z = z;
  1591.  
  1592. if (bChangeTree)
  1593. {
  1594. EncodeInsertPacket(this);
  1595. sectree->InsertEntity(this);
  1596.  
  1597. UpdateSectree();
  1598. }
  1599.  
  1600. else
  1601. {
  1602. ViewReencode();
  1603. sys_log(0, " in same sectree");
  1604. }
  1605.  
  1606. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  1607.  
  1608. SetValidComboInterval(0);
  1609.  
  1610. return true;
  1611. }
  1612.  
  1613. struct BGMInfo
  1614. {
  1615. std::string name;
  1616. float vol;
  1617. };
  1618.  
  1619. typedef std::map<unsigned, BGMInfo> BGMInfoMap;
  1620.  
  1621. static BGMInfoMap gs_bgmInfoMap;
  1622. static bool gs_bgmVolEnable = false;
  1623.  
  1624. void CHARACTER_SetBGMVolumeEnable()
  1625. {
  1626. gs_bgmVolEnable = true;
  1627.  
  1628. sys_log(0, "bgm_info.set_bgm_volume_enable");
  1629. }
  1630.  
  1631. void CHARACTER_AddBGMInfo(unsigned mapIndex, const char* name, float vol)
  1632. {
  1633. BGMInfo newInfo;
  1634. newInfo.name = name;
  1635. newInfo.vol = vol;
  1636.  
  1637. gs_bgmInfoMap[mapIndex] = newInfo;
  1638.  
  1639. sys_log(0, "bgm_info.add_info(%d, '%s', %f)", mapIndex, name, vol);
  1640. }
  1641.  
  1642. const BGMInfo& CHARACTER_GetBGMInfo(unsigned mapIndex)
  1643. {
  1644. BGMInfoMap::iterator f = gs_bgmInfoMap.find(mapIndex);
  1645. if (gs_bgmInfoMap.end() == f)
  1646. {
  1647. static BGMInfo s_empty = {"", 0.0f};
  1648.  
  1649. return s_empty;
  1650. }
  1651.  
  1652. return f->second;
  1653. }
  1654.  
  1655. bool CHARACTER_IsBGMVolumeEnable()
  1656. {
  1657. return gs_bgmVolEnable;
  1658. }
  1659.  
  1660. void CHARACTER::MainCharacterPacket()
  1661. {
  1662. const unsigned mapIndex = GetMapIndex();
  1663. const BGMInfo& bgmInfo = CHARACTER_GetBGMInfo(mapIndex);
  1664.  
  1665. if (!bgmInfo.name.empty())
  1666. {
  1667. if (CHARACTER_IsBGMVolumeEnable())
  1668. {
  1669. sys_log(1, "bgm_info.play_bgm_vol(%d, name='%s', vol=%f)", mapIndex, bgmInfo.name.c_str(), bgmInfo.vol);
  1670. TPacketGCMainCharacter4_BGM_VOL mainChrPacket;
  1671.  
  1672. mainChrPacket.header = HEADER_GC_MAIN_CHARACTER4_BGM_VOL;
  1673. mainChrPacket.dwVID = m_vid;
  1674. mainChrPacket.wRaceNum = GetRaceNum();
  1675. mainChrPacket.lx = GetX();
  1676. mainChrPacket.ly = GetY();
  1677. mainChrPacket.lz = GetZ();
  1678. mainChrPacket.empire = GetDesc()->GetEmpire();
  1679. mainChrPacket.skill_group = GetSkillGroup();
  1680.  
  1681. strlcpy(mainChrPacket.szChrName, GetName(), sizeof(mainChrPacket.szChrName));
  1682.  
  1683. mainChrPacket.fBGMVol = bgmInfo.vol;
  1684. strlcpy(mainChrPacket.szBGMName, bgmInfo.name.c_str(), sizeof(mainChrPacket.szBGMName));
  1685. GetDesc()->Packet(&mainChrPacket, sizeof(TPacketGCMainCharacter4_BGM_VOL));
  1686. }
  1687.  
  1688. else
  1689. {
  1690. sys_log(1, "bgm_info.play(%d, '%s')", mapIndex, bgmInfo.name.c_str());
  1691. TPacketGCMainCharacter3_BGM mainChrPacket;
  1692.  
  1693. mainChrPacket.header = HEADER_GC_MAIN_CHARACTER3_BGM;
  1694. mainChrPacket.dwVID = m_vid;
  1695. mainChrPacket.wRaceNum = GetRaceNum();
  1696. mainChrPacket.lx = GetX();
  1697. mainChrPacket.ly = GetY();
  1698. mainChrPacket.lz = GetZ();
  1699. mainChrPacket.empire = GetDesc()->GetEmpire();
  1700. mainChrPacket.skill_group = GetSkillGroup();
  1701.  
  1702. strlcpy(mainChrPacket.szChrName, GetName(), sizeof(mainChrPacket.szChrName));
  1703. strlcpy(mainChrPacket.szBGMName, bgmInfo.name.c_str(), sizeof(mainChrPacket.szBGMName));
  1704.  
  1705. GetDesc()->Packet(&mainChrPacket, sizeof(TPacketGCMainCharacter3_BGM));
  1706. }
  1707. }
  1708.  
  1709. else
  1710. {
  1711. sys_log(0, "bgm_info.play(%d, DEFAULT_BGM_NAME)", mapIndex);
  1712.  
  1713. TPacketGCMainCharacter2_EMPIRE pack;
  1714.  
  1715. pack.header = HEADER_GC_MAIN_CHARACTER2_EMPIRE;
  1716. pack.dwVID = m_vid;
  1717. pack.wRaceNum = GetRaceNum();
  1718. pack.lx = GetX();
  1719. pack.ly = GetY();
  1720. pack.lz = GetZ();
  1721. pack.empire = GetDesc()->GetEmpire();
  1722. pack.skill_group = GetSkillGroup();
  1723.  
  1724. strlcpy(pack.szName, GetName(), sizeof(pack.szName));
  1725. GetDesc()->Packet(&pack, sizeof(TPacketGCMainCharacter2_EMPIRE));
  1726. }
  1727. }
  1728.  
  1729. void CHARACTER::PointsPacket()
  1730. {
  1731. if (!GetDesc())
  1732. return;
  1733.  
  1734. TPacketGCPoints pack;
  1735.  
  1736. pack.header = HEADER_GC_CHARACTER_POINTS;
  1737.  
  1738. pack.points[POINT_LEVEL] = GetLevel();
  1739. pack.points[POINT_EXP] = GetExp();
  1740. pack.points[POINT_NEXT_EXP] = GetNextExp();
  1741. pack.points[POINT_HP] = GetHP();
  1742. pack.points[POINT_MAX_HP] = GetMaxHP();
  1743. pack.points[POINT_SP] = GetSP();
  1744. pack.points[POINT_MAX_SP] = GetMaxSP();
  1745. pack.points[POINT_GOLD] = GetGold();
  1746. pack.points[POINT_STAMINA] = GetStamina();
  1747. pack.points[POINT_MAX_STAMINA] = GetMaxStamina();
  1748.  
  1749. for (int i = POINT_ST; i < POINT_MAX_NUM; ++i)
  1750. pack.points[i] = GetPoint(i);
  1751.  
  1752. #ifdef __TITLE_SYSTEM__
  1753. for (int w = TITLE_0; w < TITLES_MAX_NUM; ++w)
  1754. {
  1755. BYTE bType = POINT_TITLE + w;
  1756. pack.points[bType] = GetPoint(bType);
  1757. }
  1758. #endif
  1759.  
  1760. GetDesc()->Packet(&pack, sizeof(TPacketGCPoints));
  1761. }
  1762.  
  1763. bool CHARACTER::ChangeSex()
  1764. {
  1765. int src_race = GetRaceNum();
  1766.  
  1767. switch (src_race)
  1768. {
  1769. case MAIN_RACE_WARRIOR_M:
  1770. m_points.job = MAIN_RACE_WARRIOR_W;
  1771. break;
  1772.  
  1773. case MAIN_RACE_WARRIOR_W:
  1774. m_points.job = MAIN_RACE_WARRIOR_M;
  1775. break;
  1776.  
  1777. case MAIN_RACE_ASSASSIN_M:
  1778. m_points.job = MAIN_RACE_ASSASSIN_W;
  1779. break;
  1780.  
  1781. case MAIN_RACE_ASSASSIN_W:
  1782. m_points.job = MAIN_RACE_ASSASSIN_M;
  1783. break;
  1784.  
  1785. case MAIN_RACE_SURA_M:
  1786. m_points.job = MAIN_RACE_SURA_W;
  1787. break;
  1788.  
  1789. case MAIN_RACE_SURA_W:
  1790. m_points.job = MAIN_RACE_SURA_M;
  1791. break;
  1792.  
  1793. case MAIN_RACE_SHAMAN_M:
  1794. m_points.job = MAIN_RACE_SHAMAN_W;
  1795. break;
  1796.  
  1797. case MAIN_RACE_SHAMAN_W:
  1798. m_points.job = MAIN_RACE_SHAMAN_M;
  1799. break;
  1800.  
  1801. default:
  1802. sys_err("CHANGE_SEX: %s unknown race %d", GetName(), src_race);
  1803. return false;
  1804. }
  1805.  
  1806. sys_log(0, "CHANGE_SEX: %s (%d -> %d)", GetName(), src_race, m_points.job);
  1807.  
  1808. return true;
  1809. }
  1810.  
  1811. WORD CHARACTER::GetRaceNum() const
  1812. {
  1813. if (m_dwPolymorphRace)
  1814. return m_dwPolymorphRace;
  1815.  
  1816. if (m_pkMobData)
  1817. return m_pkMobData->m_table.dwVnum;
  1818.  
  1819. return m_points.job;
  1820. }
  1821.  
  1822. void CHARACTER::SetRace(BYTE race)
  1823. {
  1824. if (race >= MAIN_RACE_MAX_NUM)
  1825. {
  1826. sys_err("CHARACTER::SetRace(name=%s, race=%d).OUT_OF_RACE_RANGE", GetName(), race);
  1827. return;
  1828. }
  1829.  
  1830. m_points.job = race;
  1831. }
  1832.  
  1833. BYTE CHARACTER::GetJob() const
  1834. {
  1835. unsigned race = m_points.job;
  1836. unsigned job;
  1837.  
  1838. if (RaceToJob(race, &job))
  1839. return job;
  1840.  
  1841. sys_err("CHARACTER::GetJob(name=%s, race=%d).OUT_OF_RACE_RANGE", GetName(), race);
  1842.  
  1843. return JOB_WARRIOR;
  1844. }
  1845.  
  1846. void CHARACTER::SetLevel(BYTE level)
  1847. {
  1848. m_points.level = level;
  1849.  
  1850. if (IsPC())
  1851. {
  1852. if (level < PK_PROTECT_LEVEL)
  1853. SetPKMode(PK_MODE_PROTECT);
  1854.  
  1855. else if (GetGMLevel() != GM_PLAYER)
  1856. SetPKMode(PK_MODE_PROTECT);
  1857.  
  1858. else if (m_bPKMode == PK_MODE_PROTECT)
  1859. SetPKMode(PK_MODE_PEACE);
  1860. }
  1861. }
  1862.  
  1863. void CHARACTER::SetEmpire(BYTE bEmpire)
  1864. {
  1865. m_bEmpire = bEmpire;
  1866. }
  1867.  
  1868. #ifdef ENABLE_VIP_SYSTEM
  1869. bool CHARACTER::VipSystemTime()
  1870. {
  1871. time_t t1 = time(0);
  1872.  
  1873. std::auto_ptr<SQLMsg> Premiums(DBManager::instance().DirectQuery("SELECT TIMP,FARA_TIMP FROM player.vip_system WHERE PID_VIP = %u", GetPlayerID()));
  1874.  
  1875. MYSQL_ROW row = mysql_fetch_row(Premiums->Get()->pSQLResult);
  1876.  
  1877. long int time = atoi(row[0]);
  1878. int no_time = atoi(row[1]);
  1879.  
  1880. if (no_time != 1)
  1881. {
  1882. if (t1 >= time)
  1883. {
  1884. DBManager::instance().DirectQuery("DELETE FROM player.vip_system WHERE PID_VIP = %u", GetPlayerID());
  1885.  
  1886. return 0;
  1887. }
  1888. }
  1889. }
  1890.  
  1891. void CHARACTER::VipSystem()
  1892. {
  1893. std::auto_ptr<SQLMsg> pmsg(DBManager::instance().DirectQuery("SELECT COUNT(*) FROM player.vip_system WHERE PID_VIP = %u", GetPlayerID()));
  1894. MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
  1895.  
  1896. BYTE exista = 0;
  1897. str_to_number(exista, row[0]);
  1898.  
  1899. if (exista)
  1900. {
  1901. if (VipSystemTime())
  1902. {
  1903. m_afAffectFlag.Set(AFF_VIP);
  1904. }
  1905. }
  1906. }
  1907. #endif
  1908.  
  1909. #ifdef ENABLE_PREMIUM_SYSTEM
  1910. bool CHARACTER::PremiumSystemTime()
  1911. {
  1912. time_t t1 = time(0);
  1913.  
  1914. std::auto_ptr<SQLMsg> Premiums(DBManager::instance().DirectQuery("SELECT TIMP,FARA_TIMP FROM player.premium_system WHERE PID_PREMIUM = %u", GetPlayerID()));
  1915.  
  1916. MYSQL_ROW row = mysql_fetch_row(Premiums->Get()->pSQLResult);
  1917.  
  1918. long int time = atoi(row[0]);
  1919. int no_time = atoi(row[1]);
  1920.  
  1921. if (no_time != 1)
  1922. {
  1923. if (t1 >= time)
  1924. {
  1925. DBManager::instance().DirectQuery("DELETE FROM player.premium_system WHERE PID_PREMIUM = %u", GetPlayerID());
  1926.  
  1927. return 0;
  1928. }
  1929. }
  1930. }
  1931.  
  1932. void CHARACTER::PremiumSystem()
  1933. {
  1934. std::auto_ptr<SQLMsg> pmsg(DBManager::instance().DirectQuery("SELECT COUNT(*) FROM player.premium_system WHERE PID_PREMIUM = %u", GetPlayerID()));
  1935. MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
  1936.  
  1937. BYTE exista = 0;
  1938. str_to_number(exista, row[0]);
  1939.  
  1940. if (exista)
  1941. {
  1942. if (PremiumSystemTime())
  1943. {
  1944. m_afAffectFlag.Set(AFF_PREMIUM);
  1945. }
  1946. }
  1947. }
  1948. #endif
  1949.  
  1950. void CHARACTER::SetPlayerProto(const TPlayerTable * t)
  1951. {
  1952. if (!GetDesc() || !*GetDesc()->GetHostName())
  1953. sys_err("cannot get desc or hostname");
  1954. else
  1955. SetGMLevel();
  1956.  
  1957. m_bCharType = CHAR_TYPE_PC;
  1958.  
  1959. m_dwPlayerID = t->id;
  1960.  
  1961. #ifdef __CUSTOM_TITLE_SYSTEM__
  1962. m_stTitle = t->title.szName;
  1963. memcpy(m_bTitleColor, t->title.bColours, sizeof(m_bTitleColor));
  1964.  
  1965. m_stTitle2 = t->title2.szName;
  1966. memcpy(m_bTitle2Color, t->title2.bColours2, sizeof(m_bTitle2Color));
  1967. #endif
  1968.  
  1969. m_iAlignment = t->lAlignment;
  1970. m_iRealAlignment = t->lAlignment;
  1971.  
  1972. m_points.voice = t->voice;
  1973.  
  1974. m_points.skill_group = t->skill_group;
  1975.  
  1976. m_pointsInstant.bBasePart = t->part_base;
  1977. SetPart(PART_HAIR, t->parts[PART_HAIR]);
  1978.  
  1979. m_points.iRandomHP = t->sRandomHP;
  1980. m_points.iRandomSP = t->sRandomSP;
  1981.  
  1982. if (m_pSkillLevels)
  1983. M2_DELETE_ARRAY(m_pSkillLevels);
  1984.  
  1985. m_pSkillLevels = M2_NEW TPlayerSkill[SKILL_MAX_NUM];
  1986. thecore_memcpy(m_pSkillLevels, t->skills, sizeof(TPlayerSkill) * SKILL_MAX_NUM);
  1987.  
  1988. if (t->lMapIndex >= 10000)
  1989. {
  1990. m_posWarp.x = t->lExitX;
  1991. m_posWarp.y = t->lExitY;
  1992. m_lWarpMapIndex = t->lExitMapIndex;
  1993. }
  1994.  
  1995. SetRealPoint(POINT_PLAYTIME, t->playtime);
  1996. m_dwLoginPlayTime = t->playtime;
  1997. SetRealPoint(POINT_ST, t->st);
  1998. SetRealPoint(POINT_HT, t->ht);
  1999. SetRealPoint(POINT_DX, t->dx);
  2000. SetRealPoint(POINT_IQ, t->iq);
  2001.  
  2002. SetPoint(POINT_ST, t->st);
  2003. SetPoint(POINT_HT, t->ht);
  2004. SetPoint(POINT_DX, t->dx);
  2005. SetPoint(POINT_IQ, t->iq);
  2006.  
  2007. SetPoint(POINT_STAT, t->stat_point);
  2008. SetPoint(POINT_SKILL, t->skill_point);
  2009. SetPoint(POINT_SUB_SKILL, t->sub_skill_point);
  2010. SetPoint(POINT_HORSE_SKILL, t->horse_skill_point);
  2011.  
  2012. SetPoint(POINT_STAT_RESET_COUNT, t->stat_reset_count);
  2013.  
  2014. SetPoint(POINT_LEVEL_STEP, t->level_step);
  2015. SetRealPoint(POINT_LEVEL_STEP, t->level_step);
  2016.  
  2017. SetRace(t->job);
  2018.  
  2019. SetLevel(t->level);
  2020. SetExp(t->exp);
  2021. SetGold(t->gold);
  2022.  
  2023. SetMapIndex(t->lMapIndex);
  2024. SetXYZ(t->x, t->y, t->z);
  2025.  
  2026. ComputePoints();
  2027.  
  2028. SetHP(t->hp);
  2029. SetSP(t->sp);
  2030. SetStamina(t->stamina);
  2031.  
  2032. #ifdef ENABLE_VIP_SYSTEM
  2033. VipSystem();
  2034. #endif
  2035.  
  2036. #ifdef ENABLE_PREMIUM_SYSTEM
  2037. PremiumSystem();
  2038. #endif
  2039.  
  2040. if (!test_server)
  2041. {
  2042. if (GetGMLevel() > GM_PLAYER)
  2043. {
  2044. m_afAffectFlag.Set(AFF_YMIR);
  2045. m_bPKMode = PK_MODE_PROTECT;
  2046. }
  2047. }
  2048.  
  2049. if (GetLevel() < PK_PROTECT_LEVEL)
  2050. m_bPKMode = PK_MODE_PROTECT;
  2051.  
  2052. SetHorseData(t->horse);
  2053.  
  2054. if (GetHorseLevel() > 0)
  2055. UpdateHorseDataByLogoff(t->logoff_interval);
  2056.  
  2057. thecore_memcpy(m_aiPremiumTimes, t->aiPremiumTimes, sizeof(t->aiPremiumTimes));
  2058.  
  2059. m_dwLogOffInterval = t->logoff_interval;
  2060.  
  2061. sys_log(0, "PLAYER_LOAD: %s PREMIUM %d %d, LOGGOFF_INTERVAL %u PTR: %p", t->name, m_aiPremiumTimes[0], m_aiPremiumTimes[1], t->logoff_interval, this);
  2062.  
  2063. if (GetGMLevel() != GM_PLAYER)
  2064. {
  2065. LogManager::instance().CharLog(this, GetGMLevel(), "GM_LOGIN", "");
  2066. sys_log(0, "GM_LOGIN(gmlevel=%d, name=%s(%d), pos=(%d, %d)", GetGMLevel(), GetName(), GetPlayerID(), GetX(), GetY());
  2067. }
  2068.  
  2069. #ifdef __PET_SYSTEM__
  2070. if (m_petSystem)
  2071. {
  2072. m_petSystem->Destroy();
  2073. delete m_petSystem;
  2074. }
  2075.  
  2076. m_petSystem = M2_NEW CPetSystem(this);
  2077. #endif
  2078.  
  2079. }
  2080.  
  2081. EVENTFUNC(kill_ore_load_event)
  2082. {
  2083. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  2084. if ( info == NULL )
  2085. {
  2086. sys_err( "kill_ore_load_even> <Factor> Null pointer" );
  2087. return 0;
  2088. }
  2089.  
  2090. LPCHARACTER ch = info->ch;
  2091. if (ch == NULL)
  2092. {
  2093. return 0;
  2094. }
  2095.  
  2096. ch->m_pkMiningEvent = NULL;
  2097. M2_DESTROY_CHARACTER(ch);
  2098.  
  2099. return 0;
  2100. }
  2101.  
  2102. void CHARACTER::SetProto(const CMob * pkMob)
  2103. {
  2104. if (m_pkMobInst)
  2105. M2_DELETE(m_pkMobInst);
  2106.  
  2107. m_pkMobData = pkMob;
  2108. m_pkMobInst = M2_NEW CMobInstance;
  2109.  
  2110. m_bPKMode = PK_MODE_FREE;
  2111.  
  2112. const TMobTable * t = &m_pkMobData->m_table;
  2113.  
  2114. m_bCharType = t->bType;
  2115.  
  2116. SetLevel(t->bLevel);
  2117. SetEmpire(t->bEmpire);
  2118.  
  2119. SetExp(t->dwExp);
  2120. SetRealPoint(POINT_ST, t->bStr);
  2121. SetRealPoint(POINT_DX, t->bDex);
  2122. SetRealPoint(POINT_HT, t->bCon);
  2123. SetRealPoint(POINT_IQ, t->bInt);
  2124.  
  2125. ComputePoints();
  2126.  
  2127. SetHP(GetMaxHP());
  2128. SetSP(GetMaxSP());
  2129.  
  2130. ////////////////////
  2131. m_pointsInstant.dwAIFlag = t->dwAIFlag;
  2132. SetImmuneFlag(t->dwImmuneFlag);
  2133.  
  2134. AssignTriggers(t);
  2135.  
  2136. ApplyMobAttribute(t);
  2137.  
  2138. if (IsStone())
  2139. {
  2140. DetermineDropMetinStone();
  2141. }
  2142.  
  2143. if (IsWarp() || IsGoto())
  2144. {
  2145. StartWarpNPCEvent();
  2146. }
  2147.  
  2148. CHARACTER_MANAGER::instance().RegisterRaceNumMap(this);
  2149.  
  2150. if (GetRaceNum() == xmas::MOB_SANTA_VNUM)
  2151. {
  2152. SetPoint(POINT_ATT_GRADE_BONUS, 10);
  2153. SetPoint(POINT_DEF_GRADE_BONUS, 6);
  2154.  
  2155. m_dwPlayStartTime = get_dword_time() + 30 * 1000;
  2156.  
  2157. if (test_server)
  2158. m_dwPlayStartTime = get_dword_time() + 30 * 1000;
  2159. }
  2160.  
  2161.  
  2162. if (warmap::IsWarFlag(GetRaceNum()))
  2163. {
  2164. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlag, &CHARACTER::EndStateEmpty);
  2165. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlag, &CHARACTER::EndStateEmpty);
  2166. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlag, &CHARACTER::EndStateEmpty);
  2167. }
  2168.  
  2169. if (warmap::IsWarFlagBase(GetRaceNum()))
  2170. {
  2171. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlagBase, &CHARACTER::EndStateEmpty);
  2172. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlagBase, &CHARACTER::EndStateEmpty);
  2173. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlagBase, &CHARACTER::EndStateEmpty);
  2174. }
  2175.  
  2176. if (m_bCharType == CHAR_TYPE_HORSE || GetRaceNum() == 20101 || GetRaceNum() == 20102 || GetRaceNum() == 20103 || GetRaceNum() == 20104 || GetRaceNum() == 20105 || GetRaceNum() == 20106 || GetRaceNum() == 20107 || GetRaceNum() == 20108 || GetRaceNum() == 20109 )
  2177. {
  2178. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateHorse, &CHARACTER::EndStateEmpty);
  2179. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateMove, &CHARACTER::EndStateEmpty);
  2180. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateHorse, &CHARACTER::EndStateEmpty);
  2181. }
  2182.  
  2183. if (mining::IsVeinOfOre (GetRaceNum()))
  2184. {
  2185. char_event_info* info = AllocEventInfo<char_event_info>();
  2186.  
  2187. info->ch = this;
  2188.  
  2189. m_pkMiningEvent = event_create(kill_ore_load_event, info, PASSES_PER_SEC(number(7 * 60, 15 * 60)));
  2190. }
  2191. }
  2192.  
  2193. const TMobTable & CHARACTER::GetMobTable() const
  2194. {
  2195. return m_pkMobData->m_table;
  2196. }
  2197.  
  2198. bool CHARACTER::IsRaceFlag(DWORD dwBit) const
  2199. {
  2200. return m_pkMobData ? IS_SET(m_pkMobData->m_table.dwRaceFlag, dwBit) : 0;
  2201. }
  2202.  
  2203. DWORD CHARACTER::GetMobDamageMin() const
  2204. {
  2205. return m_pkMobData->m_table.dwDamageRange[0];
  2206. }
  2207.  
  2208. DWORD CHARACTER::GetMobDamageMax() const
  2209. {
  2210. return m_pkMobData->m_table.dwDamageRange[1];
  2211. }
  2212.  
  2213. float CHARACTER::GetMobDamageMultiply() const
  2214. {
  2215. float fDamMultiply = GetMobTable().fDamMultiply;
  2216.  
  2217. if (IsBerserk())
  2218. fDamMultiply = fDamMultiply * 2.0f;
  2219.  
  2220. return fDamMultiply;
  2221. }
  2222.  
  2223. DWORD CHARACTER::GetMobDropItemVnum() const
  2224. {
  2225. return m_pkMobData->m_table.dwDropItemVnum;
  2226. }
  2227.  
  2228. bool CHARACTER::IsSummonMonster() const
  2229. {
  2230. return GetSummonVnum() != 0;
  2231. }
  2232.  
  2233. DWORD CHARACTER::GetSummonVnum() const
  2234. {
  2235. return m_pkMobData ? m_pkMobData->m_table.dwSummonVnum : 0;
  2236. }
  2237.  
  2238. DWORD CHARACTER::GetPolymorphItemVnum() const
  2239. {
  2240. return m_pkMobData ? m_pkMobData->m_table.dwPolymorphItemVnum : 0;
  2241. }
  2242.  
  2243. DWORD CHARACTER::GetMonsterDrainSPPoint() const
  2244. {
  2245. return m_pkMobData ? m_pkMobData->m_table.dwDrainSP : 0;
  2246. }
  2247.  
  2248. BYTE CHARACTER::GetMobRank() const
  2249. {
  2250. if (!m_pkMobData)
  2251. return MOB_RANK_KNIGHT;
  2252.  
  2253. return m_pkMobData->m_table.bRank;
  2254. }
  2255.  
  2256. BYTE CHARACTER::GetMobSize() const
  2257. {
  2258. if (!m_pkMobData)
  2259. return MOBSIZE_MEDIUM;
  2260.  
  2261. return m_pkMobData->m_table.bSize;
  2262. }
  2263.  
  2264. WORD CHARACTER::GetMobAttackRange() const
  2265. {
  2266. switch (GetMobBattleType())
  2267. {
  2268. case BATTLE_TYPE_RANGE:
  2269. case BATTLE_TYPE_MAGIC:
  2270. return m_pkMobData->m_table.wAttackRange + GetPoint(POINT_BOW_DISTANCE);
  2271.  
  2272. default:
  2273. return m_pkMobData->m_table.wAttackRange;
  2274. }
  2275. }
  2276.  
  2277. BYTE CHARACTER::GetMobBattleType() const
  2278. {
  2279. if (!m_pkMobData)
  2280. return BATTLE_TYPE_MELEE;
  2281.  
  2282. return (m_pkMobData->m_table.bBattleType);
  2283. }
  2284.  
  2285. void CHARACTER::ComputeBattlePoints()
  2286. {
  2287. if (IsPolymorphed())
  2288. {
  2289. DWORD dwMobVnum = GetPolymorphVnum();
  2290.  
  2291. const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
  2292. int iAtt = 0;
  2293. int iDef = 0;
  2294.  
  2295. if (pMob)
  2296. {
  2297. iAtt = GetLevel() * 2 + GetPolymorphPoint(POINT_ST) * 2;
  2298. iDef = GetLevel() + GetPolymorphPoint(POINT_HT) + pMob->m_table.wDef;
  2299. }
  2300.  
  2301. SetPoint(POINT_ATT_GRADE, iAtt);
  2302. SetPoint(POINT_DEF_GRADE, iDef);
  2303. SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
  2304. SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
  2305. }
  2306.  
  2307. else if (IsPC())
  2308. {
  2309. SetPoint(POINT_ATT_GRADE, 0);
  2310. SetPoint(POINT_DEF_GRADE, 0);
  2311. SetPoint(POINT_CLIENT_DEF_GRADE, 0);
  2312. SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
  2313. SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
  2314.  
  2315. int iAtk = GetLevel() * 2;
  2316. int iStatAtk = 0;
  2317.  
  2318. switch (GetJob())
  2319. {
  2320. case JOB_WARRIOR:
  2321. case JOB_SURA:
  2322. iStatAtk = (2 * GetPoint(POINT_ST));
  2323. break;
  2324.  
  2325. case JOB_ASSASSIN:
  2326. iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_DX)) / 3;
  2327. break;
  2328.  
  2329. case JOB_SHAMAN:
  2330. iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_IQ)) / 3;
  2331. break;
  2332.  
  2333. default:
  2334. sys_err("invalid job %d", GetJob());
  2335. iStatAtk = (2 * GetPoint(POINT_ST));
  2336. break;
  2337. }
  2338.  
  2339. if (GetMountVnum() && iStatAtk < 2 * GetPoint(POINT_ST))
  2340. iStatAtk = (2 * GetPoint(POINT_ST));
  2341.  
  2342. iAtk += iStatAtk;
  2343.  
  2344. if (GetMountVnum())
  2345. {
  2346. if (GetJob() == JOB_SURA && GetSkillGroup() == 1)
  2347. {
  2348. iAtk += (iAtk * GetHorseLevel()) / 60;
  2349. }
  2350.  
  2351. else
  2352. {
  2353. iAtk += (iAtk * GetHorseLevel()) / 30;
  2354. }
  2355. }
  2356.  
  2357. iAtk += GetPoint(POINT_ATT_GRADE_BONUS);
  2358.  
  2359. PointChange(POINT_ATT_GRADE, iAtk);
  2360.  
  2361. int iShowDef = GetLevel() + GetPoint(POINT_HT);
  2362. int iDef = GetLevel() + (int) (GetPoint(POINT_HT) / 1.25);
  2363. int iArmor = 0;
  2364.  
  2365. LPITEM pkItem;
  2366.  
  2367. for (int i = 0; i < WEAR_MAX_NUM; ++i)
  2368. if ((pkItem = GetWear(i)) && pkItem->GetType() == ITEM_ARMOR)
  2369. {
  2370. if (pkItem->GetSubType() == ARMOR_BODY || pkItem->GetSubType() == ARMOR_HEAD || pkItem->GetSubType() == ARMOR_FOOTS || pkItem->GetSubType() == ARMOR_SHIELD)
  2371. {
  2372. iArmor += pkItem->GetValue(1);
  2373. iArmor += (2 * pkItem->GetValue(5));
  2374. }
  2375. }
  2376.  
  2377. if( true == IsHorseRiding() )
  2378. {
  2379. if (iArmor < GetHorseArmor())
  2380. iArmor = GetHorseArmor();
  2381.  
  2382. const char* pHorseName = CHorseNameManager::instance().GetHorseName(GetPlayerID());
  2383.  
  2384. if (pHorseName != NULL && strlen(pHorseName))
  2385. {
  2386. iArmor += 20;
  2387. }
  2388. }
  2389.  
  2390. iArmor += GetPoint(POINT_DEF_GRADE_BONUS);
  2391. iArmor += GetPoint(POINT_PARTY_DEFENDER_BONUS);
  2392.  
  2393. PointChange(POINT_DEF_GRADE, iDef + iArmor);
  2394. PointChange(POINT_CLIENT_DEF_GRADE, (iShowDef + iArmor) - GetPoint(POINT_DEF_GRADE));
  2395.  
  2396. PointChange(POINT_MAGIC_ATT_GRADE, GetLevel() * 2 + GetPoint(POINT_IQ) * 2 + GetPoint(POINT_MAGIC_ATT_GRADE_BONUS));
  2397. PointChange(POINT_MAGIC_DEF_GRADE, GetLevel() + (GetPoint(POINT_IQ) * 3 + GetPoint(POINT_HT)) / 3 + iArmor / 2 + GetPoint(POINT_MAGIC_DEF_GRADE_BONUS));
  2398. }
  2399.  
  2400. else
  2401. {
  2402. int iAtt = GetLevel() * 2 + GetPoint(POINT_ST) * 2;
  2403. int iDef = GetLevel() + GetPoint(POINT_HT) + GetMobTable().wDef;
  2404.  
  2405. SetPoint(POINT_ATT_GRADE, iAtt);
  2406. SetPoint(POINT_DEF_GRADE, iDef);
  2407. SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
  2408. SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
  2409. }
  2410. }
  2411.  
  2412. void CHARACTER::ComputePoints()
  2413. {
  2414. long lStat = GetPoint(POINT_STAT);
  2415. long lStatResetCount = GetPoint(POINT_STAT_RESET_COUNT);
  2416. long lSkillActive = GetPoint(POINT_SKILL);
  2417. long lSkillSub = GetPoint(POINT_SUB_SKILL);
  2418. long lSkillHorse = GetPoint(POINT_HORSE_SKILL);
  2419. long lLevelStep = GetPoint(POINT_LEVEL_STEP);
  2420.  
  2421. long lAttackerBonus = GetPoint(POINT_PARTY_ATTACKER_BONUS);
  2422. long lTankerBonus = GetPoint(POINT_PARTY_TANKER_BONUS);
  2423. long lBufferBonus = GetPoint(POINT_PARTY_BUFFER_BONUS);
  2424. long lSkillMasterBonus = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
  2425. long lHasteBonus = GetPoint(POINT_PARTY_HASTE_BONUS);
  2426. long lDefenderBonus = GetPoint(POINT_PARTY_DEFENDER_BONUS);
  2427.  
  2428. long lHPRecovery = GetPoint(POINT_HP_RECOVERY);
  2429. long lSPRecovery = GetPoint(POINT_SP_RECOVERY);
  2430.  
  2431. #ifdef __TITLE_SYSTEM__
  2432. std::vector<int> vTitles;
  2433. if (IsPC())
  2434. {
  2435. for (int w = TITLE_0; w < TITLES_MAX_NUM; ++w)
  2436. {
  2437. BYTE bType = POINT_TITLE + w;
  2438. vTitles.push_back(GetPoint(bType));
  2439. }
  2440.  
  2441. vTitles.push_back(0);
  2442. }
  2443. #endif
  2444.  
  2445. memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points));
  2446. BuffOnAttr_ClearAll();
  2447. m_SkillDamageBonus.clear();
  2448.  
  2449. SetPoint(POINT_STAT, lStat);
  2450. SetPoint(POINT_SKILL, lSkillActive);
  2451. SetPoint(POINT_SUB_SKILL, lSkillSub);
  2452. SetPoint(POINT_HORSE_SKILL, lSkillHorse);
  2453. SetPoint(POINT_LEVEL_STEP, lLevelStep);
  2454. SetPoint(POINT_STAT_RESET_COUNT, lStatResetCount);
  2455.  
  2456. SetPoint(POINT_ST, GetRealPoint(POINT_ST));
  2457. SetPoint(POINT_HT, GetRealPoint(POINT_HT));
  2458. SetPoint(POINT_DX, GetRealPoint(POINT_DX));
  2459. SetPoint(POINT_IQ, GetRealPoint(POINT_IQ));
  2460.  
  2461. SetPart(PART_MAIN, GetOriginalPart(PART_MAIN));
  2462. SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON));
  2463. SetPart(PART_HEAD, GetOriginalPart(PART_HEAD));
  2464. SetPart(PART_HAIR, GetOriginalPart(PART_HAIR));
  2465.  
  2466. #ifdef __EFFECT_SYSTEM__
  2467. SetPart(BODY_EFFECT, GetOriginalPart(BODY_EFFECT));
  2468. SetPart(WEAPON_RIGHT_EFFECT, GetOriginalPart(WEAPON_RIGHT_EFFECT));
  2469. SetPart(WEAPON_LEFT_EFFECT, GetOriginalPart(WEAPON_LEFT_EFFECT));
  2470. #endif
  2471.  
  2472. SetPoint(POINT_PARTY_ATTACKER_BONUS, lAttackerBonus);
  2473. SetPoint(POINT_PARTY_TANKER_BONUS, lTankerBonus);
  2474. SetPoint(POINT_PARTY_BUFFER_BONUS, lBufferBonus);
  2475. SetPoint(POINT_PARTY_SKILL_MASTER_BONUS, lSkillMasterBonus);
  2476. SetPoint(POINT_PARTY_HASTE_BONUS, lHasteBonus);
  2477. SetPoint(POINT_PARTY_DEFENDER_BONUS, lDefenderBonus);
  2478.  
  2479. SetPoint(POINT_HP_RECOVERY, lHPRecovery);
  2480. SetPoint(POINT_SP_RECOVERY, lSPRecovery);
  2481.  
  2482. #ifdef __TITLE_SYSTEM__
  2483. if (IsPC())
  2484. {
  2485. for (int w = TITLE_0; w < TITLES_MAX_NUM; ++w)
  2486. {
  2487. BYTE bType = POINT_TITLE + w;
  2488. SetPoint(bType, vTitles[w]);
  2489. }
  2490.  
  2491. vTitles.clear();
  2492. }
  2493. #endif
  2494.  
  2495. int iMaxHP, iMaxSP;
  2496. int iMaxStamina;
  2497.  
  2498. if (IsPC())
  2499. {
  2500. iMaxHP = JobInitialPoints[GetJob()].max_hp + m_points.iRandomHP + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].hp_per_ht;
  2501. iMaxSP = JobInitialPoints[GetJob()].max_sp + m_points.iRandomSP + GetPoint(POINT_IQ) * JobInitialPoints[GetJob()].sp_per_iq;
  2502. iMaxStamina = JobInitialPoints[GetJob()].max_stamina + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].stamina_per_con;
  2503.  
  2504. {
  2505. CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_ADD_HP);
  2506.  
  2507. if (NULL != pkSk)
  2508. {
  2509. pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_ADD_HP) / 100.0f);
  2510.  
  2511. iMaxHP += static_cast<int>(pkSk->kPointPoly.Eval());
  2512. }
  2513. }
  2514.  
  2515. if (CPVPManager::instance().IsFightingGerman(GetPlayerID()))
  2516. {
  2517. if (GetJob() == JOB_ASSASSIN)
  2518. SetPoint(POINT_MAX_HP, 150000);
  2519.  
  2520. else if (GetJob() == JOB_SURA)
  2521. SetPoint(POINT_MAX_HP, 150000);
  2522.  
  2523. else if (GetJob() == JOB_SHAMAN)
  2524. SetPoint(POINT_MAX_HP, 150000);
  2525.  
  2526. else
  2527. SetPoint(POINT_MAX_HP, 170000);
  2528.  
  2529. SetPoint(POINT_CRITICAL_PCT, 500);
  2530. SetPoint(POINT_MOV_SPEED, 200);
  2531. SetPoint(POINT_ATT_SPEED, 170);
  2532. SetPoint(POINT_CASTING_SPEED, 160);
  2533. }
  2534.  
  2535. else if (CPVPManager::instance().IsFightingTactic(GetPlayerID()))
  2536. {
  2537. SetPoint(POINT_MAX_HP, 45000);
  2538. SetPoint(POINT_MOV_SPEED, 200);
  2539. SetPoint(POINT_ATT_SPEED, 170);
  2540. SetPoint(POINT_CASTING_SPEED, 160);
  2541. }
  2542.  
  2543. else
  2544. {
  2545. SetPoint(POINT_MOV_SPEED, 140);
  2546. SetPoint(POINT_ATT_SPEED, 130);
  2547. SetPoint(POINT_CASTING_SPEED, 100);
  2548. SetPoint(POINT_PENETRATE_PCT, 25);
  2549. SetPoint(POINT_RESIST_MAGIC, 10);
  2550. SetPoint(POINT_MAX_HP, 15000);
  2551. SetPoint(POINT_MAX_SP, 35000);
  2552. }
  2553. }
  2554.  
  2555. else
  2556. {
  2557. iMaxHP = m_pkMobData->m_table.dwMaxHP;
  2558. iMaxSP = 0;
  2559. iMaxStamina = 0;
  2560.  
  2561. SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed);
  2562. SetPoint(POINT_MOV_SPEED, m_pkMobData->m_table.sMovingSpeed);
  2563. SetPoint(POINT_CASTING_SPEED, m_pkMobData->m_table.sAttackSpeed);
  2564. }
  2565.  
  2566. if (IsPC())
  2567. {
  2568. if (GetMountVnum())
  2569. {
  2570. if (GetHorseST() > GetPoint(POINT_ST))
  2571. PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
  2572.  
  2573. if (GetHorseDX() > GetPoint(POINT_DX))
  2574. PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
  2575.  
  2576. if (GetHorseHT() > GetPoint(POINT_HT))
  2577. PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
  2578.  
  2579. if (GetHorseIQ() > GetPoint(POINT_IQ))
  2580. PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
  2581. }
  2582. }
  2583.  
  2584. ComputeBattlePoints();
  2585.  
  2586. if (iMaxHP != GetMaxHP())
  2587. {
  2588. SetRealPoint(POINT_MAX_HP, iMaxHP);
  2589. }
  2590.  
  2591. PointChange(POINT_MAX_HP, 0);
  2592.  
  2593. if (iMaxSP != GetMaxSP())
  2594. {
  2595. SetRealPoint(POINT_MAX_SP, iMaxSP);
  2596. }
  2597.  
  2598. PointChange(POINT_MAX_SP, 0);
  2599.  
  2600. SetMaxStamina(iMaxStamina);
  2601.  
  2602. int iCurHP = this->GetHP();
  2603. int iCurSP = this->GetSP();
  2604.  
  2605. m_pointsInstant.dwImmuneFlag = 0;
  2606.  
  2607. for (int i = 0 ; i < WEAR_MAX_NUM; i++)
  2608. {
  2609. LPITEM pItem = GetWear(i);
  2610. if (pItem)
  2611. {
  2612. pItem->ModifyPoints(true);
  2613. SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag());
  2614. }
  2615. }
  2616.  
  2617. if (DragonSoul_IsDeckActivated())
  2618. {
  2619. for (int i = WEAR_MAX_NUM + DS_SLOT_MAX * DragonSoul_GetActiveDeck();
  2620. i < WEAR_MAX_NUM + DS_SLOT_MAX * (DragonSoul_GetActiveDeck() + 1); i++)
  2621. {
  2622. LPITEM pItem = GetWear(i);
  2623. if (pItem)
  2624. {
  2625. if (DSManager::instance().IsTimeLeftDragonSoul(pItem))
  2626. pItem->ModifyPoints(true);
  2627. }
  2628. }
  2629. }
  2630.  
  2631. if (GetHP() > GetMaxHP())
  2632. PointChange(POINT_HP, GetMaxHP() - GetHP());
  2633.  
  2634. if (GetSP() > GetMaxSP())
  2635. PointChange(POINT_SP, GetMaxSP() - GetSP());
  2636.  
  2637. ComputeSkillPoints();
  2638.  
  2639. RefreshAffect();
  2640.  
  2641. if (IsPC())
  2642. {
  2643. if (this->GetHP() != iCurHP)
  2644. this->PointChange(POINT_HP, iCurHP-this->GetHP());
  2645.  
  2646. if (this->GetSP() != iCurSP)
  2647. this->PointChange(POINT_SP, iCurSP-this->GetSP());
  2648. }
  2649.  
  2650. // CPetSystem* pPetSystem = GetPetSystem();
  2651. // if (NULL != pPetSystem)
  2652. // {
  2653. // pPetSystem->RefreshBuff();
  2654. // }
  2655.  
  2656. UpdatePacket();
  2657. }
  2658.  
  2659. #ifdef __PET_SYSTEM__
  2660. void CHARACTER::PetSummon(LPITEM petItem)
  2661. {
  2662. CPetSystem* petSystem = GetPetSystem();
  2663. DWORD mobVnum = 0;
  2664.  
  2665. if (GetMapIndex() == 113)
  2666. return;
  2667.  
  2668. if (!petSystem || !petItem)
  2669. return;
  2670.  
  2671. if(petItem->GetValue(1) != 0)
  2672. mobVnum = petItem->GetValue(1);
  2673.  
  2674. petSystem->Summon(mobVnum, petItem, false);
  2675. }
  2676.  
  2677. void CHARACTER::PetUnsummon(LPITEM petItem)
  2678. {
  2679. CPetSystem* petSystem = GetPetSystem();
  2680. DWORD mobVnum = 0;
  2681.  
  2682. if (!petSystem || !petItem)
  2683. return;
  2684.  
  2685. if(petItem->GetValue(1) != 0)
  2686. mobVnum = petItem->GetValue(1);
  2687.  
  2688. petSystem->Unsummon(mobVnum);
  2689. }
  2690.  
  2691. void CHARACTER::CheckPet()
  2692. {
  2693. CPetSystem* petSystem = GetPetSystem();
  2694. LPITEM petItem = GetWear(WEAR_NORMAL_PET);
  2695. DWORD mobVnum = 0;
  2696.  
  2697. if (GetMapIndex() == 113)
  2698. return;
  2699.  
  2700. if (!petSystem || !petItem)
  2701. return;
  2702.  
  2703. if(petItem->GetValue(1) != 0)
  2704. mobVnum = petItem->GetValue(1);
  2705.  
  2706. if(petSystem->CountSummoned() == 0)
  2707. {
  2708. petSystem->Summon(mobVnum, petItem, false);
  2709. }
  2710. }
  2711.  
  2712. bool CHARACTER::IsPetSummon()
  2713. {
  2714. return (GetWear(WEAR_NORMAL_PET));
  2715. }
  2716. #endif
  2717.  
  2718. #ifdef __CUSTOM_TITLE_SYSTEM__
  2719. const char * CHARACTER::GetTitle()
  2720. {
  2721. return this->m_stTitle.c_str();
  2722. }
  2723.  
  2724. void CHARACTER::SetTitle(const char * title)
  2725. {
  2726. m_stTitle = title;
  2727. }
  2728.  
  2729. BYTE* CHARACTER::GetTitleColors() const
  2730. {
  2731. return const_cast<BYTE*>(m_bTitleColor);
  2732. }
  2733.  
  2734. BYTE CHARACTER::GetTitleColor(int index)
  2735. {
  2736. assert(index < TITLE_COLOR_MAX_NUM);
  2737.  
  2738. return m_bTitleColor[index];
  2739. }
  2740.  
  2741. void CHARACTER::SetTitleColor(int index, BYTE val)
  2742. {
  2743. assert(index < TITLE_COLOR_MAX_NUM);
  2744. m_bTitleColor[index] = val;
  2745. }
  2746.  
  2747. void CHARACTER::SetTitleColors(const BYTE* colors)
  2748. {
  2749. if (!colors)
  2750. return;
  2751.  
  2752. memcpy(m_bTitleColor, colors, sizeof(m_bTitleColor));
  2753. }
  2754.  
  2755. void CHARACTER::UpdateTitle()
  2756. {
  2757. TPacketGCUpdateTitle pack;
  2758.  
  2759. pack.header = HEADER_GC_UPDATE_TITLE;
  2760. pack.dwVID = GetVID();
  2761.  
  2762. strlcpy(pack.title.szName, GetTitle(), sizeof(pack.title.szName));
  2763. memcpy(pack.title.bColours, m_bTitleColor, sizeof(pack.title.bColours));
  2764.  
  2765. PacketAround(&pack, sizeof(pack));
  2766. }
  2767.  
  2768. const char * CHARACTER::GetTitle2()
  2769. {
  2770. return this->m_stTitle2.c_str();
  2771. }
  2772.  
  2773. void CHARACTER::SetTitle2(const char * title2)
  2774. {
  2775. m_stTitle2 = title2;
  2776. }
  2777.  
  2778. BYTE* CHARACTER::GetTitle2Colors() const
  2779. {
  2780. return const_cast<BYTE*>(m_bTitle2Color);
  2781. }
  2782.  
  2783. BYTE CHARACTER::GetTitle2Color(int index)
  2784. {
  2785. assert(index < TITLE2_COLOR_MAX_NUM);
  2786.  
  2787. return m_bTitle2Color[index];
  2788. }
  2789.  
  2790. void CHARACTER::SetTitle2Color(int index, BYTE val)
  2791. {
  2792. assert(index < TITLE2_COLOR_MAX_NUM);
  2793. m_bTitle2Color[index] = val;
  2794. }
  2795.  
  2796. void CHARACTER::SetTitle2Colors(const BYTE* colors2)
  2797. {
  2798. if (!colors2)
  2799. return;
  2800.  
  2801. memcpy(m_bTitle2Color, colors2, sizeof(m_bTitle2Color));
  2802. }
  2803.  
  2804. void CHARACTER::UpdateTitle2()
  2805. {
  2806. TPacketGCUpdateTitle2 pack;
  2807.  
  2808. pack.header = HEADER_GC_UPDATE_TITLE2;
  2809. pack.dwVID = GetVID();
  2810.  
  2811. strlcpy(pack.title2.szName, GetTitle2(), sizeof(pack.title2.szName));
  2812. memcpy(pack.title2.bColours2, m_bTitle2Color, sizeof(pack.title2.bColours2))
  2813. ;
  2814. PacketAround(&pack, sizeof(pack));
  2815. }
  2816. #endif
  2817.  
  2818. void CHARACTER::ResetPlayTime(DWORD dwTimeRemain)
  2819. {
  2820. m_dwPlayStartTime = get_dword_time() - dwTimeRemain;
  2821. }
  2822.  
  2823. const int aiRecoveryPercents[10] = { 1, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
  2824.  
  2825. EVENTFUNC(recovery_event)
  2826. {
  2827. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  2828. if ( info == NULL )
  2829. {
  2830. sys_err( "recovery_event> <Factor> Null pointer" );
  2831. return 0;
  2832. }
  2833.  
  2834. LPCHARACTER ch = info->ch;
  2835.  
  2836. if (ch == NULL)
  2837. {
  2838. return 0;
  2839. }
  2840.  
  2841. if (!ch->IsPC())
  2842. {
  2843. if (ch->IsAffectFlag(AFF_POISON))
  2844. return PASSES_PER_SEC(MAX(1, ch->GetMobTable().bRegenCycle));
  2845.  
  2846. if (2493 == ch->GetMobTable().dwVnum)
  2847. {
  2848. int regenPct = BlueDragon_GetRangeFactor("hp_regen", ch->GetHPPct());
  2849. regenPct += ch->GetMobTable().bRegenPercent;
  2850.  
  2851. for (int i=1 ; i <= 4 ; ++i)
  2852. {
  2853. if (REGEN_PECT_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
  2854. {
  2855. DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
  2856. size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
  2857. size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( ch->GetMapIndex(), dwDragonStoneID );
  2858.  
  2859. regenPct += (val*cnt);
  2860.  
  2861. break;
  2862. }
  2863. }
  2864.  
  2865. ch->PointChange(POINT_HP, MAX(1, (ch->GetMaxHP() * regenPct) / 100));
  2866. }
  2867.  
  2868. else if (!ch->IsDoor())
  2869. {
  2870. ch->MonsterLog("HP_REGEN +%d", MAX(1, (ch->GetMaxHP() * ch->GetMobTable().bRegenPercent) / 100));
  2871. ch->PointChange(POINT_HP, MAX(1, (ch->GetMaxHP() * ch->GetMobTable().bRegenPercent) / 100));
  2872. }
  2873.  
  2874. if (ch->GetHP() >= ch->GetMaxHP())
  2875. {
  2876. ch->m_pkRecoveryEvent = NULL;
  2877. return 0;
  2878. }
  2879.  
  2880. if (2493 == ch->GetMobTable().dwVnum)
  2881. {
  2882. for (int i=1 ; i <= 4 ; ++i)
  2883. {
  2884. if (REGEN_TIME_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
  2885. {
  2886. DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
  2887. size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
  2888. size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( ch->GetMapIndex(), dwDragonStoneID );
  2889.  
  2890. return PASSES_PER_SEC(MAX(1, (ch->GetMobTable().bRegenCycle - (val*cnt))));
  2891. }
  2892. }
  2893. }
  2894.  
  2895. return PASSES_PER_SEC(MAX(1, ch->GetMobTable().bRegenCycle));
  2896. }
  2897.  
  2898. else
  2899. {
  2900. ch->CheckTarget();
  2901. //ch->UpdateSectree();
  2902. ch->UpdateKillerMode();
  2903.  
  2904. if (ch->IsAffectFlag(AFF_POISON) == true)
  2905. {
  2906. return 3;
  2907. }
  2908.  
  2909. int iSec = (get_dword_time() - ch->GetLastMoveTime()) / 3000;
  2910.  
  2911.  
  2912. ch->DistributeSP(ch);
  2913.  
  2914. if (ch->GetMaxHP() <= ch->GetHP())
  2915. return PASSES_PER_SEC(3);
  2916.  
  2917. int iPercent = 0;
  2918. int iAmount = 0;
  2919.  
  2920. {
  2921. iPercent = aiRecoveryPercents[MIN(9, iSec)];
  2922. iAmount = 15 + (ch->GetMaxHP() * iPercent) / 100;
  2923. }
  2924.  
  2925. iAmount += (iAmount * ch->GetPoint(POINT_HP_REGEN)) / 100;
  2926.  
  2927. sys_log(1, "RECOVERY_EVENT: %s %d HP_REGEN %d HP +%d", ch->GetName(), iPercent, ch->GetPoint(POINT_HP_REGEN), iAmount);
  2928.  
  2929. if (!CPVPManager::instance().IsFightingTactic(ch->GetPlayerID()) && !CPVPManager::instance().IsFightingGerman(ch->GetPlayerID()))
  2930. ch->PointChange(POINT_HP, iAmount, false);
  2931.  
  2932. return PASSES_PER_SEC(3);
  2933. }
  2934. }
  2935.  
  2936. void CHARACTER::StartRecoveryEvent()
  2937. {
  2938. if (m_pkRecoveryEvent)
  2939. return;
  2940.  
  2941. if (IsDead() || IsStun())
  2942. return;
  2943.  
  2944. if (IsNPC() && GetHP() >= GetMaxHP())
  2945. return;
  2946.  
  2947. char_event_info* info = AllocEventInfo<char_event_info>();
  2948.  
  2949. info->ch = this;
  2950.  
  2951. int iSec = IsPC() ? 3 : (MAX(1, GetMobTable().bRegenCycle));
  2952. m_pkRecoveryEvent = event_create(recovery_event, info, PASSES_PER_SEC(iSec));
  2953. }
  2954.  
  2955. void CHARACTER::Standup()
  2956. {
  2957. struct packet_position pack_position;
  2958.  
  2959. if (!IsPosition(POS_SITTING))
  2960. return;
  2961.  
  2962. SetPosition(POS_STANDING);
  2963.  
  2964. sys_log(1, "STANDUP: %s", GetName());
  2965.  
  2966. pack_position.header = HEADER_GC_CHARACTER_POSITION;
  2967. pack_position.vid = GetVID();
  2968. pack_position.position = POSITION_GENERAL;
  2969.  
  2970. PacketAround(&pack_position, sizeof(pack_position));
  2971. }
  2972.  
  2973. void CHARACTER::Sitdown(int is_ground)
  2974. {
  2975. struct packet_position pack_position;
  2976.  
  2977. if (IsPosition(POS_SITTING))
  2978. return;
  2979.  
  2980. SetPosition(POS_SITTING);
  2981. sys_log(1, "SITDOWN: %s", GetName());
  2982.  
  2983. pack_position.header = HEADER_GC_CHARACTER_POSITION;
  2984. pack_position.vid = GetVID();
  2985. pack_position.position = POSITION_SITTING_GROUND;
  2986. PacketAround(&pack_position, sizeof(pack_position));
  2987. }
  2988.  
  2989. void CHARACTER::SetRotation(float fRot)
  2990. {
  2991. m_pointsInstant.fRot = fRot;
  2992. }
  2993.  
  2994. void CHARACTER::SetRotationToXY(long x, long y)
  2995. {
  2996. SetRotation(GetDegreeFromPositionXY(GetX(), GetY(), x, y));
  2997. }
  2998.  
  2999. bool CHARACTER::CannotMoveByAffect() const
  3000. {
  3001. return (IsAffectFlag(AFF_STUN));
  3002. }
  3003.  
  3004. bool CHARACTER::CanMove() const
  3005. {
  3006. if (CannotMoveByAffect())
  3007. return false;
  3008.  
  3009. if (GetMyShop())
  3010. return false;
  3011.  
  3012. /*
  3013. if (get_float_time() - m_fSyncTime < 0.2f)
  3014. return false;
  3015. */
  3016.  
  3017. return true;
  3018. }
  3019.  
  3020. bool CHARACTER::Sync(long x, long y)
  3021. {
  3022. if (!GetSectree())
  3023. return false;
  3024.  
  3025. LPSECTREE new_tree = SECTREE_MANAGER::instance().Get(GetMapIndex(), x, y);
  3026.  
  3027. if (!new_tree)
  3028. {
  3029. if (GetDesc())
  3030. {
  3031. sys_err("cannot find tree at %d %d (name: %s)", x, y, GetName());
  3032. GetDesc()->SetPhase(PHASE_CLOSE);
  3033. }
  3034.  
  3035. else
  3036. {
  3037. sys_err("no tree: %s %d %d %d", GetName(), x, y, GetMapIndex());
  3038. Dead();
  3039. }
  3040.  
  3041. return false;
  3042. }
  3043.  
  3044. SetRotationToXY(x, y);
  3045. SetXYZ(x, y, 0);
  3046.  
  3047. if (GetDungeon())
  3048. {
  3049.  
  3050. int iLastEventAttr = m_iEventAttr;
  3051. m_iEventAttr = new_tree->GetEventAttribute(x, y);
  3052.  
  3053. if (m_iEventAttr != iLastEventAttr)
  3054. {
  3055. if (GetParty())
  3056. {
  3057. quest::CQuestManager::instance().AttrOut(GetParty()->GetLeaderPID(), this, iLastEventAttr);
  3058. quest::CQuestManager::instance().AttrIn(GetParty()->GetLeaderPID(), this, m_iEventAttr);
  3059. }
  3060.  
  3061. else
  3062. {
  3063. quest::CQuestManager::instance().AttrOut(GetPlayerID(), this, iLastEventAttr);
  3064. quest::CQuestManager::instance().AttrIn(GetPlayerID(), this, m_iEventAttr);
  3065. }
  3066. }
  3067. }
  3068.  
  3069. if (GetSectree() != new_tree)
  3070. {
  3071. if (!IsNPC())
  3072. {
  3073. SECTREEID id = new_tree->GetID();
  3074. SECTREEID old_id = GetSectree()->GetID();
  3075.  
  3076. sys_log(0, "SECTREE DIFFER: %s %dx%d was %dx%d", GetName(), id.coord.x, id.coord.y, old_id.coord.x, old_id.coord.y);
  3077. }
  3078.  
  3079. new_tree->InsertEntity(this);
  3080. }
  3081.  
  3082. return true;
  3083. }
  3084.  
  3085. void CHARACTER::Stop()
  3086. {
  3087. if (!IsState(m_stateIdle))
  3088. MonsterLog("[IDLE] 정지");
  3089.  
  3090. GotoState(m_stateIdle);
  3091.  
  3092. m_posDest.x = m_posStart.x = GetX();
  3093. m_posDest.y = m_posStart.y = GetY();
  3094. }
  3095.  
  3096. bool CHARACTER::Goto(long x, long y)
  3097. {
  3098. if (GetX() == x && GetY() == y)
  3099. return false;
  3100.  
  3101. if (m_posDest.x == x && m_posDest.y == y)
  3102. {
  3103. if (!IsState(m_stateMove))
  3104. {
  3105. m_dwStateDuration = 4;
  3106. GotoState(m_stateMove);
  3107. }
  3108.  
  3109. return false;
  3110. }
  3111.  
  3112. m_posDest.x = x;
  3113. m_posDest.y = y;
  3114.  
  3115. CalculateMoveDuration();
  3116.  
  3117. m_dwStateDuration = 4;
  3118.  
  3119. if (!IsState(m_stateMove))
  3120. {
  3121. MonsterLog("[MOVE] %s", GetVictim() ? "대상추적" : "그냥이동");
  3122.  
  3123. if (GetVictim())
  3124. {
  3125. //MonsterChat(MONSTER_CHAT_CHASE);
  3126. MonsterChat(MONSTER_CHAT_ATTACK);
  3127. }
  3128. }
  3129.  
  3130. GotoState(m_stateMove);
  3131.  
  3132. return true;
  3133. }
  3134.  
  3135. DWORD CHARACTER::GetMotionMode() const
  3136. {
  3137. DWORD dwMode = MOTION_MODE_GENERAL;
  3138.  
  3139. if (IsPolymorphed())
  3140. return dwMode;
  3141.  
  3142. LPITEM pkItem;
  3143.  
  3144. if ((pkItem = GetWear(WEAR_WEAPON)))
  3145. {
  3146. switch (pkItem->GetProto()->bSubType)
  3147. {
  3148. case WEAPON_SWORD:
  3149. dwMode = MOTION_MODE_ONEHAND_SWORD;
  3150. break;
  3151.  
  3152. case WEAPON_TWO_HANDED:
  3153. dwMode = MOTION_MODE_TWOHAND_SWORD;
  3154. break;
  3155.  
  3156. case WEAPON_DAGGER:
  3157. dwMode = MOTION_MODE_DUALHAND_SWORD;
  3158. break;
  3159.  
  3160. case WEAPON_BOW:
  3161. dwMode = MOTION_MODE_BOW;
  3162. break;
  3163.  
  3164. case WEAPON_BELL:
  3165. dwMode = MOTION_MODE_BELL;
  3166. break;
  3167.  
  3168. case WEAPON_FAN:
  3169. dwMode = MOTION_MODE_FAN;
  3170. break;
  3171. }
  3172. }
  3173. return dwMode;
  3174. }
  3175.  
  3176. float CHARACTER::GetMoveMotionSpeed() const
  3177. {
  3178. DWORD dwMode = GetMotionMode();
  3179.  
  3180. const CMotion * pkMotion = NULL;
  3181.  
  3182. if (!GetMountVnum())
  3183. pkMotion = CMotionManager::instance().GetMotion(GetRaceNum(), MAKE_MOTION_KEY(dwMode, (IsWalking() && IsPC()) ? MOTION_WALK : MOTION_RUN));
  3184.  
  3185. else
  3186. {
  3187. pkMotion = CMotionManager::instance().GetMotion(GetMountVnum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, (IsWalking() && IsPC()) ? MOTION_WALK : MOTION_RUN));
  3188.  
  3189. if (!pkMotion)
  3190. pkMotion = CMotionManager::instance().GetMotion(GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_HORSE, (IsWalking() && IsPC()) ? MOTION_WALK : MOTION_RUN));
  3191. }
  3192.  
  3193. if (pkMotion)
  3194. return -pkMotion->GetAccumVector().y / pkMotion->GetDuration();
  3195.  
  3196. else
  3197. {
  3198. sys_err("cannot find motion (name %s race %d mode %d)", GetName(), GetRaceNum(), dwMode);
  3199.  
  3200. return 300.0f;
  3201. }
  3202. }
  3203.  
  3204. float CHARACTER::GetMoveSpeed() const
  3205. {
  3206. return GetMoveMotionSpeed() * 10000 / CalculateDuration(GetLimitPoint(POINT_MOV_SPEED), 10000);
  3207. }
  3208.  
  3209. void CHARACTER::CalculateMoveDuration()
  3210. {
  3211. m_posStart.x = GetX();
  3212. m_posStart.y = GetY();
  3213.  
  3214. float fDist = DISTANCE_SQRT(m_posStart.x - m_posDest.x, m_posStart.y - m_posDest.y);
  3215.  
  3216. float motionSpeed = GetMoveMotionSpeed();
  3217.  
  3218. m_dwMoveDuration = CalculateDuration(GetLimitPoint(POINT_MOV_SPEED), (int) ((fDist / motionSpeed) * 1000.0f));
  3219.  
  3220. if (IsNPC())
  3221. sys_log(1, "%s: GOTO: distance %f, spd %u, duration %u, motion speed %f pos %d %d -> %d %d", GetName(), fDist, GetLimitPoint(POINT_MOV_SPEED), m_dwMoveDuration, motionSpeed, m_posStart.x, m_posStart.y, m_posDest.x, m_posDest.y);
  3222.  
  3223. m_dwMoveStartTime = get_dword_time();
  3224. }
  3225.  
  3226. bool CHARACTER::Move(long x, long y)
  3227. {
  3228. if (GetX() == x && GetY() == y)
  3229. return true;
  3230.  
  3231. if (test_server)
  3232. if (m_bDetailLog)
  3233. sys_log(0, "%s position %u %u", GetName(), x, y);
  3234.  
  3235. OnMove();
  3236.  
  3237. return Sync(x, y);
  3238. }
  3239.  
  3240. void CHARACTER::SendMovePacket(BYTE bFunc, BYTE bArg, DWORD x, DWORD y, DWORD dwDuration, DWORD dwTime, int iRot)
  3241. {
  3242. TPacketGCMove pack;
  3243.  
  3244. if (bFunc == FUNC_WAIT)
  3245. {
  3246. x = m_posDest.x;
  3247. y = m_posDest.y;
  3248.  
  3249. dwDuration = m_dwMoveDuration;
  3250. }
  3251.  
  3252. EncodeMovePacket(pack, GetVID(), bFunc, bArg, x, y, dwDuration, dwTime, iRot == -1 ? (int) GetRotation() / 5 : iRot);
  3253. PacketView(&pack, sizeof(TPacketGCMove), this);
  3254. }
  3255.  
  3256. int CHARACTER::GetRealPoint(BYTE type) const
  3257. {
  3258. return m_points.points[type];
  3259. }
  3260.  
  3261. void CHARACTER::SetRealPoint(BYTE type, int val)
  3262. {
  3263. m_points.points[type] = val;
  3264. }
  3265.  
  3266. int CHARACTER::GetPolymorphPoint(BYTE type) const
  3267. {
  3268. if (IsPolymorphed() && !IsPolyMaintainStat())
  3269. {
  3270. DWORD dwMobVnum = GetPolymorphVnum();
  3271.  
  3272. const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
  3273. int iPower = GetPolymorphPower();
  3274.  
  3275. if (pMob)
  3276. {
  3277. switch (type)
  3278. {
  3279. case POINT_ST:
  3280. if ((GetJob() == JOB_SHAMAN) || ((GetJob() == JOB_SURA) && (GetSkillGroup() == 2)))
  3281. return pMob->m_table.bStr * iPower / 100 + GetPoint(POINT_IQ);
  3282.  
  3283. return pMob->m_table.bStr * iPower / 100 + GetPoint(POINT_ST);
  3284.  
  3285. case POINT_HT:
  3286. return pMob->m_table.bCon * iPower / 100 + GetPoint(POINT_HT);
  3287.  
  3288. case POINT_IQ:
  3289. return pMob->m_table.bInt * iPower / 100 + GetPoint(POINT_IQ);
  3290.  
  3291. case POINT_DX:
  3292. return pMob->m_table.bDex * iPower / 100 + GetPoint(POINT_DX);
  3293. }
  3294. }
  3295. }
  3296.  
  3297. return GetPoint(type);
  3298. }
  3299.  
  3300. long long CHARACTER::GetPoint(BYTE type) const
  3301. {
  3302. if (type >= POINT_MAX_NUM)
  3303. {
  3304. sys_err("Point type overflow (type %u)", type);
  3305. return 0;
  3306. }
  3307.  
  3308. long long val = m_pointsInstant.points[type];
  3309. long long max_val = LLONG_MAX;
  3310.  
  3311. switch (type)
  3312. {
  3313. case POINT_STEAL_HP:
  3314. case POINT_STEAL_SP:
  3315. max_val = 50;
  3316. break;
  3317.  
  3318. case POINT_GOLD:
  3319. max_val = yang_max;
  3320. break;
  3321. }
  3322.  
  3323. if (val > max_val)
  3324. sys_err("POINT_ERROR: %s type %d val %lld (max: %lld)", GetName(), val, max_val);
  3325.  
  3326. return (val);
  3327. }
  3328.  
  3329. int CHARACTER::GetLimitPoint(BYTE type) const
  3330. {
  3331. if (type >= POINT_MAX_NUM)
  3332. {
  3333. sys_err("Point type overflow (type %u)", type);
  3334. return 0;
  3335. }
  3336.  
  3337. int val = m_pointsInstant.points[type];
  3338. int max_val = INT_MAX;
  3339. int limit = INT_MAX;
  3340. int min_limit = -INT_MAX;
  3341.  
  3342. switch (type)
  3343. {
  3344. case POINT_ATT_SPEED:
  3345. min_limit = 0;
  3346.  
  3347. if (IsPC())
  3348. limit = 170;
  3349. else
  3350. limit = 250;
  3351. break;
  3352.  
  3353. case POINT_MOV_SPEED:
  3354. min_limit = 0;
  3355.  
  3356. if (IsPC())
  3357. limit = 200;
  3358. else
  3359. limit = 250;
  3360. break;
  3361.  
  3362. case POINT_STEAL_HP:
  3363. case POINT_STEAL_SP:
  3364. limit = 50;
  3365. max_val = 50;
  3366. break;
  3367.  
  3368. case POINT_MALL_ATTBONUS:
  3369. case POINT_MALL_DEFBONUS:
  3370. limit = 20;
  3371. max_val = 50;
  3372. break;
  3373. }
  3374.  
  3375. if (val > max_val)
  3376. sys_err("POINT_ERROR: %s type %d val %d (max: %d)", GetName(), val, max_val);
  3377.  
  3378. if (val > limit)
  3379. val = limit;
  3380.  
  3381. if (val < min_limit)
  3382. val = min_limit;
  3383.  
  3384. return (val);
  3385. }
  3386.  
  3387. void CHARACTER::SetPoint(BYTE type, long long val)
  3388. {
  3389. if (type >= POINT_MAX_NUM)
  3390. {
  3391. sys_err("Point type overflow (type %u)", type);
  3392. return;
  3393. }
  3394.  
  3395. m_pointsInstant.points[type] = val;
  3396.  
  3397. if (type == POINT_MOV_SPEED && get_dword_time() < m_dwMoveStartTime + m_dwMoveDuration)
  3398. {
  3399. CalculateMoveDuration();
  3400. }
  3401. }
  3402.  
  3403. long long CHARACTER::GetAllowedGold() const
  3404. {
  3405. if (GetLevel() <= 10)
  3406. return 100000;
  3407.  
  3408. else if (GetLevel() <= 20)
  3409. return 500000;
  3410.  
  3411. else
  3412. return 50000000;
  3413. }
  3414.  
  3415. void CHARACTER::CheckMaximumPoints()
  3416. {
  3417. if (GetMaxHP() < GetHP())
  3418. PointChange(POINT_HP, GetMaxHP() - GetHP());
  3419.  
  3420. if (GetMaxSP() < GetSP())
  3421. PointChange(POINT_SP, GetMaxSP() - GetSP());
  3422. }
  3423.  
  3424. #ifdef SKILL_SELECT_RENEWALL
  3425. void CHARACTER::SelectSkillGroupWithWindow(BYTE group)
  3426. {
  3427. if (!IsPC() || GetSkillGroup() != 0)
  3428. return;
  3429.  
  3430. SetSkillGroup(group);
  3431. SetHorseLevel(SKILL_MAX_LEVEL);
  3432.  
  3433. for (int i = 0; i < SKILL_MAX_NUM; i++)
  3434. {
  3435. if (true == CanUseSkill(i))
  3436. {
  3437. switch(i)
  3438. {
  3439. case SKILL_COMBO:
  3440. SetSkillLevel(i, 2);
  3441. break;
  3442.  
  3443. case SKILL_LEADERSHIP:
  3444. case SKILL_POLYMORPH:
  3445. SetSkillLevel(i, 40);
  3446. break;
  3447.  
  3448. case SKILL_LANGUAGE1:
  3449. case SKILL_LANGUAGE2:
  3450. case SKILL_LANGUAGE3:
  3451. SetSkillLevel(i, 40);
  3452. break;
  3453.  
  3454. case SKILL_HORSE_SUMMON:
  3455. SetSkillLevel(i, 10);
  3456. break;
  3457.  
  3458. case SKILL_HORSE:
  3459. SetSkillLevel(i, HORSE_MAX_LEVEL);
  3460. break;
  3461.  
  3462. case SKILL_HORSE_WILDATTACK:
  3463. case SKILL_HORSE_CHARGE:
  3464. case SKILL_HORSE_ESCAPE:
  3465. case SKILL_HORSE_WILDATTACK_RANGE:
  3466. SetSkillLevel(i, 40);
  3467. break;
  3468.  
  3469. default:
  3470. SetSkillLevel(i, 40);
  3471. break;
  3472. }
  3473. }
  3474.  
  3475. else
  3476. {
  3477. switch(i)
  3478. {
  3479. case SKILL_HORSE_WILDATTACK:
  3480. case SKILL_HORSE_CHARGE:
  3481. case SKILL_HORSE_ESCAPE:
  3482.  
  3483. case SKILL_HORSE_WILDATTACK_RANGE:
  3484. SetSkillLevel(i, 20);
  3485. break;
  3486. }
  3487. }
  3488. }
  3489.  
  3490. SetHorseLevel(HORSE_MAX_LEVEL);
  3491. ComputePoints();
  3492. SkillLevelPacket();
  3493. }
  3494. #endif
  3495.  
  3496. void CHARACTER::PointChange(BYTE type, long long amount, bool bAmount, bool bBroadcast)
  3497. {
  3498. long long val = 0;
  3499.  
  3500. //sys_log(0, "PointChange %d %d | %d -> %d cHP %d mHP %d", type, amount, GetPoint(type), GetPoint(type)+amount, GetHP(), GetMaxHP());
  3501.  
  3502. switch (type)
  3503. {
  3504. case POINT_NONE:
  3505. return;
  3506.  
  3507. case POINT_LEVEL:
  3508. if ((GetLevel() + static_cast<int>(amount)) > gPlayerMaxLevel)
  3509. return;
  3510.  
  3511. SetLevel(GetLevel() + static_cast<int>(amount));
  3512. val = GetLevel();
  3513.  
  3514. sys_log(0, "LEVELUP: %s %d NEXT EXP %d", GetName(), GetLevel(), GetNextExp());
  3515.  
  3516. #ifdef SKILL_SELECT_RENEWALL
  3517. if (GetLevel() >= 5 && GetSkillGroup() == 0)
  3518. ChatPacket(CHAT_TYPE_COMMAND, "open_select_skill_window %d", GetJob());
  3519. #endif
  3520.  
  3521. PointChange(POINT_NEXT_EXP, GetNextExp(), false);
  3522.  
  3523. if (static_cast<int>(amount))
  3524. {
  3525. quest::CQuestManager::instance().LevelUp(GetPlayerID());
  3526.  
  3527. LogManager::instance().LevelLog(this, val, GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000);
  3528.  
  3529. if (GetGuild())
  3530. {
  3531. GetGuild()->LevelChange(GetPlayerID(), GetLevel());
  3532. }
  3533.  
  3534. if (GetParty())
  3535. {
  3536. GetParty()->RequestSetMemberLevel(GetPlayerID(), GetLevel());
  3537. }
  3538. }
  3539. break;
  3540.  
  3541. case POINT_NEXT_EXP:
  3542. val = GetNextExp();
  3543. bAmount = false;
  3544. break;
  3545.  
  3546. case POINT_EXP:
  3547. {
  3548. DWORD exp = GetExp();
  3549. DWORD next_exp = GetNextExp();
  3550.  
  3551. if (static_cast<int>(amount) < 0 && exp < -static_cast<int>(amount))
  3552. {
  3553. sys_log(1, "%s AMOUNT < 0 %d, CUR EXP: %d", GetName(), -static_cast<int>(amount), exp);
  3554. amount = -exp;
  3555.  
  3556. SetExp(exp + static_cast<int>(amount));
  3557. val = GetExp();
  3558. }
  3559.  
  3560. else
  3561. {
  3562. if (gPlayerMaxLevel <= GetLevel())
  3563. return;
  3564.  
  3565. if (test_server)
  3566. ChatPacket(CHAT_TYPE_INFO, "You have gained %d exp.", static_cast<int>(amount));
  3567.  
  3568. DWORD iExpBalance = 0;
  3569.  
  3570. if (exp + static_cast<int>(amount) >= next_exp)
  3571. {
  3572. iExpBalance = (exp + static_cast<int>(amount)) - next_exp;
  3573. amount = next_exp - exp;
  3574.  
  3575. SetExp(0);
  3576. exp = next_exp;
  3577. }
  3578.  
  3579. else
  3580. {
  3581. SetExp(exp + static_cast<int>(amount));
  3582. exp = GetExp();
  3583. }
  3584.  
  3585. DWORD q = DWORD(next_exp / 4.0f);
  3586. int iLevStep = GetRealPoint(POINT_LEVEL_STEP);
  3587.  
  3588. if (iLevStep >= 4)
  3589. {
  3590. sys_err("%s LEVEL_STEP bigger than 4! (%d)", GetName(), iLevStep);
  3591. iLevStep = 4;
  3592. }
  3593.  
  3594. if (exp >= next_exp && iLevStep < 4)
  3595. {
  3596. for (int i = 0; i < 4 - iLevStep; ++i)
  3597. PointChange(POINT_LEVEL_STEP, 1, false, true);
  3598. }
  3599.  
  3600. else if (exp >= q * 3 && iLevStep < 3)
  3601. {
  3602. for (int i = 0; i < 3 - iLevStep; ++i)
  3603. PointChange(POINT_LEVEL_STEP, 1, false, true);
  3604. }
  3605.  
  3606. else if (exp >= q * 2 && iLevStep < 2)
  3607. {
  3608. for (int i = 0; i < 2 - iLevStep; ++i)
  3609. PointChange(POINT_LEVEL_STEP, 1, false, true);
  3610. }
  3611.  
  3612. else if (exp >= q && iLevStep < 1)
  3613. PointChange(POINT_LEVEL_STEP, 1);
  3614.  
  3615. if (iExpBalance)
  3616. {
  3617. PointChange(POINT_EXP, iExpBalance);
  3618. }
  3619.  
  3620. val = GetExp();
  3621. }
  3622. }
  3623. break;
  3624.  
  3625. case POINT_LEVEL_STEP:
  3626. if (static_cast<int>(amount) > 0)
  3627. {
  3628. val = GetPoint(POINT_LEVEL_STEP) + static_cast<int>(amount);
  3629.  
  3630. switch (val)
  3631. {
  3632. case 1:
  3633. case 2:
  3634. case 3:
  3635. if (GetLevel() < 91) PointChange(POINT_STAT, 1);
  3636. break;
  3637.  
  3638. case 4:
  3639. {
  3640. int iHP = number(JobInitialPoints[GetJob()].hp_per_lv_begin, JobInitialPoints[GetJob()].hp_per_lv_end);
  3641. int iSP = number(JobInitialPoints[GetJob()].sp_per_lv_begin, JobInitialPoints[GetJob()].sp_per_lv_end);
  3642.  
  3643. m_points.iRandomHP += iHP;
  3644. m_points.iRandomSP += iSP;
  3645.  
  3646. if (GetSkillGroup())
  3647. {
  3648. if (GetLevel() >= 5)
  3649. PointChange(POINT_SKILL, 1);
  3650.  
  3651. if (GetLevel() >= 9)
  3652. PointChange(POINT_SUB_SKILL, 1);
  3653. }
  3654.  
  3655. PointChange(POINT_MAX_HP, iHP);
  3656. PointChange(POINT_MAX_SP, iSP);
  3657. PointChange(POINT_LEVEL, 1, false, true);
  3658.  
  3659. val = 0;
  3660. }
  3661. break;
  3662. }
  3663.  
  3664. if (GetLevel() <= 10)
  3665. AutoGiveItem(27001, 2);
  3666. else if (GetLevel() <= 30)
  3667. AutoGiveItem(27002, 2);
  3668. else
  3669. {
  3670. AutoGiveItem(27002, 2);
  3671. // AutoGiveItem(27003, 2);
  3672. }
  3673.  
  3674. PointChange(POINT_HP, GetMaxHP() - GetHP());
  3675. PointChange(POINT_SP, GetMaxSP() - GetSP());
  3676. PointChange(POINT_STAMINA, GetMaxStamina() - GetStamina());
  3677.  
  3678. SetPoint(POINT_LEVEL_STEP, val);
  3679. SetRealPoint(POINT_LEVEL_STEP, val);
  3680.  
  3681. Save();
  3682. }
  3683.  
  3684. else
  3685. val = GetPoint(POINT_LEVEL_STEP);
  3686.  
  3687. break;
  3688.  
  3689. case POINT_HP:
  3690. {
  3691. if (IsDead() || IsStun())
  3692. return;
  3693.  
  3694. #ifdef WJ_ENABLE_AUTO_POTION_OPTIMIZATION
  3695. if (FindAffect(AFFECT_AUTO_HP_RECOVERY))
  3696. AutoRecoveryItemProcess(AFFECT_AUTO_HP_RECOVERY);
  3697. #endif
  3698. int prev_hp = GetHP();
  3699.  
  3700. amount = MIN(GetMaxHP() - GetHP(), static_cast<int>(amount));
  3701. SetHP(GetHP() + static_cast<int>(amount));
  3702. val = GetHP();
  3703.  
  3704. #ifdef WJ_ENABLE_AUTO_POTION_OPTIMIZATION
  3705. if (FindAffect(AFFECT_AUTO_SP_RECOVERY))
  3706. AutoRecoveryItemProcess(AFFECT_AUTO_SP_RECOVERY);
  3707. #endif
  3708. BroadcastTargetPacket();
  3709.  
  3710. if (GetParty() && IsPC() && val != prev_hp)
  3711. GetParty()->SendPartyInfoOneToAll(this);
  3712. }
  3713. break;
  3714.  
  3715. case POINT_SP:
  3716. {
  3717. if (IsDead() || IsStun())
  3718. return;
  3719.  
  3720. amount = MIN(GetMaxSP() - GetSP(), static_cast<int>(amount));
  3721. SetSP(GetSP() + static_cast<int>(amount));
  3722. val = GetSP();
  3723. }
  3724. break;
  3725.  
  3726. case POINT_STAMINA:
  3727. {
  3728. if (IsDead() || IsStun())
  3729. return;
  3730.  
  3731. int prev_val = GetStamina();
  3732.  
  3733. amount = MIN(GetMaxStamina() - GetStamina(), static_cast<int>(amount));
  3734. SetStamina(GetStamina() + static_cast<int>(amount));
  3735. val = GetStamina();
  3736.  
  3737. if (val == 0)
  3738. {
  3739. SetNowWalking(true);
  3740. }
  3741.  
  3742. else if (prev_val == 0)
  3743. {
  3744. ResetWalking();
  3745. }
  3746.  
  3747. if (static_cast<int>(amount) < 0 && val != 0)
  3748. return;
  3749. }
  3750. break;
  3751.  
  3752. case POINT_MAX_HP:
  3753. {
  3754. if (CPVPManager::instance().IsFightingGerman(GetPlayerID()))
  3755. {
  3756. SetPoint(type, GetPoint(type) + amount);
  3757. if (GetJob() == JOB_ASSASSIN)
  3758. SetMaxHP(150000);
  3759.  
  3760. else if (GetJob() == JOB_SURA)
  3761. SetMaxHP(150000);
  3762.  
  3763. else if (GetJob() == JOB_SHAMAN)
  3764. SetMaxHP(150000);
  3765.  
  3766. else
  3767. SetMaxHP(170000);
  3768.  
  3769. val = GetMaxHP();
  3770. }
  3771.  
  3772. else if (CPVPManager::instance().IsFightingTactic(GetPlayerID()))
  3773. {
  3774. SetPoint(type, GetPoint(type) + amount);
  3775. SetMaxHP(45000);
  3776. val = GetMaxHP();
  3777. }
  3778.  
  3779. else
  3780. {
  3781. SetPoint(type, GetPoint(type) + amount);
  3782.  
  3783. int hp = GetRealPoint(POINT_MAX_HP);
  3784. int add_hp = MIN(3500, hp * GetPoint(POINT_MAX_HP_PCT) / 100);
  3785.  
  3786. add_hp += GetPoint(POINT_MAX_HP);
  3787. add_hp += GetPoint(POINT_PARTY_TANKER_BONUS);
  3788.  
  3789. SetMaxHP(hp + add_hp);
  3790. val = GetMaxHP();
  3791. }
  3792. }
  3793. break;
  3794.  
  3795. case POINT_MAX_SP:
  3796. {
  3797. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  3798.  
  3799. int sp = GetRealPoint(POINT_MAX_SP);
  3800. int add_sp = MIN(800, sp * GetPoint(POINT_MAX_SP_PCT) / 100);
  3801.  
  3802. add_sp += GetPoint(POINT_MAX_SP);
  3803. add_sp += GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
  3804.  
  3805. SetMaxSP(sp + add_sp);
  3806.  
  3807. val = GetMaxSP();
  3808. }
  3809. break;
  3810.  
  3811. case POINT_MAX_HP_PCT:
  3812. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  3813. val = GetPoint(type);
  3814.  
  3815. PointChange(POINT_MAX_HP, 0);
  3816. break;
  3817.  
  3818. case POINT_MAX_SP_PCT:
  3819. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  3820. val = GetPoint(type);
  3821.  
  3822. PointChange(POINT_MAX_SP, 0);
  3823. break;
  3824.  
  3825. case POINT_MAX_STAMINA:
  3826. SetMaxStamina(GetMaxStamina() + amount);
  3827. val = GetMaxStamina();
  3828. break;
  3829.  
  3830. case POINT_GOLD:
  3831. {
  3832. const long long nTotalMoney = static_cast<long long>(GetGold()) + static_cast<long long>(amount);
  3833. if (yang_max <= nTotalMoney)
  3834. {
  3835. sys_err("[OVERFLOW_GOLD] OriGold %lld AddedGold %lld id %u Name %s ", GetGold(), amount, GetPlayerID(), GetName());
  3836. LogManager::instance().CharLog(this, GetGold() + amount, "OVERFLOW_GOLD", "");
  3837. return;
  3838. }
  3839.  
  3840. SetGold(GetGold() + amount);
  3841. val = GetGold();
  3842. }
  3843. break;
  3844.  
  3845. case POINT_SKILL:
  3846. case POINT_STAT:
  3847. case POINT_SUB_SKILL:
  3848. case POINT_STAT_RESET_COUNT:
  3849. case POINT_HORSE_SKILL:
  3850. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  3851. val = GetPoint(type);
  3852.  
  3853. SetRealPoint(type, val);
  3854. break;
  3855.  
  3856. case POINT_DEF_GRADE:
  3857. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  3858. val = GetPoint(type);
  3859.  
  3860. PointChange(POINT_CLIENT_DEF_GRADE, amount);
  3861. break;
  3862.  
  3863. case POINT_CLIENT_DEF_GRADE:
  3864. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  3865. val = GetPoint(type);
  3866. break;
  3867.  
  3868. case POINT_ST:
  3869. case POINT_HT:
  3870. case POINT_DX:
  3871. case POINT_IQ:
  3872. case POINT_HP_REGEN:
  3873. case POINT_SP_REGEN:
  3874. SetPoint(type, GetPoint(type) + amount);
  3875. val = GetPoint(type);
  3876. break;
  3877.  
  3878. case POINT_ATT_SPEED:
  3879. if (CPVPManager::instance().IsFightingGerman(GetPlayerID()))
  3880. {
  3881. SetPoint(type, 170);
  3882. val = GetPoint(type);
  3883. }
  3884.  
  3885. else if (CPVPManager::instance().IsFightingTactic(GetPlayerID()))
  3886. {
  3887. SetPoint(type, 170);
  3888. val = GetPoint(type);
  3889. }
  3890.  
  3891. else
  3892. {
  3893. SetPoint(type, GetPoint(type) + amount);
  3894. val = GetPoint(type);
  3895. }
  3896. break;
  3897.  
  3898. case POINT_ATT_GRADE:
  3899. SetPoint(type, GetPoint(type) + amount);
  3900. val = GetPoint(type);
  3901. break;
  3902.  
  3903. case POINT_MOV_SPEED:
  3904. if (CPVPManager::instance().IsFightingGerman(GetPlayerID()))
  3905. {
  3906. SetPoint(type, 200);
  3907. val = GetPoint(type);
  3908. }
  3909.  
  3910. else if (CPVPManager::instance().IsFightingTactic(GetPlayerID()))
  3911. {
  3912. SetPoint(type, 200);
  3913. val = GetPoint(type);
  3914. }
  3915.  
  3916. else
  3917. {
  3918. SetPoint(type, GetPoint(type) + amount);
  3919. val = GetPoint(type);
  3920. }
  3921. break;
  3922.  
  3923. case POINT_CASTING_SPEED:
  3924. if (CPVPManager::instance().IsFightingGerman(GetPlayerID()))
  3925. {
  3926. SetPoint(type, 160);
  3927. val = GetPoint(type);
  3928. }
  3929.  
  3930. else if (CPVPManager::instance().IsFightingTactic(GetPlayerID()))
  3931. {
  3932. SetPoint(type, 160);
  3933. val = GetPoint(type);
  3934. }
  3935.  
  3936. else
  3937. {
  3938. SetPoint(type, GetPoint(type) + amount);
  3939. val = GetPoint(type);
  3940. }
  3941. break;
  3942.  
  3943. case POINT_MAGIC_ATT_GRADE:
  3944. case POINT_MAGIC_DEF_GRADE:
  3945. case POINT_BOW_DISTANCE:
  3946. case POINT_HP_RECOVERY:
  3947. case POINT_SP_RECOVERY:
  3948.  
  3949. case POINT_ATTBONUS_HUMAN:
  3950. case POINT_ATTBONUS_ANIMAL:
  3951. case POINT_ATTBONUS_ORC:
  3952. case POINT_ATTBONUS_MILGYO:
  3953. case POINT_ATTBONUS_UNDEAD:
  3954. case POINT_ATTBONUS_DEVIL:
  3955.  
  3956. case POINT_ATTBONUS_MONSTER:
  3957. case POINT_ATTBONUS_SURA:
  3958. case POINT_ATTBONUS_ASSASSIN:
  3959. case POINT_ATTBONUS_WARRIOR:
  3960. case POINT_ATTBONUS_SHAMAN:
  3961.  
  3962. case POINT_POISON_PCT:
  3963. case POINT_STUN_PCT:
  3964. case POINT_SLOW_PCT:
  3965.  
  3966. case POINT_BLOCK:
  3967. case POINT_DODGE:
  3968.  
  3969. case POINT_CRITICAL_PCT:
  3970. case POINT_RESIST_CRITICAL:
  3971. case POINT_PENETRATE_PCT:
  3972. case POINT_RESIST_PENETRATE:
  3973. case POINT_CURSE_PCT:
  3974.  
  3975. case POINT_STEAL_HP:
  3976. case POINT_STEAL_SP:
  3977.  
  3978. case POINT_MANA_BURN_PCT:
  3979. case POINT_DAMAGE_SP_RECOVER:
  3980. case POINT_RESIST_NORMAL_DAMAGE:
  3981. case POINT_RESIST_SWORD:
  3982. case POINT_RESIST_TWOHAND:
  3983. case POINT_RESIST_DAGGER:
  3984. case POINT_RESIST_BELL:
  3985. case POINT_RESIST_FAN:
  3986. case POINT_RESIST_BOW:
  3987. case POINT_RESIST_FIRE:
  3988. case POINT_RESIST_ELEC:
  3989. case POINT_RESIST_MAGIC:
  3990. case POINT_RESIST_WIND:
  3991. case POINT_RESIST_ICE:
  3992. case POINT_RESIST_EARTH:
  3993. case POINT_RESIST_DARK:
  3994. case POINT_REFLECT_MELEE:
  3995. case POINT_REFLECT_CURSE:
  3996. case POINT_POISON_REDUCE:
  3997. case POINT_KILL_SP_RECOVER:
  3998. case POINT_KILL_HP_RECOVERY:
  3999. case POINT_HIT_HP_RECOVERY:
  4000. case POINT_HIT_SP_RECOVERY:
  4001. case POINT_MANASHIELD:
  4002. case POINT_ATT_BONUS:
  4003. case POINT_DEF_BONUS:
  4004. case POINT_SKILL_DAMAGE_BONUS:
  4005. case POINT_NORMAL_HIT_DAMAGE_BONUS:
  4006.  
  4007. case POINT_SKILL_DEFEND_BONUS:
  4008. case POINT_NORMAL_HIT_DEFEND_BONUS:
  4009. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4010. val = GetPoint(type);
  4011. break;
  4012.  
  4013. case POINT_PARTY_ATTACKER_BONUS:
  4014. case POINT_PARTY_TANKER_BONUS:
  4015. case POINT_PARTY_BUFFER_BONUS:
  4016. case POINT_PARTY_SKILL_MASTER_BONUS:
  4017. case POINT_PARTY_HASTE_BONUS:
  4018. case POINT_PARTY_DEFENDER_BONUS:
  4019.  
  4020. case POINT_RESIST_WARRIOR :
  4021. case POINT_RESIST_ASSASSIN :
  4022. case POINT_RESIST_SURA :
  4023. case POINT_RESIST_SHAMAN :
  4024. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4025. val = GetPoint(type);
  4026. break;
  4027.  
  4028. case POINT_MALL_ATTBONUS:
  4029. case POINT_MALL_DEFBONUS:
  4030. case POINT_MALL_EXPBONUS:
  4031. case POINT_MALL_ITEMBONUS:
  4032. case POINT_MALL_GOLDBONUS:
  4033. case POINT_MELEE_MAGIC_ATT_BONUS_PER:
  4034. if (GetPoint(type) + static_cast<int>(amount) > 100)
  4035. {
  4036. sys_err("MALL_BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), static_cast<int>(amount));
  4037. amount = 100 - GetPoint(type);
  4038. }
  4039. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4040. val = GetPoint(type);
  4041. break;
  4042.  
  4043. case POINT_EXP_DOUBLE_BONUS:
  4044. case POINT_GOLD_DOUBLE_BONUS:
  4045. case POINT_ITEM_DROP_BONUS:
  4046. case POINT_POTION_BONUS:
  4047. if (GetPoint(type) + static_cast<int>(amount) > 100)
  4048. {
  4049. sys_err("BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), static_cast<int>(amount));
  4050. amount = 100 - GetPoint(type);
  4051. }
  4052.  
  4053. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4054. val = GetPoint(type);
  4055.  
  4056. break;
  4057.  
  4058. case POINT_IMMUNE_STUN:
  4059. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4060. val = GetPoint(type);
  4061. if (val)
  4062. {
  4063. SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN);
  4064. }
  4065.  
  4066. else
  4067. {
  4068. REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN);
  4069. }
  4070. break;
  4071.  
  4072. case POINT_IMMUNE_SLOW:
  4073. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4074. val = GetPoint(type);
  4075. if (val)
  4076. {
  4077. SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW);
  4078. }
  4079.  
  4080. else
  4081. {
  4082. REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW);
  4083. }
  4084. break;
  4085.  
  4086. case POINT_IMMUNE_FALL:
  4087. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4088. val = GetPoint(type);
  4089. if (val)
  4090. {
  4091. SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL);
  4092. }
  4093.  
  4094. else
  4095. {
  4096. REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL);
  4097. }
  4098. break;
  4099.  
  4100. case POINT_ATT_GRADE_BONUS:
  4101. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4102. PointChange(POINT_ATT_GRADE, static_cast<int>(amount));
  4103. val = GetPoint(type);
  4104. break;
  4105.  
  4106. case POINT_DEF_GRADE_BONUS:
  4107. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4108. PointChange(POINT_DEF_GRADE, static_cast<int>(amount));
  4109. val = GetPoint(type);
  4110. break;
  4111.  
  4112. case POINT_MAGIC_ATT_GRADE_BONUS:
  4113. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4114. PointChange(POINT_MAGIC_ATT_GRADE, static_cast<int>(amount));
  4115. val = GetPoint(type);
  4116. break;
  4117.  
  4118. case POINT_MAGIC_DEF_GRADE_BONUS:
  4119. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4120. PointChange(POINT_MAGIC_DEF_GRADE, static_cast<int>(amount));
  4121. val = GetPoint(type);
  4122. break;
  4123.  
  4124. case POINT_VOICE:
  4125. case POINT_EMPIRE_POINT:
  4126. //sys_err("CHARACTER::PointChange: %s: point cannot be changed. use SetPoint instead (type: %d)", GetName(), type);
  4127. val = GetRealPoint(type);
  4128. break;
  4129.  
  4130. case POINT_POLYMORPH:
  4131. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4132. val = GetPoint(type);
  4133. SetPolymorph(val);
  4134. break;
  4135.  
  4136. case POINT_MOUNT:
  4137. SetPoint(type, GetPoint(type) + static_cast<int>(amount));
  4138. val = GetPoint(type);
  4139. MountVnum(val);
  4140. break;
  4141.  
  4142. case POINT_ENERGY:
  4143. case POINT_COSTUME_ATTR_BONUS:
  4144. {
  4145. int old_val = GetPoint(type);
  4146. SetPoint(type, old_val + static_cast<int>(amount));
  4147. val = GetPoint(type);
  4148. BuffOnAttr_ValueChange(type, old_val, val);
  4149. }
  4150. break;
  4151.  
  4152. default:
  4153. sys_err("CHARACTER::PointChange: %s: unknown point change type %d", GetName(), type);
  4154. return;
  4155. }
  4156.  
  4157. switch (type)
  4158. {
  4159. case POINT_LEVEL:
  4160. case POINT_ST:
  4161. case POINT_DX:
  4162. case POINT_IQ:
  4163. case POINT_HT:
  4164. ComputeBattlePoints();
  4165. break;
  4166.  
  4167. case POINT_MAX_HP:
  4168. case POINT_MAX_SP:
  4169. case POINT_MAX_STAMINA:
  4170. break;
  4171. }
  4172.  
  4173. if (type == POINT_HP && static_cast<int>(amount) == 0)
  4174. return;
  4175.  
  4176. if (GetDesc())
  4177. {
  4178. struct packet_point_change pack;
  4179.  
  4180. pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
  4181. pack.dwVID = m_vid;
  4182. pack.type = type;
  4183. pack.value = val;
  4184.  
  4185. if (bAmount)
  4186. pack.amount = amount;
  4187. else
  4188. pack.amount = 0;
  4189.  
  4190. if (!bBroadcast)
  4191. GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
  4192. else
  4193. PacketAround(&pack, sizeof(pack));
  4194. }
  4195. }
  4196.  
  4197. void CHARACTER::ApplyPoint(BYTE bApplyType, int iVal)
  4198. {
  4199. switch (bApplyType)
  4200. {
  4201. case APPLY_NONE:
  4202. break;
  4203.  
  4204. case APPLY_CON:
  4205. PointChange(POINT_HT, iVal);
  4206. PointChange(POINT_MAX_HP, (iVal * JobInitialPoints[GetJob()].hp_per_ht));
  4207. PointChange(POINT_MAX_STAMINA, (iVal * JobInitialPoints[GetJob()].stamina_per_con));
  4208. break;
  4209.  
  4210. case APPLY_INT:
  4211. PointChange(POINT_IQ, iVal);
  4212. PointChange(POINT_MAX_SP, (iVal * JobInitialPoints[GetJob()].sp_per_iq));
  4213. break;
  4214.  
  4215. case APPLY_SKILL:
  4216. {
  4217. BYTE bSkillVnum = (BYTE) (((DWORD)iVal) >> 24);
  4218. int iAdd = iVal & 0x00800000;
  4219. int iChange = iVal & 0x007fffff;
  4220.  
  4221. sys_log(1, "APPLY_SKILL skill %d add? %d change %d", bSkillVnum, iAdd ? 1 : 0, iChange);
  4222.  
  4223. if (0 == iAdd)
  4224. iChange = -iChange;
  4225.  
  4226. boost::unordered_map<BYTE, int>::iterator iter = m_SkillDamageBonus.find(bSkillVnum);
  4227.  
  4228. if (iter == m_SkillDamageBonus.end())
  4229. m_SkillDamageBonus.insert(std::make_pair(bSkillVnum, iChange));
  4230. else
  4231. iter->second += iChange;
  4232. }
  4233. break;
  4234.  
  4235. case APPLY_MAX_HP:
  4236. case APPLY_MAX_HP_PCT:
  4237. {
  4238. int i = GetMaxHP(); if(i == 0) break;
  4239.  
  4240. PointChange(aApplyInfo[bApplyType].bPointType, iVal);
  4241.  
  4242. float fRatio = (float)GetMaxHP() / (float)i;
  4243.  
  4244. PointChange(POINT_HP, GetHP() * fRatio - GetHP());
  4245. }
  4246. break;
  4247.  
  4248. case APPLY_MAX_SP:
  4249. case APPLY_MAX_SP_PCT:
  4250. {
  4251. int i = GetMaxSP(); if(i == 0) break;
  4252.  
  4253. PointChange(aApplyInfo[bApplyType].bPointType, iVal);
  4254.  
  4255. float fRatio = (float)GetMaxSP() / (float)i;
  4256.  
  4257. PointChange(POINT_SP, GetSP() * fRatio - GetSP());
  4258. }
  4259. break;
  4260.  
  4261. case APPLY_STR:
  4262. case APPLY_DEX:
  4263. case APPLY_ATT_SPEED:
  4264. case APPLY_MOV_SPEED:
  4265. case APPLY_CAST_SPEED:
  4266. case APPLY_HP_REGEN:
  4267. case APPLY_SP_REGEN:
  4268. case APPLY_POISON_PCT:
  4269. case APPLY_STUN_PCT:
  4270. case APPLY_SLOW_PCT:
  4271. case APPLY_CRITICAL_PCT:
  4272. case APPLY_PENETRATE_PCT:
  4273. case APPLY_ATTBONUS_HUMAN:
  4274. case APPLY_ATTBONUS_ANIMAL:
  4275. case APPLY_ATTBONUS_ORC:
  4276. case APPLY_ATTBONUS_MILGYO:
  4277. case APPLY_ATTBONUS_UNDEAD:
  4278. case APPLY_ATTBONUS_DEVIL:
  4279. case APPLY_ATTBONUS_WARRIOR:
  4280. case APPLY_ATTBONUS_ASSASSIN:
  4281. case APPLY_ATTBONUS_SURA:
  4282. case APPLY_ATTBONUS_SHAMAN:
  4283. case APPLY_ATTBONUS_MONSTER:
  4284. case APPLY_STEAL_HP:
  4285. case APPLY_STEAL_SP:
  4286. case APPLY_MANA_BURN_PCT:
  4287. case APPLY_DAMAGE_SP_RECOVER:
  4288. case APPLY_BLOCK:
  4289. case APPLY_DODGE:
  4290. case APPLY_RESIST_SWORD:
  4291. case APPLY_RESIST_TWOHAND:
  4292. case APPLY_RESIST_DAGGER:
  4293. case APPLY_RESIST_BELL:
  4294. case APPLY_RESIST_FAN:
  4295. case APPLY_RESIST_BOW:
  4296. case APPLY_RESIST_FIRE:
  4297. case APPLY_RESIST_ELEC:
  4298. case APPLY_RESIST_MAGIC:
  4299. case APPLY_RESIST_WIND:
  4300. case APPLY_RESIST_ICE:
  4301. case APPLY_RESIST_EARTH:
  4302. case APPLY_RESIST_DARK:
  4303. case APPLY_REFLECT_MELEE:
  4304. case APPLY_REFLECT_CURSE:
  4305. case APPLY_ANTI_CRITICAL_PCT:
  4306. case APPLY_ANTI_PENETRATE_PCT:
  4307. case APPLY_POISON_REDUCE:
  4308. case APPLY_KILL_SP_RECOVER:
  4309. case APPLY_EXP_DOUBLE_BONUS:
  4310. case APPLY_GOLD_DOUBLE_BONUS:
  4311. case APPLY_ITEM_DROP_BONUS:
  4312. case APPLY_POTION_BONUS:
  4313. case APPLY_KILL_HP_RECOVER:
  4314. case APPLY_IMMUNE_STUN:
  4315. case APPLY_IMMUNE_SLOW:
  4316. case APPLY_IMMUNE_FALL:
  4317. case APPLY_BOW_DISTANCE:
  4318. case APPLY_ATT_GRADE_BONUS:
  4319. case APPLY_DEF_GRADE_BONUS:
  4320. case APPLY_MAGIC_ATT_GRADE:
  4321. case APPLY_MAGIC_DEF_GRADE:
  4322. case APPLY_CURSE_PCT:
  4323. case APPLY_MAX_STAMINA:
  4324. case APPLY_MALL_ATTBONUS:
  4325. case APPLY_MALL_DEFBONUS:
  4326. case APPLY_MALL_EXPBONUS:
  4327. case APPLY_MALL_ITEMBONUS:
  4328. case APPLY_MALL_GOLDBONUS:
  4329. case APPLY_SKILL_DAMAGE_BONUS:
  4330. case APPLY_NORMAL_HIT_DAMAGE_BONUS:
  4331.  
  4332. case APPLY_SKILL_DEFEND_BONUS:
  4333. case APPLY_NORMAL_HIT_DEFEND_BONUS:
  4334.  
  4335. case APPLY_RESIST_WARRIOR :
  4336. case APPLY_RESIST_ASSASSIN :
  4337. case APPLY_RESIST_SURA :
  4338. case APPLY_RESIST_SHAMAN :
  4339. case APPLY_ENERGY:
  4340. case APPLY_DEF_GRADE:
  4341. case APPLY_COSTUME_ATTR_BONUS:
  4342. case APPLY_MAGIC_ATTBONUS_PER:
  4343. case APPLY_MELEE_MAGIC_ATTBONUS_PER:
  4344. PointChange(aApplyInfo[bApplyType].bPointType, iVal);
  4345. break;
  4346.  
  4347. default:
  4348. sys_err("Unknown apply type %d name %s", bApplyType, GetName());
  4349. break;
  4350. }
  4351. }
  4352.  
  4353. void CHARACTER::MotionPacketEncode(BYTE motion, LPCHARACTER victim, struct packet_motion * packet)
  4354. {
  4355. packet->header = HEADER_GC_MOTION;
  4356. packet->vid = m_vid;
  4357. packet->motion = motion;
  4358.  
  4359. if (victim)
  4360. packet->victim_vid = victim->GetVID();
  4361. else
  4362. packet->victim_vid = 0;
  4363. }
  4364.  
  4365. void CHARACTER::Motion(BYTE motion, LPCHARACTER victim)
  4366. {
  4367. struct packet_motion pack_motion;
  4368. MotionPacketEncode(motion, victim, &pack_motion);
  4369. PacketAround(&pack_motion, sizeof(struct packet_motion));
  4370. }
  4371.  
  4372. EVENTFUNC(save_event)
  4373. {
  4374. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  4375. if ( info == NULL )
  4376. {
  4377. sys_err( "save_event> <Factor> Null pointer" );
  4378. return 0;
  4379. }
  4380.  
  4381. LPCHARACTER ch = info->ch;
  4382.  
  4383. if (ch == NULL)
  4384. {
  4385. return 0;
  4386. }
  4387.  
  4388. sys_log(1, "SAVE_EVENT: %s", ch->GetName());
  4389.  
  4390. ch->Save();
  4391. ch->FlushDelayedSaveItem();
  4392.  
  4393. return (save_event_second_cycle);
  4394. }
  4395.  
  4396. void CHARACTER::StartSaveEvent()
  4397. {
  4398. if (m_pkSaveEvent)
  4399. return;
  4400.  
  4401. char_event_info* info = AllocEventInfo<char_event_info>();
  4402.  
  4403. info->ch = this;
  4404. m_pkSaveEvent = event_create(save_event, info, save_event_second_cycle);
  4405. }
  4406.  
  4407. void CHARACTER::MonsterLog(const char* format, ...)
  4408. {
  4409. if (!test_server)
  4410. return;
  4411.  
  4412. if (IsPC())
  4413. return;
  4414.  
  4415. char chatbuf[CHAT_MAX_LEN + 1];
  4416. int len = snprintf(chatbuf, sizeof(chatbuf), "%u)", (DWORD)GetVID());
  4417.  
  4418. if (len < 0 || len >= (int) sizeof(chatbuf))
  4419. len = sizeof(chatbuf) - 1;
  4420.  
  4421. va_list args;
  4422.  
  4423. va_start(args, format);
  4424.  
  4425. int len2 = vsnprintf(chatbuf + len, sizeof(chatbuf) - len, format, args);
  4426.  
  4427. if (len2 < 0 || len2 >= (int) sizeof(chatbuf) - len)
  4428. len += (sizeof(chatbuf) - len) - 1;
  4429. else
  4430. len += len2;
  4431.  
  4432. ++len;
  4433.  
  4434. va_end(args);
  4435.  
  4436. TPacketGCChat pack_chat;
  4437.  
  4438. pack_chat.header = HEADER_GC_CHAT;
  4439. pack_chat.size = sizeof(TPacketGCChat) + len;
  4440. pack_chat.type = CHAT_TYPE_TALKING;
  4441. pack_chat.id = (DWORD)GetVID();
  4442. pack_chat.bEmpire = 0;
  4443.  
  4444. TEMP_BUFFER buf;
  4445. buf.write(&pack_chat, sizeof(TPacketGCChat));
  4446. buf.write(chatbuf, len);
  4447.  
  4448. CHARACTER_MANAGER::instance().PacketMonsterLog(this, buf.read_peek(), buf.size());
  4449. }
  4450.  
  4451. void CHARACTER::ChatPacket(BYTE type, const char * format, ...)
  4452. {
  4453. LPDESC d = GetDesc();
  4454.  
  4455. if (!d || !format)
  4456. return;
  4457.  
  4458. char chatbuf[CHAT_MAX_LEN + 1];
  4459. va_list args;
  4460.  
  4461. va_start(args, format);
  4462. int len = vsnprintf(chatbuf, sizeof(chatbuf), format, args);
  4463. va_end(args);
  4464.  
  4465. struct packet_chat pack_chat;
  4466.  
  4467. pack_chat.header = HEADER_GC_CHAT;
  4468. pack_chat.size = sizeof(struct packet_chat) + len;
  4469. pack_chat.type = type;
  4470. pack_chat.id = 0;
  4471. pack_chat.bEmpire = d->GetEmpire();
  4472.  
  4473. TEMP_BUFFER buf;
  4474. buf.write(&pack_chat, sizeof(struct packet_chat));
  4475. buf.write(chatbuf, len);
  4476.  
  4477. d->Packet(buf.read_peek(), buf.size());
  4478.  
  4479. if (type == CHAT_TYPE_COMMAND && test_server)
  4480. sys_log(0, "SEND_COMMAND %s %s", GetName(), chatbuf);
  4481. }
  4482.  
  4483. void CHARACTER::mining_take()
  4484. {
  4485. m_pkMiningEvent = NULL;
  4486. }
  4487.  
  4488. void CHARACTER::mining_cancel()
  4489. {
  4490. if (m_pkMiningEvent)
  4491. {
  4492. sys_log(0, "XXX MINING CANCEL");
  4493. event_cancel(&m_pkMiningEvent);
  4494. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("채광을 중단하였습니다."));
  4495. }
  4496. }
  4497.  
  4498. void CHARACTER::mining(LPCHARACTER chLoad)
  4499. {
  4500. if (m_pkMiningEvent)
  4501. {
  4502. mining_cancel();
  4503. return;
  4504. }
  4505.  
  4506. if (!chLoad)
  4507. return;
  4508.  
  4509. if (GetMapIndex() != chLoad->GetMapIndex() || DISTANCE_APPROX(GetX() - chLoad->GetX(), GetY() - chLoad->GetY()) > 1000)
  4510. return;
  4511.  
  4512. if (mining::GetRawOreFromLoad(chLoad->GetRaceNum()) == 0)
  4513. return;
  4514.  
  4515. LPITEM pick = GetWear(WEAR_WEAPON);
  4516.  
  4517. if (!pick || pick->GetType() != ITEM_PICK)
  4518. {
  4519. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("곡괭이를 장착하세요."));
  4520. return;
  4521. }
  4522.  
  4523. int count = number(5, 15);
  4524.  
  4525. TPacketGCDigMotion p;
  4526.  
  4527. p.header = HEADER_GC_DIG_MOTION;
  4528. p.vid = GetVID();
  4529. p.target_vid = chLoad->GetVID();
  4530. p.count = count;
  4531.  
  4532. PacketAround(&p, sizeof(p));
  4533.  
  4534. m_pkMiningEvent = mining::CreateMiningEvent(this, chLoad, count);
  4535. }
  4536.  
  4537. void CHARACTER::fishing()
  4538. {
  4539. if (m_pkFishingEvent)
  4540. {
  4541. fishing_take();
  4542. return;
  4543. }
  4544.  
  4545. {
  4546. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(GetMapIndex());
  4547.  
  4548. int x = GetX();
  4549. int y = GetY();
  4550.  
  4551. LPSECTREE tree = pkSectreeMap->Find(x, y);
  4552. DWORD dwAttr = tree->GetAttribute(x, y);
  4553.  
  4554. if (IS_SET(dwAttr, ATTR_BLOCK))
  4555. {
  4556. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("낚시를 할 수 있는 곳이 아닙니다"));
  4557. return;
  4558. }
  4559. }
  4560.  
  4561. LPITEM rod = GetWear(WEAR_WEAPON);
  4562.  
  4563. if (!rod || rod->GetType() != ITEM_ROD)
  4564. {
  4565. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("낚시대를 장착 하세요."));
  4566. return;
  4567. }
  4568.  
  4569. if (0 == rod->GetSocket(2))
  4570. {
  4571. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("미끼를 끼고 던져 주세요."));
  4572. return;
  4573. }
  4574.  
  4575. float fx, fy;
  4576. GetDeltaByDegree(GetRotation(), 400.0f, &fx, &fy);
  4577.  
  4578. m_pkFishingEvent = fishing::CreateFishingEvent(this);
  4579. }
  4580.  
  4581. void CHARACTER::fishing_take()
  4582. {
  4583. LPITEM rod = GetWear(WEAR_WEAPON);
  4584. if (rod && rod->GetType() == ITEM_ROD)
  4585. {
  4586. using fishing::fishing_event_info;
  4587. if (m_pkFishingEvent)
  4588. {
  4589. struct fishing_event_info* info = dynamic_cast<struct fishing_event_info*>(m_pkFishingEvent->info);
  4590.  
  4591. if (info)
  4592. fishing::Take(info, this);
  4593. }
  4594. }
  4595.  
  4596. else
  4597. {
  4598. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("낚시대가 아닌 물건으로 낚시를 할 수 없습니다!"));
  4599. }
  4600.  
  4601. event_cancel(&m_pkFishingEvent);
  4602. }
  4603.  
  4604. bool CHARACTER::StartStateMachine(int iNextPulse)
  4605. {
  4606. if (CHARACTER_MANAGER::instance().AddToStateList(this))
  4607. {
  4608. m_dwNextStatePulse = thecore_heart->pulse + iNextPulse;
  4609. return true;
  4610. }
  4611.  
  4612. return false;
  4613. }
  4614.  
  4615. void CHARACTER::StopStateMachine()
  4616. {
  4617. CHARACTER_MANAGER::instance().RemoveFromStateList(this);
  4618. }
  4619.  
  4620. void CHARACTER::UpdateStateMachine(DWORD dwPulse)
  4621. {
  4622. if (dwPulse < m_dwNextStatePulse)
  4623. return;
  4624.  
  4625. if (IsDead())
  4626. return;
  4627.  
  4628. Update();
  4629. m_dwNextStatePulse = dwPulse + m_dwStateDuration;
  4630. }
  4631.  
  4632. void CHARACTER::SetNextStatePulse(int iNextPulse)
  4633. {
  4634. CHARACTER_MANAGER::instance().AddToStateList(this);
  4635. m_dwNextStatePulse = iNextPulse;
  4636.  
  4637. if (iNextPulse < 10)
  4638. MonsterLog("다음상태로어서가자");
  4639. }
  4640.  
  4641. void CHARACTER::UpdateCharacter(DWORD dwPulse)
  4642. {
  4643. CFSM::Update();
  4644. }
  4645.  
  4646. void CHARACTER::SetShop(LPSHOP pkShop)
  4647. {
  4648. if ((m_pkShop = pkShop))
  4649. SET_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_SHOP);
  4650. else
  4651. {
  4652. REMOVE_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_SHOP);
  4653. SetShopOwner(NULL);
  4654. }
  4655. }
  4656.  
  4657. void CHARACTER::SetExchange(CExchange * pkExchange)
  4658. {
  4659. m_pkExchange = pkExchange;
  4660. }
  4661.  
  4662. void CHARACTER::SetPart(BYTE bPartPos, WORD wVal)
  4663. {
  4664. assert(bPartPos < PART_MAX_NUM);
  4665. m_pointsInstant.parts[bPartPos] = wVal;
  4666. }
  4667.  
  4668. WORD CHARACTER::GetPart(BYTE bPartPos) const
  4669. {
  4670. assert(bPartPos < PART_MAX_NUM);
  4671. return m_pointsInstant.parts[bPartPos];
  4672. }
  4673.  
  4674. WORD CHARACTER::GetOriginalPart(BYTE bPartPos) const
  4675. {
  4676. switch (bPartPos)
  4677. {
  4678. case PART_MAIN:
  4679. if (!IsPC())
  4680. return GetPart(PART_MAIN);
  4681. else
  4682. return m_pointsInstant.bBasePart;
  4683.  
  4684. case PART_HAIR:
  4685. return GetPart(PART_HAIR);
  4686.  
  4687. #ifdef __WEAPON_COSTUME_SYSTEM__
  4688. case PART_WEAPON:
  4689. return GetPart(PART_WEAPON);
  4690. #endif
  4691.  
  4692. #ifdef __EFFECT_SYSTEM__
  4693. case BODY_EFFECT:
  4694. return GetPart(BODY_EFFECT);
  4695.  
  4696. case WEAPON_RIGHT_EFFECT:
  4697. return GetPart(WEAPON_RIGHT_EFFECT);
  4698.  
  4699. case WEAPON_LEFT_EFFECT:
  4700. return GetPart(WEAPON_LEFT_EFFECT);
  4701. #endif
  4702. default:
  4703. return 0;
  4704. }
  4705. }
  4706.  
  4707. BYTE CHARACTER::GetCharType() const
  4708. {
  4709. return m_bCharType;
  4710. }
  4711.  
  4712. bool CHARACTER::SetSyncOwner(LPCHARACTER ch, bool bRemoveFromList)
  4713. {
  4714. if (IS_SET(m_pointsInstant.dwAIFlag, AIFLAG_NOMOVE))
  4715. return false;
  4716.  
  4717. if (ch)
  4718. {
  4719. if (!battle_is_attackable(ch, this))
  4720. {
  4721. SendDamagePacket(ch, 0, DAMAGE_BLOCK);
  4722. return false;
  4723. }
  4724. }
  4725.  
  4726. if (ch == this)
  4727. {
  4728. sys_err("SetSyncOwner owner == this (%p)", this);
  4729. return false;
  4730. }
  4731.  
  4732. if (!ch)
  4733. {
  4734. if (bRemoveFromList && m_pkChrSyncOwner)
  4735. {
  4736. m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.remove(this);
  4737. }
  4738.  
  4739. if (m_pkChrSyncOwner)
  4740. sys_log(1, "SyncRelease %s %p from %s", GetName(), this, m_pkChrSyncOwner->GetName());
  4741.  
  4742. m_pkChrSyncOwner = NULL;
  4743. }
  4744.  
  4745. else
  4746. {
  4747. if (!IsSyncOwner(ch))
  4748. return false;
  4749.  
  4750. if (DISTANCE_APPROX(GetX() - ch->GetX(), GetY() - ch->GetY()) > 250)
  4751. {
  4752. sys_log(1, "SetSyncOwner distance over than 250 %s %s", GetName(), ch->GetName());
  4753.  
  4754. if (m_pkChrSyncOwner == ch)
  4755. return true;
  4756.  
  4757. return false;
  4758. }
  4759.  
  4760. if (m_pkChrSyncOwner != ch)
  4761. {
  4762. if (m_pkChrSyncOwner)
  4763. {
  4764. sys_log(1, "SyncRelease %s %p from %s", GetName(), this, m_pkChrSyncOwner->GetName());
  4765. m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.remove(this);
  4766. }
  4767.  
  4768. m_pkChrSyncOwner = ch;
  4769. m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.push_back(this);
  4770.  
  4771. static const timeval zero_tv = {0, 0};
  4772. SetLastSyncTime(zero_tv);
  4773.  
  4774. sys_log(1, "SetSyncOwner set %s %p to %s", GetName(), this, ch->GetName());
  4775. }
  4776.  
  4777. m_fSyncTime = get_float_time();
  4778. }
  4779.  
  4780. TPacketGCOwnership pack;
  4781.  
  4782. pack.bHeader = HEADER_GC_OWNERSHIP;
  4783. pack.dwOwnerVID = ch ? ch->GetVID() : 0;
  4784. pack.dwVictimVID = GetVID();
  4785.  
  4786. PacketAround(&pack, sizeof(TPacketGCOwnership));
  4787.  
  4788. return true;
  4789. }
  4790.  
  4791. struct FuncClearSync
  4792. {
  4793. void operator () (LPCHARACTER ch)
  4794. {
  4795. assert(ch != NULL);
  4796. ch->SetSyncOwner(NULL, false);
  4797. }
  4798. };
  4799.  
  4800. void CHARACTER::ClearSync()
  4801. {
  4802. SetSyncOwner(NULL);
  4803.  
  4804. std::for_each(m_kLst_pkChrSyncOwned.begin(), m_kLst_pkChrSyncOwned.end(), FuncClearSync());
  4805. m_kLst_pkChrSyncOwned.clear();
  4806. }
  4807.  
  4808. bool CHARACTER::IsSyncOwner(LPCHARACTER ch) const
  4809. {
  4810. if (m_pkChrSyncOwner == ch)
  4811. return true;
  4812.  
  4813. if (get_float_time() - m_fSyncTime >= 3.0f)
  4814. return true;
  4815.  
  4816. return false;
  4817. }
  4818.  
  4819. void CHARACTER::SetParty(LPPARTY pkParty)
  4820. {
  4821. if (pkParty == m_pkParty)
  4822. return;
  4823.  
  4824. if (pkParty && m_pkParty)
  4825. sys_err("%s is trying to reassigning party (current %p, new party %p)", GetName(), get_pointer(m_pkParty), get_pointer(pkParty));
  4826.  
  4827. sys_log(1, "PARTY set to %p", get_pointer(pkParty));
  4828.  
  4829. if (m_pkDungeon && IsPC() && !pkParty)
  4830. SetDungeon(NULL);
  4831.  
  4832. m_pkParty = pkParty;
  4833.  
  4834. if (IsPC())
  4835. {
  4836. if (m_pkParty)
  4837. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_PARTY);
  4838. else
  4839. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_PARTY);
  4840.  
  4841. UpdatePacket();
  4842. }
  4843. }
  4844.  
  4845.  
  4846. EVENTINFO(TPartyJoinEventInfo)
  4847. {
  4848. DWORD dwGuestPID;
  4849. DWORD dwLeaderPID;
  4850.  
  4851. TPartyJoinEventInfo()
  4852. : dwGuestPID( 0 )
  4853. , dwLeaderPID( 0 )
  4854. {
  4855. }
  4856. } ;
  4857.  
  4858. EVENTFUNC(party_request_event)
  4859. {
  4860. TPartyJoinEventInfo * info = dynamic_cast<TPartyJoinEventInfo *>( event->info );
  4861.  
  4862. if ( info == NULL )
  4863. {
  4864. sys_err( "party_request_event> <Factor> Null pointer" );
  4865. return 0;
  4866. }
  4867.  
  4868. LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(info->dwGuestPID);
  4869.  
  4870. if (ch)
  4871. {
  4872. sys_log(0, "PartyRequestEvent %s", ch->GetName());
  4873. ch->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequestDenied");
  4874. ch->SetPartyRequestEvent(NULL);
  4875. }
  4876.  
  4877. return 0;
  4878. }
  4879.  
  4880. bool CHARACTER::RequestToParty(LPCHARACTER leader)
  4881. {
  4882. if (leader->GetParty())
  4883. leader = leader->GetParty()->GetLeaderCharacter();
  4884.  
  4885. if (!leader)
  4886. {
  4887. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("파티장이 접속 상태가 아니라서 요청을 할 수 없습니다."));
  4888. return false;
  4889. }
  4890.  
  4891. if (m_pkPartyRequestEvent)
  4892. return false;
  4893.  
  4894. if (!IsPC() || !leader->IsPC())
  4895. return false;
  4896.  
  4897. if (leader->IsBlockMode(BLOCK_PARTY_REQUEST))
  4898. return false;
  4899.  
  4900. PartyJoinErrCode errcode = IsPartyJoinableCondition(leader, this);
  4901.  
  4902. switch (errcode)
  4903. {
  4904. case PERR_NONE:
  4905. break;
  4906.  
  4907. case PERR_SERVER:
  4908. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 서버 문제로 파티 관련 처리를 할 수 없습니다."));
  4909. return false;
  4910.  
  4911. case PERR_DIFFEMPIRE:
  4912. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 다른 제국과 파티를 이룰 수 없습니다."));
  4913. return false;
  4914.  
  4915. case PERR_DUNGEON:
  4916. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티 초대를 할 수 없습니다."));
  4917. return false;
  4918.  
  4919. case PERR_OBSERVER:
  4920. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 관전 모드에선 파티 초대를 할 수 없습니다."));
  4921. return false;
  4922.  
  4923. case PERR_LVBOUNDARY:
  4924. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> -30 ~ +30 레벨 이내의 상대방만 초대할 수 있습니다."));
  4925. return false;
  4926.  
  4927. case PERR_LOWLEVEL:
  4928. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최고 레벨 보다 30레벨이 낮아 초대할 수 없습니다."));
  4929. return false;
  4930.  
  4931. case PERR_HILEVEL:
  4932. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최저 레벨 보다 30레벨이 높아 초대할 수 없습니다."));
  4933. return false;
  4934.  
  4935. case PERR_ALREADYJOIN:
  4936. return false;
  4937.  
  4938. case PERR_PARTYISFULL:
  4939. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 더 이상 파티원을 초대할 수 없습니다."));
  4940. return false;
  4941.  
  4942. default:
  4943. sys_err("Do not process party join error(%d)", errcode);
  4944. return false;
  4945. }
  4946.  
  4947. TPartyJoinEventInfo* info = AllocEventInfo<TPartyJoinEventInfo>();
  4948.  
  4949. info->dwGuestPID = GetPlayerID();
  4950. info->dwLeaderPID = leader->GetPlayerID();
  4951.  
  4952. SetPartyRequestEvent(event_create(party_request_event, info, PASSES_PER_SEC(10)));
  4953.  
  4954. leader->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequest %u", (DWORD) GetVID());
  4955. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 님에게 파티가입 신청을 했습니다."), leader->GetName());
  4956.  
  4957. return true;
  4958. }
  4959.  
  4960. void CHARACTER::DenyToParty(LPCHARACTER member)
  4961. {
  4962. sys_log(1, "DenyToParty %s member %s %p", GetName(), member->GetName(), get_pointer(member->m_pkPartyRequestEvent));
  4963.  
  4964. if (!member->m_pkPartyRequestEvent)
  4965. return;
  4966.  
  4967. TPartyJoinEventInfo * info = dynamic_cast<TPartyJoinEventInfo *>(member->m_pkPartyRequestEvent->info);
  4968.  
  4969. if (!info)
  4970. {
  4971. sys_err( "CHARACTER::DenyToParty> <Factor> Null pointer" );
  4972. return;
  4973. }
  4974.  
  4975. if (info->dwGuestPID != member->GetPlayerID())
  4976. return;
  4977.  
  4978. if (info->dwLeaderPID != GetPlayerID())
  4979. return;
  4980.  
  4981. event_cancel(&member->m_pkPartyRequestEvent);
  4982.  
  4983. member->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequestDenied");
  4984. }
  4985.  
  4986. void CHARACTER::AcceptToParty(LPCHARACTER member)
  4987. {
  4988. sys_log(1, "AcceptToParty %s member %s %p", GetName(), member->GetName(), get_pointer(member->m_pkPartyRequestEvent));
  4989.  
  4990. if (!member->m_pkPartyRequestEvent)
  4991. return;
  4992.  
  4993. TPartyJoinEventInfo * info = dynamic_cast<TPartyJoinEventInfo *>(member->m_pkPartyRequestEvent->info);
  4994.  
  4995. if (!info)
  4996. {
  4997. sys_err( "CHARACTER::AcceptToParty> <Factor> Null pointer" );
  4998. return;
  4999. }
  5000.  
  5001. if (info->dwGuestPID != member->GetPlayerID())
  5002. return;
  5003.  
  5004. if (info->dwLeaderPID != GetPlayerID())
  5005. return;
  5006.  
  5007. event_cancel(&member->m_pkPartyRequestEvent);
  5008.  
  5009. if (!GetParty())
  5010. member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 파티에 속해있지 않습니다."));
  5011. else
  5012. {
  5013. if (GetPlayerID() != GetParty()->GetLeaderPID())
  5014. return;
  5015.  
  5016. PartyJoinErrCode errcode = IsPartyJoinableCondition(this, member);
  5017. switch (errcode)
  5018. {
  5019. case PERR_NONE: member->PartyJoin(this); return;
  5020. case PERR_SERVER: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 서버 문제로 파티 관련 처리를 할 수 없습니다.")); break;
  5021. case PERR_DUNGEON: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티 초대를 할 수 없습니다.")); break;
  5022. case PERR_OBSERVER: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 관전 모드에선 파티 초대를 할 수 없습니다.")); break;
  5023. case PERR_LVBOUNDARY: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> -30 ~ +30 레벨 이내의 상대방만 초대할 수 있습니다.")); break;
  5024. case PERR_LOWLEVEL: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최고 레벨 보다 30레벨이 낮아 초대할 수 없습니다.")); break;
  5025. case PERR_HILEVEL: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최저 레벨 보다 30레벨이 높아 초대할 수 없습니다.")); break;
  5026. case PERR_ALREADYJOIN: break;
  5027.  
  5028. case PERR_PARTYISFULL: {
  5029. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 더 이상 파티원을 초대할 수 없습니다."));
  5030. member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티의 인원제한이 초과하여 파티에 참가할 수 없습니다."));
  5031. break;
  5032. }
  5033.  
  5034. default: sys_err("Do not process party join error(%d)", errcode);
  5035. }
  5036. }
  5037.  
  5038. member->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequestDenied");
  5039. }
  5040.  
  5041. EVENTFUNC(party_invite_event)
  5042. {
  5043. TPartyJoinEventInfo * pInfo = dynamic_cast<TPartyJoinEventInfo *>( event->info );
  5044.  
  5045. if ( pInfo == NULL )
  5046. {
  5047. sys_err( "party_invite_event> <Factor> Null pointer" );
  5048. return 0;
  5049. }
  5050.  
  5051. LPCHARACTER pchInviter = CHARACTER_MANAGER::instance().FindByPID(pInfo->dwLeaderPID);
  5052.  
  5053. if (pchInviter)
  5054. {
  5055. sys_log(1, "PartyInviteEvent %s", pchInviter->GetName());
  5056. pchInviter->PartyInviteDeny(pInfo->dwGuestPID);
  5057. }
  5058.  
  5059. return 0;
  5060. }
  5061.  
  5062. void CHARACTER::PartyInvite(LPCHARACTER pchInvitee)
  5063. {
  5064. if (GetParty() && GetParty()->GetLeaderPID() != GetPlayerID())
  5065. {
  5066. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티원을 초대할 수 있는 권한이 없습니다."));
  5067. return;
  5068. }
  5069.  
  5070. else if (pchInvitee->IsBlockMode(BLOCK_PARTY_INVITE))
  5071. {
  5072. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> %s 님이 파티 거부 상태입니다."), pchInvitee->GetName());
  5073. return;
  5074. }
  5075.  
  5076. PartyJoinErrCode errcode = IsPartyJoinableCondition(this, pchInvitee);
  5077.  
  5078. switch (errcode)
  5079. {
  5080. case PERR_NONE:
  5081. break;
  5082.  
  5083. case PERR_SERVER:
  5084. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 서버 문제로 파티 관련 처리를 할 수 없습니다."));
  5085. return;
  5086.  
  5087. case PERR_DIFFEMPIRE:
  5088. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 다른 제국과 파티를 이룰 수 없습니다."));
  5089. return;
  5090.  
  5091. case PERR_DUNGEON:
  5092. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티 초대를 할 수 없습니다."));
  5093. return;
  5094.  
  5095. case PERR_OBSERVER:
  5096. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 관전 모드에선 파티 초대를 할 수 없습니다."));
  5097. return;
  5098.  
  5099. case PERR_LVBOUNDARY:
  5100. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> -30 ~ +30 레벨 이내의 상대방만 초대할 수 있습니다."));
  5101. return;
  5102.  
  5103. case PERR_LOWLEVEL:
  5104. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최고 레벨 보다 30레벨이 낮아 초대할 수 없습니다."));
  5105. return;
  5106.  
  5107. case PERR_HILEVEL:
  5108. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최저 레벨 보다 30레벨이 높아 초대할 수 없습니다."));
  5109. return;
  5110.  
  5111. case PERR_ALREADYJOIN:
  5112. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 이미 %s님은 파티에 속해 있습니다."), pchInvitee->GetName());
  5113. return;
  5114.  
  5115. case PERR_PARTYISFULL:
  5116. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 더 이상 파티원을 초대할 수 없습니다."));
  5117. return;
  5118.  
  5119. default:
  5120. sys_err("Do not process party join error(%d)", errcode);
  5121. return;
  5122. }
  5123.  
  5124. if (m_PartyInviteEventMap.end() != m_PartyInviteEventMap.find(pchInvitee->GetPlayerID()))
  5125. return;
  5126.  
  5127. TPartyJoinEventInfo* info = AllocEventInfo<TPartyJoinEventInfo>();
  5128.  
  5129. info->dwGuestPID = pchInvitee->GetPlayerID();
  5130. info->dwLeaderPID = GetPlayerID();
  5131.  
  5132. m_PartyInviteEventMap.insert(EventMap::value_type(pchInvitee->GetPlayerID(), event_create(party_invite_event, info, PASSES_PER_SEC(10))));
  5133.  
  5134. TPacketGCPartyInvite p;
  5135. p.header = HEADER_GC_PARTY_INVITE;
  5136. p.leader_vid = GetVID();
  5137.  
  5138. pchInvitee->GetDesc()->Packet(&p, sizeof(p));
  5139. }
  5140.  
  5141. void CHARACTER::PartyInviteAccept(LPCHARACTER pchInvitee)
  5142. {
  5143. EventMap::iterator itFind = m_PartyInviteEventMap.find(pchInvitee->GetPlayerID());
  5144.  
  5145. if (itFind == m_PartyInviteEventMap.end())
  5146. {
  5147. sys_log(1, "PartyInviteAccept from not invited character(%s)", pchInvitee->GetName());
  5148. return;
  5149. }
  5150.  
  5151. event_cancel(&itFind->second);
  5152. m_PartyInviteEventMap.erase(itFind);
  5153.  
  5154. if (GetParty() && GetParty()->GetLeaderPID() != GetPlayerID())
  5155. {
  5156. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티원을 초대할 수 있는 권한이 없습니다."));
  5157. return;
  5158. }
  5159.  
  5160. PartyJoinErrCode errcode = IsPartyJoinableMutableCondition(this, pchInvitee);
  5161.  
  5162. switch (errcode)
  5163. {
  5164. case PERR_NONE:
  5165. break;
  5166.  
  5167. case PERR_SERVER:
  5168. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 서버 문제로 파티 관련 처리를 할 수 없습니다."));
  5169. return;
  5170.  
  5171. case PERR_DUNGEON:
  5172. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 던전 안에서는 파티 초대에 응할 수 없습니다."));
  5173. return;
  5174.  
  5175. case PERR_OBSERVER:
  5176. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 관전 모드에선 파티 초대를 할 수 없습니다."));
  5177. return;
  5178.  
  5179. case PERR_LVBOUNDARY:
  5180. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> -30 ~ +30 레벨 이내의 상대방만 초대할 수 있습니다."));
  5181. return;
  5182.  
  5183. case PERR_LOWLEVEL:
  5184. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최고 레벨 보다 30레벨이 낮아 초대할 수 없습니다."));
  5185. return;
  5186.  
  5187. case PERR_HILEVEL:
  5188. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티내 최저 레벨 보다 30레벨이 높아 초대할 수 없습니다."));
  5189. return;
  5190.  
  5191. case PERR_ALREADYJOIN:
  5192. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티 초대에 응할 수 없습니다."));
  5193. return;
  5194.  
  5195. case PERR_PARTYISFULL:
  5196. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 더 이상 파티원을 초대할 수 없습니다."));
  5197. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티의 인원제한이 초과하여 파티에 참가할 수 없습니다."));
  5198. return;
  5199.  
  5200. default:
  5201. sys_err("ignore party join error(%d)", errcode);
  5202. return;
  5203. }
  5204.  
  5205. if (GetParty())
  5206. pchInvitee->PartyJoin(this);
  5207.  
  5208. else
  5209. {
  5210. LPPARTY pParty = CPartyManager::instance().CreateParty(this);
  5211.  
  5212. pParty->Join(pchInvitee->GetPlayerID());
  5213. pParty->Link(pchInvitee);
  5214. pParty->SendPartyInfoAllToOne(this);
  5215. }
  5216. }
  5217.  
  5218. void CHARACTER::PartyInviteDeny(DWORD dwPID)
  5219. {
  5220. EventMap::iterator itFind = m_PartyInviteEventMap.find(dwPID);
  5221.  
  5222. if (itFind == m_PartyInviteEventMap.end())
  5223. {
  5224. sys_log(1, "PartyInviteDeny to not exist event(inviter PID: %d, invitee PID: %d)", GetPlayerID(), dwPID);
  5225. return;
  5226. }
  5227.  
  5228. event_cancel(&itFind->second);
  5229. m_PartyInviteEventMap.erase(itFind);
  5230.  
  5231. LPCHARACTER pchInvitee = CHARACTER_MANAGER::instance().FindByPID(dwPID);
  5232. if (pchInvitee)
  5233. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> %s님이 파티 초대를 거절하셨습니다."), pchInvitee->GetName());
  5234. }
  5235.  
  5236. void CHARACTER::PartyJoin(LPCHARACTER pLeader)
  5237. {
  5238. pLeader->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> %s님이 파티에 참가하셨습니다."), GetName());
  5239. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> %s님의 파티에 참가하셨습니다."), pLeader->GetName());
  5240.  
  5241. pLeader->GetParty()->Join(GetPlayerID());
  5242. pLeader->GetParty()->Link(this);
  5243. }
  5244.  
  5245. CHARACTER::PartyJoinErrCode CHARACTER::IsPartyJoinableCondition(const LPCHARACTER pchLeader, const LPCHARACTER pchGuest)
  5246. {
  5247. if (pchLeader->GetEmpire() != pchGuest->GetEmpire())
  5248. return PERR_DIFFEMPIRE;
  5249.  
  5250. return IsPartyJoinableMutableCondition(pchLeader, pchGuest);
  5251. }
  5252.  
  5253. static bool __party_can_join_by_level(LPCHARACTER leader, LPCHARACTER quest)
  5254. {
  5255. int level_limit = 30;
  5256.  
  5257. return (abs(leader->GetLevel() - quest->GetLevel()) <= level_limit);
  5258. }
  5259.  
  5260. CHARACTER::PartyJoinErrCode CHARACTER::IsPartyJoinableMutableCondition(const LPCHARACTER pchLeader, const LPCHARACTER pchGuest)
  5261. {
  5262. if (!CPartyManager::instance().IsEnablePCParty())
  5263. return PERR_SERVER;
  5264.  
  5265. else if (pchLeader->GetDungeon())
  5266. return PERR_DUNGEON;
  5267.  
  5268. else if (pchGuest->IsObserverMode())
  5269. return PERR_OBSERVER;
  5270.  
  5271. else if (false == __party_can_join_by_level(pchLeader, pchGuest))
  5272. return PERR_LVBOUNDARY;
  5273.  
  5274. else if (pchGuest->GetParty())
  5275. return PERR_ALREADYJOIN;
  5276.  
  5277. else if (pchLeader->GetParty())
  5278. {
  5279. if (pchLeader->GetParty()->GetMemberCount() == PARTY_MAX_MEMBER)
  5280. return PERR_PARTYISFULL;
  5281. }
  5282.  
  5283. return PERR_NONE;
  5284. }
  5285.  
  5286. void CHARACTER::SetDungeon(LPDUNGEON pkDungeon)
  5287. {
  5288. if (pkDungeon && m_pkDungeon)
  5289. sys_err("%s is trying to reassigning dungeon (current %p, new party %p)", GetName(), get_pointer(m_pkDungeon), get_pointer(pkDungeon));
  5290.  
  5291. if (m_pkDungeon == pkDungeon) {
  5292. return;
  5293. }
  5294.  
  5295. if (m_pkDungeon)
  5296. {
  5297. if (IsPC())
  5298. {
  5299. if (GetParty())
  5300. m_pkDungeon->DecPartyMember(GetParty(), this);
  5301. else
  5302. m_pkDungeon->DecMember(this);
  5303. }
  5304.  
  5305. else if (IsMonster() || IsStone())
  5306. {
  5307. m_pkDungeon->DecMonster();
  5308. }
  5309. }
  5310.  
  5311. m_pkDungeon = pkDungeon;
  5312.  
  5313. if (pkDungeon)
  5314. {
  5315. sys_log(0, "%s DUNGEON set to %p, PARTY is %p", GetName(), get_pointer(pkDungeon), get_pointer(m_pkParty));
  5316.  
  5317. if (IsPC())
  5318. {
  5319. if (GetParty())
  5320. m_pkDungeon->IncPartyMember(GetParty(), this);
  5321. else
  5322. m_pkDungeon->IncMember(this);
  5323. }
  5324.  
  5325. else if (IsMonster() || IsStone())
  5326. {
  5327. m_pkDungeon->IncMonster();
  5328. }
  5329. }
  5330. }
  5331.  
  5332. void CHARACTER::SetWarMap(CWarMap * pWarMap)
  5333. {
  5334.  
  5335. #ifdef ENABLE_WAR_BOARD
  5336. ChatPacket(CHAT_TYPE_COMMAND, "warboard toggle|0");
  5337. #endif
  5338.  
  5339. if (m_pWarMap)
  5340. m_pWarMap->DecMember(this);
  5341.  
  5342. m_pWarMap = pWarMap;
  5343.  
  5344. if (m_pWarMap)
  5345. m_pWarMap->IncMember(this);
  5346. }
  5347.  
  5348. void CHARACTER::SetWeddingMap(marriage::WeddingMap* pMap)
  5349. {
  5350. if (m_pWeddingMap)
  5351. m_pWeddingMap->DecMember(this);
  5352.  
  5353. m_pWeddingMap = pMap;
  5354.  
  5355. if (m_pWeddingMap)
  5356. m_pWeddingMap->IncMember(this);
  5357. }
  5358.  
  5359. void CHARACTER::SetRegen(LPREGEN pkRegen)
  5360. {
  5361. m_pkRegen = pkRegen;
  5362. if (pkRegen != NULL)
  5363. {
  5364. regen_id_ = pkRegen->id;
  5365. }
  5366.  
  5367. m_fRegenAngle = GetRotation();
  5368. m_posRegen = GetXYZ();
  5369. }
  5370.  
  5371. bool CHARACTER::OnIdle()
  5372. {
  5373. return false;
  5374. }
  5375.  
  5376. void CHARACTER::OnMove(bool bIsAttack)
  5377. {
  5378. m_dwLastMoveTime = get_dword_time();
  5379.  
  5380. if (bIsAttack)
  5381. {
  5382. m_dwLastAttackTime = m_dwLastMoveTime;
  5383.  
  5384. if (IsAffectFlag(AFF_REVIVE_INVISIBLE))
  5385. RemoveAffect(AFFECT_REVIVE_INVISIBLE);
  5386.  
  5387. if (IsAffectFlag(AFF_EUNHYUNG))
  5388. {
  5389. RemoveAffect(SKILL_EUNHYUNG);
  5390. SetAffectedEunhyung();
  5391. }
  5392.  
  5393. else
  5394. {
  5395. ClearAffectedEunhyung();
  5396. }
  5397.  
  5398. /*if (IsAffectFlag(AFF_JEONSIN))
  5399. RemoveAffect(SKILL_JEONSINBANGEO);*/
  5400. }
  5401.  
  5402. /*if (IsAffectFlag(AFF_GUNGON))
  5403. RemoveAffect(SKILL_GUNGON);*/
  5404.  
  5405. mining_cancel();
  5406. }
  5407.  
  5408. void CHARACTER::OnClick(LPCHARACTER pkChrCauser)
  5409. {
  5410. if (!pkChrCauser)
  5411. {
  5412. sys_err("OnClick %s by NULL", GetName());
  5413. return;
  5414. }
  5415.  
  5416. DWORD vid = GetVID();
  5417. sys_log(0, "OnClick %s[vnum %d ServerUniqueID %d, pid %d] by %s", GetName(), GetRaceNum(), vid, GetPlayerID(), pkChrCauser->GetName());
  5418.  
  5419. {
  5420. if (pkChrCauser->GetMyShop() && pkChrCauser != this)
  5421. {
  5422. sys_err("OnClick Fail (%s->%s) - pc has shop", pkChrCauser->GetName(), GetName());
  5423. return;
  5424. }
  5425. }
  5426.  
  5427. {
  5428. if (pkChrCauser->GetExchange())
  5429. {
  5430. sys_err("OnClick Fail (%s->%s) - pc is exchanging", pkChrCauser->GetName(), GetName());
  5431. return;
  5432. }
  5433. }
  5434.  
  5435. if (IsPC())
  5436. {
  5437. if (!CTargetManager::instance().GetTargetInfo(pkChrCauser->GetPlayerID(), TARGET_TYPE_VID, GetVID()))
  5438. {
  5439. if (GetMyShop())
  5440. {
  5441. if (pkChrCauser->IsDead() == true) return;
  5442.  
  5443. if (pkChrCauser == this)
  5444. {
  5445. if ((GetExchange() || IsOpenSafebox() || GetShopOwner()) || IsCubeOpen())
  5446. {
  5447. pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 개인상점을 사용할 수 없습니다."));
  5448. return;
  5449. }
  5450. }
  5451.  
  5452. else
  5453. {
  5454. if ((pkChrCauser->GetExchange() || pkChrCauser->IsOpenSafebox() || pkChrCauser->GetMyShop() || pkChrCauser->GetShopOwner()) || pkChrCauser->IsCubeOpen() )
  5455. {
  5456. pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 개인상점을 사용할 수 없습니다."));
  5457. return;
  5458. }
  5459.  
  5460. if ((GetExchange() || IsOpenSafebox() || IsCubeOpen()))
  5461. {
  5462. pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 다른 거래를 하고 있는 중입니다."));
  5463. return;
  5464. }
  5465. }
  5466.  
  5467. if (pkChrCauser->GetShop())
  5468. {
  5469. pkChrCauser->GetShop()->RemoveGuest(pkChrCauser);
  5470. pkChrCauser->SetShop(NULL);
  5471. }
  5472.  
  5473. GetMyShop()->AddGuest(pkChrCauser, GetVID(), false);
  5474. pkChrCauser->SetShopOwner(this);
  5475.  
  5476. return;
  5477. }
  5478.  
  5479. if (test_server)
  5480. sys_err("%s.OnClickFailure(%s) - target is PC", pkChrCauser->GetName(), GetName());
  5481.  
  5482. return;
  5483. }
  5484. }
  5485.  
  5486. pkChrCauser->SetQuestNPCID(GetVID());
  5487.  
  5488. if (quest::CQuestManager::instance().Click(pkChrCauser->GetPlayerID(), this))
  5489. {
  5490. return;
  5491. }
  5492.  
  5493. if (!IsPC())
  5494. {
  5495. if (!m_triggerOnClick.pFunc)
  5496. {
  5497.  
  5498. //sys_err("%s.OnClickFailure(%s) : triggerOnClick.pFunc is EMPTY(pid=%d)",
  5499. // pkChrCauser->GetName(),
  5500. // GetName(),
  5501. // pkChrCauser->GetPlayerID());
  5502. return;
  5503. }
  5504.  
  5505. m_triggerOnClick.pFunc(this, pkChrCauser);
  5506. }
  5507.  
  5508. }
  5509.  
  5510. BYTE CHARACTER::GetGMLevel() const
  5511. {
  5512. if (test_server)
  5513. return GM_IMPLEMENTOR;
  5514.  
  5515. return m_pointsInstant.gm_level;
  5516. }
  5517.  
  5518. void CHARACTER::SetGMLevel()
  5519. {
  5520. if (GetDesc())
  5521. {
  5522. m_pointsInstant.gm_level = gm_get_level(GetName(), GetDesc()->GetHostName(), GetDesc()->GetAccountTable().login);
  5523. }
  5524.  
  5525. else
  5526. {
  5527. m_pointsInstant.gm_level = GM_PLAYER;
  5528. }
  5529. }
  5530.  
  5531. BOOL CHARACTER::IsGM() const
  5532. {
  5533. if (m_pointsInstant.gm_level != GM_PLAYER)
  5534. return true;
  5535.  
  5536. if (test_server)
  5537. return true;
  5538.  
  5539. return false;
  5540. }
  5541.  
  5542. void CHARACTER::SetStone(LPCHARACTER pkChrStone)
  5543. {
  5544. m_pkChrStone = pkChrStone;
  5545.  
  5546. if (m_pkChrStone)
  5547. {
  5548. if (pkChrStone->m_set_pkChrSpawnedBy.find(this) == pkChrStone->m_set_pkChrSpawnedBy.end())
  5549. pkChrStone->m_set_pkChrSpawnedBy.insert(this);
  5550. }
  5551. }
  5552.  
  5553. struct FuncDeadSpawnedByStone
  5554. {
  5555. void operator () (LPCHARACTER ch)
  5556. {
  5557. ch->Dead(NULL);
  5558. ch->SetStone(NULL);
  5559. }
  5560. };
  5561.  
  5562. void CHARACTER::ClearStone()
  5563. {
  5564. if (!m_set_pkChrSpawnedBy.empty())
  5565. {
  5566. FuncDeadSpawnedByStone f;
  5567. std::for_each(m_set_pkChrSpawnedBy.begin(), m_set_pkChrSpawnedBy.end(), f);
  5568. m_set_pkChrSpawnedBy.clear();
  5569. }
  5570.  
  5571. if (!m_pkChrStone)
  5572. return;
  5573.  
  5574. m_pkChrStone->m_set_pkChrSpawnedBy.erase(this);
  5575. m_pkChrStone = NULL;
  5576. }
  5577.  
  5578. void CHARACTER::ClearTarget()
  5579. {
  5580. if (m_pkChrTarget)
  5581. {
  5582. m_pkChrTarget->m_set_pkChrTargetedBy.erase(this);
  5583. m_pkChrTarget = NULL;
  5584. }
  5585.  
  5586. TPacketGCTarget p;
  5587.  
  5588. p.header = HEADER_GC_TARGET;
  5589. p.dwVID = 0;
  5590. p.bHPPercent = 0;
  5591.  
  5592. #ifdef WJ_TARGET_HP_SYSTEM
  5593. p.dwActualHP = 0;
  5594. p.dwMaxHP = 0;
  5595. #endif
  5596.  
  5597. CHARACTER_SET::iterator it = m_set_pkChrTargetedBy.begin();
  5598.  
  5599. while (it != m_set_pkChrTargetedBy.end())
  5600. {
  5601. LPCHARACTER pkChr = *(it++);
  5602. pkChr->m_pkChrTarget = NULL;
  5603.  
  5604. if (!pkChr->GetDesc())
  5605. {
  5606. sys_err("%s %p does not have desc", pkChr->GetName(), get_pointer(pkChr));
  5607. abort();
  5608. }
  5609.  
  5610. pkChr->GetDesc()->Packet(&p, sizeof(TPacketGCTarget));
  5611. }
  5612.  
  5613. m_set_pkChrTargetedBy.clear();
  5614. }
  5615.  
  5616. void CHARACTER::SetTarget(LPCHARACTER pkChrTarget)
  5617. {
  5618. if (m_pkChrTarget == pkChrTarget)
  5619. return;
  5620.  
  5621. if (m_pkChrTarget)
  5622. m_pkChrTarget->m_set_pkChrTargetedBy.erase(this);
  5623.  
  5624. m_pkChrTarget = pkChrTarget;
  5625.  
  5626. TPacketGCTarget p;
  5627.  
  5628. p.header = HEADER_GC_TARGET;
  5629.  
  5630. if (m_pkChrTarget)
  5631. {
  5632. m_pkChrTarget->m_set_pkChrTargetedBy.insert(this);
  5633.  
  5634. p.dwVID = m_pkChrTarget->GetVID();
  5635.  
  5636. p.bHPPercent = 0;
  5637.  
  5638. #ifdef WJ_TARGET_HP_SYSTEM
  5639. p.dwActualHP = 0;
  5640. p.dwMaxHP = 0;
  5641. #endif
  5642.  
  5643. if (m_pkChrTarget->GetMaxHP() <= 0)
  5644. {
  5645. p.bHPPercent = 0;
  5646.  
  5647. #ifdef WJ_TARGET_HP_SYSTEM
  5648. p.dwActualHP = 0;
  5649. p.dwMaxHP = 0;
  5650. #endif
  5651. }
  5652.  
  5653. else
  5654. {
  5655. if (m_pkChrTarget->GetRaceNum() == 20101 ||
  5656. m_pkChrTarget->GetRaceNum() == 20102 ||
  5657. m_pkChrTarget->GetRaceNum() == 20103 ||
  5658. m_pkChrTarget->GetRaceNum() == 20104 ||
  5659. m_pkChrTarget->GetRaceNum() == 20105 ||
  5660. m_pkChrTarget->GetRaceNum() == 20106 ||
  5661. m_pkChrTarget->GetRaceNum() == 20107 ||
  5662. m_pkChrTarget->GetRaceNum() == 20108 ||
  5663. m_pkChrTarget->GetRaceNum() == 20109)
  5664. {
  5665. LPCHARACTER owner = m_pkChrTarget->GetVictim();
  5666.  
  5667. if (owner)
  5668. {
  5669. int iHorseHealth = owner->GetHorseHealth();
  5670. int iHorseMaxHealth = owner->GetHorseMaxHealth();
  5671.  
  5672. if (iHorseMaxHealth)
  5673. {
  5674. p.bHPPercent = MINMAX(0, iHorseHealth * 100 / iHorseMaxHealth, 100);
  5675.  
  5676. #ifdef WJ_TARGET_HP_SYSTEM
  5677. p.dwActualHP = 100;
  5678. p.dwMaxHP = 100;
  5679. #endif
  5680. }
  5681.  
  5682. else
  5683. {
  5684. p.bHPPercent = 100;
  5685.  
  5686. #ifdef WJ_TARGET_HP_SYSTEM
  5687. p.dwActualHP = 100;
  5688. p.dwMaxHP = 100;
  5689. #endif
  5690. }
  5691. }
  5692.  
  5693. else
  5694. {
  5695. p.bHPPercent = 100;
  5696.  
  5697. #ifdef WJ_TARGET_HP_SYSTEM
  5698. p.dwActualHP = 100;
  5699. p.dwMaxHP = 100;
  5700. #endif
  5701. }
  5702. }
  5703.  
  5704. else
  5705. {
  5706. p.bHPPercent = MINMAX(0, (m_pkChrTarget->GetHP() * 100) / m_pkChrTarget->GetMaxHP(), 100);
  5707.  
  5708. #ifdef WJ_TARGET_HP_SYSTEM
  5709. p.dwActualHP = m_pkChrTarget->GetHP();
  5710. p.dwMaxHP = m_pkChrTarget->GetMaxHP();
  5711. #endif
  5712. }
  5713. }
  5714. }
  5715.  
  5716. else
  5717. {
  5718. p.dwVID = 0;
  5719. p.bHPPercent = 0;
  5720.  
  5721. #ifdef WJ_TARGET_HP_SYSTEM
  5722. p.dwActualHP = 0;
  5723. p.dwMaxHP = 0;
  5724. #endif
  5725.  
  5726. }
  5727.  
  5728. GetDesc()->Packet(&p, sizeof(TPacketGCTarget));
  5729. }
  5730.  
  5731. void CHARACTER::BroadcastTargetPacket()
  5732. {
  5733. if (m_set_pkChrTargetedBy.empty())
  5734. return;
  5735.  
  5736. TPacketGCTarget p;
  5737.  
  5738. p.header = HEADER_GC_TARGET;
  5739. p.dwVID = GetVID();
  5740.  
  5741. p.bHPPercent = 0;
  5742.  
  5743. #ifdef WJ_TARGET_HP_SYSTEM
  5744. p.dwActualHP = 0;
  5745. p.dwMaxHP = 0;
  5746.  
  5747. if (GetMaxHP() <= 0)
  5748. {
  5749. p.bHPPercent = 0;
  5750. p.dwActualHP = 0;
  5751. p.dwMaxHP = 0;
  5752. }
  5753.  
  5754. else
  5755. {
  5756. p.bHPPercent = MINMAX(0, (GetHP() * 100) / GetMaxHP(), 100);
  5757. p.dwActualHP = GetHP();
  5758. p.dwMaxHP = GetMaxHP();
  5759. }
  5760. #else
  5761.  
  5762. if (IsPC())
  5763. p.bHPPercent = 0;
  5764.  
  5765. else if (GetMaxHP() <= 0)
  5766. p.bHPPercent = 0;
  5767.  
  5768. else
  5769. p.bHPPercent = MINMAX(0, (GetHP() * 100) / GetMaxHP(), 100);
  5770. #endif
  5771.  
  5772. CHARACTER_SET::iterator it = m_set_pkChrTargetedBy.begin();
  5773.  
  5774. while (it != m_set_pkChrTargetedBy.end())
  5775. {
  5776. LPCHARACTER pkChr = *it++;
  5777.  
  5778. if (!pkChr->GetDesc())
  5779. {
  5780. sys_err("%s %p does not have desc", pkChr->GetName(), get_pointer(pkChr));
  5781. abort();
  5782. }
  5783.  
  5784. pkChr->GetDesc()->Packet(&p, sizeof(TPacketGCTarget));
  5785. }
  5786. }
  5787.  
  5788. void CHARACTER::CheckTarget()
  5789. {
  5790. if (!m_pkChrTarget)
  5791. return;
  5792.  
  5793. if (DISTANCE_APPROX(GetX() - m_pkChrTarget->GetX(), GetY() - m_pkChrTarget->GetY()) >= 4800)
  5794. SetTarget(NULL);
  5795. }
  5796.  
  5797. void CHARACTER::SetWarpLocation(long lMapIndex, long x, long y)
  5798. {
  5799. m_posWarp.x = x * 100;
  5800. m_posWarp.y = y * 100;
  5801. m_lWarpMapIndex = lMapIndex;
  5802. }
  5803.  
  5804. void CHARACTER::SaveExitLocation()
  5805. {
  5806. m_posExit = GetXYZ();
  5807. m_lExitMapIndex = GetMapIndex();
  5808. }
  5809.  
  5810. void CHARACTER::ExitToSavedLocation()
  5811. {
  5812. sys_log (0, "ExitToSavedLocation");
  5813. WarpSet(m_posWarp.x, m_posWarp.y, m_lWarpMapIndex);
  5814.  
  5815. m_posExit.x = m_posExit.y = m_posExit.z = 0;
  5816. m_lExitMapIndex = 0;
  5817. }
  5818.  
  5819. bool CHARACTER::WarpSet(long x, long y, long lPrivateMapIndex)
  5820. {
  5821. if (!IsPC())
  5822. return false;
  5823.  
  5824. long lAddr;
  5825. long lMapIndex;
  5826. WORD wPort;
  5827.  
  5828. if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort))
  5829. {
  5830. sys_err("cannot find map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
  5831. return false;
  5832. }
  5833.  
  5834. if (lPrivateMapIndex >= 10000)
  5835. {
  5836. if (lPrivateMapIndex / 10000 != lMapIndex)
  5837. {
  5838. sys_err("Invalid map index %d, must be child of %d", lPrivateMapIndex, lMapIndex);
  5839. return false;
  5840. }
  5841.  
  5842. lMapIndex = lPrivateMapIndex;
  5843. }
  5844.  
  5845. Stop();
  5846. Save();
  5847.  
  5848. if (GetSectree())
  5849. {
  5850. GetSectree()->RemoveEntity(this);
  5851. ViewCleanup();
  5852.  
  5853. EncodeRemovePacket(this);
  5854. }
  5855.  
  5856. m_lWarpMapIndex = lMapIndex;
  5857. m_posWarp.x = x;
  5858. m_posWarp.y = y;
  5859.  
  5860. sys_log(0, "WarpSet %s %d %d current map %d target map %d", GetName(), x, y, GetMapIndex(), lMapIndex);
  5861.  
  5862. TPacketGCWarp p;
  5863.  
  5864. p.bHeader = HEADER_GC_WARP;
  5865. p.lX = x;
  5866. p.lY = y;
  5867. p.lAddr = lAddr;
  5868. p.wPort = wPort;
  5869.  
  5870. #ifdef __SWITCHBOT__
  5871. CSwitchbotManager::Instance().SetIsWarping(GetPlayerID(), true);
  5872.  
  5873. if (p.wPort != mother_port)
  5874. {
  5875. CSwitchbotManager::Instance().P2PSendSwitchbot(GetPlayerID(), p.wPort);
  5876. }
  5877. #endif
  5878.  
  5879. GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
  5880.  
  5881. char buf[256];
  5882. snprintf(buf, sizeof(buf), "%s MapIdx %ld DestMapIdx%ld DestX%ld DestY%ld Empire%d", GetName(), GetMapIndex(), lPrivateMapIndex, x, y, GetEmpire());
  5883. LogManager::instance().CharLog(this, 0, "WARP", buf);
  5884.  
  5885. return true;
  5886. }
  5887.  
  5888. void CHARACTER::WarpEnd()
  5889. {
  5890. if (test_server)
  5891. sys_log(0, "WarpEnd %s", GetName());
  5892.  
  5893. if (m_posWarp.x == 0 && m_posWarp.y == 0)
  5894. return;
  5895.  
  5896. int index = m_lWarpMapIndex;
  5897.  
  5898. if (index > 10000)
  5899. index /= 10000;
  5900.  
  5901. if (!map_allow_find(index))
  5902. {
  5903. sys_err("location %d %d not allowed to login this server", m_posWarp.x, m_posWarp.y);
  5904. GoHome();
  5905. return;
  5906. }
  5907.  
  5908. sys_log(0, "WarpEnd %s %d %u %u", GetName(), m_lWarpMapIndex, m_posWarp.x, m_posWarp.y);
  5909.  
  5910. Show(m_lWarpMapIndex, m_posWarp.x, m_posWarp.y, 0);
  5911. Stop();
  5912.  
  5913. m_lWarpMapIndex = 0;
  5914. m_posWarp.x = m_posWarp.y = m_posWarp.z = 0;
  5915.  
  5916. {
  5917. TPacketGGLogin p;
  5918.  
  5919. p.bHeader = HEADER_GG_LOGIN;
  5920. strlcpy(p.szName, GetName(), sizeof(p.szName));
  5921. p.dwPID = GetPlayerID();
  5922. p.bEmpire = GetEmpire();
  5923. p.lMapIndex = SECTREE_MANAGER::instance().GetMapIndex(GetX(), GetY());
  5924. p.bChannel = g_bChannel;
  5925.  
  5926. P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGLogin));
  5927. }
  5928. }
  5929.  
  5930. bool CHARACTER::Return()
  5931. {
  5932. if (!IsNPC())
  5933. return false;
  5934.  
  5935. int x, y;
  5936. /*
  5937. float fDist = DISTANCE_SQRT(m_pkMobData->m_posLastAttacked.x - GetX(), m_pkMobData->m_posLastAttacked.y - GetY());
  5938. float fx, fy;
  5939. GetDeltaByDegree(GetRotation(), fDist, &fx, &fy);
  5940. x = GetX() + (int) fx;
  5941. y = GetY() + (int) fy;
  5942. */
  5943. SetVictim(NULL);
  5944.  
  5945. x = m_pkMobInst->m_posLastAttacked.x;
  5946. y = m_pkMobInst->m_posLastAttacked.y;
  5947.  
  5948. SetRotationToXY(x, y);
  5949.  
  5950. if (!Goto(x, y))
  5951. return false;
  5952.  
  5953. SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
  5954.  
  5955. if (test_server)
  5956. sys_log(0, "%s %p 포기하고 돌아가자! %d %d", GetName(), this, x, y);
  5957.  
  5958. if (GetParty())
  5959. GetParty()->SendMessage(this, PM_RETURN, x, y);
  5960.  
  5961. return true;
  5962. }
  5963.  
  5964. bool CHARACTER::Follow(LPCHARACTER pkChr, float fMinDistance)
  5965. {
  5966. if (IsPC())
  5967. {
  5968. sys_err("CHARACTER::Follow : PC cannot use this method", GetName());
  5969. return false;
  5970. }
  5971.  
  5972. if (IS_SET(m_pointsInstant.dwAIFlag, AIFLAG_NOMOVE))
  5973. {
  5974. if (pkChr->IsPC())
  5975. {
  5976. if (!GetParty() || !GetParty()->GetLeader() || GetParty()->GetLeader() == this)
  5977. {
  5978. if (get_dword_time() - m_pkMobInst->m_dwLastAttackedTime >= 15000)
  5979. {
  5980. if (m_pkMobData->m_table.wAttackRange < DISTANCE_APPROX(pkChr->GetX() - GetX(), pkChr->GetY() - GetY()))
  5981. if (Return())
  5982. return true;
  5983. }
  5984. }
  5985. }
  5986.  
  5987. return false;
  5988. }
  5989.  
  5990. long x = pkChr->GetX();
  5991. long y = pkChr->GetY();
  5992.  
  5993. if (pkChr->IsPC())
  5994. {
  5995. if (!GetParty() || !GetParty()->GetLeader() || GetParty()->GetLeader() == this)
  5996. {
  5997. if (get_dword_time() - m_pkMobInst->m_dwLastAttackedTime >= 15000)
  5998. {
  5999. if (5000 < DISTANCE_APPROX(m_pkMobInst->m_posLastAttacked.x - GetX(), m_pkMobInst->m_posLastAttacked.y - GetY()))
  6000. if (Return())
  6001. return true;
  6002. }
  6003. }
  6004. }
  6005.  
  6006. if (IsGuardNPC())
  6007. {
  6008. if (5000 < DISTANCE_APPROX(m_pkMobInst->m_posLastAttacked.x - GetX(), m_pkMobInst->m_posLastAttacked.y - GetY()))
  6009. if (Return())
  6010. return true;
  6011. }
  6012.  
  6013. if (pkChr->IsState(pkChr->m_stateMove) && GetMobBattleType() != BATTLE_TYPE_RANGE && GetMobBattleType() != BATTLE_TYPE_MAGIC && false == IsPet())
  6014. {
  6015. float rot = pkChr->GetRotation();
  6016. float rot_delta = GetDegreeDelta(rot, GetDegreeFromPositionXY(GetX(), GetY(), pkChr->GetX(), pkChr->GetY()));
  6017.  
  6018. float yourSpeed = pkChr->GetMoveSpeed();
  6019. float mySpeed = GetMoveSpeed();
  6020.  
  6021. float fDist = DISTANCE_SQRT(x - GetX(), y - GetY());
  6022. float fFollowSpeed = mySpeed - yourSpeed * cos(rot_delta * M_PI / 180);
  6023.  
  6024. if (fFollowSpeed >= 0.1f)
  6025. {
  6026. float fMeetTime = fDist / fFollowSpeed;
  6027. float fYourMoveEstimateX, fYourMoveEstimateY;
  6028.  
  6029. if( fMeetTime * yourSpeed <= 100000.0f )
  6030. {
  6031. GetDeltaByDegree(pkChr->GetRotation(), fMeetTime * yourSpeed, &fYourMoveEstimateX, &fYourMoveEstimateY);
  6032.  
  6033. x += (long) fYourMoveEstimateX;
  6034. y += (long) fYourMoveEstimateY;
  6035.  
  6036. float fDistNew = sqrt(((double)x - GetX())*(x-GetX())+((double)y - GetY())*(y-GetY()));
  6037. if (fDist < fDistNew)
  6038. {
  6039. x = (long)(GetX() + (x - GetX()) * fDist / fDistNew);
  6040. y = (long)(GetY() + (y - GetY()) * fDist / fDistNew);
  6041. }
  6042. }
  6043. }
  6044. }
  6045.  
  6046. SetRotationToXY(x, y);
  6047.  
  6048. float fDist = DISTANCE_SQRT(x - GetX(), y - GetY());
  6049.  
  6050. if (fDist <= fMinDistance)
  6051. return false;
  6052.  
  6053. float fx, fy;
  6054.  
  6055. if (IsChangeAttackPosition(pkChr) && GetMobRank() < MOB_RANK_BOSS)
  6056. {
  6057. SetChangeAttackPositionTime();
  6058.  
  6059. int retry = 16;
  6060. int dx, dy;
  6061. int rot = (int) GetDegreeFromPositionXY(x, y, GetX(), GetY());
  6062.  
  6063. while (--retry)
  6064. {
  6065. if (fDist < 500.0f)
  6066. GetDeltaByDegree((rot + number(-90, 90) + number(-90, 90)) % 360, fMinDistance, &fx, &fy);
  6067. else
  6068. GetDeltaByDegree(number(0, 359), fMinDistance, &fx, &fy);
  6069.  
  6070. dx = x + (int) fx;
  6071. dy = y + (int) fy;
  6072.  
  6073. LPSECTREE tree = SECTREE_MANAGER::instance().Get(GetMapIndex(), dx, dy);
  6074.  
  6075. if (NULL == tree)
  6076. break;
  6077.  
  6078. if (0 == (tree->GetAttribute(dx, dy) & (ATTR_BLOCK | ATTR_OBJECT)))
  6079. break;
  6080. }
  6081.  
  6082. if (!Goto(dx, dy))
  6083. return false;
  6084. }
  6085.  
  6086. else
  6087. {
  6088. float fDistToGo = fDist - fMinDistance;
  6089. GetDeltaByDegree(GetRotation(), fDistToGo, &fx, &fy);
  6090.  
  6091. if (!Goto(GetX() + (int) fx, GetY() + (int) fy))
  6092. return false;
  6093. }
  6094.  
  6095. SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
  6096.  
  6097. return true;
  6098. }
  6099.  
  6100. float CHARACTER::GetDistanceFromSafeboxOpen() const
  6101. {
  6102. return DISTANCE_APPROX(GetX() - m_posSafeboxOpen.x, GetY() - m_posSafeboxOpen.y);
  6103. }
  6104.  
  6105. void CHARACTER::SetSafeboxOpenPosition()
  6106. {
  6107. m_posSafeboxOpen = GetXYZ();
  6108. }
  6109.  
  6110. CSafebox * CHARACTER::GetSafebox() const
  6111. {
  6112. return m_pkSafebox;
  6113. }
  6114.  
  6115. void CHARACTER::ReqSafeboxLoad(const char* pszPassword)
  6116. {
  6117. if (!*pszPassword || strlen(pszPassword) > SAFEBOX_PASSWORD_MAX_LEN)
  6118. {
  6119. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<창고> 잘못된 암호를 입력하셨습니다."));
  6120. return;
  6121. }
  6122.  
  6123. else if (m_pkSafebox)
  6124. {
  6125. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<창고> 창고가 이미 열려있습니다."));
  6126. return;
  6127. }
  6128.  
  6129. int iPulse = thecore_pulse();
  6130.  
  6131. if (iPulse - GetSafeboxLoadTime() < PASSES_PER_SEC(10))
  6132. {
  6133. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<창고> 창고를 닫은지 10초 안에는 열 수 없습니다."));
  6134. return;
  6135. }
  6136.  
  6137. /*else if (GetDistanceFromSafeboxOpen() > 1000)
  6138. {
  6139. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<창고> 거리가 멀어서 창고를 열 수 없습니다."));
  6140. return;
  6141. }*/
  6142.  
  6143. else if (m_bOpeningSafebox)
  6144. {
  6145. sys_log(0, "Overlapped safebox load request from %s", GetName());
  6146. return;
  6147. }
  6148.  
  6149. SetSafeboxLoadTime();
  6150. m_bOpeningSafebox = true;
  6151.  
  6152. TSafeboxLoadPacket p;
  6153. p.dwID = GetDesc()->GetAccountTable().id;
  6154. strlcpy(p.szLogin, GetDesc()->GetAccountTable().login, sizeof(p.szLogin));
  6155. strlcpy(p.szPassword, pszPassword, sizeof(p.szPassword));
  6156.  
  6157. db_clientdesc->DBPacket(HEADER_GD_SAFEBOX_LOAD, GetDesc()->GetHandle(), &p, sizeof(p));
  6158. }
  6159.  
  6160. void CHARACTER::LoadSafebox(int iSize, DWORD dwGold, int iItemCount, TPlayerItem * pItems)
  6161. {
  6162. bool bLoaded = false;
  6163.  
  6164. SetOpenSafebox(true);
  6165.  
  6166. if (m_pkSafebox)
  6167. bLoaded = true;
  6168.  
  6169. if (!m_pkSafebox)
  6170. m_pkSafebox = M2_NEW CSafebox(this, iSize, dwGold);
  6171. else
  6172. m_pkSafebox->ChangeSize(iSize);
  6173.  
  6174. m_iSafeboxSize = iSize;
  6175.  
  6176. TPacketCGSafeboxSize p;
  6177.  
  6178. p.bHeader = HEADER_GC_SAFEBOX_SIZE;
  6179. p.bSize = iSize;
  6180.  
  6181. GetDesc()->Packet(&p, sizeof(TPacketCGSafeboxSize));
  6182.  
  6183. if (!bLoaded)
  6184. {
  6185. for (int i = 0; i < iItemCount; ++i, ++pItems)
  6186. {
  6187. if (!m_pkSafebox->IsValidPosition(pItems->pos))
  6188. continue;
  6189.  
  6190. LPITEM item = ITEM_MANAGER::instance().CreateItem(pItems->vnum, pItems->count, pItems->id);
  6191.  
  6192. if (!item)
  6193. {
  6194. sys_err("cannot create item vnum %d id %u (name: %s)", pItems->vnum, pItems->id, GetName());
  6195. continue;
  6196. }
  6197.  
  6198. item->SetSkipSave(true);
  6199. item->SetSockets(pItems->alSockets);
  6200. item->SetAttributes(pItems->aAttr);
  6201.  
  6202. if (!m_pkSafebox->Add(pItems->pos, item))
  6203. {
  6204. M2_DESTROY_ITEM(item);
  6205. }
  6206.  
  6207. else
  6208. item->SetSkipSave(false);
  6209. }
  6210. }
  6211. }
  6212.  
  6213. void CHARACTER::ChangeSafeboxSize(BYTE bSize)
  6214. {
  6215. //if (!m_pkSafebox)
  6216. //return;
  6217.  
  6218. TPacketCGSafeboxSize p;
  6219.  
  6220. p.bHeader = HEADER_GC_SAFEBOX_SIZE;
  6221. p.bSize = bSize;
  6222.  
  6223. GetDesc()->Packet(&p, sizeof(TPacketCGSafeboxSize));
  6224.  
  6225. if (m_pkSafebox)
  6226. m_pkSafebox->ChangeSize(bSize);
  6227.  
  6228. m_iSafeboxSize = bSize;
  6229. }
  6230.  
  6231. void CHARACTER::CloseSafebox()
  6232. {
  6233. if (!m_pkSafebox)
  6234. return;
  6235.  
  6236. SetOpenSafebox(false);
  6237.  
  6238. m_pkSafebox->Save();
  6239.  
  6240. M2_DELETE(m_pkSafebox);
  6241. m_pkSafebox = NULL;
  6242.  
  6243. ChatPacket(CHAT_TYPE_COMMAND, "CloseSafebox");
  6244.  
  6245. SetSafeboxLoadTime();
  6246. m_bOpeningSafebox = false;
  6247.  
  6248. Save();
  6249. }
  6250.  
  6251. CSafebox * CHARACTER::GetMall() const
  6252. {
  6253. return m_pkMall;
  6254. }
  6255.  
  6256. void CHARACTER::LoadMall(int iItemCount, TPlayerItem * pItems)
  6257. {
  6258. bool bLoaded = false;
  6259.  
  6260. if (m_pkMall)
  6261. bLoaded = true;
  6262.  
  6263. if (!m_pkMall)
  6264. m_pkMall = M2_NEW CSafebox(this, 3 * SAFEBOX_PAGE_SIZE, 0);
  6265.  
  6266. else
  6267. m_pkMall->ChangeSize(3 * SAFEBOX_PAGE_SIZE);
  6268.  
  6269. m_pkMall->SetWindowMode(MALL);
  6270.  
  6271. TPacketCGSafeboxSize p;
  6272.  
  6273. p.bHeader = HEADER_GC_MALL_OPEN;
  6274. p.bSize = 3 * SAFEBOX_PAGE_SIZE;
  6275.  
  6276. GetDesc()->Packet(&p, sizeof(TPacketCGSafeboxSize));
  6277.  
  6278. if (!bLoaded)
  6279. {
  6280. for (int i = 0; i < iItemCount; ++i, ++pItems)
  6281. {
  6282. if (!m_pkMall->IsValidPosition(pItems->pos))
  6283. continue;
  6284.  
  6285. LPITEM item = ITEM_MANAGER::instance().CreateItem(pItems->vnum, pItems->count, pItems->id);
  6286.  
  6287. if (!item)
  6288. {
  6289. sys_err("cannot create item vnum %d id %u (name: %s)", pItems->vnum, pItems->id, GetName());
  6290. continue;
  6291. }
  6292.  
  6293. item->SetSkipSave(true);
  6294. item->SetSockets(pItems->alSockets);
  6295. item->SetAttributes(pItems->aAttr);
  6296.  
  6297. if (!m_pkMall->Add(pItems->pos, item))
  6298. M2_DESTROY_ITEM(item);
  6299. else
  6300. item->SetSkipSave(false);
  6301. }
  6302. }
  6303. }
  6304.  
  6305. void CHARACTER::CloseMall()
  6306. {
  6307. if (!m_pkMall)
  6308. return;
  6309.  
  6310. m_pkMall->Save();
  6311.  
  6312. M2_DELETE(m_pkMall);
  6313. m_pkMall = NULL;
  6314.  
  6315. ChatPacket(CHAT_TYPE_COMMAND, "CloseMall");
  6316. }
  6317.  
  6318. bool CHARACTER::BuildUpdatePartyPacket(TPacketGCPartyUpdate & out)
  6319. {
  6320. if (!GetParty())
  6321. return false;
  6322.  
  6323. memset(&out, 0, sizeof(out));
  6324.  
  6325. out.header = HEADER_GC_PARTY_UPDATE;
  6326. out.pid = GetPlayerID();
  6327.  
  6328. if (GetMaxHP() <= 0)
  6329. out.percent_hp = 0;
  6330. else
  6331. out.percent_hp = MINMAX(0, GetHP() * 100 / GetMaxHP(), 100);
  6332.  
  6333. out.role = GetParty()->GetRole(GetPlayerID());
  6334.  
  6335. sys_log(1, "PARTY %s role is %d", GetName(), out.role);
  6336.  
  6337. LPCHARACTER l = GetParty()->GetLeaderCharacter();
  6338.  
  6339. if (l && DISTANCE_APPROX(GetX() - l->GetX(), GetY() - l->GetY()) < PARTY_DEFAULT_RANGE)
  6340. {
  6341. out.affects[0] = GetParty()->GetPartyBonusExpPercent();
  6342. out.affects[1] = GetPoint(POINT_PARTY_ATTACKER_BONUS);
  6343. out.affects[2] = GetPoint(POINT_PARTY_TANKER_BONUS);
  6344. out.affects[3] = GetPoint(POINT_PARTY_BUFFER_BONUS);
  6345. out.affects[4] = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
  6346. out.affects[5] = GetPoint(POINT_PARTY_HASTE_BONUS);
  6347. out.affects[6] = GetPoint(POINT_PARTY_DEFENDER_BONUS);
  6348. }
  6349.  
  6350. return true;
  6351. }
  6352.  
  6353. int CHARACTER::GetLeadershipSkillLevel() const
  6354. {
  6355. return GetSkillLevel(SKILL_LEADERSHIP);
  6356. }
  6357.  
  6358. void CHARACTER::QuerySafeboxSize()
  6359. {
  6360. if (m_iSafeboxSize == -1)
  6361. {
  6362. DBManager::instance().ReturnQuery(QID_SAFEBOX_SIZE, GetPlayerID(), NULL, "SELECT size FROM safebox%s WHERE account_id = %u", get_table_postfix(), GetDesc()->GetAccountTable().id);
  6363. }
  6364. }
  6365.  
  6366. void CHARACTER::SetSafeboxSize(int iSize)
  6367. {
  6368. sys_log(1, "SetSafeboxSize: %s %d", GetName(), iSize);
  6369. m_iSafeboxSize = iSize;
  6370. DBManager::instance().Query("UPDATE safebox%s SET size = %d WHERE account_id = %u", get_table_postfix(), iSize / SAFEBOX_PAGE_SIZE, GetDesc()->GetAccountTable().id);
  6371. }
  6372.  
  6373. int CHARACTER::GetSafeboxSize() const
  6374. {
  6375. return m_iSafeboxSize;
  6376. }
  6377.  
  6378. void CHARACTER::SetNowWalking(bool bWalkFlag)
  6379. {
  6380. if (m_bNowWalking != bWalkFlag)
  6381. {
  6382. if (bWalkFlag)
  6383. {
  6384. m_bNowWalking = true;
  6385. m_dwWalkStartTime = get_dword_time();
  6386. }
  6387.  
  6388. else
  6389. {
  6390. m_bNowWalking = false;
  6391. }
  6392.  
  6393. //if (m_bNowWalking)
  6394. {
  6395. TPacketGCWalkMode p;
  6396. p.vid = GetVID();
  6397. p.header = HEADER_GC_WALK_MODE;
  6398. p.mode = m_bNowWalking ? WALKMODE_WALK : WALKMODE_RUN;
  6399.  
  6400. PacketView(&p, sizeof(p));
  6401. }
  6402.  
  6403. if (IsNPC())
  6404. {
  6405. if (m_bNowWalking)
  6406. MonsterLog("걷는다");
  6407. else
  6408. MonsterLog("뛴다");
  6409. }
  6410. }
  6411. }
  6412.  
  6413. void CHARACTER::StartStaminaConsume()
  6414. {
  6415. if (m_bStaminaConsume)
  6416. return;
  6417.  
  6418. PointChange(POINT_STAMINA, 0);
  6419. m_bStaminaConsume = true;
  6420.  
  6421. if (IsStaminaHalfConsume())
  6422. ChatPacket(CHAT_TYPE_COMMAND, "StartStaminaConsume %d %d", STAMINA_PER_STEP * passes_per_sec / 2, GetStamina());
  6423. else
  6424. ChatPacket(CHAT_TYPE_COMMAND, "StartStaminaConsume %d %d", STAMINA_PER_STEP * passes_per_sec, GetStamina());
  6425. }
  6426.  
  6427. void CHARACTER::StopStaminaConsume()
  6428. {
  6429. if (!m_bStaminaConsume)
  6430. return;
  6431.  
  6432. PointChange(POINT_STAMINA, 0);
  6433. m_bStaminaConsume = false;
  6434. ChatPacket(CHAT_TYPE_COMMAND, "StopStaminaConsume %d", GetStamina());
  6435. }
  6436.  
  6437. bool CHARACTER::IsStaminaConsume() const
  6438. {
  6439. return m_bStaminaConsume;
  6440. }
  6441.  
  6442. bool CHARACTER::IsStaminaHalfConsume() const
  6443. {
  6444. return IsEquipUniqueItem(UNIQUE_ITEM_HALF_STAMINA);
  6445. }
  6446.  
  6447. void CHARACTER::ResetStopTime()
  6448. {
  6449. m_dwStopTime = get_dword_time();
  6450. }
  6451.  
  6452. DWORD CHARACTER::GetStopTime() const
  6453. {
  6454. return m_dwStopTime;
  6455. }
  6456.  
  6457. void CHARACTER::ResetPoint(int iLv)
  6458. {
  6459. BYTE bJob = GetJob();
  6460.  
  6461. PointChange(POINT_LEVEL, iLv - GetLevel());
  6462.  
  6463. SetRealPoint(POINT_ST, JobInitialPoints[bJob].st);
  6464. SetPoint(POINT_ST, GetRealPoint(POINT_ST));
  6465.  
  6466. SetRealPoint(POINT_HT, JobInitialPoints[bJob].ht);
  6467. SetPoint(POINT_HT, GetRealPoint(POINT_HT));
  6468.  
  6469. SetRealPoint(POINT_DX, JobInitialPoints[bJob].dx);
  6470. SetPoint(POINT_DX, GetRealPoint(POINT_DX));
  6471.  
  6472. SetRealPoint(POINT_IQ, JobInitialPoints[bJob].iq);
  6473. SetPoint(POINT_IQ, GetRealPoint(POINT_IQ));
  6474.  
  6475. SetRandomHP((iLv - 1) * number(JobInitialPoints[GetJob()].hp_per_lv_begin, JobInitialPoints[GetJob()].hp_per_lv_end));
  6476. SetRandomSP((iLv - 1) * number(JobInitialPoints[GetJob()].sp_per_lv_begin, JobInitialPoints[GetJob()].sp_per_lv_end));
  6477.  
  6478. //PointChange(POINT_STAT, ((MINMAX(1, iLv, 90) - 1) * 3) + GetPoint(POINT_LEVEL_STEP) - GetPoint(POINT_STAT));
  6479.  
  6480. if(iLv <= 90)
  6481. PointChange(POINT_STAT, ((MINMAX(1, iLv, 90) - 1) * 3) + GetPoint(POINT_LEVEL_STEP) - GetPoint(POINT_STAT));
  6482. else
  6483. PointChange(POINT_STAT, 270 - GetPoint(POINT_STAT));
  6484.  
  6485. ComputePoints();
  6486.  
  6487. PointChange(POINT_HP, GetMaxHP() - GetHP());
  6488. PointChange(POINT_SP, GetMaxSP() - GetSP());
  6489.  
  6490. PointsPacket();
  6491.  
  6492. LogManager::instance().CharLog(this, 0, "RESET_POINT", "");
  6493. }
  6494.  
  6495. bool CHARACTER::IsChangeAttackPosition(LPCHARACTER target) const
  6496. {
  6497. if (!IsNPC())
  6498. return true;
  6499.  
  6500. DWORD dwChangeTime = AI_CHANGE_ATTACK_POISITION_TIME_NEAR;
  6501.  
  6502. if (DISTANCE_APPROX(GetX() - target->GetX(), GetY() - target->GetY()) >
  6503. AI_CHANGE_ATTACK_POISITION_DISTANCE + GetMobAttackRange())
  6504. dwChangeTime = AI_CHANGE_ATTACK_POISITION_TIME_FAR;
  6505.  
  6506. return get_dword_time() - m_dwLastChangeAttackPositionTime > dwChangeTime;
  6507. }
  6508.  
  6509. void CHARACTER::GiveRandomSkillBook()
  6510. {
  6511. LPITEM item = AutoGiveItem(50300);
  6512.  
  6513. if (NULL != item)
  6514. {
  6515. BYTE bJob = 0;
  6516.  
  6517. if (!number(0, 1))
  6518. bJob = GetJob() + 1;
  6519.  
  6520. DWORD dwSkillVnum = 0;
  6521.  
  6522. do
  6523. {
  6524. dwSkillVnum = number(1, 111);
  6525. const CSkillProto* pkSk = CSkillManager::instance().Get(dwSkillVnum);
  6526.  
  6527. if (NULL == pkSk)
  6528. continue;
  6529.  
  6530. if (bJob && bJob != pkSk->dwType)
  6531. continue;
  6532.  
  6533. break;
  6534.  
  6535. } while (true);
  6536.  
  6537. item->SetSocket(0, dwSkillVnum);
  6538. }
  6539. }
  6540.  
  6541. void CHARACTER::ReviveInvisible(int iDur)
  6542. {
  6543. AddAffect(AFFECT_REVIVE_INVISIBLE, POINT_NONE, 0, AFF_REVIVE_INVISIBLE, iDur, 0, true);
  6544. }
  6545.  
  6546. void CHARACTER::ToggleMonsterLog()
  6547. {
  6548. m_bMonsterLog = !m_bMonsterLog;
  6549.  
  6550. if (m_bMonsterLog)
  6551. {
  6552. CHARACTER_MANAGER::instance().RegisterForMonsterLog(this);
  6553. }
  6554.  
  6555. else
  6556. {
  6557. CHARACTER_MANAGER::instance().UnregisterForMonsterLog(this);
  6558. }
  6559. }
  6560.  
  6561. void CHARACTER::SetGuild(CGuild* pGuild)
  6562. {
  6563. if (m_pGuild != pGuild)
  6564. {
  6565. m_pGuild = pGuild;
  6566. UpdatePacket();
  6567. }
  6568. }
  6569.  
  6570. void CHARACTER::BeginStateEmpty()
  6571. {
  6572. MonsterLog("!");
  6573. }
  6574.  
  6575. void CHARACTER::EffectPacket(int enumEffectType)
  6576. {
  6577. TPacketGCSpecialEffect p;
  6578.  
  6579. p.header = HEADER_GC_SEPCIAL_EFFECT;
  6580. p.type = enumEffectType;
  6581. p.vid = GetVID();
  6582.  
  6583. PacketAround(&p, sizeof(TPacketGCSpecialEffect));
  6584. }
  6585.  
  6586. void CHARACTER::SpecificEffectPacket(const char filename[MAX_EFFECT_FILE_NAME])
  6587. {
  6588. TPacketGCSpecificEffect p;
  6589.  
  6590. p.header = HEADER_GC_SPECIFIC_EFFECT;
  6591. p.vid = GetVID();
  6592. memcpy (p.effect_file, filename, MAX_EFFECT_FILE_NAME);
  6593.  
  6594. PacketAround(&p, sizeof(TPacketGCSpecificEffect));
  6595. }
  6596.  
  6597. void CHARACTER::MonsterChat(BYTE bMonsterChatType)
  6598. {
  6599. if (IsPC())
  6600. return;
  6601.  
  6602. char sbuf[256+1];
  6603.  
  6604. if (IsMonster())
  6605. {
  6606. if (number(0, 60))
  6607. return;
  6608.  
  6609. snprintf(sbuf, sizeof(sbuf), "(locale.monster_chat[%i] and locale.monster_chat[%i][%d] or '')",
  6610.  
  6611. GetRaceNum(), GetRaceNum(), bMonsterChatType*3 + number(1, 3));
  6612. }
  6613. else
  6614. {
  6615. if (bMonsterChatType != MONSTER_CHAT_WAIT)
  6616. return;
  6617.  
  6618. if (IsGuardNPC())
  6619. {
  6620. if (number(0, 6))
  6621. return;
  6622. }
  6623.  
  6624. else
  6625. {
  6626. if (number(0, 30))
  6627. return;
  6628. }
  6629.  
  6630. snprintf(sbuf, sizeof(sbuf), "(locale.monster_chat[%i] and locale.monster_chat[%i][number(1, table.getn(locale.monster_chat[%i]))] or '')", GetRaceNum(), GetRaceNum(), GetRaceNum());
  6631. }
  6632.  
  6633. std::string text = quest::ScriptToString(sbuf);
  6634.  
  6635. if (text.empty())
  6636. return;
  6637.  
  6638. struct packet_chat pack_chat;
  6639.  
  6640. pack_chat.header = HEADER_GC_CHAT;
  6641. pack_chat.size = sizeof(struct packet_chat) + text.size() + 1;
  6642. pack_chat.type = CHAT_TYPE_TALKING;
  6643. pack_chat.id = GetVID();
  6644. pack_chat.bEmpire = 0;
  6645.  
  6646. TEMP_BUFFER buf;
  6647. buf.write(&pack_chat, sizeof(struct packet_chat));
  6648. buf.write(text.c_str(), text.size() + 1);
  6649.  
  6650. PacketAround(buf.read_peek(), buf.size());
  6651. }
  6652.  
  6653. void CHARACTER::SetQuestNPCID(DWORD vid)
  6654. {
  6655. m_dwQuestNPCVID = vid;
  6656. }
  6657.  
  6658. LPCHARACTER CHARACTER::GetQuestNPC() const
  6659. {
  6660. return CHARACTER_MANAGER::instance().Find(m_dwQuestNPCVID);
  6661. }
  6662.  
  6663. void CHARACTER::SetQuestItemPtr(LPITEM item)
  6664. {
  6665. m_pQuestItem = item;
  6666. }
  6667.  
  6668. void CHARACTER::ClearQuestItemPtr()
  6669. {
  6670. m_pQuestItem = NULL;
  6671. }
  6672.  
  6673. LPITEM CHARACTER::GetQuestItemPtr() const
  6674. {
  6675. return m_pQuestItem;
  6676. }
  6677.  
  6678. LPDUNGEON CHARACTER::GetDungeonForce() const
  6679. {
  6680. if (m_lWarpMapIndex > 10000)
  6681. return CDungeonManager::instance().FindByMapIndex(m_lWarpMapIndex);
  6682.  
  6683. return m_pkDungeon;
  6684. }
  6685.  
  6686. void CHARACTER::SetBlockMode(BYTE bFlag)
  6687. {
  6688. m_pointsInstant.bBlockMode = bFlag;
  6689.  
  6690. ChatPacket(CHAT_TYPE_COMMAND, "setblockmode %d", m_pointsInstant.bBlockMode);
  6691.  
  6692. SetQuestFlag("game_option.block_exchange", bFlag & BLOCK_EXCHANGE ? 1 : 0);
  6693. SetQuestFlag("game_option.block_party_invite", bFlag & BLOCK_PARTY_INVITE ? 1 : 0);
  6694. SetQuestFlag("game_option.block_guild_invite", bFlag & BLOCK_GUILD_INVITE ? 1 : 0);
  6695. SetQuestFlag("game_option.block_whisper", bFlag & BLOCK_WHISPER ? 1 : 0);
  6696. SetQuestFlag("game_option.block_messenger_invite", bFlag & BLOCK_MESSENGER_INVITE ? 1 : 0);
  6697. SetQuestFlag("game_option.block_party_request", bFlag & BLOCK_PARTY_REQUEST ? 1 : 0);
  6698.  
  6699. #ifdef __VIEW_EQUIP__
  6700. SetQuestFlag("game_option.block_view_equipment", bFlag & BLOCK_VIEW_EQUIPMENT ? 1 : 0);
  6701. #endif
  6702.  
  6703. }
  6704.  
  6705. void CHARACTER::SetBlockModeForce(BYTE bFlag)
  6706. {
  6707. m_pointsInstant.bBlockMode = bFlag;
  6708. ChatPacket(CHAT_TYPE_COMMAND, "setblockmode %d", m_pointsInstant.bBlockMode);
  6709. }
  6710.  
  6711. bool CHARACTER::IsGuardNPC() const
  6712. {
  6713. return IsNPC() && (GetRaceNum() == 11000 || GetRaceNum() == 11002 || GetRaceNum() == 11004);
  6714. }
  6715.  
  6716. int CHARACTER::GetPolymorphPower() const
  6717. {
  6718. if (test_server)
  6719. {
  6720. int value = quest::CQuestManager::instance().GetEventFlag("poly");
  6721. if (value)
  6722. return value;
  6723. }
  6724.  
  6725. return aiPolymorphPowerByLevel[MINMAX(0, GetSkillLevel(SKILL_POLYMORPH), 40)];
  6726. }
  6727.  
  6728. void CHARACTER::SetPolymorph(DWORD dwRaceNum, bool bMaintainStat)
  6729. {
  6730. if (dwRaceNum < JOB_MAX_NUM)
  6731. {
  6732. dwRaceNum = 0;
  6733. bMaintainStat = false;
  6734. }
  6735.  
  6736. if (m_dwPolymorphRace == dwRaceNum)
  6737. return;
  6738.  
  6739. m_bPolyMaintainStat = bMaintainStat;
  6740. m_dwPolymorphRace = dwRaceNum;
  6741.  
  6742. sys_log(0, "POLYMORPH: %s race %u ", GetName(), dwRaceNum);
  6743.  
  6744. if (dwRaceNum != 0)
  6745. StopRiding();
  6746.  
  6747. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  6748. m_afAffectFlag.Set(AFF_SPAWN);
  6749.  
  6750. ViewReencode();
  6751.  
  6752. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  6753.  
  6754. if (!bMaintainStat)
  6755. {
  6756. PointChange(POINT_ST, 0);
  6757. PointChange(POINT_DX, 0);
  6758. PointChange(POINT_IQ, 0);
  6759. PointChange(POINT_HT, 0);
  6760. }
  6761.  
  6762. SetValidComboInterval(0);
  6763. SetComboSequence(0);
  6764.  
  6765. ComputeBattlePoints();
  6766. }
  6767.  
  6768. int CHARACTER::GetQuestFlag(const std::string& flag) const
  6769. {
  6770. quest::CQuestManager& q = quest::CQuestManager::instance();
  6771. quest::PC* pPC = q.GetPC(GetPlayerID());
  6772. if(!pPC)
  6773. {
  6774. // sys_err("Nullpointer in CHARACTER::GetQuestFlag %lu", GetPlayerID());
  6775. return 0;
  6776. }
  6777.  
  6778. return pPC->GetFlag(flag);
  6779. }
  6780.  
  6781. void CHARACTER::SetQuestFlag(const std::string& flag, int value)
  6782. {
  6783. quest::CQuestManager& q = quest::CQuestManager::instance();
  6784. quest::PC* pPC = q.GetPC(GetPlayerID());
  6785. if(!pPC)
  6786. {
  6787. // sys_err("Nullpointer in CHARACTER::GetQuestFlag %lu", GetPlayerID());
  6788. return;
  6789. }
  6790.  
  6791. pPC->SetFlag(flag, value);
  6792. }
  6793.  
  6794. void CHARACTER::DetermineDropMetinStone()
  6795. {
  6796. const int METIN_STONE_NUM = 14;
  6797. static DWORD c_adwMetin[METIN_STONE_NUM] =
  6798. {
  6799. 28030,
  6800. 28031,
  6801. 28032,
  6802. 28033,
  6803. 28034,
  6804. 28035,
  6805. 28036,
  6806. 28037,
  6807. 28038,
  6808. 28039,
  6809. 28040,
  6810. 28041,
  6811. 28042,
  6812. 28043,
  6813. };
  6814.  
  6815. DWORD stone_num = GetRaceNum();
  6816. int idx = std::lower_bound(aStoneDrop, aStoneDrop+STONE_INFO_MAX_NUM, stone_num) - aStoneDrop;
  6817.  
  6818. if (idx >= STONE_INFO_MAX_NUM || aStoneDrop[idx].dwMobVnum != stone_num)
  6819. {
  6820. m_dwDropMetinStone = 0;
  6821. }
  6822.  
  6823. else
  6824. {
  6825. const SStoneDropInfo & info = aStoneDrop[idx];
  6826. m_bDropMetinStonePct = info.iDropPct;
  6827. {
  6828. m_dwDropMetinStone = c_adwMetin[number(0, METIN_STONE_NUM - 1)];
  6829. int iGradePct = number(1, 100);
  6830.  
  6831. for (int iStoneLevel = 0; iStoneLevel < STONE_LEVEL_MAX_NUM; iStoneLevel ++)
  6832. {
  6833. int iLevelGradePortion = info.iLevelPct[iStoneLevel];
  6834. if (iGradePct <= iLevelGradePortion)
  6835. {
  6836. break;
  6837. }
  6838.  
  6839. else
  6840. {
  6841. iGradePct -= iLevelGradePortion;
  6842. m_dwDropMetinStone += 100;
  6843. }
  6844. }
  6845. }
  6846. }
  6847. }
  6848.  
  6849. #ifdef __VIEW_EQUIP__
  6850. void CHARACTER::SendEquipment(LPCHARACTER ch)
  6851. {
  6852. TPacketViewEquip p;
  6853. p.header = HEADER_GC_VIEW_EQUIP;
  6854. p.vid = GetVID();
  6855.  
  6856. int pos[26] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33};
  6857.  
  6858. for (int i = 0; i < 26; i++)
  6859. {
  6860. LPITEM item = GetWear(pos[i]);
  6861. if (item)
  6862. {
  6863. p.equips[i].vnum = item->GetVnum();
  6864. p.equips[i].count = item->GetCount();
  6865.  
  6866. thecore_memcpy(p.equips[i].alSockets, item->GetSockets(), sizeof(p.equips[i].alSockets));
  6867. thecore_memcpy(p.equips[i].aAttr, item->GetAttributes(), sizeof(p.equips[i].aAttr));
  6868. }
  6869.  
  6870. else
  6871. {
  6872. p.equips[i].vnum = 0;
  6873. }
  6874. }
  6875.  
  6876. ch->GetDesc()->Packet(&p, sizeof(p));
  6877.  
  6878. }
  6879. #else
  6880. void CHARACTER::SendEquipment(LPCHARACTER ch)
  6881. {
  6882. TPacketViewEquip p;
  6883. p.header = HEADER_GC_VIEW_EQUIP;
  6884. p.vid = GetVID();
  6885. for (int i = 0; i<WEAR_MAX_NUM; i++)
  6886. {
  6887. LPITEM item = GetWear(i);
  6888. if (item)
  6889. {
  6890. p.equips[i].vnum = item->GetVnum();
  6891. p.equips[i].count = item->GetCount();
  6892.  
  6893. thecore_memcpy(p.equips[i].alSockets, item->GetSockets(), sizeof(p.equips[i].alSockets));
  6894. thecore_memcpy(p.equips[i].aAttr, item->GetAttributes(), sizeof(p.equips[i].aAttr));
  6895. }
  6896.  
  6897. else
  6898. {
  6899. p.equips[i].vnum = 0;
  6900. }
  6901. }
  6902.  
  6903. ch->GetDesc()->Packet(&p, sizeof(p));
  6904. }
  6905. #endif
  6906.  
  6907. bool CHARACTER::CanSummon(int iLeaderShip)
  6908. {
  6909. return ((iLeaderShip >= 20) || ((iLeaderShip >= 12) && ((m_dwLastDeadTime + 180) > get_dword_time())));
  6910. }
  6911.  
  6912. void CHARACTER::MountVnum(DWORD vnum)
  6913. {
  6914. if (m_dwMountVnum == vnum)
  6915. return;
  6916.  
  6917. if ((m_dwMountVnum != 0)&&(vnum!=0))
  6918. MountVnum(0);
  6919.  
  6920. m_dwMountVnum = vnum;
  6921. m_dwMountTime = get_dword_time();
  6922.  
  6923. if (m_bIsObserver)
  6924. return;
  6925.  
  6926. m_posDest.x = m_posStart.x = GetX();
  6927. m_posDest.y = m_posStart.y = GetY();
  6928.  
  6929. EncodeInsertPacket(this);
  6930.  
  6931. ENTITY_MAP::iterator it = m_map_view.begin();
  6932.  
  6933. while (it != m_map_view.end())
  6934. {
  6935. LPENTITY entity = (it++)->first;
  6936.  
  6937. //EncodeRemovePacket(entity);
  6938. //if (!m_bIsObserver)
  6939. EncodeInsertPacket(entity);
  6940.  
  6941. //if (!entity->IsObserverMode())
  6942. // entity->EncodeInsertPacket(this);
  6943. }
  6944.  
  6945. SetValidComboInterval(0);
  6946. SetComboSequence(0);
  6947.  
  6948. ComputePoints();
  6949. }
  6950.  
  6951. namespace {
  6952. class FuncCheckWarp
  6953. {
  6954. public:
  6955. FuncCheckWarp(LPCHARACTER pkWarp)
  6956. {
  6957. m_lTargetY = 0;
  6958. m_lTargetX = 0;
  6959.  
  6960. m_lX = pkWarp->GetX();
  6961. m_lY = pkWarp->GetY();
  6962.  
  6963. m_bInvalid = false;
  6964. m_bEmpire = pkWarp->GetEmpire();
  6965.  
  6966. char szTmp[64];
  6967.  
  6968. if (3 != sscanf(pkWarp->GetName(), " %s %ld %ld ", szTmp, &m_lTargetX, &m_lTargetY))
  6969. {
  6970. if (number(1, 100) < 5)
  6971. sys_err("Warp NPC name wrong : vnum(%d) name(%s)", pkWarp->GetRaceNum(), pkWarp->GetName());
  6972.  
  6973. m_bInvalid = true;
  6974.  
  6975. return;
  6976. }
  6977.  
  6978. m_lTargetX *= 100;
  6979. m_lTargetY *= 100;
  6980.  
  6981. m_bUseWarp = true;
  6982.  
  6983. if (pkWarp->IsGoto())
  6984. {
  6985. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(pkWarp->GetMapIndex());
  6986. m_lTargetX += pkSectreeMap->m_setting.iBaseX;
  6987. m_lTargetY += pkSectreeMap->m_setting.iBaseY;
  6988. m_bUseWarp = false;
  6989. }
  6990. }
  6991.  
  6992. bool Valid()
  6993. {
  6994. return !m_bInvalid;
  6995. }
  6996.  
  6997. void operator () (LPENTITY ent)
  6998. {
  6999. if (!Valid())
  7000. return;
  7001.  
  7002. if (!ent->IsType(ENTITY_CHARACTER))
  7003. return;
  7004.  
  7005. LPCHARACTER pkChr = (LPCHARACTER) ent;
  7006.  
  7007. if (!pkChr->IsPC())
  7008. return;
  7009.  
  7010. int iDist = DISTANCE_APPROX(pkChr->GetX() - m_lX, pkChr->GetY() - m_lY);
  7011.  
  7012. if (iDist > 300)
  7013. return;
  7014.  
  7015. if (m_bEmpire && pkChr->GetEmpire() && m_bEmpire != pkChr->GetEmpire())
  7016. return;
  7017.  
  7018. if (pkChr->IsHack())
  7019. return;
  7020.  
  7021. if (!pkChr->CanHandleItem(false, true))
  7022. return;
  7023.  
  7024. if (m_bUseWarp)
  7025. pkChr->WarpSet(m_lTargetX, m_lTargetY);
  7026.  
  7027. else
  7028. {
  7029. pkChr->Show(pkChr->GetMapIndex(), m_lTargetX, m_lTargetY);
  7030. pkChr->Stop();
  7031. }
  7032. }
  7033.  
  7034. bool m_bInvalid;
  7035. bool m_bUseWarp;
  7036.  
  7037. long m_lX;
  7038. long m_lY;
  7039. long m_lTargetX;
  7040. long m_lTargetY;
  7041.  
  7042. BYTE m_bEmpire;
  7043. };
  7044. }
  7045.  
  7046. EVENTFUNC(warp_npc_event)
  7047. {
  7048. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  7049. if ( info == NULL )
  7050. {
  7051. sys_err( "warp_npc_event> <Factor> Null pointer" );
  7052. return 0;
  7053. }
  7054.  
  7055. LPCHARACTER ch = info->ch;
  7056.  
  7057. if (ch == NULL)
  7058. {
  7059. return 0;
  7060. }
  7061.  
  7062. if (!ch->GetSectree())
  7063. {
  7064. ch->m_pkWarpNPCEvent = NULL;
  7065. return 0;
  7066. }
  7067.  
  7068. FuncCheckWarp f(ch);
  7069. if (f.Valid())
  7070. ch->GetSectree()->ForEachAround(f);
  7071.  
  7072. return passes_per_sec / 2;
  7073. }
  7074.  
  7075. void CHARACTER::StartWarpNPCEvent()
  7076. {
  7077. if (m_pkWarpNPCEvent)
  7078. return;
  7079.  
  7080. if (!IsWarp() && !IsGoto())
  7081. return;
  7082.  
  7083. char_event_info* info = AllocEventInfo<char_event_info>();
  7084.  
  7085. info->ch = this;
  7086.  
  7087. m_pkWarpNPCEvent = event_create(warp_npc_event, info, passes_per_sec / 2);
  7088. }
  7089.  
  7090. void CHARACTER::SyncPacket()
  7091. {
  7092. TEMP_BUFFER buf;
  7093.  
  7094. TPacketCGSyncPositionElement elem;
  7095.  
  7096. elem.dwVID = GetVID();
  7097. elem.lX = GetX();
  7098. elem.lY = GetY();
  7099.  
  7100. TPacketGCSyncPosition pack;
  7101.  
  7102. pack.bHeader = HEADER_GC_SYNC_POSITION;
  7103. pack.wSize = sizeof(TPacketGCSyncPosition) + sizeof(elem);
  7104.  
  7105. buf.write(&pack, sizeof(pack));
  7106. buf.write(&elem, sizeof(elem));
  7107.  
  7108. PacketAround(buf.read_peek(), buf.size());
  7109. }
  7110.  
  7111. LPCHARACTER CHARACTER::GetMarryPartner() const
  7112. {
  7113. return m_pkChrMarried;
  7114. }
  7115.  
  7116. void CHARACTER::SetMarryPartner(LPCHARACTER ch)
  7117. {
  7118. m_pkChrMarried = ch;
  7119. }
  7120.  
  7121. #ifdef SET_LEVEL_FIRST_LOGIN
  7122. void CHARACTER::FirstLogin()
  7123. {
  7124. if (!GetQuestFlag("start.first_login"))
  7125. {
  7126. ResetPoint(MINMAX(1, 99, PLAYER_MAX_LEVEL_CONST)); /* Aici schimbi acel 99 cu nivelul pe care vrei sa il primeasca playerii la prima logare pe server */
  7127. SetQuestFlag("start.first_login", 1);
  7128. }
  7129. }
  7130. #endif
  7131.  
  7132. int CHARACTER::GetMarriageBonus(DWORD dwItemVnum, bool bSum)
  7133. {
  7134. if (IsNPC())
  7135. return 0;
  7136.  
  7137. marriage::TMarriage* pMarriage = marriage::CManager::instance().Get(GetPlayerID());
  7138.  
  7139. if (!pMarriage)
  7140. return 0;
  7141.  
  7142. return pMarriage->GetBonus(dwItemVnum, bSum, this);
  7143. }
  7144.  
  7145. void CHARACTER::ConfirmWithMsg(const char* szMsg, int iTimeout, DWORD dwRequestPID)
  7146. {
  7147. if (!IsPC())
  7148. return;
  7149.  
  7150. TPacketGCQuestConfirm p;
  7151.  
  7152. p.header = HEADER_GC_QUEST_CONFIRM;
  7153. p.requestPID = dwRequestPID;
  7154. p.timeout = iTimeout;
  7155. strlcpy(p.msg, szMsg, sizeof(p.msg));
  7156.  
  7157. GetDesc()->Packet(&p, sizeof(p));
  7158. }
  7159.  
  7160. int CHARACTER::GetPremiumRemainSeconds(BYTE bType) const
  7161. {
  7162. if (bType >= PREMIUM_MAX_NUM)
  7163. return 0;
  7164.  
  7165. return m_aiPremiumTimes[bType] - get_global_time();
  7166. }
  7167.  
  7168. bool CHARACTER::WarpToPID(DWORD dwPID)
  7169. {
  7170. LPCHARACTER victim;
  7171. if ((victim = (CHARACTER_MANAGER::instance().FindByPID(dwPID))))
  7172. {
  7173. int mapIdx = victim->GetMapIndex();
  7174. if (IS_SUMMONABLE_ZONE(mapIdx))
  7175. {
  7176. if (CAN_ENTER_ZONE(this, mapIdx))
  7177. {
  7178. WarpSet(victim->GetX(), victim->GetY());
  7179. }
  7180.  
  7181. else
  7182. {
  7183. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 있는 곳으로 워프할 수 없습니다."));
  7184. return false;
  7185. }
  7186. }
  7187.  
  7188. else
  7189. {
  7190. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 있는 곳으로 워프할 수 없습니다."));
  7191. return false;
  7192. }
  7193. }
  7194.  
  7195. else
  7196. {
  7197. CCI * pcci = P2P_MANAGER::instance().FindByPID(dwPID);
  7198.  
  7199. if (!pcci)
  7200. {
  7201. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 온라인 상태가 아닙니다."));
  7202. return false;
  7203. }
  7204.  
  7205. if (pcci->bChannel != g_bChannel)
  7206. {
  7207. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 %d 채널에 있습니다. (현재 채널 %d)"), pcci->bChannel, g_bChannel);
  7208. return false;
  7209. }
  7210.  
  7211. else if (false == IS_SUMMONABLE_ZONE(pcci->lMapIndex))
  7212. {
  7213. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 있는 곳으로 워프할 수 없습니다."));
  7214. return false;
  7215. }
  7216.  
  7217. else
  7218. {
  7219. if (!CAN_ENTER_ZONE(this, pcci->lMapIndex))
  7220. {
  7221. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 있는 곳으로 워프할 수 없습니다."));
  7222. return false;
  7223. }
  7224.  
  7225. TPacketGGFindPosition p;
  7226. p.header = HEADER_GG_FIND_POSITION;
  7227. p.dwFromPID = GetPlayerID();
  7228. p.dwTargetPID = dwPID;
  7229. pcci->pkDesc->Packet(&p, sizeof(TPacketGGFindPosition));
  7230.  
  7231. if (test_server)
  7232. ChatPacket(CHAT_TYPE_PARTY, "sent find position packet for teleport");
  7233. }
  7234. }
  7235.  
  7236. return true;
  7237. }
  7238.  
  7239. CGuild * CHARACTER::GetRefineGuild() const
  7240. {
  7241. LPCHARACTER chRefineNPC = CHARACTER_MANAGER::instance().Find(m_dwRefineNPCVID);
  7242.  
  7243. return (chRefineNPC ? chRefineNPC->GetGuild() : NULL);
  7244. }
  7245.  
  7246. bool CHARACTER::IsRefineThroughGuild() const
  7247. {
  7248. return GetRefineGuild() != NULL;
  7249. }
  7250.  
  7251. int CHARACTER::ComputeRefineFee(int iCost, int iMultiply) const
  7252. {
  7253. CGuild * pGuild = GetRefineGuild();
  7254. if (pGuild)
  7255. {
  7256. if (pGuild == GetGuild())
  7257. return iCost * iMultiply * 9 / 10;
  7258.  
  7259. LPCHARACTER chRefineNPC = CHARACTER_MANAGER::instance().Find(m_dwRefineNPCVID);
  7260. if (chRefineNPC && chRefineNPC->GetEmpire() != GetEmpire())
  7261. return iCost * iMultiply * 3;
  7262.  
  7263. return iCost * iMultiply;
  7264. }
  7265.  
  7266. else
  7267. return iCost;
  7268. }
  7269.  
  7270. void CHARACTER::PayRefineFee(int iTotalMoney)
  7271. {
  7272. int iFee = iTotalMoney / 10;
  7273. CGuild* pGuild = GetRefineGuild();
  7274.  
  7275. int iRemain = iTotalMoney;
  7276.  
  7277. if (pGuild)
  7278. {
  7279. if (pGuild != GetGuild())
  7280. {
  7281. pGuild->RequestDepositMoney(this, iFee);
  7282. iRemain -= iFee;
  7283. }
  7284. }
  7285.  
  7286. PointChange(POINT_GOLD, -iRemain);
  7287. }
  7288.  
  7289. bool CHARACTER::IsHack(bool bSendMsg, bool bCheckShopOwner, int limittime)
  7290. {
  7291. const int iPulse = thecore_pulse();
  7292.  
  7293. if (test_server)
  7294. bSendMsg = true;
  7295.  
  7296. if (iPulse - GetSafeboxLoadTime() < PASSES_PER_SEC(limittime))
  7297. {
  7298. if (bSendMsg)
  7299. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("창고를 연후 %d초 이내에는 다른곳으로 이동할수 없습니다."), limittime);
  7300.  
  7301. if (test_server)
  7302. ChatPacket(CHAT_TYPE_INFO, "[TestOnly]Pulse %d LoadTime %d PASS %d", iPulse, GetSafeboxLoadTime(), PASSES_PER_SEC(limittime));
  7303.  
  7304. return true;
  7305. }
  7306.  
  7307. if (bCheckShopOwner)
  7308. {
  7309. if (GetExchange() || GetMyShop() || GetShopOwner() || IsOpenSafebox() || IsCubeOpen())
  7310. {
  7311. if (bSendMsg)
  7312. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("거래창,창고 등을 연 상태에서는 다른곳으로 이동,종료 할수 없습니다"));
  7313.  
  7314. return true;
  7315. }
  7316. }
  7317.  
  7318. else
  7319. {
  7320. if (GetExchange() || GetMyShop() || IsOpenSafebox() || IsCubeOpen())
  7321. {
  7322. if (bSendMsg)
  7323. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("거래창,창고 등을 연 상태에서는 다른곳으로 이동,종료 할수 없습니다"));
  7324.  
  7325. return true;
  7326. }
  7327. }
  7328.  
  7329. if (iPulse - GetExchangeTime() < PASSES_PER_SEC(limittime))
  7330. {
  7331. if (bSendMsg)
  7332. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("거래 후 %d초 이내에는 다른지역으로 이동 할 수 없습니다."), limittime );
  7333.  
  7334. return true;
  7335. }
  7336.  
  7337. if (iPulse - GetMyShopTime() < PASSES_PER_SEC(limittime))
  7338. {
  7339. if (bSendMsg)
  7340. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("거래 후 %d초 이내에는 다른지역으로 이동 할 수 없습니다."), limittime);
  7341.  
  7342. return true;
  7343. }
  7344.  
  7345. if (iPulse - GetRefineTime() < PASSES_PER_SEC(limittime))
  7346. {
  7347. if (bSendMsg)
  7348. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("아이템 개량후 %d초 이내에는 귀환부,귀환기억부를 사용할 수 없습니다."), limittime);
  7349.  
  7350. return true;
  7351. }
  7352.  
  7353. return false;
  7354. }
  7355.  
  7356. void CHARACTER::Say(const std::string & s)
  7357. {
  7358. struct ::packet_script packet_script;
  7359.  
  7360. packet_script.header = HEADER_GC_SCRIPT;
  7361. packet_script.skin = 1;
  7362. packet_script.src_size = s.size();
  7363. packet_script.size = packet_script.src_size + sizeof(struct packet_script);
  7364.  
  7365. TEMP_BUFFER buf;
  7366.  
  7367. buf.write(&packet_script, sizeof(struct packet_script));
  7368. buf.write(&s[0], s.size());
  7369.  
  7370. if (IsPC())
  7371. {
  7372. GetDesc()->Packet(buf.read_peek(), buf.size());
  7373. }
  7374. }
  7375.  
  7376. void CHARACTER::UpdateDepositPulse()
  7377. {
  7378. m_deposit_pulse = thecore_pulse() + PASSES_PER_SEC(60*5);
  7379. }
  7380.  
  7381. bool CHARACTER::CanDeposit() const
  7382. {
  7383. return (m_deposit_pulse == 0 || (m_deposit_pulse < thecore_pulse()));
  7384. }
  7385.  
  7386. ESex GET_SEX(LPCHARACTER ch)
  7387. {
  7388. switch (ch->GetRaceNum())
  7389. {
  7390. case MAIN_RACE_WARRIOR_M:
  7391. case MAIN_RACE_SURA_M:
  7392. case MAIN_RACE_ASSASSIN_M:
  7393. case MAIN_RACE_SHAMAN_M:
  7394. return SEX_MALE;
  7395.  
  7396. case MAIN_RACE_ASSASSIN_W:
  7397. case MAIN_RACE_SHAMAN_W:
  7398. case MAIN_RACE_WARRIOR_W:
  7399. case MAIN_RACE_SURA_W:
  7400. return SEX_FEMALE;
  7401. }
  7402.  
  7403. /* default sex = male */
  7404. return SEX_MALE;
  7405. }
  7406.  
  7407. int CHARACTER::GetHPPct() const
  7408. {
  7409. if (GetMaxHP() <= 0)
  7410. return 0;
  7411.  
  7412. return (GetHP() * 100) / GetMaxHP();
  7413. }
  7414.  
  7415. bool CHARACTER::IsBerserk() const
  7416. {
  7417. if (m_pkMobInst != NULL)
  7418. return m_pkMobInst->m_IsBerserk;
  7419. else
  7420. return false;
  7421. }
  7422.  
  7423. void CHARACTER::SetBerserk(bool mode)
  7424. {
  7425. if (m_pkMobInst != NULL)
  7426. m_pkMobInst->m_IsBerserk = mode;
  7427. }
  7428.  
  7429. bool CHARACTER::IsGodSpeed() const
  7430. {
  7431. if (m_pkMobInst != NULL)
  7432. {
  7433. return m_pkMobInst->m_IsGodSpeed;
  7434. }
  7435.  
  7436. else
  7437. {
  7438. return false;
  7439. }
  7440. }
  7441.  
  7442. void CHARACTER::SetGodSpeed(bool mode)
  7443. {
  7444. if (m_pkMobInst != NULL)
  7445. {
  7446. m_pkMobInst->m_IsGodSpeed = mode;
  7447.  
  7448. if (mode == true)
  7449. {
  7450. SetPoint(POINT_ATT_SPEED, 250);
  7451. }
  7452.  
  7453. else
  7454. {
  7455. SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed);
  7456. }
  7457. }
  7458. }
  7459.  
  7460. bool CHARACTER::IsDeathBlow() const
  7461. {
  7462. if (number(1, 100) <= m_pkMobData->m_table.bDeathBlowPoint)
  7463. {
  7464. return true;
  7465. }
  7466.  
  7467. else
  7468. {
  7469. return false;
  7470. }
  7471. }
  7472.  
  7473. struct FFindReviver
  7474. {
  7475. FFindReviver()
  7476. {
  7477. pChar = NULL;
  7478. HasReviver = false;
  7479. }
  7480.  
  7481. void operator() (LPCHARACTER ch)
  7482. {
  7483. if (ch->IsMonster() != true)
  7484. {
  7485. return;
  7486. }
  7487.  
  7488. if (ch->IsReviver() == true && pChar != ch && ch->IsDead() != true)
  7489. {
  7490. if (number(1, 100) <= ch->GetMobTable().bRevivePoint)
  7491. {
  7492. HasReviver = true;
  7493. pChar = ch;
  7494. }
  7495. }
  7496. }
  7497.  
  7498. LPCHARACTER pChar;
  7499. bool HasReviver;
  7500. };
  7501.  
  7502. bool CHARACTER::HasReviverInParty() const
  7503. {
  7504. LPPARTY party = GetParty();
  7505.  
  7506. if (party != NULL)
  7507. {
  7508. if (party->GetMemberCount() == 1) return false;
  7509.  
  7510. FFindReviver f;
  7511. party->ForEachMemberPtr(f);
  7512.  
  7513. return f.HasReviver;
  7514. }
  7515.  
  7516. return false;
  7517. }
  7518.  
  7519. bool CHARACTER::IsRevive() const
  7520. {
  7521. if (m_pkMobInst != NULL)
  7522. {
  7523. return m_pkMobInst->m_IsRevive;
  7524. }
  7525.  
  7526. return false;
  7527. }
  7528.  
  7529. void CHARACTER::SetRevive(bool mode)
  7530. {
  7531. if (m_pkMobInst != NULL)
  7532. {
  7533. m_pkMobInst->m_IsRevive = mode;
  7534. }
  7535. }
  7536.  
  7537. #define IS_SPEED_HACK_PLAYER(ch) (ch->m_speed_hack_count > SPEEDHACK_LIMIT_COUNT)
  7538.  
  7539. EVENTFUNC(check_speedhack_event)
  7540. {
  7541. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  7542. if ( info == NULL )
  7543. {
  7544. sys_err( "check_speedhack_event> <Factor> Null pointer" );
  7545. return 0;
  7546. }
  7547.  
  7548. LPCHARACTER ch = info->ch;
  7549.  
  7550. if (NULL == ch || ch->IsNPC())
  7551. return 0;
  7552.  
  7553. if (IS_SPEED_HACK_PLAYER(ch))
  7554. {
  7555. LogManager::instance().SpeedHackLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(), ch->m_speed_hack_count);
  7556. }
  7557.  
  7558. ch->m_speed_hack_count = 0;
  7559.  
  7560. ch->ResetComboHackCount();
  7561.  
  7562. return PASSES_PER_SEC(60);
  7563. }
  7564.  
  7565. void CHARACTER::StartCheckSpeedHackEvent()
  7566. {
  7567. if (m_pkCheckSpeedHackEvent)
  7568. return;
  7569.  
  7570. char_event_info* info = AllocEventInfo<char_event_info>();
  7571.  
  7572. info->ch = this;
  7573.  
  7574. m_pkCheckSpeedHackEvent = event_create(check_speedhack_event, info, PASSES_PER_SEC(60)); // 1분
  7575. }
  7576.  
  7577. void CHARACTER::GoHome()
  7578. {
  7579. WarpSet(EMPIRE_START_X(GetEmpire()), EMPIRE_START_Y(GetEmpire()));
  7580. }
  7581.  
  7582. void CHARACTER::SendGuildName(CGuild* pGuild)
  7583. {
  7584. if (NULL == pGuild) return;
  7585.  
  7586. DESC *desc = GetDesc();
  7587.  
  7588. if (NULL == desc) return;
  7589. if (m_known_guild.find(pGuild->GetID()) != m_known_guild.end()) return;
  7590.  
  7591. m_known_guild.insert(pGuild->GetID());
  7592.  
  7593. TPacketGCGuildName pack;
  7594. memset(&pack, 0x00, sizeof(pack));
  7595.  
  7596. pack.header = HEADER_GC_GUILD;
  7597. pack.subheader = GUILD_SUBHEADER_GC_GUILD_NAME;
  7598. pack.size = sizeof(TPacketGCGuildName);
  7599. pack.guildID = pGuild->GetID();
  7600. memcpy(pack.guildName, pGuild->GetName(), GUILD_NAME_MAX_LEN);
  7601.  
  7602. desc->Packet(&pack, sizeof(pack));
  7603. }
  7604.  
  7605. void CHARACTER::SendGuildName(DWORD dwGuildID)
  7606. {
  7607. SendGuildName(CGuildManager::instance().FindGuild(dwGuildID));
  7608. }
  7609.  
  7610. EVENTFUNC(destroy_when_idle_event)
  7611. {
  7612. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  7613. if ( info == NULL )
  7614. {
  7615. sys_err( "destroy_when_idle_event> <Factor> Null pointer" );
  7616. return 0;
  7617. }
  7618.  
  7619. LPCHARACTER ch = info->ch;
  7620. if (ch == NULL)
  7621. {
  7622. return 0;
  7623. }
  7624.  
  7625. if (ch->GetVictim())
  7626. {
  7627. return PASSES_PER_SEC(300);
  7628. }
  7629.  
  7630. sys_log(1, "DESTROY_WHEN_IDLE: %s", ch->GetName());
  7631.  
  7632. ch->m_pkDestroyWhenIdleEvent = NULL;
  7633. M2_DESTROY_CHARACTER(ch);
  7634.  
  7635. return 0;
  7636. }
  7637.  
  7638. void CHARACTER::StartDestroyWhenIdleEvent()
  7639. {
  7640. if (m_pkDestroyWhenIdleEvent)
  7641. return;
  7642.  
  7643. char_event_info* info = AllocEventInfo<char_event_info>();
  7644.  
  7645. info->ch = this;
  7646.  
  7647. m_pkDestroyWhenIdleEvent = event_create(destroy_when_idle_event, info, PASSES_PER_SEC(300));
  7648. }
  7649.  
  7650. void CHARACTER::SetComboSequence(BYTE seq)
  7651. {
  7652. m_bComboSequence = seq;
  7653. }
  7654.  
  7655. BYTE CHARACTER::GetComboSequence() const
  7656. {
  7657. return m_bComboSequence;
  7658. }
  7659.  
  7660. void CHARACTER::SetLastComboTime(DWORD time)
  7661. {
  7662. m_dwLastComboTime = time;
  7663. }
  7664.  
  7665. DWORD CHARACTER::GetLastComboTime() const
  7666. {
  7667. return m_dwLastComboTime;
  7668. }
  7669.  
  7670. void CHARACTER::SetValidComboInterval(int interval)
  7671. {
  7672. m_iValidComboInterval = interval;
  7673. }
  7674.  
  7675. int CHARACTER::GetValidComboInterval() const
  7676. {
  7677. return m_iValidComboInterval;
  7678. }
  7679.  
  7680. BYTE CHARACTER::GetComboIndex() const
  7681. {
  7682. return m_bComboIndex;
  7683. }
  7684.  
  7685. void CHARACTER::IncreaseComboHackCount(int k)
  7686. {
  7687. m_iComboHackCount += k;
  7688.  
  7689. if (m_iComboHackCount >= 10)
  7690. {
  7691. if (GetDesc())
  7692. if (GetDesc()->DelayedDisconnect(number(2, 7)))
  7693. {
  7694. sys_log(0, "COMBO_HACK_DISCONNECT: %s count: %d", GetName(), m_iComboHackCount);
  7695. LogManager::instance().HackLog("Combo", this);
  7696. }
  7697. }
  7698. }
  7699.  
  7700. void CHARACTER::ResetComboHackCount()
  7701. {
  7702. m_iComboHackCount = 0;
  7703. }
  7704.  
  7705. void CHARACTER::SkipComboAttackByTime(int interval)
  7706. {
  7707. m_dwSkipComboAttackByTime = get_dword_time() + interval;
  7708. }
  7709.  
  7710. DWORD CHARACTER::GetSkipComboAttackByTime() const
  7711. {
  7712. return m_dwSkipComboAttackByTime;
  7713. }
  7714.  
  7715. void CHARACTER::ResetChatCounter()
  7716. {
  7717. m_bChatCounter = 0;
  7718. }
  7719.  
  7720. BYTE CHARACTER::IncreaseChatCounter()
  7721. {
  7722. return ++m_bChatCounter;
  7723. }
  7724.  
  7725. BYTE CHARACTER::GetChatCounter() const
  7726. {
  7727. return m_bChatCounter;
  7728. }
  7729.  
  7730. bool CHARACTER::IsRiding() const
  7731. {
  7732. return IsHorseRiding() || GetMountVnum();
  7733. }
  7734.  
  7735. void CHARACTER::RefreshBonusDuel()
  7736. {
  7737. ComputePoints();
  7738. PointsPacket();
  7739. UpdatePacket();
  7740. }
  7741.  
  7742. void CHARACTER::SetDuel(const char* type, int value)
  7743. {
  7744. if (!strcmp(type, "IsFight"))
  7745. {
  7746. SetQuestFlag("pvp.IsFight", value);
  7747. }
  7748. }
  7749.  
  7750. void CHARACTER::DestroyPvP()
  7751. {
  7752. if (GetDesc() != NULL)
  7753. {
  7754. int isDuel = GetQuestFlag("pvp.IsFight");
  7755.  
  7756. if (isDuel != 0)
  7757. {
  7758. SetQuestFlag("pvp.IsFight", 0);
  7759. }
  7760. }
  7761. }
  7762.  
  7763. #ifdef __TITLE_SYSTEM__
  7764. void CHARACTER::SetTitle(int iTitle, BYTE bValue)
  7765. {
  7766. assert(iTitle < TITLES_MAX_NUM);
  7767.  
  7768. int iNewTitle = POINT_TITLE + iTitle;
  7769.  
  7770. if (bValue > 0)
  7771. {
  7772. SetPoint(iNewTitle, 1);
  7773.  
  7774. sys_log(0, "|cFF00ff33[Title Info] > |h|r %s has just learn the title %d .", GetName(), iTitle);
  7775. }
  7776.  
  7777. else
  7778. {
  7779. SetPoint(iNewTitle, 0);
  7780.  
  7781. sys_log(0, "|cFF00ff33[Title Info] > |h|r %s has just unlearn the title %d .", GetName(), iTitle);
  7782. }
  7783.  
  7784. ComputePoints();
  7785. PointsPacket();
  7786. }
  7787.  
  7788. bool CHARACTER::GetTitle(int iTitle)
  7789. {
  7790. assert(iTitle < TITLES_MAX_NUM);
  7791.  
  7792. int iNewTitle = POINT_TITLE + iTitle;
  7793. bool _to_return = false;
  7794.  
  7795. if (GetPoint(iNewTitle) == 1)
  7796. _to_return = true;
  7797.  
  7798. return _to_return;
  7799. }
  7800.  
  7801. bool CHARACTER::ChooseTitle(int iTitle)
  7802. {
  7803. assert(iTitle < TITLES_MAX_NUM);
  7804.  
  7805. int iNewTitle = POINT_TITLE + iTitle;
  7806. bool _to_return = false;
  7807.  
  7808. if ((iTitle == 0) || (GetPoint(iNewTitle) == 1 && iNewTitle != POINT_TITLE))
  7809. _to_return = true;
  7810.  
  7811. if (_to_return)
  7812. {
  7813. SetPoint(POINT_TITLE, iTitle);
  7814. sys_log(0, "|cFF00ff33[Title Info] > |h|r %s has just choose to have the title %d .", GetName(), iTitle);
  7815. }
  7816.  
  7817. ComputePoints();
  7818. PointsPacket();
  7819. UpdatePacket();
  7820.  
  7821. return _to_return;
  7822. }
  7823.  
  7824. void CHARACTER::pChooseTitle(int iTitle)
  7825. {
  7826. BYTE bAnswer = 0;
  7827.  
  7828. bool bPass = false;
  7829. int iNewTitle = POINT_TITLE + iTitle;
  7830.  
  7831. if (iTitle >= TITLES_MAX_NUM || iTitle < 1)
  7832. {
  7833. bAnswer = 1;
  7834. bPass = true;
  7835. }
  7836.  
  7837. else if (iTitle == ChoosedTitle())
  7838. {
  7839. bAnswer = 2;
  7840. bPass = true;
  7841. }
  7842.  
  7843. else if (GetPoint(iNewTitle) != 1)
  7844. {
  7845. bAnswer = 3;
  7846. bPass = true;
  7847. }
  7848.  
  7849. else
  7850. bAnswer = 4;
  7851.  
  7852. if (iTitle == 0)
  7853. {
  7854. if (GetPoint(iNewTitle) != 0)
  7855. {
  7856. bAnswer = 4;
  7857. bPass = false;
  7858. }
  7859.  
  7860. else
  7861. {
  7862. bAnswer = 2;
  7863. bPass = true;
  7864. }
  7865. }
  7866.  
  7867. if (!bPass)
  7868. bPass = ChooseTitle(iTitle);
  7869.  
  7870. TPacketGGTitleInfo p;
  7871.  
  7872. p.bHeader = HEADER_GG_TITLE_ANSWER;
  7873. p.iTitle = iTitle;
  7874. p.bAnswer = bAnswer;
  7875.  
  7876. GetDesc()->Packet(&p, sizeof(TPacketGGTitleInfo));
  7877. }
  7878.  
  7879. int CHARACTER::ChoosedTitle()
  7880. {
  7881. int iChoosed = GetPoint(POINT_TITLE);
  7882. return iChoosed;
  7883. }
  7884.  
  7885. void CHARACTER::EquipTitle(LPITEM item)
  7886. {
  7887. DWORD iTitle = item->GetValue(1);
  7888. SetPoint(POINT_TITLE, iTitle);
  7889. ComputePoints();
  7890. PointsPacket();
  7891. UpdatePacket();
  7892. }
  7893.  
  7894. void CHARACTER::UnequipTitle(LPITEM item)
  7895. {
  7896. SetPoint(POINT_TITLE, 0);
  7897. ComputePoints();
  7898. PointsPacket();
  7899. UpdatePacket();
  7900. }
  7901.  
  7902. void CHARACTER::CheckTitle()
  7903. {
  7904. LPITEM item = GetWear(WEAR_ITEM_NORMAL_TITLE);
  7905. DWORD iTitle = item->GetValue(1);
  7906. SetPoint(POINT_TITLE, iTitle);
  7907. }
  7908.  
  7909. #endif
  7910.  
  7911. #ifdef ENABLE_HIDE_COSTUME_SYSTEM
  7912. int CHARACTER::GetSlotsCostume()
  7913. {
  7914. int slot_default = 1;
  7915.  
  7916. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_ACCE
  7917. slot_default += 1;
  7918. #endif
  7919.  
  7920. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_WEAPON_COSTUME
  7921. slot_default += 1;
  7922. #endif
  7923.  
  7924. return slot_default;
  7925. }
  7926.  
  7927. int CHARACTER::GetSlotDefault(int slot)
  7928. {
  7929. int slot_amor = 0;
  7930. int slot_hair = 1;
  7931. int slot_weapon = 2;
  7932. int slot_acce = 3;
  7933.  
  7934. if(slot == 0){return slot_amor;}
  7935. if(slot == 1){return slot_hair;}
  7936. if(slot == 2){return slot_weapon;}
  7937. if(slot == 3){return slot_acce;}
  7938.  
  7939. return 0;
  7940. }
  7941.  
  7942. void CHARACTER::FuncHideCostume(int slot)
  7943. {
  7944.  
  7945. if (slot <0 || slot > GetSlotsCostume())
  7946. return;
  7947.  
  7948. int part_value = 0;
  7949. int part_acce = 0;
  7950.  
  7951. bool bAdd = false;
  7952.  
  7953. char costume_hide[1024];
  7954.  
  7955. snprintf(costume_hide, sizeof(costume_hide), "hide_costume_w.hide_costume_%d", slot);
  7956.  
  7957. const CItem* pArmor;
  7958. const CItem * pWeapon;
  7959.  
  7960. LPITEM pkItem;
  7961.  
  7962. if(slot == GetSlotDefault(0))
  7963. {
  7964. pkItem = GetWear(WEAR_COSTUME_BODY);
  7965. if(!pkItem)
  7966. return;
  7967.  
  7968. if (GetQuestFlag(costume_hide) == 0)
  7969. {
  7970. SetQuestFlag(costume_hide,1);
  7971. pArmor = GetWear(WEAR_BODY);
  7972. }
  7973.  
  7974. else
  7975. {
  7976. SetQuestFlag(costume_hide,0);
  7977. pArmor = GetWear(WEAR_COSTUME_BODY);
  7978. }
  7979.  
  7980. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_TRANSMUTACION
  7981. if (NULL != pArmor)
  7982. {
  7983. if (pArmor->GetTransmutation() > 0)
  7984. {
  7985. part_value = pArmor->GetTransmutation();
  7986. }
  7987.  
  7988. else
  7989. {
  7990. part_value = pArmor->GetVnum();
  7991. }
  7992.  
  7993. }
  7994.  
  7995. else
  7996. {
  7997. part_value = GetOriginalPart(PART_MAIN);
  7998. }
  7999. #else
  8000. part_value = (NULL != pArmor) ? pArmor->GetVnum() : GetOriginalPart(PART_MAIN);
  8001. #endif
  8002.  
  8003. SetPart(PART_MAIN, part_value);
  8004. }
  8005.  
  8006. else if(slot == GetSlotDefault(1))
  8007. {
  8008.  
  8009. pkItem = GetWear(WEAR_COSTUME_HAIR);
  8010. if(!pkItem)
  8011. return;
  8012.  
  8013. if (GetQuestFlag(costume_hide) == 0)
  8014. {
  8015. SetQuestFlag(costume_hide,1);
  8016. bAdd = false;
  8017. }
  8018.  
  8019. else
  8020. {
  8021. SetQuestFlag(costume_hide,0);
  8022. bAdd = true;
  8023. }
  8024.  
  8025. LPITEM pkItem = GetWear(WEAR_COSTUME_HAIR);
  8026. if (pkItem)
  8027. {
  8028. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_TRANSMUTACION
  8029. if (pkItem->GetTransmutation() > 0)
  8030. {
  8031. TItemTable * pHair = ITEM_MANAGER::instance().GetTable(pkItem->GetTransmutation());
  8032. if (!pHair)
  8033. {
  8034. part_value = (true == bAdd) ? pkItem->GetValue(3) : 0;
  8035. }
  8036.  
  8037. else
  8038. {
  8039. part_value = (true == bAdd) ? pHair->alValues[3] : 0;
  8040. }
  8041.  
  8042. }
  8043.  
  8044. else
  8045. {
  8046. part_value = (true == bAdd) ? pkItem->GetValue(3) : 0;
  8047. }
  8048. #else
  8049. part_value = (true == bAdd) ? pkItem->GetValue(3) : 0;
  8050. #endif
  8051. }
  8052.  
  8053. else
  8054. {
  8055. part_value = 0;
  8056. }
  8057.  
  8058. SetPart(PART_HAIR, part_value);
  8059. }
  8060.  
  8061. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_ACCE
  8062. else if(slot == GetSlotDefault(3))
  8063. {
  8064. pkItem = GetWear(WEAR_COSTUME_ACCE);
  8065. if(!pkItem)
  8066. return;
  8067.  
  8068. if (GetQuestFlag(costume_hide) == 0)
  8069. {
  8070. SetQuestFlag(costume_hide,1);
  8071. bAdd = false;
  8072. }
  8073.  
  8074. else
  8075. {
  8076. SetQuestFlag(costume_hide,0);
  8077. bAdd = true;
  8078. }
  8079.  
  8080. if (pkItem){
  8081. part_value = pkItem->GetVnum();
  8082. part_value -= 85000;
  8083.  
  8084. if (pkItem->GetSocket(ACCE_ABSORPTION_SOCKET) >= ACCE_EFFECT_FROM_ABS)
  8085. {
  8086. part_value += 2000;
  8087. }
  8088.  
  8089. part_value = (bAdd == true) ? part_value : 0;
  8090. }
  8091.  
  8092. SetPart(PART_ACCE, part_value);
  8093. }
  8094. #endif
  8095.  
  8096. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_WEAPON_COSTUME
  8097. else if(slot == GetSlotDefault(2))
  8098. {
  8099.  
  8100. pkItem = GetWear(WEAR_COSTUME_WEAPON);
  8101. if(!pkItem)
  8102. return;
  8103.  
  8104. if (GetQuestFlag(costume_hide) == 0)
  8105. {
  8106. SetQuestFlag(costume_hide,1);
  8107. pWeapon = GetWear(WEAR_WEAPON);
  8108. }
  8109.  
  8110. else
  8111. {
  8112. SetQuestFlag(costume_hide,0);
  8113. pWeapon = GetWear(WEAR_COSTUME_WEAPON);
  8114. }
  8115.  
  8116. if (NULL != pWeapon)
  8117. {
  8118. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_TRANSMUTACION
  8119. if (pWeapon->GetTransmutation() > 0)
  8120. {
  8121. part_value = pWeapon->GetTransmutation();
  8122. }
  8123.  
  8124. else
  8125. {
  8126. part_value = pWeapon->GetVnum();
  8127. }
  8128. #else
  8129. part_value = pWeapon->GetVnum();
  8130. #endif
  8131. }
  8132.  
  8133. else
  8134. {
  8135. part_value = GetOriginalPart(PART_WEAPON);
  8136. }
  8137.  
  8138. SetPart(PART_WEAPON, part_value);
  8139. }
  8140. #endif
  8141.  
  8142. FuncHideCostumeLoad();
  8143. UpdatePacket();
  8144.  
  8145. }
  8146.  
  8147. void CHARACTER::FuncHideCostumeLoad()
  8148. {
  8149. char costume_hide[1024];
  8150. ChatPacket(CHAT_TYPE_COMMAND,"COSTUME_HIDE_CLEAR");
  8151.  
  8152. for (int i = 0; i < GetSlotsCostume()+1; ++i)
  8153. {
  8154. snprintf(costume_hide, sizeof(costume_hide), "hide_costume_w.hide_costume_%d", i);
  8155. ChatPacket(CHAT_TYPE_COMMAND,"COSTUME_HIDE_LIST %d %d",i,GetQuestFlag(costume_hide));
  8156. }
  8157.  
  8158. ChatPacket(CHAT_TYPE_COMMAND,"COSTUME_HIDE_LOAD");
  8159. }
  8160.  
  8161. void CHARACTER::SetHideCostumeUpdate()
  8162. {
  8163. CItem* body_costume = GetWear(WEAR_COSTUME_BODY);
  8164.  
  8165. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_ACCE
  8166. CItem* acce_costume = GetWear(WEAR_COSTUME_ACCE);
  8167. #endif
  8168. CItem* hair_costume = GetWear(WEAR_COSTUME_HAIR);
  8169.  
  8170. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_WEAPON_COSTUME
  8171. CItem* weapon_costume = GetWear(WEAR_COSTUME_WEAPON);
  8172. #endif
  8173.  
  8174. if (GetHideCostume(GetSlotDefault(0)) == 1)
  8175. {
  8176. CItem* body_armor = GetWear(WEAR_BODY);
  8177.  
  8178. if (body_costume)
  8179. {
  8180. if (body_armor)
  8181. {
  8182.  
  8183. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_TRANSMUTACION
  8184. if (body_armor->GetTransmutation() > 0)
  8185. {
  8186. SetPart(PART_MAIN, body_armor->GetTransmutation());
  8187. }
  8188.  
  8189. else
  8190. {
  8191. SetPart(PART_MAIN, body_armor->GetVnum());
  8192. }
  8193. #else
  8194. SetPart(PART_MAIN, body_armor->GetVnum());
  8195. #endif
  8196. }
  8197.  
  8198. else
  8199. {
  8200. SetPart(PART_MAIN, GetOriginalPart(PART_MAIN));
  8201. }
  8202. }
  8203. }
  8204.  
  8205. if (GetHideCostume(GetSlotDefault(1)) == 1)
  8206. {
  8207. if (hair_costume){
  8208. SetPart(PART_HAIR, 0);
  8209. }
  8210. }
  8211.  
  8212. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_ACCE
  8213. if (GetHideCostume(GetSlotDefault(3)) == 1)
  8214. {
  8215. if (acce_costume)
  8216. {
  8217. SetPart(PART_ACCE, 0);
  8218. }
  8219. }
  8220. #endif
  8221.  
  8222. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_WEAPON_COSTUME
  8223. if (GetHideCostume(GetSlotDefault(2)) == 1)
  8224. {
  8225. CItem* body_weapon = GetWear(WEAR_WEAPON);
  8226.  
  8227. if (weapon_costume)
  8228. {
  8229. if (body_weapon)
  8230. {
  8231. #ifdef ENABLE_HIDE_COSTUME_SYSTEM_TRANSMUTACION
  8232. if (body_weapon->GetTransmutation() > 0)
  8233. {
  8234. SetPart(PART_WEAPON, body_weapon->GetTransmutation());
  8235. }
  8236.  
  8237. else
  8238. {
  8239. SetPart(PART_WEAPON, body_weapon->GetVnum());
  8240. }
  8241. #else
  8242. SetPart(PART_WEAPON, body_weapon->GetVnum());
  8243. #endif
  8244. }
  8245.  
  8246. else
  8247. {
  8248. SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON));
  8249. }
  8250. }
  8251. }
  8252. #endif
  8253.  
  8254. }
  8255.  
  8256. int CHARACTER::GetHideCostume(int wear) const
  8257. {
  8258. char costume_hide[1024];
  8259. snprintf(costume_hide, sizeof(costume_hide), "hide_costume_w.hide_costume_%d", wear);
  8260.  
  8261. return GetQuestFlag(costume_hide);
  8262. }
  8263. #endif
  8264.  
  8265. #ifdef __EQUIP_RESTRICT_SYSTEM__
  8266. bool CHARACTER::IsEquipRestricted()
  8267. {
  8268. return GetQuestFlag("equip.restricted");
  8269. }
  8270. #endif
  8271.  
  8272. #ifdef ENABLE_SORT_INVEN
  8273. void CHARACTER::SortInven(BYTE option)
  8274. {
  8275. if (IsDead())
  8276. return;
  8277.  
  8278. if (GetLastSortTime() > get_global_time())
  8279. {
  8280. ChatPacket(CHAT_TYPE_INFO, "|cFF00ff33[Sortare Info] > |h|r You need to wait %d sec .", GetLastSortTime() - get_global_time());
  8281. return;
  8282. }
  8283.  
  8284. std::vector<LPITEM> all;
  8285. LPITEM myitems;
  8286. const auto size = static_cast<WORD>(INVENTORY_MAX_NUM);
  8287.  
  8288. for (WORD i = 0; i < size; ++i)
  8289. {
  8290. if (myitems = GetInventoryItem(i))
  8291. {
  8292. all.emplace_back(myitems);
  8293. myitems->RemoveFromCharacter();
  8294. SyncQuickslot(QUICKSLOT_TYPE_ITEM, static_cast<BYTE>(i), 255);
  8295. }
  8296. }
  8297.  
  8298. if (all.empty())
  8299. return;
  8300.  
  8301. std::sort(all.begin(), all.end(), [option](const LPITEM i1, const LPITEM i2)
  8302. {
  8303. switch (option)
  8304. {
  8305. case 2:
  8306. return i1->CustomSort() == i2->CustomSort() ? i1->GetSubType() < i2->GetSubType() : i1->CustomSort() < i2->CustomSort();
  8307.  
  8308. case 3:
  8309. return i1->GetLevelLimit() == i2->GetLevelLimit() ? i1->GetSubType() < i2->GetSubType() : i1->GetLevelLimit() > i2->GetLevelLimit();
  8310.  
  8311. default:
  8312. return std::strcmp(i1->GetName(), i2->GetName()) < 0;
  8313. }
  8314. });
  8315.  
  8316. for (const auto& getitem : all)
  8317. {
  8318. const auto table = ITEM_MANAGER::instance().GetTable(getitem->GetVnum());
  8319.  
  8320. if (!table)
  8321. continue;
  8322.  
  8323. static const std::initializer_list<DWORD> out = { ITEM_AUTO_HP_RECOVERY_S, ITEM_AUTO_HP_RECOVERY_M, ITEM_AUTO_HP_RECOVERY_L, ITEM_AUTO_HP_RECOVERY_X, ITEM_AUTO_SP_RECOVERY_S, ITEM_AUTO_SP_RECOVERY_M, ITEM_AUTO_SP_RECOVERY_L, ITEM_AUTO_SP_RECOVERY_X };
  8324. if (table->dwFlags & ITEM_FLAG_STACKABLE && table->bType != ITEM_BLEND && std::find(out.begin(), out.end(), getitem->GetVnum()) == out.end())
  8325. {
  8326. AutoGiveItem(getitem->GetVnum(), getitem->GetCount(), -1, false);
  8327. M2_DESTROY_ITEM(getitem);
  8328. }
  8329.  
  8330. else
  8331. AutoGiveItem(getitem);
  8332. };
  8333.  
  8334. SetLastSortTime(get_global_time() + 15);
  8335. }
  8336. #endif
  8337.  
  8338. #ifdef ENABLE_COINS_SYSTEM
  8339. #define VOUCHER_NUM 7
  8340.  
  8341. const DWORD cdwVoucherVnum[VOUCHER_NUM] =
  8342. {
  8343. 80000,
  8344. 80001,
  8345. 80002,
  8346. 80003,
  8347. 80004,
  8348. 80005,
  8349. 80006
  8350. };
  8351.  
  8352. const int ciVoucherCountDR[VOUCHER_NUM] =
  8353. {
  8354. 1,
  8355. 5,
  8356. 10,
  8357. 50,
  8358. 100,
  8359. 500,
  8360. 1000
  8361. };
  8362.  
  8363. void CHARACTER::SetCoins(bool bVoucher, int iCoins, DWORD dwVnum)
  8364. {
  8365. int iCount = 0;
  8366.  
  8367. for (int i = 0 ; i < VOUCHER_NUM ; i++)
  8368. {
  8369. if (dwVnum == cdwVoucherVnum[i])
  8370. {
  8371. iCount = ciVoucherCountDR[i];
  8372. break;
  8373. }
  8374. }
  8375.  
  8376. if (iCount == 0 && bVoucher == true)
  8377. return;
  8378.  
  8379. std::unique_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery("UPDATE account.account SET coins = coins + '%d' WHERE id = '%d'", bVoucher == true ? iCount : iCoins, GetDesc()->GetAccountTable().id));
  8380. bool bSucc = (pMsg->uiSQLErrno == 0);
  8381.  
  8382. if (bSucc && bVoucher == true)
  8383. {
  8384. ChatPacket(CHAT_TYPE_INFO, "|cFF00ff33[Coins Info] > |h|r You got %ld Dragon Coins .", iCount);
  8385. }
  8386.  
  8387. ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_Coins2 %d", GetCoins());
  8388. }
  8389.  
  8390. int CHARACTER::GetCoins()
  8391. {
  8392. int coins = 0;
  8393. char querySelect[256];
  8394.  
  8395. snprintf(querySelect, sizeof(querySelect), "SELECT coins FROM account.account WHERE id = '%u'", GetDesc()->GetAccountTable().id);
  8396.  
  8397. std::unique_ptr<SQLMsg> pSelectMsg(DBManager::instance().DirectQuery(querySelect));
  8398. SQLResult* resSelect = pSelectMsg->Get();
  8399.  
  8400. if (resSelect && resSelect->uiNumRows > 0)
  8401. {
  8402. MYSQL_ROW row = mysql_fetch_row(resSelect->pSQLResult);
  8403. str_to_number(coins, row[0]);
  8404. ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_Coins2 %d", coins);
  8405.  
  8406. return coins;
  8407. }
  8408. }
  8409.  
  8410. #define VOUCHER_NUM_JD 7
  8411.  
  8412. const DWORD cdwVoucherVnumjd[VOUCHER_NUM_JD] =
  8413. {
  8414. 80007,
  8415. 80008,
  8416. 80009,
  8417. 80010,
  8418. 80011,
  8419. 80012,
  8420. 80013
  8421. };
  8422.  
  8423. const int ciVoucherCountjd[VOUCHER_NUM_JD] =
  8424. {
  8425. 1,
  8426. 5,
  8427. 10,
  8428. 50,
  8429. 100,
  8430. 500,
  8431. 1000
  8432. };
  8433.  
  8434. void CHARACTER::SetJD(bool bVoucher, int iCoins, DWORD dwVnum)
  8435. {
  8436. int iCount = 0;
  8437.  
  8438. for (int i = 0 ; i < VOUCHER_NUM_JD ; i++)
  8439. {
  8440. if (dwVnum == cdwVoucherVnumjd[i])
  8441. {
  8442. iCount = ciVoucherCountjd[i];
  8443. break;
  8444. }
  8445. }
  8446.  
  8447. if (iCount == 0 && bVoucher == true)
  8448. return;
  8449.  
  8450. std::unique_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery("UPDATE account.account SET jcoins = jcoins + '%d' WHERE id = '%d'", bVoucher == true ? iCount : iCoins, GetDesc()->GetAccountTable().id));
  8451. bool bSucc = (pMsg->uiSQLErrno == 0);
  8452.  
  8453. if (bSucc && bVoucher == true)
  8454. {
  8455. ChatPacket(CHAT_TYPE_INFO, "|cFF00ff33[JD Info] > |h|r You got %ld Dragon Jetons .", iCount);
  8456. }
  8457.  
  8458. ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_JD2 %d", GetJD());
  8459. }
  8460.  
  8461. int CHARACTER::GetJD()
  8462. {
  8463. int coins = 0;
  8464. char querySelect[256];
  8465.  
  8466. snprintf(querySelect, sizeof(querySelect), "SELECT jcoins FROM account.account WHERE id = '%u'", GetDesc()->GetAccountTable().id);
  8467.  
  8468. std::unique_ptr<SQLMsg> pSelectMsg(DBManager::instance().DirectQuery(querySelect));
  8469. SQLResult* resSelect = pSelectMsg->Get();
  8470.  
  8471. if (resSelect && resSelect->uiNumRows > 0)
  8472. {
  8473. MYSQL_ROW row = mysql_fetch_row(resSelect->pSQLResult);
  8474. str_to_number(coins, row[0]);
  8475. ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_JD2 %d", coins);
  8476.  
  8477. return coins;
  8478. }
  8479. }
  8480.  
  8481. #define VOUCHER_NUM_EURO 2
  8482.  
  8483. const DWORD cdwVoucherVnumEuro[VOUCHER_NUM_EURO] =
  8484. {
  8485. 80014,
  8486. 80015
  8487. };
  8488.  
  8489. const int ciVoucherCountEuro[VOUCHER_NUM_EURO] =
  8490. {
  8491. 5,
  8492. 10,
  8493. };
  8494.  
  8495. void CHARACTER::SetEuro(bool bVoucher, int iCoins, DWORD dwVnum)
  8496. {
  8497. int iCount = 0;
  8498.  
  8499. for (int i = 0 ; i < VOUCHER_NUM_EURO ; i++)
  8500. {
  8501. if (dwVnum == cdwVoucherVnumEuro[i])
  8502. {
  8503. iCount = ciVoucherCountEuro[i];
  8504. break;
  8505. }
  8506. }
  8507.  
  8508. if (iCount == 0 && bVoucher == true)
  8509. return;
  8510.  
  8511. std::unique_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery("UPDATE account.account SET euro = euro + '%d' WHERE id = '%d'", bVoucher == true ? iCount : iCoins, GetDesc()->GetAccountTable().id));
  8512. bool bSucc = (pMsg->uiSQLErrno == 0);
  8513.  
  8514. if (bSucc && bVoucher == true)
  8515. {
  8516. ChatPacket(CHAT_TYPE_INFO, "|cFF00ff33[Euro Info] > |h|r You got %ld Euro.", iCount);
  8517. }
  8518.  
  8519. ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_EURO2 %d", GetEuro());
  8520. }
  8521.  
  8522. int CHARACTER::GetEuro()
  8523. {
  8524. int coins = 0;
  8525. char querySelect[256];
  8526.  
  8527. snprintf(querySelect, sizeof(querySelect), "SELECT euro FROM account.account WHERE id = '%u'", GetDesc()->GetAccountTable().id);
  8528.  
  8529. std::unique_ptr<SQLMsg> pSelectMsg(DBManager::instance().DirectQuery(querySelect));
  8530. SQLResult* resSelect = pSelectMsg->Get();
  8531.  
  8532. if (resSelect && resSelect->uiNumRows > 0)
  8533. {
  8534. MYSQL_ROW row = mysql_fetch_row(resSelect->pSQLResult);
  8535. str_to_number(coins, row[0]);
  8536. ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_EURO2 %d", coins);
  8537.  
  8538. return coins;
  8539. }
  8540. }
  8541. #endif
  8542.  
  8543. bool CHARACTER::CanWarp() const
  8544. {
  8545. const int iPulse = thecore_pulse();
  8546. const int limit_time = PASSES_PER_SEC(g_nPortalLimitTime);
  8547.  
  8548. if ((iPulse - GetSafeboxLoadTime()) < limit_time)
  8549. return false;
  8550.  
  8551. if ((iPulse - GetExchangeTime()) < limit_time)
  8552. return false;
  8553.  
  8554. if ((iPulse - GetMyShopTime()) < limit_time)
  8555. return false;
  8556.  
  8557. if ((iPulse - GetRefineTime()) < limit_time)
  8558. return false;
  8559.  
  8560. if (GetExchange() || GetMyShop() || GetShopOwner() || IsOpenSafebox() || IsCubeOpen())
  8561. return false;
  8562.  
  8563. return true;
  8564. }
  8565.  
  8566. DWORD CHARACTER::GetNextExp() const
  8567. {
  8568. if (PLAYER_EXP_TABLE_MAX < GetLevel())
  8569. return 2500000000;
  8570. else
  8571. return exp_table[GetLevel()];
  8572. }
  8573.  
  8574. int CHARACTER::GetSkillPowerByLevel(int level, bool bMob) const
  8575. {
  8576. return CTableBySkill::instance().GetSkillPowerByLevelFromType(GetJob(), GetSkillGroup(), MINMAX(0, level, SKILL_MAX_LEVEL), bMob);
  8577. }
  8578.  
Advertisement
Add Comment
Please, Sign In to add comment