trus7

char.cpp

Nov 20th, 2020
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 269.91 KB | None | 0 0
  1. #include "stdafx.h"
  2.  
  3. #include "../../common/teen_packet.h"
  4. #include "../../common/VnumHelper.h"
  5.  
  6. #include "char.h"
  7.  
  8. #include "config.h"
  9. #include "utils.h"
  10. #include "crc32.h"
  11. #include "char_manager.h"
  12. #include "desc_client.h"
  13. #include "desc_manager.h"
  14. #include "buffer_manager.h"
  15. #include "item_manager.h"
  16. #include "motion.h"
  17. #include "vector.h"
  18. #include "packet.h"
  19. #include "cmd.h"
  20. #include "fishing.h"
  21. #include "exchange.h"
  22. #include "battle.h"
  23. #include "affect.h"
  24. #include "shop.h"
  25. #include "shop_manager.h"
  26. #include "safebox.h"
  27. #include "regen.h"
  28. #include "pvp.h"
  29. #include "party.h"
  30. #include "start_position.h"
  31. #include "questmanager.h"
  32. #include "log.h"
  33. #include "p2p.h"
  34. #include "guild.h"
  35. #include "guild_manager.h"
  36. #include "dungeon.h"
  37. #include "messenger_manager.h"
  38. #include "unique_item.h"
  39. #include "priv_manager.h"
  40. #include "war_map.h"
  41. #include "xmas_event.h"
  42. #include "banword.h"
  43. #include "target.h"
  44. #include "wedding.h"
  45. #include "mob_manager.h"
  46. #include "mining.h"
  47. #include "monarch.h"
  48. #include "castle.h"
  49. #include "arena.h"
  50. #include "dev_log.h"
  51. #include "horsename_manager.h"
  52. #include "pcbang.h"
  53. #include "gm.h"
  54. #include "map_location.h"
  55. #include "BlueDragon_Binder.h"
  56. #include "HackShield.h"
  57. #include "skill_power.h"
  58. #include "XTrapManager.h"
  59. #include "buff_on_attributes.h"
  60. #include <boost/algorithm/string.hpp>
  61.  
  62.  
  63. #ifdef __PET_SYSTEM__
  64. #include "PetSystem.h"
  65. #endif
  66. #ifdef NEW_PET_SYSTEM
  67. #include "New_PetSystem.h"
  68. #endif
  69. #include "DragonSoul.h"
  70. #include "OXEvent.h"
  71. #ifdef __SEND_TARGET_INFO__
  72. #include <algorithm>
  73. #include <iterator>
  74. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  75. #include "MountSystem.h"
  76. #endif
  77. #ifdef __MELEY_LAIR_DUNGEON__
  78. #include "MeleyLair.h"
  79. #endif
  80. using namespace std;
  81. #endif
  82. #include "../../common/CommonDefines.h"
  83. #ifdef ENABLE_SUPPORT_SYSTEM
  84. #include "SupportSystem.h"
  85. #endif
  86. #ifdef __ENABLE_BATTLE_FIELD__
  87. #include "battle_zone.h"
  88. #endif
  89. #include "System_Battlepass.cpp"
  90.  
  91. extern const BYTE g_aBuffOnAttrPoints;
  92. extern bool RaceToJob(unsigned race, unsigned *ret_job);
  93.  
  94. extern bool IS_SUMMONABLE_ZONE(int map_index); // char_item.cpp
  95. bool CAN_ENTER_ZONE(const LPCHARACTER& ch, int map_index);
  96.  
  97. bool CAN_ENTER_ZONE(const LPCHARACTER& ch, int map_index)
  98. {
  99. switch (map_index)
  100. {
  101. case 301:
  102. case 302:
  103. case 303:
  104. case 304:
  105. if (ch->GetLevel() < 90)
  106. return false;
  107. }
  108. return true;
  109. }
  110.  
  111. #ifdef NEW_ICEDAMAGE_SYSTEM
  112. const DWORD CHARACTER::GetNoDamageRaceFlag()
  113. {
  114. return m_dwNDRFlag;
  115. }
  116.  
  117. void CHARACTER::SetNoDamageRaceFlag(DWORD dwRaceFlag)
  118. {
  119. if (dwRaceFlag>=MAIN_RACE_MAX_NUM) return;
  120. if (IS_SET(m_dwNDRFlag, 1<<dwRaceFlag)) return;
  121. SET_BIT(m_dwNDRFlag, 1<<dwRaceFlag);
  122. }
  123.  
  124. void CHARACTER::UnsetNoDamageRaceFlag(DWORD dwRaceFlag)
  125. {
  126. if (dwRaceFlag>=MAIN_RACE_MAX_NUM) return;
  127. if (!IS_SET(m_dwNDRFlag, 1<<dwRaceFlag)) return;
  128. REMOVE_BIT(m_dwNDRFlag, 1<<dwRaceFlag);
  129. }
  130.  
  131. void CHARACTER::ResetNoDamageRaceFlag()
  132. {
  133. m_dwNDRFlag = 0;
  134. }
  135.  
  136. const std::set<DWORD> & CHARACTER::GetNoDamageAffectFlag()
  137. {
  138. return m_setNDAFlag;
  139. }
  140.  
  141. void CHARACTER::SetNoDamageAffectFlag(DWORD dwAffectFlag)
  142. {
  143. m_setNDAFlag.insert(dwAffectFlag);
  144. }
  145.  
  146. void CHARACTER::UnsetNoDamageAffectFlag(DWORD dwAffectFlag)
  147. {
  148. m_setNDAFlag.erase(dwAffectFlag);
  149. }
  150.  
  151. void CHARACTER::ResetNoDamageAffectFlag()
  152. {
  153. m_setNDAFlag.clear();
  154. }
  155. #endif
  156.  
  157. // <Factor> DynamicCharacterPtr member function definitions
  158.  
  159. LPCHARACTER DynamicCharacterPtr::Get() const {
  160. LPCHARACTER p = NULL;
  161. if (is_pc) {
  162. p = CHARACTER_MANAGER::instance().FindByPID(id);
  163. } else {
  164. p = CHARACTER_MANAGER::instance().Find(id);
  165. }
  166. return p;
  167. }
  168.  
  169. DynamicCharacterPtr& DynamicCharacterPtr::operator=(LPCHARACTER character) {
  170. if (character == NULL) {
  171. Reset();
  172. return *this;
  173. }
  174. if (character->IsPC()) {
  175. is_pc = true;
  176. id = character->GetPlayerID();
  177. } else {
  178. is_pc = false;
  179. id = character->GetVID();
  180. }
  181. return *this;
  182. }
  183.  
  184. CHARACTER::CHARACTER()
  185. {
  186. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateIdle, &CHARACTER::EndStateEmpty);
  187. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateMove, &CHARACTER::EndStateEmpty);
  188. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateBattle, &CHARACTER::EndStateEmpty);
  189. #ifdef __UPGRADE_ITEMS_STORAGE__
  190. m_pkStorage = new CUpgradeItemsStorage(this);
  191. #endif
  192. Initialize();
  193. }
  194.  
  195. CHARACTER::~CHARACTER()
  196. {
  197. Destroy();
  198. }
  199.  
  200. void CHARACTER::Initialize()
  201. {
  202. CEntity::Initialize(ENTITY_CHARACTER);
  203.  
  204. m_bNoOpenedShop = true;
  205.  
  206. m_bOpeningSafebox = false;
  207.  
  208. m_fSyncTime = get_float_time()-3;
  209. m_dwPlayerID = 0;
  210. #ifdef NEW_PET_SYSTEM
  211. m_stImmortalSt = 0;
  212.  
  213. m_newpetskillcd[0] = 0;
  214. m_newpetskillcd[1] = 0;
  215. m_newpetskillcd[2] = 0;
  216. #endif
  217. m_dwKillerPID = 0;
  218. #ifdef __SEND_TARGET_INFO__
  219. dwLastTargetInfoPulse = 0;
  220. #endif
  221.  
  222. m_iMoveCount = 0;
  223.  
  224. m_pkRegen = NULL;
  225. regen_id_ = 0;
  226. m_posRegen.x = m_posRegen.y = m_posRegen.z = 0;
  227. m_posStart.x = m_posStart.y = 0;
  228. m_posDest.x = m_posDest.y = 0;
  229. m_fRegenAngle = 0.0f;
  230.  
  231. m_pkMobData = NULL;
  232. m_pkMobInst = NULL;
  233.  
  234. m_pkShop = NULL;
  235. m_pkChrShopOwner = NULL;
  236. m_pkMyShop = NULL;
  237. m_pkExchange = NULL;
  238. m_pkParty = NULL;
  239. m_pkPartyRequestEvent = NULL;
  240.  
  241. m_pGuild = NULL;
  242.  
  243. m_pkChrTarget = NULL;
  244.  
  245. m_pkMuyeongEvent = NULL;
  246.  
  247. m_pkWarpNPCEvent = NULL;
  248. m_pkDeadEvent = NULL;
  249. m_pkStunEvent = NULL;
  250. m_pkSaveEvent = NULL;
  251. m_pkRecoveryEvent = NULL;
  252. m_pkTimedEvent = NULL;
  253. m_pkFishingEvent = NULL;
  254. m_pkWarpEvent = NULL;
  255.  
  256. // MINING
  257. m_pkMiningEvent = NULL;
  258. // END_OF_MINING
  259.  
  260. m_pkPoisonEvent = NULL;
  261. #ifdef ENABLE_CHANGE_CHANNEL
  262. m_pkChangeChannelEvent = NULL;
  263. #endif
  264. #ifdef ENABLE_WOLFMAN_CHARACTER
  265. m_pkBleedingEvent = NULL;
  266. #endif
  267. #ifdef __ENABLE_BATTLE_FIELD__
  268. m_pkBattleZoneEvent = NULL;
  269. #endif
  270. m_pkFireEvent = NULL;
  271. m_pkCheckSpeedHackEvent = NULL;
  272. m_speed_hack_count = 0;
  273.  
  274. m_pkAffectEvent = NULL;
  275. m_afAffectFlag = TAffectFlag(0, 0);
  276.  
  277. m_pkDestroyWhenIdleEvent = NULL;
  278.  
  279. m_pkChrSyncOwner = NULL;
  280.  
  281. memset(&m_points, 0, sizeof(m_points));
  282. memset(&m_pointsInstant, 0, sizeof(m_pointsInstant));
  283. memset(&m_quickslot, 0, sizeof(m_quickslot));
  284. memset(&character_cards, 0, sizeof(character_cards));
  285. memset(&randomized_cards, 0, sizeof(randomized_cards));
  286.  
  287. m_bCharType = CHAR_TYPE_MONSTER;
  288.  
  289. SetPosition(POS_STANDING);
  290.  
  291. m_dwPlayStartTime = m_dwLastMoveTime = get_dword_time();
  292.  
  293. GotoState(m_stateIdle);
  294. m_dwStateDuration = 1;
  295.  
  296. m_dwLastAttackTime = get_dword_time() - 20000;
  297.  
  298. m_bAddChrState = 0;
  299.  
  300. m_pkChrStone = NULL;
  301.  
  302. m_pkSafebox = NULL;
  303. m_iSafeboxSize = -1;
  304. m_iSafeboxLoadTime = 0;
  305.  
  306. m_pkMall = NULL;
  307. m_iMallLoadTime = 0;
  308.  
  309. m_posWarp.x = m_posWarp.y = m_posWarp.z = 0;
  310. m_lWarpMapIndex = 0;
  311.  
  312. m_posExit.x = m_posExit.y = m_posExit.z = 0;
  313. m_lExitMapIndex = 0;
  314.  
  315. m_pSkillLevels = NULL;
  316.  
  317. #ifdef ENABLE_GEM_SYSTEM
  318. m_gemItems = NULL;
  319. #endif
  320.  
  321. m_dwMoveStartTime = 0;
  322. m_dwMoveDuration = 0;
  323.  
  324. m_dwFlyTargetID = 0;
  325.  
  326. m_dwNextStatePulse = 0;
  327.  
  328. m_dwLastDeadTime = get_dword_time()-180000;
  329.  
  330. m_bSkipSave = false;
  331.  
  332. m_bItemLoaded = false;
  333.  
  334. m_bHasPoisoned = false;
  335. #ifdef ENABLE_WOLFMAN_CHARACTER
  336. m_bHasBled = false;
  337. #endif
  338. m_pkDungeon = NULL;
  339. m_iEventAttr = 0;
  340.  
  341. m_kAttackLog.dwVID = 0;
  342. m_kAttackLog.dwTime = 0;
  343.  
  344. m_bNowWalking = m_bWalking = false;
  345. ResetChangeAttackPositionTime();
  346.  
  347. m_bDetailLog = false;
  348. m_bMonsterLog = false;
  349.  
  350. m_bDisableCooltime = false;
  351.  
  352. m_iAlignment = 0;
  353. m_iRealAlignment = 0;
  354.  
  355. m_iKillerModePulse = 0;
  356. m_bPKMode = PK_MODE_PEACE;
  357.  
  358. m_dwQuestNPCVID = 0;
  359. m_dwQuestByVnum = 0;
  360. m_pQuestItem = NULL;
  361.  
  362. m_szMobileAuth[0] = '\0';
  363.  
  364. m_dwUnderGuildWarInfoMessageTime = get_dword_time()-60000;
  365.  
  366. m_bUnderRefine = false;
  367.  
  368. // REFINE_NPC
  369. m_dwRefineNPCVID = 0;
  370. // END_OF_REFINE_NPC
  371.  
  372. m_dwPolymorphRace = 0;
  373.  
  374. m_bStaminaConsume = false;
  375.  
  376. ResetChainLightningIndex();
  377.  
  378. m_dwMountVnum = 0;
  379. m_chHorse = NULL;
  380. m_chRider = NULL;
  381.  
  382. m_pWarMap = NULL;
  383. m_pWeddingMap = NULL;
  384. m_bChatCounter = 0;
  385.  
  386. ResetStopTime();
  387.  
  388. m_dwLastVictimSetTime = get_dword_time() - 3000;
  389. m_iMaxAggro = -100;
  390.  
  391. m_bSendHorseLevel = 0;
  392. m_bSendHorseHealthGrade = 0;
  393. m_bSendHorseStaminaGrade = 0;
  394.  
  395. m_dwLoginPlayTime = 0;
  396.  
  397. m_pkChrMarried = NULL;
  398.  
  399. m_posSafeboxOpen.x = -1000;
  400. m_posSafeboxOpen.y = -1000;
  401.  
  402. // EQUIP_LAST_SKILL_DELAY
  403. m_dwLastSkillTime = get_dword_time();
  404. m_dwLastSkillVnum = 0;
  405. // END_OF_EQUIP_LAST_SKILL_DELAY
  406.  
  407. // MOB_SKILL_COOLTIME
  408. memset(m_adwMobSkillCooltime, 0, sizeof(m_adwMobSkillCooltime));
  409. // END_OF_MOB_SKILL_COOLTIME
  410.  
  411. m_isinPCBang = false;
  412.  
  413. // ARENA
  414. m_pArena = NULL;
  415. m_nPotionLimit = quest::CQuestManager::instance().GetEventFlag("arena_potion_limit_count");
  416. // END_ARENA
  417.  
  418. //PREVENT_TRADE_WINDOW
  419. m_isOpenSafebox = 0;
  420. //END_PREVENT_TRADE_WINDOW
  421.  
  422. //PREVENT_REFINE_HACK
  423. m_iRefineTime = 0;
  424. //END_PREVENT_REFINE_HACK
  425.  
  426. //RESTRICT_USE_SEED_OR_MOONBOTTLE
  427. m_iSeedTime = 0;
  428. //END_RESTRICT_USE_SEED_OR_MOONBOTTLE
  429. //PREVENT_PORTAL_AFTER_EXCHANGE
  430. m_iExchangeTime = 0;
  431. //END_PREVENT_PORTAL_AFTER_EXCHANGE
  432. //
  433. m_iSafeboxLoadTime = 0;
  434.  
  435. m_iMyShopTime = 0;
  436.  
  437. InitMC();
  438.  
  439. m_deposit_pulse = 0;
  440.  
  441. SET_OVER_TIME(this, OT_NONE);
  442.  
  443. m_strNewName = "";
  444.  
  445. m_known_guild.clear();
  446.  
  447. m_dwLogOffInterval = 0;
  448.  
  449. #ifdef ENABLE_GEM_SYSTEM
  450. m_dwGemNextRefresh = 0;
  451. #endif
  452.  
  453. m_bComboSequence = 0;
  454. m_dwLastComboTime = 0;
  455. m_bComboIndex = 0;
  456. m_iComboHackCount = 0;
  457. m_dwSkipComboAttackByTime = 0;
  458.  
  459. m_dwMountTime = 0;
  460.  
  461. m_dwLastGoldDropTime = 0;
  462. #ifdef ENABLE_NEWSTUFF
  463. m_dwLastItemDropTime = 0;
  464. m_dwLastBoxUseTime = 0;
  465. m_dwLastBuySellTime = 0;
  466. #endif
  467.  
  468. m_HackShieldCheckEvent = NULL;
  469. m_HackShieldCheckMode = false;
  470.  
  471. m_bIsLoadedAffect = false;
  472. cannot_dead = false;
  473.  
  474. #ifdef ENABLE_SUPPORT_SYSTEM
  475. m_supportSystem = 0;
  476. m_dwSupportHair = 0;
  477. m_dwSupportWeapon = 0;
  478. m_dwSupportCostume = 0;
  479. m_bIsSupport = false;
  480. m_Owner = NULL;
  481. #endif
  482.  
  483. #ifdef __PET_SYSTEM__
  484. m_petSystem = 0;
  485. m_bIsPet = false;
  486. #endif
  487. #ifdef NEW_PET_SYSTEM
  488. m_newpetSystem = 0;
  489. m_bIsNewPet = false;
  490. m_eggvid = 0;
  491. #endif
  492. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  493. m_mountSystem = 0;
  494. m_bIsMount = false;
  495. #endif
  496. #ifdef NEW_ICEDAMAGE_SYSTEM
  497. m_dwNDRFlag = 0;
  498. m_setNDAFlag.clear();
  499. #endif
  500.  
  501. #ifdef OFFLINE_SHOP
  502. m_pkRefreshShopEvent = NULL;
  503. bprivShop = 0;
  504. bprivShopOwner = 0;
  505. bprivShop = 0;
  506. bprivShopOwner = 0;
  507. dw_ShopTime = 0;
  508. m_mapshops.clear();
  509. #endif
  510. #ifdef GIFT_SYSTEM
  511. m_pkGiftRefresh = NULL;
  512. m_dwLastGiftPage = 0;
  513. m_mapGiftGrid.clear();
  514. #endif
  515.  
  516. m_fAttMul = 1.0f;
  517. m_fDamMul = 1.0f;
  518.  
  519. m_pointsInstant.iDragonSoulActiveDeck = -1;
  520.  
  521. #ifdef ENABLE_FISH_EVENT
  522. m_fishSlots = NULL;
  523. m_dwFishUseCount = 0;
  524. m_bFishAttachedShape = 0;
  525. #endif
  526.  
  527. #ifdef __ATTENDANCE_EVENT__
  528. m_hitCount.clear();
  529. #endif
  530. #ifdef __ENABLE_BATTLE_FIELD__
  531. m_bBattleRank = 0;
  532. m_bBattleDeadCount = 0;
  533. #endif
  534. #ifdef ENABLE_ANTI_CMD_FLOOD
  535. m_dwCmdAntiFloodCount = 0;
  536. m_dwCmdAntiFloodPulse = 0;
  537. #endif
  538. memset(&m_tvLastSyncTime, 0, sizeof(m_tvLastSyncTime));
  539. #ifdef __UPGRADE_ITEMS_STORAGE__
  540. m_pkStorage = NULL;
  541. #endif
  542. m_iSyncHackCount = 0;
  543. #ifdef ENABLE_SORT_INVENTORY
  544. m_sortInventoryPulse = 0;
  545. m_sortSpecialStoragePulse = 0;
  546. #endif
  547. #ifdef __CHANGELOOK_SYSTEM__
  548. m_bChangeLook = false;
  549. #endif
  550. #ifdef __SASH_SYSTEM__
  551. m_bSashCombination = false;
  552. m_bSashAbsorption = false;
  553. #endif
  554. #ifdef __FAKE_BUFF__
  555. m_pkFakeBuffOwner = NULL;
  556. m_pkFakeBuffSpawn = NULL;
  557. m_pkFakeBuffItem = NULL;
  558. #endif
  559. }
  560.  
  561. void CHARACTER::Create(const char * c_pszName, DWORD vid, bool isPC)
  562. {
  563. static int s_crc = 172814;
  564.  
  565. char crc_string[128+1];
  566. snprintf(crc_string, sizeof(crc_string), "%s%p%d", c_pszName, this, ++s_crc);
  567. m_vid = VID(vid, GetCRC32(crc_string, strlen(crc_string)));
  568.  
  569. if (isPC)
  570. m_stName = c_pszName;
  571. }
  572.  
  573. void CHARACTER::Destroy()
  574. {
  575. CloseMyShop();
  576.  
  577. if (m_pkRegen)
  578. {
  579. if (m_pkDungeon) {
  580. // Dungeon regen may not be valid at this point
  581. if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {
  582. --m_pkRegen->count;
  583. }
  584. } else {
  585. // Is this really safe?
  586. --m_pkRegen->count;
  587. }
  588. m_pkRegen = NULL;
  589. }
  590.  
  591. if (m_pkDungeon)
  592. {
  593. SetDungeon(NULL);
  594. }
  595.  
  596. #ifdef ENABLE_SUPPORT_SYSTEM
  597. if (m_supportSystem)
  598. {
  599. m_supportSystem->Destroy();
  600. delete m_supportSystem;
  601.  
  602. m_supportSystem = 0;
  603. }
  604. #endif
  605.  
  606. #ifdef __PET_SYSTEM__
  607. if (m_petSystem)
  608. {
  609. m_petSystem->Destroy();
  610. delete m_petSystem;
  611.  
  612. m_petSystem = 0;
  613. }
  614. #endif
  615. #ifdef NEW_PET_SYSTEM
  616. if (m_newpetSystem)
  617. {
  618. m_newpetSystem->Destroy();
  619. delete m_newpetSystem;
  620.  
  621. m_newpetSystem = 0;
  622. }
  623. #endif
  624. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  625. if (m_mountSystem)
  626. {
  627. m_mountSystem->Destroy();
  628. delete m_mountSystem;
  629.  
  630. m_mountSystem = 0;
  631. }
  632.  
  633. if(GetMountVnum())
  634. {
  635. RemoveAffect(AFFECT_MOUNT);
  636. RemoveAffect(AFFECT_MOUNT_BONUS);
  637. }
  638. HorseSummon(false);
  639. #endif
  640.  
  641. if (GetRider())
  642. GetRider()->ClearHorseInfo();
  643.  
  644. if( IsPC() )
  645. {
  646. if (isHackShieldEnable)
  647. {
  648. CHackShieldManager::instance().DeleteClientHandle(GetPlayerID());
  649. }
  650. }
  651.  
  652. if (GetDesc())
  653. {
  654. GetDesc()->BindCharacter(NULL);
  655. // BindDesc(NULL);
  656. }
  657.  
  658. if (m_pkExchange)
  659. m_pkExchange->Cancel();
  660.  
  661. SetVictim(NULL);
  662.  
  663. if (GetShop())
  664. {
  665. GetShop()->RemoveGuest(this);
  666. SetShop(NULL);
  667. }
  668.  
  669. ClearStone();
  670. ClearSync();
  671. ClearTarget();
  672.  
  673. if (NULL == m_pkMobData)
  674. {
  675. DragonSoul_CleanUp();
  676. ClearItem();
  677. }
  678.  
  679. // <Factor> m_pkParty becomes NULL after CParty destructor call!
  680. LPPARTY party = m_pkParty;
  681. if (party)
  682. {
  683. if (party->GetLeaderPID() == GetVID() && !IsPC())
  684. {
  685. M2_DELETE(party);
  686. }
  687. else
  688. {
  689. party->Unlink(this);
  690.  
  691. if (!IsPC())
  692. party->Quit(GetVID());
  693. }
  694.  
  695. SetParty(NULL); // ¾ÈÇØµµ µÇÁö¸¸ ¾ÈÀüÇϰÔ.
  696. }
  697.  
  698. if (m_pkMobInst)
  699. {
  700. M2_DELETE(m_pkMobInst);
  701. m_pkMobInst = NULL;
  702. }
  703.  
  704. m_pkMobData = NULL;
  705.  
  706. if (m_pkSafebox)
  707. {
  708. M2_DELETE(m_pkSafebox);
  709. m_pkSafebox = NULL;
  710. }
  711.  
  712. if (m_pkMall)
  713. {
  714. M2_DELETE(m_pkMall);
  715. m_pkMall = NULL;
  716. }
  717.  
  718. #ifdef __UPGRADE_ITEMS_STORAGE__
  719. if (m_pkStorage)
  720. {
  721. M2_DELETE(m_pkStorage);
  722. m_pkStorage = NULL;
  723. }
  724. #endif
  725.  
  726. for (TMapBuffOnAttrs::iterator it = m_map_buff_on_attrs.begin(); it != m_map_buff_on_attrs.end(); it++)
  727. {
  728. if (NULL != it->second)
  729. {
  730. M2_DELETE(it->second);
  731. }
  732. }
  733. m_map_buff_on_attrs.clear();
  734.  
  735. m_set_pkChrSpawnedBy.clear();
  736.  
  737. StopMuyeongEvent();
  738. event_cancel(&m_pkWarpNPCEvent);
  739. event_cancel(&m_pkRecoveryEvent);
  740. event_cancel(&m_pkDeadEvent);
  741. event_cancel(&m_pkSaveEvent);
  742. event_cancel(&m_pkTimedEvent);
  743. event_cancel(&m_pkStunEvent);
  744. event_cancel(&m_pkFishingEvent);
  745. event_cancel(&m_pkPoisonEvent);
  746. #ifdef __ENABLE_BATTLE_FIELD__
  747. event_cancel(&m_pkBattleZoneEvent);
  748. #endif
  749. #ifdef ENABLE_CHANGE_CHANNEL
  750. event_cancel(&m_pkChangeChannelEvent);
  751. #endif
  752. #ifdef ENABLE_WOLFMAN_CHARACTER
  753. event_cancel(&m_pkBleedingEvent);
  754. #endif
  755. #ifdef GIFT_SYSTEM
  756. event_cancel(&m_pkGiftRefresh);
  757. m_dwLastGiftPage = 0;
  758. m_mapGiftGrid.clear();
  759. #endif
  760. #ifdef OFFLINE_SHOP
  761. event_cancel(&m_pkRefreshShopEvent);
  762. bprivShop = 0;
  763. bprivShopOwner = 0;
  764. dw_ShopTime = 0;
  765. m_mapshops.clear();
  766. #endif
  767. event_cancel(&m_pkFireEvent);
  768. event_cancel(&m_pkPartyRequestEvent);
  769. //DELAYED_WARP
  770. event_cancel(&m_pkWarpEvent);
  771. event_cancel(&m_pkCheckSpeedHackEvent);
  772. //END_DELAYED_WARP
  773.  
  774. // RECALL_DELAY
  775. //event_cancel(&m_pkRecallEvent);
  776. // END_OF_RECALL_DELAY
  777.  
  778. // MINING
  779. event_cancel(&m_pkMiningEvent);
  780. // END_OF_MINING
  781.  
  782. StopHackShieldCheckCycle();
  783.  
  784. for (itertype(m_mapMobSkillEvent) it = m_mapMobSkillEvent.begin(); it != m_mapMobSkillEvent.end(); ++it)
  785. {
  786. LPEVENT pkEvent = it->second;
  787. event_cancel(&pkEvent);
  788. }
  789. m_mapMobSkillEvent.clear();
  790.  
  791. //event_cancel(&m_pkAffectEvent);
  792. ClearAffect();
  793.  
  794. event_cancel(&m_pkDestroyWhenIdleEvent);
  795.  
  796. if (m_pSkillLevels)
  797. {
  798. M2_DELETE_ARRAY(m_pSkillLevels);
  799. m_pSkillLevels = NULL;
  800. }
  801.  
  802. #ifdef ENABLE_FISH_EVENT
  803. if (m_fishSlots)
  804. {
  805. M2_DELETE_ARRAY(m_fishSlots);
  806. m_fishSlots = NULL;
  807. }
  808. #endif
  809.  
  810. #ifdef ENABLE_GEM_SYSTEM
  811. if (m_gemItems)
  812. {
  813. M2_DELETE_ARRAY(m_gemItems);
  814. m_gemItems = NULL;
  815. }
  816. #endif
  817.  
  818. #ifdef __FAKE_BUFF__
  819. if (FakeBuff_Check())
  820. FakeBuff_Destroy();
  821. #endif
  822.  
  823. CEntity::Destroy();
  824.  
  825. if (GetSectree())
  826. GetSectree()->RemoveEntity(this);
  827.  
  828. if (m_bMonsterLog)
  829. CHARACTER_MANAGER::instance().UnregisterForMonsterLog(this);
  830. }
  831.  
  832. const char * CHARACTER::GetName() const
  833. {
  834. return m_stName.empty() ? (m_pkMobData ? m_pkMobData->m_table.szLocaleName : "") : m_stName.c_str();
  835. }
  836.  
  837.  
  838. void CHARACTER::OpenMyShop(const char * c_pszSign, TShopItemTable * pTable, BYTE bItemCount)
  839. {
  840. if (!CanHandleItem()) // @fixme149
  841. {
  842. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡Áß(â°í,±³È¯,»óÁ¡)¿¡´Â °³ÀλóÁ¡À» »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  843. return;
  844. }
  845.  
  846. if (GetMyShop()) // ÀÌ¹Ì ¼¥ÀÌ ¿­·Á ÀÖÀ¸¸é ´Ý´Â´Ù.
  847. {
  848. CloseMyShop();
  849. return;
  850. }
  851.  
  852. // ÁøÇàÁßÀÎ Äù½ºÆ®°¡ ÀÖÀ¸¸é »óÁ¡À» ¿­ ¼ö ¾ø´Ù.
  853. quest::PC * pPC = quest::CQuestManager::instance().GetPCForce(GetPlayerID());
  854.  
  855. // GetPCForce´Â NULLÀÏ ¼ö ¾øÀ¸¹Ç·Î µû·Î È®ÀÎÇÏÁö ¾ÊÀ½
  856. if (pPC->IsRunning())
  857. return;
  858.  
  859. if (bItemCount == 0)
  860. return;
  861.  
  862. long long nTotalMoney = 0;
  863.  
  864. for (int n = 0; n < bItemCount; ++n)
  865. {
  866. nTotalMoney += static_cast<long long>((pTable+n)->price);
  867. }
  868.  
  869. nTotalMoney += static_cast<long long>(GetGold());
  870.  
  871. if (GOLD_MAX <= nTotalMoney)
  872. {
  873. sys_err("[OVERFLOW_GOLD] Overflow (GOLD_MAX) id %u name %s", GetPlayerID(), GetName());
  874. ChatPacket(CHAT_TYPE_INFO,("Limita de yang a fost atinsa!"));
  875. return;
  876. }
  877.  
  878. char szSign[SHOP_SIGN_MAX_LEN+1];
  879. strlcpy(szSign, c_pszSign, sizeof(szSign));
  880.  
  881. m_stShopSign = szSign;
  882.  
  883. if (m_stShopSign.length() == 0)
  884. return;
  885.  
  886. if (CBanwordManager::instance().CheckString(m_stShopSign.c_str(), m_stShopSign.length()))
  887. {
  888. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ºñ¼Ó¾î³ª Àº¾î°¡ Æ÷ÇÔµÈ »óÁ¡ À̸§À¸·Î »óÁ¡À» ¿­ ¼ö ¾ø½À´Ï´Ù."));
  889. return;
  890. }
  891.  
  892. // MYSHOP_PRICE_LIST
  893. std::map<DWORD, DWORD> itemkind; // ¾ÆÀÌÅÛ Á¾·ùº° °¡°Ý, first: vnum, second: ´ÜÀÏ ¼ö·® °¡°Ý
  894. // END_OF_MYSHOP_PRICE_LIST
  895.  
  896. std::set<TItemPos> cont;
  897. for (BYTE i = 0; i < bItemCount; ++i)
  898. {
  899. if (cont.find((pTable + i)->pos) != cont.end())
  900. {
  901. sys_err("MYSHOP: duplicate shop item detected! (name: %s)", GetName());
  902. return;
  903. }
  904.  
  905. // ANTI_GIVE, ANTI_MYSHOP check
  906. LPITEM pkItem = GetItem((pTable + i)->pos);
  907.  
  908. if (pkItem)
  909. {
  910. const TItemTable * item_table = pkItem->GetProto();
  911.  
  912. if (item_table && (IS_SET(item_table->dwAntiFlags, ITEM_ANTIFLAG_GIVE | ITEM_ANTIFLAG_MYSHOP)))
  913. {
  914. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("À¯·áÈ­ ¾ÆÀÌÅÛÀº °³ÀλóÁ¡¿¡¼­ ÆÇ¸ÅÇÒ ¼ö ¾ø½À´Ï´Ù."));
  915. return;
  916. }
  917.  
  918. if (pkItem->IsEquipped() == true)
  919. {
  920. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀåºñÁßÀÎ ¾ÆÀÌÅÛÀº °³ÀλóÁ¡¿¡¼­ ÆÇ¸ÅÇÒ ¼ö ¾ø½À´Ï´Ù."));
  921. return;
  922. }
  923.  
  924. if (true == pkItem->isLocked())
  925. {
  926. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ç¿ëÁßÀÎ ¾ÆÀÌÅÛÀº °³ÀλóÁ¡¿¡¼­ ÆÇ¸ÅÇÒ ¼ö ¾ø½À´Ï´Ù."));
  927. return;
  928. }
  929.  
  930. if (pkItem->GetTransmutation() != 0)
  931. {
  932. ChatPacket(CHAT_TYPE_INFO, "Nu poti pune la vanzare un obiect transmutat.");
  933. return;
  934. }
  935.  
  936. // MYSHOP_PRICE_LIST
  937. itemkind[pkItem->GetVnum()] = (pTable + i)->price / pkItem->GetCount();
  938. // END_OF_MYSHOP_PRICE_LIST
  939. }
  940.  
  941. cont.insert((pTable + i)->pos);
  942. }
  943.  
  944. // MYSHOP_PRICE_LIST
  945. // º¸µû¸® °³¼ö¸¦ °¨¼Ò½ÃŲ´Ù.
  946. if (CountSpecifyItem(71049)) { // ºñ´Ü º¸µû¸®´Â ¾ø¾ÖÁö ¾Ê°í °¡°ÝÁ¤º¸¸¦ ÀúÀåÇÑ´Ù.
  947.  
  948. //
  949. // ¾ÆÀÌÅÛ °¡°ÝÁ¤º¸¸¦ ÀúÀåÇϱâ À§ÇØ ¾ÆÀÌÅÛ °¡°ÝÁ¤º¸ ÆÐŶÀ» ¸¸µé¾î DB ij½Ã¿¡ º¸³½´Ù.
  950. //
  951. TPacketMyshopPricelistHeader header;
  952. TItemPriceInfo info;
  953.  
  954. header.dwOwnerID = GetPlayerID();
  955. header.byCount = itemkind.size();
  956.  
  957. TEMP_BUFFER buf;
  958. buf.write(&header, sizeof(header));
  959.  
  960. for (itertype(itemkind) it = itemkind.begin(); it != itemkind.end(); ++it)
  961. {
  962. info.dwVnum = it->first;
  963. info.dwPrice = it->second;
  964.  
  965. buf.write(&info, sizeof(info));
  966. }
  967.  
  968. db_clientdesc->DBPacket(HEADER_GD_MYSHOP_PRICELIST_UPDATE, 0, buf.read_peek(), buf.size());
  969. }
  970. // END_OF_MYSHOP_PRICE_LIST
  971. else if (CountSpecifyItem(50200))
  972. RemoveSpecifyItem(50200, 1);
  973. else
  974. return; // º¸µû¸®°¡ ¾øÀ¸¸é Áß´Ü.
  975.  
  976. if (m_pkExchange)
  977. m_pkExchange->Cancel();
  978.  
  979. TPacketGCShopSign p;
  980.  
  981. p.bHeader = HEADER_GC_SHOP_SIGN;
  982. p.dwVID = GetVID();
  983. strlcpy(p.szSign, c_pszSign, sizeof(p.szSign));
  984.  
  985. PacketAround(&p, sizeof(TPacketGCShopSign));
  986.  
  987. m_pkMyShop = CShopManager::instance().CreatePCShop(this, pTable, bItemCount);
  988.  
  989. if (IsPolymorphed() == true)
  990. {
  991. RemoveAffect(AFFECT_POLYMORPH);
  992. }
  993.  
  994. if (GetHorse())
  995. {
  996. HorseSummon( false, true );
  997. }
  998. // new mount ÀÌ¿ë Áß¿¡, °³ÀÎ »óÁ¡ ¿­¸é ÀÚµ¿ unmount
  999. // StopRidingÀ¸·Î ´º¸¶¿îÆ®±îÁö ó¸®Çϸé ÁÁÀºµ¥ ¿Ö ±×·¸°Ô ¾ÈÇØ³ù´ÂÁö ¾Ë ¼ö ¾ø´Ù.
  1000. else if (GetMountVnum())
  1001. {
  1002. RemoveAffect(AFFECT_MOUNT);
  1003. RemoveAffect(AFFECT_MOUNT_BONUS);
  1004. }
  1005.  
  1006. SetPolymorph(30000, true);
  1007.  
  1008. }
  1009.  
  1010. void CHARACTER::CloseMyShop()
  1011. {
  1012. if (GetMyShop())
  1013. {
  1014. m_stShopSign.clear();
  1015. CShopManager::instance().DestroyPCShop(this);
  1016. m_pkMyShop = NULL;
  1017.  
  1018. TPacketGCShopSign p;
  1019.  
  1020. p.bHeader = HEADER_GC_SHOP_SIGN;
  1021. p.dwVID = GetVID();
  1022. p.szSign[0] = '\0';
  1023.  
  1024. PacketAround(&p, sizeof(p));
  1025. #ifdef OFFLINE_SHOP
  1026. if (IsPrivShop())
  1027. {
  1028. M2_DESTROY_CHARACTER(this);
  1029. return;
  1030. }
  1031. #endif
  1032. #ifdef ENABLE_WOLFMAN_CHARACTER
  1033. SetPolymorph(m_points.job, true);
  1034. // SetPolymorph(0, true);
  1035. #else
  1036. SetPolymorph(GetJob(), true);
  1037. #endif
  1038. }
  1039. }
  1040.  
  1041. void EncodeMovePacket(TPacketGCMove & pack, DWORD dwVID, BYTE bFunc, BYTE bArg, DWORD x, DWORD y, DWORD dwDuration, DWORD dwTime, BYTE bRot)
  1042. {
  1043. pack.bHeader = HEADER_GC_MOVE;
  1044. pack.bFunc = bFunc;
  1045. pack.bArg = bArg;
  1046. pack.dwVID = dwVID;
  1047. pack.dwTime = dwTime ? dwTime : get_dword_time();
  1048. pack.bRot = bRot;
  1049. pack.lX = x;
  1050. pack.lY = y;
  1051. pack.dwDuration = dwDuration;
  1052. }
  1053.  
  1054. void CHARACTER::RestartAtSamePos()
  1055. {
  1056. if (m_bIsObserver)
  1057. return;
  1058.  
  1059. EncodeRemovePacket(this);
  1060. EncodeInsertPacket(this);
  1061.  
  1062. ENTITY_MAP::iterator it = m_map_view.begin();
  1063.  
  1064. while (it != m_map_view.end())
  1065. {
  1066. LPENTITY entity = (it++)->first;
  1067.  
  1068. EncodeRemovePacket(entity);
  1069. if (!m_bIsObserver)
  1070. EncodeInsertPacket(entity);
  1071.  
  1072. if( entity->IsType(ENTITY_CHARACTER) )
  1073. {
  1074. LPCHARACTER lpChar = (LPCHARACTER)entity;
  1075. if( lpChar->IsPC() || lpChar->IsNPC() || lpChar->IsMonster() )
  1076. {
  1077. if (!entity->IsObserverMode())
  1078. entity->EncodeInsertPacket(this);
  1079. }
  1080. }
  1081. else
  1082. {
  1083. if( !entity->IsObserverMode())
  1084. {
  1085. entity->EncodeInsertPacket(this);
  1086. }
  1087. }
  1088. }
  1089. }
  1090.  
  1091. // #define ENABLE_SHOWNPCLEVEL
  1092. // Entity¿¡ ³»°¡ ³ªÅ¸³µ´Ù°í ÆÐŶÀ» º¸³½´Ù.
  1093. void CHARACTER::EncodeInsertPacket(LPENTITY entity)
  1094. {
  1095.  
  1096. LPDESC d;
  1097.  
  1098. if (!(d = entity->GetDesc()))
  1099. return;
  1100.  
  1101. // ±æµåÀ̸§ ¹ö±× ¼öÁ¤ ÄÚµå
  1102. LPCHARACTER ch = (LPCHARACTER) entity;
  1103. ch->SendGuildName(GetGuild());
  1104. // ±æµåÀ̸§ ¹ö±× ¼öÁ¤ ÄÚµå
  1105.  
  1106. TPacketGCCharacterAdd pack;
  1107.  
  1108. pack.header = HEADER_GC_CHARACTER_ADD;
  1109. pack.dwVID = m_vid;
  1110. #if defined(__WJ_SHOW_MOB_INFO__)
  1111. if (IsMonster() || IsStone() /*|| IsGrowthPet()*/)
  1112. {
  1113. pack.dwLevel = GetLevel();
  1114. pack.dwAIFlag = IsMonster() ? GetAIFlag() : 0;
  1115. }
  1116. else
  1117. {
  1118. pack.dwLevel = 0;
  1119. pack.dwAIFlag = 0;
  1120. }
  1121. #endif
  1122. pack.bType = GetCharType();
  1123. pack.angle = GetRotation();
  1124. pack.x = GetX();
  1125. pack.y = GetY();
  1126. pack.z = GetZ();
  1127. pack.wRaceNum = GetRaceNum();
  1128. #ifdef NEW_PET_SYSTEM
  1129. if (IsPet() || IsSupport() || IsNewPet())
  1130. #else
  1131. if (IsPet())
  1132. #endif
  1133. {
  1134. pack.bMovingSpeed = 150;
  1135. }
  1136. else
  1137. {
  1138. pack.bMovingSpeed = GetLimitPoint(POINT_MOV_SPEED);
  1139. }
  1140. pack.bAttackSpeed = GetLimitPoint(POINT_ATT_SPEED);
  1141. pack.dwAffectFlag[0] = m_afAffectFlag.bits[0];
  1142. pack.dwAffectFlag[1] = m_afAffectFlag.bits[1];
  1143.  
  1144. pack.bStateFlag = m_bAddChrState;
  1145.  
  1146. int iDur = 0;
  1147.  
  1148. #ifdef __FAKE_BUFF__
  1149. if (FakeBuff_Check())
  1150. {
  1151. pack.bType = CHAR_TYPE_PC;
  1152. pack.wRaceNum = MAIN_RACE_SHAMAN_W;
  1153. }
  1154. #endif
  1155.  
  1156. if (m_posDest.x != pack.x || m_posDest.y != pack.y)
  1157. {
  1158. iDur = (m_dwMoveStartTime + m_dwMoveDuration) - get_dword_time();
  1159.  
  1160. if (iDur <= 0)
  1161. {
  1162. pack.x = m_posDest.x;
  1163. pack.y = m_posDest.y;
  1164. }
  1165. }
  1166.  
  1167. d->Packet(&pack, sizeof(pack));
  1168.  
  1169. if (IsPC() == true || m_bCharType == CHAR_TYPE_NPC)
  1170. {
  1171. TPacketGCCharacterAdditionalInfo addPacket;
  1172. memset(&addPacket, 0, sizeof(TPacketGCCharacterAdditionalInfo));
  1173.  
  1174. addPacket.header = HEADER_GC_CHAR_ADDITIONAL_INFO;
  1175. addPacket.dwVID = m_vid;
  1176.  
  1177. addPacket.awPart[CHR_EQUIPPART_ARMOR] = GetPart(PART_MAIN);
  1178. addPacket.awPart[CHR_EQUIPPART_WEAPON] = GetPart(PART_WEAPON);
  1179. addPacket.awPart[CHR_EQUIPPART_HEAD] = GetPart(PART_HEAD);
  1180. addPacket.awPart[CHR_EQUIPPART_HAIR] = GetPart(PART_HAIR);
  1181. #ifdef __SASH_SYSTEM__
  1182. addPacket.awPart[CHR_EQUIPPART_SASH] = GetPart(PART_SASH);
  1183. #endif
  1184. #ifdef __NEW_ARROW_SYSTEM__
  1185. addPacket.awPart[CHR_PART_ARROW_TYPE] = GetPart(PART_ARROW_TYPE);
  1186. #endif
  1187. addPacket.bPKMode = m_bPKMode;
  1188. addPacket.dwMountVnum = GetMountVnum();
  1189. addPacket.bEmpire = m_bEmpire;
  1190. #ifdef __ENABLE_BATTLE_FIELD__
  1191. addPacket.bBattleRank = GetBattleRank();
  1192. #endif
  1193.  
  1194. #ifdef NEW_PET_SYSTEM
  1195. if (IsPC() == true || IsNewPet() == true)
  1196. #else
  1197. if (IsPC() == true && (LC_IsEurope() == true || LC_IsCanada() == true || LC_IsSingapore() == true))
  1198. #endif
  1199. {
  1200. addPacket.dwLevel = GetLevel();
  1201. }
  1202. else
  1203. {
  1204. addPacket.dwLevel = 0;
  1205. }
  1206.  
  1207. if (false)
  1208. {
  1209. LPCHARACTER ch = (LPCHARACTER) entity;
  1210.  
  1211. if (GetEmpire() == ch->GetEmpire() || ch->GetGMLevel() > GM_PLAYER || m_bCharType == CHAR_TYPE_NPC)
  1212. {
  1213. goto show_all_info;
  1214. }
  1215. else
  1216. {
  1217. memset(addPacket.name, 0, CHARACTER_NAME_MAX_LEN);
  1218. addPacket.dwGuildID = 0;
  1219. addPacket.sAlignment = 0;
  1220. #ifdef __TITLE_SYSTEM__
  1221. addPacket.iTitleID = 0;
  1222. #endif
  1223. }
  1224. }
  1225. else
  1226. {
  1227. show_all_info:
  1228. #if defined(SHOP_HIDE_NAME) && defined(OFFLINE_SHOP)
  1229. if (IsPC() || GetRaceNum() != 30000 && !IsPrivShop())
  1230. #endif
  1231. strlcpy(addPacket.name, GetName(), sizeof(addPacket.name));
  1232.  
  1233. if (GetGuild() != NULL)
  1234. {
  1235. addPacket.dwGuildID = GetGuild()->GetID();
  1236. #ifdef WJ_GUILD_LEADER_SYSTEM
  1237. CGuild* pGuild = this->GetGuild();
  1238. if (pGuild->GetMasterPID() == GetPlayerID())
  1239. addPacket.dwNewIsGuildName = 3;
  1240.  
  1241. else if (pGuild->NewIsGuildGeneral(GetPlayerID()) == true)
  1242. addPacket.dwNewIsGuildName = 2;
  1243.  
  1244. else
  1245. addPacket.dwNewIsGuildName = 1;
  1246. #endif
  1247. }
  1248. else
  1249. {
  1250. addPacket.dwGuildID = 0;
  1251. #ifdef WJ_GUILD_LEADER_SYSTEM
  1252. addPacket.dwNewIsGuildName = 0;
  1253. #endif
  1254. }
  1255.  
  1256. addPacket.sAlignment = m_iAlignment / 10;
  1257. #ifdef __TITLE_SYSTEM__
  1258. addPacket.iTitleID = GetPoint(POINT_TITLE);
  1259. #endif
  1260. }
  1261.  
  1262. #ifdef __ENABLE_BATTLE_FIELD__
  1263. if (CBattleZone::instance().IsBattleZoneMapIndex(GetMapIndex()))
  1264. {
  1265. memset(addPacket.name, 0, CHARACTER_NAME_MAX_LEN);
  1266. addPacket.sAlignment = 0;
  1267. addPacket.dwGuildID = 0;
  1268. addPacket.dwLevel = 0;
  1269. addPacket.bBattleRank = 0;
  1270. }
  1271. #endif
  1272.  
  1273. d->Packet(&addPacket, sizeof(TPacketGCCharacterAdditionalInfo));
  1274. }
  1275.  
  1276. if (iDur)
  1277. {
  1278. TPacketGCMove pack;
  1279. EncodeMovePacket(pack, GetVID(), FUNC_MOVE, 0, m_posDest.x, m_posDest.y, iDur, 0, (BYTE) (GetRotation() / 5));
  1280. d->Packet(&pack, sizeof(pack));
  1281.  
  1282. TPacketGCWalkMode p;
  1283. p.vid = GetVID();
  1284. p.header = HEADER_GC_WALK_MODE;
  1285. p.mode = m_bNowWalking ? WALKMODE_WALK : WALKMODE_RUN;
  1286.  
  1287. d->Packet(&p, sizeof(p));
  1288. }
  1289.  
  1290. if (entity->IsType(ENTITY_CHARACTER) && GetDesc())
  1291. {
  1292. LPCHARACTER ch = (LPCHARACTER) entity;
  1293. if (ch->IsWalking())
  1294. {
  1295. TPacketGCWalkMode p;
  1296. p.vid = ch->GetVID();
  1297. p.header = HEADER_GC_WALK_MODE;
  1298. p.mode = ch->m_bNowWalking ? WALKMODE_WALK : WALKMODE_RUN;
  1299. GetDesc()->Packet(&p, sizeof(p));
  1300. }
  1301. }
  1302.  
  1303. if (GetMyShop())
  1304. {
  1305. TPacketGCShopSign p;
  1306.  
  1307. p.bHeader = HEADER_GC_SHOP_SIGN;
  1308. p.dwVID = GetVID();
  1309. strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
  1310.  
  1311. d->Packet(&p, sizeof(TPacketGCShopSign));
  1312. }
  1313.  
  1314. if (entity->IsType(ENTITY_CHARACTER))
  1315. {
  1316. sys_log(3, "EntityInsert %s (RaceNum %d) (%d %d) TO %s",
  1317. GetName(), GetRaceNum(), GetX() / SECTREE_SIZE, GetY() / SECTREE_SIZE, ((LPCHARACTER)entity)->GetName());
  1318. }
  1319. }
  1320.  
  1321. void CHARACTER::EncodeRemovePacket(LPENTITY entity)
  1322. {
  1323. if (entity->GetType() != ENTITY_CHARACTER)
  1324. return;
  1325.  
  1326. LPDESC d;
  1327.  
  1328. if (!(d = entity->GetDesc()))
  1329. return;
  1330.  
  1331. TPacketGCCharacterDelete pack;
  1332.  
  1333. pack.header = HEADER_GC_CHARACTER_DEL;
  1334. pack.id = m_vid;
  1335.  
  1336. d->Packet(&pack, sizeof(TPacketGCCharacterDelete));
  1337.  
  1338. if (entity->IsType(ENTITY_CHARACTER))
  1339. sys_log(3, "EntityRemove %s(%d) FROM %s", GetName(), (DWORD) m_vid, ((LPCHARACTER) entity)->GetName());
  1340. }
  1341.  
  1342. void CHARACTER::UpdatePacket()
  1343. {
  1344. if (GetSectree() == NULL) return;
  1345.  
  1346. TPacketGCCharacterUpdate pack;
  1347. TPacketGCCharacterUpdate pack2;
  1348.  
  1349. pack.header = HEADER_GC_CHARACTER_UPDATE;
  1350. pack.dwVID = m_vid;
  1351.  
  1352. pack.awPart[CHR_EQUIPPART_ARMOR] = GetPart(PART_MAIN);
  1353. pack.awPart[CHR_EQUIPPART_WEAPON] = GetPart(PART_WEAPON);
  1354. pack.awPart[CHR_EQUIPPART_HEAD] = GetPart(PART_HEAD);
  1355. pack.awPart[CHR_EQUIPPART_HAIR] = GetPart(PART_HAIR);
  1356. #ifdef __SASH_SYSTEM__
  1357. pack.awPart[CHR_EQUIPPART_SASH] = GetPart(PART_SASH);
  1358. #endif
  1359.  
  1360. pack.bMovingSpeed = GetLimitPoint(POINT_MOV_SPEED);
  1361. pack.bAttackSpeed = GetLimitPoint(POINT_ATT_SPEED);
  1362. pack.bStateFlag = m_bAddChrState;
  1363. pack.dwAffectFlag[0] = m_afAffectFlag.bits[0];
  1364. pack.dwAffectFlag[1] = m_afAffectFlag.bits[1];
  1365. pack.dwGuildID = 0;
  1366.  
  1367. #ifdef __ENABLE_BATTLE_FIELD__
  1368. bool isBattle = CBattleZone::instance().IsBattleZoneMapIndex(GetMapIndex());
  1369.  
  1370. pack.sAlignment = isBattle ? 0 : m_iAlignment / 10;
  1371. pack.bBattleRank = IsPC() && !isBattle ? GetBattleRank() : 0;
  1372. #else
  1373. pack.sAlignment = m_iAlignment / 10;
  1374. #endif
  1375.  
  1376. #ifdef ENABLE_SUPPORT_SYSTEM
  1377. if(IsSupport())
  1378. {
  1379. pack.awPart[CHR_EQUIPPART_ARMOR] = GetSupportArmor();
  1380. pack.awPart[CHR_EQUIPPART_WEAPON] = GetSupportWeapon();
  1381. pack.awPart[CHR_EQUIPPART_HAIR] = GetSupportHair();
  1382. }
  1383. #endif
  1384. #ifdef NEW_PET_SYSTEM
  1385. pack.dwLevel = GetLevel();
  1386. #endif
  1387. pack.bPKMode = m_bPKMode;
  1388. #ifdef __TITLE_SYSTEM__
  1389. pack.iTitleID = GetPoint(POINT_TITLE);
  1390. #endif
  1391.  
  1392. #ifdef __ENABLE_BATTLE_FIELD__
  1393. if (GetGuild() && !isBattle)
  1394. pack.dwGuildID = GetGuild()->GetID();
  1395. #else
  1396. if (GetGuild())
  1397. pack.dwGuildID = GetGuild()->GetID();
  1398. #endif
  1399. #ifdef WJ_GUILD_LEADER_SYSTEM
  1400. CGuild* pGuild = this->GetGuild();
  1401. if (pGuild)
  1402. {
  1403. if (pGuild->GetMasterPID() == GetPlayerID())
  1404. pack.dwNewIsGuildName = 3;
  1405. else if (pGuild->NewIsGuildGeneral(GetPlayerID()) == true)
  1406. pack.dwNewIsGuildName = 2;
  1407. else
  1408. pack.dwNewIsGuildName = 1;
  1409. }
  1410. else
  1411. {
  1412. pack.dwNewIsGuildName = 0;
  1413. }
  1414. #endif
  1415.  
  1416. pack.dwMountVnum = GetMountVnum();
  1417.  
  1418. pack2 = pack;
  1419. pack2.dwGuildID = 0;
  1420. pack2.sAlignment = 0;
  1421. #ifdef __TITLE_SYSTEM__
  1422. pack.iTitleID = GetPoint(POINT_TITLE);
  1423. #endif
  1424. #ifdef NEW_PET_SYSTEM
  1425. pack2.dwLevel = 0;
  1426. #endif
  1427.  
  1428.  
  1429. if (false)
  1430. {
  1431. if (m_bIsObserver != true)
  1432. {
  1433. for (ENTITY_MAP::iterator iter = m_map_view.begin(); iter != m_map_view.end(); iter++)
  1434. {
  1435. LPENTITY pEntity = iter->first;
  1436.  
  1437. if (pEntity != NULL)
  1438. {
  1439. if (pEntity->IsType(ENTITY_CHARACTER) == true)
  1440. {
  1441. if (pEntity->GetDesc() != NULL)
  1442. {
  1443. LPCHARACTER pChar = (LPCHARACTER)pEntity;
  1444.  
  1445. if (GetEmpire() == pChar->GetEmpire() || pChar->GetGMLevel() > GM_PLAYER)
  1446. {
  1447. pEntity->GetDesc()->Packet(&pack, sizeof(pack));
  1448. }
  1449. else
  1450. {
  1451. pEntity->GetDesc()->Packet(&pack2, sizeof(pack2));
  1452. }
  1453. }
  1454. }
  1455. else
  1456. {
  1457. if (pEntity->GetDesc() != NULL)
  1458. {
  1459. pEntity->GetDesc()->Packet(&pack, sizeof(pack));
  1460. }
  1461. }
  1462. }
  1463. }
  1464. }
  1465.  
  1466. if (GetDesc() != NULL)
  1467. {
  1468. GetDesc()->Packet(&pack, sizeof(pack));
  1469. }
  1470. }
  1471. else
  1472. {
  1473. PacketAround(&pack, sizeof(pack));
  1474. }
  1475. }
  1476.  
  1477. LPCHARACTER CHARACTER::FindCharacterInView(const char * c_pszName, bool bFindPCOnly)
  1478. {
  1479. ENTITY_MAP::iterator it = m_map_view.begin();
  1480.  
  1481. for (; it != m_map_view.end(); ++it)
  1482. {
  1483. if (!it->first->IsType(ENTITY_CHARACTER))
  1484. continue;
  1485.  
  1486. LPCHARACTER tch = (LPCHARACTER) it->first;
  1487.  
  1488. if (bFindPCOnly && tch->IsNPC())
  1489. continue;
  1490.  
  1491. if (!strcasecmp(tch->GetName(), c_pszName))
  1492. return (tch);
  1493. }
  1494.  
  1495. return NULL;
  1496. }
  1497.  
  1498. void CHARACTER::SetPosition(int pos)
  1499. {
  1500. if (pos == POS_STANDING)
  1501. {
  1502. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_DEAD);
  1503. REMOVE_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_STUN);
  1504.  
  1505. event_cancel(&m_pkDeadEvent);
  1506. event_cancel(&m_pkStunEvent);
  1507. }
  1508. else if (pos == POS_DEAD)
  1509. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_DEAD);
  1510.  
  1511. if (!IsStone())
  1512. {
  1513. switch (pos)
  1514. {
  1515. case POS_FIGHTING:
  1516. if (!IsState(m_stateBattle))
  1517. MonsterLog("[BATTLE] ½Î¿ì´Â »óÅÂ");
  1518.  
  1519. GotoState(m_stateBattle);
  1520. break;
  1521.  
  1522. default:
  1523. if (!IsState(m_stateIdle))
  1524. MonsterLog("[IDLE] ½¬´Â »óÅÂ");
  1525.  
  1526. GotoState(m_stateIdle);
  1527. break;
  1528. }
  1529. }
  1530.  
  1531. m_pointsInstant.position = pos;
  1532. }
  1533.  
  1534. void CHARACTER::Save()
  1535. {
  1536. if (!m_bSkipSave)
  1537. CHARACTER_MANAGER::instance().DelayedSave(this);
  1538. }
  1539.  
  1540. void CHARACTER::CreatePlayerProto(TPlayerTable & tab)
  1541. {
  1542. memset(&tab, 0, sizeof(TPlayerTable));
  1543.  
  1544. if (GetNewName().empty())
  1545. {
  1546. strlcpy(tab.name, GetName(), sizeof(tab.name));
  1547. }
  1548. else
  1549. {
  1550. strlcpy(tab.name, GetNewName().c_str(), sizeof(tab.name));
  1551. }
  1552.  
  1553. strlcpy(tab.ip, GetDesc()->GetHostName(), sizeof(tab.ip));
  1554.  
  1555. tab.id = m_dwPlayerID;
  1556. tab.voice = GetPoint(POINT_VOICE);
  1557. tab.level = GetLevel();
  1558. tab.level_step = GetPoint(POINT_LEVEL_STEP);
  1559. tab.exp = GetExp();
  1560. tab.gold = GetGold();
  1561. #ifdef ENABLE_GEM_SYSTEM
  1562. tab.gem = GetGem();
  1563. #endif
  1564. #ifdef __ENABLE_BATTLE_FIELD__
  1565. tab.battlePoint = GetBattlePoints();
  1566. #endif
  1567. tab.job = m_points.job;
  1568. tab.part_base = m_pointsInstant.bBasePart;
  1569. tab.skill_group = m_points.skill_group;
  1570.  
  1571. DWORD dwPlayedTime = (get_dword_time() - m_dwPlayStartTime);
  1572.  
  1573. if (dwPlayedTime > 60000)
  1574. {
  1575. if (GetSectree() && !GetSectree()->IsAttr(GetX(), GetY(), ATTR_BANPK))
  1576. {
  1577. if (GetRealAlignment() < 0)
  1578. {
  1579. if (IsEquipUniqueItem(UNIQUE_ITEM_FASTER_ALIGNMENT_UP_BY_TIME))
  1580. UpdateAlignment(120 * (dwPlayedTime / 60000));
  1581. else
  1582. UpdateAlignment(60 * (dwPlayedTime / 60000));
  1583. }
  1584. else
  1585. UpdateAlignment(5 * (dwPlayedTime / 60000));
  1586. }
  1587.  
  1588. SetRealPoint(POINT_PLAYTIME, GetRealPoint(POINT_PLAYTIME) + dwPlayedTime / 60000);
  1589. ResetPlayTime(dwPlayedTime % 60000);
  1590. }
  1591.  
  1592. tab.playtime = GetRealPoint(POINT_PLAYTIME);
  1593. tab.lAlignment = m_iRealAlignment;
  1594.  
  1595. if (m_posWarp.x != 0 || m_posWarp.y != 0)
  1596. {
  1597. tab.x = m_posWarp.x;
  1598. tab.y = m_posWarp.y;
  1599. tab.z = 0;
  1600. tab.lMapIndex = m_lWarpMapIndex;
  1601. }
  1602. else
  1603. {
  1604. tab.x = GetX();
  1605. tab.y = GetY();
  1606. tab.z = GetZ();
  1607. tab.lMapIndex = GetMapIndex();
  1608. }
  1609.  
  1610. if (m_lExitMapIndex == 0)
  1611. {
  1612. tab.lExitMapIndex = tab.lMapIndex;
  1613. tab.lExitX = tab.x;
  1614. tab.lExitY = tab.y;
  1615. }
  1616. else
  1617. {
  1618. tab.lExitMapIndex = m_lExitMapIndex;
  1619. tab.lExitX = m_posExit.x;
  1620. tab.lExitY = m_posExit.y;
  1621. }
  1622.  
  1623. sys_log(0, "SAVE: %s %dx%d", GetName(), tab.x, tab.y);
  1624.  
  1625. tab.st = GetRealPoint(POINT_ST);
  1626. tab.ht = GetRealPoint(POINT_HT);
  1627. tab.dx = GetRealPoint(POINT_DX);
  1628. tab.iq = GetRealPoint(POINT_IQ);
  1629.  
  1630. tab.stat_point = GetPoint(POINT_STAT);
  1631. tab.skill_point = GetPoint(POINT_SKILL);
  1632. tab.sub_skill_point = GetPoint(POINT_SUB_SKILL);
  1633. tab.horse_skill_point = GetPoint(POINT_HORSE_SKILL);
  1634.  
  1635. tab.stat_reset_count = GetPoint(POINT_STAT_RESET_COUNT);
  1636.  
  1637. tab.hp = GetHP();
  1638. tab.sp = GetSP();
  1639.  
  1640. tab.stamina = GetStamina();
  1641.  
  1642. tab.sRandomHP = m_points.iRandomHP;
  1643. tab.sRandomSP = m_points.iRandomSP;
  1644.  
  1645. for (int i = 0; i < QUICKSLOT_MAX_NUM; ++i)
  1646. tab.quickslot[i] = m_quickslot[i];
  1647.  
  1648. if (m_stMobile.length() && !*m_szMobileAuth)
  1649. strlcpy(tab.szMobile, m_stMobile.c_str(), sizeof(tab.szMobile));
  1650.  
  1651. thecore_memcpy(tab.parts, m_pointsInstant.parts, sizeof(tab.parts));
  1652.  
  1653. // REMOVE_REAL_SKILL_LEVLES
  1654. thecore_memcpy(tab.skills, m_pSkillLevels, sizeof(TPlayerSkill) * SKILL_MAX_NUM);
  1655. // END_OF_REMOVE_REAL_SKILL_LEVLES
  1656.  
  1657. #ifdef ENABLE_FISH_EVENT
  1658. thecore_memcpy(tab.fishSlots, m_fishSlots, sizeof(TPlayerFishEventSlot) * FISH_EVENT_SLOTS_NUM);
  1659. tab.fishEventUseCount = GetFishEventUseCount();
  1660. #endif
  1661.  
  1662. #ifdef ENABLE_GEM_SYSTEM
  1663. thecore_memcpy(tab.gemItems, m_gemItems, sizeof(TPlayerGemItems) * GEM_SLOTS_MAX_NUM);
  1664. tab.gem_next_refresh = GetGemNextRefresh();
  1665. #endif
  1666.  
  1667. tab.horse = GetHorseData();
  1668. #ifdef __TITLE_SYSTEM__
  1669. tab.iTChoosed = GetPoint(POINT_TITLE);
  1670. strlcpy(tab.cTAvailable, GetTitlesAvailable(), sizeof(tab.cTAvailable));
  1671. #endif
  1672. }
  1673.  
  1674.  
  1675. void CHARACTER::SaveReal()
  1676. {
  1677. if (m_bSkipSave)
  1678. return;
  1679.  
  1680. if (!GetDesc())
  1681. {
  1682. sys_err("Character::Save : no descriptor when saving (name: %s)", GetName());
  1683. return;
  1684. }
  1685.  
  1686. TPlayerTable table;
  1687. CreatePlayerProto(table);
  1688.  
  1689. db_clientdesc->DBPacket(HEADER_GD_PLAYER_SAVE, GetDesc()->GetHandle(), &table, sizeof(TPlayerTable));
  1690.  
  1691. quest::PC * pkQuestPC = quest::CQuestManager::instance().GetPCForce(GetPlayerID());
  1692.  
  1693. if (!pkQuestPC)
  1694. sys_err("CHARACTER::Save : null quest::PC pointer! (name %s)", GetName());
  1695. else
  1696. {
  1697. pkQuestPC->Save();
  1698. }
  1699.  
  1700. marriage::TMarriage* pMarriage = marriage::CManager::instance().Get(GetPlayerID());
  1701. if (pMarriage)
  1702. pMarriage->Save();
  1703. }
  1704.  
  1705. void CHARACTER::FlushDelayedSaveItem()
  1706. {
  1707. // ÀúÀå ¾ÈµÈ ¼ÒÁöǰÀ» ÀüºÎ ÀúÀå½ÃŲ´Ù.
  1708. LPITEM item;
  1709.  
  1710. for (int i = 0; i < INVENTORY_AND_EQUIP_SLOT_MAX; ++i)
  1711. if ((item = GetInventoryItem(i)))
  1712. ITEM_MANAGER::instance().FlushDelayedSave(item);
  1713. }
  1714.  
  1715. void CHARACTER::Disconnect(const char * c_pszReason)
  1716. {
  1717. assert(GetDesc() != NULL);
  1718.  
  1719. sys_log(0, "DISCONNECT: %s (%s)", GetName(), c_pszReason ? c_pszReason : "unset" );
  1720.  
  1721. if (GetShop())
  1722. {
  1723. GetShop()->RemoveGuest(this);
  1724. SetShop(NULL);
  1725. }
  1726.  
  1727. if (GetArena() != NULL)
  1728. {
  1729. GetArena()->OnDisconnect(GetPlayerID());
  1730. }
  1731.  
  1732. if (GetParty() != NULL)
  1733. {
  1734. GetParty()->UpdateOfflineState(GetPlayerID());
  1735. }
  1736.  
  1737. marriage::CManager::instance().Logout(this);
  1738.  
  1739. #ifdef ENABLE_FEATURES_OXEVENT
  1740. COXEventManager::instance().Disconnect(this);
  1741. #endif
  1742.  
  1743. // P2P Logout
  1744. TPacketGGLogout p;
  1745. p.bHeader = HEADER_GG_LOGOUT;
  1746. strlcpy(p.szName, GetName(), sizeof(p.szName));
  1747. P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGLogout));
  1748. LogManager::instance().CharLog(this, 0, "LOGOUT", "");
  1749. #ifdef __MELEY_LAIR_DUNGEON__
  1750. if (MeleyLair::CMgr::instance().IsMeleyMap(GetMapIndex()))
  1751. MeleyLair::CMgr::instance().Leave(GetGuild(), this, false);
  1752. #endif
  1753. #ifdef ENABLE_PCBANG_FEATURE // @warme006
  1754. {
  1755. long playTime = GetRealPoint(POINT_PLAYTIME) - m_dwLoginPlayTime;
  1756. LogManager::instance().LoginLog(false, GetDesc()->GetAccountTable().id, GetPlayerID(), GetLevel(), GetJob(), playTime);
  1757.  
  1758. if (0)
  1759. CPCBangManager::instance().Log(GetDesc()->GetHostName(), GetPlayerID(), playTime);
  1760. }
  1761. #endif
  1762.  
  1763. if (m_pWarMap)
  1764. SetWarMap(NULL);
  1765.  
  1766. if (m_pWeddingMap)
  1767. {
  1768. SetWeddingMap(NULL);
  1769. }
  1770.  
  1771. if (GetGuild())
  1772. GetGuild()->LogoutMember(this);
  1773.  
  1774. quest::CQuestManager::instance().LogoutPC(this);
  1775.  
  1776.  
  1777. if (GetParty())
  1778. GetParty()->Unlink(this);
  1779.  
  1780. // Á×¾úÀ» ¶§ Á¢¼Ó²÷À¸¸é °æÇèÄ¡ ÁÙ°Ô Çϱâ
  1781. if (IsStun() || IsDead())
  1782. {
  1783. DeathPenalty(0);
  1784. PointChange(POINT_HP, 50 - GetHP());
  1785. }
  1786.  
  1787.  
  1788. if (!CHARACTER_MANAGER::instance().FlushDelayedSave(this))
  1789. {
  1790. SaveReal();
  1791. }
  1792.  
  1793. FlushDelayedSaveItem();
  1794.  
  1795. SaveAffect();
  1796. m_bIsLoadedAffect = false;
  1797.  
  1798. m_bSkipSave = true; // ÀÌ ÀÌÈÄ¿¡´Â ´õÀÌ»ó ÀúÀåÇÏ¸é ¾ÈµÈ´Ù.
  1799.  
  1800. quest::CQuestManager::instance().DisconnectPC(this);
  1801.  
  1802. CloseSafebox();
  1803.  
  1804. CloseMall();
  1805.  
  1806. CPVPManager::instance().Disconnect(this);
  1807.  
  1808. CTargetManager::instance().Logout(GetPlayerID());
  1809.  
  1810. MessengerManager::instance().Logout(GetName());
  1811.  
  1812. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  1813. if(GetMountVnum())
  1814. {
  1815. RemoveAffect(AFFECT_MOUNT);
  1816. RemoveAffect(AFFECT_MOUNT_BONUS);
  1817. }
  1818. #endif
  1819.  
  1820. if (g_TeenDesc)
  1821. {
  1822. int offset = 0;
  1823. char buf[245] = {0};
  1824.  
  1825. buf[0] = HEADER_GT_LOGOUT;
  1826. offset += 1;
  1827.  
  1828. memset(buf+offset, 0x00, 2);
  1829. offset += 2;
  1830.  
  1831. TAccountTable &acc_table = GetDesc()->GetAccountTable();
  1832. memcpy(buf+offset, &acc_table.id, 4);
  1833. offset += 4;
  1834.  
  1835. g_TeenDesc->Packet(buf, offset);
  1836. }
  1837.  
  1838. if (GetDesc())
  1839. {
  1840. GetDesc()->BindCharacter(NULL);
  1841. // BindDesc(NULL);
  1842. }
  1843.  
  1844. CXTrapManager::instance().DestroyClientSession(this);
  1845.  
  1846. M2_DESTROY_CHARACTER(this);
  1847. }
  1848.  
  1849. bool CHARACTER::Show(long lMapIndex, long x, long y, long z, bool bShowSpawnMotion/* = false */)
  1850. {
  1851. LPSECTREE sectree = SECTREE_MANAGER::instance().Get(lMapIndex, x, y);
  1852.  
  1853. if (!sectree)
  1854. {
  1855. sys_log(0, "cannot find sectree by %dx%d mapindex %d", x, y, lMapIndex);
  1856. return false;
  1857. }
  1858.  
  1859. SetMapIndex(lMapIndex);
  1860.  
  1861. bool bChangeTree = false;
  1862.  
  1863. if (!GetSectree() || GetSectree() != sectree)
  1864. bChangeTree = true;
  1865.  
  1866. if (bChangeTree)
  1867. {
  1868. if (GetSectree())
  1869. GetSectree()->RemoveEntity(this);
  1870.  
  1871. ViewCleanup();
  1872. }
  1873.  
  1874. if (!IsNPC())
  1875. {
  1876. sys_log(0, "SHOW: %s %dx%dx%d", GetName(), x, y, z);
  1877. if (GetStamina() < GetMaxStamina())
  1878. StartAffectEvent();
  1879. }
  1880. else if (m_pkMobData)
  1881. {
  1882. m_pkMobInst->m_posLastAttacked.x = x;
  1883. m_pkMobInst->m_posLastAttacked.y = y;
  1884. m_pkMobInst->m_posLastAttacked.z = z;
  1885. }
  1886.  
  1887. if (bShowSpawnMotion)
  1888. {
  1889. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  1890. m_afAffectFlag.Set(AFF_SPAWN);
  1891. }
  1892.  
  1893. SetXYZ(x, y, z);
  1894.  
  1895. m_posDest.x = x;
  1896. m_posDest.y = y;
  1897. m_posDest.z = z;
  1898.  
  1899. m_posStart.x = x;
  1900. m_posStart.y = y;
  1901. m_posStart.z = z;
  1902.  
  1903. if (bChangeTree)
  1904. {
  1905. EncodeInsertPacket(this);
  1906. sectree->InsertEntity(this);
  1907.  
  1908. UpdateSectree();
  1909. }
  1910. else
  1911. {
  1912. ViewReencode();
  1913. sys_log(0, " in same sectree");
  1914. }
  1915.  
  1916. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  1917.  
  1918. SetValidComboInterval(0);
  1919. return true;
  1920. }
  1921.  
  1922. // BGM_INFO
  1923. struct BGMInfo
  1924. {
  1925. std::string name;
  1926. float vol;
  1927. };
  1928.  
  1929. typedef std::map<unsigned, BGMInfo> BGMInfoMap;
  1930.  
  1931. static BGMInfoMap gs_bgmInfoMap;
  1932. static bool gs_bgmVolEnable = false;
  1933.  
  1934. void CHARACTER_SetBGMVolumeEnable()
  1935. {
  1936. gs_bgmVolEnable = true;
  1937. sys_log(0, "bgm_info.set_bgm_volume_enable");
  1938. }
  1939.  
  1940. void CHARACTER_AddBGMInfo(unsigned mapIndex, const char* name, float vol)
  1941. {
  1942. BGMInfo newInfo;
  1943. newInfo.name = name;
  1944. newInfo.vol = vol;
  1945.  
  1946. gs_bgmInfoMap[mapIndex] = newInfo;
  1947.  
  1948. sys_log(0, "bgm_info.add_info(%d, '%s', %f)", mapIndex, name, vol);
  1949. }
  1950.  
  1951. const BGMInfo& CHARACTER_GetBGMInfo(unsigned mapIndex)
  1952. {
  1953. BGMInfoMap::iterator f = gs_bgmInfoMap.find(mapIndex);
  1954. if (gs_bgmInfoMap.end() == f)
  1955. {
  1956. static BGMInfo s_empty = {"", 0.0f};
  1957. return s_empty;
  1958. }
  1959. return f->second;
  1960. }
  1961.  
  1962. bool CHARACTER_IsBGMVolumeEnable()
  1963. {
  1964. return gs_bgmVolEnable;
  1965. }
  1966. // END_OF_BGM_INFO
  1967.  
  1968. void CHARACTER::MainCharacterPacket()
  1969. {
  1970. const unsigned mapIndex = GetMapIndex();
  1971. const BGMInfo& bgmInfo = CHARACTER_GetBGMInfo(mapIndex);
  1972.  
  1973. // SUPPORT_BGM
  1974. if (!bgmInfo.name.empty())
  1975. {
  1976. if (CHARACTER_IsBGMVolumeEnable())
  1977. {
  1978. sys_log(1, "bgm_info.play_bgm_vol(%d, name='%s', vol=%f)", mapIndex, bgmInfo.name.c_str(), bgmInfo.vol);
  1979. TPacketGCMainCharacter4_BGM_VOL mainChrPacket;
  1980. mainChrPacket.header = HEADER_GC_MAIN_CHARACTER4_BGM_VOL;
  1981. mainChrPacket.dwVID = m_vid;
  1982. mainChrPacket.wRaceNum = GetRaceNum();
  1983. mainChrPacket.lx = GetX();
  1984. mainChrPacket.ly = GetY();
  1985. mainChrPacket.lz = GetZ();
  1986. mainChrPacket.empire = GetDesc()->GetEmpire();
  1987. mainChrPacket.skill_group = GetSkillGroup();
  1988. strlcpy(mainChrPacket.szChrName, GetName(), sizeof(mainChrPacket.szChrName));
  1989.  
  1990. mainChrPacket.fBGMVol = bgmInfo.vol;
  1991. strlcpy(mainChrPacket.szBGMName, bgmInfo.name.c_str(), sizeof(mainChrPacket.szBGMName));
  1992. GetDesc()->Packet(&mainChrPacket, sizeof(TPacketGCMainCharacter4_BGM_VOL));
  1993. }
  1994. else
  1995. {
  1996. sys_log(1, "bgm_info.play(%d, '%s')", mapIndex, bgmInfo.name.c_str());
  1997. TPacketGCMainCharacter3_BGM mainChrPacket;
  1998. mainChrPacket.header = HEADER_GC_MAIN_CHARACTER3_BGM;
  1999. mainChrPacket.dwVID = m_vid;
  2000. mainChrPacket.wRaceNum = GetRaceNum();
  2001. mainChrPacket.lx = GetX();
  2002. mainChrPacket.ly = GetY();
  2003. mainChrPacket.lz = GetZ();
  2004. mainChrPacket.empire = GetDesc()->GetEmpire();
  2005. mainChrPacket.skill_group = GetSkillGroup();
  2006. strlcpy(mainChrPacket.szChrName, GetName(), sizeof(mainChrPacket.szChrName));
  2007. strlcpy(mainChrPacket.szBGMName, bgmInfo.name.c_str(), sizeof(mainChrPacket.szBGMName));
  2008. GetDesc()->Packet(&mainChrPacket, sizeof(TPacketGCMainCharacter3_BGM));
  2009. }
  2010. //if (m_stMobile.length())
  2011. // ChatPacket(CHAT_TYPE_COMMAND, "sms");
  2012. }
  2013. // END_OF_SUPPORT_BGM
  2014. else
  2015. {
  2016. sys_log(0, "bgm_info.play(%d, DEFAULT_BGM_NAME)", mapIndex);
  2017.  
  2018. TPacketGCMainCharacter pack;
  2019. pack.header = HEADER_GC_MAIN_CHARACTER;
  2020. pack.dwVID = m_vid;
  2021. pack.wRaceNum = GetRaceNum();
  2022. pack.lx = GetX();
  2023. pack.ly = GetY();
  2024. pack.lz = GetZ();
  2025. pack.empire = GetDesc()->GetEmpire();
  2026. pack.skill_group = GetSkillGroup();
  2027. strlcpy(pack.szName, GetName(), sizeof(pack.szName));
  2028. GetDesc()->Packet(&pack, sizeof(TPacketGCMainCharacter));
  2029.  
  2030. if (m_stMobile.length())
  2031. ChatPacket(CHAT_TYPE_COMMAND, "sms");
  2032. }
  2033. }
  2034.  
  2035. void CHARACTER::PointsPacket()
  2036. {
  2037. if (!GetDesc())
  2038. return;
  2039.  
  2040. TPacketGCPoints pack;
  2041.  
  2042. pack.header = HEADER_GC_CHARACTER_POINTS;
  2043.  
  2044. pack.points[POINT_LEVEL] = GetLevel();
  2045. pack.points[POINT_EXP] = GetExp();
  2046. pack.points[POINT_NEXT_EXP] = GetNextExp();
  2047. pack.points[POINT_HP] = GetHP();
  2048. pack.points[POINT_MAX_HP] = GetMaxHP();
  2049. pack.points[POINT_SP] = GetSP();
  2050. pack.points[POINT_MAX_SP] = GetMaxSP();
  2051. pack.points[POINT_GOLD] = GetGold();
  2052. pack.points[POINT_STAMINA] = GetStamina();
  2053. pack.points[POINT_MAX_STAMINA] = GetMaxStamina();
  2054.  
  2055. for (int i = POINT_ST; i < POINT_MAX_NUM; ++i)
  2056. pack.points[i] = GetPoint(i);
  2057.  
  2058. #ifdef ENABLE_GEM_SYSTEM
  2059. pack.points[POINT_GEM] = GetGem();
  2060. #endif
  2061. #ifdef __ENABLE_BATTLE_FIELD__
  2062. pack.points[POINT_BATTLE_POINT] = GetBattlePoints();
  2063. pack.points[POINT_TEMP_BATTLE_POINT] = GetPoint(POINT_TEMP_BATTLE_POINT);
  2064. #endif
  2065. #ifdef __TITLE_SYSTEM__
  2066. for (int w = TITLE_0; w < TITLES_MAX_NUM; ++w)
  2067. {
  2068. BYTE bType = POINT_TITLE + w;
  2069. pack.points[bType] = GetPoint(bType);
  2070. }
  2071. #endif
  2072.  
  2073. GetDesc()->Packet(&pack, sizeof(TPacketGCPoints));
  2074. }
  2075.  
  2076. bool CHARACTER::ChangeSex()
  2077. {
  2078. int src_race = GetRaceNum();
  2079.  
  2080. switch (src_race)
  2081. {
  2082. case MAIN_RACE_WARRIOR_M:
  2083. m_points.job = MAIN_RACE_WARRIOR_W;
  2084. break;
  2085.  
  2086. case MAIN_RACE_WARRIOR_W:
  2087. m_points.job = MAIN_RACE_WARRIOR_M;
  2088. break;
  2089.  
  2090. case MAIN_RACE_ASSASSIN_M:
  2091. m_points.job = MAIN_RACE_ASSASSIN_W;
  2092. break;
  2093.  
  2094. case MAIN_RACE_ASSASSIN_W:
  2095. m_points.job = MAIN_RACE_ASSASSIN_M;
  2096. break;
  2097.  
  2098. case MAIN_RACE_SURA_M:
  2099. m_points.job = MAIN_RACE_SURA_W;
  2100. break;
  2101.  
  2102. case MAIN_RACE_SURA_W:
  2103. m_points.job = MAIN_RACE_SURA_M;
  2104. break;
  2105.  
  2106. case MAIN_RACE_SHAMAN_M:
  2107. m_points.job = MAIN_RACE_SHAMAN_W;
  2108. break;
  2109.  
  2110. case MAIN_RACE_SHAMAN_W:
  2111. m_points.job = MAIN_RACE_SHAMAN_M;
  2112. break;
  2113. #ifdef ENABLE_WOLFMAN_CHARACTER
  2114. case MAIN_RACE_WOLFMAN_M:
  2115. m_points.job = MAIN_RACE_WOLFMAN_M;
  2116. break;
  2117. #endif
  2118. default:
  2119. sys_err("CHANGE_SEX: %s unknown race %d", GetName(), src_race);
  2120. return false;
  2121. }
  2122.  
  2123. #ifdef __CHANGE_SEX_WR__
  2124. UpdatePacket();
  2125. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  2126. m_afAffectFlag.Set(AFF_SPAWN);
  2127. ViewReencode();
  2128. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  2129. m_afAffectFlag.Reset(AFF_SPAWN);
  2130. #endif
  2131. sys_log(0, "CHANGE_SEX: %s (%d -> %d)", GetName(), src_race, m_points.job);
  2132. return true;
  2133. }
  2134.  
  2135. WORD CHARACTER::GetRaceNum() const
  2136. {
  2137. if (m_dwPolymorphRace)
  2138. return m_dwPolymorphRace;
  2139.  
  2140. if (m_pkMobData)
  2141. return m_pkMobData->m_table.dwVnum;
  2142.  
  2143. return m_points.job;
  2144. }
  2145.  
  2146. void CHARACTER::SetRace(BYTE race)
  2147. {
  2148. if (race >= MAIN_RACE_MAX_NUM)
  2149. {
  2150. sys_err("CHARACTER::SetRace(name=%s, race=%d).OUT_OF_RACE_RANGE", GetName(), race);
  2151. return;
  2152. }
  2153.  
  2154. m_points.job = race;
  2155. }
  2156.  
  2157. BYTE CHARACTER::GetJob() const
  2158. {
  2159. #ifdef __FAKE_BUFF__
  2160. if (FakeBuff_Check())
  2161. return JOB_SHAMAN;
  2162. #endif
  2163.  
  2164. unsigned race = m_points.job;
  2165. unsigned job;
  2166.  
  2167. if (RaceToJob(race, &job))
  2168. return job;
  2169.  
  2170. sys_err("CHARACTER::GetJob(name=%s, race=%d).OUT_OF_RACE_RANGE", GetName(), race);
  2171. return JOB_WARRIOR;
  2172. }
  2173.  
  2174. void CHARACTER::SetLevel(BYTE level)
  2175. {
  2176. m_points.level = level;
  2177.  
  2178. if (IsPC())
  2179. {
  2180. if (level < PK_PROTECT_LEVEL)
  2181. SetPKMode(PK_MODE_PROTECT);
  2182. else if (GetGMLevel() != GM_PLAYER)
  2183. SetPKMode(PK_MODE_PROTECT);
  2184. else if (m_bPKMode == PK_MODE_PROTECT)
  2185. SetPKMode(PK_MODE_PEACE);
  2186. }
  2187. }
  2188.  
  2189. void CHARACTER::SetEmpire(BYTE bEmpire)
  2190. {
  2191. m_bEmpire = bEmpire;
  2192. }
  2193.  
  2194. void CHARACTER::SetPlayerProto(const TPlayerTable * t)
  2195. {
  2196. if (!GetDesc() || !*GetDesc()->GetHostName())
  2197. sys_err("cannot get desc or hostname");
  2198. else
  2199. SetGMLevel();
  2200.  
  2201. m_bCharType = CHAR_TYPE_PC;
  2202.  
  2203. m_dwPlayerID = t->id;
  2204.  
  2205. m_iAlignment = t->lAlignment;
  2206. m_iRealAlignment = t->lAlignment;
  2207.  
  2208. m_points.voice = t->voice;
  2209.  
  2210. m_points.skill_group = t->skill_group;
  2211.  
  2212. m_pointsInstant.bBasePart = t->part_base;
  2213. SetPart(PART_HAIR, t->parts[PART_HAIR]);
  2214. #ifdef __SASH_SYSTEM__
  2215. SetPart(PART_SASH, t->parts[PART_SASH]);
  2216. #endif
  2217.  
  2218. m_points.iRandomHP = t->sRandomHP;
  2219. m_points.iRandomSP = t->sRandomSP;
  2220.  
  2221. // REMOVE_REAL_SKILL_LEVLES
  2222. if (m_pSkillLevels)
  2223. M2_DELETE_ARRAY(m_pSkillLevels);
  2224.  
  2225. m_pSkillLevels = M2_NEW TPlayerSkill[SKILL_MAX_NUM];
  2226. thecore_memcpy(m_pSkillLevels, t->skills, sizeof(TPlayerSkill) * SKILL_MAX_NUM);
  2227. // END_OF_REMOVE_REAL_SKILL_LEVLES
  2228.  
  2229. #ifdef ENABLE_FISH_EVENT
  2230. if (m_fishSlots)
  2231. M2_DELETE_ARRAY(m_fishSlots);
  2232.  
  2233. m_fishSlots = M2_NEW TPlayerFishEventSlot[FISH_EVENT_SLOTS_NUM];
  2234. thecore_memcpy(m_fishSlots, t->fishSlots, sizeof(TPlayerFishEventSlot) * FISH_EVENT_SLOTS_NUM);
  2235.  
  2236. m_dwFishUseCount = t->fishEventUseCount;
  2237. #endif
  2238.  
  2239. #ifdef ENABLE_GEM_SYSTEM
  2240. if (m_gemItems)
  2241. M2_DELETE_ARRAY(m_gemItems);
  2242.  
  2243. m_gemItems = M2_NEW TPlayerGemItems[GEM_SLOTS_MAX_NUM];
  2244. thecore_memcpy(m_gemItems, t->gemItems, sizeof(TPlayerGemItems) * GEM_SLOTS_MAX_NUM);
  2245. #endif
  2246.  
  2247.  
  2248. if (t->lMapIndex >= 10000)
  2249. {
  2250. m_posWarp.x = t->lExitX;
  2251. m_posWarp.y = t->lExitY;
  2252. m_lWarpMapIndex = t->lExitMapIndex;
  2253. }
  2254.  
  2255. SetRealPoint(POINT_PLAYTIME, t->playtime);
  2256. m_dwLoginPlayTime = t->playtime;
  2257. SetRealPoint(POINT_ST, t->st);
  2258. SetRealPoint(POINT_HT, t->ht);
  2259. SetRealPoint(POINT_DX, t->dx);
  2260. SetRealPoint(POINT_IQ, t->iq);
  2261.  
  2262. SetPoint(POINT_ST, t->st);
  2263. SetPoint(POINT_HT, t->ht);
  2264. SetPoint(POINT_DX, t->dx);
  2265. SetPoint(POINT_IQ, t->iq);
  2266.  
  2267. SetPoint(POINT_STAT, t->stat_point);
  2268. SetPoint(POINT_SKILL, t->skill_point);
  2269. SetPoint(POINT_SUB_SKILL, t->sub_skill_point);
  2270. SetPoint(POINT_HORSE_SKILL, t->horse_skill_point);
  2271.  
  2272. SetPoint(POINT_STAT_RESET_COUNT, t->stat_reset_count);
  2273.  
  2274. SetPoint(POINT_LEVEL_STEP, t->level_step);
  2275. SetRealPoint(POINT_LEVEL_STEP, t->level_step);
  2276.  
  2277. SetRace(t->job);
  2278.  
  2279. SetLevel(t->level);
  2280. SetExp(t->exp);
  2281. SetGold(t->gold);
  2282.  
  2283. #ifdef ENABLE_GEM_SYSTEM
  2284. SetGem(t->gem);
  2285. #endif
  2286. #ifdef __ENABLE_BATTLE_FIELD__
  2287. SetBattlePoints(t->battlePoint);
  2288. #endif
  2289.  
  2290. SetMapIndex(t->lMapIndex);
  2291. SetXYZ(t->x, t->y, t->z);
  2292. // #ifdef __TITLE_SYSTEM__
  2293. // SetPoint(POINT_TITLE, t->iTChoosed);
  2294. // int w = 1;
  2295. // const std::string text = t->cTAvailable;
  2296. // std::size_t start = 0, end = 0;
  2297. // while ((end = text.find(',', start)) != std::string::npos)
  2298. // {
  2299. // BYTE bType = POINT_TITLE + w;
  2300. // std::string sString = text.substr(start, end - start);
  2301. // SetPoint(bType, atoi(sString.c_str()));
  2302. // w += 1;
  2303. // start = end + 1;
  2304. // }
  2305. // #endif
  2306. ComputePoints();
  2307.  
  2308. SetHP(t->hp);
  2309. SetSP(t->sp);
  2310. SetStamina(t->stamina);
  2311.  
  2312. //GMÀ϶§ º¸È£¸ðµå
  2313. if (!test_server)
  2314. {
  2315. if (GetGMLevel() > GM_WIZARD)
  2316. {
  2317. m_afAffectFlag.Set(AFF_YMIR);
  2318. m_bPKMode = PK_MODE_PROTECT;
  2319. }
  2320. }
  2321.  
  2322. if (GetLevel() < PK_PROTECT_LEVEL)
  2323. m_bPKMode = PK_MODE_PROTECT;
  2324.  
  2325. m_stMobile = t->szMobile;
  2326.  
  2327. SetHorseData(t->horse);
  2328.  
  2329. if (GetHorseLevel() > 0)
  2330. UpdateHorseDataByLogoff(t->logoff_interval);
  2331.  
  2332. thecore_memcpy(m_aiPremiumTimes, t->aiPremiumTimes, sizeof(t->aiPremiumTimes));
  2333.  
  2334. m_dwLogOffInterval = t->logoff_interval;
  2335. #ifdef ENABLE_GEM_SYSTEM
  2336. m_dwGemNextRefresh = t->gem_next_refresh;
  2337. #endif
  2338.  
  2339. 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);
  2340.  
  2341. if (GetGMLevel() != GM_PLAYER)
  2342. {
  2343. LogManager::instance().CharLog(this, GetGMLevel(), "GM_LOGIN", "");
  2344. sys_log(0, "GM_LOGIN(gmlevel=%d, name=%s(%d), pos=(%d, %d)", GetGMLevel(), GetName(), GetPlayerID(), GetX(), GetY());
  2345. }
  2346.  
  2347. #ifdef ENABLE_SUPPORT_SYSTEM
  2348. if (m_supportSystem)
  2349. {
  2350. m_supportSystem->Destroy();
  2351. delete m_supportSystem;
  2352. }
  2353.  
  2354. m_supportSystem = M2_NEW CSupportSystem(this);
  2355. #endif
  2356.  
  2357. #ifdef __PET_SYSTEM__
  2358. if (m_petSystem)
  2359. {
  2360. m_petSystem->Destroy();
  2361. delete m_petSystem;
  2362. }
  2363.  
  2364. m_petSystem = M2_NEW CPetSystem(this);
  2365. #endif
  2366. #ifdef NEW_PET_SYSTEM
  2367. if (m_newpetSystem)
  2368. {
  2369. m_newpetSystem->Destroy();
  2370. delete m_newpetSystem;
  2371. }
  2372.  
  2373. m_newpetSystem = M2_NEW CNewPetSystem(this);
  2374. #endif
  2375. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  2376. if (m_mountSystem)
  2377. {
  2378. m_mountSystem->Destroy();
  2379. delete m_mountSystem;
  2380. }
  2381.  
  2382. m_mountSystem = M2_NEW CMountSystem(this);
  2383. #endif
  2384. #ifdef __FAKE_BUFF__
  2385. m_stFakeBuffName = t->fakebuff_name;
  2386. #endif
  2387. }
  2388.  
  2389. EVENTFUNC(kill_ore_load_event)
  2390. {
  2391. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  2392. if ( info == NULL )
  2393. {
  2394. sys_err( "kill_ore_load_even> <Factor> Null pointer" );
  2395. return 0;
  2396. }
  2397.  
  2398. LPCHARACTER ch = info->ch;
  2399. if (ch == NULL) { // <Factor>
  2400. return 0;
  2401. }
  2402.  
  2403. ch->m_pkMiningEvent = NULL;
  2404. M2_DESTROY_CHARACTER(ch);
  2405. return 0;
  2406. }
  2407.  
  2408. void CHARACTER::SetProto(const CMob * pkMob)
  2409. {
  2410. if (m_pkMobInst)
  2411. M2_DELETE(m_pkMobInst);
  2412.  
  2413. m_pkMobData = pkMob;
  2414. m_pkMobInst = M2_NEW CMobInstance;
  2415.  
  2416. m_bPKMode = PK_MODE_FREE;
  2417.  
  2418. const TMobTable * t = &m_pkMobData->m_table;
  2419.  
  2420. m_bCharType = t->bType;
  2421.  
  2422. SetLevel(t->bLevel);
  2423. SetEmpire(t->bEmpire);
  2424.  
  2425. SetExp(t->dwExp);
  2426. SetRealPoint(POINT_ST, t->bStr);
  2427. SetRealPoint(POINT_DX, t->bDex);
  2428. SetRealPoint(POINT_HT, t->bCon);
  2429. SetRealPoint(POINT_IQ, t->bInt);
  2430.  
  2431. ComputePoints();
  2432.  
  2433. SetHP(GetMaxHP());
  2434. SetSP(GetMaxSP());
  2435.  
  2436. ////////////////////
  2437. m_pointsInstant.dwAIFlag = t->dwAIFlag;
  2438. SetImmuneFlag(t->dwImmuneFlag);
  2439.  
  2440. AssignTriggers(t);
  2441.  
  2442. ApplyMobAttribute(t);
  2443.  
  2444. if (IsStone())
  2445. {
  2446. DetermineDropMetinStone();
  2447. }
  2448.  
  2449. if (IsWarp() || IsGoto())
  2450. {
  2451. StartWarpNPCEvent();
  2452. }
  2453.  
  2454. CHARACTER_MANAGER::instance().RegisterRaceNumMap(this);
  2455.  
  2456. // XXX X-mas santa hardcoding
  2457. if (GetRaceNum() == xmas::MOB_SANTA_VNUM)
  2458. {
  2459. SetPoint(POINT_ATT_GRADE_BONUS, 10);
  2460. SetPoint(POINT_DEF_GRADE_BONUS, 6);
  2461.  
  2462. //»êŸ¿ë
  2463. //m_dwPlayStartTime = get_dword_time() + 10 * 60 * 1000;
  2464. //½Å¼±ÀÚ ³ëÇØ
  2465. m_dwPlayStartTime = get_dword_time() + 30 * 1000;
  2466. if (test_server)
  2467. m_dwPlayStartTime = get_dword_time() + 30 * 1000;
  2468. }
  2469.  
  2470. // XXX CTF GuildWar hardcoding
  2471. if (warmap::IsWarFlag(GetRaceNum()))
  2472. {
  2473. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlag, &CHARACTER::EndStateEmpty);
  2474. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlag, &CHARACTER::EndStateEmpty);
  2475. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlag, &CHARACTER::EndStateEmpty);
  2476. }
  2477.  
  2478. if (warmap::IsWarFlagBase(GetRaceNum()))
  2479. {
  2480. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlagBase, &CHARACTER::EndStateEmpty);
  2481. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlagBase, &CHARACTER::EndStateEmpty);
  2482. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateFlagBase, &CHARACTER::EndStateEmpty);
  2483. }
  2484.  
  2485. if (m_bCharType == CHAR_TYPE_HORSE ||
  2486. GetRaceNum() == 20101 ||
  2487. GetRaceNum() == 20102 ||
  2488. GetRaceNum() == 20103 ||
  2489. GetRaceNum() == 20104 ||
  2490. GetRaceNum() == 20105 ||
  2491. GetRaceNum() == 20106 ||
  2492. GetRaceNum() == 20107 ||
  2493. GetRaceNum() == 20108 ||
  2494. GetRaceNum() == 20109
  2495. )
  2496. {
  2497. m_stateIdle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateHorse, &CHARACTER::EndStateEmpty);
  2498. m_stateMove.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateMove, &CHARACTER::EndStateEmpty);
  2499. m_stateBattle.Set(this, &CHARACTER::BeginStateEmpty, &CHARACTER::StateHorse, &CHARACTER::EndStateEmpty);
  2500. }
  2501.  
  2502. // MINING
  2503. if (mining::IsVeinOfOre (GetRaceNum()))
  2504. {
  2505. char_event_info* info = AllocEventInfo<char_event_info>();
  2506.  
  2507. info->ch = this;
  2508.  
  2509. m_pkMiningEvent = event_create(kill_ore_load_event, info, PASSES_PER_SEC(number(7 * 60, 15 * 60)));
  2510. }
  2511. // END_OF_MINING
  2512. }
  2513.  
  2514. const TMobTable & CHARACTER::GetMobTable() const
  2515. {
  2516. return m_pkMobData->m_table;
  2517. }
  2518.  
  2519. bool CHARACTER::IsRaceFlag(DWORD dwBit) const
  2520. {
  2521. return m_pkMobData ? IS_SET(m_pkMobData->m_table.dwRaceFlag, dwBit) : 0;
  2522. }
  2523.  
  2524. DWORD CHARACTER::GetMobDamageMin() const
  2525. {
  2526. return m_pkMobData->m_table.dwDamageRange[0];
  2527. }
  2528.  
  2529. DWORD CHARACTER::GetMobDamageMax() const
  2530. {
  2531. return m_pkMobData->m_table.dwDamageRange[1];
  2532. }
  2533.  
  2534. float CHARACTER::GetMobDamageMultiply() const
  2535. {
  2536. float fDamMultiply = GetMobTable().fDamMultiply;
  2537.  
  2538. if (IsBerserk())
  2539. fDamMultiply = fDamMultiply * 2.0f; // BALANCE: ±¤ÆøÈ­ ½Ã µÎ¹è
  2540.  
  2541. return fDamMultiply;
  2542. }
  2543.  
  2544. DWORD CHARACTER::GetMobDropItemVnum() const
  2545. {
  2546. return m_pkMobData->m_table.dwDropItemVnum;
  2547. }
  2548.  
  2549. bool CHARACTER::IsSummonMonster() const
  2550. {
  2551. return GetSummonVnum() != 0;
  2552. }
  2553.  
  2554. DWORD CHARACTER::GetSummonVnum() const
  2555. {
  2556. return m_pkMobData ? m_pkMobData->m_table.dwSummonVnum : 0;
  2557. }
  2558.  
  2559. DWORD CHARACTER::GetPolymorphItemVnum() const
  2560. {
  2561. return m_pkMobData ? m_pkMobData->m_table.dwPolymorphItemVnum : 0;
  2562. }
  2563.  
  2564. DWORD CHARACTER::GetMonsterDrainSPPoint() const
  2565. {
  2566. return m_pkMobData ? m_pkMobData->m_table.dwDrainSP : 0;
  2567. }
  2568.  
  2569. BYTE CHARACTER::GetMobRank() const
  2570. {
  2571. if (!m_pkMobData)
  2572. return MOB_RANK_KNIGHT; // PCÀÏ °æ¿ì KNIGHT±Þ
  2573.  
  2574. return m_pkMobData->m_table.bRank;
  2575. }
  2576.  
  2577. BYTE CHARACTER::GetMobSize() const
  2578. {
  2579. if (!m_pkMobData)
  2580. return MOBSIZE_MEDIUM;
  2581.  
  2582. return m_pkMobData->m_table.bSize;
  2583. }
  2584.  
  2585. WORD CHARACTER::GetMobAttackRange() const
  2586. {
  2587. switch (GetMobBattleType())
  2588. {
  2589. case BATTLE_TYPE_RANGE:
  2590. case BATTLE_TYPE_MAGIC:
  2591. return m_pkMobData->m_table.wAttackRange + GetPoint(POINT_BOW_DISTANCE);
  2592. default:
  2593. return m_pkMobData->m_table.wAttackRange;
  2594. }
  2595. }
  2596.  
  2597. BYTE CHARACTER::GetMobBattleType() const
  2598. {
  2599. if (!m_pkMobData)
  2600. return BATTLE_TYPE_MELEE;
  2601.  
  2602. return (m_pkMobData->m_table.bBattleType);
  2603. }
  2604.  
  2605. void CHARACTER::ComputeBattlePoints()
  2606. {
  2607. if (IsPolymorphed())
  2608. {
  2609. DWORD dwMobVnum = GetPolymorphVnum();
  2610. const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
  2611. int iAtt = 0;
  2612. int iDef = 0;
  2613.  
  2614. if (pMob)
  2615. {
  2616. iAtt = GetLevel() * 2 + GetPolymorphPoint(POINT_ST) * 2;
  2617. // lev + con
  2618. iDef = GetLevel() + GetPolymorphPoint(POINT_HT) + pMob->m_table.wDef;
  2619. }
  2620.  
  2621. SetPoint(POINT_ATT_GRADE, iAtt);
  2622. SetPoint(POINT_DEF_GRADE, iDef);
  2623. SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
  2624. SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
  2625. }
  2626. else if (IsPC())
  2627. {
  2628. SetPoint(POINT_ATT_GRADE, 0);
  2629. SetPoint(POINT_DEF_GRADE, 0);
  2630. SetPoint(POINT_CLIENT_DEF_GRADE, 0);
  2631. SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
  2632. SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
  2633.  
  2634. //
  2635. // ±âº» ATK = 2lev + 2str, Á÷¾÷¿¡ ¸¶´Ù 2strÀº ¹Ù²ð ¼ö ÀÖÀ½
  2636. //
  2637. int iAtk = GetLevel() * 2;
  2638. int iStatAtk = 0;
  2639.  
  2640. switch (GetJob())
  2641. {
  2642. case JOB_WARRIOR:
  2643. case JOB_SURA:
  2644. iStatAtk = (2 * GetPoint(POINT_ST));
  2645. break;
  2646.  
  2647. case JOB_ASSASSIN:
  2648. iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_DX)) / 3;
  2649. break;
  2650.  
  2651. case JOB_SHAMAN:
  2652. iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_IQ)) / 3;
  2653. break;
  2654. #ifdef ENABLE_WOLFMAN_CHARACTER
  2655. case JOB_WOLFMAN:
  2656. // TODO: ¼öÀÎÁ· °ø°Ý·Â °ø½Ä ±âȹÀÚ¿¡°Ô ¿äû
  2657. iStatAtk = (2 * GetPoint(POINT_ST));
  2658. break;
  2659. #endif
  2660. default:
  2661. sys_err("invalid job %d", GetJob());
  2662. iStatAtk = (2 * GetPoint(POINT_ST));
  2663. break;
  2664. }
  2665.  
  2666. // ¸»À» Ÿ°í ÀÖ°í, ½ºÅÈÀ¸·Î ÀÎÇÑ °ø°Ý·ÂÀÌ ST*2 º¸´Ù ³·À¸¸é ST*2·Î ÇÑ´Ù.
  2667. // ½ºÅÈÀ» À߸ø ÂïÀº »ç¶÷ °ø°Ý·ÂÀÌ ´õ ³·Áö ¾Ê°Ô Çϱâ À§Çؼ­´Ù.
  2668. if (GetMountVnum() && iStatAtk < 2 * GetPoint(POINT_ST))
  2669. iStatAtk = (2 * GetPoint(POINT_ST));
  2670.  
  2671. iAtk += iStatAtk;
  2672.  
  2673. if (GetMountVnum())
  2674. {
  2675. if (GetJob() == JOB_SURA && GetSkillGroup() == 1)
  2676. {
  2677. iAtk += (iAtk * GetHorseLevel()) / 60;
  2678. }
  2679. else
  2680. {
  2681. iAtk += (iAtk * GetHorseLevel()) / 30;
  2682. }
  2683. }
  2684.  
  2685. //
  2686. // ATK Setting
  2687. //
  2688. iAtk += GetPoint(POINT_ATT_GRADE_BONUS);
  2689.  
  2690. PointChange(POINT_ATT_GRADE, iAtk);
  2691.  
  2692. // DEF = LEV + CON + ARMOR
  2693. int iShowDef = GetLevel() + GetPoint(POINT_HT); // For Ymir(õ¸¶)
  2694. int iDef = GetLevel() + (int) (GetPoint(POINT_HT) / 1.25); // For Other
  2695. int iArmor = 0;
  2696.  
  2697. LPITEM pkItem;
  2698.  
  2699. for (int i = 0; i < WEAR_MAX_NUM; ++i)
  2700. if ((pkItem = GetWear(i)) && pkItem->GetType() == ITEM_ARMOR)
  2701. {
  2702. if (pkItem->GetSubType() == ARMOR_BODY || pkItem->GetSubType() == ARMOR_HEAD || pkItem->GetSubType() == ARMOR_FOOTS || pkItem->GetSubType() == ARMOR_SHIELD)
  2703. {
  2704. iArmor += pkItem->GetValue(1);
  2705. iArmor += (2 * pkItem->GetValue(5));
  2706. }
  2707. }
  2708.  
  2709. // ¸» Ÿ°í ÀÖÀ» ¶§ ¹æ¾î·ÂÀÌ ¸»ÀÇ ±âÁØ ¹æ¾î·Âº¸´Ù ³·À¸¸é ±âÁØ ¹æ¾î·ÂÀ¸·Î ¼³Á¤
  2710. if( true == IsHorseRiding() )
  2711. {
  2712. if (iArmor < GetHorseArmor())
  2713. iArmor = GetHorseArmor();
  2714.  
  2715. const char* pHorseName = CHorseNameManager::instance().GetHorseName(GetPlayerID());
  2716.  
  2717. if (pHorseName != NULL && strlen(pHorseName))
  2718. {
  2719. iArmor += 20;
  2720. }
  2721. }
  2722.  
  2723. iArmor += GetPoint(POINT_DEF_GRADE_BONUS);
  2724. iArmor += GetPoint(POINT_PARTY_DEFENDER_BONUS);
  2725.  
  2726. // INTERNATIONAL_VERSION
  2727. PointChange(POINT_DEF_GRADE, iDef + iArmor);
  2728. PointChange(POINT_CLIENT_DEF_GRADE, (iShowDef + iArmor) - GetPoint(POINT_DEF_GRADE));
  2729. // END_OF_INTERNATIONAL_VERSION
  2730.  
  2731. PointChange(POINT_MAGIC_ATT_GRADE, GetLevel() * 2 + GetPoint(POINT_IQ) * 2 + GetPoint(POINT_MAGIC_ATT_GRADE_BONUS));
  2732. PointChange(POINT_MAGIC_DEF_GRADE, GetLevel() + (GetPoint(POINT_IQ) * 3 + GetPoint(POINT_HT)) / 3 + iArmor / 2 + GetPoint(POINT_MAGIC_DEF_GRADE_BONUS));
  2733. }
  2734. else
  2735. {
  2736. // 2lev + str * 2
  2737. int iAtt = GetLevel() * 2 + GetPoint(POINT_ST) * 2;
  2738. // lev + con
  2739. int iDef = GetLevel() + GetPoint(POINT_HT) + GetMobTable().wDef;
  2740.  
  2741. SetPoint(POINT_ATT_GRADE, iAtt);
  2742. SetPoint(POINT_DEF_GRADE, iDef);
  2743. SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE));
  2744. SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE));
  2745. }
  2746. }
  2747.  
  2748. void CHARACTER::ComputePoints()
  2749. {
  2750. long lStat = GetPoint(POINT_STAT);
  2751. long lStatResetCount = GetPoint(POINT_STAT_RESET_COUNT);
  2752. long lSkillActive = GetPoint(POINT_SKILL);
  2753. long lSkillSub = GetPoint(POINT_SUB_SKILL);
  2754. long lSkillHorse = GetPoint(POINT_HORSE_SKILL);
  2755. long lLevelStep = GetPoint(POINT_LEVEL_STEP);
  2756.  
  2757. long lAttackerBonus = GetPoint(POINT_PARTY_ATTACKER_BONUS);
  2758. long lTankerBonus = GetPoint(POINT_PARTY_TANKER_BONUS);
  2759. long lBufferBonus = GetPoint(POINT_PARTY_BUFFER_BONUS);
  2760. long lSkillMasterBonus = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
  2761. long lHasteBonus = GetPoint(POINT_PARTY_HASTE_BONUS);
  2762. long lDefenderBonus = GetPoint(POINT_PARTY_DEFENDER_BONUS);
  2763.  
  2764. long lHPRecovery = GetPoint(POINT_HP_RECOVERY);
  2765. long lSPRecovery = GetPoint(POINT_SP_RECOVERY);
  2766. #ifdef __TITLE_SYSTEM__
  2767. std::vector<int> vTitles;
  2768. if (IsPC())
  2769. {
  2770. for (int w = TITLE_0; w < TITLES_MAX_NUM; ++w)
  2771. {
  2772. BYTE bType = POINT_TITLE + w;
  2773. vTitles.push_back(GetPoint(bType));
  2774. }
  2775.  
  2776. vTitles.push_back(0);
  2777. }
  2778. #endif
  2779.  
  2780. memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points));
  2781. BuffOnAttr_ClearAll();
  2782. m_SkillDamageBonus.clear();
  2783.  
  2784. SetPoint(POINT_STAT, lStat);
  2785. SetPoint(POINT_SKILL, lSkillActive);
  2786. SetPoint(POINT_SUB_SKILL, lSkillSub);
  2787. SetPoint(POINT_HORSE_SKILL, lSkillHorse);
  2788. SetPoint(POINT_LEVEL_STEP, lLevelStep);
  2789. SetPoint(POINT_STAT_RESET_COUNT, lStatResetCount);
  2790.  
  2791. SetPoint(POINT_ST, GetRealPoint(POINT_ST));
  2792. SetPoint(POINT_HT, GetRealPoint(POINT_HT));
  2793. SetPoint(POINT_DX, GetRealPoint(POINT_DX));
  2794. SetPoint(POINT_IQ, GetRealPoint(POINT_IQ));
  2795.  
  2796. SetPart(PART_MAIN, GetOriginalPart(PART_MAIN));
  2797. SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON));
  2798. SetPart(PART_HEAD, GetOriginalPart(PART_HEAD));
  2799. SetPart(PART_HAIR, GetOriginalPart(PART_HAIR));
  2800. #ifdef __SASH_SYSTEM__
  2801. SetPart(PART_SASH, GetOriginalPart(PART_SASH));
  2802. #endif
  2803.  
  2804. SetPoint(POINT_PARTY_ATTACKER_BONUS, lAttackerBonus);
  2805. SetPoint(POINT_PARTY_TANKER_BONUS, lTankerBonus);
  2806. SetPoint(POINT_PARTY_BUFFER_BONUS, lBufferBonus);
  2807. SetPoint(POINT_PARTY_SKILL_MASTER_BONUS, lSkillMasterBonus);
  2808. SetPoint(POINT_PARTY_HASTE_BONUS, lHasteBonus);
  2809. SetPoint(POINT_PARTY_DEFENDER_BONUS, lDefenderBonus);
  2810.  
  2811. SetPoint(POINT_HP_RECOVERY, lHPRecovery);
  2812. SetPoint(POINT_SP_RECOVERY, lSPRecovery);
  2813.  
  2814. // PC_BANG_ITEM_ADD
  2815. SetPoint(POINT_PC_BANG_EXP_BONUS, 0);
  2816. SetPoint(POINT_PC_BANG_DROP_BONUS, 0);
  2817. #ifdef __TITLE_SYSTEM__
  2818. if (IsPC())
  2819. {
  2820. for (int w = TITLE_0; w < TITLES_MAX_NUM; ++w)
  2821. {
  2822. BYTE bType = POINT_TITLE + w;
  2823. SetPoint(bType, vTitles[w]);
  2824. }
  2825.  
  2826. vTitles.clear();
  2827. }
  2828. #endif
  2829. // END_PC_BANG_ITEM_ADD
  2830.  
  2831. int iMaxHP, iMaxSP;
  2832. int iMaxStamina;
  2833.  
  2834. if (IsPC())
  2835. {
  2836. // ÃÖ´ë »ý¸í·Â/Á¤½Å·Â
  2837. iMaxHP = JobInitialPoints[GetJob()].max_hp + m_points.iRandomHP + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].hp_per_ht;
  2838. iMaxSP = JobInitialPoints[GetJob()].max_sp + m_points.iRandomSP + GetPoint(POINT_IQ) * JobInitialPoints[GetJob()].sp_per_iq;
  2839. iMaxStamina = JobInitialPoints[GetJob()].max_stamina + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].stamina_per_con;
  2840.  
  2841. {
  2842. CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_ADD_HP);
  2843.  
  2844. if (NULL != pkSk)
  2845. {
  2846. pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_ADD_HP) / 100.0f);
  2847.  
  2848. iMaxHP += static_cast<int>(pkSk->kPointPoly.Eval());
  2849. }
  2850. }
  2851.  
  2852. // ±âº» °ªµé
  2853. SetPoint(POINT_MOV_SPEED, 100);
  2854. SetPoint(POINT_ATT_SPEED, 100);
  2855. PointChange(POINT_ATT_SPEED, GetPoint(POINT_PARTY_HASTE_BONUS));
  2856. SetPoint(POINT_CASTING_SPEED, 100);
  2857. }
  2858. else
  2859. {
  2860. iMaxHP = m_pkMobData->m_table.dwMaxHP;
  2861. iMaxSP = 0;
  2862. iMaxStamina = 0;
  2863.  
  2864. SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed);
  2865. SetPoint(POINT_MOV_SPEED, m_pkMobData->m_table.sMovingSpeed);
  2866. SetPoint(POINT_CASTING_SPEED, m_pkMobData->m_table.sAttackSpeed);
  2867. }
  2868.  
  2869. if (IsPC())
  2870. {
  2871. if (GetMountVnum())
  2872. {
  2873. if (GetHorseST() > GetPoint(POINT_ST))
  2874. PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
  2875.  
  2876. if (GetHorseDX() > GetPoint(POINT_DX))
  2877. PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
  2878.  
  2879. if (GetHorseHT() > GetPoint(POINT_HT))
  2880. PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
  2881.  
  2882. if (GetHorseIQ() > GetPoint(POINT_IQ))
  2883. PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
  2884. }
  2885.  
  2886. }
  2887.  
  2888. ComputeBattlePoints();
  2889.  
  2890. // ±âº» HP/SP ¼³Á¤
  2891. if (iMaxHP != GetMaxHP())
  2892. {
  2893. SetRealPoint(POINT_MAX_HP, iMaxHP); // ±âº»HP¸¦ RealPoint¿¡ ÀúÀåÇØ ³õ´Â´Ù.
  2894. }
  2895.  
  2896. PointChange(POINT_MAX_HP, 0);
  2897.  
  2898. if (iMaxSP != GetMaxSP())
  2899. {
  2900. SetRealPoint(POINT_MAX_SP, iMaxSP); // ±âº»SP¸¦ RealPoint¿¡ ÀúÀåÇØ ³õ´Â´Ù.
  2901. }
  2902.  
  2903. PointChange(POINT_MAX_SP, 0);
  2904.  
  2905. SetMaxStamina(iMaxStamina);
  2906. // @fixme118 part1
  2907. int iCurHP = this->GetHP();
  2908. int iCurSP = this->GetSP();
  2909.  
  2910. m_pointsInstant.dwImmuneFlag = 0;
  2911.  
  2912. for (int i = 0 ; i < WEAR_MAX_NUM; i++)
  2913. {
  2914. LPITEM pItem = GetWear(i);
  2915. if (pItem)
  2916. {
  2917. pItem->ModifyPoints(true);
  2918. SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag());
  2919. }
  2920. }
  2921.  
  2922. // ¿ëÈ¥¼® ½Ã½ºÅÛ
  2923. // ComputePoints¿¡¼­´Â Äɸ¯ÅÍÀÇ ¸ðµç ¼Ó¼º°ªÀ» ÃʱâÈ­Çϰí,
  2924. // ¾ÆÀÌÅÛ, ¹öÇÁ µî¿¡ °ü·ÃµÈ ¸ðµç ¼Ó¼º°ªÀ» Àç°è»êÇϱ⠶§¹®¿¡,
  2925. // ¿ëÈ¥¼® ½Ã½ºÅÛµµ ActiveDeck¿¡ ÀÖ´Â ¸ðµç ¿ëÈ¥¼®ÀÇ ¼Ó¼º°ªÀ» ´Ù½Ã Àû¿ë½ÃÄÑ¾ß ÇÑ´Ù.
  2926. if (DragonSoul_IsDeckActivated())
  2927. {
  2928. for (int i = WEAR_MAX_NUM + DS_SLOT_MAX * DragonSoul_GetActiveDeck();
  2929. i < WEAR_MAX_NUM + DS_SLOT_MAX * (DragonSoul_GetActiveDeck() + 1); i++)
  2930. {
  2931. LPITEM pItem = GetWear(i);
  2932. if (pItem)
  2933. {
  2934. if (DSManager::instance().IsTimeLeftDragonSoul(pItem))
  2935. pItem->ModifyPoints(true);
  2936. }
  2937. }
  2938. }
  2939.  
  2940. if (GetHP() > GetMaxHP())
  2941. PointChange(POINT_HP, GetMaxHP() - GetHP());
  2942.  
  2943. if (GetSP() > GetMaxSP())
  2944. PointChange(POINT_SP, GetMaxSP() - GetSP());
  2945.  
  2946. ComputeSkillPoints();
  2947.  
  2948. RefreshAffect();
  2949. // @fixme118 part2 (before petsystem stuff)
  2950. if (IsPC())
  2951. {
  2952. if (this->GetHP() != iCurHP)
  2953. this->PointChange(POINT_HP, iCurHP-this->GetHP());
  2954. if (this->GetSP() != iCurSP)
  2955. this->PointChange(POINT_SP, iCurSP-this->GetSP());
  2956. }
  2957.  
  2958. UpdatePacket();
  2959. }
  2960.  
  2961. // m_dwPlayStartTimeÀÇ ´ÜÀ§´Â milisecond´Ù. µ¥ÀÌÅͺ£À̽º¿¡´Â ºÐ´ÜÀ§·Î ±â·ÏÇϱâ
  2962. // ¶§¹®¿¡ Ç÷¹À̽ð£À» °è»êÇÒ ¶§ / 60000 À¸·Î ³ª´²¼­ Çϴµ¥, ±× ³ª¸ÓÁö °ªÀÌ ³²¾Ò
  2963. // À» ¶§ ¿©±â¿¡ dwTimeRemainÀ¸·Î ³Ö¾î¼­ Á¦´ë·Î °è»êµÇµµ·Ï ÇØÁÖ¾î¾ß ÇÑ´Ù.
  2964. void CHARACTER::ResetPlayTime(DWORD dwTimeRemain)
  2965. {
  2966. m_dwPlayStartTime = get_dword_time() - dwTimeRemain;
  2967. }
  2968.  
  2969. const int aiRecoveryPercents[10] = { 1, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
  2970.  
  2971. EVENTFUNC(recovery_event)
  2972. {
  2973. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  2974. if ( info == NULL )
  2975. {
  2976. sys_err( "recovery_event> <Factor> Null pointer" );
  2977. return 0;
  2978. }
  2979.  
  2980. LPCHARACTER ch = info->ch;
  2981.  
  2982. if (ch == NULL) { // <Factor>
  2983. return 0;
  2984. }
  2985.  
  2986. if (!ch->IsPC())
  2987. {
  2988. //
  2989. // ¸ó½ºÅÍ È¸º¹
  2990. //
  2991. if (ch->IsAffectFlag(AFF_POISON))
  2992. return PASSES_PER_SEC(MAX(1, ch->GetMobTable().bRegenCycle));
  2993. #ifdef ENABLE_WOLFMAN_CHARACTER
  2994. if (ch->IsAffectFlag(AFF_BLEEDING))
  2995. return PASSES_PER_SEC(MAX(1, ch->GetMobTable().bRegenCycle));
  2996. #endif
  2997. if (2493 == ch->GetMobTable().dwVnum)
  2998. {
  2999. int regenPct = BlueDragon_GetRangeFactor("hp_regen", ch->GetHPPct());
  3000. regenPct += ch->GetMobTable().bRegenPercent;
  3001.  
  3002. for (int i=1 ; i <= 4 ; ++i)
  3003. {
  3004. if (REGEN_PECT_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
  3005. {
  3006. DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
  3007. size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
  3008. size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( ch->GetMapIndex(), dwDragonStoneID );
  3009.  
  3010. regenPct += (val*cnt);
  3011.  
  3012. break;
  3013. }
  3014. }
  3015.  
  3016. ch->PointChange(POINT_HP, MAX(1, (ch->GetMaxHP() * regenPct) / 100));
  3017. }
  3018. else if (!ch->IsDoor())
  3019. {
  3020. ch->MonsterLog("HP_REGEN +%d", MAX(1, (ch->GetMaxHP() * ch->GetMobTable().bRegenPercent) / 100));
  3021. ch->PointChange(POINT_HP, MAX(1, (ch->GetMaxHP() * ch->GetMobTable().bRegenPercent) / 100));
  3022. }
  3023.  
  3024. if (ch->GetHP() >= ch->GetMaxHP())
  3025. {
  3026. ch->m_pkRecoveryEvent = NULL;
  3027. return 0;
  3028. }
  3029.  
  3030. if (2493 == ch->GetMobTable().dwVnum)
  3031. {
  3032. for (int i=1 ; i <= 4 ; ++i)
  3033. {
  3034. if (REGEN_TIME_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
  3035. {
  3036. DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
  3037. size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
  3038. size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( ch->GetMapIndex(), dwDragonStoneID );
  3039.  
  3040. return PASSES_PER_SEC(MAX(1, (ch->GetMobTable().bRegenCycle - (val*cnt))));
  3041. }
  3042. }
  3043. }
  3044.  
  3045. return PASSES_PER_SEC(MAX(1, ch->GetMobTable().bRegenCycle));
  3046. }
  3047. else
  3048. {
  3049. //
  3050. // PC ȸº¹
  3051. //
  3052. ch->CheckTarget();
  3053. //ch->UpdateSectree(); // ¿©±â¼­ ÀÌ°É ¿ÖÇÏÁö?
  3054. ch->UpdateKillerMode();
  3055.  
  3056. if (ch->IsAffectFlag(AFF_POISON) == true)
  3057. {
  3058. // Áßµ¶ÀÎ °æ¿ì ÀÚµ¿È¸º¹ ±ÝÁö
  3059. // ÆÄ¹ý¼úÀÎ °æ¿ì ÀÚµ¿È¸º¹ ±ÝÁö
  3060. return 3;
  3061. }
  3062. #ifdef ENABLE_WOLFMAN_CHARACTER
  3063. if (ch->IsAffectFlag(AFF_BLEEDING))
  3064. return 3;
  3065. #endif
  3066. int iSec = (get_dword_time() - ch->GetLastMoveTime()) / 3000;
  3067.  
  3068. // SP ȸº¹ ·çƾ.
  3069. // ¿Ö ÀÌ°É·Î ÇØ¼­ ÇÔ¼ö·Î »©³ù´Â°¡ ?!
  3070. ch->DistributeSP(ch);
  3071.  
  3072. if (ch->GetMaxHP() <= ch->GetHP())
  3073. return PASSES_PER_SEC(3);
  3074.  
  3075. int iPercent = 0;
  3076. int iAmount = 0;
  3077.  
  3078. {
  3079. iPercent = aiRecoveryPercents[MIN(9, iSec)];
  3080. iAmount = 15 + (ch->GetMaxHP() * iPercent) / 100;
  3081. }
  3082.  
  3083. iAmount += (iAmount * ch->GetPoint(POINT_HP_REGEN)) / 100;
  3084.  
  3085. sys_log(1, "RECOVERY_EVENT: %s %d HP_REGEN %d HP +%d", ch->GetName(), iPercent, ch->GetPoint(POINT_HP_REGEN), iAmount);
  3086.  
  3087. ch->PointChange(POINT_HP, iAmount, false);
  3088. return PASSES_PER_SEC(3);
  3089. }
  3090. }
  3091.  
  3092. void CHARACTER::StartRecoveryEvent()
  3093. {
  3094. if (m_pkRecoveryEvent)
  3095. return;
  3096.  
  3097. if (IsDead() || IsStun())
  3098. return;
  3099.  
  3100. if (IsNPC() && GetHP() >= GetMaxHP()) // ¸ó½ºÅʹ ü·ÂÀÌ ´Ù Â÷ÀÖÀ¸¸é ½ÃÀÛ ¾ÈÇÑ´Ù.
  3101. return;
  3102. #ifdef __MELEY_LAIR_DUNGEON__
  3103. if ((MeleyLair::CMgr::instance().IsMeleyMap(GetMapIndex())) && ((GetRaceNum() == (WORD)(MeleyLair::STATUE_VNUM)) || ((GetRaceNum() == (WORD)(MeleyLair::BOSS_VNUM)))))
  3104. return;
  3105. #endif
  3106.  
  3107. char_event_info* info = AllocEventInfo<char_event_info>();
  3108.  
  3109. info->ch = this;
  3110.  
  3111. int iSec = IsPC() ? 3 : (MAX(1, GetMobTable().bRegenCycle));
  3112. m_pkRecoveryEvent = event_create(recovery_event, info, PASSES_PER_SEC(iSec));
  3113. }
  3114.  
  3115. void CHARACTER::Standup()
  3116. {
  3117. struct packet_position pack_position;
  3118.  
  3119. if (!IsPosition(POS_SITTING))
  3120. return;
  3121.  
  3122. SetPosition(POS_STANDING);
  3123.  
  3124. sys_log(1, "STANDUP: %s", GetName());
  3125.  
  3126. pack_position.header = HEADER_GC_CHARACTER_POSITION;
  3127. pack_position.vid = GetVID();
  3128. pack_position.position = POSITION_GENERAL;
  3129.  
  3130. PacketAround(&pack_position, sizeof(pack_position));
  3131. }
  3132.  
  3133. void CHARACTER::Sitdown(int is_ground)
  3134. {
  3135. struct packet_position pack_position;
  3136.  
  3137. if (IsPosition(POS_SITTING))
  3138. return;
  3139.  
  3140. SetPosition(POS_SITTING);
  3141. sys_log(1, "SITDOWN: %s", GetName());
  3142.  
  3143. pack_position.header = HEADER_GC_CHARACTER_POSITION;
  3144. pack_position.vid = GetVID();
  3145. pack_position.position = POSITION_SITTING_GROUND;
  3146. PacketAround(&pack_position, sizeof(pack_position));
  3147. }
  3148.  
  3149. void CHARACTER::SetRotation(float fRot)
  3150. {
  3151. m_pointsInstant.fRot = fRot;
  3152. }
  3153.  
  3154. // x, y ¹æÇâÀ¸·Î º¸°í ¼±´Ù.
  3155. void CHARACTER::SetRotationToXY(long x, long y)
  3156. {
  3157. SetRotation(GetDegreeFromPositionXY(GetX(), GetY(), x, y));
  3158. }
  3159.  
  3160. bool CHARACTER::CannotMoveByAffect() const
  3161. {
  3162. return (IsAffectFlag(AFF_STUN));
  3163. }
  3164.  
  3165. bool CHARACTER::CanMove() const
  3166. {
  3167. if (CannotMoveByAffect())
  3168. return false;
  3169.  
  3170. if (GetMyShop()) // »óÁ¡ ¿¬ »óÅ¿¡¼­´Â ¿òÁ÷ÀÏ ¼ö ¾øÀ½
  3171. return false;
  3172.  
  3173. // 0.2ÃÊ ÀüÀ̶ó¸é ¿òÁ÷ÀÏ ¼ö ¾ø´Ù.
  3174. /*
  3175. if (get_float_time() - m_fSyncTime < 0.2f)
  3176. return false;
  3177. */
  3178. return true;
  3179. }
  3180.  
  3181. // ¹«Á¶°Ç x, y À§Ä¡·Î À̵¿ ½ÃŲ´Ù.
  3182. bool CHARACTER::Sync(long x, long y)
  3183. {
  3184. if (!GetSectree())
  3185. return false;
  3186.  
  3187. LPSECTREE new_tree = SECTREE_MANAGER::instance().Get(GetMapIndex(), x, y);
  3188.  
  3189. if (!new_tree)
  3190. {
  3191. if (GetDesc())
  3192. {
  3193. sys_err("cannot find tree at %d %d (name: %s)", x, y, GetName());
  3194. GetDesc()->SetPhase(PHASE_CLOSE);
  3195. }
  3196. else
  3197. {
  3198. // sys_err("no tree: %s %d %d %d", GetName(), x, y, GetMapIndex());
  3199. Dead();
  3200. }
  3201.  
  3202. return false;
  3203. }
  3204.  
  3205. SetRotationToXY(x, y);
  3206. SetXYZ(x, y, 0);
  3207.  
  3208. if (GetDungeon())
  3209. {
  3210. // ´øÁ¯¿ë À̺¥Æ® ¼Ó¼º º¯È­
  3211. int iLastEventAttr = m_iEventAttr;
  3212. m_iEventAttr = new_tree->GetEventAttribute(x, y);
  3213.  
  3214. if (m_iEventAttr != iLastEventAttr)
  3215. {
  3216. if (GetParty())
  3217. {
  3218. quest::CQuestManager::instance().AttrOut(GetParty()->GetLeaderPID(), this, iLastEventAttr);
  3219. quest::CQuestManager::instance().AttrIn(GetParty()->GetLeaderPID(), this, m_iEventAttr);
  3220. }
  3221. else
  3222. {
  3223. quest::CQuestManager::instance().AttrOut(GetPlayerID(), this, iLastEventAttr);
  3224. quest::CQuestManager::instance().AttrIn(GetPlayerID(), this, m_iEventAttr);
  3225. }
  3226. }
  3227. }
  3228.  
  3229. if (GetSectree() != new_tree)
  3230. {
  3231. if (!IsNPC())
  3232. {
  3233. SECTREEID id = new_tree->GetID();
  3234. SECTREEID old_id = GetSectree()->GetID();
  3235.  
  3236. const float fDist = DISTANCE_SQRT(id.coord.x - old_id.coord.x, id.coord.y - old_id.coord.y);
  3237. sys_log(0, "SECTREE DIFFER: %s %dx%d was %dx%d dist %.1fm",
  3238. GetName(),
  3239. id.coord.x,
  3240. id.coord.y,
  3241. old_id.coord.x,
  3242. old_id.coord.y,
  3243. fDist);
  3244. }
  3245.  
  3246. new_tree->InsertEntity(this);
  3247. }
  3248.  
  3249. return true;
  3250. }
  3251.  
  3252. void CHARACTER::Stop()
  3253. {
  3254. if (!IsState(m_stateIdle))
  3255. MonsterLog("[IDLE] Á¤Áö");
  3256.  
  3257. GotoState(m_stateIdle);
  3258.  
  3259. m_posDest.x = m_posStart.x = GetX();
  3260. m_posDest.y = m_posStart.y = GetY();
  3261. }
  3262.  
  3263. bool CHARACTER::Goto(long x, long y)
  3264. {
  3265. // TODO °Å¸®Ã¼Å© ÇÊ¿ä
  3266. // °°Àº À§Ä¡¸é À̵¿ÇÒ ÇÊ¿ä ¾øÀ½ (ÀÚµ¿ ¼º°ø)
  3267. if (GetX() == x && GetY() == y)
  3268. return false;
  3269.  
  3270. if (m_posDest.x == x && m_posDest.y == y)
  3271. {
  3272. if (!IsState(m_stateMove))
  3273. {
  3274. m_dwStateDuration = 4;
  3275. GotoState(m_stateMove);
  3276. }
  3277. return false;
  3278. }
  3279.  
  3280. m_posDest.x = x;
  3281. m_posDest.y = y;
  3282.  
  3283. CalculateMoveDuration();
  3284.  
  3285. m_dwStateDuration = 4;
  3286.  
  3287.  
  3288. if (!IsState(m_stateMove))
  3289. {
  3290. MonsterLog("[MOVE] %s", GetVictim() ? "´ë»óÃßÀû" : "±×³ÉÀ̵¿");
  3291.  
  3292. if (GetVictim())
  3293. {
  3294. //MonsterChat(MONSTER_CHAT_CHASE);
  3295. MonsterChat(MONSTER_CHAT_ATTACK);
  3296. }
  3297. }
  3298.  
  3299. GotoState(m_stateMove);
  3300.  
  3301. return true;
  3302. }
  3303.  
  3304.  
  3305. DWORD CHARACTER::GetMotionMode() const
  3306. {
  3307. DWORD dwMode = MOTION_MODE_GENERAL;
  3308.  
  3309. if (IsPolymorphed())
  3310. return dwMode;
  3311.  
  3312. LPITEM pkItem;
  3313.  
  3314. if ((pkItem = GetWear(WEAR_WEAPON)))
  3315. {
  3316. switch (pkItem->GetProto()->bSubType)
  3317. {
  3318. case WEAPON_SWORD:
  3319. dwMode = MOTION_MODE_ONEHAND_SWORD;
  3320. break;
  3321.  
  3322. case WEAPON_TWO_HANDED:
  3323. dwMode = MOTION_MODE_TWOHAND_SWORD;
  3324. break;
  3325.  
  3326. case WEAPON_DAGGER:
  3327. dwMode = MOTION_MODE_DUALHAND_SWORD;
  3328. break;
  3329.  
  3330. case WEAPON_BOW:
  3331. dwMode = MOTION_MODE_BOW;
  3332. break;
  3333.  
  3334. case WEAPON_BELL:
  3335. dwMode = MOTION_MODE_BELL;
  3336. break;
  3337.  
  3338. case WEAPON_FAN:
  3339. dwMode = MOTION_MODE_FAN;
  3340. break;
  3341. #ifdef ENABLE_WOLFMAN_CHARACTER
  3342. case WEAPON_CLAW:
  3343. dwMode = MOTION_MODE_CLAW;
  3344. break;
  3345. #endif
  3346. }
  3347. }
  3348. return dwMode;
  3349. }
  3350.  
  3351. float CHARACTER::GetMoveMotionSpeed() const
  3352. {
  3353. DWORD dwMode = GetMotionMode();
  3354.  
  3355. const CMotion * pkMotion = NULL;
  3356.  
  3357. if (!GetMountVnum())
  3358. pkMotion = CMotionManager::instance().GetMotion(GetRaceNum(), MAKE_MOTION_KEY(dwMode, (IsWalking() && IsPC()) ? MOTION_WALK : MOTION_RUN));
  3359. else
  3360. {
  3361. pkMotion = CMotionManager::instance().GetMotion(GetMountVnum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, (IsWalking() && IsPC()) ? MOTION_WALK : MOTION_RUN));
  3362.  
  3363. if (!pkMotion)
  3364. pkMotion = CMotionManager::instance().GetMotion(GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_HORSE, (IsWalking() && IsPC()) ? MOTION_WALK : MOTION_RUN));
  3365. }
  3366.  
  3367. if (pkMotion)
  3368. return -pkMotion->GetAccumVector().y / pkMotion->GetDuration();
  3369. else
  3370. {
  3371. sys_err("cannot find motion (name %s race %d mode %d)", GetName(), GetRaceNum(), dwMode);
  3372. return 300.0f;
  3373. }
  3374. }
  3375.  
  3376. float CHARACTER::GetMoveSpeed() const
  3377. {
  3378. return GetMoveMotionSpeed() * 10000 / CalculateDuration(GetLimitPoint(POINT_MOV_SPEED), 10000);
  3379. }
  3380.  
  3381. void CHARACTER::CalculateMoveDuration()
  3382. {
  3383. m_posStart.x = GetX();
  3384. m_posStart.y = GetY();
  3385.  
  3386. float fDist = DISTANCE_SQRT(m_posStart.x - m_posDest.x, m_posStart.y - m_posDest.y);
  3387.  
  3388. float motionSpeed = GetMoveMotionSpeed();
  3389.  
  3390. m_dwMoveDuration = CalculateDuration(GetLimitPoint(POINT_MOV_SPEED),
  3391. (int) ((fDist / motionSpeed) * 1000.0f));
  3392.  
  3393. if (IsNPC())
  3394. sys_log(1, "%s: GOTO: distance %f, spd %u, duration %u, motion speed %f pos %d %d -> %d %d",
  3395. GetName(), fDist, GetLimitPoint(POINT_MOV_SPEED), m_dwMoveDuration, motionSpeed,
  3396. m_posStart.x, m_posStart.y, m_posDest.x, m_posDest.y);
  3397.  
  3398. m_dwMoveStartTime = get_dword_time();
  3399. }
  3400.  
  3401. // x y À§Ä¡·Î À̵¿ ÇÑ´Ù. (À̵¿ÇÒ ¼ö ÀÖ´Â °¡ ¾ø´Â °¡¸¦ È®ÀÎ Çϰí Sync ¸Þ¼Òµå·Î ½ÇÁ¦ À̵¿ ÇÑ´Ù)
  3402. // ¼­¹ö´Â charÀÇ x, y °ªÀ» ¹Ù·Î ¹Ù²ÙÁö¸¸,
  3403. // Ŭ¶ó¿¡¼­´Â ÀÌÀü À§Ä¡¿¡¼­ ¹Ù²Û x, y±îÁö interpolationÇÑ´Ù.
  3404. // °È°Å³ª ¶Ù´Â °ÍÀº charÀÇ m_bNowWalking¿¡ ´Þ·ÁÀÖ´Ù.
  3405. // Warp¸¦ ÀǵµÇÑ °ÍÀ̶ó¸é Show¸¦ »ç¿ëÇÒ °Í.
  3406. bool CHARACTER::Move(long x, long y)
  3407. {
  3408. // °°Àº À§Ä¡¸é À̵¿ÇÒ ÇÊ¿ä ¾øÀ½ (ÀÚµ¿ ¼º°ø)
  3409. if (GetX() == x && GetY() == y)
  3410. return true;
  3411.  
  3412. if (test_server)
  3413. if (m_bDetailLog)
  3414. sys_log(0, "%s position %u %u", GetName(), x, y);
  3415.  
  3416. OnMove();
  3417. return Sync(x, y);
  3418. }
  3419.  
  3420. void CHARACTER::SendMovePacket(BYTE bFunc, BYTE bArg, DWORD x, DWORD y, DWORD dwDuration, DWORD dwTime, int iRot)
  3421. {
  3422. TPacketGCMove pack;
  3423.  
  3424. if (bFunc == FUNC_WAIT)
  3425. {
  3426. x = m_posDest.x;
  3427. y = m_posDest.y;
  3428. dwDuration = m_dwMoveDuration;
  3429. }
  3430.  
  3431. EncodeMovePacket(pack, GetVID(), bFunc, bArg, x, y, dwDuration, dwTime, iRot == -1 ? (int) GetRotation() / 5 : iRot);
  3432. PacketView(&pack, sizeof(TPacketGCMove), this);
  3433. }
  3434.  
  3435. #ifdef ENABLE_SUPPORT_SYSTEM
  3436. void CHARACTER::SendSupportSkillPacket(DWORD skill_vnum)
  3437. {
  3438. TPacketGCSupportUseSkill pack;
  3439. pack.bHeader = HEADER_GC_SUPPORT_SKILL;
  3440. pack.dwVnum = skill_vnum;
  3441. pack.dwVid = GetVID();
  3442. pack.dwLevel = 41;
  3443.  
  3444. PacketView(&pack, sizeof(TPacketGCSupportUseSkill), this);
  3445. }
  3446. #endif
  3447.  
  3448. int CHARACTER::GetRealPoint(BYTE type) const
  3449. {
  3450. return m_points.points[type];
  3451. }
  3452.  
  3453. void CHARACTER::SetRealPoint(BYTE type, int val)
  3454. {
  3455. m_points.points[type] = val;
  3456. }
  3457.  
  3458. int CHARACTER::GetPolymorphPoint(BYTE type) const
  3459. {
  3460. if (IsPolymorphed() && !IsPolyMaintainStat())
  3461. {
  3462. DWORD dwMobVnum = GetPolymorphVnum();
  3463. const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
  3464. int iPower = GetPolymorphPower();
  3465.  
  3466. if (pMob)
  3467. {
  3468. switch (type)
  3469. {
  3470. case POINT_ST:
  3471. if ((GetJob() == JOB_SHAMAN) || ((GetJob() == JOB_SURA) && (GetSkillGroup() == 2)))
  3472. return pMob->m_table.bStr * iPower / 100 + GetPoint(POINT_IQ);
  3473. return pMob->m_table.bStr * iPower / 100 + GetPoint(POINT_ST);
  3474.  
  3475. case POINT_HT:
  3476. return pMob->m_table.bCon * iPower / 100 + GetPoint(POINT_HT);
  3477.  
  3478. case POINT_IQ:
  3479. return pMob->m_table.bInt * iPower / 100 + GetPoint(POINT_IQ);
  3480.  
  3481. case POINT_DX:
  3482. return pMob->m_table.bDex * iPower / 100 + GetPoint(POINT_DX);
  3483. }
  3484. }
  3485. }
  3486.  
  3487. return GetPoint(type);
  3488. }
  3489.  
  3490. long long CHARACTER::GetPoint(BYTE type) const
  3491. {
  3492. if (type >= POINT_MAX_NUM)
  3493. {
  3494. sys_err("Point type overflow (type %u)", type);
  3495. return 0;
  3496. }
  3497.  
  3498. long long val = m_pointsInstant.points[type];
  3499. long long max_val = LLONG_MAX;
  3500.  
  3501. switch (type)
  3502. {
  3503. case POINT_STEAL_HP:
  3504. case POINT_STEAL_SP:
  3505. max_val = 50;
  3506. break;
  3507. case POINT_GOLD:
  3508. max_val = GOLD_MAX;
  3509. break;
  3510. }
  3511.  
  3512. if (val > max_val)
  3513. sys_err("POINT_ERROR: %s type %d val %lld (max: %lld)", GetName(), val, max_val);
  3514.  
  3515. return (val);
  3516. }
  3517.  
  3518. int CHARACTER::GetLimitPoint(BYTE type) const
  3519. {
  3520. if (type >= POINT_MAX_NUM)
  3521. {
  3522. sys_err("Point type overflow (type %u)", type);
  3523. return 0;
  3524. }
  3525.  
  3526. int val = m_pointsInstant.points[type];
  3527. int max_val = INT_MAX;
  3528. int limit = INT_MAX;
  3529. int min_limit = -INT_MAX;
  3530.  
  3531. switch (type)
  3532. {
  3533. case POINT_ATT_SPEED:
  3534. min_limit = 0;
  3535.  
  3536. if (IsPC())
  3537. limit = 170;
  3538. else
  3539. limit = 250;
  3540. break;
  3541.  
  3542. case POINT_MOV_SPEED:
  3543. min_limit = 0;
  3544.  
  3545. if (IsPC())
  3546. limit = 200;
  3547. else
  3548. limit = 250;
  3549. break;
  3550.  
  3551. case POINT_STEAL_HP:
  3552. case POINT_STEAL_SP:
  3553. limit = 50;
  3554. max_val = 50;
  3555. break;
  3556.  
  3557. case POINT_MALL_ATTBONUS:
  3558. case POINT_MALL_DEFBONUS:
  3559. limit = 20;
  3560. max_val = 50;
  3561. break;
  3562. }
  3563.  
  3564. if (val > max_val)
  3565. sys_err("POINT_ERROR: %s type %d val %d (max: %d)", GetName(), val, max_val);
  3566.  
  3567. if (val > limit)
  3568. val = limit;
  3569.  
  3570. if (val < min_limit)
  3571. val = min_limit;
  3572.  
  3573. return (val);
  3574. }
  3575.  
  3576. void CHARACTER::SetPoint(BYTE type, long long val)
  3577. {
  3578. if (type >= POINT_MAX_NUM)
  3579. {
  3580. sys_err("Point type overflow (type %u)", type);
  3581. return;
  3582. }
  3583.  
  3584. m_pointsInstant.points[type] = val;
  3585.  
  3586. // ¾ÆÁ÷ À̵¿ÀÌ ´Ù ¾È³¡³µ´Ù¸é À̵¿ ½Ã°£ °è»êÀ» ´Ù½Ã ÇØ¾ß ÇÑ´Ù.
  3587. if (type == POINT_MOV_SPEED && get_dword_time() < m_dwMoveStartTime + m_dwMoveDuration)
  3588. {
  3589. CalculateMoveDuration();
  3590. }
  3591. }
  3592.  
  3593. long long CHARACTER::GetAllowedGold() const
  3594. {
  3595. if (GetLevel() <= 10)
  3596. return 100000;
  3597. else if (GetLevel() <= 20)
  3598. return 500000;
  3599. else
  3600. return 50000000;
  3601. }
  3602.  
  3603. void CHARACTER::CheckMaximumPoints()
  3604. {
  3605. if (GetMaxHP() < GetHP())
  3606. PointChange(POINT_HP, GetMaxHP() - GetHP());
  3607.  
  3608. if (GetMaxSP() < GetSP())
  3609. PointChange(POINT_SP, GetMaxSP() - GetSP());
  3610. }
  3611.  
  3612. void CHARACTER::PointChange(BYTE type, long long amount, bool bAmount, bool bBroadcast)
  3613. {
  3614. long long val = 0;
  3615.  
  3616. //sys_log(0, "PointChange %d %d | %d -> %d cHP %d mHP %d", type, amount, GetPoint(type), GetPoint(type)+amount, GetHP(), GetMaxHP());
  3617.  
  3618. switch (type)
  3619. {
  3620. case POINT_NONE:
  3621. return;
  3622.  
  3623. case POINT_LEVEL:
  3624. if ((GetLevel() + amount) > gPlayerMaxLevel)
  3625. return;
  3626.  
  3627. SetLevel(GetLevel() + amount);
  3628. val = GetLevel();
  3629.  
  3630. sys_log(0, "LEVELUP: %s %d NEXT EXP %d", GetName(), GetLevel(), GetNextExp());
  3631. #ifdef ENABLE_WOLFMAN_CHARACTER
  3632. if (GetJob() == JOB_WOLFMAN)
  3633. {
  3634. if ((5 <= val) && (GetSkillGroup()!=1))
  3635. {
  3636. ClearSkill();
  3637. SetSkillGroup(1);
  3638. SetRealPoint(POINT_SKILL, GetLevel()-1);
  3639. SetPoint(POINT_SKILL, GetRealPoint(POINT_SKILL));
  3640. PointChange(POINT_SKILL, 0);
  3641. }
  3642. }
  3643. #endif
  3644. PointChange(POINT_NEXT_EXP, GetNextExp(), false);
  3645.  
  3646. switch (val)
  3647. {
  3648. case 80: case 90: case 100: case 105: case 120:
  3649. char szNoticeLevelUp[QUERY_MAX_LEN];
  3650. snprintf(szNoticeLevelUp, sizeof(szNoticeLevelUp), "[i] CH%d: (%s) a atins nivelul [%u].", g_bChannel, GetName(), GetLevel());
  3651. BroadcastNotice(szNoticeLevelUp);
  3652. break;
  3653.  
  3654. default:
  3655. break;
  3656. }
  3657.  
  3658. if (amount)
  3659. {
  3660. quest::CQuestManager::instance().LevelUp(GetPlayerID());
  3661.  
  3662. LogManager::instance().LevelLog(this, val, GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000);
  3663.  
  3664. if (GetGuild())
  3665. {
  3666. GetGuild()->LevelChange(GetPlayerID(), GetLevel());
  3667. }
  3668.  
  3669. if (GetParty())
  3670. {
  3671. GetParty()->RequestSetMemberLevel(GetPlayerID(), GetLevel());
  3672. }
  3673. }
  3674. break;
  3675.  
  3676. case POINT_NEXT_EXP:
  3677. val = GetNextExp();
  3678. bAmount = false; // ¹«Á¶°Ç bAmount´Â false ¿©¾ß ÇÑ´Ù.
  3679. break;
  3680.  
  3681. case POINT_EXP:
  3682. {
  3683.  
  3684. #ifdef ENABLE_ANTIEXP_RENEWAL
  3685. if (FindAffect(AFFECT_ANTIEXP) && amount > 0)
  3686. return;
  3687. #endif
  3688.  
  3689. DWORD exp = GetExp();
  3690. DWORD next_exp = GetNextExp();
  3691.  
  3692. // û¼Ò³âº¸È£
  3693. if (g_bChinaIntoxicationCheck)
  3694. {
  3695. if (IsOverTime(OT_NONE))
  3696. {
  3697. dev_log(LOG_DEB0, "<EXP_LOG> %s = NONE", GetName());
  3698. }
  3699. else if (IsOverTime(OT_3HOUR))
  3700. {
  3701. amount = (amount / 2);
  3702. dev_log(LOG_DEB0, "<EXP_LOG> %s = 3HOUR", GetName());
  3703. }
  3704. else if (IsOverTime(OT_5HOUR))
  3705. {
  3706. amount = 0;
  3707. dev_log(LOG_DEB0, "<EXP_LOG> %s = 5HOUR", GetName());
  3708. }
  3709. }
  3710.  
  3711. // exp°¡ 0 ÀÌÇÏ·Î °¡Áö ¾Êµµ·Ï ÇÑ´Ù
  3712. if ((amount < 0) && (exp < (DWORD)(-amount)))
  3713. {
  3714. sys_log(1, "%s AMOUNT < 0 %d, CUR EXP: %d", GetName(), -amount, exp);
  3715. amount = -exp;
  3716.  
  3717. SetExp(exp + amount);
  3718. val = GetExp();
  3719. }
  3720. else
  3721. {
  3722. if (gPlayerMaxLevel <= GetLevel())
  3723. return;
  3724.  
  3725. if (block_exp)
  3726. return;
  3727.  
  3728. if (test_server)
  3729. ChatPacket(CHAT_TYPE_INFO, "You have gained %d exp.", amount);
  3730.  
  3731. DWORD iExpBalance = 0;
  3732.  
  3733. // ·¹º§ ¾÷!
  3734. if (exp + amount >= next_exp)
  3735. {
  3736. iExpBalance = (exp + amount) - next_exp;
  3737. amount = next_exp - exp;
  3738.  
  3739. SetExp(0);
  3740. exp = next_exp;
  3741. }
  3742. else
  3743. {
  3744. SetExp(exp + amount);
  3745. exp = GetExp();
  3746. }
  3747.  
  3748. DWORD q = DWORD(next_exp / 4.0f);
  3749. int iLevStep = GetRealPoint(POINT_LEVEL_STEP);
  3750.  
  3751. // iLevStepÀÌ 4 ÀÌ»óÀÌ¸é ·¹º§ÀÌ ¿Ã¶ú¾î¾ß ÇϹǷΠ¿©±â¿¡ ¿Ã ¼ö ¾ø´Â °ªÀÌ´Ù.
  3752. if (iLevStep >= 4)
  3753. {
  3754. sys_err("%s LEVEL_STEP bigger than 4! (%d)", GetName(), iLevStep);
  3755. iLevStep = 4;
  3756. }
  3757.  
  3758. if (exp >= next_exp && iLevStep < 4)
  3759. {
  3760. for (int i = 0; i < 4 - iLevStep; ++i)
  3761. PointChange(POINT_LEVEL_STEP, 1, false, true);
  3762. }
  3763. else if (exp >= q * 3 && iLevStep < 3)
  3764. {
  3765. for (int i = 0; i < 3 - iLevStep; ++i)
  3766. PointChange(POINT_LEVEL_STEP, 1, false, true);
  3767. }
  3768. else if (exp >= q * 2 && iLevStep < 2)
  3769. {
  3770. for (int i = 0; i < 2 - iLevStep; ++i)
  3771. PointChange(POINT_LEVEL_STEP, 1, false, true);
  3772. }
  3773. else if (exp >= q && iLevStep < 1)
  3774. PointChange(POINT_LEVEL_STEP, 1);
  3775.  
  3776. if (iExpBalance)
  3777. {
  3778. PointChange(POINT_EXP, iExpBalance);
  3779. }
  3780.  
  3781. val = GetExp();
  3782. }
  3783. }
  3784. break;
  3785.  
  3786. case POINT_LEVEL_STEP:
  3787. if (amount > 0)
  3788. {
  3789. val = GetPoint(POINT_LEVEL_STEP) + amount;
  3790.  
  3791. switch (val)
  3792. {
  3793. case 1:
  3794. case 2:
  3795. case 3:
  3796. if ((GetLevel() <= g_iStatusPointGetLevelLimit) &&
  3797. (GetLevel() <= gPlayerMaxLevel) ) // @fixme104
  3798. PointChange(POINT_STAT, 1);
  3799. break;
  3800.  
  3801. case 4:
  3802. {
  3803. int iHP = number(JobInitialPoints[GetJob()].hp_per_lv_begin, JobInitialPoints[GetJob()].hp_per_lv_end);
  3804. int iSP = number(JobInitialPoints[GetJob()].sp_per_lv_begin, JobInitialPoints[GetJob()].sp_per_lv_end);
  3805.  
  3806. m_points.iRandomHP += iHP;
  3807. m_points.iRandomSP += iSP;
  3808.  
  3809. if (GetSkillGroup())
  3810. {
  3811. if (GetLevel() >= 5)
  3812. PointChange(POINT_SKILL, 1);
  3813.  
  3814. if (GetLevel() >= 9)
  3815. PointChange(POINT_SUB_SKILL, 1);
  3816. }
  3817.  
  3818. PointChange(POINT_MAX_HP, iHP);
  3819. PointChange(POINT_MAX_SP, iSP);
  3820. PointChange(POINT_LEVEL, 1, false, true);
  3821.  
  3822. val = 0;
  3823. }
  3824. break;
  3825. }
  3826.  
  3827. // if (GetLevel() <= 10)
  3828. // AutoGiveItem(27001, 2);
  3829. // else if (GetLevel() <= 30)
  3830. // AutoGiveItem(27002, 2);
  3831. // else
  3832. // {
  3833. // AutoGiveItem(27002, 2);
  3834. // AutoGiveItem(27003, 2);
  3835. // }
  3836.  
  3837. PointChange(POINT_HP, GetMaxHP() - GetHP());
  3838. PointChange(POINT_SP, GetMaxSP() - GetSP());
  3839. PointChange(POINT_STAMINA, GetMaxStamina() - GetStamina());
  3840.  
  3841. SetPoint(POINT_LEVEL_STEP, val);
  3842. SetRealPoint(POINT_LEVEL_STEP, val);
  3843.  
  3844. Save();
  3845. }
  3846. else
  3847. val = GetPoint(POINT_LEVEL_STEP);
  3848.  
  3849. break;
  3850.  
  3851. case POINT_HP:
  3852. {
  3853. if (IsDead() || IsStun())
  3854. return;
  3855.  
  3856. int prev_hp = GetHP();
  3857.  
  3858. amount = MIN(GetMaxHP() - GetHP(), amount);
  3859. SetHP(GetHP() + amount);
  3860. val = GetHP();
  3861.  
  3862. BroadcastTargetPacket();
  3863.  
  3864. if (GetParty() && IsPC() && val != prev_hp)
  3865. GetParty()->SendPartyInfoOneToAll(this);
  3866. }
  3867. break;
  3868.  
  3869. case POINT_SP:
  3870. {
  3871. if (IsDead() || IsStun())
  3872. return;
  3873.  
  3874. amount = MIN(GetMaxSP() - GetSP(), amount);
  3875. SetSP(GetSP() + amount);
  3876. val = GetSP();
  3877. }
  3878. break;
  3879.  
  3880. case POINT_STAMINA:
  3881. {
  3882. if (IsDead() || IsStun())
  3883. return;
  3884.  
  3885. int prev_val = GetStamina();
  3886. amount = MIN(GetMaxStamina() - GetStamina(), amount);
  3887. SetStamina(GetStamina() + amount);
  3888. val = GetStamina();
  3889.  
  3890. if (val == 0)
  3891. {
  3892. // Stamina°¡ ¾øÀ¸´Ï °ÈÀÚ!
  3893. SetNowWalking(true);
  3894. }
  3895. else if (prev_val == 0)
  3896. {
  3897. // ¾ø´ø ½ºÅ׹̳ª°¡ »ý°åÀ¸´Ï ÀÌÀü ¸ðµå º¹±Í
  3898. ResetWalking();
  3899. }
  3900.  
  3901. if (amount < 0 && val != 0) // °¨¼Ò´Â º¸³»Áö¾Ê´Â´Ù.
  3902. return;
  3903. }
  3904. break;
  3905.  
  3906. case POINT_MAX_HP:
  3907. {
  3908. SetPoint(type, GetPoint(type) + amount);
  3909.  
  3910. //SetMaxHP(GetMaxHP() + amount);
  3911. // ÃÖ´ë »ý¸í·Â = (±âº» ÃÖ´ë »ý¸í·Â + Ãß°¡) * ÃÖ´ë»ý¸í·Â%
  3912. int hp = GetRealPoint(POINT_MAX_HP);
  3913. int add_hp = MIN(3500, hp * GetPoint(POINT_MAX_HP_PCT) / 100);
  3914. add_hp += GetPoint(POINT_MAX_HP);
  3915. add_hp += GetPoint(POINT_PARTY_TANKER_BONUS);
  3916.  
  3917. SetMaxHP(hp + add_hp);
  3918.  
  3919. val = GetMaxHP();
  3920. }
  3921. break;
  3922.  
  3923. case POINT_MAX_SP:
  3924. {
  3925. SetPoint(type, GetPoint(type) + amount);
  3926.  
  3927. //SetMaxSP(GetMaxSP() + amount);
  3928. // ÃÖ´ë Á¤½Å·Â = (±âº» ÃÖ´ë Á¤½Å·Â + Ãß°¡) * ÃÖ´ëÁ¤½Å·Â%
  3929. int sp = GetRealPoint(POINT_MAX_SP);
  3930. int add_sp = MIN(800, sp * GetPoint(POINT_MAX_SP_PCT) / 100);
  3931. add_sp += GetPoint(POINT_MAX_SP);
  3932. add_sp += GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
  3933.  
  3934. SetMaxSP(sp + add_sp);
  3935.  
  3936. val = GetMaxSP();
  3937. }
  3938. break;
  3939.  
  3940. case POINT_MAX_HP_PCT:
  3941. SetPoint(type, GetPoint(type) + amount);
  3942. val = GetPoint(type);
  3943.  
  3944. PointChange(POINT_MAX_HP, 0);
  3945. break;
  3946.  
  3947. case POINT_MAX_SP_PCT:
  3948. SetPoint(type, GetPoint(type) + amount);
  3949. val = GetPoint(type);
  3950.  
  3951. PointChange(POINT_MAX_SP, 0);
  3952. break;
  3953.  
  3954. case POINT_MAX_STAMINA:
  3955. SetMaxStamina(GetMaxStamina() + amount);
  3956. val = GetMaxStamina();
  3957. break;
  3958.  
  3959. case POINT_GOLD:
  3960. {
  3961. const long long nTotalMoney = static_cast<long long>(GetGold()) + static_cast<long long>(amount);
  3962.  
  3963. if (GOLD_MAX <= nTotalMoney)
  3964. {
  3965. sys_err("[OVERFLOW_GOLD] OriGold %lld AddedGold %lld id %u Name %s ", GetGold(), amount, GetPlayerID(), GetName());
  3966. LogManager::instance().CharLog(this, GetGold() + amount, "OVERFLOW_GOLD", "");
  3967. return;
  3968. }
  3969.  
  3970. // û¼Ò³âº¸È£
  3971. if (g_bChinaIntoxicationCheck && amount > 0)
  3972. {
  3973. if (IsOverTime(OT_NONE))
  3974. {
  3975. dev_log(LOG_DEB0, "<GOLD_LOG> %s = NONE", GetName());
  3976. }
  3977. else if (IsOverTime(OT_3HOUR))
  3978. {
  3979. amount = (amount / 2);
  3980. dev_log(LOG_DEB0, "<GOLD_LOG> %s = 3HOUR", GetName());
  3981. }
  3982. else if (IsOverTime(OT_5HOUR))
  3983. {
  3984. amount = 0;
  3985. dev_log(LOG_DEB0, "<GOLD_LOG> %s = 5HOUR", GetName());
  3986. }
  3987. }
  3988.  
  3989. SetGold(GetGold() + amount);
  3990. val = GetGold();
  3991. }
  3992. break;
  3993.  
  3994. #ifdef ENABLE_GEM_SYSTEM
  3995. case POINT_GEM:
  3996. {
  3997. DWORD nTotalGem = GetGem() + amount;
  3998.  
  3999. if (GEM_MAX <= nTotalGem)
  4000. {
  4001. LogManager::instance().CharLog(this, GetGem() + amount, "OVERFLOW_GEM", "");
  4002. return;
  4003. }
  4004.  
  4005. SetGem(GetGem() + amount);
  4006. val = GetGem();
  4007. }
  4008. break;
  4009. #endif
  4010.  
  4011. #ifdef __ENABLE_BATTLE_FIELD__
  4012. case POINT_BATTLE_POINT:
  4013. {
  4014. const int64_t nTotalBattlePoints = static_cast<int64_t>(GetBattlePoints()) + static_cast<int64_t>(amount);
  4015.  
  4016. if (BATTLE_POINT_MAX <= nTotalBattlePoints || nTotalBattlePoints < 0)
  4017. {
  4018. return;
  4019. }
  4020.  
  4021. SetBattlePoints(GetBattlePoints() + amount);
  4022. val = GetBattlePoints();
  4023. }
  4024. break;
  4025.  
  4026. case POINT_TEMP_BATTLE_POINT:
  4027. SetPoint(type, GetPoint(type) + amount);
  4028. val = GetPoint(type);
  4029. break;
  4030. #endif
  4031.  
  4032. case POINT_SKILL:
  4033. case POINT_STAT:
  4034. case POINT_SUB_SKILL:
  4035. case POINT_STAT_RESET_COUNT:
  4036. case POINT_HORSE_SKILL:
  4037. SetPoint(type, GetPoint(type) + amount);
  4038. val = GetPoint(type);
  4039.  
  4040. SetRealPoint(type, val);
  4041. break;
  4042.  
  4043. case POINT_DEF_GRADE:
  4044. SetPoint(type, GetPoint(type) + amount);
  4045. val = GetPoint(type);
  4046.  
  4047. PointChange(POINT_CLIENT_DEF_GRADE, amount);
  4048. break;
  4049.  
  4050. case POINT_CLIENT_DEF_GRADE:
  4051. SetPoint(type, GetPoint(type) + amount);
  4052. val = GetPoint(type);
  4053. break;
  4054.  
  4055. case POINT_ST:
  4056. case POINT_HT:
  4057. case POINT_DX:
  4058. case POINT_IQ:
  4059. case POINT_HP_REGEN:
  4060. case POINT_SP_REGEN:
  4061. case POINT_ATT_SPEED:
  4062. case POINT_ATT_GRADE:
  4063. case POINT_MOV_SPEED:
  4064. case POINT_CASTING_SPEED:
  4065. case POINT_MAGIC_ATT_GRADE:
  4066. case POINT_MAGIC_DEF_GRADE:
  4067. case POINT_BOW_DISTANCE:
  4068. case POINT_HP_RECOVERY:
  4069. case POINT_SP_RECOVERY:
  4070.  
  4071. case POINT_ATTBONUS_HUMAN: // 42 Àΰ£¿¡°Ô °­ÇÔ
  4072. case POINT_ATTBONUS_ANIMAL: // 43 µ¿¹°¿¡°Ô µ¥¹ÌÁö % Áõ°¡
  4073. case POINT_ATTBONUS_ORC: // 44 ¿õ±Í¿¡°Ô µ¥¹ÌÁö % Áõ°¡
  4074. case POINT_ATTBONUS_MILGYO: // 45 ¹Ð±³¿¡°Ô µ¥¹ÌÁö % Áõ°¡
  4075. case POINT_ATTBONUS_UNDEAD: // 46 ½Ãü¿¡°Ô µ¥¹ÌÁö % Áõ°¡
  4076. case POINT_ATTBONUS_DEVIL: // 47 ¸¶±Í(¾Ç¸¶)¿¡°Ô µ¥¹ÌÁö % Áõ°¡
  4077. case POINT_ATTBONUS_MONSTER:
  4078. case POINT_ATTBONUS_SURA:
  4079. case POINT_ATTBONUS_ASSASSIN:
  4080. case POINT_ATTBONUS_WARRIOR:
  4081. case POINT_ATTBONUS_SHAMAN:
  4082. #ifdef ENABLE_WOLFMAN_CHARACTER
  4083. case POINT_ATTBONUS_WOLFMAN:
  4084. #endif
  4085.  
  4086. case POINT_POISON_PCT:
  4087. #ifdef ENABLE_WOLFMAN_CHARACTER
  4088. case POINT_BLEEDING_PCT:
  4089. #endif
  4090. case POINT_STUN_PCT:
  4091. case POINT_SLOW_PCT:
  4092.  
  4093. case POINT_BLOCK:
  4094. case POINT_DODGE:
  4095.  
  4096. case POINT_CRITICAL_PCT:
  4097. case POINT_RESIST_CRITICAL:
  4098. case POINT_PENETRATE_PCT:
  4099. case POINT_RESIST_PENETRATE:
  4100. case POINT_CURSE_PCT:
  4101.  
  4102. case POINT_STEAL_HP: // 48 »ý¸í·Â Èí¼ö
  4103. case POINT_STEAL_SP: // 49 Á¤½Å·Â Èí¼ö
  4104.  
  4105. case POINT_MANA_BURN_PCT: // 50 ¸¶³ª ¹ø
  4106. case POINT_DAMAGE_SP_RECOVER: // 51 °ø°Ý´çÇÒ ½Ã Á¤½Å·Â ȸº¹ È®·ü
  4107. case POINT_RESIST_NORMAL_DAMAGE:
  4108. case POINT_RESIST_SWORD:
  4109. case POINT_RESIST_TWOHAND:
  4110. case POINT_RESIST_DAGGER:
  4111. case POINT_RESIST_BELL:
  4112. case POINT_RESIST_FAN:
  4113. case POINT_RESIST_BOW:
  4114. #ifdef ENABLE_WOLFMAN_CHARACTER
  4115. case POINT_RESIST_CLAW:
  4116. #endif
  4117. case POINT_RESIST_FIRE:
  4118. case POINT_RESIST_ELEC:
  4119. case POINT_RESIST_MAGIC:
  4120. #ifdef ENABLE_ACCE_COSTUME_SYSTEM
  4121. case POINT_ACCEDRAIN_RATE:
  4122. #endif
  4123. #ifdef ENABLE_MAGIC_REDUCTION_SYSTEM
  4124. case POINT_RESIST_MAGIC_REDUCTION:
  4125. #endif
  4126. case POINT_RESIST_WIND:
  4127. case POINT_RESIST_ICE:
  4128. case POINT_RESIST_EARTH:
  4129. case POINT_RESIST_DARK:
  4130. case POINT_REFLECT_MELEE: // 67 °ø°Ý ¹Ý»ç
  4131. case POINT_REFLECT_CURSE: // 68 ÀúÁÖ ¹Ý»ç
  4132. case POINT_POISON_REDUCE: // 69 µ¶µ¥¹ÌÁö °¨¼Ò
  4133. #ifdef ENABLE_WOLFMAN_CHARACTER
  4134. case POINT_BLEEDING_REDUCE:
  4135. #endif
  4136. case POINT_KILL_SP_RECOVER: // 70 Àû ¼Ò¸ê½Ã MP ȸº¹
  4137. case POINT_KILL_HP_RECOVERY: // 75
  4138. case POINT_HIT_HP_RECOVERY:
  4139. case POINT_HIT_SP_RECOVERY:
  4140. case POINT_MANASHIELD:
  4141. case POINT_ATT_BONUS:
  4142. case POINT_DEF_BONUS:
  4143. case POINT_SKILL_DAMAGE_BONUS:
  4144. case POINT_NORMAL_HIT_DAMAGE_BONUS:
  4145.  
  4146. // DEPEND_BONUS_ATTRIBUTES
  4147. case POINT_SKILL_DEFEND_BONUS:
  4148. case POINT_NORMAL_HIT_DEFEND_BONUS:
  4149. SetPoint(type, GetPoint(type) + amount);
  4150. val = GetPoint(type);
  4151. break;
  4152. // END_OF_DEPEND_BONUS_ATTRIBUTES
  4153.  
  4154. case POINT_PARTY_ATTACKER_BONUS:
  4155. case POINT_PARTY_TANKER_BONUS:
  4156. case POINT_PARTY_BUFFER_BONUS:
  4157. case POINT_PARTY_SKILL_MASTER_BONUS:
  4158. case POINT_PARTY_HASTE_BONUS:
  4159. case POINT_PARTY_DEFENDER_BONUS:
  4160.  
  4161. case POINT_RESIST_WARRIOR :
  4162. case POINT_RESIST_ASSASSIN :
  4163. case POINT_RESIST_SURA :
  4164. case POINT_RESIST_SHAMAN :
  4165. #ifdef ENABLE_WOLFMAN_CHARACTER
  4166. case POINT_RESIST_WOLFMAN :
  4167. #endif
  4168.  
  4169. SetPoint(type, GetPoint(type) + amount);
  4170. val = GetPoint(type);
  4171. break;
  4172.  
  4173. case POINT_MALL_ATTBONUS:
  4174. case POINT_MALL_DEFBONUS:
  4175. case POINT_MALL_EXPBONUS:
  4176. case POINT_MALL_ITEMBONUS:
  4177. case POINT_MALL_GOLDBONUS:
  4178. case POINT_MELEE_MAGIC_ATT_BONUS_PER:
  4179. // if (GetPoint(type) + amount > 100)
  4180. // {
  4181. // sys_err("MALL_BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), amount);
  4182. // amount = 100 - GetPoint(type);
  4183. // }
  4184.  
  4185. SetPoint(type, GetPoint(type) + amount);
  4186. val = GetPoint(type);
  4187. break;
  4188.  
  4189. // PC_BANG_ITEM_ADD
  4190. case POINT_PC_BANG_EXP_BONUS :
  4191. case POINT_PC_BANG_DROP_BONUS :
  4192. case POINT_RAMADAN_CANDY_BONUS_EXP:
  4193. SetPoint(type, amount);
  4194. val = GetPoint(type);
  4195. break;
  4196. // END_PC_BANG_ITEM_ADD
  4197.  
  4198. case POINT_EXP_DOUBLE_BONUS: // 71
  4199. case POINT_GOLD_DOUBLE_BONUS: // 72
  4200. case POINT_ITEM_DROP_BONUS: // 73
  4201. case POINT_POTION_BONUS: // 74
  4202. // if (GetPoint(type) + amount > 100)
  4203. // {
  4204. // sys_err("BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), amount);
  4205. // amount = 100 - GetPoint(type);
  4206. // }
  4207.  
  4208. SetPoint(type, GetPoint(type) + amount);
  4209. val = GetPoint(type);
  4210. break;
  4211.  
  4212. case POINT_IMMUNE_STUN: // 76
  4213. SetPoint(type, GetPoint(type) + amount);
  4214. val = GetPoint(type);
  4215. if (val)
  4216. {
  4217. // ChatPacket(CHAT_TYPE_INFO, "IMMUNE_STUN SET_BIT type(%u) amount(%d)", type, amount);
  4218. SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN);
  4219. }
  4220. else
  4221. {
  4222. // ChatPacket(CHAT_TYPE_INFO, "IMMUNE_STUN REMOVE_BIT type(%u) amount(%d)", type, amount);
  4223. REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN);
  4224. }
  4225. break;
  4226.  
  4227. case POINT_IMMUNE_SLOW: // 77
  4228. SetPoint(type, GetPoint(type) + amount);
  4229. val = GetPoint(type);
  4230. if (val)
  4231. {
  4232. SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW);
  4233. }
  4234. else
  4235. {
  4236. REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW);
  4237. }
  4238. break;
  4239.  
  4240. case POINT_IMMUNE_FALL: // 78
  4241. SetPoint(type, GetPoint(type) + amount);
  4242. val = GetPoint(type);
  4243. if (val)
  4244. {
  4245. SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL);
  4246. }
  4247. else
  4248. {
  4249. REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL);
  4250. }
  4251. break;
  4252.  
  4253. case POINT_ATT_GRADE_BONUS:
  4254. SetPoint(type, GetPoint(type) + amount);
  4255. PointChange(POINT_ATT_GRADE, amount);
  4256. val = GetPoint(type);
  4257. break;
  4258.  
  4259. case POINT_DEF_GRADE_BONUS:
  4260. SetPoint(type, GetPoint(type) + amount);
  4261. PointChange(POINT_DEF_GRADE, amount);
  4262. val = GetPoint(type);
  4263. break;
  4264.  
  4265. case POINT_MAGIC_ATT_GRADE_BONUS:
  4266. SetPoint(type, GetPoint(type) + amount);
  4267. PointChange(POINT_MAGIC_ATT_GRADE, amount);
  4268. val = GetPoint(type);
  4269. break;
  4270.  
  4271. case POINT_MAGIC_DEF_GRADE_BONUS:
  4272. SetPoint(type, GetPoint(type) + amount);
  4273. PointChange(POINT_MAGIC_DEF_GRADE, amount);
  4274. val = GetPoint(type);
  4275. break;
  4276.  
  4277. case POINT_VOICE:
  4278. case POINT_EMPIRE_POINT:
  4279. //sys_err("CHARACTER::PointChange: %s: point cannot be changed. use SetPoint instead (type: %d)", GetName(), type);
  4280. val = GetRealPoint(type);
  4281. break;
  4282.  
  4283. case POINT_POLYMORPH:
  4284. SetPoint(type, GetPoint(type) + amount);
  4285. val = GetPoint(type);
  4286. SetPolymorph(val);
  4287. break;
  4288.  
  4289. case POINT_MOUNT:
  4290. SetPoint(type, GetPoint(type) + amount);
  4291. val = GetPoint(type);
  4292. MountVnum(val);
  4293. break;
  4294.  
  4295. case POINT_ENERGY:
  4296. case POINT_COSTUME_ATTR_BONUS:
  4297. {
  4298. int old_val = GetPoint(type);
  4299. SetPoint(type, old_val + amount);
  4300. val = GetPoint(type);
  4301. BuffOnAttr_ValueChange(type, old_val, val);
  4302. }
  4303. break;
  4304.  
  4305. default:
  4306. sys_err("CHARACTER::PointChange: %s: unknown point change type %d", GetName(), type);
  4307. return;
  4308. }
  4309.  
  4310. switch (type)
  4311. {
  4312. case POINT_LEVEL:
  4313. case POINT_ST:
  4314. case POINT_DX:
  4315. case POINT_IQ:
  4316. case POINT_HT:
  4317. ComputeBattlePoints();
  4318. break;
  4319. case POINT_MAX_HP:
  4320. case POINT_MAX_SP:
  4321. case POINT_MAX_STAMINA:
  4322. break;
  4323. }
  4324.  
  4325. if (type == POINT_HP && amount == 0)
  4326. return;
  4327.  
  4328. if (GetDesc())
  4329. {
  4330. struct packet_point_change pack;
  4331.  
  4332. pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
  4333. pack.dwVID = m_vid;
  4334. pack.type = type;
  4335. pack.value = val;
  4336.  
  4337. if (bAmount)
  4338. pack.amount = amount;
  4339. else
  4340. pack.amount = 0;
  4341.  
  4342. if (!bBroadcast)
  4343. GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
  4344. else
  4345. PacketAround(&pack, sizeof(pack));
  4346. }
  4347. }
  4348.  
  4349. #ifdef NEW_PET_SYSTEM
  4350. void CHARACTER::SendPetLevelUpEffect(int vid, int type, int value, int amount) {
  4351. struct packet_point_change pack;
  4352.  
  4353. pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
  4354. pack.dwVID = vid;
  4355. pack.type = type;
  4356. pack.value = value;
  4357. pack.amount = amount;
  4358. PacketAround(&pack, sizeof(pack));
  4359. }
  4360. #endif
  4361.  
  4362. void CHARACTER::ApplyPoint(BYTE bApplyType, int iVal)
  4363. {
  4364. switch (bApplyType)
  4365. {
  4366. case APPLY_NONE: // 0
  4367. break;;
  4368.  
  4369. case APPLY_CON:
  4370. PointChange(POINT_HT, iVal);
  4371. PointChange(POINT_MAX_HP, (iVal * JobInitialPoints[GetJob()].hp_per_ht));
  4372. PointChange(POINT_MAX_STAMINA, (iVal * JobInitialPoints[GetJob()].stamina_per_con));
  4373. break;
  4374.  
  4375. case APPLY_INT:
  4376. PointChange(POINT_IQ, iVal);
  4377. PointChange(POINT_MAX_SP, (iVal * JobInitialPoints[GetJob()].sp_per_iq));
  4378. break;
  4379.  
  4380. case APPLY_SKILL:
  4381. // SKILL_DAMAGE_BONUS
  4382. {
  4383. // ÃÖ»óÀ§ ºñÆ® ±âÁØÀ¸·Î 8ºñÆ® vnum, 9ºñÆ® add, 15ºñÆ® change
  4384. // 00000000 00000000 00000000 00000000
  4385. // ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
  4386. // vnum ^ add change
  4387. BYTE bSkillVnum = (BYTE) (((DWORD)iVal) >> 24);
  4388. int iAdd = iVal & 0x00800000;
  4389. int iChange = iVal & 0x007fffff;
  4390.  
  4391. sys_log(1, "APPLY_SKILL skill %d add? %d change %d", bSkillVnum, iAdd ? 1 : 0, iChange);
  4392.  
  4393. if (0 == iAdd)
  4394. iChange = -iChange;
  4395.  
  4396. boost::unordered_map<BYTE, int>::iterator iter = m_SkillDamageBonus.find(bSkillVnum);
  4397.  
  4398. if (iter == m_SkillDamageBonus.end())
  4399. m_SkillDamageBonus.insert(std::make_pair(bSkillVnum, iChange));
  4400. else
  4401. iter->second += iChange;
  4402. }
  4403. // END_OF_SKILL_DAMAGE_BONUS
  4404. break;
  4405.  
  4406. // NOTE: ¾ÆÀÌÅÛ¿¡ ÀÇÇÑ ÃÖ´ëHP º¸³Ê½º³ª Äù½ºÆ® º¸»ó º¸³Ê½º°¡ ¶È°°Àº ¹æ½ÄÀ» »ç¿ëÇϹǷÎ
  4407. // ±×³É MAX_HP¸¸ °è»êÇϸé Äù½ºÆ® º¸»óÀÇ °æ¿ì ¹®Á¦°¡ »ý±è. »ç½Ç ¿ø·¡ ÀÌÂÊÀÌ ÇÕ¸®ÀûÀ̱⵵ Çϰí..
  4408. // ¹Ù²Û °ø½ÄÀº ÇöÀç ÃÖ´ë hp¿Í º¸À¯ hpÀÇ ºñÀ²À» ±¸ÇÑ µÚ ¹Ù²ð ÃÖ´ë hp¸¦ ±âÁØÀ¸·Î hp¸¦ º¸Á¤ÇÑ´Ù.
  4409. // ¿ø·¡ PointChange¿¡¼­ ÇÏ´Â°Ô ÁÁÀ»°Í °°Àºµ¥ ¼³°è ¹®Á¦·Î ¾î·Á¿ö¼­ skip..
  4410. // SPµµ ¶È°°ÀÌ °è»êÇÑ´Ù.
  4411. // Mantis : 101460 ~ ity ~
  4412. case APPLY_MAX_HP:
  4413. case APPLY_MAX_HP_PCT:
  4414. {
  4415. int i = GetMaxHP(); if(i == 0) break;
  4416. PointChange(aApplyInfo[bApplyType].bPointType, iVal);
  4417. float fRatio = (float)GetMaxHP() / (float)i;
  4418. PointChange(POINT_HP, GetHP() * fRatio - GetHP());
  4419. }
  4420. break;
  4421.  
  4422. case APPLY_MAX_SP:
  4423. case APPLY_MAX_SP_PCT:
  4424. {
  4425. int i = GetMaxSP(); if(i == 0) break;
  4426. PointChange(aApplyInfo[bApplyType].bPointType, iVal);
  4427. float fRatio = (float)GetMaxSP() / (float)i;
  4428. PointChange(POINT_SP, GetSP() * fRatio - GetSP());
  4429. }
  4430. break;
  4431.  
  4432. case APPLY_STR:
  4433. case APPLY_DEX:
  4434. case APPLY_ATT_SPEED:
  4435. case APPLY_MOV_SPEED:
  4436. case APPLY_CAST_SPEED:
  4437. case APPLY_HP_REGEN:
  4438. case APPLY_SP_REGEN:
  4439. case APPLY_POISON_PCT:
  4440. #ifdef ENABLE_WOLFMAN_CHARACTER
  4441. case APPLY_BLEEDING_PCT:
  4442. #endif
  4443. case APPLY_STUN_PCT:
  4444. case APPLY_SLOW_PCT:
  4445. case APPLY_CRITICAL_PCT:
  4446. case APPLY_PENETRATE_PCT:
  4447. case APPLY_ATTBONUS_HUMAN:
  4448. case APPLY_ATTBONUS_ANIMAL:
  4449. case APPLY_ATTBONUS_ORC:
  4450. case APPLY_ATTBONUS_MILGYO:
  4451. case APPLY_ATTBONUS_UNDEAD:
  4452. case APPLY_ATTBONUS_DEVIL:
  4453. case APPLY_ATTBONUS_WARRIOR: // 59
  4454. case APPLY_ATTBONUS_ASSASSIN: // 60
  4455. case APPLY_ATTBONUS_SURA: // 61
  4456. case APPLY_ATTBONUS_SHAMAN: // 62
  4457. #ifdef ENABLE_WOLFMAN_CHARACTER
  4458. case APPLY_ATTBONUS_WOLFMAN:
  4459. #endif
  4460. case APPLY_ATTBONUS_MONSTER: // 63
  4461. case APPLY_STEAL_HP:
  4462. case APPLY_STEAL_SP:
  4463. case APPLY_MANA_BURN_PCT:
  4464. case APPLY_DAMAGE_SP_RECOVER:
  4465. case APPLY_BLOCK:
  4466. case APPLY_DODGE:
  4467. case APPLY_RESIST_SWORD:
  4468. case APPLY_RESIST_TWOHAND:
  4469. case APPLY_RESIST_DAGGER:
  4470. case APPLY_RESIST_BELL:
  4471. case APPLY_RESIST_FAN:
  4472. case APPLY_RESIST_BOW:
  4473. #ifdef ENABLE_WOLFMAN_CHARACTER
  4474. case APPLY_RESIST_CLAW:
  4475. #endif
  4476. case APPLY_RESIST_FIRE:
  4477. case APPLY_RESIST_ELEC:
  4478. case APPLY_RESIST_MAGIC:
  4479. case APPLY_RESIST_WIND:
  4480. case APPLY_RESIST_ICE:
  4481. case APPLY_RESIST_EARTH:
  4482. case APPLY_RESIST_DARK:
  4483. case APPLY_REFLECT_MELEE:
  4484. case APPLY_REFLECT_CURSE:
  4485. case APPLY_ANTI_CRITICAL_PCT:
  4486. case APPLY_ANTI_PENETRATE_PCT:
  4487. case APPLY_POISON_REDUCE:
  4488. #ifdef ENABLE_WOLFMAN_CHARACTER
  4489. case APPLY_BLEEDING_REDUCE:
  4490. #endif
  4491. case APPLY_KILL_SP_RECOVER:
  4492. case APPLY_EXP_DOUBLE_BONUS:
  4493. case APPLY_GOLD_DOUBLE_BONUS:
  4494. case APPLY_ITEM_DROP_BONUS:
  4495. case APPLY_POTION_BONUS:
  4496. case APPLY_KILL_HP_RECOVER:
  4497. case APPLY_IMMUNE_STUN:
  4498. case APPLY_IMMUNE_SLOW:
  4499. case APPLY_IMMUNE_FALL:
  4500. case APPLY_BOW_DISTANCE:
  4501. case APPLY_ATT_GRADE_BONUS:
  4502. case APPLY_DEF_GRADE_BONUS:
  4503. case APPLY_MAGIC_ATT_GRADE:
  4504. case APPLY_MAGIC_DEF_GRADE:
  4505. case APPLY_CURSE_PCT:
  4506. case APPLY_MAX_STAMINA:
  4507. case APPLY_MALL_ATTBONUS:
  4508. case APPLY_MALL_DEFBONUS:
  4509. case APPLY_MALL_EXPBONUS:
  4510. case APPLY_MALL_ITEMBONUS:
  4511. case APPLY_MALL_GOLDBONUS:
  4512. case APPLY_SKILL_DAMAGE_BONUS:
  4513. case APPLY_NORMAL_HIT_DAMAGE_BONUS:
  4514.  
  4515. // DEPEND_BONUS_ATTRIBUTES
  4516. case APPLY_SKILL_DEFEND_BONUS:
  4517. case APPLY_NORMAL_HIT_DEFEND_BONUS:
  4518. // END_OF_DEPEND_BONUS_ATTRIBUTES
  4519.  
  4520. case APPLY_PC_BANG_EXP_BONUS :
  4521. case APPLY_PC_BANG_DROP_BONUS :
  4522.  
  4523. case APPLY_RESIST_WARRIOR :
  4524. case APPLY_RESIST_ASSASSIN :
  4525. case APPLY_RESIST_SURA :
  4526. case APPLY_RESIST_SHAMAN :
  4527. #ifdef ENABLE_WOLFMAN_CHARACTER
  4528. case APPLY_RESIST_WOLFMAN :
  4529. #endif
  4530. case APPLY_ENERGY: // 82 ±â·Â
  4531. case APPLY_DEF_GRADE: // 83 ¹æ¾î·Â. DEF_GRADE_BONUS´Â Ŭ¶ó¿¡¼­ µÎ¹è·Î º¸¿©Áö´Â ÀǵµµÈ ¹ö±×(...)°¡ ÀÖ´Ù.
  4532. case APPLY_COSTUME_ATTR_BONUS: // 84 ÄÚ½ºÆ¬ ¾ÆÀÌÅÛ¿¡ ºÙÀº ¼Ó¼ºÄ¡ º¸³Ê½º
  4533. case APPLY_MAGIC_ATTBONUS_PER: // 85 ¸¶¹ý °ø°Ý·Â +x%
  4534. case APPLY_MELEE_MAGIC_ATTBONUS_PER: // 86 ¸¶¹ý + ¹Ð¸® °ø°Ý·Â +x%
  4535. #ifdef ENABLE_ACCE_COSTUME_SYSTEM
  4536. case APPLY_ACCEDRAIN_RATE: //97
  4537. #endif
  4538. #ifdef ENABLE_MAGIC_REDUCTION_SYSTEM
  4539. case APPLY_RESIST_MAGIC_REDUCTION: //98
  4540. #endif
  4541. PointChange(aApplyInfo[bApplyType].bPointType, iVal);
  4542. break;
  4543.  
  4544. default:
  4545. sys_err("Unknown apply type %d name %s", bApplyType, GetName());
  4546. break;
  4547. }
  4548. }
  4549.  
  4550. void CHARACTER::MotionPacketEncode(BYTE motion, LPCHARACTER victim, struct packet_motion * packet)
  4551. {
  4552. packet->header = HEADER_GC_MOTION;
  4553. packet->vid = m_vid;
  4554. packet->motion = motion;
  4555.  
  4556. if (victim)
  4557. packet->victim_vid = victim->GetVID();
  4558. else
  4559. packet->victim_vid = 0;
  4560. }
  4561.  
  4562. void CHARACTER::Motion(BYTE motion, LPCHARACTER victim)
  4563. {
  4564. struct packet_motion pack_motion;
  4565. MotionPacketEncode(motion, victim, &pack_motion);
  4566. PacketAround(&pack_motion, sizeof(struct packet_motion));
  4567. }
  4568.  
  4569. EVENTFUNC(save_event)
  4570. {
  4571. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  4572. if ( info == NULL )
  4573. {
  4574. sys_err( "save_event> <Factor> Null pointer" );
  4575. return 0;
  4576. }
  4577.  
  4578. LPCHARACTER ch = info->ch;
  4579.  
  4580. if (ch == NULL) { // <Factor>
  4581. return 0;
  4582. }
  4583. sys_log(1, "SAVE_EVENT: %s", ch->GetName());
  4584. ch->Save();
  4585. ch->FlushDelayedSaveItem();
  4586. return (save_event_second_cycle);
  4587. }
  4588.  
  4589. void CHARACTER::StartSaveEvent()
  4590. {
  4591. if (m_pkSaveEvent)
  4592. return;
  4593.  
  4594. char_event_info* info = AllocEventInfo<char_event_info>();
  4595.  
  4596. info->ch = this;
  4597. m_pkSaveEvent = event_create(save_event, info, save_event_second_cycle);
  4598. }
  4599.  
  4600. void CHARACTER::MonsterLog(const char* format, ...)
  4601. {
  4602. if (!test_server)
  4603. return;
  4604.  
  4605. if (IsPC())
  4606. return;
  4607.  
  4608. char chatbuf[CHAT_MAX_LEN + 1];
  4609. int len = snprintf(chatbuf, sizeof(chatbuf), "%u)", (DWORD)GetVID());
  4610.  
  4611. if (len < 0 || len >= (int) sizeof(chatbuf))
  4612. len = sizeof(chatbuf) - 1;
  4613.  
  4614. va_list args;
  4615.  
  4616. va_start(args, format);
  4617.  
  4618. int len2 = vsnprintf(chatbuf + len, sizeof(chatbuf) - len, format, args);
  4619.  
  4620. if (len2 < 0 || len2 >= (int) sizeof(chatbuf) - len)
  4621. len += (sizeof(chatbuf) - len) - 1;
  4622. else
  4623. len += len2;
  4624.  
  4625. // \0 ¹®ÀÚ Æ÷ÇÔ
  4626. ++len;
  4627.  
  4628. va_end(args);
  4629.  
  4630. TPacketGCChat pack_chat;
  4631.  
  4632. pack_chat.header = HEADER_GC_CHAT;
  4633. pack_chat.size = sizeof(TPacketGCChat) + len;
  4634. pack_chat.type = CHAT_TYPE_TALKING;
  4635. pack_chat.id = (DWORD)GetVID();
  4636. pack_chat.bEmpire = 0;
  4637.  
  4638. TEMP_BUFFER buf;
  4639. buf.write(&pack_chat, sizeof(TPacketGCChat));
  4640. buf.write(chatbuf, len);
  4641.  
  4642. CHARACTER_MANAGER::instance().PacketMonsterLog(this, buf.read_peek(), buf.size());
  4643. }
  4644.  
  4645. void CHARACTER::ChatPacket(BYTE type, const char * format, ...)
  4646. {
  4647. LPDESC d = GetDesc();
  4648.  
  4649. if (!d || !format)
  4650. return;
  4651.  
  4652. char chatbuf[CHAT_MAX_LEN + 1];
  4653. va_list args;
  4654.  
  4655. va_start(args, format);
  4656. int len = vsnprintf(chatbuf, sizeof(chatbuf), format, args);
  4657. va_end(args);
  4658.  
  4659. struct packet_chat pack_chat;
  4660.  
  4661. pack_chat.header = HEADER_GC_CHAT;
  4662. pack_chat.size = sizeof(struct packet_chat) + len;
  4663. pack_chat.type = type;
  4664. pack_chat.id = 0;
  4665. pack_chat.bEmpire = d->GetEmpire();
  4666.  
  4667. TEMP_BUFFER buf;
  4668. buf.write(&pack_chat, sizeof(struct packet_chat));
  4669. buf.write(chatbuf, len);
  4670.  
  4671. d->Packet(buf.read_peek(), buf.size());
  4672.  
  4673. if (type == CHAT_TYPE_COMMAND && test_server)
  4674. sys_log(0, "SEND_COMMAND %s %s", GetName(), chatbuf);
  4675. }
  4676.  
  4677. // MINING
  4678. void CHARACTER::mining_take()
  4679. {
  4680. m_pkMiningEvent = NULL;
  4681. }
  4682.  
  4683. void CHARACTER::mining_cancel()
  4684. {
  4685. if (m_pkMiningEvent)
  4686. {
  4687. sys_log(0, "XXX MINING CANCEL");
  4688. event_cancel(&m_pkMiningEvent);
  4689. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("䱤À» Áß´ÜÇÏ¿´½À´Ï´Ù."));
  4690. }
  4691. }
  4692.  
  4693. void CHARACTER::mining(LPCHARACTER chLoad)
  4694. {
  4695. if (m_pkMiningEvent)
  4696. {
  4697. mining_cancel();
  4698. return;
  4699. }
  4700.  
  4701. if (!chLoad)
  4702. return;
  4703.  
  4704. // @fixme128
  4705. if (GetMapIndex() != chLoad->GetMapIndex() || DISTANCE_APPROX(GetX() - chLoad->GetX(), GetY() - chLoad->GetY()) > 1000)
  4706. return;
  4707.  
  4708. if (mining::GetRawOreFromLoad(chLoad->GetRaceNum()) == 0)
  4709. return;
  4710.  
  4711. LPITEM pick = GetWear(WEAR_WEAPON);
  4712.  
  4713. if (!pick || pick->GetType() != ITEM_PICK)
  4714. {
  4715. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°î±ªÀ̸¦ ÀåÂøÇϼ¼¿ä."));
  4716. return;
  4717. }
  4718.  
  4719. int count = number(5, 15); // µ¿ÀÛ È½¼ö, ÇÑ µ¿ÀÛ´ç 2ÃÊ
  4720.  
  4721. // 䱤 µ¿ÀÛÀ» º¸¿©ÁÜ
  4722. TPacketGCDigMotion p;
  4723. p.header = HEADER_GC_DIG_MOTION;
  4724. p.vid = GetVID();
  4725. p.target_vid = chLoad->GetVID();
  4726. p.count = count;
  4727.  
  4728. PacketAround(&p, sizeof(p));
  4729.  
  4730. m_pkMiningEvent = mining::CreateMiningEvent(this, chLoad, count);
  4731. }
  4732. // END_OF_MINING
  4733.  
  4734. void CHARACTER::fishing()
  4735. {
  4736. if (m_pkFishingEvent)
  4737. {
  4738. fishing_take();
  4739. return;
  4740. }
  4741.  
  4742. // ¸ø°¨ ¼Ó¼º¿¡¼­ ³¬½Ã¸¦ ½ÃµµÇÑ´Ù?
  4743. {
  4744. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(GetMapIndex());
  4745.  
  4746. int x = GetX();
  4747. int y = GetY();
  4748.  
  4749. LPSECTREE tree = pkSectreeMap->Find(x, y);
  4750. DWORD dwAttr = tree->GetAttribute(x, y);
  4751.  
  4752. if (IS_SET(dwAttr, ATTR_BLOCK))
  4753. {
  4754. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("³¬½Ã¸¦ ÇÒ ¼ö ÀÖ´Â °÷ÀÌ ¾Æ´Õ´Ï´Ù"));
  4755. return;
  4756. }
  4757. }
  4758.  
  4759. LPITEM rod = GetWear(WEAR_WEAPON);
  4760.  
  4761. // ³¬½Ã´ë ÀåÂø
  4762. if (!rod || rod->GetType() != ITEM_ROD)
  4763. {
  4764. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("³¬½Ã´ë¸¦ ÀåÂø Çϼ¼¿ä."));
  4765. return;
  4766. }
  4767.  
  4768. if (0 == rod->GetSocket(2))
  4769. {
  4770. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¹Ì³¢¸¦ ³¢°í ´øÁ® ÁÖ¼¼¿ä."));
  4771. return;
  4772. }
  4773.  
  4774. float fx, fy;
  4775. GetDeltaByDegree(GetRotation(), 400.0f, &fx, &fy);
  4776.  
  4777. m_pkFishingEvent = fishing::CreateFishingEvent(this);
  4778. }
  4779.  
  4780. void CHARACTER::fishing_take()
  4781. {
  4782. LPITEM rod = GetWear(WEAR_WEAPON);
  4783. if (rod && rod->GetType() == ITEM_ROD)
  4784. {
  4785. using fishing::fishing_event_info;
  4786. if (m_pkFishingEvent)
  4787. {
  4788. struct fishing_event_info* info = dynamic_cast<struct fishing_event_info*>(m_pkFishingEvent->info);
  4789.  
  4790. if (info)
  4791. fishing::Take(info, this);
  4792. }
  4793. }
  4794. else
  4795. {
  4796. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("³¬½Ã´ë°¡ ¾Æ´Ñ ¹°°ÇÀ¸·Î ³¬½Ã¸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù!"));
  4797. }
  4798.  
  4799. event_cancel(&m_pkFishingEvent);
  4800. }
  4801.  
  4802. bool CHARACTER::StartStateMachine(int iNextPulse)
  4803. {
  4804. if (CHARACTER_MANAGER::instance().AddToStateList(this))
  4805. {
  4806. m_dwNextStatePulse = thecore_heart->pulse + iNextPulse;
  4807. return true;
  4808. }
  4809.  
  4810. return false;
  4811. }
  4812.  
  4813. void CHARACTER::StopStateMachine()
  4814. {
  4815. CHARACTER_MANAGER::instance().RemoveFromStateList(this);
  4816. }
  4817.  
  4818. void CHARACTER::UpdateStateMachine(DWORD dwPulse)
  4819. {
  4820. if (dwPulse < m_dwNextStatePulse)
  4821. return;
  4822.  
  4823. if (IsDead())
  4824. return;
  4825.  
  4826. Update();
  4827. m_dwNextStatePulse = dwPulse + m_dwStateDuration;
  4828. }
  4829.  
  4830. void CHARACTER::SetNextStatePulse(int iNextPulse)
  4831. {
  4832. CHARACTER_MANAGER::instance().AddToStateList(this);
  4833. m_dwNextStatePulse = iNextPulse;
  4834.  
  4835. if (iNextPulse < 10)
  4836. MonsterLog("´ÙÀ½»óÅ·ξ°¡ÀÚ");
  4837. }
  4838.  
  4839.  
  4840. // ij¸¯ÅÍ ÀνºÅϽº ¾÷µ¥ÀÌÆ® ÇÔ¼ö.
  4841. void CHARACTER::UpdateCharacter(DWORD dwPulse)
  4842. {
  4843. CFSM::Update();
  4844. }
  4845.  
  4846. void CHARACTER::SetShop(LPSHOP pkShop)
  4847. {
  4848. if ((m_pkShop = pkShop))
  4849. SET_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_SHOP);
  4850. else
  4851. {
  4852. REMOVE_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_SHOP);
  4853. SetShopOwner(NULL);
  4854. }
  4855. }
  4856.  
  4857. void CHARACTER::SetExchange(CExchange * pkExchange)
  4858. {
  4859. m_pkExchange = pkExchange;
  4860. }
  4861.  
  4862. void CHARACTER::SetPart(BYTE bPartPos, WORD wVal)
  4863. {
  4864. assert(bPartPos < PART_MAX_NUM);
  4865. m_pointsInstant.parts[bPartPos] = wVal;
  4866. }
  4867.  
  4868. WORD CHARACTER::GetPart(BYTE bPartPos) const
  4869. {
  4870. assert(bPartPos < PART_MAX_NUM);
  4871. return m_pointsInstant.parts[bPartPos];
  4872. }
  4873.  
  4874. WORD CHARACTER::GetOriginalPart(BYTE bPartPos) const
  4875. {
  4876. switch (bPartPos)
  4877. {
  4878. case PART_MAIN:
  4879. if (!IsPC()) // PC°¡ ¾Æ´Ñ °æ¿ì ÇöÀç ÆÄÆ®¸¦ ±×´ë·Î ¸®ÅÏ
  4880. return GetPart(PART_MAIN);
  4881. else
  4882. return m_pointsInstant.bBasePart;
  4883.  
  4884. case PART_HAIR:
  4885. return GetPart(PART_HAIR);
  4886. #ifdef __SASH_SYSTEM__
  4887. case PART_SASH:
  4888. return GetPart(PART_SASH);
  4889. #endif
  4890. #ifdef __WEAPON_COSTUME_SYSTEM__
  4891. case PART_WEAPON:
  4892. return GetPart(PART_WEAPON);
  4893. #endif
  4894. default:
  4895. return 0;
  4896. }
  4897. }
  4898.  
  4899. BYTE CHARACTER::GetCharType() const
  4900. {
  4901. return m_bCharType;
  4902. }
  4903.  
  4904. bool CHARACTER::SetSyncOwner(LPCHARACTER ch, bool bRemoveFromList)
  4905. {
  4906. // TRENT_MONSTER
  4907. if (IS_SET(m_pointsInstant.dwAIFlag, AIFLAG_NOMOVE))
  4908. return false;
  4909. // END_OF_TRENT_MONSTER
  4910.  
  4911. if (ch) // @fixme131
  4912. {
  4913. if (!battle_is_attackable(ch, this))
  4914. {
  4915. SendDamagePacket(ch, 0, DAMAGE_BLOCK);
  4916. return false;
  4917. }
  4918. }
  4919.  
  4920. if (ch == this)
  4921. {
  4922. sys_err("SetSyncOwner owner == this (%p)", this);
  4923. return false;
  4924. }
  4925.  
  4926. if (!ch)
  4927. {
  4928. if (bRemoveFromList && m_pkChrSyncOwner)
  4929. {
  4930. m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.remove(this);
  4931. }
  4932.  
  4933. if (m_pkChrSyncOwner)
  4934. sys_log(1, "SyncRelease %s %p from %s", GetName(), this, m_pkChrSyncOwner->GetName());
  4935.  
  4936. // ¸®½ºÆ®¿¡¼­ Á¦°ÅÇÏÁö ¾Ê´õ¶óµµ Æ÷ÀÎÅÍ´Â NULL·Î ¼ÂÆÃµÇ¾î¾ß ÇÑ´Ù.
  4937. m_pkChrSyncOwner = NULL;
  4938. }
  4939. else
  4940. {
  4941. if (!IsSyncOwner(ch))
  4942. return false;
  4943.  
  4944. // °Å¸®°¡ 200 ÀÌ»óÀ̸é SyncOwner°¡ µÉ ¼ö ¾ø´Ù.
  4945. if (DISTANCE_APPROX(GetX() - ch->GetX(), GetY() - ch->GetY()) > 250)
  4946. {
  4947. sys_log(1, "SetSyncOwner distance over than 250 %s %s", GetName(), ch->GetName());
  4948.  
  4949. // SyncOwnerÀÏ °æ¿ì Owner·Î Ç¥½ÃÇÑ´Ù.
  4950. if (m_pkChrSyncOwner == ch)
  4951. return true;
  4952.  
  4953. return false;
  4954. }
  4955.  
  4956. if (m_pkChrSyncOwner != ch)
  4957. {
  4958. if (m_pkChrSyncOwner)
  4959. {
  4960. sys_log(1, "SyncRelease %s %p from %s", GetName(), this, m_pkChrSyncOwner->GetName());
  4961. m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.remove(this);
  4962. }
  4963.  
  4964. m_pkChrSyncOwner = ch;
  4965. m_pkChrSyncOwner->m_kLst_pkChrSyncOwned.push_back(this);
  4966.  
  4967. // SyncOwner°¡ ¹Ù²î¸é LastSyncTimeÀ» ÃʱâÈ­ÇÑ´Ù.
  4968. static const timeval zero_tv = {0, 0};
  4969. SetLastSyncTime(zero_tv);
  4970.  
  4971. sys_log(1, "SetSyncOwner set %s %p to %s", GetName(), this, ch->GetName());
  4972. }
  4973.  
  4974. m_fSyncTime = get_float_time();
  4975. }
  4976.  
  4977. // TODO: Sync Owner°¡ °°´õ¶óµµ °è¼Ó ÆÐŶÀ» º¸³»°í ÀÖÀ¸¹Ç·Î,
  4978. // µ¿±âÈ­ µÈ ½Ã°£ÀÌ 3ÃÊ ÀÌ»ó Áö³µÀ» ¶§ Ç®¾îÁÖ´Â ÆÐŶÀ»
  4979. // º¸³»´Â ¹æ½ÄÀ¸·Î ÇÏ¸é ÆÐŶÀ» ÁÙÀÏ ¼ö ÀÖ´Ù.
  4980. TPacketGCOwnership pack;
  4981.  
  4982. pack.bHeader = HEADER_GC_OWNERSHIP;
  4983. pack.dwOwnerVID = ch ? ch->GetVID() : 0;
  4984. pack.dwVictimVID = GetVID();
  4985.  
  4986. PacketAround(&pack, sizeof(TPacketGCOwnership));
  4987. return true;
  4988. }
  4989.  
  4990. struct FuncClearSync
  4991. {
  4992. void operator () (LPCHARACTER ch)
  4993. {
  4994. assert(ch != NULL);
  4995. ch->SetSyncOwner(NULL, false); // false Ç÷¡±×·Î ÇØ¾ß for_each °¡ Á¦´ë·Î µ·´Ù.
  4996. }
  4997. };
  4998.  
  4999. void CHARACTER::ClearSync()
  5000. {
  5001. SetSyncOwner(NULL);
  5002.  
  5003. // ¾Æ·¡ for_each¿¡¼­ ³ª¸¦ m_pkChrSyncOwner·Î °¡Áø ÀÚµéÀÇ Æ÷ÀÎÅ͸¦ NULL·Î ÇÑ´Ù.
  5004. std::for_each(m_kLst_pkChrSyncOwned.begin(), m_kLst_pkChrSyncOwned.end(), FuncClearSync());
  5005. m_kLst_pkChrSyncOwned.clear();
  5006. }
  5007.  
  5008. bool CHARACTER::IsSyncOwner(LPCHARACTER ch) const
  5009. {
  5010. if (m_pkChrSyncOwner == ch)
  5011. return true;
  5012.  
  5013. // ¸¶Áö¸·À¸·Î µ¿±âÈ­ µÈ ½Ã°£ÀÌ 3ÃÊ ÀÌ»ó Áö³µ´Ù¸é ¼ÒÀ¯±ÇÀÌ ¾Æ¹«¿¡°Ôµµ
  5014. // ¾ø´Ù. µû¶ó¼­ ¾Æ¹«³ª SyncOwnerÀ̹ǷΠtrue ¸®ÅÏ
  5015. if (get_float_time() - m_fSyncTime >= 3.0f)
  5016. return true;
  5017.  
  5018. return false;
  5019. }
  5020.  
  5021. void CHARACTER::SetParty(LPPARTY pkParty)
  5022. {
  5023. if (pkParty == m_pkParty)
  5024. return;
  5025.  
  5026. if (pkParty && m_pkParty)
  5027. sys_err("%s is trying to reassigning party (current %p, new party %p)", GetName(), get_pointer(m_pkParty), get_pointer(pkParty));
  5028.  
  5029. sys_log(1, "PARTY set to %p", get_pointer(pkParty));
  5030.  
  5031. if (m_pkDungeon && IsPC() && !pkParty)
  5032. SetDungeon(NULL);
  5033. m_pkParty = pkParty;
  5034.  
  5035. if (IsPC())
  5036. {
  5037. if (m_pkParty)
  5038. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_PARTY);
  5039. else
  5040. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_PARTY);
  5041.  
  5042. UpdatePacket();
  5043. }
  5044. }
  5045.  
  5046. // PARTY_JOIN_BUG_FIX
  5047. /// ÆÄƼ °¡ÀÔ event Á¤º¸
  5048. EVENTINFO(TPartyJoinEventInfo)
  5049. {
  5050. DWORD dwGuestPID; ///< ÆÄƼ¿¡ Âü¿©ÇÒ Ä³¸¯ÅÍÀÇ PID
  5051. DWORD dwLeaderPID; ///< ÆÄƼ ¸®´õÀÇ PID
  5052.  
  5053. TPartyJoinEventInfo()
  5054. : dwGuestPID( 0 )
  5055. , dwLeaderPID( 0 )
  5056. {
  5057. }
  5058. } ;
  5059.  
  5060. EVENTFUNC(party_request_event)
  5061. {
  5062. TPartyJoinEventInfo * info = dynamic_cast<TPartyJoinEventInfo *>( event->info );
  5063.  
  5064. if ( info == NULL )
  5065. {
  5066. sys_err( "party_request_event> <Factor> Null pointer" );
  5067. return 0;
  5068. }
  5069.  
  5070. LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(info->dwGuestPID);
  5071.  
  5072. if (ch)
  5073. {
  5074. sys_log(0, "PartyRequestEvent %s", ch->GetName());
  5075. ch->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequestDenied");
  5076. ch->SetPartyRequestEvent(NULL);
  5077. }
  5078.  
  5079. return 0;
  5080. }
  5081.  
  5082. bool CHARACTER::RequestToParty(LPCHARACTER leader)
  5083. {
  5084. if (leader->GetParty())
  5085. leader = leader->GetParty()->GetLeaderCharacter();
  5086.  
  5087. if (!leader)
  5088. {
  5089. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÆÄƼÀåÀÌ Á¢¼Ó »óŰ¡ ¾Æ´Ï¶ó¼­ ¿äûÀ» ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5090. return false;
  5091. }
  5092.  
  5093. if (m_pkPartyRequestEvent)
  5094. return false;
  5095.  
  5096. if (!IsPC() || !leader->IsPC())
  5097. return false;
  5098.  
  5099. if (leader->IsBlockMode(BLOCK_PARTY_REQUEST))
  5100. return false;
  5101.  
  5102. PartyJoinErrCode errcode = IsPartyJoinableCondition(leader, this);
  5103.  
  5104. switch (errcode)
  5105. {
  5106. case PERR_NONE:
  5107. break;
  5108.  
  5109. case PERR_SERVER:
  5110. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5111. return false;
  5112.  
  5113. case PERR_DIFFEMPIRE:
  5114. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´Ù¸¥ Á¦±¹°ú ÆÄƼ¸¦ ÀÌ·ê ¼ö ¾ø½À´Ï´Ù."));
  5115. return false;
  5116.  
  5117. case PERR_DUNGEON:
  5118. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÀü ¾È¿¡¼­´Â ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5119. return false;
  5120.  
  5121. case PERR_OBSERVER:
  5122. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> °üÀü ¸ðµå¿¡¼± ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5123. return false;
  5124.  
  5125. case PERR_LVBOUNDARY:
  5126. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> -30 ~ +30 ·¹º§ À̳»ÀÇ »ó´ë¹æ¸¸ ÃÊ´ëÇÒ ¼ö ÀÖ½À´Ï´Ù."));
  5127. return false;
  5128.  
  5129. case PERR_LOWLEVEL:
  5130. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖ°í ·¹º§ º¸´Ù 30·¹º§ÀÌ ³·¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5131. return false;
  5132.  
  5133. case PERR_HILEVEL:
  5134. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖÀú ·¹º§ º¸´Ù 30·¹º§ÀÌ ³ô¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5135. return false;
  5136.  
  5137. case PERR_ALREADYJOIN:
  5138. return false;
  5139.  
  5140. case PERR_PARTYISFULL:
  5141. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´õ ÀÌ»ó ÆÄƼ¿øÀ» ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5142. return false;
  5143.  
  5144. default:
  5145. sys_err("Do not process party join error(%d)", errcode);
  5146. return false;
  5147. }
  5148.  
  5149. TPartyJoinEventInfo* info = AllocEventInfo<TPartyJoinEventInfo>();
  5150.  
  5151. info->dwGuestPID = GetPlayerID();
  5152. info->dwLeaderPID = leader->GetPlayerID();
  5153.  
  5154. SetPartyRequestEvent(event_create(party_request_event, info, PASSES_PER_SEC(10)));
  5155.  
  5156. leader->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequest %u", (DWORD) GetVID());
  5157. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s ´Ô¿¡°Ô ÆÄƼ°¡ÀÔ ½ÅûÀ» Çß½À´Ï´Ù."), leader->GetName());
  5158. return true;
  5159. }
  5160.  
  5161. void CHARACTER::DenyToParty(LPCHARACTER member)
  5162. {
  5163. sys_log(1, "DenyToParty %s member %s %p", GetName(), member->GetName(), get_pointer(member->m_pkPartyRequestEvent));
  5164.  
  5165. if (!member->m_pkPartyRequestEvent)
  5166. return;
  5167.  
  5168. TPartyJoinEventInfo * info = dynamic_cast<TPartyJoinEventInfo *>(member->m_pkPartyRequestEvent->info);
  5169.  
  5170. if (!info)
  5171. {
  5172. sys_err( "CHARACTER::DenyToParty> <Factor> Null pointer" );
  5173. return;
  5174. }
  5175.  
  5176. if (info->dwGuestPID != member->GetPlayerID())
  5177. return;
  5178.  
  5179. if (info->dwLeaderPID != GetPlayerID())
  5180. return;
  5181.  
  5182. event_cancel(&member->m_pkPartyRequestEvent);
  5183.  
  5184. member->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequestDenied");
  5185. }
  5186.  
  5187. void CHARACTER::AcceptToParty(LPCHARACTER member)
  5188. {
  5189. sys_log(1, "AcceptToParty %s member %s %p", GetName(), member->GetName(), get_pointer(member->m_pkPartyRequestEvent));
  5190.  
  5191. if (!member->m_pkPartyRequestEvent)
  5192. return;
  5193.  
  5194. TPartyJoinEventInfo * info = dynamic_cast<TPartyJoinEventInfo *>(member->m_pkPartyRequestEvent->info);
  5195.  
  5196. if (!info)
  5197. {
  5198. sys_err( "CHARACTER::AcceptToParty> <Factor> Null pointer" );
  5199. return;
  5200. }
  5201.  
  5202. if (info->dwGuestPID != member->GetPlayerID())
  5203. return;
  5204.  
  5205. if (info->dwLeaderPID != GetPlayerID())
  5206. return;
  5207.  
  5208. event_cancel(&member->m_pkPartyRequestEvent);
  5209.  
  5210. if (!GetParty())
  5211. member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ÆÄƼ¿¡ ¼ÓÇØÀÖÁö ¾Ê½À´Ï´Ù."));
  5212. else
  5213. {
  5214. if (GetPlayerID() != GetParty()->GetLeaderPID())
  5215. return;
  5216.  
  5217. PartyJoinErrCode errcode = IsPartyJoinableCondition(this, member);
  5218. switch (errcode)
  5219. {
  5220. case PERR_NONE: member->PartyJoin(this); return;
  5221. case PERR_SERVER: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù.")); break;
  5222. case PERR_DUNGEON: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÀü ¾È¿¡¼­´Â ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù.")); break;
  5223. case PERR_OBSERVER: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> °üÀü ¸ðµå¿¡¼± ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù.")); break;
  5224. case PERR_LVBOUNDARY: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> -30 ~ +30 ·¹º§ À̳»ÀÇ »ó´ë¹æ¸¸ ÃÊ´ëÇÒ ¼ö ÀÖ½À´Ï´Ù.")); break;
  5225. case PERR_LOWLEVEL: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖ°í ·¹º§ º¸´Ù 30·¹º§ÀÌ ³·¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù.")); break;
  5226. case PERR_HILEVEL: member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖÀú ·¹º§ º¸´Ù 30·¹º§ÀÌ ³ô¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù.")); break;
  5227. case PERR_ALREADYJOIN: break;
  5228. case PERR_PARTYISFULL: {
  5229. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´õ ÀÌ»ó ÆÄƼ¿øÀ» ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5230. member->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼÀÇ ÀοøÁ¦ÇÑÀÌ ÃʰúÇÏ¿© ÆÄƼ¿¡ Âü°¡ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5231. break;
  5232. }
  5233. default: sys_err("Do not process party join error(%d)", errcode);
  5234. }
  5235. }
  5236.  
  5237. member->ChatPacket(CHAT_TYPE_COMMAND, "PartyRequestDenied");
  5238. }
  5239.  
  5240. /**
  5241. * ÆÄƼ ÃÊ´ë event callback ÇÔ¼ö.
  5242. * event °¡ ¹ßµ¿Çϸé ÃÊ´ë °ÅÀý·Î ó¸®ÇÑ´Ù.
  5243. */
  5244. EVENTFUNC(party_invite_event)
  5245. {
  5246. TPartyJoinEventInfo * pInfo = dynamic_cast<TPartyJoinEventInfo *>( event->info );
  5247.  
  5248. if ( pInfo == NULL )
  5249. {
  5250. sys_err( "party_invite_event> <Factor> Null pointer" );
  5251. return 0;
  5252. }
  5253.  
  5254. LPCHARACTER pchInviter = CHARACTER_MANAGER::instance().FindByPID(pInfo->dwLeaderPID);
  5255.  
  5256. if (pchInviter)
  5257. {
  5258. sys_log(1, "PartyInviteEvent %s", pchInviter->GetName());
  5259. pchInviter->PartyInviteDeny(pInfo->dwGuestPID);
  5260. }
  5261.  
  5262. return 0;
  5263. }
  5264.  
  5265. void CHARACTER::PartyInvite(LPCHARACTER pchInvitee)
  5266. {
  5267. if (GetParty() && GetParty()->GetLeaderPID() != GetPlayerID())
  5268. {
  5269. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ¿øÀ» ÃÊ´ëÇÒ ¼ö ÀÖ´Â ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  5270. return;
  5271. }
  5272. else if (pchInvitee->IsBlockMode(BLOCK_PARTY_INVITE))
  5273. {
  5274. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> %s ´ÔÀÌ ÆÄƼ °ÅºÎ »óÅÂÀÔ´Ï´Ù."), pchInvitee->GetName());
  5275. return;
  5276. }
  5277.  
  5278. PartyJoinErrCode errcode = IsPartyJoinableCondition(this, pchInvitee);
  5279.  
  5280. switch (errcode)
  5281. {
  5282. case PERR_NONE:
  5283. break;
  5284.  
  5285. case PERR_SERVER:
  5286. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5287. return;
  5288.  
  5289. case PERR_DIFFEMPIRE:
  5290. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´Ù¸¥ Á¦±¹°ú ÆÄƼ¸¦ ÀÌ·ê ¼ö ¾ø½À´Ï´Ù."));
  5291. return;
  5292.  
  5293. case PERR_DUNGEON:
  5294. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÀü ¾È¿¡¼­´Â ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5295. return;
  5296.  
  5297. case PERR_OBSERVER:
  5298. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> °üÀü ¸ðµå¿¡¼± ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5299. return;
  5300.  
  5301. case PERR_LVBOUNDARY:
  5302. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> -30 ~ +30 ·¹º§ À̳»ÀÇ »ó´ë¹æ¸¸ ÃÊ´ëÇÒ ¼ö ÀÖ½À´Ï´Ù."));
  5303. return;
  5304.  
  5305. case PERR_LOWLEVEL:
  5306. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖ°í ·¹º§ º¸´Ù 30·¹º§ÀÌ ³·¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5307. return;
  5308.  
  5309. case PERR_HILEVEL:
  5310. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖÀú ·¹º§ º¸´Ù 30·¹º§ÀÌ ³ô¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5311. return;
  5312.  
  5313. case PERR_ALREADYJOIN:
  5314. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÀÌ¹Ì %s´ÔÀº ÆÄƼ¿¡ ¼ÓÇØ ÀÖ½À´Ï´Ù."), pchInvitee->GetName());
  5315. return;
  5316.  
  5317. case PERR_PARTYISFULL:
  5318. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´õ ÀÌ»ó ÆÄƼ¿øÀ» ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5319. return;
  5320.  
  5321. default:
  5322. sys_err("Do not process party join error(%d)", errcode);
  5323. return;
  5324. }
  5325.  
  5326. if (m_PartyInviteEventMap.end() != m_PartyInviteEventMap.find(pchInvitee->GetPlayerID()))
  5327. return;
  5328.  
  5329. //
  5330. // EventMap ¿¡ À̺¥Æ® Ãß°¡
  5331. //
  5332. TPartyJoinEventInfo* info = AllocEventInfo<TPartyJoinEventInfo>();
  5333.  
  5334. info->dwGuestPID = pchInvitee->GetPlayerID();
  5335. info->dwLeaderPID = GetPlayerID();
  5336.  
  5337. m_PartyInviteEventMap.insert(EventMap::value_type(pchInvitee->GetPlayerID(), event_create(party_invite_event, info, PASSES_PER_SEC(10))));
  5338.  
  5339. //
  5340. // ÃÊ´ë ¹Þ´Â character ¿¡°Ô ÃÊ´ë ÆÐŶ Àü¼Û
  5341. //
  5342.  
  5343. TPacketGCPartyInvite p;
  5344. p.header = HEADER_GC_PARTY_INVITE;
  5345. p.leader_vid = GetVID();
  5346. pchInvitee->GetDesc()->Packet(&p, sizeof(p));
  5347. }
  5348.  
  5349. void CHARACTER::PartyInviteAccept(LPCHARACTER pchInvitee)
  5350. {
  5351. EventMap::iterator itFind = m_PartyInviteEventMap.find(pchInvitee->GetPlayerID());
  5352.  
  5353. if (itFind == m_PartyInviteEventMap.end())
  5354. {
  5355. sys_log(1, "PartyInviteAccept from not invited character(%s)", pchInvitee->GetName());
  5356. return;
  5357. }
  5358.  
  5359. event_cancel(&itFind->second);
  5360. m_PartyInviteEventMap.erase(itFind);
  5361.  
  5362. if (GetParty() && GetParty()->GetLeaderPID() != GetPlayerID())
  5363. {
  5364. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ¿øÀ» ÃÊ´ëÇÒ ¼ö ÀÖ´Â ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  5365. return;
  5366. }
  5367.  
  5368. PartyJoinErrCode errcode = IsPartyJoinableMutableCondition(this, pchInvitee);
  5369.  
  5370. switch (errcode)
  5371. {
  5372. case PERR_NONE:
  5373. break;
  5374.  
  5375. case PERR_SERVER:
  5376. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5377. return;
  5378.  
  5379. case PERR_DUNGEON:
  5380. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÀü ¾È¿¡¼­´Â ÆÄƼ ÃÊ´ë¿¡ ÀÀÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5381. return;
  5382.  
  5383. case PERR_OBSERVER:
  5384. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> °üÀü ¸ðµå¿¡¼± ÆÄƼ Ãʴ븦 ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5385. return;
  5386.  
  5387. case PERR_LVBOUNDARY:
  5388. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> -30 ~ +30 ·¹º§ À̳»ÀÇ »ó´ë¹æ¸¸ ÃÊ´ëÇÒ ¼ö ÀÖ½À´Ï´Ù."));
  5389. return;
  5390.  
  5391. case PERR_LOWLEVEL:
  5392. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖ°í ·¹º§ º¸´Ù 30·¹º§ÀÌ ³·¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5393. return;
  5394.  
  5395. case PERR_HILEVEL:
  5396. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ³» ÃÖÀú ·¹º§ º¸´Ù 30·¹º§ÀÌ ³ô¾Æ ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5397. return;
  5398.  
  5399. case PERR_ALREADYJOIN:
  5400. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ ÃÊ´ë¿¡ ÀÀÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5401. return;
  5402.  
  5403. case PERR_PARTYISFULL:
  5404. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´õ ÀÌ»ó ÆÄƼ¿øÀ» ÃÊ´ëÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5405. pchInvitee->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼÀÇ ÀοøÁ¦ÇÑÀÌ ÃʰúÇÏ¿© ÆÄƼ¿¡ Âü°¡ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  5406. return;
  5407.  
  5408. default:
  5409. sys_err("ignore party join error(%d)", errcode);
  5410. return;
  5411. }
  5412.  
  5413. //
  5414. // ÆÄƼ °¡ÀÔ Ã³¸®
  5415. //
  5416.  
  5417. if (GetParty())
  5418. pchInvitee->PartyJoin(this);
  5419. else
  5420. {
  5421. LPPARTY pParty = CPartyManager::instance().CreateParty(this);
  5422.  
  5423. pParty->Join(pchInvitee->GetPlayerID());
  5424. pParty->Link(pchInvitee);
  5425. pParty->SendPartyInfoAllToOne(this);
  5426. }
  5427. }
  5428.  
  5429. void CHARACTER::PartyInviteDeny(DWORD dwPID)
  5430. {
  5431. EventMap::iterator itFind = m_PartyInviteEventMap.find(dwPID);
  5432.  
  5433. if (itFind == m_PartyInviteEventMap.end())
  5434. {
  5435. sys_log(1, "PartyInviteDeny to not exist event(inviter PID: %d, invitee PID: %d)", GetPlayerID(), dwPID);
  5436. return;
  5437. }
  5438.  
  5439. event_cancel(&itFind->second);
  5440. m_PartyInviteEventMap.erase(itFind);
  5441.  
  5442. LPCHARACTER pchInvitee = CHARACTER_MANAGER::instance().FindByPID(dwPID);
  5443. if (pchInvitee)
  5444. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> %s´ÔÀÌ ÆÄƼ Ãʴ븦 °ÅÀýÇϼ̽À´Ï´Ù."), pchInvitee->GetName());
  5445. }
  5446.  
  5447. void CHARACTER::PartyJoin(LPCHARACTER pLeader)
  5448. {
  5449. pLeader->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> %s´ÔÀÌ ÆÄƼ¿¡ Âü°¡Çϼ̽À´Ï´Ù."), GetName());
  5450. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> %s´ÔÀÇ ÆÄƼ¿¡ Âü°¡Çϼ̽À´Ï´Ù."), pLeader->GetName());
  5451.  
  5452. pLeader->GetParty()->Join(GetPlayerID());
  5453. pLeader->GetParty()->Link(this);
  5454. }
  5455.  
  5456. CHARACTER::PartyJoinErrCode CHARACTER::IsPartyJoinableCondition(const LPCHARACTER pchLeader, const LPCHARACTER pchGuest)
  5457. {
  5458. if (pchLeader->GetEmpire() != pchGuest->GetEmpire())
  5459. return PERR_DIFFEMPIRE;
  5460.  
  5461. return IsPartyJoinableMutableCondition(pchLeader, pchGuest);
  5462. }
  5463.  
  5464. static bool __party_can_join_by_level(LPCHARACTER leader, LPCHARACTER quest)
  5465. {
  5466. int level_limit = 30;
  5467. return (abs(leader->GetLevel() - quest->GetLevel()) <= level_limit);
  5468. }
  5469.  
  5470. CHARACTER::PartyJoinErrCode CHARACTER::IsPartyJoinableMutableCondition(const LPCHARACTER pchLeader, const LPCHARACTER pchGuest)
  5471. {
  5472. if (!CPartyManager::instance().IsEnablePCParty())
  5473. return PERR_SERVER;
  5474. else if (pchLeader->GetDungeon())
  5475. return PERR_DUNGEON;
  5476. else if (pchGuest->IsObserverMode())
  5477. return PERR_OBSERVER;
  5478. else if (false == __party_can_join_by_level(pchLeader, pchGuest))
  5479. return PERR_LVBOUNDARY;
  5480. else if (pchGuest->GetParty())
  5481. return PERR_ALREADYJOIN;
  5482. else if (pchLeader->GetParty())
  5483. {
  5484. if (pchLeader->GetParty()->GetMemberCount() == PARTY_MAX_MEMBER)
  5485. return PERR_PARTYISFULL;
  5486. }
  5487.  
  5488. return PERR_NONE;
  5489. }
  5490. // END_OF_PARTY_JOIN_BUG_FIX
  5491.  
  5492. void CHARACTER::SetDungeon(LPDUNGEON pkDungeon)
  5493. {
  5494. if (pkDungeon && m_pkDungeon)
  5495. sys_err("%s is trying to reassigning dungeon (current %p, new party %p)", GetName(), get_pointer(m_pkDungeon), get_pointer(pkDungeon));
  5496.  
  5497. if (m_pkDungeon == pkDungeon) {
  5498. return;
  5499. }
  5500.  
  5501. if (m_pkDungeon)
  5502. {
  5503. if (IsPC())
  5504. {
  5505. if (GetParty())
  5506. m_pkDungeon->DecPartyMember(GetParty(), this);
  5507. else
  5508. m_pkDungeon->DecMember(this);
  5509. }
  5510. else if (IsMonster() || IsStone())
  5511. {
  5512. m_pkDungeon->DecMonster();
  5513. }
  5514. }
  5515.  
  5516. m_pkDungeon = pkDungeon;
  5517.  
  5518. if (pkDungeon)
  5519. {
  5520. sys_log(0, "%s DUNGEON set to %p, PARTY is %p", GetName(), get_pointer(pkDungeon), get_pointer(m_pkParty));
  5521.  
  5522. if (IsPC())
  5523. {
  5524. if (GetParty())
  5525. m_pkDungeon->IncPartyMember(GetParty(), this);
  5526. else
  5527. m_pkDungeon->IncMember(this);
  5528. }
  5529. else if (IsMonster() || IsStone())
  5530. {
  5531. m_pkDungeon->IncMonster();
  5532. }
  5533. }
  5534. }
  5535.  
  5536. void CHARACTER::SetWarMap(CWarMap * pWarMap)
  5537. {
  5538. if (m_pWarMap)
  5539. m_pWarMap->DecMember(this);
  5540.  
  5541. m_pWarMap = pWarMap;
  5542.  
  5543. if (m_pWarMap)
  5544. m_pWarMap->IncMember(this);
  5545. }
  5546.  
  5547. void CHARACTER::SetWeddingMap(marriage::WeddingMap* pMap)
  5548. {
  5549. if (m_pWeddingMap)
  5550. m_pWeddingMap->DecMember(this);
  5551.  
  5552. m_pWeddingMap = pMap;
  5553.  
  5554. if (m_pWeddingMap)
  5555. m_pWeddingMap->IncMember(this);
  5556. }
  5557.  
  5558. void CHARACTER::SetRegen(LPREGEN pkRegen)
  5559. {
  5560. m_pkRegen = pkRegen;
  5561. if (pkRegen != NULL) {
  5562. regen_id_ = pkRegen->id;
  5563. }
  5564. m_fRegenAngle = GetRotation();
  5565. m_posRegen = GetXYZ();
  5566. }
  5567.  
  5568. bool CHARACTER::OnIdle()
  5569. {
  5570. return false;
  5571. }
  5572.  
  5573. void CHARACTER::OnMove(bool bIsAttack)
  5574. {
  5575. m_dwLastMoveTime = get_dword_time();
  5576.  
  5577. if (bIsAttack)
  5578. {
  5579. m_dwLastAttackTime = m_dwLastMoveTime;
  5580.  
  5581. if (IsAffectFlag(AFF_REVIVE_INVISIBLE))
  5582. RemoveAffect(AFFECT_REVIVE_INVISIBLE);
  5583.  
  5584. if (IsAffectFlag(AFF_EUNHYUNG))
  5585. {
  5586. RemoveAffect(SKILL_EUNHYUNG);
  5587. SetAffectedEunhyung();
  5588. }
  5589. else
  5590. {
  5591. ClearAffectedEunhyung();
  5592. }
  5593.  
  5594. /*if (IsAffectFlag(AFF_JEONSIN))
  5595. RemoveAffect(SKILL_JEONSINBANGEO);*/
  5596. }
  5597.  
  5598. /*if (IsAffectFlag(AFF_GUNGON))
  5599. RemoveAffect(SKILL_GUNGON);*/
  5600.  
  5601. // MINING
  5602. mining_cancel();
  5603. // END_OF_MINING
  5604. }
  5605.  
  5606. void CHARACTER::OnClick(LPCHARACTER pkChrCauser)
  5607. {
  5608. if (!pkChrCauser)
  5609. {
  5610. sys_err("OnClick %s by NULL", GetName());
  5611. return;
  5612. }
  5613.  
  5614. DWORD vid = GetVID();
  5615. //if (test_server)
  5616. sys_log(0, "OnClick %s[vnum %d ServerUniqueID %d, pid %d] by %s", GetName(), GetRaceNum(), vid, GetPlayerID(), pkChrCauser->GetName());
  5617.  
  5618. #ifdef __MELEY_LAIR_DUNGEON__
  5619. if ((IsNPC()) && (GetRaceNum() == (WORD)(MeleyLair::GATE_VNUM)) && (MeleyLair::CMgr::instance().IsMeleyMap(pkChrCauser->GetMapIndex())))
  5620. {
  5621. MeleyLair::CMgr::instance().Start(pkChrCauser, pkChrCauser->GetGuild());
  5622. return;
  5623. }
  5624. #endif
  5625.  
  5626. // ??? ???? ???? ??? ? ??.
  5627. {
  5628. // ?, ??? ??? ??? ??? ? ??.
  5629. if (pkChrCauser->GetMyShop() && pkChrCauser != this)
  5630. {
  5631. if (test_server)
  5632. sys_err("OnClick Fail (%s->%s) - pc has shop", pkChrCauser->GetName(), GetName());
  5633. return;
  5634. }
  5635. }
  5636.  
  5637. // ????? ???? ??? ? ??.
  5638. {
  5639. if (pkChrCauser->GetExchange())
  5640. {
  5641. if (test_server)
  5642. sys_err("OnClick Fail (%s->%s) - pc is exchanging", pkChrCauser->GetName(), GetName());
  5643. return;
  5644. }
  5645. }
  5646.  
  5647. #ifdef OFFLINE_SHOP
  5648. if (IsPC() || IsNPC() && GetRaceNum() == 30000)
  5649. {
  5650. if (!CTargetManager::instance().GetTargetInfo(pkChrCauser->GetPlayerID(), TARGET_TYPE_VID, GetVID()) || GetRaceNum() == 30000)
  5651. #else
  5652.  
  5653. if (IsPC())
  5654. {
  5655. if (!CTargetManager::instance().GetTargetInfo(pkChrCauser->GetPlayerID(), TARGET_TYPE_VID, GetVID()))
  5656. #endif
  5657. {
  5658. // 2005.03.17.myevan.?¢¬¡Æ??? ??¢¥? ¡Æ???¢¥A ¡Æ©©?I ¡íoA¢§ ?©©¢¬¢ç ¡¾a¢¥E?¡í ??¥ì?¢©??¢­¢¥?.
  5659. if (GetMyShop())
  5660. {
  5661. if (pkChrCauser->IsDead() == true) return;
  5662.  
  5663. //PREVENT_TRADE_WINDOW
  5664. if (pkChrCauser == this) // ?U¡¾a¢¥A ¡Æ¢§¢¥E
  5665. {
  5666. if ((GetExchange() || IsOpenSafebox() || GetShopOwner()) || IsCubeOpen())
  5667. {
  5668. pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("shop_err1."));
  5669. return;
  5670. }
  5671. }
  5672. else // ¢¥?¢¬? ¡íc¢Ò¡À?? ?¡þ¢¬?C©¬?¡í¢Ò¡×
  5673. {
  5674. // ?¡þ¢¬?C? ¡íc¢Ò¡À?? ¡¾©©??/?¢¨¡Æi/¡Æ©©?I¡íoA¢§/¡íoA¢§???eA©¬??¢Òo¢¬e ??¡Æ¢§
  5675. if ((pkChrCauser->GetExchange() || pkChrCauser->IsOpenSafebox() || pkChrCauser->GetMyShop() || pkChrCauser->GetShopOwner()) || pkChrCauser->IsCubeOpen())
  5676. {
  5677. pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("shop_err2"));
  5678. return;
  5679. }
  5680.  
  5681. // ?¡þ¢¬?C? ¢¥e¡ío?? ¡¾©©??/?¢¨¡Æi/¡íoA¢§???eA©¬??¢Òo¢¬e ??¡Æ¢§
  5682. //if ((GetExchange() || IsOpenSafebox() || GetShopOwner()))
  5683. if ((GetExchange() || IsOpenSafebox() || IsCubeOpen()))
  5684. {
  5685. pkChrCauser->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("shop_err3"));
  5686. return;
  5687. }
  5688. }
  5689. #if defined(SHOP_SEARCH)
  5690. CTargetManager::Instance().DeleteTarget(pkChrCauser->GetPlayerID(), IsPrivShop() ? GetPrivShop() : GetPlayerID(), "SHOP_SEARCH_TARGET");
  5691.  
  5692. #endif
  5693. //END_PREVENT_TRADE_WINDOW
  5694. #ifdef OFFLINE_SHOP
  5695. if (GetMyShop()->IsLocked())
  5696. return;
  5697. #endif
  5698. GetMyShop()->AddGuest(pkChrCauser, GetVID(), false);
  5699.  
  5700. pkChrCauser->SetShopOwner(this);
  5701. return;
  5702. }
  5703.  
  5704. if (test_server)
  5705. sys_err("%s.OnClickFailure(%s) - target is PC", pkChrCauser->GetName(), GetName());
  5706.  
  5707. return;
  5708. }
  5709. }
  5710. pkChrCauser->SetQuestNPCID(GetVID());
  5711.  
  5712. if (quest::CQuestManager::instance().Click(pkChrCauser->GetPlayerID(), this))
  5713. {
  5714. return;
  5715. }
  5716.  
  5717.  
  5718. // NPC ?? ?? ?? : ?? ?? ?
  5719. if (!IsPC())
  5720. {
  5721. if (!m_triggerOnClick.pFunc)
  5722. {
  5723. return;
  5724. }
  5725.  
  5726. m_triggerOnClick.pFunc(this, pkChrCauser);
  5727. }
  5728.  
  5729. }
  5730.  
  5731. BYTE CHARACTER::GetGMLevel() const
  5732. {
  5733. if (test_server)
  5734. return GM_IMPLEMENTOR;
  5735. return m_pointsInstant.gm_level;
  5736. }
  5737.  
  5738. void CHARACTER::SetGMLevel()
  5739. {
  5740. if (GetDesc())
  5741. {
  5742. m_pointsInstant.gm_level = gm_get_level(GetName(), GetDesc()->GetHostName(), GetDesc()->GetAccountTable().login);
  5743. }
  5744. else
  5745. {
  5746. m_pointsInstant.gm_level = GM_PLAYER;
  5747. }
  5748. }
  5749.  
  5750. BOOL CHARACTER::IsGM() const
  5751. {
  5752. if (m_pointsInstant.gm_level != GM_PLAYER)
  5753. return true;
  5754. if (test_server)
  5755. return true;
  5756. return false;
  5757. }
  5758.  
  5759. void CHARACTER::SetStone(LPCHARACTER pkChrStone)
  5760. {
  5761. m_pkChrStone = pkChrStone;
  5762.  
  5763. if (m_pkChrStone)
  5764. {
  5765. if (pkChrStone->m_set_pkChrSpawnedBy.find(this) == pkChrStone->m_set_pkChrSpawnedBy.end())
  5766. pkChrStone->m_set_pkChrSpawnedBy.insert(this);
  5767. }
  5768. }
  5769.  
  5770. struct FuncDeadSpawnedByStone
  5771. {
  5772. void operator () (LPCHARACTER ch)
  5773. {
  5774. ch->Dead(NULL);
  5775. ch->SetStone(NULL);
  5776. }
  5777. };
  5778.  
  5779. void CHARACTER::ClearStone()
  5780. {
  5781. if (!m_set_pkChrSpawnedBy.empty())
  5782. {
  5783. // ³»°¡ ½ºÆù½ÃŲ ¸ó½ºÅ͵éÀ» ¸ðµÎ Á×ÀδÙ.
  5784. FuncDeadSpawnedByStone f;
  5785. std::for_each(m_set_pkChrSpawnedBy.begin(), m_set_pkChrSpawnedBy.end(), f);
  5786. m_set_pkChrSpawnedBy.clear();
  5787. }
  5788.  
  5789. if (!m_pkChrStone)
  5790. return;
  5791.  
  5792. m_pkChrStone->m_set_pkChrSpawnedBy.erase(this);
  5793. m_pkChrStone = NULL;
  5794. }
  5795.  
  5796. void CHARACTER::ClearTarget()
  5797. {
  5798. if (m_pkChrTarget)
  5799. {
  5800. m_pkChrTarget->m_set_pkChrTargetedBy.erase(this);
  5801. m_pkChrTarget = NULL;
  5802. }
  5803.  
  5804. TPacketGCTarget p;
  5805. p.header = HEADER_GC_TARGET;
  5806. p.dwVID = 0;
  5807. p.bHPPercent = 0;
  5808. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5809. p.iMinHP = 0;
  5810. p.iMaxHP = 0;
  5811. #endif
  5812. CHARACTER_SET::iterator it = m_set_pkChrTargetedBy.begin();
  5813. while (it != m_set_pkChrTargetedBy.end())
  5814. {
  5815. LPCHARACTER pkChr = *(it++);
  5816. pkChr->m_pkChrTarget = NULL;
  5817.  
  5818. if (!pkChr->GetDesc())
  5819. {
  5820. sys_err("%s %p does not have desc", pkChr->GetName(), get_pointer(pkChr));
  5821. abort();
  5822. }
  5823.  
  5824. pkChr->GetDesc()->Packet(&p, sizeof(TPacketGCTarget));
  5825. }
  5826.  
  5827. m_set_pkChrTargetedBy.clear();
  5828. }
  5829.  
  5830. void CHARACTER::SetTarget(LPCHARACTER pkChrTarget)
  5831. {
  5832. if (m_pkChrTarget == pkChrTarget)
  5833. return;
  5834.  
  5835. if (IS_CASTLE_MAP(GetMapIndex()) && !IsGM())
  5836. return;
  5837.  
  5838. if (m_pkChrTarget)
  5839. m_pkChrTarget->m_set_pkChrTargetedBy.erase(this);
  5840.  
  5841. m_pkChrTarget = pkChrTarget;
  5842.  
  5843. TPacketGCTarget p;
  5844. p.header = HEADER_GC_TARGET;
  5845. if (m_pkChrTarget)
  5846. {
  5847. m_pkChrTarget->m_set_pkChrTargetedBy.insert(this);
  5848. p.dwVID = m_pkChrTarget->GetVID();
  5849. #ifdef __VIEW_TARGET_PLAYER_HP__
  5850. if ((m_pkChrTarget->GetMaxHP() <= 0))
  5851. {
  5852. p.bHPPercent = 0;
  5853. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5854. p.iMinHP = 0;
  5855. p.iMaxHP = 0;
  5856. #endif
  5857. }
  5858. else if (m_pkChrTarget->IsPC() && !m_pkChrTarget->IsPolymorphed())
  5859. {
  5860. p.bHPPercent = MINMAX(0, (m_pkChrTarget->GetHP() * 100) / m_pkChrTarget->GetMaxHP(), 100);
  5861. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5862. p.iMinHP = m_pkChrTarget->GetHP();
  5863. p.iMaxHP = m_pkChrTarget->GetMaxHP();
  5864. #endif
  5865. #else
  5866. if ((m_pkChrTarget->IsPC() && !m_pkChrTarget->IsPolymorphed()) || (m_pkChrTarget->GetMaxHP() <= 0))
  5867. {
  5868. p.bHPPercent = 0;
  5869. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5870. p.iMinHP = 0;
  5871. p.iMaxHP = 0;
  5872. #endif
  5873. #endif
  5874. }
  5875. else
  5876. {
  5877. if (m_pkChrTarget->GetRaceNum() == 20101 || m_pkChrTarget->GetRaceNum() == 20102 || m_pkChrTarget->GetRaceNum() == 20103 || m_pkChrTarget->GetRaceNum() == 20104 || m_pkChrTarget->GetRaceNum() == 20105 || m_pkChrTarget->GetRaceNum() == 20106 || m_pkChrTarget->GetRaceNum() == 20107 || m_pkChrTarget->GetRaceNum() == 20108 || m_pkChrTarget->GetRaceNum() == 20109)
  5878. {
  5879. LPCHARACTER owner = m_pkChrTarget->GetVictim();
  5880. if (owner)
  5881. {
  5882. int iHorseHealth = owner->GetHorseHealth();
  5883. int iHorseMaxHealth = owner->GetHorseMaxHealth();
  5884. if (iHorseMaxHealth)
  5885. {
  5886. p.bHPPercent = MINMAX(0, iHorseHealth * 100 / iHorseMaxHealth, 100);
  5887. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5888. p.iMinHP = 100;
  5889. p.iMaxHP = 100;
  5890. #endif
  5891. }
  5892. else
  5893. {
  5894. p.bHPPercent = 100;
  5895. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5896. p.iMinHP = 100;
  5897. p.iMaxHP = 100;
  5898. #endif
  5899. }
  5900. }
  5901. else
  5902. {
  5903. p.bHPPercent = 100;
  5904. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5905. p.iMinHP = 100;
  5906. p.iMaxHP = 100;
  5907. #endif
  5908. }
  5909. }
  5910. else
  5911. {
  5912. if (m_pkChrTarget->GetMaxHP() <= 0)
  5913. {
  5914. p.bHPPercent = 0;
  5915. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5916. p.iMinHP = 0;
  5917. p.iMaxHP = 0;
  5918. #endif
  5919. }
  5920. else
  5921. {
  5922. p.bHPPercent = MINMAX(0, (m_pkChrTarget->GetHP() * 100) / m_pkChrTarget->GetMaxHP(), 100);
  5923. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5924. p.iMinHP = m_pkChrTarget->GetHP();
  5925. p.iMaxHP = m_pkChrTarget->GetMaxHP();
  5926. #endif
  5927. }
  5928. }
  5929. }
  5930. }
  5931. else
  5932. {
  5933. p.dwVID = 0;
  5934. p.bHPPercent = 0;
  5935. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5936. p.iMinHP = 0;
  5937. p.iMaxHP = 0;
  5938. #endif
  5939. }
  5940.  
  5941. GetDesc()->Packet(&p, sizeof(TPacketGCTarget));
  5942. }
  5943.  
  5944. void CHARACTER::BroadcastTargetPacket()
  5945. {
  5946. if (m_set_pkChrTargetedBy.empty())
  5947. return;
  5948.  
  5949. TPacketGCTarget p;
  5950. p.header = HEADER_GC_TARGET;
  5951. p.dwVID = GetVID();
  5952. if (GetMaxHP() <= 0)
  5953. {
  5954. p.bHPPercent = 0;
  5955. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5956. p.iMinHP = 0;
  5957. p.iMaxHP = 0;
  5958. #endif
  5959. }
  5960. else
  5961. {
  5962. #ifdef __VIEW_TARGET_PLAYER_HP__
  5963. p.bHPPercent = MINMAX(0, (GetHP() * 100) / GetMaxHP(), 100);
  5964. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5965. p.iMinHP = GetHP();
  5966. p.iMaxHP = GetMaxHP();
  5967. #endif
  5968. #else
  5969. if (IsPC())
  5970. {
  5971. p.bHPPercent = 0;
  5972. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5973. p.iMinHP = 0;
  5974. p.iMaxHP = 0;
  5975. #endif
  5976. }
  5977. else
  5978. {
  5979. p.bHPPercent = MINMAX(0, (GetHP() * 100) / GetMaxHP(), 100);
  5980. #ifdef __VIEW_TARGET_DECIMAL_HP__
  5981. p.iMinHP = GetHP();
  5982. p.iMaxHP = GetMaxHP();
  5983. #endif
  5984. }
  5985. #endif
  5986. }
  5987.  
  5988. CHARACTER_SET::iterator it = m_set_pkChrTargetedBy.begin();
  5989. while (it != m_set_pkChrTargetedBy.end())
  5990. {
  5991. LPCHARACTER pkChr = *it++;
  5992. if (!pkChr->GetDesc())
  5993. {
  5994. sys_err("%s %p does not have desc", pkChr->GetName(), get_pointer(pkChr));
  5995. abort();
  5996. }
  5997.  
  5998. pkChr->GetDesc()->Packet(&p, sizeof(TPacketGCTarget));
  5999. }
  6000. }
  6001.  
  6002. void CHARACTER::CheckTarget()
  6003. {
  6004. if (!m_pkChrTarget)
  6005. return;
  6006.  
  6007. if (DISTANCE_APPROX(GetX() - m_pkChrTarget->GetX(), GetY() - m_pkChrTarget->GetY()) >= 4800)
  6008. SetTarget(NULL);
  6009. }
  6010.  
  6011. void CHARACTER::SetWarpLocation(long lMapIndex, long x, long y)
  6012. {
  6013. m_posWarp.x = x * 100;
  6014. m_posWarp.y = y * 100;
  6015. m_lWarpMapIndex = lMapIndex;
  6016. }
  6017.  
  6018. void CHARACTER::SaveExitLocation()
  6019. {
  6020. m_posExit = GetXYZ();
  6021. m_lExitMapIndex = GetMapIndex();
  6022. }
  6023.  
  6024. void CHARACTER::ExitToSavedLocation()
  6025. {
  6026. sys_log (0, "ExitToSavedLocation");
  6027. WarpSet(m_posWarp.x, m_posWarp.y, m_lWarpMapIndex);
  6028.  
  6029. m_posExit.x = m_posExit.y = m_posExit.z = 0;
  6030. m_lExitMapIndex = 0;
  6031. }
  6032.  
  6033. // fixme
  6034. // Áö±Ý±îÁø privateMapIndex °¡ ÇöÀç ¸Ê À妽º¿Í °°ÀºÁö üũ ÇÏ´Â °ÍÀ» ¿ÜºÎ¿¡¼­ Çϰí,
  6035. // ´Ù¸£¸é warpsetÀ» ºÒ·¶´Âµ¥
  6036. // À̸¦ warpset ¾ÈÀ¸·Î ³ÖÀÚ.
  6037. bool CHARACTER::WarpSet(long x, long y, long lPrivateMapIndex)
  6038. {
  6039. if (!IsPC())
  6040. return false;
  6041.  
  6042. long lAddr;
  6043. long lMapIndex;
  6044. WORD wPort;
  6045.  
  6046. if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort))
  6047. {
  6048. sys_err("cannot find map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
  6049. return false;
  6050. }
  6051.  
  6052. if (lPrivateMapIndex >= 10000)
  6053. {
  6054. if (lPrivateMapIndex / 10000 != lMapIndex)
  6055. {
  6056. sys_err("Invalid map inedx %d, must be child of %d", lPrivateMapIndex, lMapIndex);
  6057. return false;
  6058. }
  6059.  
  6060. lMapIndex = lPrivateMapIndex;
  6061. }
  6062.  
  6063. Stop();
  6064. Save();
  6065.  
  6066. if (GetSectree())
  6067. {
  6068. GetSectree()->RemoveEntity(this);
  6069. ViewCleanup();
  6070.  
  6071. EncodeRemovePacket(this);
  6072. }
  6073.  
  6074. m_lWarpMapIndex = lMapIndex;
  6075. m_posWarp.x = x;
  6076. m_posWarp.y = y;
  6077.  
  6078. sys_log(0, "WarpSet %s %d %d current map %d target map %d", GetName(), x, y, GetMapIndex(), lMapIndex);
  6079.  
  6080. TPacketGCWarp p;
  6081.  
  6082. p.bHeader = HEADER_GC_WARP;
  6083. p.lX = x;
  6084. p.lY = y;
  6085. p.lAddr = lAddr;
  6086. p.wPort = wPort;
  6087.  
  6088. GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
  6089.  
  6090. char buf[256];
  6091. snprintf(buf, sizeof(buf), "%s MapIdx %ld DestMapIdx%ld DestX%ld DestY%ld Empire%d", GetName(), GetMapIndex(), lPrivateMapIndex, x, y, GetEmpire());
  6092. LogManager::instance().CharLog(this, 0, "WARP", buf);
  6093.  
  6094. return true;
  6095. }
  6096.  
  6097. #define ENABLE_GOHOME_IF_MAP_NOT_ALLOWED
  6098. void CHARACTER::WarpEnd()
  6099. {
  6100. if (test_server)
  6101. sys_log(0, "WarpEnd %s", GetName());
  6102.  
  6103. if (m_posWarp.x == 0 && m_posWarp.y == 0)
  6104. return;
  6105.  
  6106. int index = m_lWarpMapIndex;
  6107.  
  6108. if (index > 10000)
  6109. index /= 10000;
  6110.  
  6111. if (!map_allow_find(index))
  6112. {
  6113. // ÀÌ °÷À¸·Î ¿öÇÁÇÒ ¼ö ¾øÀ¸¹Ç·Î ¿öÇÁÇϱâ Àü ÁÂÇ¥·Î µÇµ¹¸®ÀÚ.
  6114. sys_err("location %d %d not allowed to login this server", m_posWarp.x, m_posWarp.y);
  6115. #ifdef ENABLE_GOHOME_IF_MAP_NOT_ALLOWED
  6116. GoHome();
  6117. #else
  6118. GetDesc()->SetPhase(PHASE_CLOSE);
  6119. #endif
  6120. return;
  6121. }
  6122.  
  6123. sys_log(0, "WarpEnd %s %d %u %u", GetName(), m_lWarpMapIndex, m_posWarp.x, m_posWarp.y);
  6124.  
  6125. Show(m_lWarpMapIndex, m_posWarp.x, m_posWarp.y, 0);
  6126. Stop();
  6127.  
  6128. m_lWarpMapIndex = 0;
  6129. m_posWarp.x = m_posWarp.y = m_posWarp.z = 0;
  6130.  
  6131. {
  6132. // P2P Login
  6133. TPacketGGLogin p;
  6134.  
  6135. p.bHeader = HEADER_GG_LOGIN;
  6136. strlcpy(p.szName, GetName(), sizeof(p.szName));
  6137. p.dwPID = GetPlayerID();
  6138. p.bEmpire = GetEmpire();
  6139. p.lMapIndex = SECTREE_MANAGER::instance().GetMapIndex(GetX(), GetY());
  6140. p.bChannel = g_bChannel;
  6141.  
  6142. P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGLogin));
  6143. }
  6144. }
  6145.  
  6146. bool CHARACTER::Return()
  6147. {
  6148. if (!IsNPC())
  6149. return false;
  6150.  
  6151. int x, y;
  6152. /*
  6153. float fDist = DISTANCE_SQRT(m_pkMobData->m_posLastAttacked.x - GetX(), m_pkMobData->m_posLastAttacked.y - GetY());
  6154. float fx, fy;
  6155. GetDeltaByDegree(GetRotation(), fDist, &fx, &fy);
  6156. x = GetX() + (int) fx;
  6157. y = GetY() + (int) fy;
  6158. */
  6159. SetVictim(NULL);
  6160.  
  6161. x = m_pkMobInst->m_posLastAttacked.x;
  6162. y = m_pkMobInst->m_posLastAttacked.y;
  6163.  
  6164. SetRotationToXY(x, y);
  6165.  
  6166. if (!Goto(x, y))
  6167. return false;
  6168.  
  6169. SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
  6170.  
  6171. if (test_server)
  6172. sys_log(0, "%s %p Æ÷±âÇÏ°í µ¹¾Æ°¡ÀÚ! %d %d", GetName(), this, x, y);
  6173.  
  6174. if (GetParty())
  6175. GetParty()->SendMessage(this, PM_RETURN, x, y);
  6176.  
  6177. return true;
  6178. }
  6179.  
  6180. bool CHARACTER::Follow(LPCHARACTER pkChr, float fMinDistance)
  6181. {
  6182. if (IsPC())
  6183. {
  6184. sys_err("CHARACTER::Follow : PC cannot use this method", GetName());
  6185. return false;
  6186. }
  6187.  
  6188. // TRENT_MONSTER
  6189. if (IS_SET(m_pointsInstant.dwAIFlag, AIFLAG_NOMOVE))
  6190. {
  6191. if (pkChr->IsPC()) // ÂѾư¡´Â »ó´ë°¡ PCÀÏ ¶§
  6192. {
  6193. // If i'm in a party. I must obey party leader's AI.
  6194. if (!GetParty() || !GetParty()->GetLeader() || GetParty()->GetLeader() == this)
  6195. {
  6196. if (get_dword_time() - m_pkMobInst->m_dwLastAttackedTime >= 15000) // ¸¶Áö¸·À¸·Î °ø°Ý¹ÞÀºÁö 15Ãʰ¡ Áö³µ°í
  6197. {
  6198. // ¸¶Áö¸· ¸ÂÀº °÷À¸·Î ºÎÅÍ 50¹ÌÅÍ ÀÌ»ó Â÷À̳ª¸é Æ÷±âÇÏ°í µ¹¾Æ°£´Ù.
  6199. if (m_pkMobData->m_table.wAttackRange < DISTANCE_APPROX(pkChr->GetX() - GetX(), pkChr->GetY() - GetY()))
  6200. if (Return())
  6201. return true;
  6202. }
  6203. }
  6204. }
  6205. return false;
  6206. }
  6207. // END_OF_TRENT_MONSTER
  6208.  
  6209. long x = pkChr->GetX();
  6210. long y = pkChr->GetY();
  6211.  
  6212. if (pkChr->IsPC()) // ÂѾư¡´Â »ó´ë°¡ PCÀÏ ¶§
  6213. {
  6214. // If i'm in a party. I must obey party leader's AI.
  6215. if (!GetParty() || !GetParty()->GetLeader() || GetParty()->GetLeader() == this)
  6216. {
  6217. if (get_dword_time() - m_pkMobInst->m_dwLastAttackedTime >= 15000) // ¸¶Áö¸·À¸·Î °ø°Ý¹ÞÀºÁö 15Ãʰ¡ Áö³µ°í
  6218. {
  6219. // ¸¶Áö¸· ¸ÂÀº °÷À¸·Î ºÎÅÍ 50¹ÌÅÍ ÀÌ»ó Â÷À̳ª¸é Æ÷±âÇÏ°í µ¹¾Æ°£´Ù.
  6220. if (5000 < DISTANCE_APPROX(m_pkMobInst->m_posLastAttacked.x - GetX(), m_pkMobInst->m_posLastAttacked.y - GetY()))
  6221. if (Return())
  6222. return true;
  6223. }
  6224. }
  6225. }
  6226.  
  6227. if (IsGuardNPC())
  6228. {
  6229. if (5000 < DISTANCE_APPROX(m_pkMobInst->m_posLastAttacked.x - GetX(), m_pkMobInst->m_posLastAttacked.y - GetY()))
  6230. if (Return())
  6231. return true;
  6232. }
  6233.  
  6234. #ifdef NEW_PET_SYSTEM
  6235. if (pkChr->IsState(pkChr->m_stateMove) &&
  6236. GetMobBattleType() != BATTLE_TYPE_RANGE &&
  6237. GetMobBattleType() != BATTLE_TYPE_MAGIC &&
  6238. false == IsPet() && false == IsSupport() && false == IsNewPet())
  6239. #else
  6240. if (pkChr->IsState(pkChr->m_stateMove) &&
  6241. GetMobBattleType() != BATTLE_TYPE_RANGE &&
  6242. GetMobBattleType() != BATTLE_TYPE_MAGIC &&
  6243. false == IsPet())
  6244. #endif
  6245. {
  6246. // ´ë»óÀÌ À̵¿ÁßÀÌ¸é ¿¹Ãø À̵¿À» ÇÑ´Ù
  6247. // ³ª¿Í »ó´ë¹æÀÇ ¼ÓµµÂ÷¿Í °Å¸®·ÎºÎÅÍ ¸¸³¯ ½Ã°£À» ¿¹»óÇÑ ÈÄ
  6248. // »ó´ë¹æÀÌ ±× ½Ã°£±îÁö Á÷¼±À¸·Î À̵¿ÇÑ´Ù°í °¡Á¤ÇÏ¿© °Å±â·Î À̵¿ÇÑ´Ù.
  6249. float rot = pkChr->GetRotation();
  6250. float rot_delta = GetDegreeDelta(rot, GetDegreeFromPositionXY(GetX(), GetY(), pkChr->GetX(), pkChr->GetY()));
  6251.  
  6252. float yourSpeed = pkChr->GetMoveSpeed();
  6253. float mySpeed = GetMoveSpeed();
  6254.  
  6255. float fDist = DISTANCE_SQRT(x - GetX(), y - GetY());
  6256. float fFollowSpeed = mySpeed - yourSpeed * cos(rot_delta * M_PI / 180);
  6257.  
  6258. if (fFollowSpeed >= 0.1f)
  6259. {
  6260. float fMeetTime = fDist / fFollowSpeed;
  6261. float fYourMoveEstimateX, fYourMoveEstimateY;
  6262.  
  6263. if( fMeetTime * yourSpeed <= 100000.0f )
  6264. {
  6265. GetDeltaByDegree(pkChr->GetRotation(), fMeetTime * yourSpeed, &fYourMoveEstimateX, &fYourMoveEstimateY);
  6266.  
  6267. x += (long) fYourMoveEstimateX;
  6268. y += (long) fYourMoveEstimateY;
  6269.  
  6270. float fDistNew = sqrt(((double)x - GetX())*(x-GetX())+((double)y - GetY())*(y-GetY()));
  6271. if (fDist < fDistNew)
  6272. {
  6273. x = (long)(GetX() + (x - GetX()) * fDist / fDistNew);
  6274. y = (long)(GetY() + (y - GetY()) * fDist / fDistNew);
  6275. }
  6276. }
  6277. }
  6278. }
  6279.  
  6280. // °¡·Á´Â À§Ä¡¸¦ ¹Ù¶óºÁ¾ß ÇÑ´Ù.
  6281. SetRotationToXY(x, y);
  6282.  
  6283. float fDist = DISTANCE_SQRT(x - GetX(), y - GetY());
  6284.  
  6285. if (fDist <= fMinDistance)
  6286. return false;
  6287.  
  6288. float fx, fy;
  6289.  
  6290. if (IsChangeAttackPosition(pkChr) && GetMobRank() < MOB_RANK_BOSS)
  6291. {
  6292. // »ó´ë¹æ ÁÖº¯ ·£´ýÇÑ °÷À¸·Î À̵¿
  6293. SetChangeAttackPositionTime();
  6294.  
  6295. int retry = 16;
  6296. int dx, dy;
  6297. int rot = (int) GetDegreeFromPositionXY(x, y, GetX(), GetY());
  6298.  
  6299. while (--retry)
  6300. {
  6301. if (fDist < 500.0f)
  6302. GetDeltaByDegree((rot + number(-90, 90) + number(-90, 90)) % 360, fMinDistance, &fx, &fy);
  6303. else
  6304. GetDeltaByDegree(number(0, 359), fMinDistance, &fx, &fy);
  6305.  
  6306. dx = x + (int) fx;
  6307. dy = y + (int) fy;
  6308.  
  6309. LPSECTREE tree = SECTREE_MANAGER::instance().Get(GetMapIndex(), dx, dy);
  6310.  
  6311. if (NULL == tree)
  6312. break;
  6313.  
  6314. if (0 == (tree->GetAttribute(dx, dy) & (ATTR_BLOCK | ATTR_OBJECT)))
  6315. break;
  6316. }
  6317.  
  6318. //sys_log(0, "±Ùó ¾îµò°¡·Î À̵¿ %s retry %d", GetName(), retry);
  6319. if (!Goto(dx, dy))
  6320. return false;
  6321. }
  6322. else
  6323. {
  6324. // Á÷¼± µû¶ó°¡±â
  6325. float fDistToGo = fDist - fMinDistance;
  6326. GetDeltaByDegree(GetRotation(), fDistToGo, &fx, &fy);
  6327.  
  6328. //sys_log(0, "Á÷¼±À¸·Î À̵¿ %s", GetName());
  6329. if (!Goto(GetX() + (int) fx, GetY() + (int) fy))
  6330. return false;
  6331. }
  6332.  
  6333. SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
  6334. //MonsterLog("ÂѾư¡±â; %s", pkChr->GetName());
  6335. return true;
  6336. }
  6337.  
  6338. float CHARACTER::GetDistanceFromSafeboxOpen() const
  6339. {
  6340. return DISTANCE_APPROX(GetX() - m_posSafeboxOpen.x, GetY() - m_posSafeboxOpen.y);
  6341. }
  6342.  
  6343. void CHARACTER::SetSafeboxOpenPosition()
  6344. {
  6345. m_posSafeboxOpen = GetXYZ();
  6346. }
  6347.  
  6348. CSafebox * CHARACTER::GetSafebox() const
  6349. {
  6350. return m_pkSafebox;
  6351. }
  6352.  
  6353. void CHARACTER::ReqSafeboxLoad(const char* pszPassword)
  6354. {
  6355. if (!*pszPassword || strlen(pszPassword) > SAFEBOX_PASSWORD_MAX_LEN)
  6356. {
  6357. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> À߸øµÈ ¾ÏÈ£¸¦ ÀÔ·ÂÇϼ̽À´Ï´Ù."));
  6358. return;
  6359. }
  6360. else if (m_pkSafebox)
  6361. {
  6362. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í°¡ ÀÌ¹Ì ¿­·ÁÀÖ½À´Ï´Ù."));
  6363. return;
  6364. }
  6365.  
  6366. int iPulse = thecore_pulse();
  6367.  
  6368. if (iPulse - GetSafeboxLoadTime() < PASSES_PER_SEC(10))
  6369. {
  6370. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í¸¦ ´ÝÀºÁö 10ÃÊ ¾È¿¡´Â ¿­ ¼ö ¾ø½À´Ï´Ù."));
  6371. return;
  6372. }
  6373. else if (GetDistanceFromSafeboxOpen() > 1000)
  6374. {
  6375. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> °Å¸®°¡ ¸Ö¾î¼­ â°í¸¦ ¿­ ¼ö ¾ø½À´Ï´Ù."));
  6376. return;
  6377. }
  6378. else if (m_bOpeningSafebox)
  6379. {
  6380. sys_log(0, "Overlapped safebox load request from %s", GetName());
  6381. return;
  6382. }
  6383.  
  6384. SetSafeboxLoadTime();
  6385. m_bOpeningSafebox = true;
  6386.  
  6387. TSafeboxLoadPacket p;
  6388. p.dwID = GetDesc()->GetAccountTable().id;
  6389. strlcpy(p.szLogin, GetDesc()->GetAccountTable().login, sizeof(p.szLogin));
  6390. strlcpy(p.szPassword, pszPassword, sizeof(p.szPassword));
  6391.  
  6392. db_clientdesc->DBPacket(HEADER_GD_SAFEBOX_LOAD, GetDesc()->GetHandle(), &p, sizeof(p));
  6393. }
  6394.  
  6395. void CHARACTER::LoadSafebox(int iSize, DWORD dwGold, int iItemCount, TPlayerItem * pItems)
  6396. {
  6397. bool bLoaded = false;
  6398.  
  6399. //PREVENT_TRADE_WINDOW
  6400. SetOpenSafebox(true);
  6401. //END_PREVENT_TRADE_WINDOW
  6402.  
  6403. if (m_pkSafebox)
  6404. bLoaded = true;
  6405.  
  6406. if (!m_pkSafebox)
  6407. m_pkSafebox = M2_NEW CSafebox(this, iSize, dwGold);
  6408. else
  6409. m_pkSafebox->ChangeSize(iSize);
  6410.  
  6411. m_iSafeboxSize = iSize;
  6412.  
  6413. TPacketCGSafeboxSize p;
  6414.  
  6415. p.bHeader = HEADER_GC_SAFEBOX_SIZE;
  6416. p.bSize = iSize;
  6417.  
  6418. GetDesc()->Packet(&p, sizeof(TPacketCGSafeboxSize));
  6419.  
  6420. if (!bLoaded)
  6421. {
  6422. for (int i = 0; i < iItemCount; ++i, ++pItems)
  6423. {
  6424. if (!m_pkSafebox->IsValidPosition(pItems->pos))
  6425. continue;
  6426.  
  6427. LPITEM item = ITEM_MANAGER::instance().CreateItem(pItems->vnum, pItems->count, pItems->id);
  6428.  
  6429. if (!item)
  6430. {
  6431. sys_err("cannot create item vnum %d id %u (name: %s)", pItems->vnum, pItems->id, GetName());
  6432. continue;
  6433. }
  6434.  
  6435. item->SetSkipSave(true);
  6436. item->SetSockets(pItems->alSockets);
  6437. item->SetAttributes(pItems->aAttr);
  6438. #ifdef __CHANGELOOK_SYSTEM__
  6439. item->SetTransmutation(pItems->transmutation);
  6440. #endif
  6441. if (!m_pkSafebox->Add(pItems->pos, item))
  6442. {
  6443. M2_DESTROY_ITEM(item);
  6444. }
  6445. else
  6446. item->SetSkipSave(false);
  6447. }
  6448. }
  6449. }
  6450.  
  6451. void CHARACTER::ChangeSafeboxSize(BYTE bSize)
  6452. {
  6453. //if (!m_pkSafebox)
  6454. //return;
  6455.  
  6456. TPacketCGSafeboxSize p;
  6457.  
  6458. p.bHeader = HEADER_GC_SAFEBOX_SIZE;
  6459. p.bSize = bSize;
  6460.  
  6461. GetDesc()->Packet(&p, sizeof(TPacketCGSafeboxSize));
  6462.  
  6463. if (m_pkSafebox)
  6464. m_pkSafebox->ChangeSize(bSize);
  6465.  
  6466. m_iSafeboxSize = bSize;
  6467. }
  6468.  
  6469. void CHARACTER::CloseSafebox()
  6470. {
  6471. if (!m_pkSafebox)
  6472. return;
  6473.  
  6474. //PREVENT_TRADE_WINDOW
  6475. SetOpenSafebox(false);
  6476. //END_PREVENT_TRADE_WINDOW
  6477.  
  6478. m_pkSafebox->Save();
  6479.  
  6480. M2_DELETE(m_pkSafebox);
  6481. m_pkSafebox = NULL;
  6482.  
  6483. ChatPacket(CHAT_TYPE_COMMAND, "CloseSafebox");
  6484.  
  6485. SetSafeboxLoadTime();
  6486. m_bOpeningSafebox = false;
  6487.  
  6488. Save();
  6489. }
  6490.  
  6491. CSafebox * CHARACTER::GetMall() const
  6492. {
  6493. return m_pkMall;
  6494. }
  6495.  
  6496. void CHARACTER::LoadMall(int iItemCount, TPlayerItem * pItems)
  6497. {
  6498. bool bLoaded = false;
  6499.  
  6500. if (m_pkMall)
  6501. bLoaded = true;
  6502.  
  6503. if (!m_pkMall)
  6504. m_pkMall = M2_NEW CSafebox(this, 3 * SAFEBOX_PAGE_SIZE, 0);
  6505. else
  6506. m_pkMall->ChangeSize(3 * SAFEBOX_PAGE_SIZE);
  6507.  
  6508. m_pkMall->SetWindowMode(MALL);
  6509.  
  6510. TPacketCGSafeboxSize p;
  6511.  
  6512. p.bHeader = HEADER_GC_MALL_OPEN;
  6513. p.bSize = 3 * SAFEBOX_PAGE_SIZE;
  6514.  
  6515. GetDesc()->Packet(&p, sizeof(TPacketCGSafeboxSize));
  6516.  
  6517. if (!bLoaded)
  6518. {
  6519. for (int i = 0; i < iItemCount; ++i, ++pItems)
  6520. {
  6521. if (!m_pkMall->IsValidPosition(pItems->pos))
  6522. continue;
  6523.  
  6524. LPITEM item = ITEM_MANAGER::instance().CreateItem(pItems->vnum, pItems->count, pItems->id);
  6525.  
  6526. if (!item)
  6527. {
  6528. sys_err("cannot create item vnum %d id %u (name: %s)", pItems->vnum, pItems->id, GetName());
  6529. continue;
  6530. }
  6531.  
  6532. item->SetSkipSave(true);
  6533. item->SetSockets(pItems->alSockets);
  6534. #ifdef __CHANGELOOK_SYSTEM__
  6535. item->SetTransmutation(pItems->transmutation);
  6536. #endif
  6537. item->SetAttributes(pItems->aAttr);
  6538.  
  6539. if (!m_pkMall->Add(pItems->pos, item))
  6540. M2_DESTROY_ITEM(item);
  6541. else
  6542. item->SetSkipSave(false);
  6543. }
  6544. }
  6545. }
  6546.  
  6547. void CHARACTER::CloseMall()
  6548. {
  6549. if (!m_pkMall)
  6550. return;
  6551.  
  6552. m_pkMall->Save();
  6553.  
  6554. M2_DELETE(m_pkMall);
  6555. m_pkMall = NULL;
  6556.  
  6557. ChatPacket(CHAT_TYPE_COMMAND, "CloseMall");
  6558. }
  6559.  
  6560. bool CHARACTER::BuildUpdatePartyPacket(TPacketGCPartyUpdate & out)
  6561. {
  6562. if (!GetParty())
  6563. return false;
  6564.  
  6565. memset(&out, 0, sizeof(out));
  6566.  
  6567. out.header = HEADER_GC_PARTY_UPDATE;
  6568. out.pid = GetPlayerID();
  6569. if (GetMaxHP() <= 0) // @fixme136
  6570. out.percent_hp = 0;
  6571. else
  6572. out.percent_hp = MINMAX(0, GetHP() * 100 / GetMaxHP(), 100);
  6573. out.role = GetParty()->GetRole(GetPlayerID());
  6574.  
  6575. sys_log(1, "PARTY %s role is %d", GetName(), out.role);
  6576.  
  6577. LPCHARACTER l = GetParty()->GetLeaderCharacter();
  6578.  
  6579. if (l && DISTANCE_APPROX(GetX() - l->GetX(), GetY() - l->GetY()) < PARTY_DEFAULT_RANGE)
  6580. {
  6581. out.affects[0] = GetParty()->GetPartyBonusExpPercent();
  6582. out.affects[1] = GetPoint(POINT_PARTY_ATTACKER_BONUS);
  6583. out.affects[2] = GetPoint(POINT_PARTY_TANKER_BONUS);
  6584. out.affects[3] = GetPoint(POINT_PARTY_BUFFER_BONUS);
  6585. out.affects[4] = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
  6586. out.affects[5] = GetPoint(POINT_PARTY_HASTE_BONUS);
  6587. out.affects[6] = GetPoint(POINT_PARTY_DEFENDER_BONUS);
  6588. }
  6589.  
  6590. return true;
  6591. }
  6592.  
  6593. int CHARACTER::GetLeadershipSkillLevel() const
  6594. {
  6595. return GetSkillLevel(SKILL_LEADERSHIP);
  6596. }
  6597.  
  6598. void CHARACTER::QuerySafeboxSize()
  6599. {
  6600. if (m_iSafeboxSize == -1)
  6601. {
  6602. DBManager::instance().ReturnQuery(QID_SAFEBOX_SIZE,
  6603. GetPlayerID(),
  6604. NULL,
  6605. "SELECT size FROM safebox%s WHERE account_id = %u",
  6606. get_table_postfix(),
  6607. GetDesc()->GetAccountTable().id);
  6608. }
  6609. }
  6610.  
  6611. void CHARACTER::SetSafeboxSize(int iSize)
  6612. {
  6613. sys_log(1, "SetSafeboxSize: %s %d", GetName(), iSize);
  6614. m_iSafeboxSize = iSize;
  6615. DBManager::instance().Query("UPDATE safebox%s SET size = %d WHERE account_id = %u", get_table_postfix(), iSize / SAFEBOX_PAGE_SIZE, GetDesc()->GetAccountTable().id);
  6616. }
  6617.  
  6618. int CHARACTER::GetSafeboxSize() const
  6619. {
  6620. return m_iSafeboxSize;
  6621. }
  6622.  
  6623. void CHARACTER::SetNowWalking(bool bWalkFlag)
  6624. {
  6625. //if (m_bNowWalking != bWalkFlag || IsNPC())
  6626. if (m_bNowWalking != bWalkFlag)
  6627. {
  6628. if (bWalkFlag)
  6629. {
  6630. m_bNowWalking = true;
  6631. m_dwWalkStartTime = get_dword_time();
  6632. }
  6633. else
  6634. {
  6635. m_bNowWalking = false;
  6636. }
  6637.  
  6638. //if (m_bNowWalking)
  6639. {
  6640. TPacketGCWalkMode p;
  6641. p.vid = GetVID();
  6642. p.header = HEADER_GC_WALK_MODE;
  6643. p.mode = m_bNowWalking ? WALKMODE_WALK : WALKMODE_RUN;
  6644.  
  6645. PacketView(&p, sizeof(p));
  6646. }
  6647.  
  6648. if (IsNPC())
  6649. {
  6650. if (m_bNowWalking)
  6651. MonsterLog("°È´Â´Ù");
  6652. else
  6653. MonsterLog("¶Ú´Ù");
  6654. }
  6655.  
  6656. //sys_log(0, "%s is now %s", GetName(), m_bNowWalking?"walking.":"running.");
  6657. }
  6658. }
  6659.  
  6660. void CHARACTER::StartStaminaConsume()
  6661. {
  6662. if (m_bStaminaConsume)
  6663. return;
  6664. PointChange(POINT_STAMINA, 0);
  6665. m_bStaminaConsume = true;
  6666. //ChatPacket(CHAT_TYPE_COMMAND, "StartStaminaConsume %d %d", STAMINA_PER_STEP * passes_per_sec, GetStamina());
  6667. if (IsStaminaHalfConsume())
  6668. ChatPacket(CHAT_TYPE_COMMAND, "StartStaminaConsume %d %d", STAMINA_PER_STEP * passes_per_sec / 2, GetStamina());
  6669. else
  6670. ChatPacket(CHAT_TYPE_COMMAND, "StartStaminaConsume %d %d", STAMINA_PER_STEP * passes_per_sec, GetStamina());
  6671. }
  6672.  
  6673. void CHARACTER::StopStaminaConsume()
  6674. {
  6675. if (!m_bStaminaConsume)
  6676. return;
  6677. PointChange(POINT_STAMINA, 0);
  6678. m_bStaminaConsume = false;
  6679. ChatPacket(CHAT_TYPE_COMMAND, "StopStaminaConsume %d", GetStamina());
  6680. }
  6681.  
  6682. bool CHARACTER::IsStaminaConsume() const
  6683. {
  6684. return m_bStaminaConsume;
  6685. }
  6686.  
  6687. bool CHARACTER::IsStaminaHalfConsume() const
  6688. {
  6689. return IsEquipUniqueItem(UNIQUE_ITEM_HALF_STAMINA);
  6690. }
  6691.  
  6692. void CHARACTER::ResetStopTime()
  6693. {
  6694. m_dwStopTime = get_dword_time();
  6695. }
  6696.  
  6697. DWORD CHARACTER::GetStopTime() const
  6698. {
  6699. return m_dwStopTime;
  6700. }
  6701.  
  6702. void CHARACTER::ResetPoint(int iLv)
  6703. {
  6704. BYTE bJob = GetJob();
  6705.  
  6706. PointChange(POINT_LEVEL, iLv - GetLevel());
  6707.  
  6708. SetRealPoint(POINT_ST, JobInitialPoints[bJob].st);
  6709. SetPoint(POINT_ST, GetRealPoint(POINT_ST));
  6710.  
  6711. SetRealPoint(POINT_HT, JobInitialPoints[bJob].ht);
  6712. SetPoint(POINT_HT, GetRealPoint(POINT_HT));
  6713.  
  6714. SetRealPoint(POINT_DX, JobInitialPoints[bJob].dx);
  6715. SetPoint(POINT_DX, GetRealPoint(POINT_DX));
  6716.  
  6717. SetRealPoint(POINT_IQ, JobInitialPoints[bJob].iq);
  6718. SetPoint(POINT_IQ, GetRealPoint(POINT_IQ));
  6719.  
  6720. SetRandomHP((iLv - 1) * number(JobInitialPoints[GetJob()].hp_per_lv_begin, JobInitialPoints[GetJob()].hp_per_lv_end));
  6721. SetRandomSP((iLv - 1) * number(JobInitialPoints[GetJob()].sp_per_lv_begin, JobInitialPoints[GetJob()].sp_per_lv_end));
  6722.  
  6723. // @fixme104
  6724. PointChange(POINT_STAT, (MINMAX(1, iLv, g_iStatusPointGetLevelLimit) * 3) + GetPoint(POINT_LEVEL_STEP) - GetPoint(POINT_STAT));
  6725.  
  6726. ComputePoints();
  6727.  
  6728. // ȸº¹
  6729. PointChange(POINT_HP, GetMaxHP() - GetHP());
  6730. PointChange(POINT_SP, GetMaxSP() - GetSP());
  6731.  
  6732. PointsPacket();
  6733.  
  6734. LogManager::instance().CharLog(this, 0, "RESET_POINT", "");
  6735. }
  6736.  
  6737. bool CHARACTER::IsChangeAttackPosition(LPCHARACTER target) const
  6738. {
  6739. if (!IsNPC())
  6740. return true;
  6741.  
  6742. DWORD dwChangeTime = AI_CHANGE_ATTACK_POISITION_TIME_NEAR;
  6743.  
  6744. if (DISTANCE_APPROX(GetX() - target->GetX(), GetY() - target->GetY()) >
  6745. AI_CHANGE_ATTACK_POISITION_DISTANCE + GetMobAttackRange())
  6746. dwChangeTime = AI_CHANGE_ATTACK_POISITION_TIME_FAR;
  6747.  
  6748. return get_dword_time() - m_dwLastChangeAttackPositionTime > dwChangeTime;
  6749. }
  6750.  
  6751. void CHARACTER::GiveRandomSkillBook()
  6752. {
  6753. LPITEM item = AutoGiveItem(50300);
  6754.  
  6755. if (NULL != item)
  6756. {
  6757. extern const DWORD GetRandomSkillVnum(BYTE bJob = JOB_MAX_NUM);
  6758. DWORD dwSkillVnum = 0;
  6759. // 50% of getting random books or getting one of the same player's race
  6760. if (!number(0, 1))
  6761. dwSkillVnum = GetRandomSkillVnum(GetJob());
  6762. else
  6763. dwSkillVnum = GetRandomSkillVnum();
  6764. item->SetSocket(0, dwSkillVnum);
  6765. }
  6766. }
  6767.  
  6768. void CHARACTER::ReviveInvisible(int iDur)
  6769. {
  6770. AddAffect(AFFECT_REVIVE_INVISIBLE, POINT_NONE, 0, AFF_REVIVE_INVISIBLE, iDur, 0, true);
  6771. }
  6772.  
  6773. void CHARACTER::ToggleMonsterLog()
  6774. {
  6775. m_bMonsterLog = !m_bMonsterLog;
  6776.  
  6777. if (m_bMonsterLog)
  6778. {
  6779. CHARACTER_MANAGER::instance().RegisterForMonsterLog(this);
  6780. }
  6781. else
  6782. {
  6783. CHARACTER_MANAGER::instance().UnregisterForMonsterLog(this);
  6784. }
  6785. }
  6786.  
  6787. void CHARACTER::SetGuild(CGuild* pGuild)
  6788. {
  6789. if (m_pGuild != pGuild)
  6790. {
  6791. m_pGuild = pGuild;
  6792. UpdatePacket();
  6793. }
  6794. }
  6795.  
  6796. void CHARACTER::SendGreetMessage()
  6797. {
  6798. __typeof(DBManager::instance().GetGreetMessage()) v = DBManager::instance().GetGreetMessage();
  6799.  
  6800. for (itertype(v) it = v.begin(); it != v.end(); ++it)
  6801. {
  6802. ChatPacket(CHAT_TYPE_NOTICE, it->c_str());
  6803. }
  6804. }
  6805.  
  6806. void CHARACTER::BeginStateEmpty()
  6807. {
  6808. MonsterLog("!");
  6809. }
  6810.  
  6811. void CHARACTER::EffectPacket(int enumEffectType)
  6812. {
  6813. TPacketGCSpecialEffect p;
  6814.  
  6815. p.header = HEADER_GC_SEPCIAL_EFFECT;
  6816. p.type = enumEffectType;
  6817. p.vid = GetVID();
  6818.  
  6819. PacketAround(&p, sizeof(TPacketGCSpecialEffect));
  6820. }
  6821.  
  6822. void CHARACTER::SpecificEffectPacket(const char filename[MAX_EFFECT_FILE_NAME])
  6823. {
  6824. TPacketGCSpecificEffect p;
  6825.  
  6826. p.header = HEADER_GC_SPECIFIC_EFFECT;
  6827. p.vid = GetVID();
  6828. memcpy (p.effect_file, filename, MAX_EFFECT_FILE_NAME);
  6829.  
  6830. PacketAround(&p, sizeof(TPacketGCSpecificEffect));
  6831. }
  6832.  
  6833. void CHARACTER::MonsterChat(BYTE bMonsterChatType)
  6834. {
  6835. if (IsPC())
  6836. return;
  6837.  
  6838. char sbuf[256+1];
  6839.  
  6840. if (IsMonster())
  6841. {
  6842. if (number(0, 60))
  6843. return;
  6844.  
  6845. snprintf(sbuf, sizeof(sbuf),
  6846. "(locale.monster_chat[%i] and locale.monster_chat[%i][%d] or '')",
  6847. GetRaceNum(), GetRaceNum(), bMonsterChatType*3 + number(1, 3));
  6848. }
  6849. else
  6850. {
  6851. if (bMonsterChatType != MONSTER_CHAT_WAIT)
  6852. return;
  6853.  
  6854. if (IsGuardNPC())
  6855. {
  6856. if (number(0, 6))
  6857. return;
  6858. }
  6859. else
  6860. {
  6861. if (number(0, 30))
  6862. return;
  6863. }
  6864.  
  6865. 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());
  6866. }
  6867.  
  6868. std::string text = quest::ScriptToString(sbuf);
  6869.  
  6870. if (text.empty())
  6871. return;
  6872.  
  6873. struct packet_chat pack_chat;
  6874.  
  6875. pack_chat.header = HEADER_GC_CHAT;
  6876. pack_chat.size = sizeof(struct packet_chat) + text.size() + 1;
  6877. pack_chat.type = CHAT_TYPE_TALKING;
  6878. pack_chat.id = GetVID();
  6879. pack_chat.bEmpire = 0;
  6880.  
  6881. TEMP_BUFFER buf;
  6882. buf.write(&pack_chat, sizeof(struct packet_chat));
  6883. buf.write(text.c_str(), text.size() + 1);
  6884.  
  6885. PacketAround(buf.read_peek(), buf.size());
  6886. }
  6887.  
  6888. void CHARACTER::SetQuestNPCID(DWORD vid)
  6889. {
  6890. m_dwQuestNPCVID = vid;
  6891. }
  6892.  
  6893. LPCHARACTER CHARACTER::GetQuestNPC() const
  6894. {
  6895. return CHARACTER_MANAGER::instance().Find(m_dwQuestNPCVID);
  6896. }
  6897.  
  6898. void CHARACTER::SetQuestItemPtr(LPITEM item)
  6899. {
  6900. m_pQuestItem = item;
  6901. }
  6902.  
  6903. void CHARACTER::ClearQuestItemPtr()
  6904. {
  6905. m_pQuestItem = NULL;
  6906. }
  6907.  
  6908. LPITEM CHARACTER::GetQuestItemPtr() const
  6909. {
  6910. return m_pQuestItem;
  6911. }
  6912.  
  6913. LPDUNGEON CHARACTER::GetDungeonForce() const
  6914. {
  6915. if (m_lWarpMapIndex > 10000)
  6916. return CDungeonManager::instance().FindByMapIndex(m_lWarpMapIndex);
  6917.  
  6918. return m_pkDungeon;
  6919. }
  6920.  
  6921. void CHARACTER::SetBlockMode(BYTE bFlag)
  6922. {
  6923. m_pointsInstant.bBlockMode = bFlag;
  6924.  
  6925. ChatPacket(CHAT_TYPE_COMMAND, "setblockmode %d", m_pointsInstant.bBlockMode);
  6926.  
  6927. SetQuestFlag("game_option.block_exchange", bFlag & BLOCK_EXCHANGE ? 1 : 0);
  6928. SetQuestFlag("game_option.block_party_invite", bFlag & BLOCK_PARTY_INVITE ? 1 : 0);
  6929. SetQuestFlag("game_option.block_guild_invite", bFlag & BLOCK_GUILD_INVITE ? 1 : 0);
  6930. SetQuestFlag("game_option.block_whisper", bFlag & BLOCK_WHISPER ? 1 : 0);
  6931. SetQuestFlag("game_option.block_messenger_invite", bFlag & BLOCK_MESSENGER_INVITE ? 1 : 0);
  6932. SetQuestFlag("game_option.block_party_request", bFlag & BLOCK_PARTY_REQUEST ? 1 : 0);
  6933. }
  6934.  
  6935. void CHARACTER::SetBlockModeForce(BYTE bFlag)
  6936. {
  6937. m_pointsInstant.bBlockMode = bFlag;
  6938. ChatPacket(CHAT_TYPE_COMMAND, "setblockmode %d", m_pointsInstant.bBlockMode);
  6939. }
  6940.  
  6941. bool CHARACTER::IsGuardNPC() const
  6942. {
  6943. return IsNPC() && (GetRaceNum() == 11000 || GetRaceNum() == 11002 || GetRaceNum() == 11004);
  6944. }
  6945.  
  6946. int CHARACTER::GetPolymorphPower() const
  6947. {
  6948. if (test_server)
  6949. {
  6950. int value = quest::CQuestManager::instance().GetEventFlag("poly");
  6951. if (value)
  6952. return value;
  6953. }
  6954. return aiPolymorphPowerByLevel[MINMAX(0, GetSkillLevel(SKILL_POLYMORPH), 40)];
  6955. }
  6956.  
  6957. void CHARACTER::SetPolymorph(DWORD dwRaceNum, bool bMaintainStat)
  6958. {
  6959. #ifdef ENABLE_WOLFMAN_CHARACTER
  6960. if (dwRaceNum < MAIN_RACE_MAX_NUM)
  6961. #else
  6962. if (dwRaceNum < JOB_MAX_NUM)
  6963. #endif
  6964. {
  6965. dwRaceNum = 0;
  6966. bMaintainStat = false;
  6967. }
  6968.  
  6969. if (m_dwPolymorphRace == dwRaceNum)
  6970. return;
  6971.  
  6972. m_bPolyMaintainStat = bMaintainStat;
  6973. m_dwPolymorphRace = dwRaceNum;
  6974.  
  6975. sys_log(0, "POLYMORPH: %s race %u ", GetName(), dwRaceNum);
  6976.  
  6977. if (dwRaceNum != 0)
  6978. StopRiding();
  6979.  
  6980. SET_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  6981. m_afAffectFlag.Set(AFF_SPAWN);
  6982.  
  6983. ViewReencode();
  6984.  
  6985. REMOVE_BIT(m_bAddChrState, ADD_CHARACTER_STATE_SPAWN);
  6986.  
  6987. if (!bMaintainStat)
  6988. {
  6989. PointChange(POINT_ST, 0);
  6990. PointChange(POINT_DX, 0);
  6991. PointChange(POINT_IQ, 0);
  6992. PointChange(POINT_HT, 0);
  6993. }
  6994.  
  6995. // Æú¸®¸ðÇÁ »óÅ¿¡¼­ Á×´Â °æ¿ì, Æú¸®¸ðÇÁ°¡ Ç®¸®°Ô µÇ´Âµ¥
  6996. // Æú¸® ¸ðÇÁ ÀüÈÄ·Î valid combo intervalÀÌ ´Ù¸£±â ¶§¹®¿¡
  6997. // Combo ÇÙ ¶Ç´Â Hacker·Î ÀνÄÇÏ´Â °æ¿ì°¡ ÀÖ´Ù.
  6998. // µû¶ó¼­ Æú¸®¸ðÇÁ¸¦ Ç®°Å³ª Æú¸®¸ðÇÁ ÇÏ°Ô µÇ¸é,
  6999. // valid combo intervalÀ» resetÇÑ´Ù.
  7000. SetValidComboInterval(0);
  7001. SetComboSequence(0);
  7002.  
  7003. ComputeBattlePoints();
  7004. }
  7005.  
  7006. int CHARACTER::GetQuestFlag(const std::string& flag) const
  7007. {
  7008. quest::CQuestManager& q = quest::CQuestManager::instance();
  7009. quest::PC* pPC = q.GetPC(GetPlayerID());
  7010. return pPC->GetFlag(flag);
  7011. }
  7012.  
  7013. void CHARACTER::SetQuestFlag(const std::string& flag, int value)
  7014. {
  7015. quest::CQuestManager& q = quest::CQuestManager::instance();
  7016. quest::PC* pPC = q.GetPC(GetPlayerID());
  7017. pPC->SetFlag(flag, value);
  7018. }
  7019.  
  7020. void CHARACTER::DetermineDropMetinStone()
  7021. {
  7022. #ifdef ENABLE_NEWSTUFF
  7023. if (g_NoDropMetinStone)
  7024. {
  7025. m_dwDropMetinStone = 0;
  7026. return;
  7027. }
  7028. #endif
  7029.  
  7030. static const DWORD c_adwMetin[] =
  7031. {
  7032. 28430,
  7033. 28431,
  7034. 28432,
  7035. 28433,
  7036. 28434,
  7037. 28435,
  7038. 28436,
  7039. 28437,
  7040. 28438,
  7041. 28439,
  7042. 28440,
  7043. 28441,
  7044. 28442,
  7045. 28443,
  7046. 28444,
  7047.  
  7048. };
  7049.  
  7050. DWORD stone_num = GetRaceNum();
  7051. int idx = std::lower_bound(aStoneDrop, aStoneDrop+STONE_INFO_MAX_NUM, stone_num) - aStoneDrop;
  7052. if (idx >= STONE_INFO_MAX_NUM || aStoneDrop[idx].dwMobVnum != stone_num)
  7053. {
  7054. m_dwDropMetinStone = 0;
  7055. }
  7056. else
  7057. {
  7058. const SStoneDropInfo & info = aStoneDrop[idx];
  7059. m_bDropMetinStonePct = info.iDropPct;
  7060. {
  7061. m_dwDropMetinStone = c_adwMetin[number(0, sizeof(c_adwMetin)/sizeof(DWORD) - 1)];
  7062. int iGradePct = number(1, 100);
  7063. for (int iStoneLevel = 0; iStoneLevel < STONE_LEVEL_MAX_NUM; iStoneLevel ++)
  7064. {
  7065. int iLevelGradePortion = info.iLevelPct[iStoneLevel];
  7066. if (iGradePct <= iLevelGradePortion)
  7067. {
  7068. break;
  7069. }
  7070. else
  7071. {
  7072. iGradePct -= iLevelGradePortion;
  7073. m_dwDropMetinStone += 0; // µ¹ +a -> +(a+1)ÀÌ µÉ¶§¸¶´Ù 100¾¿ Áõ°¡
  7074. }
  7075. }
  7076. }
  7077. }
  7078. }
  7079.  
  7080. void CHARACTER::SendEquipment(LPCHARACTER ch)
  7081. {
  7082. TPacketViewEquip p;
  7083. p.header = HEADER_GC_VIEW_EQUIP;
  7084. p.vid = GetVID();
  7085. for (int i = 0; i<WEAR_MAX_NUM; i++)
  7086. {
  7087. LPITEM item = GetWear(i);
  7088. if (item)
  7089. {
  7090. p.equips[i].vnum = item->GetVnum();
  7091. p.equips[i].count = item->GetCount();
  7092.  
  7093. thecore_memcpy(p.equips[i].alSockets, item->GetSockets(), sizeof(p.equips[i].alSockets));
  7094. thecore_memcpy(p.equips[i].aAttr, item->GetAttributes(), sizeof(p.equips[i].aAttr));
  7095. }
  7096. else
  7097. {
  7098. p.equips[i].vnum = 0;
  7099. }
  7100. }
  7101. ch->GetDesc()->Packet(&p, sizeof(p));
  7102. }
  7103.  
  7104.  
  7105. bool CHARACTER::CanSummon(int iLeaderShip)
  7106. {
  7107. return ((iLeaderShip >= 20) || ((iLeaderShip >= 12) && ((m_dwLastDeadTime + 180) > get_dword_time())));
  7108. }
  7109.  
  7110. #ifdef __BIOLOG_SYSTEM__
  7111. int CHARACTER::GetBiologState(const std::string& state) const
  7112. {
  7113. quest::CQuestManager& q = quest::CQuestManager::instance();
  7114. quest::PC* pPC = q.GetPC(GetPlayerID());
  7115. return pPC->GetFlag(state);
  7116. }
  7117.  
  7118. void CHARACTER::SetBiologState(const std::string& state, int szValue)
  7119. {
  7120. quest::CQuestManager& q = quest::CQuestManager::instance();
  7121. quest::PC* pPC = q.GetPC(GetPlayerID());
  7122. pPC->SetFlag(state, szValue);
  7123. }
  7124. #endif
  7125.  
  7126.  
  7127. void CHARACTER::MountVnum(DWORD vnum)
  7128. {
  7129. if (m_dwMountVnum == vnum)
  7130. return;
  7131. if ((m_dwMountVnum != 0)&&(vnum!=0)) //@fixme108 set recursively to 0 for eventuality
  7132. MountVnum(0);
  7133.  
  7134. m_dwMountVnum = vnum;
  7135. m_dwMountTime = get_dword_time();
  7136.  
  7137. if (m_bIsObserver)
  7138. return;
  7139.  
  7140. //NOTE : MountÇÑ´Ù°í ÇØ¼­ Client SideÀÇ °´Ã¼¸¦ »èÁ¦ÇÏÁø ¾Ê´Â´Ù.
  7141. //±×¸®°í ¼­¹öSide¿¡¼­ ÅÀÀ»¶§ À§Ä¡ À̵¿Àº ÇÏÁö ¾Ê´Â´Ù. ¿Ö³ÄÇϸé Client Side¿¡¼­ Coliision Adjust¸¦ ÇÒ¼ö Àִµ¥
  7142. //°´Ã¼¸¦ ¼Ò¸ê½ÃÄ×´Ù°¡ ¼­¹öÀ§Ä¡·Î À̵¿½Ã۸é À̶§ collision check¸¦ ÇÏÁö´Â ¾ÊÀ¸¹Ç·Î ¹è°æ¿¡ ³¢°Å³ª ¶Õ°í ³ª°¡´Â ¹®Á¦°¡ Á¸ÀçÇÑ´Ù.
  7143. m_posDest.x = m_posStart.x = GetX();
  7144. m_posDest.y = m_posStart.y = GetY();
  7145. //EncodeRemovePacket(this);
  7146. EncodeInsertPacket(this);
  7147.  
  7148. ENTITY_MAP::iterator it = m_map_view.begin();
  7149.  
  7150. while (it != m_map_view.end())
  7151. {
  7152. LPENTITY entity = (it++)->first;
  7153.  
  7154. //MountÇÑ´Ù°í ÇØ¼­ Client SideÀÇ °´Ã¼¸¦ »èÁ¦ÇÏÁø ¾Ê´Â´Ù.
  7155. //EncodeRemovePacket(entity);
  7156. //if (!m_bIsObserver)
  7157. EncodeInsertPacket(entity);
  7158.  
  7159. //if (!entity->IsObserverMode())
  7160. // entity->EncodeInsertPacket(this);
  7161. }
  7162.  
  7163. SetValidComboInterval(0);
  7164. SetComboSequence(0);
  7165.  
  7166. ComputePoints();
  7167. }
  7168.  
  7169. namespace {
  7170. class FuncCheckWarp
  7171. {
  7172. public:
  7173. FuncCheckWarp(LPCHARACTER pkWarp)
  7174. {
  7175. m_lTargetY = 0;
  7176. m_lTargetX = 0;
  7177.  
  7178. m_lX = pkWarp->GetX();
  7179. m_lY = pkWarp->GetY();
  7180.  
  7181. m_bInvalid = false;
  7182. m_bEmpire = pkWarp->GetEmpire();
  7183.  
  7184. char szTmp[64];
  7185.  
  7186. if (3 != sscanf(pkWarp->GetName(), " %s %ld %ld ", szTmp, &m_lTargetX, &m_lTargetY))
  7187. {
  7188. if (number(1, 100) < 5)
  7189. sys_err("Warp NPC name wrong : vnum(%d) name(%s)", pkWarp->GetRaceNum(), pkWarp->GetName());
  7190.  
  7191. m_bInvalid = true;
  7192.  
  7193. return;
  7194. }
  7195.  
  7196. m_lTargetX *= 100;
  7197. m_lTargetY *= 100;
  7198.  
  7199. m_bUseWarp = true;
  7200.  
  7201. if (pkWarp->IsGoto())
  7202. {
  7203. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(pkWarp->GetMapIndex());
  7204. m_lTargetX += pkSectreeMap->m_setting.iBaseX;
  7205. m_lTargetY += pkSectreeMap->m_setting.iBaseY;
  7206. m_bUseWarp = false;
  7207. }
  7208. }
  7209.  
  7210. bool Valid()
  7211. {
  7212. return !m_bInvalid;
  7213. }
  7214.  
  7215. void operator () (LPENTITY ent)
  7216. {
  7217. if (!Valid())
  7218. return;
  7219.  
  7220. if (!ent->IsType(ENTITY_CHARACTER))
  7221. return;
  7222.  
  7223. LPCHARACTER pkChr = (LPCHARACTER) ent;
  7224.  
  7225. if (!pkChr->IsPC())
  7226. return;
  7227.  
  7228. int iDist = DISTANCE_APPROX(pkChr->GetX() - m_lX, pkChr->GetY() - m_lY);
  7229.  
  7230. if (iDist > 300)
  7231. return;
  7232.  
  7233. if (m_bEmpire && pkChr->GetEmpire() && m_bEmpire != pkChr->GetEmpire())
  7234. return;
  7235.  
  7236. if (pkChr->IsHack())
  7237. return;
  7238.  
  7239. if (!pkChr->CanHandleItem(false, true))
  7240. return;
  7241.  
  7242. if (m_bUseWarp)
  7243. pkChr->WarpSet(m_lTargetX, m_lTargetY);
  7244. else
  7245. {
  7246. pkChr->Show(pkChr->GetMapIndex(), m_lTargetX, m_lTargetY);
  7247. pkChr->Stop();
  7248. }
  7249. }
  7250.  
  7251. bool m_bInvalid;
  7252. bool m_bUseWarp;
  7253.  
  7254. long m_lX;
  7255. long m_lY;
  7256. long m_lTargetX;
  7257. long m_lTargetY;
  7258.  
  7259. BYTE m_bEmpire;
  7260. };
  7261. }
  7262.  
  7263. EVENTFUNC(warp_npc_event)
  7264. {
  7265. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  7266. if ( info == NULL )
  7267. {
  7268. sys_err( "warp_npc_event> <Factor> Null pointer" );
  7269. return 0;
  7270. }
  7271.  
  7272. LPCHARACTER ch = info->ch;
  7273.  
  7274. if (ch == NULL) { // <Factor>
  7275. return 0;
  7276. }
  7277.  
  7278. if (!ch->GetSectree())
  7279. {
  7280. ch->m_pkWarpNPCEvent = NULL;
  7281. return 0;
  7282. }
  7283.  
  7284. FuncCheckWarp f(ch);
  7285. if (f.Valid())
  7286. ch->GetSectree()->ForEachAround(f);
  7287.  
  7288. return passes_per_sec / 2;
  7289. }
  7290.  
  7291. void CHARACTER::ChannelSwitch(int new_ch){
  7292. long lAddr;
  7293. long lMapIndex;
  7294. WORD wPort;
  7295. long x = this->GetX();
  7296. long y = this->GetY();
  7297.  
  7298. if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort))
  7299. {
  7300. sys_err("cannot find map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
  7301. return;
  7302. }
  7303. if(lMapIndex >= 10000){
  7304. return;
  7305. }
  7306.  
  7307. std::map<WORD, int>micha;
  7308.  
  7309. micha[13001] = 1;
  7310. micha[13002] = 1;
  7311. micha[13003] = 1;
  7312.  
  7313. micha[13101] = 2;
  7314. micha[13102] = 2;
  7315. micha[13103] = 2;
  7316.  
  7317. micha[13201] = 3;
  7318. micha[13202] = 3;
  7319. micha[13203] = 3;
  7320.  
  7321. micha[13301] = 4;
  7322. micha[13302] = 4;
  7323. micha[13303] = 4;
  7324.  
  7325. // micha[13402] = 5;
  7326. // micha[13408] = 5;
  7327.  
  7328. // micha[13502] = 6;
  7329. // micha[13508] = 6;
  7330.  
  7331. //micha[13002] = 1;
  7332. int chan;
  7333. if(micha.find(wPort) != micha.end()){
  7334. chan = micha[wPort];
  7335. }else{return;}
  7336. Stop();
  7337. Save();
  7338.  
  7339. if(GetSectree()){
  7340. GetSectree()->RemoveEntity(this);
  7341. ViewCleanup();
  7342. EncodeRemovePacket(this);
  7343. }
  7344. TPacketGCWarp p;
  7345.  
  7346. p.bHeader = HEADER_GC_WARP;
  7347. p.lX = x;
  7348. p.lY = y;
  7349. p.lAddr = lAddr;
  7350. p.wPort = (wPort - 100*(chan-1) + 100*(new_ch-1));
  7351.  
  7352.  
  7353. GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
  7354. }
  7355.  
  7356.  
  7357. void CHARACTER::StartWarpNPCEvent()
  7358. {
  7359. if (m_pkWarpNPCEvent)
  7360. return;
  7361.  
  7362. if (!IsWarp() && !IsGoto())
  7363. return;
  7364.  
  7365. char_event_info* info = AllocEventInfo<char_event_info>();
  7366.  
  7367. info->ch = this;
  7368.  
  7369. m_pkWarpNPCEvent = event_create(warp_npc_event, info, passes_per_sec / 2);
  7370. }
  7371.  
  7372. void CHARACTER::SyncPacket()
  7373. {
  7374. TEMP_BUFFER buf;
  7375.  
  7376. TPacketCGSyncPositionElement elem;
  7377.  
  7378. elem.dwVID = GetVID();
  7379. elem.lX = GetX();
  7380. elem.lY = GetY();
  7381.  
  7382. TPacketGCSyncPosition pack;
  7383.  
  7384. pack.bHeader = HEADER_GC_SYNC_POSITION;
  7385. pack.wSize = sizeof(TPacketGCSyncPosition) + sizeof(elem);
  7386.  
  7387. buf.write(&pack, sizeof(pack));
  7388. buf.write(&elem, sizeof(elem));
  7389.  
  7390. PacketAround(buf.read_peek(), buf.size());
  7391. }
  7392.  
  7393. LPCHARACTER CHARACTER::GetMarryPartner() const
  7394. {
  7395. return m_pkChrMarried;
  7396. }
  7397.  
  7398. void CHARACTER::SetMarryPartner(LPCHARACTER ch)
  7399. {
  7400. m_pkChrMarried = ch;
  7401. }
  7402.  
  7403. int CHARACTER::GetMarriageBonus(DWORD dwItemVnum, bool bSum)
  7404. {
  7405. if (IsNPC())
  7406. return 0;
  7407.  
  7408. marriage::TMarriage* pMarriage = marriage::CManager::instance().Get(GetPlayerID());
  7409.  
  7410. if (!pMarriage)
  7411. return 0;
  7412.  
  7413. return pMarriage->GetBonus(dwItemVnum, bSum, this);
  7414. }
  7415.  
  7416. void CHARACTER::ConfirmWithMsg(const char* szMsg, int iTimeout, DWORD dwRequestPID)
  7417. {
  7418. if (!IsPC())
  7419. return;
  7420.  
  7421. TPacketGCQuestConfirm p;
  7422.  
  7423. p.header = HEADER_GC_QUEST_CONFIRM;
  7424. p.requestPID = dwRequestPID;
  7425. p.timeout = iTimeout;
  7426. strlcpy(p.msg, szMsg, sizeof(p.msg));
  7427.  
  7428. GetDesc()->Packet(&p, sizeof(p));
  7429. }
  7430.  
  7431. int CHARACTER::GetPremiumRemainSeconds(BYTE bType) const
  7432. {
  7433. if (bType >= PREMIUM_MAX_NUM)
  7434. return 0;
  7435.  
  7436. return m_aiPremiumTimes[bType] - get_global_time();
  7437. }
  7438.  
  7439. bool CHARACTER::WarpToPID(DWORD dwPID)
  7440. {
  7441. LPCHARACTER victim;
  7442. if ((victim = (CHARACTER_MANAGER::instance().FindByPID(dwPID))))
  7443. {
  7444. int mapIdx = victim->GetMapIndex();
  7445. if (IS_SUMMONABLE_ZONE(mapIdx))
  7446. {
  7447. if (CAN_ENTER_ZONE(this, mapIdx))
  7448. {
  7449. WarpSet(victim->GetX(), victim->GetY());
  7450. }
  7451. else
  7452. {
  7453. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ÀÖ´Â °÷À¸·Î ¿öÇÁÇÒ ¼ö ¾ø½À´Ï´Ù."));
  7454. return false;
  7455. }
  7456. }
  7457. else
  7458. {
  7459. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ÀÖ´Â °÷À¸·Î ¿öÇÁÇÒ ¼ö ¾ø½À´Ï´Ù."));
  7460. return false;
  7461. }
  7462. }
  7463. else
  7464. {
  7465. // ´Ù¸¥ ¼­¹ö¿¡ ·Î±×ÀÎµÈ »ç¶÷ÀÌ ÀÖÀ½ -> ¸Þ½ÃÁö º¸³» ÁÂÇ¥¸¦ ¹Þ¾Æ¿ÀÀÚ
  7466. // 1. A.pid, B.pid ¸¦ »Ñ¸²
  7467. // 2. B.pid¸¦ °¡Áø ¼­¹ö°¡ »Ñ¸°¼­¹ö¿¡°Ô A.pid, ÁÂÇ¥ ¸¦ º¸³¿
  7468. // 3. ¿öÇÁ
  7469. CCI * pcci = P2P_MANAGER::instance().FindByPID(dwPID);
  7470.  
  7471. if (!pcci)
  7472. {
  7473. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ¿Â¶óÀÎ »óŰ¡ ¾Æ´Õ´Ï´Ù."));
  7474. return false;
  7475. }
  7476.  
  7477. if (pcci->bChannel != g_bChannel)
  7478. {
  7479. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ %d ä³Î¿¡ ÀÖ½À´Ï´Ù. (ÇöÀç ä³Î %d)"), pcci->bChannel, g_bChannel);
  7480. return false;
  7481. }
  7482. else if (false == IS_SUMMONABLE_ZONE(pcci->lMapIndex))
  7483. {
  7484. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ÀÖ´Â °÷À¸·Î ¿öÇÁÇÒ ¼ö ¾ø½À´Ï´Ù."));
  7485. return false;
  7486. }
  7487. else
  7488. {
  7489. if (!CAN_ENTER_ZONE(this, pcci->lMapIndex))
  7490. {
  7491. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ÀÖ´Â °÷À¸·Î ¿öÇÁÇÒ ¼ö ¾ø½À´Ï´Ù."));
  7492. return false;
  7493. }
  7494.  
  7495. TPacketGGFindPosition p;
  7496. p.header = HEADER_GG_FIND_POSITION;
  7497. p.dwFromPID = GetPlayerID();
  7498. p.dwTargetPID = dwPID;
  7499. pcci->pkDesc->Packet(&p, sizeof(TPacketGGFindPosition));
  7500.  
  7501. if (test_server)
  7502. ChatPacket(CHAT_TYPE_PARTY, "sent find position packet for teleport");
  7503. }
  7504. }
  7505. return true;
  7506. }
  7507.  
  7508. // ADD_REFINE_BUILDING
  7509. CGuild* CHARACTER::GetRefineGuild() const
  7510. {
  7511. LPCHARACTER chRefineNPC = CHARACTER_MANAGER::instance().Find(m_dwRefineNPCVID);
  7512.  
  7513. return (chRefineNPC ? chRefineNPC->GetGuild() : NULL);
  7514. }
  7515.  
  7516. bool CHARACTER::IsRefineThroughGuild() const
  7517. {
  7518. return GetRefineGuild() != NULL;
  7519. }
  7520.  
  7521. int CHARACTER::ComputeRefineFee(int iCost, int iMultiply) const
  7522. {
  7523. CGuild* pGuild = GetRefineGuild();
  7524. if (pGuild)
  7525. {
  7526. if (pGuild == GetGuild())
  7527. return iCost * iMultiply * 9 / 10;
  7528.  
  7529. // ´Ù¸¥ Á¦±¹ »ç¶÷ÀÌ ½ÃµµÇÏ´Â °æ¿ì Ãß°¡·Î 3¹è ´õ
  7530. LPCHARACTER chRefineNPC = CHARACTER_MANAGER::instance().Find(m_dwRefineNPCVID);
  7531. if (chRefineNPC && chRefineNPC->GetEmpire() != GetEmpire())
  7532. return iCost * iMultiply * 3;
  7533.  
  7534. return iCost * iMultiply;
  7535. }
  7536. else
  7537. return iCost;
  7538. }
  7539.  
  7540. void CHARACTER::PayRefineFee(int iTotalMoney)
  7541. {
  7542. int iFee = iTotalMoney / 10;
  7543. CGuild* pGuild = GetRefineGuild();
  7544.  
  7545. int iRemain = iTotalMoney;
  7546.  
  7547. if (pGuild)
  7548. {
  7549. // Àڱ⠱æµåÀ̸é iTotalMoney¿¡ ÀÌ¹Ì 10%°¡ Á¦¿ÜµÇ¾îÀÖ´Ù
  7550. if (pGuild != GetGuild())
  7551. {
  7552. pGuild->RequestDepositMoney(this, iFee);
  7553. iRemain -= iFee;
  7554. }
  7555. }
  7556.  
  7557. PointChange(POINT_GOLD, -iRemain);
  7558. }
  7559. // END_OF_ADD_REFINE_BUILDING
  7560.  
  7561. //Hack ¹æÁö¸¦ À§ÇÑ Ã¼Å©.
  7562. bool CHARACTER::IsHack(bool bSendMsg, bool bCheckShopOwner, int limittime)
  7563. {
  7564. const int iPulse = thecore_pulse();
  7565.  
  7566. if (test_server)
  7567. bSendMsg = true;
  7568.  
  7569. //â°í ¿¬ÈÄ Ã¼Å©
  7570. if (iPulse - GetSafeboxLoadTime() < PASSES_PER_SEC(limittime))
  7571. {
  7572. if (bSendMsg)
  7573. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("â°í¸¦ ¿¬ÈÄ %dÃÊ À̳»¿¡´Â ´Ù¸¥°÷À¸·Î À̵¿ÇÒ¼ö ¾ø½À´Ï´Ù."), limittime);
  7574.  
  7575. if (test_server)
  7576. ChatPacket(CHAT_TYPE_INFO, "[TestOnly]Pulse %d LoadTime %d PASS %d", iPulse, GetSafeboxLoadTime(), PASSES_PER_SEC(limittime));
  7577. return true;
  7578. }
  7579.  
  7580. //°Å·¡°ü·Ã â üũ
  7581. if (bCheckShopOwner)
  7582. {
  7583. if (GetExchange() || GetMyShop() || GetShopOwner() || IsOpenSafebox() || IsCubeOpen()
  7584. #if defined(WHEEL_OF_DESTINY)
  7585. || GetWheelDestiny()
  7586. #endif
  7587. )
  7588. {
  7589. if (bSendMsg)
  7590. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡Ã¢,â°í µîÀ» ¿¬ »óÅ¿¡¼­´Â ´Ù¸¥°÷À¸·Î À̵¿,Á¾·á ÇÒ¼ö ¾ø½À´Ï´Ù"));
  7591.  
  7592. return true;
  7593. }
  7594. }
  7595. else
  7596. {
  7597. if (GetExchange() || GetMyShop() || IsOpenSafebox() || IsCubeOpen()
  7598. #if defined(WHEEL_OF_DESTINY)
  7599. || GetWheelDestiny()
  7600. #endif
  7601. )
  7602. {
  7603. if (bSendMsg)
  7604. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡Ã¢,â°í µîÀ» ¿¬ »óÅ¿¡¼­´Â ´Ù¸¥°÷À¸·Î À̵¿,Á¾·á ÇÒ¼ö ¾ø½À´Ï´Ù"));
  7605.  
  7606. return true;
  7607. }
  7608. }
  7609.  
  7610. //PREVENT_PORTAL_AFTER_EXCHANGE
  7611. //±³È¯ ÈÄ ½Ã°£Ã¼Å©
  7612. if (iPulse - GetExchangeTime() < PASSES_PER_SEC(limittime))
  7613. {
  7614. if (bSendMsg)
  7615. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡ ÈÄ %dÃÊ À̳»¿¡´Â ´Ù¸¥Áö¿ªÀ¸·Î À̵¿ ÇÒ ¼ö ¾ø½À´Ï´Ù."), limittime );
  7616. return true;
  7617. }
  7618. //END_PREVENT_PORTAL_AFTER_EXCHANGE
  7619.  
  7620. //PREVENT_ITEM_COPY
  7621. if (iPulse - GetMyShopTime() < PASSES_PER_SEC(limittime))
  7622. {
  7623. if (bSendMsg)
  7624. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡ ÈÄ %dÃÊ À̳»¿¡´Â ´Ù¸¥Áö¿ªÀ¸·Î À̵¿ ÇÒ ¼ö ¾ø½À´Ï´Ù."), limittime);
  7625. return true;
  7626. }
  7627.  
  7628. if (iPulse - GetRefineTime() < PASSES_PER_SEC(limittime))
  7629. {
  7630. if (bSendMsg)
  7631. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾ÆÀÌÅÛ °³·®ÈÄ %dÃÊ À̳»¿¡´Â ±ÍȯºÎ,±Íȯ±â¾ïºÎ¸¦ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù."), limittime);
  7632. return true;
  7633. }
  7634. //END_PREVENT_ITEM_COPY
  7635.  
  7636. return false;
  7637. }
  7638.  
  7639. BOOL CHARACTER::IsMonarch() const
  7640. {
  7641. //MONARCH_LIMIT
  7642. if (CMonarch::instance().IsMonarch(GetPlayerID(), GetEmpire()))
  7643. return true;
  7644.  
  7645. return false;
  7646.  
  7647. //END_MONARCH_LIMIT
  7648. }
  7649. void CHARACTER::Say(const std::string & s)
  7650. {
  7651. struct ::packet_script packet_script;
  7652.  
  7653. packet_script.header = HEADER_GC_SCRIPT;
  7654. packet_script.skin = 1;
  7655. packet_script.src_size = s.size();
  7656. packet_script.size = packet_script.src_size + sizeof(struct packet_script);
  7657.  
  7658. TEMP_BUFFER buf;
  7659.  
  7660. buf.write(&packet_script, sizeof(struct packet_script));
  7661. buf.write(&s[0], s.size());
  7662.  
  7663. if (IsPC())
  7664. {
  7665. GetDesc()->Packet(buf.read_peek(), buf.size());
  7666. }
  7667. }
  7668.  
  7669. //
  7670. // Monarch
  7671. //
  7672. void CHARACTER::InitMC()
  7673. {
  7674. for (int n = 0; n < MI_MAX; ++n)
  7675. {
  7676. m_dwMonarchCooltime[n] = thecore_pulse();
  7677. }
  7678.  
  7679. m_dwMonarchCooltimelimit[MI_HEAL] = PASSES_PER_SEC(MC_HEAL);
  7680. m_dwMonarchCooltimelimit[MI_WARP] = PASSES_PER_SEC(MC_WARP);
  7681. m_dwMonarchCooltimelimit[MI_TRANSFER] = PASSES_PER_SEC(MC_TRANSFER);
  7682. m_dwMonarchCooltimelimit[MI_TAX] = PASSES_PER_SEC(MC_TAX);
  7683. m_dwMonarchCooltimelimit[MI_SUMMON] = PASSES_PER_SEC(MC_SUMMON);
  7684.  
  7685. m_dwMonarchCooltime[MI_HEAL] -= PASSES_PER_SEC(GetMCL(MI_HEAL));
  7686. m_dwMonarchCooltime[MI_WARP] -= PASSES_PER_SEC(GetMCL(MI_WARP));
  7687. m_dwMonarchCooltime[MI_TRANSFER] -= PASSES_PER_SEC(GetMCL(MI_TRANSFER));
  7688. m_dwMonarchCooltime[MI_TAX] -= PASSES_PER_SEC(GetMCL(MI_TAX));
  7689. m_dwMonarchCooltime[MI_SUMMON] -= PASSES_PER_SEC(GetMCL(MI_SUMMON));
  7690. }
  7691.  
  7692. DWORD CHARACTER::GetMC(enum MONARCH_INDEX e) const
  7693. {
  7694. return m_dwMonarchCooltime[e];
  7695. }
  7696.  
  7697. void CHARACTER::SetMC(enum MONARCH_INDEX e)
  7698. {
  7699. m_dwMonarchCooltime[e] = thecore_pulse();
  7700. }
  7701.  
  7702. bool CHARACTER::IsMCOK(enum MONARCH_INDEX e) const
  7703. {
  7704. int iPulse = thecore_pulse();
  7705.  
  7706. if ((iPulse - GetMC(e)) < GetMCL(e))
  7707. {
  7708. if (test_server)
  7709. sys_log(0, " Pulse %d cooltime %d, limit %d", iPulse, GetMC(e), GetMCL(e));
  7710.  
  7711. return false;
  7712. }
  7713.  
  7714. if (test_server)
  7715. sys_log(0, " Pulse %d cooltime %d, limit %d", iPulse, GetMC(e), GetMCL(e));
  7716.  
  7717. return true;
  7718. }
  7719.  
  7720. DWORD CHARACTER::GetMCL(enum MONARCH_INDEX e) const
  7721. {
  7722. return m_dwMonarchCooltimelimit[e];
  7723. }
  7724.  
  7725. DWORD CHARACTER::GetMCLTime(enum MONARCH_INDEX e) const
  7726. {
  7727. int iPulse = thecore_pulse();
  7728.  
  7729. if (test_server)
  7730. sys_log(0, " Pulse %d cooltime %d, limit %d", iPulse, GetMC(e), GetMCL(e));
  7731.  
  7732. return (GetMCL(e)) / passes_per_sec - (iPulse - GetMC(e)) / passes_per_sec;
  7733. }
  7734.  
  7735. bool CHARACTER::IsSiegeNPC() const
  7736. {
  7737. return IsNPC() && (GetRaceNum() == 11000 || GetRaceNum() == 11002 || GetRaceNum() == 11004);
  7738. }
  7739.  
  7740. //------------------------------------------------
  7741. void CHARACTER::UpdateDepositPulse()
  7742. {
  7743. m_deposit_pulse = thecore_pulse() + PASSES_PER_SEC(60*5); // 5ºÐ
  7744. }
  7745.  
  7746. bool CHARACTER::CanDeposit() const
  7747. {
  7748. return (m_deposit_pulse == 0 || (m_deposit_pulse < thecore_pulse()));
  7749. }
  7750. //------------------------------------------------
  7751.  
  7752. ESex GET_SEX(LPCHARACTER ch)
  7753. {
  7754. switch (ch->GetRaceNum())
  7755. {
  7756. case MAIN_RACE_WARRIOR_M:
  7757. case MAIN_RACE_SURA_M:
  7758. case MAIN_RACE_ASSASSIN_M:
  7759. case MAIN_RACE_SHAMAN_M:
  7760. #ifdef ENABLE_WOLFMAN_CHARACTER
  7761. case MAIN_RACE_WOLFMAN_M:
  7762. #endif
  7763. return SEX_MALE;
  7764.  
  7765. case MAIN_RACE_ASSASSIN_W:
  7766. case MAIN_RACE_SHAMAN_W:
  7767. case MAIN_RACE_WARRIOR_W:
  7768. case MAIN_RACE_SURA_W:
  7769. return SEX_FEMALE;
  7770. }
  7771.  
  7772. /* default sex = male */
  7773. return SEX_MALE;
  7774. }
  7775.  
  7776. int CHARACTER::GetHPPct() const
  7777. {
  7778. if (GetMaxHP() <= 0) // @fixme136
  7779. return 0;
  7780. return (GetHP() * 100) / GetMaxHP();
  7781. }
  7782.  
  7783. bool CHARACTER::IsBerserk() const
  7784. {
  7785. if (m_pkMobInst != NULL)
  7786. return m_pkMobInst->m_IsBerserk;
  7787. else
  7788. return false;
  7789. }
  7790.  
  7791. void CHARACTER::SetBerserk(bool mode)
  7792. {
  7793. if (m_pkMobInst != NULL)
  7794. m_pkMobInst->m_IsBerserk = mode;
  7795. }
  7796.  
  7797. bool CHARACTER::IsGodSpeed() const
  7798. {
  7799. if (m_pkMobInst != NULL)
  7800. {
  7801. return m_pkMobInst->m_IsGodSpeed;
  7802. }
  7803. else
  7804. {
  7805. return false;
  7806. }
  7807. }
  7808.  
  7809. void CHARACTER::SetGodSpeed(bool mode)
  7810. {
  7811. if (m_pkMobInst != NULL)
  7812. {
  7813. m_pkMobInst->m_IsGodSpeed = mode;
  7814.  
  7815. if (mode == true)
  7816. {
  7817. SetPoint(POINT_ATT_SPEED, 250);
  7818. }
  7819. else
  7820. {
  7821. SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed);
  7822. }
  7823. }
  7824. }
  7825.  
  7826. bool CHARACTER::IsDeathBlow() const
  7827. {
  7828. if (number(1, 100) <= m_pkMobData->m_table.bDeathBlowPoint)
  7829. {
  7830. return true;
  7831. }
  7832. else
  7833. {
  7834. return false;
  7835. }
  7836. }
  7837.  
  7838. struct FFindReviver
  7839. {
  7840. FFindReviver()
  7841. {
  7842. pChar = NULL;
  7843. HasReviver = false;
  7844. }
  7845.  
  7846. void operator() (LPCHARACTER ch)
  7847. {
  7848. if (ch->IsMonster() != true)
  7849. {
  7850. return;
  7851. }
  7852.  
  7853. if (ch->IsReviver() == true && pChar != ch && ch->IsDead() != true)
  7854. {
  7855. if (number(1, 100) <= ch->GetMobTable().bRevivePoint)
  7856. {
  7857. HasReviver = true;
  7858. pChar = ch;
  7859. }
  7860. }
  7861. }
  7862.  
  7863. LPCHARACTER pChar;
  7864. bool HasReviver;
  7865. };
  7866.  
  7867. bool CHARACTER::HasReviverInParty() const
  7868. {
  7869. LPPARTY party = GetParty();
  7870.  
  7871. if (party != NULL)
  7872. {
  7873. if (party->GetMemberCount() == 1) return false;
  7874.  
  7875. FFindReviver f;
  7876. party->ForEachMemberPtr(f);
  7877. return f.HasReviver;
  7878. }
  7879.  
  7880. return false;
  7881. }
  7882.  
  7883. bool CHARACTER::IsRevive() const
  7884. {
  7885. if (m_pkMobInst != NULL)
  7886. {
  7887. return m_pkMobInst->m_IsRevive;
  7888. }
  7889.  
  7890. return false;
  7891. }
  7892.  
  7893. void CHARACTER::SetRevive(bool mode)
  7894. {
  7895. if (m_pkMobInst != NULL)
  7896. {
  7897. m_pkMobInst->m_IsRevive = mode;
  7898. }
  7899. }
  7900.  
  7901. #define IS_SPEED_HACK_PLAYER(ch) (ch->m_speed_hack_count > SPEEDHACK_LIMIT_COUNT)
  7902.  
  7903. EVENTFUNC(check_speedhack_event)
  7904. {
  7905. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  7906. if ( info == NULL )
  7907. {
  7908. sys_err( "check_speedhack_event> <Factor> Null pointer" );
  7909. return 0;
  7910. }
  7911.  
  7912. LPCHARACTER ch = info->ch;
  7913.  
  7914. if (NULL == ch || ch->IsNPC())
  7915. return 0;
  7916.  
  7917. if (IS_SPEED_HACK_PLAYER(ch))
  7918. {
  7919. // write hack log
  7920. LogManager::instance().SpeedHackLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(), ch->m_speed_hack_count);
  7921.  
  7922. if (g_bEnableSpeedHackCrash)
  7923. {
  7924. // close connection
  7925. LPDESC desc = ch->GetDesc();
  7926.  
  7927. if (desc)
  7928. {
  7929. DESC_MANAGER::instance().DestroyDesc(desc);
  7930. return 0;
  7931. }
  7932. }
  7933. }
  7934.  
  7935. ch->m_speed_hack_count = 0;
  7936.  
  7937. ch->ResetComboHackCount();
  7938. return PASSES_PER_SEC(60);
  7939. }
  7940.  
  7941. void CHARACTER::StartCheckSpeedHackEvent()
  7942. {
  7943. if (m_pkCheckSpeedHackEvent)
  7944. return;
  7945.  
  7946. char_event_info* info = AllocEventInfo<char_event_info>();
  7947.  
  7948. info->ch = this;
  7949.  
  7950. m_pkCheckSpeedHackEvent = event_create(check_speedhack_event, info, PASSES_PER_SEC(60)); // 1ºÐ
  7951. }
  7952.  
  7953. void CHARACTER::GoHome()
  7954. {
  7955. WarpSet(EMPIRE_START_X(GetEmpire()), EMPIRE_START_Y(GetEmpire()));
  7956. }
  7957.  
  7958. void CHARACTER::SendGuildName(CGuild* pGuild)
  7959. {
  7960. if (NULL == pGuild) return;
  7961.  
  7962. DESC *desc = GetDesc();
  7963.  
  7964. if (NULL == desc) return;
  7965. if (m_known_guild.find(pGuild->GetID()) != m_known_guild.end()) return;
  7966.  
  7967. m_known_guild.insert(pGuild->GetID());
  7968.  
  7969. TPacketGCGuildName pack;
  7970. memset(&pack, 0x00, sizeof(pack));
  7971.  
  7972. pack.header = HEADER_GC_GUILD;
  7973. pack.subheader = GUILD_SUBHEADER_GC_GUILD_NAME;
  7974. pack.size = sizeof(TPacketGCGuildName);
  7975. pack.guildID = pGuild->GetID();
  7976. memcpy(pack.guildName, pGuild->GetName(), GUILD_NAME_MAX_LEN);
  7977.  
  7978. desc->Packet(&pack, sizeof(pack));
  7979. }
  7980.  
  7981. void CHARACTER::SendGuildName(DWORD dwGuildID)
  7982. {
  7983. SendGuildName(CGuildManager::instance().FindGuild(dwGuildID));
  7984. }
  7985.  
  7986. EVENTFUNC(destroy_when_idle_event)
  7987. {
  7988. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  7989. if ( info == NULL )
  7990. {
  7991. sys_err( "destroy_when_idle_event> <Factor> Null pointer" );
  7992. return 0;
  7993. }
  7994.  
  7995. LPCHARACTER ch = info->ch;
  7996. if (ch == NULL) { // <Factor>
  7997. return 0;
  7998. }
  7999.  
  8000. if (ch->GetVictim())
  8001. {
  8002. return PASSES_PER_SEC(300);
  8003. }
  8004.  
  8005. sys_log(1, "DESTROY_WHEN_IDLE: %s", ch->GetName());
  8006.  
  8007. ch->m_pkDestroyWhenIdleEvent = NULL;
  8008. M2_DESTROY_CHARACTER(ch);
  8009. return 0;
  8010. }
  8011.  
  8012. void CHARACTER::StartDestroyWhenIdleEvent()
  8013. {
  8014. if (m_pkDestroyWhenIdleEvent)
  8015. return;
  8016.  
  8017. char_event_info* info = AllocEventInfo<char_event_info>();
  8018.  
  8019. info->ch = this;
  8020.  
  8021. m_pkDestroyWhenIdleEvent = event_create(destroy_when_idle_event, info, PASSES_PER_SEC(300));
  8022. }
  8023.  
  8024. void CHARACTER::SetComboSequence(BYTE seq)
  8025. {
  8026. m_bComboSequence = seq;
  8027. }
  8028.  
  8029. BYTE CHARACTER::GetComboSequence() const
  8030. {
  8031. return m_bComboSequence;
  8032. }
  8033.  
  8034. void CHARACTER::SetLastComboTime(DWORD time)
  8035. {
  8036. m_dwLastComboTime = time;
  8037. }
  8038.  
  8039. DWORD CHARACTER::GetLastComboTime() const
  8040. {
  8041. return m_dwLastComboTime;
  8042. }
  8043.  
  8044. void CHARACTER::SetValidComboInterval(int interval)
  8045. {
  8046. m_iValidComboInterval = interval;
  8047. }
  8048.  
  8049. int CHARACTER::GetValidComboInterval() const
  8050. {
  8051. return m_iValidComboInterval;
  8052. }
  8053.  
  8054. BYTE CHARACTER::GetComboIndex() const
  8055. {
  8056. return m_bComboIndex;
  8057. }
  8058.  
  8059. void CHARACTER::IncreaseComboHackCount(int k)
  8060. {
  8061. m_iComboHackCount += k;
  8062.  
  8063. if (m_iComboHackCount >= 10)
  8064. {
  8065. if (GetDesc())
  8066. if (GetDesc()->DelayedDisconnect(number(2, 7)))
  8067. {
  8068. sys_log(0, "COMBO_HACK_DISCONNECT: %s count: %d", GetName(), m_iComboHackCount);
  8069. LogManager::instance().HackLog("Combo", this);
  8070. }
  8071. }
  8072. }
  8073.  
  8074. void CHARACTER::ResetComboHackCount()
  8075. {
  8076. m_iComboHackCount = 0;
  8077. }
  8078.  
  8079. void CHARACTER::SkipComboAttackByTime(int interval)
  8080. {
  8081. m_dwSkipComboAttackByTime = get_dword_time() + interval;
  8082. }
  8083.  
  8084. DWORD CHARACTER::GetSkipComboAttackByTime() const
  8085. {
  8086. return m_dwSkipComboAttackByTime;
  8087. }
  8088.  
  8089. void CHARACTER::ResetChatCounter()
  8090. {
  8091. m_bChatCounter = 0;
  8092. }
  8093.  
  8094. BYTE CHARACTER::IncreaseChatCounter()
  8095. {
  8096. return ++m_bChatCounter;
  8097. }
  8098.  
  8099. BYTE CHARACTER::GetChatCounter() const
  8100. {
  8101. return m_bChatCounter;
  8102. }
  8103.  
  8104. // ¸»À̳ª ´Ù¸¥°ÍÀ» Ÿ°í ÀÖ³ª?
  8105. bool CHARACTER::IsRiding() const
  8106. {
  8107. return IsHorseRiding() || GetMountVnum();
  8108. }
  8109.  
  8110. bool CHARACTER::CanWarp() const
  8111. {
  8112. const int iPulse = thecore_pulse();
  8113. const int limit_time = PASSES_PER_SEC(g_nPortalLimitTime);
  8114.  
  8115. if ((iPulse - GetSafeboxLoadTime()) < limit_time)
  8116. return false;
  8117.  
  8118. if ((iPulse - GetExchangeTime()) < limit_time)
  8119. return false;
  8120.  
  8121. if ((iPulse - GetMyShopTime()) < limit_time)
  8122. return false;
  8123.  
  8124. if ((iPulse - GetRefineTime()) < limit_time)
  8125. return false;
  8126.  
  8127. if (GetExchange() || GetMyShop() || GetShopOwner() || IsOpenSafebox() || IsCubeOpen())
  8128. return false;
  8129.  
  8130. return true;
  8131. }
  8132.  
  8133. DWORD CHARACTER::GetNextExp() const
  8134. {
  8135. if (PLAYER_MAX_LEVEL_CONST < GetLevel())
  8136. return 2500000000u;
  8137. else
  8138. return exp_table[GetLevel()];
  8139. }
  8140.  
  8141. #ifdef ENABLE_SUPPORT_SYSTEM
  8142. DWORD CHARACTER::SupportGetNextExp() const
  8143. {
  8144. if (120 < GetLevel())
  8145. return 2500000000;
  8146. else
  8147. return exp_support_table[GetLevel()];
  8148. }
  8149. #endif
  8150.  
  8151. #ifdef NEW_PET_SYSTEM
  8152. DWORD CHARACTER::PetGetNextExp() const
  8153. {
  8154. if (IsNewPet()) {
  8155. if (PLAYER_MAX_LEVEL_CONST < GetLevel())
  8156. return 2500000000;
  8157. else
  8158. return exppet_table[GetLevel()];
  8159. }
  8160. }
  8161. #endif
  8162.  
  8163. #ifdef __TITLE_SYSTEM__
  8164. void CHARACTER::SetTitle(int iTitle, BYTE bValue)
  8165. {
  8166. assert(iTitle < TITLES_MAX_NUM);
  8167. int iNewTitle = POINT_TITLE + iTitle;
  8168. if (bValue > 0)
  8169. {
  8170. SetPoint(iNewTitle, 1);
  8171. sys_log(0, "[Title System]: %s has just learn the title %d.", GetName(), iTitle);
  8172. }
  8173. else
  8174. {
  8175. // if (iTitle == ChoosedTitle())
  8176. // {
  8177. // SetPoint(POINT_TITLE, 0);
  8178. // sys_log(0, "[Title System]: %s title choosed, was automated seted to 0.", GetName());
  8179. // }
  8180.  
  8181. SetPoint(iNewTitle, 0);
  8182. sys_log(0, "[Title System]: %s has just unlearn the title %d.", GetName(), iTitle);
  8183. }
  8184.  
  8185. ComputePoints();
  8186. PointsPacket();
  8187. }
  8188.  
  8189. bool CHARACTER::GetTitle(int iTitle)
  8190. {
  8191. assert(iTitle < TITLES_MAX_NUM);
  8192. int iNewTitle = POINT_TITLE + iTitle;
  8193. bool _to_return = false;
  8194. if (GetPoint(iNewTitle) == 1)
  8195. _to_return = true;
  8196.  
  8197. return _to_return;
  8198. }
  8199.  
  8200. bool CHARACTER::ChooseTitle(int iTitle)
  8201. {
  8202. assert(iTitle < TITLES_MAX_NUM);
  8203. int iNewTitle = POINT_TITLE + iTitle;
  8204. bool _to_return = false;
  8205. if ((iTitle == 0) || (GetPoint(iNewTitle) == 1 && iNewTitle != POINT_TITLE))
  8206. _to_return = true;
  8207.  
  8208. if (_to_return)
  8209. {
  8210. SetPoint(POINT_TITLE, iTitle);
  8211. sys_log(0, "[Title System]: %s has just choose to have the title %d.", GetName(), iTitle);
  8212. }
  8213.  
  8214. ComputePoints();
  8215. PointsPacket();
  8216. UpdatePacket();
  8217. return _to_return;
  8218. }
  8219.  
  8220. void CHARACTER::pChooseTitle(int iTitle)
  8221. {
  8222. BYTE bAnswer = 0;
  8223. bool bPass = false;
  8224. int iNewTitle = POINT_TITLE + iTitle;
  8225. if (iTitle >= TITLES_MAX_NUM || iTitle < 1)
  8226. {
  8227. bAnswer = 1;
  8228. bPass = true;
  8229. }
  8230. else if (iTitle == ChoosedTitle())
  8231. {
  8232. bAnswer = 2;
  8233. bPass = true;
  8234. }
  8235. else if (GetPoint(iNewTitle) != 1)
  8236. {
  8237. bAnswer = 3;
  8238. bPass = true;
  8239. }
  8240. else
  8241. bAnswer = 4;
  8242.  
  8243. if (iTitle == 0)
  8244. {
  8245. if (GetPoint(iNewTitle) != 0)
  8246. {
  8247. bAnswer = 4;
  8248. bPass = false;
  8249. }
  8250. else
  8251. {
  8252. bAnswer = 2;
  8253. bPass = true;
  8254. }
  8255. }
  8256.  
  8257. if (!bPass)
  8258. bPass = ChooseTitle(iTitle);
  8259.  
  8260. TPacketGGTitleInfo p;
  8261. p.bHeader = HEADER_GG_TITLE_ANSWER;
  8262. p.iTitle = iTitle;
  8263. p.bAnswer = bAnswer;
  8264. GetDesc()->Packet(&p, sizeof(TPacketGGTitleInfo));
  8265. }
  8266.  
  8267. int CHARACTER::ChoosedTitle()
  8268. {
  8269. int iChoosed = GetPoint(POINT_TITLE);
  8270. return iChoosed;
  8271. }
  8272.  
  8273. const char * CHARACTER::GetTitlesAvailable() const
  8274. {
  8275. static char cString[TITLE_MAX_LEN + 1];
  8276. snprintf(cString, sizeof(cString), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,", GetPoint(POINT_TITLE_1), GetPoint(POINT_TITLE_2), GetPoint(POINT_TITLE_3), GetPoint(POINT_TITLE_4), GetPoint(POINT_TITLE_5), GetPoint(POINT_TITLE_6), GetPoint(POINT_TITLE_7), GetPoint(POINT_TITLE_8), GetPoint(POINT_TITLE_9), GetPoint(POINT_TITLE_10), GetPoint(POINT_TITLE_11), GetPoint(POINT_TITLE_12), GetPoint(POINT_TITLE_13), GetPoint(POINT_TITLE_14), GetPoint(POINT_TITLE_15), GetPoint(POINT_TITLE_16), GetPoint(POINT_TITLE_17), GetPoint(POINT_TITLE_18), GetPoint(POINT_TITLE_19), GetPoint(POINT_TITLE_20));
  8277. return cString;
  8278. }
  8279. #endif
  8280.  
  8281. int CHARACTER::GetSkillPowerByLevel(int level, bool bMob) const
  8282. {
  8283. return CTableBySkill::instance().GetSkillPowerByLevelFromType(GetJob(), GetSkillGroup(), MINMAX(0, level, SKILL_MAX_LEVEL), bMob);
  8284. }
  8285.  
  8286. void CHARACTER::CheckWrongItems()
  8287. {
  8288.  
  8289. for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
  8290. {
  8291. LPITEM item;
  8292.  
  8293. if (!(item = GetInventoryItem(i)))
  8294. continue;
  8295.  
  8296. if (item->GetVnum())
  8297. {
  8298. switch (item->GetVnum())
  8299. {
  8300. case 290: case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: case 299:
  8301. case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189:
  8302. case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199:
  8303. case 3210: case 3211: case 3212: case 3213: case 3214: case 3215: case 3216: case 3217: case 3218: case 3219:
  8304. case 3160: case 3161: case 3162: case 3163: case 3164: case 3165: case 3166: case 3167: case 3168: case 3169:
  8305. case 1170: case 1171: case 1172: case 1173: case 1174: case 1175: case 1176: case 1177: case 1178: case 1179:
  8306. case 1130: case 1131: case 1132: case 1133: case 1134: case 1135: case 1136: case 1137: case 1138: case 1139:
  8307. case 2150: case 2151: case 2152: case 2153: case 2154: case 2155: case 2156: case 2157: case 2158: case 2159:
  8308. case 2170: case 2171: case 2172: case 2173: case 2174: case 2175: case 2176: case 2177: case 2178: case 2179:
  8309. case 7160: case 7161: case 7162: case 7163: case 7164: case 7165: case 7166: case 7167: case 7168: case 7169:
  8310. case 5110: case 5111: case 5112: case 5113: case 5114: case 5115: case 5116: case 5117: case 5118: case 5119:
  8311. case 5120: case 5121: case 5122: case 5123: case 5124: case 5125: case 5126: case 5127: case 5128: case 5129:
  8312. continue;
  8313. }
  8314. }
  8315.  
  8316. for (int ia = 0; ia < ITEM_ATTRIBUTE_MAX_NUM; ia++)
  8317. {
  8318. const TPlayerItemAttribute& attr = item->GetAttribute(ia);
  8319. const TItemAttrTable & r = g_map_itemAttr[attr.bType];
  8320.  
  8321. if(item->GetAttributeSetIndex() != -1 && attr.sValue > r.lValues[r.bMaxLevelBySet[item->GetAttributeSetIndex()] - 1])
  8322. {
  8323. ChatPacket(CHAT_TYPE_INFO, "Wrong item found : %s, pos = %d, value = %d, max_value = %d",
  8324. item->GetName(), i, attr.sValue, r.lValues[r.bMaxLevelBySet[item->GetAttributeSetIndex()] - 1]);
  8325.  
  8326. DBManager::instance().DirectQuery("INSERT INTO log.wrong_items(player_id, item_id, date, w_b_value) VALUES(%d, %d, NOW(), '%d|%d')",
  8327. GetPlayerID(), item->GetID(), attr.bType, attr.sValue);
  8328.  
  8329. item->ChangeAttribute();
  8330. // item->RemoveFromCharacter();
  8331.  
  8332. break;
  8333. }
  8334. }
  8335.  
  8336. continue;
  8337. }
  8338. }
  8339.  
  8340. #ifdef GIFT_SYSTEM
  8341. #include <boost/algorithm/string.hpp>
  8342. EVENTFUNC(gift_refresh_event)
  8343. {
  8344. char_event_info* info = dynamic_cast<char_event_info*>(event->info);
  8345. if (info == NULL)
  8346. {
  8347. sys_err("gift_refresh_event> <Factor> Null pointer");
  8348. return 0;
  8349. }
  8350.  
  8351. LPCHARACTER ch = info->ch;
  8352.  
  8353. if (NULL == ch || ch->IsNPC())
  8354. return 0;
  8355. ch->RefreshGift();
  8356. return PASSES_PER_SEC(5 * 60);
  8357. }
  8358. void CHARACTER::StartRefreshGift()
  8359. {
  8360. if (m_pkGiftRefresh)
  8361. return;
  8362. char_event_info* info = AllocEventInfo<char_event_info>();
  8363.  
  8364. info->ch = this;
  8365. m_pkGiftRefresh = event_create(gift_refresh_event, info, PASSES_PER_SEC(1)); // 1o?
  8366. }
  8367. void SendGift(LPCHARACTER ch, TGiftItem item)
  8368. {
  8369. char szSockets[1024] = { '\0' };
  8370. char *tempSockets = szSockets;
  8371. for (int soc = 0; soc < ITEM_SOCKET_MAX_NUM; soc++)
  8372. tempSockets += sprintf(tempSockets, "%ld%s", item.alSockets[soc], (soc<ITEM_SOCKET_MAX_NUM - 1 ? "|" : ""));
  8373. char szAttrs[1024] = { '\0' };
  8374. char *tempAttrs = szAttrs;
  8375. for (int attr = 0; attr < ITEM_ATTRIBUTE_MAX_NUM; attr++)
  8376. tempAttrs += sprintf(tempAttrs, "%u,%d%s", item.aAttr[attr].bType, item.aAttr[attr].sValue, (attr<ITEM_ATTRIBUTE_MAX_NUM - 1 ? "|" : ""));
  8377. #ifdef FULL_YANG
  8378. ch->ChatPacket(CHAT_TYPE_COMMAND, "gift_item %d %d %lld %d %d %s %s %s %s", item.id, item.vnum, item.count, item.pos, item.dwDateAdd, item.szFrom, item.szReason, szSockets, szAttrs);
  8379. #else
  8380. ch->ChatPacket(CHAT_TYPE_COMMAND, "gift_item %d %d %d %d %d %s %s %s %s", item.id, item.vnum, item.count, item.pos, item.dwDateAdd, item.szFrom, item.szReason, szSockets, szAttrs);
  8381. #endif
  8382. }
  8383. void CHARACTER::LoadGiftPage(int page)
  8384. {
  8385. page = MINMAX(1, page, m_mapGiftGrid.size());
  8386. ChatPacket(CHAT_TYPE_COMMAND, "gift_clear");
  8387. GIFT_MAP::iterator it = m_mapGiftGrid.find(page);
  8388. if (it == m_mapGiftGrid.end())
  8389. return;
  8390. m_dwLastGiftPage = page;
  8391. for (int i = 0; i < it->second.size(); i++)
  8392. SendGift(this, it->second[i]);
  8393. ChatPacket(CHAT_TYPE_COMMAND, "gift_load");
  8394.  
  8395. }
  8396. static CGrid* grid;
  8397. void CHARACTER::AddGiftGrid(int page)
  8398. {
  8399. if (m_mapGiftGrid.find(page) == m_mapGiftGrid.end())
  8400. {
  8401. std::vector<TGiftItem> vec;
  8402. m_mapGiftGrid.insert(std::make_pair(page, vec));
  8403. }
  8404.  
  8405. }
  8406. int CHARACTER::AddGiftGridItem( int page, int size)
  8407. {
  8408. AddGiftGrid(page);
  8409. int iPos = grid->FindBlank(1, size);
  8410.  
  8411. if (iPos < 0)
  8412. return -1;
  8413.  
  8414. if (!grid->IsEmpty(iPos, 1, size))
  8415. return -1;
  8416.  
  8417.  
  8418. grid->Put(iPos, 1, size);
  8419. return iPos;
  8420.  
  8421. }
  8422. void CHARACTER::RefreshGift()
  8423. {
  8424. char szSockets[1024] = { '\0' };
  8425. char *tempSockets = szSockets;
  8426. for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
  8427. {
  8428. tempSockets += sprintf(tempSockets, "socket%d", i);
  8429.  
  8430. if (i<ITEM_SOCKET_MAX_NUM - 1)
  8431. tempSockets += sprintf(tempSockets, ",");
  8432. }
  8433. char szAttrs[1024] = { '\0' };
  8434. char *tempAttrs = szAttrs;
  8435. for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
  8436. {
  8437. if (i < 7)
  8438. tempAttrs += sprintf(tempAttrs, "attrtype%d,attrvalue%d", i, i);
  8439. else
  8440. tempAttrs += sprintf(tempAttrs, "applytype%d,applyvalue%d", i - 7, i - 7);
  8441. if (i<ITEM_ATTRIBUTE_MAX_NUM - 1)
  8442. tempAttrs += sprintf(tempAttrs, ",");
  8443. }
  8444. SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT id,vnum,count,unix_timestamp(date_add),replace(reason,' ','_'),replace(`from`,' ','_'),%s,%s from player_gift where owner_id = %d and status = 'WAIT' ORDER BY date_add ", szSockets, szAttrs, GetPlayerID()));
  8445. SQLResult * pRes = pkMsg->Get();
  8446. m_mapGiftGrid.clear();
  8447. grid = M2_NEW CGrid(15, 8);
  8448. grid->Clear();
  8449. int page = 1;
  8450. if (pRes->uiNumRows>0)
  8451. {
  8452. AddGiftGrid(page);
  8453. MYSQL_ROW row;
  8454. while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
  8455. {
  8456. int col = 0;
  8457. TGiftItem item;
  8458. memset(&item, 0, sizeof(item));
  8459. str_to_number(item.id, row[col++]);
  8460. str_to_number(item.vnum, row[col++]);
  8461. str_to_number(item.count, row[col++]);
  8462. str_to_number(item.dwDateAdd, row[col++]);
  8463. strlcpy(item.szReason, row[col++], sizeof(item.szReason) - 1);
  8464. strlcpy(item.szFrom, row[col++], sizeof(item.szFrom) - 1);
  8465. for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
  8466. str_to_number(item.alSockets[i], row[col++]);
  8467. for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
  8468. {
  8469. str_to_number(item.aAttr[i].bType, row[col++]);
  8470. str_to_number(item.aAttr[i].sValue, row[col++]);
  8471. }
  8472.  
  8473. const TItemTable * item_table = ITEM_MANAGER::instance().GetTable(item.vnum);
  8474. if (!item_table)
  8475. continue;
  8476. int iPos = AddGiftGridItem( page, item_table->bSize);
  8477. if (iPos < 0)
  8478. {
  8479. page++;
  8480. grid->Clear();
  8481. iPos = AddGiftGridItem(page, item_table->bSize);
  8482. if (iPos < 0)
  8483. {
  8484. sys_err("iPos <0");
  8485. break;
  8486. }
  8487. }
  8488. item.pos = iPos;
  8489. m_mapGiftGrid[page].push_back(item);
  8490.  
  8491. }
  8492. M2_DELETE(grid);
  8493. }
  8494. if(GetGiftPages()>0)
  8495. ChatPacket(CHAT_TYPE_COMMAND, "gift_info %d", GetGiftPages());
  8496. }
  8497. #endif
  8498.  
  8499. #ifdef OFFLINE_SHOP
  8500.  
  8501. extern std::map<DWORD, DWORD> g_ShopIndexCount;
  8502. extern std::map<int, TShopCost> g_ShopCosts;
  8503. void CHARACTER::OpenMyShop(const char * c_pszSign, TShopItemTable * pTable, BYTE bItemCount, DWORD id)
  8504. {
  8505.  
  8506. if (g_ShopCosts.find(id) == g_ShopCosts.end())
  8507. {
  8508. sys_log(0, "Shop days error %s %d", c_pszSign, id);
  8509. return;
  8510. }
  8511. int days = g_ShopCosts[id].days;
  8512. long long price = g_ShopCosts[id].price;
  8513. if (price > 0 && GetGold() < price)
  8514. {
  8515. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_NEED_MONEY"), price);
  8516. return;
  8517. }
  8518. if (GetMyShop())
  8519. {
  8520. CloseMyShop();
  8521. return;
  8522. }
  8523.  
  8524.  
  8525. int gShopMax = quest::CQuestManager::Instance().GetEventFlag("shop_max");
  8526. if (m_mapshops.size() >= (gShopMax ? gShopMax : 2))
  8527. {
  8528. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_MAX_ERR"));
  8529. return;
  8530. }
  8531.  
  8532.  
  8533. if (g_ShopIndexCount.count(GetMapIndex())>0)
  8534. {
  8535. int shop_max = g_ShopIndexCount[GetMapIndex()];
  8536. bool block = false;
  8537.  
  8538. #ifdef SHOP_ONLY_ALLOWED_INDEX
  8539. if (shop_max > 0)
  8540. {
  8541. #else
  8542. if (shop_max == 0)
  8543. block = true;
  8544. else{
  8545. #endif
  8546. std::unique_ptr<SQLMsg> pkMsg(DBManager::instance().DirectQuery("SELECT map_index from player_shop WHERE channel=%d and status='OK' and map_index=%d", g_bChannel, GetMapIndex()));
  8547. SQLResult * pRes = pkMsg->Get();
  8548. if (pRes->uiNumRows >= shop_max)
  8549. block = true;
  8550. }
  8551. if (block)
  8552. {
  8553. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_MAP_MAX"));
  8554. return;
  8555. }
  8556. }
  8557. #ifdef SHOP_ONLY_ALLOWED_INDEX
  8558. else
  8559. {
  8560. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_CANNOT_OPEN_HERE"));
  8561. return;
  8562. }
  8563. #endif
  8564. if (GetMyShop()) // AI1I 1YAI ?¡©¡¤A AOA¢¬¢¬e ¢¥Y¢¥A¢¥U.
  8565. {
  8566. CloseMyShop();
  8567. return;
  8568. }
  8569. #ifndef FULL_YANG
  8570. int64_t nTotalMoney = 0;
  8571.  
  8572. for (int n = 0; n < bItemCount; ++n)
  8573. {
  8574. nTotalMoney += static_cast<int64_t> ((pTable + n)->price);
  8575. }
  8576.  
  8577. nTotalMoney += static_cast<int64_t> (GetGold());
  8578.  
  8579. if (GOLD_MAX <= nTotalMoney)
  8580. {
  8581. sys_err("[OVERFLOW_GOLD] Overflow (GOLD_MAX) id %u name %s", GetPlayerID(), GetName());
  8582. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("20?? ©©E?¡í ??¡ÆuC??¨Ï ¡íoA¢§?¡í ?¡©?o¡Æ¢§ ??¢©?¢¥?¢¥?"));
  8583. return;
  8584. }
  8585. #endif
  8586. #ifdef ACCE_FIX
  8587. if(IsAcceOpen())
  8588. Acce_close(this);
  8589. #endif
  8590. quest::PC * pPC = quest::CQuestManager::instance().GetPCForce(GetPlayerID());
  8591. if (pPC->IsRunning())
  8592. return;
  8593. std::vector<TShopItemTable *> map_shop;
  8594. for (BYTE i = 0; i < bItemCount; ++i)
  8595. {
  8596. // ANTI_GIVE, ANTI_MYSHOP check
  8597. LPITEM pkItem = GetItem((pTable + i)->pos);
  8598.  
  8599. if (pkItem)
  8600. {
  8601. const TItemTable * item_table = pkItem->GetProto();
  8602.  
  8603. if (item_table && (IS_SET(item_table->dwAntiFlags, ITEM_ANTIFLAG_GIVE | ITEM_ANTIFLAG_MYSHOP)))
  8604. {
  8605. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "??¡¤a?¡© ???????? ¡Æ©©?I¡íoA¢§?¢§?¡© ?C¢¬?C? ?o ??¢©?¢¥?¢¥?."));
  8606. return;
  8607. }
  8608.  
  8609. if (pkItem->IsEquipped())
  8610. {
  8611. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "????A©¬?I ???????? ¡Æ©©?I¡íoA¢§?¢§?¡© ?C¢¬?C? ?o ??¢©?¢¥?¢¥?."));
  8612. return;
  8613. }
  8614.  
  8615. if (pkItem->isLocked())
  8616. {
  8617. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "¡íc?eA©¬?I ???????? ¡Æ©©?I¡íoA¢§?¢§?¡© ?C¢¬?C? ?o ??¢©?¢¥?¢¥?."));
  8618. return;
  8619. }
  8620. if (pkItem->GetTransmutation() != 0)
  8621. {
  8622. ChatPacket(CHAT_TYPE_INFO, "Nu poti pune la vanzare un obiect transmutat.");
  8623. return;
  8624. }
  8625. if (pkItem->GetOwner() != this)
  8626. {
  8627. return;
  8628. }
  8629. #ifdef SOULBIND_SYSTEM
  8630. if (pkItem->IsSoulBind())
  8631. {
  8632. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "You can't sell in private shop item with soul bind."));
  8633. return;
  8634. }
  8635. #endif
  8636. }
  8637. if (days != 0)
  8638. map_shop.push_back(pTable++);
  8639. }
  8640. if (days != 0 && map_shop.size() == 0)
  8641. return;
  8642. char szName[256];
  8643. DBManager::instance().EscapeString(szName, 256, c_pszSign, strlen(c_pszSign));
  8644. m_stShopSign = szName;
  8645. boost::replace_all(m_stShopSign, "%", "%%");
  8646.  
  8647.  
  8648. if (m_stShopSign.length()>30)
  8649. m_stShopSign.resize(30);
  8650. if (m_stShopSign.length() == 0)
  8651. return;
  8652. #ifdef STRING_PROTECTION
  8653. if (CBanwordManager::instance().CheckString(m_stShopSign.c_str(), m_stShopSign.length()) != "")
  8654. {
  8655. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "???O?i©©? ???i¡Æ¢§ ?¡ÀCO¥ì? ¡íoA¢§ ??¢¬¡×?¢¬¡¤I ¡íoA¢§?¡í ?¡© ?o ??¢©?¢¥?¢¥?."));
  8656. return;
  8657. }
  8658. #else
  8659. if (CBanwordManager::instance().CheckString(m_stShopSign.c_str(), m_stShopSign.length()))
  8660. {
  8661. ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "???O?i©©? ???i¡Æ¢§ ?¡ÀCO¥ì? ¡íoA¢§ ??¢¬¡×?¢¬¡¤I ¡íoA¢§?¡í ?¡© ?o ??¢©?¢¥?¢¥?."));
  8662. return;
  8663. }
  8664. #endif
  8665. if (m_pkExchange)
  8666. m_pkExchange->Cancel();
  8667. if (price > 0)
  8668. #ifdef FULL_YANG_OWN
  8669. ChangeGold(-price);
  8670. #else
  8671. PointChange(POINT_GOLD, -price);
  8672. #endif
  8673. if (days != 0)
  8674. {
  8675. CShopManager::instance().CreateOfflineShop(this, m_stShopSign.c_str(), map_shop, id);
  8676. m_stShopSign.clear();
  8677. return;
  8678. }
  8679. TPacketGCShopSign p;
  8680. p.bHeader = HEADER_GC_SHOP_SIGN;
  8681. p.dwVID = GetVID();
  8682. strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
  8683.  
  8684. PacketAround(&p, sizeof(TPacketGCShopSign));
  8685.  
  8686. m_pkMyShop = CShopManager::instance().CreatePCShop(this, pTable, bItemCount);
  8687. if (!m_pkMyShop)
  8688. {
  8689. sys_err("Cannot open normal shop %s %s", GetName(), m_stShopSign.c_str());
  8690. return;
  8691. }
  8692. if (IsPolymorphed() == true)
  8693. {
  8694. RemoveAffect(AFFECT_POLYMORPH);
  8695. }
  8696.  
  8697. if (GetHorse())
  8698. {
  8699. HorseSummon(false, true);
  8700. }
  8701. else if (GetMountVnum())
  8702. {
  8703. RemoveAffect(AFFECT_MOUNT);
  8704. RemoveAffect(AFFECT_MOUNT_BONUS);
  8705. }
  8706.  
  8707. SetPolymorph(30000, true);
  8708.  
  8709. }
  8710. void CHARACTER::SetShopSign(const char * name)
  8711. {
  8712. m_stShopSign = name;
  8713. TPacketGCShopSign p;
  8714. p.bHeader = HEADER_GC_SHOP_SIGN;
  8715. p.dwVID = GetVID();
  8716. strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
  8717. PacketAround(&p, sizeof(TPacketGCShopSign));
  8718. }
  8719.  
  8720. TPrivShop CHARACTER::GetPrivShopTable(DWORD id)
  8721. {
  8722. TPrivShop shop;
  8723. memset(&shop, 0, sizeof(TPrivShop));
  8724. PSHOP_MAP::iterator it = m_mapshops.find(id);
  8725. if (it != m_mapshops.end())
  8726. return it->second;
  8727. return shop;
  8728.  
  8729. }
  8730. void CHARACTER::UpdatePrivShopTable(DWORD id, TPrivShop shop)
  8731. {
  8732. if (m_mapshops.find(id) != m_mapshops.end())
  8733. m_mapshops[id]=shop;
  8734. SendShops();
  8735. }
  8736. void CHARACTER::RemovePrivShopTable(DWORD id)
  8737. {
  8738. if (m_mapshops.find(id) != m_mapshops.end())
  8739. m_mapshops.erase(m_mapshops.find(id));
  8740. SendShops();
  8741. }
  8742. void CHARACTER::UpdateShopItems()
  8743. {
  8744. LPSHOP npcshop = GetMyShop();
  8745. LPCHARACTER owner = CHARACTER_MANAGER::instance().FindByPID(GetPrivShopOwner());
  8746. if (!npcshop || !IsPrivShop())
  8747. return;
  8748. npcshop->RemoveGuests(owner);
  8749. npcshop->SetLocked(true);
  8750. npcshop->ClearItems();
  8751. std::vector<TShopItemTable *> map_shop;
  8752. char szSockets[1024] = { '\0' };
  8753. char *tempSockets = szSockets;
  8754. for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
  8755. {
  8756. tempSockets += sprintf(tempSockets, "socket%d", i);
  8757.  
  8758. if (i<ITEM_SOCKET_MAX_NUM - 1)
  8759. tempSockets += sprintf(tempSockets, ",");
  8760. }
  8761. char szAttrs[1024] = { '\0' };
  8762. char *tempAttrs = szAttrs;
  8763. for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
  8764. {
  8765. if (i < 7)
  8766. tempAttrs += sprintf(tempAttrs, "attrtype%d,attrvalue%d", i, i);
  8767. else
  8768. tempAttrs += sprintf(tempAttrs, "applytype%d,applyvalue%d", i - 7, i - 7);
  8769. if (i<ITEM_ATTRIBUTE_MAX_NUM - 1)
  8770. tempAttrs += sprintf(tempAttrs, ",");
  8771. }
  8772. SQLMsg * Msg(DBManager::instance().DirectQuery("SELECT id,vnum,count,display_pos,price,%s,%s from player_shop_items where shop_id='%d'",szSockets,szAttrs, GetPrivShop()));
  8773. SQLResult * Res = Msg->Get();
  8774. if (Res->uiNumRows > 0)
  8775. {
  8776. MYSQL_ROW row;
  8777. while ((row = mysql_fetch_row(Res->pSQLResult)) != NULL)
  8778. {
  8779.  
  8780. int col = 0;
  8781.  
  8782.  
  8783.  
  8784. TShopItemTable *shop = new TShopItemTable;
  8785. memset(shop, 0, sizeof(TShopItemTable));
  8786. DWORD id;
  8787. shop->pos.window_type = INVENTORY;
  8788. str_to_number(id, row[col++]);
  8789. str_to_number(shop->vnum, row[col++]);
  8790. str_to_number(shop->count, row[col++]);
  8791. str_to_number(shop->display_pos, row[col++]);
  8792. //col++;
  8793. str_to_number(shop->price, row[col++]);
  8794.  
  8795. const TItemTable * item_table = ITEM_MANAGER::instance().GetTable(shop->vnum);
  8796.  
  8797.  
  8798. if (!item_table)
  8799. {
  8800. sys_err("Shop: no item table by item vnum #%d", shop->vnum);
  8801. continue;
  8802. }
  8803. for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
  8804. {
  8805. if (NULL != GetInventoryItem(i) && GetInventoryItem(i)->GetRealID() == id)
  8806. GetInventoryItem(i)->RemoveFromCharacter();
  8807. }
  8808. LPITEM item = ITEM_MANAGER::instance().CreateItem(shop->vnum, shop->count, id, false, -1, true);
  8809. if (-1 == (shop->pos.cell = GetEmptyInventory(item_table->bSize)))
  8810. {
  8811. sys_err("no empty position in npc inventory");
  8812. return;
  8813. }
  8814. if (item)
  8815. {
  8816. item->ClearAttribute();
  8817. item->SetRealID(id);
  8818. for (int s = 0;s<ITEM_SOCKET_MAX_NUM;s++)
  8819. {
  8820. DWORD soc;
  8821. str_to_number(soc, row[col++]);
  8822. item->SetSocket(s, soc, false);
  8823. }
  8824. for (int at = 0;at<ITEM_ATTRIBUTE_MAX_NUM;at++)
  8825. {
  8826. DWORD attr;
  8827. long val;
  8828. str_to_number(attr, row[col++]);
  8829. str_to_number(val, row[col++]);
  8830. item->SetForceAttribute(at, attr, val);
  8831. }
  8832.  
  8833. item->AddToCharacter(this, shop->pos);
  8834. }
  8835. else
  8836. {
  8837. sys_err("%d is not item", shop->vnum);
  8838. continue;
  8839. }
  8840. map_shop.push_back(shop);
  8841. }
  8842. }
  8843.  
  8844.  
  8845.  
  8846. if (map_shop.size() == 0 || map_shop.size() > SHOP_HOST_ITEM_MAX_NUM)
  8847. {
  8848. DeleteMyShop();
  8849. return;
  8850. }
  8851. npcshop->SetPrivShopItems(map_shop);
  8852. npcshop->SetLocked(false);
  8853. for (int i = 0;i < SHOP_HOST_ITEM_MAX_NUM;i++)
  8854. npcshop->BroadcastUpdateItem(i);
  8855.  
  8856. if (owner)
  8857. {
  8858. owner->LoadPrivShops();
  8859. owner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("SHOP_EDIT_SUCCESS"));
  8860. }
  8861. }
  8862. void CHARACTER::LoadPrivShops()
  8863. {
  8864. m_mapshops.clear();
  8865. SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT id,shop_vid,replace(replace(name,' ','\\\\'),'#','_'),gold,item_count,(select count(id) from player_shop_items where shop_id=player_shop.id),DATEDIFF(date_close,now()) AS days,UNIX_TIMESTAMP(date_close) from player_shop WHERE player_id=%d", GetPlayerID()));
  8866. SQLResult * pRes = pkMsg->Get();
  8867. if (pRes->uiNumRows>0)
  8868. {
  8869.  
  8870. MYSQL_ROW row;
  8871. while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
  8872. {
  8873. int col = 0;
  8874. TPrivShop shop;
  8875. memset(&shop, 0, sizeof(TPrivShop));
  8876. str_to_number(shop.shop_id, row[col++]);
  8877. str_to_number(shop.shop_vid, row[col++]);
  8878. strlcpy(shop.szSign, row[col++], sizeof(shop.szSign));
  8879. str_to_number(shop.gold, row[col++]);
  8880. str_to_number(shop.item_count, row[col++]);
  8881. str_to_number(shop.rest_count, row[col++]);
  8882. str_to_number(shop.days, row[col++]);
  8883. str_to_number(shop.date_close, row[col++]);
  8884. m_mapshops.insert(std::make_pair(shop.shop_id, shop));
  8885. }
  8886. }
  8887. SendShops();
  8888. }
  8889. void CHARACTER::SendShops(bool isGm)
  8890. {
  8891. ChatPacket(CHAT_TYPE_COMMAND, "shop_clear");
  8892. PSHOP_MAP::iterator it = m_mapshops.begin();
  8893. while (it != m_mapshops.end())
  8894. {
  8895. ChatPacket(CHAT_TYPE_COMMAND, "shop_add %d %d %s %lld %d %d %d %d", it->second.shop_id, it->second.shop_vid, it->second.szSign, it->second.gold, it->second.item_count, it->second.rest_count, it->second.days, it->second.date_close);
  8896. it++;
  8897. }
  8898.  
  8899.  
  8900. }
  8901. void CHARACTER::SendShopCost()
  8902. {
  8903. extern std::map<int, TShopCost> g_ShopCosts;
  8904. ChatPacket(CHAT_TYPE_COMMAND, "shop_cost_clear");
  8905. std::map<int, TShopCost>::iterator it = g_ShopCosts.begin();
  8906. while (it != g_ShopCosts.end())
  8907. {
  8908. ChatPacket(CHAT_TYPE_COMMAND, "shop_cost %d %d %d %lld", it->first,it->second.days, it->second.time, it->second.price);
  8909. it++;
  8910. }
  8911.  
  8912.  
  8913. }
  8914. void CHARACTER::OpenShop(DWORD id, const char *name, bool onboot)
  8915. {
  8916. if (GetMyShop())
  8917. {
  8918. CloseMyShop();
  8919. return;
  8920. }
  8921. if (IsPC())
  8922. return;
  8923. char szSockets[1024] = { '\0' };
  8924. char *tempSockets = szSockets;
  8925. for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
  8926. {
  8927. tempSockets += sprintf(tempSockets, "socket%d", i);
  8928.  
  8929. if (i<ITEM_SOCKET_MAX_NUM - 1)
  8930. tempSockets += sprintf(tempSockets, ",");
  8931. }
  8932. char szAttrs[1024] = { '\0' };
  8933. char *tempAttrs = szAttrs;
  8934. for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
  8935. {
  8936. if (i < 7)
  8937. tempAttrs += sprintf(tempAttrs, "attrtype%d,attrvalue%d", i, i);
  8938. else
  8939. tempAttrs += sprintf(tempAttrs, "applytype%d,applyvalue%d", i - 7, i - 7);
  8940. if (i<ITEM_ATTRIBUTE_MAX_NUM - 1)
  8941. tempAttrs += sprintf(tempAttrs, ",");
  8942. }
  8943. SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT id,vnum,count,display_pos,price,%s,%s from player_shop_items where shop_id='%d'",szSockets,szAttrs, id));
  8944.  
  8945. SQLResult * pRes = pkMsg->Get();
  8946. BYTE bItemCount = pRes->uiNumRows;
  8947.  
  8948. TShopItemTable * m_pShopTable = new TShopItemTable[bItemCount];
  8949. memset(&m_pShopTable[0], 0, sizeof(TShopItemTable) * bItemCount);
  8950.  
  8951. std::vector<TShopItemTable *> map_shop;
  8952.  
  8953. if (bItemCount>0)
  8954. {
  8955. bItemCount = 0;
  8956. MYSQL_ROW row;
  8957. int c = 0;
  8958. while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
  8959. {
  8960. int col = 0;
  8961.  
  8962.  
  8963.  
  8964. TShopItemTable *shop = new TShopItemTable;
  8965. memset(shop, 0, sizeof(TShopItemTable));
  8966. DWORD id;
  8967. shop->pos.window_type = INVENTORY;
  8968. str_to_number(id, row[col++]);
  8969. str_to_number(shop->vnum, row[col++]);
  8970. str_to_number(shop->count, row[col++]);
  8971. str_to_number(shop->display_pos, row[col++]);
  8972. //col++;
  8973. str_to_number(shop->price, row[col++]);
  8974.  
  8975. const TItemTable * item_table = ITEM_MANAGER::instance().GetTable(shop->vnum);
  8976.  
  8977.  
  8978. if (!item_table)
  8979. {
  8980. sys_err("Shop: no item table by item vnum #%d", shop->vnum);
  8981. continue;
  8982. }
  8983. if (-1 == (shop->pos.cell = GetEmptyInventory(item_table->bSize)))
  8984. {
  8985. sys_err("no empty position in npc inventory");
  8986. return;
  8987. }
  8988.  
  8989. LPITEM item = ITEM_MANAGER::instance().CreateItem(shop->vnum, shop->count, 0, false, -1, true);
  8990.  
  8991. if (item)
  8992. {
  8993. item->ClearAttribute();
  8994. item->SetSkipSave(true);
  8995. item->SetRealID(id);
  8996. for (int s = 0;s<ITEM_SOCKET_MAX_NUM;s++)
  8997. {
  8998. DWORD soc;
  8999. str_to_number(soc, row[col++]);
  9000. item->SetSocket(s, soc, false);
  9001. }
  9002. for (int at = 0;at<ITEM_ATTRIBUTE_MAX_NUM;at++)
  9003. {
  9004. DWORD attr;
  9005. long val;
  9006. str_to_number(attr, row[col++]);
  9007. str_to_number(val, row[col++]);
  9008. item->SetForceAttribute(at, attr, val);
  9009. }
  9010.  
  9011.  
  9012. item->AddToCharacter(this, shop->pos);
  9013. }
  9014. else
  9015. {
  9016. sys_err("%d is not item", shop->vnum);
  9017. continue;
  9018. }
  9019.  
  9020. map_shop.push_back(shop);
  9021. ++bItemCount;
  9022. }
  9023. }
  9024.  
  9025.  
  9026.  
  9027. if (bItemCount == 0 && !onboot || bItemCount > SHOP_HOST_ITEM_MAX_NUM)
  9028. return;
  9029.  
  9030.  
  9031. m_stShopSign = name;
  9032.  
  9033. if (m_stShopSign.length()>30)
  9034. m_stShopSign.resize(30);
  9035. if (m_stShopSign.length() == 0)
  9036. return;
  9037.  
  9038.  
  9039. TPacketGCShopSign p;
  9040.  
  9041. p.bHeader = HEADER_GC_SHOP_SIGN;
  9042. p.dwVID = GetVID();
  9043. strlcpy(p.szSign, m_stShopSign.c_str(), sizeof(p.szSign));
  9044.  
  9045. PacketAround(&p, sizeof(TPacketGCShopSign));
  9046.  
  9047. m_pkMyShop = CShopManager::instance().CreateNPCShop(this, map_shop);
  9048.  
  9049. }
  9050. void CHARACTER::DeleteMyShop()
  9051. {
  9052. if (GetMyShop())
  9053. {
  9054. SQLMsg * pkMsg(DBManager::instance().DirectQuery("SELECT gold FROM player_shop where id='%d'", GetPrivShop()));
  9055. SQLResult * pRes = pkMsg->Get();
  9056. if (pRes->uiNumRows>0)
  9057. {
  9058. MYSQL_ROW row;
  9059. while ((row = mysql_fetch_row(pRes->pSQLResult)) != NULL)
  9060. {
  9061. long long gold;
  9062. str_to_number(gold, row[0]);
  9063. if (gold>0)
  9064. {
  9065. char query[1024];
  9066. sprintf(query, "INSERT INTO player_gift SET \
  9067. owner_id=%d,vnum=1,count='%s',reason=\"%s\",`from`=replace(\"%s\",' ','_'),status='WAIT',date_add=NOW()",
  9068. GetPrivShopOwner(), row[0], LC_TEXT("SHOP_REASON"), GetName());
  9069. DBManager::instance().DirectQuery(query);
  9070. }
  9071.  
  9072. }
  9073. GetMyShop()->GetItems();
  9074. LPCHARACTER owner = CHARACTER_MANAGER::instance().FindByPID(GetPrivShopOwner());
  9075. if (owner)
  9076. {
  9077. #ifdef GIFT_SYSTEM
  9078. owner->RefreshGift();
  9079. #endif
  9080. owner->RemovePrivShopTable(GetPrivShop());
  9081. owner->SendShops();
  9082. owner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_SUCCESS_CLOSE"));
  9083. }
  9084. else{
  9085. TPacketShopClose packet;
  9086. packet.shop_id = GetPrivShop();
  9087. packet.pid = GetPrivShopOwner();
  9088. db_clientdesc->DBPacket(HEADER_GD_SHOP_CLOSE, 0, &packet, sizeof(packet));
  9089. }
  9090.  
  9091. DBManager::instance().DirectQuery("delete from player_shop where id='%d'", GetPrivShop());
  9092. CloseMyShop();
  9093. }
  9094. return;
  9095. }
  9096. M2_DESTROY_CHARACTER(this);
  9097. }
  9098.  
  9099.  
  9100.  
  9101. EVENTFUNC(RefreshShopEvent)
  9102. {
  9103. char_event_info* info = dynamic_cast<char_event_info*>(event->info);
  9104. if (info == NULL)
  9105. {
  9106. sys_err("ishop_refresh_event> <Factor> Null pointer");
  9107. return 0;
  9108. }
  9109.  
  9110. LPCHARACTER ch = info->ch;
  9111.  
  9112. if (NULL == ch)
  9113. return 0;
  9114.  
  9115.  
  9116. ch->SendShops();
  9117. ch->SendShopCost();
  9118. if(ch->GetGiftPages()>0)
  9119. ch->ChatPacket(CHAT_TYPE_COMMAND, "gift_info %d", ch->GetGiftPages());
  9120. return PASSES_PER_SEC(10);
  9121. }
  9122. void CHARACTER::StartRefreshShopEvent()
  9123. {
  9124. if (m_pkRefreshShopEvent)
  9125. return;
  9126.  
  9127. char_event_info* info = AllocEventInfo<char_event_info>();
  9128.  
  9129. info->ch = this;
  9130.  
  9131. m_pkRefreshShopEvent = event_create(RefreshShopEvent, info, PASSES_PER_SEC(1)); // 1o?
  9132. }
  9133. #endif
  9134.  
  9135. #ifdef ENABLE_CHANGE_CHANNEL
  9136. void CHARACTER::ChangeChannel(DWORD channelId){
  9137. long lAddr;
  9138. long lMapIndex;
  9139. WORD wPort;
  9140. long x = this->GetX();
  9141. long y = this->GetY();
  9142.  
  9143.  
  9144. if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort))
  9145. {
  9146. sys_err("cannot find map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
  9147. return;
  9148. }
  9149.  
  9150. if(lMapIndex >= 10000)
  9151. {
  9152. this->ChatPacket(CHAT_TYPE_INFO, ("You can't change channel in private map."));
  9153. return;
  9154. }
  9155.  
  9156. if (GetMyShopTime())
  9157. {
  9158. this->ChatPacket(CHAT_TYPE_INFO, ("Mataaaaaaa."));
  9159. return;
  9160. }
  9161.  
  9162.  
  9163. //this->ChatPacket(CHAT_TYPE_COMMAND, "RefreshChannel %d", channelId);
  9164.  
  9165. Stop();
  9166. Save();
  9167.  
  9168. if(GetSectree()){
  9169. GetSectree()->RemoveEntity(this);
  9170. ViewCleanup();
  9171. EncodeRemovePacket(this);
  9172. }
  9173. TPacketGCWarp p;
  9174.  
  9175. p.bHeader = HEADER_GC_WARP;
  9176. p.lX = x;
  9177. p.lY = y;
  9178. p.lAddr = lAddr;
  9179.  
  9180. p.wPort = (wPort - 100*(g_bChannel-1) + 100*(channelId-1));
  9181.  
  9182. GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
  9183. }
  9184. #endif
  9185.  
  9186.  
  9187. #ifdef __SASH_SYSTEM__
  9188. void CHARACTER::OpenSash(bool bCombination)
  9189. {
  9190. if (isSashOpened(bCombination))
  9191. {
  9192. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("The sash window it's already opened."));
  9193. return;
  9194. }
  9195.  
  9196. if (bCombination)
  9197. {
  9198. if (m_bSashAbsorption)
  9199. {
  9200. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Before you may close the sash absorption window."));
  9201. return;
  9202. }
  9203.  
  9204. m_bSashCombination = true;
  9205. }
  9206. else
  9207. {
  9208. if (m_bSashCombination)
  9209. {
  9210. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Before you may close the sash combine window."));
  9211. return;
  9212. }
  9213.  
  9214. m_bSashAbsorption = true;
  9215. }
  9216.  
  9217. TItemPos tPos;
  9218. tPos.window_type = INVENTORY;
  9219. tPos.cell = 0;
  9220.  
  9221. TPacketSash sPacket;
  9222. sPacket.header = HEADER_GC_SASH;
  9223. sPacket.subheader = SASH_SUBHEADER_GC_OPEN;
  9224. sPacket.bWindow = bCombination;
  9225. sPacket.dwPrice = 0;
  9226. sPacket.bPos = 0;
  9227. sPacket.tPos = tPos;
  9228. sPacket.dwItemVnum = 0;
  9229. sPacket.dwMinAbs = 0;
  9230. sPacket.dwMaxAbs = 0;
  9231. GetDesc()->Packet(&sPacket, sizeof(TPacketSash));
  9232.  
  9233. ClearSashMaterials();
  9234. }
  9235.  
  9236. void CHARACTER::CloseSash()
  9237. {
  9238. if ((!m_bSashCombination) && (!m_bSashAbsorption))
  9239. return;
  9240.  
  9241. bool bWindow = (m_bSashCombination == true ? true : false);
  9242.  
  9243. TItemPos tPos;
  9244. tPos.window_type = INVENTORY;
  9245. tPos.cell = 0;
  9246.  
  9247. TPacketSash sPacket;
  9248. sPacket.header = HEADER_GC_SASH;
  9249. sPacket.subheader = SASH_SUBHEADER_GC_CLOSE;
  9250. sPacket.bWindow = bWindow;
  9251. sPacket.dwPrice = 0;
  9252. sPacket.bPos = 0;
  9253. sPacket.tPos = tPos;
  9254. sPacket.dwItemVnum = 0;
  9255. sPacket.dwMinAbs = 0;
  9256. sPacket.dwMaxAbs = 0;
  9257. GetDesc()->Packet(&sPacket, sizeof(TPacketSash));
  9258.  
  9259. if (bWindow)
  9260. m_bSashCombination = false;
  9261. else
  9262. m_bSashAbsorption = false;
  9263.  
  9264. ClearSashMaterials();
  9265. }
  9266.  
  9267. void CHARACTER::ClearSashMaterials()
  9268. {
  9269. LPITEM * pkItemMaterial;
  9270. pkItemMaterial = GetSashMaterials();
  9271. for (int i = 0; i < SASH_WINDOW_MAX_MATERIALS; ++i)
  9272. {
  9273. if (!pkItemMaterial[i])
  9274. continue;
  9275.  
  9276. pkItemMaterial[i]->Lock(false);
  9277. pkItemMaterial[i] = NULL;
  9278. }
  9279. }
  9280.  
  9281. bool CHARACTER::SashIsSameGrade(long lGrade)
  9282. {
  9283. LPITEM * pkItemMaterial;
  9284. pkItemMaterial = GetSashMaterials();
  9285. if (!pkItemMaterial[0])
  9286. return false;
  9287.  
  9288. bool bReturn = (pkItemMaterial[0]->GetValue(SASH_GRADE_VALUE_FIELD) == lGrade ? true : false);
  9289. return bReturn;
  9290. }
  9291.  
  9292. DWORD CHARACTER::GetSashCombinePrice(long lGrade)
  9293. {
  9294. long long dwPrice = 0;
  9295. switch (lGrade)
  9296. {
  9297. case 2:
  9298. {
  9299. dwPrice = SASH_GRADE_2_PRICE;
  9300. }
  9301. break;
  9302. case 3:
  9303. {
  9304. dwPrice = SASH_GRADE_3_PRICE;
  9305. }
  9306. break;
  9307. case 4:
  9308. {
  9309. dwPrice = SASH_GRADE_4_PRICE;
  9310. }
  9311. break;
  9312. default:
  9313. {
  9314. dwPrice = SASH_GRADE_1_PRICE;
  9315. }
  9316. break;
  9317. }
  9318.  
  9319. return dwPrice;
  9320. }
  9321.  
  9322. BYTE CHARACTER::CheckEmptyMaterialSlot()
  9323. {
  9324. LPITEM * pkItemMaterial;
  9325. pkItemMaterial = GetSashMaterials();
  9326. for (int i = 0; i < SASH_WINDOW_MAX_MATERIALS; ++i)
  9327. {
  9328. if (!pkItemMaterial[i])
  9329. return i;
  9330. }
  9331.  
  9332. return 255;
  9333. }
  9334.  
  9335. void CHARACTER::GetSashCombineResult(DWORD & dwItemVnum, DWORD & dwMinAbs, DWORD & dwMaxAbs)
  9336. {
  9337. LPITEM * pkItemMaterial;
  9338. pkItemMaterial = GetSashMaterials();
  9339.  
  9340. if (m_bSashCombination)
  9341. {
  9342. if ((pkItemMaterial[0]) && (pkItemMaterial[1]))
  9343. {
  9344. long lVal = pkItemMaterial[0]->GetValue(SASH_GRADE_VALUE_FIELD);
  9345. if (lVal == 4)
  9346. {
  9347. dwItemVnum = pkItemMaterial[0]->GetOriginalVnum();
  9348. dwMinAbs = pkItemMaterial[0]->GetSocket(SASH_ABSORPTION_SOCKET);
  9349. DWORD dwMaxAbsCalc = (dwMinAbs + SASH_GRADE_4_ABS_RANGE > SASH_GRADE_4_ABS_MAX ? SASH_GRADE_4_ABS_MAX : (dwMinAbs + SASH_GRADE_4_ABS_RANGE));
  9350. dwMaxAbs = dwMaxAbsCalc;
  9351. }
  9352. else
  9353. {
  9354. DWORD dwMaskVnum = pkItemMaterial[0]->GetOriginalVnum();
  9355. TItemTable * pTable = ITEM_MANAGER::instance().GetTable(dwMaskVnum + 1);
  9356. if (pTable)
  9357. dwMaskVnum += 1;
  9358.  
  9359. dwItemVnum = dwMaskVnum;
  9360. switch (lVal)
  9361. {
  9362. case 2:
  9363. {
  9364. dwMinAbs = SASH_GRADE_3_ABS;
  9365. dwMaxAbs = SASH_GRADE_3_ABS;
  9366. }
  9367. break;
  9368. case 3:
  9369. {
  9370. dwMinAbs = SASH_GRADE_4_ABS_MIN;
  9371. dwMaxAbs = SASH_GRADE_4_ABS_MAX_COMB;
  9372. }
  9373. break;
  9374. default:
  9375. {
  9376. dwMinAbs = SASH_GRADE_2_ABS;
  9377. dwMaxAbs = SASH_GRADE_2_ABS;
  9378. }
  9379. break;
  9380. }
  9381. }
  9382. }
  9383. else
  9384. {
  9385. dwItemVnum = 0;
  9386. dwMinAbs = 0;
  9387. dwMaxAbs = 0;
  9388. }
  9389. }
  9390. else
  9391. {
  9392. if ((pkItemMaterial[0]) && (pkItemMaterial[1]))
  9393. {
  9394. dwItemVnum = pkItemMaterial[0]->GetOriginalVnum();
  9395. dwMinAbs = pkItemMaterial[0]->GetSocket(SASH_ABSORPTION_SOCKET);
  9396. dwMaxAbs = dwMinAbs;
  9397. }
  9398. else
  9399. {
  9400. dwItemVnum = 0;
  9401. dwMinAbs = 0;
  9402. dwMaxAbs = 0;
  9403. }
  9404. }
  9405. }
  9406.  
  9407. void CHARACTER::AddSashMaterial(TItemPos tPos, BYTE bPos)
  9408. {
  9409. if (bPos >= SASH_WINDOW_MAX_MATERIALS)
  9410. {
  9411. if (bPos == 255)
  9412. {
  9413. bPos = CheckEmptyMaterialSlot();
  9414. if (bPos >= SASH_WINDOW_MAX_MATERIALS)
  9415. return;
  9416. }
  9417. else
  9418. return;
  9419. }
  9420.  
  9421. LPITEM pkItem = GetItem(tPos);
  9422. if (!pkItem)
  9423. return;
  9424. else if ((pkItem->GetCell() >= INVENTORY_MAX_NUM) || (pkItem->IsEquipped()) || (tPos.IsBeltInventoryPosition()) || (pkItem->IsDragonSoul()))
  9425. return;
  9426. else if ((pkItem->GetType() != ITEM_COSTUME) && (m_bSashCombination))
  9427. return;
  9428. else if ((pkItem->GetType() != ITEM_COSTUME) && (bPos == 0) && (m_bSashAbsorption))
  9429. return;
  9430. else if (pkItem->isLocked())
  9431. {
  9432. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't add locked items."));
  9433. return;
  9434. }
  9435. #ifdef __SOULBINDING_SYSTEM__
  9436. else if ((pkItem->IsBind()) || (pkItem->IsUntilBind()))
  9437. {
  9438. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't add binded items."));
  9439. return;
  9440. }
  9441. #endif
  9442. else if ((m_bSashCombination) && (bPos == 1) && (!SashIsSameGrade(pkItem->GetValue(SASH_GRADE_VALUE_FIELD))))
  9443. {
  9444. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can combine just sashes of same grade."));
  9445. return;
  9446. }
  9447. else if ((m_bSashCombination) && (pkItem->GetSocket(SASH_ABSORPTION_SOCKET) >= SASH_GRADE_4_ABS_MAX))
  9448. {
  9449. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("This sash got already maximum absorption chance."));
  9450. return;
  9451. }
  9452. else if ((bPos == 1) && (m_bSashAbsorption))
  9453. {
  9454. if ((pkItem->GetType() != ITEM_WEAPON) && (pkItem->GetType() != ITEM_ARMOR))
  9455. {
  9456. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can absorb just the bonuses from armors and weapons."));
  9457. return;
  9458. }
  9459. else if ((pkItem->GetType() == ITEM_ARMOR) && (pkItem->GetSubType() != ARMOR_BODY))
  9460. {
  9461. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can absorb just the bonuses from armors and weapons."));
  9462. return;
  9463. }
  9464. }
  9465. else if ((pkItem->GetSubType() != COSTUME_SASH) && (m_bSashCombination))
  9466. return;
  9467. else if ((pkItem->GetSubType() != COSTUME_SASH) && (bPos == 0) && (m_bSashAbsorption))
  9468. return;
  9469. else if ((pkItem->GetSocket(SASH_ABSORBED_SOCKET) > 0) && (bPos == 0) && (m_bSashAbsorption))
  9470. return;
  9471.  
  9472. LPITEM * pkItemMaterial;
  9473. pkItemMaterial = GetSashMaterials();
  9474. if ((bPos == 1) && (!pkItemMaterial[0]))
  9475. return;
  9476.  
  9477. if (pkItemMaterial[bPos])
  9478. return;
  9479.  
  9480. pkItemMaterial[bPos] = pkItem;
  9481. pkItemMaterial[bPos]->Lock(true);
  9482.  
  9483. DWORD dwItemVnum, dwMinAbs, dwMaxAbs;
  9484. GetSashCombineResult(dwItemVnum, dwMinAbs, dwMaxAbs);
  9485.  
  9486. TPacketSash sPacket;
  9487. sPacket.header = HEADER_GC_SASH;
  9488. sPacket.subheader = SASH_SUBHEADER_GC_ADDED;
  9489. sPacket.bWindow = m_bSashCombination == true ? true : false;
  9490. sPacket.dwPrice = GetSashCombinePrice(pkItem->GetValue(SASH_GRADE_VALUE_FIELD));
  9491. sPacket.bPos = bPos;
  9492. sPacket.tPos = tPos;
  9493. sPacket.dwItemVnum = dwItemVnum;
  9494. sPacket.dwMinAbs = dwMinAbs;
  9495. sPacket.dwMaxAbs = dwMaxAbs;
  9496. GetDesc()->Packet(&sPacket, sizeof(TPacketSash));
  9497. }
  9498.  
  9499. void CHARACTER::RemoveSashMaterial(BYTE bPos)
  9500. {
  9501. if (bPos >= SASH_WINDOW_MAX_MATERIALS)
  9502. return;
  9503.  
  9504. LPITEM * pkItemMaterial;
  9505. pkItemMaterial = GetSashMaterials();
  9506.  
  9507. long long dwPrice = 0;
  9508.  
  9509. if (bPos == 1)
  9510. {
  9511. if (pkItemMaterial[bPos])
  9512. {
  9513. pkItemMaterial[bPos]->Lock(false);
  9514. pkItemMaterial[bPos] = NULL;
  9515. }
  9516.  
  9517. if (pkItemMaterial[0])
  9518. dwPrice = GetSashCombinePrice(pkItemMaterial[0]->GetValue(SASH_GRADE_VALUE_FIELD));
  9519. }
  9520. else
  9521. ClearSashMaterials();
  9522.  
  9523. TItemPos tPos;
  9524. tPos.window_type = INVENTORY;
  9525. tPos.cell = 0;
  9526.  
  9527. TPacketSash sPacket;
  9528. sPacket.header = HEADER_GC_SASH;
  9529. sPacket.subheader = SASH_SUBHEADER_GC_REMOVED;
  9530. sPacket.bWindow = m_bSashCombination == true ? true : false;
  9531. sPacket.dwPrice = dwPrice;
  9532. sPacket.bPos = bPos;
  9533. sPacket.tPos = tPos;
  9534. sPacket.dwItemVnum = 0;
  9535. sPacket.dwMinAbs = 0;
  9536. sPacket.dwMaxAbs = 0;
  9537. GetDesc()->Packet(&sPacket, sizeof(TPacketSash));
  9538. }
  9539.  
  9540. BYTE CHARACTER::CanRefineSashMaterials()
  9541. {
  9542. BYTE bReturn = 0;
  9543. LPITEM * pkItemMaterial;
  9544. pkItemMaterial = GetSashMaterials();
  9545. if (m_bSashCombination)
  9546. {
  9547. for (int i = 0; i < SASH_WINDOW_MAX_MATERIALS; ++i)
  9548. {
  9549. if (pkItemMaterial[i])
  9550. {
  9551. if ((pkItemMaterial[i]->GetType() == ITEM_COSTUME) && (pkItemMaterial[i]->GetSubType() == COSTUME_SASH))
  9552. bReturn = 1;
  9553. else
  9554. {
  9555. bReturn = 0;
  9556. break;
  9557. }
  9558. }
  9559. else
  9560. {
  9561. bReturn = 0;
  9562. break;
  9563. }
  9564. }
  9565. }
  9566. else if (m_bSashAbsorption)
  9567. {
  9568. if ((pkItemMaterial[0]) && (pkItemMaterial[1]))
  9569. {
  9570. if ((pkItemMaterial[0]->GetType() == ITEM_COSTUME) && (pkItemMaterial[0]->GetSubType() == COSTUME_SASH))
  9571. bReturn = 2;
  9572. else
  9573. bReturn = 0;
  9574.  
  9575. if ((pkItemMaterial[1]->GetType() == ITEM_WEAPON) || ((pkItemMaterial[1]->GetType() == ITEM_ARMOR) && (pkItemMaterial[1]->GetSubType() == ARMOR_BODY)))
  9576. bReturn = 2;
  9577. else
  9578. bReturn = 0;
  9579.  
  9580. if (pkItemMaterial[0]->GetSocket(SASH_ABSORBED_SOCKET) > 0)
  9581. bReturn = 0;
  9582. }
  9583. else
  9584. bReturn = 0;
  9585. }
  9586.  
  9587. return bReturn;
  9588. }
  9589.  
  9590. void CHARACTER::RefineSashMaterials()
  9591. {
  9592. BYTE bCan = CanRefineSashMaterials();
  9593. if (bCan == 0)
  9594. return;
  9595.  
  9596. LPITEM * pkItemMaterial;
  9597. pkItemMaterial = GetSashMaterials();
  9598.  
  9599. DWORD dwItemVnum, dwMinAbs, dwMaxAbs;
  9600. GetSashCombineResult(dwItemVnum, dwMinAbs, dwMaxAbs);
  9601. long long dwPrice = GetSashCombinePrice(pkItemMaterial[0]->GetValue(SASH_GRADE_VALUE_FIELD));
  9602.  
  9603. if (bCan == 1)
  9604. {
  9605. int iSuccessChance = 0;
  9606. long lVal = pkItemMaterial[0]->GetValue(SASH_GRADE_VALUE_FIELD);
  9607. switch (lVal)
  9608. {
  9609. case 2:
  9610. {
  9611. iSuccessChance = SASH_COMBINE_GRADE_2;
  9612. }
  9613. break;
  9614. case 3:
  9615. {
  9616. iSuccessChance = SASH_COMBINE_GRADE_3;
  9617. }
  9618. break;
  9619. case 4:
  9620. {
  9621. iSuccessChance = SASH_COMBINE_GRADE_4;
  9622. }
  9623. break;
  9624. default:
  9625. {
  9626. iSuccessChance = SASH_COMBINE_GRADE_1;
  9627. }
  9628. break;
  9629. }
  9630.  
  9631. if (GetGold() < dwPrice)
  9632. {
  9633. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You don't have enough Yang."));
  9634. return;
  9635. }
  9636.  
  9637. int iChance = number(1, 100);
  9638. bool bSucces = (iChance <= iSuccessChance ? true : false);
  9639. if (bSucces)
  9640. {
  9641. LPITEM pkItem = ITEM_MANAGER::instance().CreateItem(dwItemVnum, 1, 0, false);
  9642. if (!pkItem)
  9643. {
  9644. sys_err("%d can't be created.", dwItemVnum);
  9645. return;
  9646. }
  9647.  
  9648. ITEM_MANAGER::CopyAllAttrTo(pkItemMaterial[0], pkItem);
  9649. LogManager::instance().ItemLog(this, pkItem, "COMBINE SUCCESS", pkItem->GetName());
  9650. DWORD dwAbs = (dwMinAbs == dwMaxAbs ? dwMinAbs : number(dwMinAbs + 1, dwMaxAbs));
  9651. pkItem->SetSocket(SASH_ABSORPTION_SOCKET, dwAbs);
  9652. pkItem->SetSocket(SASH_ABSORBED_SOCKET, pkItemMaterial[0]->GetSocket(SASH_ABSORBED_SOCKET));
  9653.  
  9654. PointChange(POINT_GOLD, -dwPrice);
  9655. DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, pkItemMaterial[0]->GetVnum(), -dwPrice);
  9656.  
  9657. WORD wCell = pkItemMaterial[0]->GetCell();
  9658. ITEM_MANAGER::instance().RemoveItem(pkItemMaterial[0], "COMBINE (REFINE SUCCESS)");
  9659. ITEM_MANAGER::instance().RemoveItem(pkItemMaterial[1], "COMBINE (REFINE SUCCESS)");
  9660.  
  9661. pkItem->AddToCharacter(this, TItemPos(INVENTORY, wCell));
  9662. ITEM_MANAGER::instance().FlushDelayedSave(pkItem);
  9663. pkItem->AttrLog();
  9664.  
  9665. if (lVal == 4)
  9666. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("New absorption rate: %d%"), dwAbs);
  9667. else
  9668. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Success."));
  9669.  
  9670. EffectPacket(SE_EFFECT_SASH_SUCCEDED);
  9671. LogManager::instance().SashLog(GetPlayerID(), GetX(), GetY(), dwItemVnum, pkItem->GetID(), 1, dwAbs, 1);
  9672.  
  9673. ClearSashMaterials();
  9674. }
  9675. else
  9676. {
  9677. PointChange(POINT_GOLD, -dwPrice);
  9678. DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, pkItemMaterial[0]->GetVnum(), -dwPrice);
  9679.  
  9680. ITEM_MANAGER::instance().RemoveItem(pkItemMaterial[1], "COMBINE (REFINE FAIL)");
  9681.  
  9682. if (lVal == 4)
  9683. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("New absorption rate: %d%"), pkItemMaterial[0]->GetSocket(SASH_ABSORPTION_SOCKET));
  9684. else
  9685. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Failed."));
  9686.  
  9687. LogManager::instance().SashLog(GetPlayerID(), GetX(), GetY(), dwItemVnum, 0, 0, 0, 0);
  9688.  
  9689. pkItemMaterial[1] = NULL;
  9690. }
  9691.  
  9692. TItemPos tPos;
  9693. tPos.window_type = INVENTORY;
  9694. tPos.cell = 0;
  9695.  
  9696. TPacketSash sPacket;
  9697. sPacket.header = HEADER_GC_SASH;
  9698. sPacket.subheader = SASH_SUBHEADER_CG_REFINED;
  9699. sPacket.bWindow = m_bSashCombination == true ? true : false;
  9700. sPacket.dwPrice = dwPrice;
  9701. sPacket.bPos = 0;
  9702. sPacket.tPos = tPos;
  9703. sPacket.dwItemVnum = 0;
  9704. sPacket.dwMinAbs = 0;
  9705. if (bSucces)
  9706. sPacket.dwMaxAbs = 100;
  9707. else
  9708. sPacket.dwMaxAbs = 0;
  9709.  
  9710. GetDesc()->Packet(&sPacket, sizeof(TPacketSash));
  9711. }
  9712. else
  9713. {
  9714. pkItemMaterial[1]->CopyAttributeTo(pkItemMaterial[0]);
  9715. LogManager::instance().ItemLog(this, pkItemMaterial[0], "ABSORB (REFINE SUCCESS)", pkItemMaterial[0]->GetName());
  9716. pkItemMaterial[0]->SetSocket(SASH_ABSORBED_SOCKET, pkItemMaterial[1]->GetOriginalVnum());
  9717. for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
  9718. {
  9719. if (pkItemMaterial[0]->GetAttributeValue(i) < 0)
  9720. pkItemMaterial[0]->SetForceAttribute(i, pkItemMaterial[0]->GetAttributeType(i), 0);
  9721. }
  9722.  
  9723. ITEM_MANAGER::instance().RemoveItem(pkItemMaterial[1], "ABSORBED (REFINE SUCCESS)");
  9724.  
  9725. ITEM_MANAGER::instance().FlushDelayedSave(pkItemMaterial[0]);
  9726. pkItemMaterial[0]->AttrLog();
  9727.  
  9728. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Success."));
  9729.  
  9730. ClearSashMaterials();
  9731.  
  9732. TItemPos tPos;
  9733. tPos.window_type = INVENTORY;
  9734. tPos.cell = 0;
  9735.  
  9736. TPacketSash sPacket;
  9737. sPacket.header = HEADER_GC_SASH;
  9738. sPacket.subheader = SASH_SUBHEADER_CG_REFINED;
  9739. sPacket.bWindow = m_bSashCombination == true ? true : false;
  9740. sPacket.dwPrice = dwPrice;
  9741. sPacket.bPos = 255;
  9742. sPacket.tPos = tPos;
  9743. sPacket.dwItemVnum = 0;
  9744. sPacket.dwMinAbs = 0;
  9745. sPacket.dwMaxAbs = 1;
  9746. GetDesc()->Packet(&sPacket, sizeof(TPacketSash));
  9747. }
  9748. }
  9749.  
  9750. bool CHARACTER::CleanSashAttr(LPITEM pkItem, LPITEM pkTarget)
  9751. {
  9752. if (!CanHandleItem())
  9753. return false;
  9754. else if ((!pkItem) || (!pkTarget))
  9755. return false;
  9756. else if ((pkTarget->GetType() != ITEM_COSTUME) && (pkTarget->GetSubType() != COSTUME_SASH))
  9757. return false;
  9758.  
  9759. if (pkTarget->GetSocket(SASH_ABSORBED_SOCKET) <= 0)
  9760. return false;
  9761.  
  9762. pkTarget->SetSocket(SASH_ABSORBED_SOCKET, 0);
  9763. for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
  9764. pkTarget->SetForceAttribute(i, 0, 0);
  9765.  
  9766. pkItem->SetCount(pkItem->GetCount() - 1);
  9767. LogManager::instance().ItemLog(this, pkTarget, "USE_DETACHMENT (CLEAN ATTR)", pkTarget->GetName());
  9768. return true;
  9769. }
  9770. #endif
  9771.  
  9772. #ifdef __CHANGELOOK_SYSTEM__
  9773. void CHARACTER::ChangeLookWindow(bool bOpen, bool bRequest)
  9774. {
  9775. if ((bOpen) && (isChangeLookOpened()))
  9776. {
  9777. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] The window is already opened."));
  9778. return;
  9779. }
  9780.  
  9781. if ((!bOpen) && (!isChangeLookOpened()))
  9782. {
  9783. if (!bRequest)
  9784. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] The window is not opened."));
  9785.  
  9786. return;
  9787. }
  9788.  
  9789. TItemPos tPos;
  9790. tPos.window_type = INVENTORY;
  9791. tPos.cell = 0;
  9792.  
  9793. TPacketChangeLook sPacket;
  9794. sPacket.header = HEADER_GC_CL;
  9795. sPacket.subheader = CL_SUBHEADER_OPEN;
  9796. sPacket.subheader = bOpen == true ? CL_SUBHEADER_OPEN : CL_SUBHEADER_CLOSE;
  9797. sPacket.dwCost = bOpen == true ? CL_TRANSMUTATION_PRICE : 0;
  9798. sPacket.bPos = 0;
  9799. sPacket.tPos = tPos;
  9800. GetDesc()->Packet(&sPacket, sizeof(TPacketChangeLook));
  9801.  
  9802. m_bChangeLook = bOpen;
  9803. ClearClWindowMaterials();
  9804. }
  9805.  
  9806. void CHARACTER::ClearClWindowMaterials()
  9807. {
  9808. LPITEM * pkItemMaterial;
  9809. pkItemMaterial = GetClWindowMaterials();
  9810. for (int i = 0; i < CL_WINDOW_MAX_MATERIALS; ++i)
  9811. {
  9812. if (!pkItemMaterial[i])
  9813. continue;
  9814.  
  9815. pkItemMaterial[i]->Lock(false);
  9816. pkItemMaterial[i] = NULL;
  9817. }
  9818. }
  9819.  
  9820. BYTE CHARACTER::CheckClEmptyMaterialSlot()
  9821. {
  9822. LPITEM * pkItemMaterial;
  9823. pkItemMaterial = GetClWindowMaterials();
  9824. for (int i = 0; i < CL_WINDOW_MAX_MATERIALS; ++i)
  9825. {
  9826. if (!pkItemMaterial[i])
  9827. return i;
  9828. }
  9829.  
  9830. return 255;
  9831. }
  9832.  
  9833. #ifdef __CHANGELOOK_EXTEND__
  9834. bool CHARACTER::CanBeWearBySex(DWORD dwVnum)
  9835. {
  9836. if(dwVnum == 0)
  9837. return true;
  9838.  
  9839. const TItemTable* itemTable = ITEM_MANAGER::instance().GetTable(dwVnum);
  9840.  
  9841. if (NULL == itemTable)
  9842. return false;
  9843.  
  9844. if (IS_SET(itemTable->dwAntiFlags, ITEM_ANTIFLAG_MALE))
  9845. {
  9846. if (SEX_MALE == GET_SEX(this))
  9847. return false;
  9848. }
  9849.  
  9850. if (IS_SET(itemTable->dwAntiFlags, ITEM_ANTIFLAG_FEMALE))
  9851. {
  9852. if (SEX_FEMALE == GET_SEX(this))
  9853. return false;
  9854. }
  9855.  
  9856. return true;
  9857. }
  9858.  
  9859. bool CHARACTER::CanBeWearByAntiflag(DWORD dwVnum)
  9860. {
  9861. if(dwVnum == 0)
  9862. return true;
  9863.  
  9864. const TItemTable* itemTable = ITEM_MANAGER::instance().GetTable(dwVnum);
  9865.  
  9866. if (NULL == itemTable)
  9867. return false;
  9868.  
  9869. switch (GetJob())
  9870. {
  9871. case JOB_WARRIOR:
  9872. if (itemTable->dwAntiFlags & ITEM_ANTIFLAG_WARRIOR)
  9873. return false;
  9874. break;
  9875.  
  9876. case JOB_ASSASSIN:
  9877. if (itemTable->dwAntiFlags & ITEM_ANTIFLAG_ASSASSIN)
  9878. return false;
  9879. break;
  9880.  
  9881. case JOB_SHAMAN:
  9882. if (itemTable->dwAntiFlags & ITEM_ANTIFLAG_SHAMAN)
  9883. return false;
  9884. break;
  9885.  
  9886. case JOB_SURA:
  9887. if (itemTable->dwAntiFlags & ITEM_ANTIFLAG_SURA)
  9888. return false;
  9889. break;
  9890. #ifdef ENABLE_WOLFMAN_CHARACTER
  9891. case JOB_WOLFMAN:
  9892. if (itemTable->dwAntiFlags & ITEM_ANTIFLAG_WOLFMAN)
  9893. return false;
  9894. break;
  9895. #endif
  9896. }
  9897.  
  9898. return true;
  9899. }
  9900. #endif
  9901.  
  9902. void CHARACTER::AddClMaterial(TItemPos tPos, BYTE bPos)
  9903. {
  9904. if (!isChangeLookOpened())
  9905. return;
  9906. else if (bPos >= CL_WINDOW_MAX_MATERIALS)
  9907. {
  9908. if (bPos != 255)
  9909. return;
  9910.  
  9911. bPos = CheckClEmptyMaterialSlot();
  9912. if (bPos >= CL_WINDOW_MAX_MATERIALS)
  9913. return;
  9914. }
  9915.  
  9916. LPITEM pkItem = GetItem(tPos);
  9917. if (!pkItem)
  9918. return;
  9919. else if ((pkItem->GetCell() >= INVENTORY_MAX_NUM) || (tPos.IsBeltInventoryPosition()))
  9920. return;
  9921. else if (pkItem->IsEquipped())
  9922. {
  9923. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You cannot transmute an item while it is equipped."));
  9924. return;
  9925. }
  9926. else if ((pkItem->GetType() != ITEM_WEAPON) && (pkItem->GetType() != ITEM_ARMOR) && (pkItem->GetType() != ITEM_COSTUME))
  9927. {
  9928. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] This item cannot be transmuted."));
  9929. return;
  9930. }
  9931. #ifdef __NEW_ARROW_SYSTEM__
  9932. else if ((pkItem->GetType() == ITEM_WEAPON) && ((pkItem->GetSubType() == WEAPON_ARROW) || (pkItem->GetSubType() == WEAPON_MOUNT_SPEAR) || (pkItem->GetSubType() == WEAPON_UNLIMITED_ARROW)))
  9933. #else
  9934. else if ((pkItem->GetType() == ITEM_WEAPON) && ((pkItem->GetSubType() == WEAPON_ARROW) || (pkItem->GetSubType() == WEAPON_MOUNT_SPEAR)))
  9935. #endif
  9936. {
  9937. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] This item cannot be transmuted."));
  9938. return;
  9939. }
  9940. else if ((pkItem->GetType() == ITEM_ARMOR) && (pkItem->GetSubType() != ARMOR_BODY))
  9941. {
  9942. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] This item cannot be transmuted."));
  9943. return;
  9944. }
  9945. #ifdef __WEAPON_COSTUME_SYSTEM__
  9946. else if ((pkItem->GetType() == ITEM_COSTUME) && (pkItem->GetSubType() != COSTUME_BODY) && (pkItem->GetSubType() != COSTUME_HAIR) && (pkItem->GetSubType() != COSTUME_WEAPON))
  9947. #else
  9948. else if ((pkItem->GetType() == ITEM_COSTUME) && (pkItem->GetSubType() != COSTUME_BODY) && (pkItem->GetSubType() != COSTUME_HAIR))
  9949. #endif
  9950. {
  9951. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] This item cannot be transmuted."));
  9952. return;
  9953. }
  9954. #ifdef __SOULBINDING_SYSTEM__
  9955. else if ((pkItem->IsBind()) || (pkItem->IsUntilBind()))
  9956. {
  9957. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You can't add binded items."));
  9958. return;
  9959. }
  9960. #endif
  9961. else if (pkItem->isLocked())
  9962. {
  9963. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You can't add locked items."));
  9964. return;
  9965. }
  9966. else if (pkItem->GetTransmutation() != 0)
  9967. {
  9968. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You can't add items which are transmuted yet."));
  9969. return;
  9970. }
  9971.  
  9972. LPITEM * pkItemMaterial;
  9973. pkItemMaterial = GetClWindowMaterials();
  9974. if ((bPos == 1) && (!pkItemMaterial[0]))
  9975. return;
  9976.  
  9977. if (pkItemMaterial[bPos])
  9978. return;
  9979.  
  9980. #ifdef __CHANGELOOK_EXTEND__
  9981. if (bPos == 1)
  9982. {
  9983. bool bStop = false;
  9984. if(pkItemMaterial[0]->GetType() == ITEM_WEAPON)
  9985. {
  9986. if (pkItemMaterial[0]->GetType() != pkItem->GetType())
  9987. bStop = true;
  9988. else if (pkItemMaterial[0]->GetSubType() != pkItem->GetSubType())
  9989. bStop = true;
  9990. else if (pkItemMaterial[0]->GetOriginalVnum() == pkItem->GetOriginalVnum())
  9991. bStop = true;
  9992. }
  9993. else if(pkItemMaterial[0]->GetType() == ITEM_ARMOR)
  9994. {
  9995. if (pkItemMaterial[0]->GetOriginalVnum() == pkItem->GetOriginalVnum())
  9996. bStop = true;
  9997. else if(pkItem->GetType() != ITEM_ARMOR && pkItem->GetType() != ITEM_COSTUME)
  9998. bStop = true;
  9999. else if(pkItem->GetType() == ITEM_ARMOR)
  10000. {
  10001. if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_WARRIOR) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_WARRIOR)))
  10002. bStop = true;
  10003. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_ASSASSIN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_ASSASSIN)))
  10004. bStop = true;
  10005. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_SHAMAN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_SHAMAN)))
  10006. bStop = true;
  10007. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_SURA) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_SURA)))
  10008. bStop = true;
  10009. #ifdef __WOLFMAN_CHARACTER__
  10010. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_WOLFMAN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_WOLFMAN)))
  10011. bStop = true;
  10012. #endif
  10013. }
  10014. }
  10015. else if(pkItemMaterial[0]->GetType() == ITEM_COSTUME)
  10016. {
  10017. if (pkItemMaterial[0]->GetOriginalVnum() == pkItem->GetOriginalVnum())
  10018. bStop = true;
  10019. else if(pkItem->GetType() != ITEM_ARMOR && pkItem->GetType() != ITEM_COSTUME)
  10020. bStop = true;
  10021. else if(pkItem->GetType() == ITEM_COSTUME)
  10022. {
  10023. if (((IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_FEMALE)) && (!IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_FEMALE))) || ((IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_MALE)) && (!IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_MALE))))
  10024. bStop = true;
  10025. }
  10026. }
  10027. else
  10028. bStop = true;
  10029.  
  10030. if (bStop)
  10031. {
  10032. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You cannot submit this item."));
  10033. return;
  10034. }
  10035. }
  10036. #else
  10037. if (bPos == 1)
  10038. {
  10039. bool bStop = false;
  10040. if (pkItemMaterial[0]->GetType() != pkItem->GetType())
  10041. bStop = true;
  10042. else if (pkItemMaterial[0]->GetSubType() != pkItem->GetSubType())
  10043. bStop = true;
  10044. else if (pkItemMaterial[0]->GetOriginalVnum() == pkItem->GetOriginalVnum())
  10045. bStop = true;
  10046. else if (((IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_FEMALE)) && (!IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_FEMALE))) || ((IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_MALE)) && (!IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_MALE))))
  10047. bStop = true;
  10048. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_WARRIOR) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_WARRIOR)))
  10049. bStop = true;
  10050. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_ASSASSIN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_ASSASSIN)))
  10051. bStop = true;
  10052. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_SHAMAN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_SHAMAN)))
  10053. bStop = true;
  10054. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_SURA) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_SURA)))
  10055. bStop = true;
  10056. #ifdef __WOLFMAN_CHARACTER__
  10057. else if ((pkItem->GetAntiFlag() & ITEM_ANTIFLAG_WOLFMAN) && (!IS_SET(pkItemMaterial[0]->GetAntiFlag(), ITEM_ANTIFLAG_WOLFMAN)))
  10058. bStop = true;
  10059. #endif
  10060.  
  10061. if (bStop)
  10062. {
  10063. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You cannot submit this item."));
  10064. return;
  10065. }
  10066. }
  10067. #endif
  10068.  
  10069. pkItemMaterial[bPos] = pkItem;
  10070. pkItemMaterial[bPos]->Lock(true);
  10071.  
  10072. TPacketChangeLook sPacket;
  10073. sPacket.header = HEADER_GC_CL;
  10074. sPacket.subheader = CL_SUBHEADER_ADD;
  10075. sPacket.dwCost = 0;
  10076. sPacket.bPos = bPos;
  10077. sPacket.tPos = tPos;
  10078. GetDesc()->Packet(&sPacket, sizeof(TPacketChangeLook));
  10079. }
  10080.  
  10081. void CHARACTER::RemoveClMaterial(BYTE bPos)
  10082. {
  10083. if (bPos >= CL_WINDOW_MAX_MATERIALS)
  10084. return;
  10085.  
  10086. LPITEM * pkItemMaterial;
  10087. pkItemMaterial = GetClWindowMaterials();
  10088.  
  10089. if (!pkItemMaterial[bPos])
  10090. return;
  10091.  
  10092. if (bPos == 1)
  10093. {
  10094. pkItemMaterial[bPos]->Lock(false);
  10095. pkItemMaterial[bPos] = NULL;
  10096. }
  10097. else
  10098. ClearClWindowMaterials();
  10099.  
  10100. TItemPos tPos;
  10101. tPos.window_type = INVENTORY;
  10102. tPos.cell = 0;
  10103.  
  10104. TPacketChangeLook sPacket;
  10105. sPacket.header = HEADER_GC_CL;
  10106. sPacket.subheader = CL_SUBHEADER_REMOVE;
  10107. sPacket.dwCost = 0;
  10108. sPacket.bPos = bPos;
  10109. sPacket.tPos = tPos;
  10110. GetDesc()->Packet(&sPacket, sizeof(TPacketChangeLook));
  10111. }
  10112.  
  10113. void CHARACTER::RefineClMaterials()
  10114. {
  10115. LPITEM * pkItemMaterial;
  10116. pkItemMaterial = GetClWindowMaterials();
  10117. if (!pkItemMaterial[0])
  10118. return;
  10119. else if (!pkItemMaterial[1])
  10120. {
  10121. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] Please submit the item you want to transmute."));
  10122. return;
  10123. }
  10124.  
  10125. long long dwPrice = CL_TRANSMUTATION_PRICE;
  10126. if (GetGold() < dwPrice)
  10127. {
  10128. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Transmutation] You don't have enough Yang."));
  10129. return;
  10130. }
  10131.  
  10132. DWORD dwVnum = pkItemMaterial[1]->GetVnum();
  10133. PointChange(POINT_GOLD, -dwPrice);
  10134. DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, pkItemMaterial[0]->GetVnum(), -dwPrice);
  10135. ITEM_MANAGER::instance().RemoveItem(pkItemMaterial[1], "TRANSMUTED (SUCCESSFULLY)");
  10136.  
  10137. pkItemMaterial[0]->SetTransmutation(dwVnum, true);
  10138. ClearClWindowMaterials();
  10139.  
  10140. TItemPos tPos;
  10141. tPos.window_type = INVENTORY;
  10142. tPos.cell = 0;
  10143.  
  10144. TPacketChangeLook sPacket;
  10145. sPacket.header = HEADER_GC_CL;
  10146. sPacket.subheader = CL_SUBHEADER_REFINE;
  10147. sPacket.dwCost = 0;
  10148. sPacket.bPos = 0;
  10149. sPacket.tPos = tPos;
  10150. GetDesc()->Packet(&sPacket, sizeof(TPacketChangeLook));
  10151. }
  10152.  
  10153. bool CHARACTER::CleanTransmutation(LPITEM pkItem, LPITEM pkTarget)
  10154. {
  10155. if (!CanHandleItem())
  10156. return false;
  10157. else if ((!pkItem) || (!pkTarget))
  10158. return false;
  10159. else if ((pkTarget->GetType() != ITEM_WEAPON) && (pkTarget->GetType() != ITEM_ARMOR) && (pkTarget->GetType() != ITEM_COSTUME))
  10160. return false;
  10161. #ifdef __SOULBINDING_SYSTEM__
  10162. else if ((pkTarget->IsBind()) || (pkTarget->IsUntilBind()))
  10163. {
  10164. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't remove the transmute because item is binded."));
  10165. return false;
  10166. }
  10167. #endif
  10168. else if (pkTarget->isLocked())
  10169. {
  10170. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't remove the transmute because item is locked."));
  10171. return false;
  10172. }
  10173.  
  10174. if (pkTarget->GetTransmutation() == 0)
  10175. return false;
  10176.  
  10177. pkTarget->SetTransmutation(0);
  10178. pkItem->SetCount(pkItem->GetCount() - 1);
  10179. LogManager::instance().ItemLog(this, pkTarget, "USE_DETACHMENT (CLEAN TRANSMUTED)", pkTarget->GetName());
  10180. return true;
  10181. }
  10182. #endif
  10183.  
  10184. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  10185. void CHARACTER::MountSummon(LPITEM mountItem)
  10186. {
  10187. CMountSystem* mountSystem = GetMountSystem();
  10188. DWORD mobVnum = 0;
  10189. if (GetMapIndex() == 113)
  10190. return;
  10191.  
  10192. if (CArenaManager::instance().IsArenaMap(GetMapIndex()) == true)
  10193. return;
  10194.  
  10195. if (!mountSystem || !mountItem)
  10196. return;
  10197.  
  10198. if(mountItem->GetValue(1) != 0)
  10199. mobVnum = mountItem->GetValue(1);
  10200.  
  10201. if (IsHorseRiding())
  10202. StopRiding();
  10203.  
  10204. if (GetHorse())
  10205. HorseSummon(false);
  10206.  
  10207. mountSystem->Summon(mobVnum, mountItem, false);
  10208. }
  10209.  
  10210. void CHARACTER::MountUnsummon(LPITEM mountItem)
  10211. {
  10212. CMountSystem* mountSystem = GetMountSystem();
  10213. DWORD mobVnum = 0;
  10214.  
  10215. if (!mountSystem || !mountItem)
  10216. return;
  10217.  
  10218. if(mountItem->GetValue(1) != 0)
  10219. mobVnum = mountItem->GetValue(1);
  10220.  
  10221. if (GetMountVnum() == mobVnum)
  10222. mountSystem->Unmount(mobVnum);
  10223.  
  10224. mountSystem->Unsummon(mobVnum);
  10225. }
  10226.  
  10227. void CHARACTER::CheckMount()
  10228. {
  10229. CMountSystem* mountSystem = GetMountSystem();
  10230. LPITEM mountItem = GetWear(WEAR_COSTUME_MOUNT);
  10231. DWORD mobVnum = 0;
  10232.  
  10233. if (GetMapIndex() == 113)
  10234. return;
  10235.  
  10236. if (CArenaManager::instance().IsArenaMap(GetMapIndex()) == true)
  10237. return;
  10238.  
  10239. if (!mountSystem || !mountItem)
  10240. return;
  10241.  
  10242. if(mountItem->GetValue(1) != 0)
  10243. mobVnum = mountItem->GetValue(1);
  10244.  
  10245. if(mountSystem->CountSummoned() == 0)
  10246. {
  10247. mountSystem->Summon(mobVnum, mountItem, false);
  10248. }
  10249. }
  10250.  
  10251. bool CHARACTER::IsRidingMount()
  10252. {
  10253. return (GetWear(WEAR_COSTUME_MOUNT) || FindAffect(AFFECT_MOUNT));
  10254. }
  10255. #endif
  10256.  
  10257. #ifdef ENABLE_GEM_SYSTEM
  10258. void CHARACTER::OpenGemShopFirstTime()
  10259. {
  10260. for (int i = 0; i < GEM_SLOTS_MAX_NUM; ++i)
  10261. {
  10262. if (m_gemItems[i].bItemId == 0)
  10263. {
  10264. if (i >= 0 && i < 3)
  10265. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(1);
  10266. else if (i >= 3 && i < 6)
  10267. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(2);
  10268. else if (i >= 6 && i < 9)
  10269. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(3);
  10270.  
  10271. if (i > 2)
  10272. m_gemItems[i].bSlotStatus = 1;
  10273. else
  10274. m_gemItems[i].bSlotStatus = 0;
  10275. }
  10276. else
  10277. {
  10278. if (i >= 0 && i < 3)
  10279. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(1);
  10280. else if (i >= 3 && i < 6)
  10281. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(2);
  10282. else if (i >= 6 && i < 9)
  10283. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(3);
  10284. }
  10285. }
  10286.  
  10287. m_dwGemNextRefresh = time(NULL) + 18000;
  10288. }
  10289.  
  10290. void CHARACTER::RefreshGemShopItems()
  10291. {
  10292. for (int i = 0; i < GEM_SLOTS_MAX_NUM; ++i)
  10293. {
  10294. if (i >= 0 && i < 3)
  10295. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(1);
  10296. else if (i >= 3 && i < 6)
  10297. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(2);
  10298. else if (i >= 6 && i < 9)
  10299. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(3);
  10300. }
  10301.  
  10302. m_dwGemNextRefresh = time(NULL) + 18000;
  10303. }
  10304.  
  10305. void CHARACTER::RefreshGemShopWithItem()
  10306. {
  10307. if(CountSpecifyItem(39063) < 1){
  10308. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Nu ai suficiente iteme Gaya Market."));
  10309. return;
  10310. }
  10311.  
  10312. RemoveSpecifyItem(39063, 1);
  10313.  
  10314. for (int i = 0; i < GEM_SLOTS_MAX_NUM; ++i)
  10315. {
  10316. if (i >= 0 && i < 3)
  10317. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(1);
  10318. else if (i >= 3 && i < 6)
  10319. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(2);
  10320. else if (i >= 6 && i < 9)
  10321. m_gemItems[i].bItemId = CShopManager::instance().GemShopGetRandomId(3);
  10322. }
  10323.  
  10324. m_dwGemNextRefresh = time(NULL) + 18000;
  10325.  
  10326. RefreshGemShop();
  10327. }
  10328.  
  10329. void CHARACTER::GemShopBuy(BYTE bPos)
  10330. {
  10331. if (bPos >= GEM_SLOTS_MAX_NUM){
  10332. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Slot overflow."));
  10333. return;
  10334. }
  10335.  
  10336. DWORD dwVnum = CShopManager::instance().GemShopGetVnumById(m_gemItems[bPos].bItemId);
  10337. BYTE bCount = CShopManager::instance().GemShopGetCountById(m_gemItems[bPos].bItemId);
  10338. DWORD dwPrice = CShopManager::instance().GemShopGetPriceById(m_gemItems[bPos].bItemId);
  10339.  
  10340. if (GetGem() < (int) dwPrice){
  10341. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Nu ai suficient Gaya."));
  10342. return;
  10343. }
  10344.  
  10345. if(m_gemItems[bPos].bSlotStatus == 1){
  10346. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Acest slot nu este deblocat."));
  10347. return;
  10348. }
  10349.  
  10350. LPITEM item = ITEM_MANAGER::instance().CreateItem(dwVnum, bCount);
  10351.  
  10352. if(item)
  10353. {
  10354. int iEmptyPos;
  10355. if (item->IsDragonSoul())
  10356. {
  10357. iEmptyPos = GetEmptyDragonSoulInventory(item);
  10358. }
  10359. else
  10360. {
  10361. iEmptyPos = GetEmptyInventory(item->GetSize());
  10362. }
  10363.  
  10364. if (iEmptyPos < 0){
  10365. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Nu ai suficient spatiu."));
  10366. return;
  10367. }
  10368.  
  10369. PointChange(POINT_GEM, -dwPrice, false);
  10370.  
  10371. if (item->IsDragonSoul())
  10372. item->AddToCharacter(this, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  10373. else
  10374. item->AddToCharacter(this, TItemPos(INVENTORY, iEmptyPos));
  10375.  
  10376. ITEM_MANAGER::instance().FlushDelayedSave(item);
  10377. }
  10378. }
  10379.  
  10380. void CHARACTER::GemShopAdd(BYTE bPos)
  10381. {
  10382. BYTE needCount[] = {0, 0, 0, 1, 2, 4, 8, 8, 8};
  10383.  
  10384. if (bPos >= GEM_SLOTS_MAX_NUM){
  10385. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Slot overflow."));
  10386. return;
  10387. }
  10388.  
  10389. if(CountSpecifyItem(39064) < needCount[bPos]){
  10390. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Nu ai suficiente : Gaya Market Expansion.Ai nevoie de mai multe %d pentru a debloca acest slot."), needCount[bPos] - CountSpecifyItem(39064));
  10391. return;
  10392. }
  10393.  
  10394. if(m_gemItems[bPos].bSlotStatus == 0){
  10395. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Gaya] Nu se mai poate debloca un alt slot."));
  10396. return;
  10397. }
  10398.  
  10399. RemoveSpecifyItem(39064, needCount[bPos]);
  10400.  
  10401. m_gemItems[bPos].bSlotStatus = 0;
  10402.  
  10403. RefreshGemShop();
  10404. }
  10405.  
  10406. void CHARACTER::RefreshGemShop()
  10407. {
  10408. TPacketGCGemShopRefresh pack;
  10409. pack.header = HEADER_GC_GEM_SHOP_REFRESH;
  10410. pack.nextRefreshTime = GetGemNextRefresh() - time(NULL);
  10411.  
  10412. for (int i = 0; i < GEM_SLOTS_MAX_NUM; ++i)
  10413. {
  10414. pack.shopItems[i].slotIndex = i;
  10415. pack.shopItems[i].status = m_gemItems[i].bSlotStatus;
  10416.  
  10417. pack.shopItems[i].dwVnum = CShopManager::instance().GemShopGetVnumById(m_gemItems[i].bItemId);
  10418. pack.shopItems[i].bCount = CShopManager::instance().GemShopGetCountById(m_gemItems[i].bItemId);
  10419. pack.shopItems[i].dwPrice = CShopManager::instance().GemShopGetPriceById(m_gemItems[i].bItemId);
  10420. }
  10421.  
  10422. GetDesc()->Packet(&pack, sizeof(TPacketGCGemShopRefresh));
  10423. }
  10424.  
  10425. void CHARACTER::OpenGemShop()
  10426. {
  10427. if(GetGemNextRefresh() == 0)
  10428. OpenGemShopFirstTime();
  10429.  
  10430. if((int)GetGemNextRefresh() - time(NULL) <= 0)
  10431. RefreshGemShopItems();
  10432.  
  10433. TPacketGCGemShopOpen pack;
  10434. pack.header = HEADER_GC_GEM_SHOP_OPEN;
  10435. pack.nextRefreshTime = GetGemNextRefresh() - time(NULL);
  10436.  
  10437. for (int i = 0; i < GEM_SLOTS_MAX_NUM; ++i)
  10438. {
  10439. pack.shopItems[i].slotIndex = i;
  10440. pack.shopItems[i].status = m_gemItems[i].bSlotStatus;
  10441.  
  10442. pack.shopItems[i].dwVnum = CShopManager::instance().GemShopGetVnumById(m_gemItems[i].bItemId);
  10443. pack.shopItems[i].bCount = CShopManager::instance().GemShopGetCountById(m_gemItems[i].bItemId);
  10444. pack.shopItems[i].dwPrice = CShopManager::instance().GemShopGetPriceById(m_gemItems[i].bItemId);
  10445. }
  10446.  
  10447. GetDesc()->Packet(&pack, sizeof(TPacketGCGemShopOpen));
  10448. }
  10449.  
  10450. bool CHARACTER::CreateGaya(int glimmerstone_count, LPITEM metinstone_item, long long cost, int pct)
  10451. {
  10452. if (!this)
  10453. return false;
  10454.  
  10455. if (!metinstone_item)
  10456. return false;
  10457.  
  10458. if (CountSpecifyItem(50926) < glimmerstone_count)
  10459. {
  10460. //ChatPacket(CHAT_TYPE_INFO, "NOT_ENOUGHT_COUNT");
  10461. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGHT_COUNT"));
  10462. return false;
  10463. }
  10464.  
  10465. if (this->GetGold() < cost)
  10466. {
  10467. //ChatPacket(CHAT_TYPE_INFO, "NOT_ENOUGHT_YANG");
  10468. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGHT_YANG"));
  10469. return false;
  10470. }
  10471.  
  10472. RemoveSpecifyItem(50926, glimmerstone_count);
  10473.  
  10474. if (metinstone_item)
  10475. metinstone_item->SetCount(metinstone_item->GetCount() - 1);
  10476. // ITEM_MANAGER::instance().RemoveItem(metinstone_item, "REMOVE (GAYA)");
  10477.  
  10478. PointChange(POINT_GOLD, -cost, false);
  10479.  
  10480. if (number(1, 100) <= pct)
  10481. {
  10482. PointChange(POINT_GEM, 1, false);
  10483. return true;
  10484. }
  10485.  
  10486. return false;
  10487. }
  10488. #endif
  10489.  
  10490. std::string CHARACTER::GetLang() {
  10491. if (GetDesc() != NULL)
  10492. return "ro";
  10493. return "de";
  10494. }
  10495.  
  10496. DWORD CHARACTER::Ep_Miktar()
  10497. {
  10498. std::unique_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT monede FROM account.account WHERE id = '%d';", GetDesc()->GetAccountTable().id));
  10499. if (pMsg->Get()->uiNumRows == 0)
  10500. return 0;
  10501.  
  10502. MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
  10503. DWORD ep = 0;
  10504. str_to_number(ep, row[0]);
  10505. return ep;
  10506. }
  10507.  
  10508. void CHARACTER::Set_Ep(DWORD black)
  10509. {
  10510. DBManager::instance().DirectQuery("UPDATE account.account SET monede = '%d' WHERE id = '%d';", black, GetDesc()->GetAccountTable().id);
  10511. }
  10512.  
  10513. #ifdef NEW_PET_SUMMON
  10514. void CHARACTER::PetSummon(LPITEM petItem)
  10515. {
  10516. CPetSystem* petSystem = GetPetSystem();
  10517. DWORD mobVnum = 0;
  10518.  
  10519. if (GetMapIndex() == 113)
  10520. return;
  10521.  
  10522. if (!petSystem || !petItem)
  10523. return;
  10524.  
  10525. if(petItem->GetValue(1) != 0)
  10526. mobVnum = petItem->GetValue(1);
  10527.  
  10528. petSystem->Summon(mobVnum, petItem, false);
  10529. }
  10530.  
  10531. void CHARACTER::PetUnsummon(LPITEM petItem)
  10532. {
  10533. CPetSystem* petSystem = GetPetSystem();
  10534. DWORD mobVnum = 0;
  10535.  
  10536. if (!petSystem || !petItem)
  10537. return;
  10538.  
  10539. if(petItem->GetValue(1) != 0)
  10540. mobVnum = petItem->GetValue(1);
  10541.  
  10542. petSystem->Unsummon(mobVnum);
  10543. }
  10544.  
  10545. void CHARACTER::CheckPet()
  10546. {
  10547. CPetSystem* petSystem = GetPetSystem();
  10548. LPITEM petItem = GetWear(WEAR_NORMAL_PET);
  10549. DWORD mobVnum = 0;
  10550.  
  10551. if (GetMapIndex() == 113)
  10552. return;
  10553.  
  10554. if (!petSystem || !petItem)
  10555. return;
  10556.  
  10557. if(petItem->GetValue(1) != 0)
  10558. mobVnum = petItem->GetValue(1);
  10559.  
  10560. if(petSystem->CountSummoned() == 0)
  10561. {
  10562. petSystem->Summon(mobVnum, petItem, false);
  10563. }
  10564. }
  10565.  
  10566. bool CHARACTER::IsPetSummon()
  10567. {
  10568. return (GetWear(WEAR_NORMAL_PET));
  10569. }
  10570.  
  10571. void CHARACTER::BuffSummon(LPITEM buffItem)
  10572. {
  10573. CSupportSystem* buffSystem = GetSupportSystem();
  10574. DWORD mobVnum = 0;
  10575.  
  10576. if (GetMapIndex() == 113 || GetMapIndex() == 1 || GetMapIndex() == 21 || GetMapIndex() == 41)
  10577. return;
  10578.  
  10579. if (!buffSystem || !buffItem)
  10580. return;
  10581.  
  10582. if(buffItem->GetValue(1) != 0)
  10583. mobVnum = buffItem->GetValue(1);
  10584.  
  10585. buffSystem->Summon(mobVnum, buffItem, false);
  10586. }
  10587.  
  10588. void CHARACTER::BuffUnsummon(LPITEM buffItem)
  10589. {
  10590. CSupportSystem* buffSystem = GetSupportSystem();
  10591. DWORD mobVnum = 0;
  10592.  
  10593. if (!buffSystem || !buffItem)
  10594. return;
  10595.  
  10596. if(buffItem->GetValue(1) != 0)
  10597. mobVnum = buffItem->GetValue(1);
  10598.  
  10599. buffSystem->Unsummon(mobVnum);
  10600. }
  10601.  
  10602. void CHARACTER::CheckBuff()
  10603. {
  10604. CSupportSystem* buffSystem = GetSupportSystem();
  10605. LPITEM buffItem = GetWear(WEAR_NORMAL_BUFF);
  10606. DWORD mobVnum = 0;
  10607.  
  10608. if (GetMapIndex() == 113 || GetMapIndex() == 1 || GetMapIndex() == 21 || GetMapIndex() == 41)
  10609. return;
  10610.  
  10611. if (!buffSystem || !buffItem)
  10612. return;
  10613.  
  10614. if(buffItem->GetValue(1) != 0)
  10615. mobVnum = buffItem->GetValue(1);
  10616.  
  10617. if(buffSystem->CountSummoned() == 0)
  10618. {
  10619. buffSystem->Summon(mobVnum, buffItem, false);
  10620. }
  10621. }
  10622.  
  10623. bool CHARACTER::IsBuffSummon()
  10624. {
  10625. return (GetWear(WEAR_NORMAL_BUFF));
  10626. }
  10627. #endif
  10628.  
  10629. #ifdef ENABLE_FISH_EVENT
  10630. void CHARACTER::FishEventGeneralInfo()
  10631. {
  10632. if (!GetDesc())
  10633. return;
  10634.  
  10635. TPacketGCFishEventInfo packFishEvent;
  10636. packFishEvent.bHeader = HEADER_GC_FISH_EVENT_INFO;
  10637. packFishEvent.bSubheader = FISH_EVENT_SUBHEADER_GC_ENABLE;
  10638. packFishEvent.dwFirstArg = quest::CQuestManager::instance().GetEventFlag("enable_fish_event");
  10639. packFishEvent.dwSecondArg = GetFishEventUseCount();
  10640. GetDesc()->Packet(&packFishEvent, sizeof(TPacketGCFishEventInfo));
  10641.  
  10642. if(GetFishEventUseCount() == 0)
  10643. {
  10644. for(int i = 0; i < FISH_EVENT_SLOTS_NUM; i++)
  10645. {
  10646. m_fishSlots[i].bIsMain = false;
  10647. m_fishSlots[i].bShape = 0;
  10648. }
  10649. }
  10650.  
  10651. for(int i = 0; i < FISH_EVENT_SLOTS_NUM; i++)
  10652. {
  10653. if(m_fishSlots[i].bIsMain)
  10654. {
  10655. TPacketGCFishEventInfo packFishEvent;
  10656. packFishEvent.bHeader = HEADER_GC_FISH_EVENT_INFO;
  10657. packFishEvent.bSubheader = FISH_EVENT_SUBHEADER_SHAPE_ADD;
  10658. packFishEvent.dwFirstArg = i;
  10659. packFishEvent.dwSecondArg = m_fishSlots[i].bShape;
  10660. GetDesc()->Packet(&packFishEvent, sizeof(TPacketGCFishEventInfo));
  10661. }
  10662. }
  10663. }
  10664.  
  10665. void CHARACTER::FishEventUseBox(TItemPos itemPos)
  10666. {
  10667. if(itemPos.window_type != INVENTORY)
  10668. return;
  10669.  
  10670. if (!GetDesc())
  10671. return;
  10672.  
  10673. LPITEM item;
  10674.  
  10675. if (!CanHandleItem())
  10676. return;
  10677.  
  10678. if (!IsValidItemPosition(itemPos) || !(item = GetItem(itemPos)))
  10679. return;
  10680.  
  10681. if (item->IsExchanging())
  10682. return;
  10683.  
  10684. if(item->GetVnum() == ITEM_FISH_EVENT_BOX)
  10685. {
  10686. BYTE randomShape = number(FISH_EVENT_SHAPE_1, FISH_EVENT_SHAPE_6);
  10687. SetFishAttachedShape(randomShape);
  10688. FishEventIncreaseUseCount();
  10689. item->SetCount(item->GetCount() - 1);
  10690. }
  10691. else if(item->GetVnum() == ITEM_FISH_EVENT_BOX_SPECIAL)
  10692. {
  10693. SetFishAttachedShape(FISH_EVENT_SHAPE_7);
  10694. FishEventIncreaseUseCount();
  10695. item->SetCount(item->GetCount() - 1);
  10696. }
  10697. else
  10698. {
  10699. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can not use this item here."));
  10700. return;
  10701. }
  10702.  
  10703. TPacketGCFishEventInfo packFishEvent;
  10704. packFishEvent.bHeader = HEADER_GC_FISH_EVENT_INFO;
  10705. packFishEvent.bSubheader = FISH_EVENT_SUBHEADER_BOX_USE;
  10706. packFishEvent.dwFirstArg = GetFishAttachedShape();
  10707. packFishEvent.dwSecondArg = GetFishEventUseCount();
  10708. GetDesc()->Packet(&packFishEvent, sizeof(TPacketGCFishEventInfo));
  10709. }
  10710.  
  10711. bool CHARACTER::FishEventIsValidPosition(BYTE shapePos, BYTE shapeType)
  10712. {
  10713. bool finalReturn = false;
  10714.  
  10715. BYTE positionList[7][8] = {
  10716. { FISH_EVENT_SHAPE_1, 12, 0, 6, 12, 0, 0, 0 },
  10717. { FISH_EVENT_SHAPE_2, 24, 0, 0, 0, 0, 0, 0 },
  10718. { FISH_EVENT_SHAPE_3, 17, 0, 6, 7, 0, 0, 0 },
  10719. { FISH_EVENT_SHAPE_4, 17, 0, 1, 7, 0, 0, 0 },
  10720. { FISH_EVENT_SHAPE_5, 17, 0, 1, 6, 7, 0, 0 },
  10721. { FISH_EVENT_SHAPE_6, 16, 0, 1, 7, 8, 0, 0 },
  10722. { FISH_EVENT_SHAPE_7, 16, 0, 1, 2, 6, 7, 8 },
  10723. };
  10724.  
  10725. for(int i = 0; i < sizeof(positionList)/sizeof(positionList[0]); i++)
  10726. {
  10727. if(positionList[i][0] == shapeType)
  10728. {
  10729. for(int j = 0; j < positionList[i][1]; j++)
  10730. {
  10731. if (shapePos == j
  10732. && m_fishSlots[j + positionList[i][2]].bShape == 0
  10733. && m_fishSlots[j + positionList[i][3]].bShape == 0
  10734. && m_fishSlots[j + positionList[i][4]].bShape == 0
  10735. && m_fishSlots[j + positionList[i][5]].bShape == 0
  10736. && m_fishSlots[j + positionList[i][6]].bShape == 0
  10737. && m_fishSlots[j + positionList[i][7]].bShape == 0)
  10738. {
  10739. finalReturn = true;
  10740. break;
  10741. }
  10742. }
  10743.  
  10744. break;
  10745. }
  10746. }
  10747.  
  10748. return finalReturn;
  10749. }
  10750.  
  10751. void CHARACTER::FishEventPlaceShape(BYTE shapePos, BYTE shapeType)
  10752. {
  10753. BYTE positionList[7][7] = {
  10754. { FISH_EVENT_SHAPE_1, 0, 6, 12, 0, 0, 0 },
  10755. { FISH_EVENT_SHAPE_2, 0, 0, 0, 0, 0, 0 },
  10756. { FISH_EVENT_SHAPE_3, 0, 6, 7, 0, 0, 0 },
  10757. { FISH_EVENT_SHAPE_4, 0, 1, 7, 0, 0, 0 },
  10758. { FISH_EVENT_SHAPE_5, 0, 1, 6, 7, 0, 0 },
  10759. { FISH_EVENT_SHAPE_6, 0, 1, 7, 8, 0, 0 },
  10760. { FISH_EVENT_SHAPE_7, 0, 1, 2, 6, 7, 8 },
  10761. };
  10762.  
  10763. for(int i = 0; i < sizeof(positionList)/sizeof(positionList[0]); i++)
  10764. {
  10765. if(positionList[i][0] == shapeType)
  10766. {
  10767. for(int j = 1; j < 7; j++)
  10768. {
  10769. if(j > 1 && positionList[i][j] == 0)
  10770. continue;
  10771.  
  10772. if(positionList[i][j] == 0)
  10773. {
  10774. m_fishSlots[shapePos].bIsMain = true;
  10775. m_fishSlots[shapePos].bShape = shapeType;
  10776. }
  10777. else
  10778. {
  10779. m_fishSlots[shapePos + positionList[i][j]].bIsMain = false;
  10780. m_fishSlots[shapePos + positionList[i][j]].bShape = shapeType;
  10781. }
  10782. }
  10783.  
  10784. break;
  10785. }
  10786. }
  10787. }
  10788.  
  10789. void CHARACTER::FishEventCheckEnd()
  10790. {
  10791. bool isComplete = true;
  10792.  
  10793. for(int i = 0; i < FISH_EVENT_SLOTS_NUM; i++)
  10794. {
  10795. if(m_fishSlots[i].bShape == 0)
  10796. {
  10797. isComplete = false;
  10798. break;
  10799. }
  10800. }
  10801.  
  10802. if(isComplete)
  10803. {
  10804. DWORD dwUseCount = GetFishEventUseCount();
  10805. DWORD dwRewardVnum = dwUseCount <= 10 ? 25113 : (dwUseCount <= 24 ? 25112 : 25111);
  10806.  
  10807. for(int i = 0; i < FISH_EVENT_SLOTS_NUM; i++)
  10808. {
  10809. m_fishSlots[i].bIsMain = false;
  10810. m_fishSlots[i].bShape = 0;
  10811. }
  10812.  
  10813. AutoGiveItem(dwRewardVnum);
  10814. PointChange(POINT_EXP, 30000);
  10815.  
  10816. m_dwFishUseCount = 0;
  10817. SetFishAttachedShape(0);
  10818.  
  10819. TPacketGCFishEventInfo packFishEvent;
  10820. packFishEvent.bHeader = HEADER_GC_FISH_EVENT_INFO;
  10821. packFishEvent.bSubheader = FISH_EVENT_SUBHEADER_GC_REWARD;
  10822. packFishEvent.dwFirstArg = dwRewardVnum;
  10823. packFishEvent.dwSecondArg = 0;
  10824. GetDesc()->Packet(&packFishEvent, sizeof(TPacketGCFishEventInfo));
  10825. }
  10826. }
  10827.  
  10828. void CHARACTER::FishEventAddShape(BYTE shapePos)
  10829. {
  10830. if (!GetDesc())
  10831. return;
  10832.  
  10833. if(shapePos >= FISH_EVENT_SLOTS_NUM)
  10834. return;
  10835.  
  10836. BYTE lastAttachedShape = GetFishAttachedShape();
  10837.  
  10838. if(lastAttachedShape == 0 || lastAttachedShape > ITEM_FISH_EVENT_BOX_SPECIAL)
  10839. return;
  10840.  
  10841. if(!FishEventIsValidPosition(shapePos, lastAttachedShape))
  10842. {
  10843. TPacketGCFishEventInfo packFishEvent;
  10844. packFishEvent.bHeader = HEADER_GC_FISH_EVENT_INFO;
  10845. packFishEvent.bSubheader = FISH_EVENT_SUBHEADER_BOX_USE;
  10846. packFishEvent.dwFirstArg = GetFishAttachedShape();
  10847. packFishEvent.dwSecondArg = GetFishEventUseCount();
  10848. GetDesc()->Packet(&packFishEvent, sizeof(TPacketGCFishEventInfo));
  10849.  
  10850. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("That shape can not fit in this position."));
  10851. return;
  10852. }
  10853.  
  10854. FishEventPlaceShape(shapePos, lastAttachedShape);
  10855.  
  10856. TPacketGCFishEventInfo packFishEvent;
  10857. packFishEvent.bHeader = HEADER_GC_FISH_EVENT_INFO;
  10858. packFishEvent.bSubheader = FISH_EVENT_SUBHEADER_SHAPE_ADD;
  10859. packFishEvent.dwFirstArg = shapePos;
  10860. packFishEvent.dwSecondArg = lastAttachedShape;
  10861. GetDesc()->Packet(&packFishEvent, sizeof(TPacketGCFishEventInfo));
  10862.  
  10863. FishEventCheckEnd();
  10864. }
  10865. #endif
  10866.  
  10867. void CHARACTER::EquipTitle(LPITEM item)
  10868. {
  10869. DWORD iTitle = item->GetValue(1);
  10870. SetPoint(POINT_TITLE, iTitle);
  10871. ComputePoints();
  10872. PointsPacket();
  10873. UpdatePacket();
  10874. }
  10875.  
  10876. void CHARACTER::UnequipTitle(LPITEM item)
  10877. {
  10878. SetPoint(POINT_TITLE, 0);
  10879. ComputePoints();
  10880. PointsPacket();
  10881. UpdatePacket();
  10882. }
  10883.  
  10884. void CHARACTER::CheckTitle()
  10885. {
  10886. LPITEM item = GetWear(WEAR_NORMAL_BUFF);
  10887. DWORD iTitle = item->GetValue(1);
  10888. SetPoint(POINT_TITLE, iTitle);
  10889. }
  10890. #ifdef ENABLE_AFTERDEATH_SHIELD
  10891. EVENTINFO(shield_countdown_data)
  10892. {
  10893. int seconds;
  10894. LPCHARACTER ch;
  10895. };
  10896.  
  10897. static LPEVENT timer_shieldcountdown_check = NULL;
  10898.  
  10899. EVENTFUNC(ShieldCountdown_Timer_Event)
  10900. {
  10901. shield_countdown_data* info = dynamic_cast<shield_countdown_data*>(event->info);
  10902.  
  10903. if (info == NULL)
  10904. {
  10905. sys_err("Afterdeath Shield - ERROR: ShieldCountdown_Timer_Event> <Factor> Time 0 - Error");
  10906. return 0;
  10907. }
  10908.  
  10909. int * pTimer = &(info->seconds);
  10910. LPCHARACTER ch = info->ch;
  10911.  
  10912. if(ch == NULL || ch->GetDesc() == NULL || !ch->IsAffectFlag(AFF_AFTERDEATH_SHIELD))
  10913. {
  10914. if(!ch->IsAffectFlag(AFF_AFTERDEATH_SHIELD))
  10915. ch->UpdatePacket();
  10916. timer_shieldcountdown_check = NULL;
  10917. return 0;
  10918. }
  10919.  
  10920. if (*pTimer == 0)
  10921. {
  10922. ch->RemoveShieldAffect();
  10923. ch->UpdatePacket();
  10924. }
  10925. else
  10926. {
  10927. --*pTimer;
  10928. return passes_per_sec;
  10929. }
  10930.  
  10931. timer_shieldcountdown_check = NULL;
  10932. return 0;
  10933. }
  10934.  
  10935. void CHARACTER::StartShieldCountdownEvent(LPCHARACTER ch, int iSec)
  10936. {
  10937.  
  10938. if(ch == NULL || ch->GetDesc() == NULL)
  10939. return;
  10940.  
  10941. shield_countdown_data* info = AllocEventInfo<shield_countdown_data>();
  10942. info->seconds = iSec;
  10943. info->ch = ch;
  10944. timer_shieldcountdown_check = event_create(ShieldCountdown_Timer_Event, info, 1);
  10945. }
  10946. #endif
  10947.  
Advertisement
Add Comment
Please, Sign In to add comment