MrP0wers

char.cpp

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