1. #include "stdafx.h"
  2. #include "dungeon.h"
  3. #include "char.h"
  4. #include "char_manager.h"
  5. #include "party.h"
  6. #ifdef ENABLE_D_NJGUILD
  7. #include "guild.h"
  8. #endif
  9. #include "affect.h"
  10. #include "packet.h"
  11. #include "desc.h"
  12. #include "config.h"
  13. #include "regen.h"
  14. #include "start_position.h"
  15. #include "item.h"
  16. #include "item_manager.h"
  17. #include "utils.h"
  18. #include "questmanager.h"
  19. CDungeon::CDungeon(IdType id, long lOriginalMapIndex, long lMapIndex)
  20. : m_id(id),
  21. m_lOrigMapIndex(lOriginalMapIndex),
  22. m_lMapIndex(lMapIndex),
  23. m_map_Area(SECTREE_MANAGER::instance().GetDungeonArea(lOriginalMapIndex))
  24. {
  25. Initialize();
  26. //sys_log(0,"DUNGEON create orig %d real %d", lOriginalMapIndex, lMapIndex);
  27. }
  28. CDungeon::~CDungeon()
  29. {
  30. if (m_pParty != NULL)
  31. {
  32. m_pParty->SetDungeon_for_Only_party (NULL);
  33. }
  34. //sys_log(0,"DUNGEON destroy orig %d real %d", m_lOrigMapIndex, m_lMapIndex );
  35. ClearRegen();
  36. event_cancel(&deadEvent);
  37. // <Factor>
  38. event_cancel(&exit_all_event_);
  39. event_cancel(&jump_to_event_);
  40. }
  41. void CDungeon::Initialize()
  42. {
  43. deadEvent = NULL;
  44. // <Factor>
  45. exit_all_event_ = NULL;
  46. jump_to_event_ = NULL;
  47. regen_id_ = 0;
  48. m_iMobKill = 0;
  49. m_iStoneKill = 0;
  50. m_bUsePotion = false;
  51. m_bUseRevive = false;
  52. m_iMonsterCount = 0;
  53. m_bExitAllAtEliminate = false;
  54. m_bWarpAtEliminate = false;
  55. m_iWarpDelay = 0;
  56. m_lWarpMapIndex = 0;
  57. m_lWarpX = 0;
  58. m_lWarpY = 0;
  59. m_stRegenFile = "";
  60. m_pParty = NULL;
  61. }
  62. void CDungeon::SetFlag(std::string name, int value)
  63. {
  64. itertype(m_map_Flag) it = m_map_Flag.find(name);
  65. if (it != m_map_Flag.end())
  66. it->second = value;
  67. else
  68. m_map_Flag.insert(make_pair(name, value));
  69. }
  70. int CDungeon::GetFlag(std::string name)
  71. {
  72. itertype(m_map_Flag) it = m_map_Flag.find(name);
  73. if (it != m_map_Flag.end())
  74. return it->second;
  75. else
  76. return 0;
  77. }
  78. struct FSendDestPosition
  79. {
  80. FSendDestPosition(long x, long y)
  81. {
  82. p1.bHeader = HEADER_GC_DUNGEON;
  83. p1.subheader = DUNGEON_SUBHEADER_GC_DESTINATION_POSITION;
  84. p2.x = x;
  85. p2.y = y;
  86. p1.size = sizeof(p1)+sizeof(p2);
  87. }
  88. void operator()(LPCHARACTER ch)
  89. {
  90. ch->GetDesc()->BufferedPacket(&p1, sizeof(TPacketGCDungeon));
  91. ch->GetDesc()->Packet(&p2, sizeof(TPacketGCDungeonDestPosition));
  92. }
  93. TPacketGCDungeon p1;
  94. TPacketGCDungeonDestPosition p2;
  95. };
  96. void CDungeon::SendDestPositionToParty(LPPARTY pParty, long x, long y)
  97. {
  98. if (m_map_pkParty.find(pParty) == m_map_pkParty.end())
  99. {
  100. sys_err("PARTY %u not in DUNGEON %d", pParty->GetLeaderPID(), m_lMapIndex);
  101. return;
  102. }
  103. FSendDestPosition f(x, y);
  104. pParty->ForEachNearMember(f);
  105. }
  106. struct FWarpToDungeon
  107. {
  108. FWarpToDungeon(long lMapIndex, LPDUNGEON d)
  109. : m_lMapIndex(lMapIndex), m_pkDungeon(d)
  110. {
  111. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(lMapIndex);
  112. m_x = pkSectreeMap->m_setting.posSpawn.x;
  113. m_y = pkSectreeMap->m_setting.posSpawn.y;
  114. }
  115. void operator () (LPCHARACTER ch)
  116. {
  117. ch->SaveExitLocation();
  118. ch->WarpSet(m_x, m_y, m_lMapIndex);
  119. //m_pkDungeon->IncPartyMember(ch->GetParty());
  120. }
  121. long m_lMapIndex;
  122. long m_x;
  123. long m_y;
  124. LPDUNGEON m_pkDungeon;
  125. };
  126. void CDungeon::Join(LPCHARACTER ch)
  127. {
  128. if (SECTREE_MANAGER::instance().GetMap(m_lMapIndex) == NULL) {
  129. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  130. return;
  131. }
  132. FWarpToDungeon(m_lMapIndex, this) (ch);
  133. }
  134. void CDungeon::JoinParty(LPPARTY pParty)
  135. {
  136. pParty->SetDungeon(this); // @warme011 the begin of the nightmare
  137. m_map_pkParty.insert(std::make_pair(pParty,0));
  138. if (SECTREE_MANAGER::instance().GetMap(m_lMapIndex) == NULL) {
  139. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  140. return;
  141. }
  142. FWarpToDungeon f(m_lMapIndex, this);
  143. pParty->ForEachOnlineMember(f);
  144. //sys_log(0, "DUNGEON-PARTY join %p %p", this, pParty);
  145. }
  146. void CDungeon::QuitParty(LPPARTY pParty)
  147. {
  148. pParty->SetDungeon(NULL);
  149. //sys_log(0, "DUNGEON-PARTY quit %p %p", this, pParty);
  150. TPartyMap::iterator it = m_map_pkParty.find(pParty); // @warme011 boom! crash!
  151. if (it != m_map_pkParty.end())
  152. m_map_pkParty.erase(it);
  153. }
  154. EVENTINFO(dungeon_id_info)
  155. {
  156. CDungeon::IdType dungeon_id;
  157. dungeon_id_info()
  158. : dungeon_id(0)
  159. {
  160. }
  161. };
  162. EVENTFUNC(dungeon_dead_event)
  163. {
  164. dungeon_id_info* info = dynamic_cast<dungeon_id_info*>( event->info );
  165. if ( info == NULL )
  166. {
  167. sys_err( "dungeon_dead_event> <Factor> Null pointer" );
  168. return 0;
  169. }
  170. LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
  171. if (pDungeon == NULL) {
  172. return 0;
  173. }
  174. pDungeon->deadEvent = NULL;
  175. CDungeonManager::instance().Destroy(info->dungeon_id);
  176. return 0;
  177. }
  178. void CDungeon::IncMember(LPCHARACTER ch)
  179. {
  180. if (m_set_pkCharacter.find(ch) == m_set_pkCharacter.end())
  181. m_set_pkCharacter.insert(ch);
  182. event_cancel(&deadEvent);
  183. }
  184. void CDungeon::DecMember(LPCHARACTER ch)
  185. {
  186. itertype(m_set_pkCharacter) it = m_set_pkCharacter.find(ch);
  187. if (it == m_set_pkCharacter.end()) {
  188. return;
  189. }
  190. m_set_pkCharacter.erase(it);
  191. if (m_set_pkCharacter.empty())
  192. {
  193. dungeon_id_info* info = AllocEventInfo<dungeon_id_info>();
  194. info->dungeon_id = m_id;
  195. event_cancel(&deadEvent);
  196. deadEvent = event_create(dungeon_dead_event, info, PASSES_PER_SEC(10));
  197. }
  198. }
  199. void CDungeon::IncPartyMember(LPPARTY pParty, LPCHARACTER ch)
  200. {
  201. //sys_log(0, "DUNGEON-PARTY inc %p %p", this, pParty);
  202. TPartyMap::iterator it = m_map_pkParty.find(pParty);
  203. if (it != m_map_pkParty.end())
  204. it->second++;
  205. else
  206. m_map_pkParty.insert(std::make_pair(pParty,1));
  207. IncMember(ch);
  208. }
  209. void CDungeon::DecPartyMember(LPPARTY pParty, LPCHARACTER ch)
  210. {
  211. //sys_log(0, "DUNGEON-PARTY dec %p %p", this, pParty);
  212. TPartyMap::iterator it = m_map_pkParty.find(pParty);
  213. if (it == m_map_pkParty.end())
  214. sys_err("cannot find party");
  215. else
  216. {
  217. it->second--;
  218. if (it->second == 0)
  219. QuitParty(pParty);
  220. }
  221. DecMember(ch);
  222. }
  223. struct FWarpToPosition
  224. {
  225. long lMapIndex;
  226. long x;
  227. long y;
  228. FWarpToPosition(long lMapIndex, long x, long y)
  229. : lMapIndex(lMapIndex), x(x), y(y)
  230. {}
  231. void operator()(LPENTITY ent)
  232. {
  233. if (!ent->IsType(ENTITY_CHARACTER)) {
  234. return;
  235. }
  236. LPCHARACTER ch = (LPCHARACTER)ent;
  237. if (!ch->IsPC()) {
  238. return;
  239. }
  240. if (ch->GetMapIndex() == lMapIndex)
  241. {
  242. ch->Show(lMapIndex, x, y, 0);
  243. ch->Stop();
  244. }
  245. else
  246. {
  247. ch->WarpSet(x,y,lMapIndex);
  248. }
  249. }
  250. };
  251. struct FWarpToPositionForce
  252. {
  253. long lMapIndex;
  254. long x;
  255. long y;
  256. FWarpToPositionForce(long lMapIndex, long x, long y)
  257. : lMapIndex(lMapIndex), x(x), y(y)
  258. {}
  259. void operator()(LPENTITY ent)
  260. {
  261. if (!ent->IsType(ENTITY_CHARACTER)) {
  262. return;
  263. }
  264. LPCHARACTER ch = (LPCHARACTER)ent;
  265. if (!ch->IsPC()) {
  266. return;
  267. }
  268. ch->WarpSet(x,y,lMapIndex);
  269. }
  270. };
  271. void CDungeon::JumpAll(long lFromMapIndex, int x, int y)
  272. {
  273. x *= 100;
  274. y *= 100;
  275. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
  276. if (!pMap)
  277. {
  278. sys_err("cannot find map by index %d", lFromMapIndex);
  279. return;
  280. }
  281. FWarpToPosition f(m_lMapIndex, x, y);
  282. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  283. pMap->for_each(f);
  284. }
  285. void CDungeon::WarpAll(long lFromMapIndex, int x, int y)
  286. {
  287. x *= 100;
  288. y *= 100;
  289. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
  290. if (!pMap)
  291. {
  292. sys_err("cannot find map by index %d", lFromMapIndex);
  293. return;
  294. }
  295. FWarpToPositionForce f(m_lMapIndex, x, y);
  296. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  297. pMap->for_each(f);
  298. }
  299. #ifdef ENABLE_D_NJGUILD
  300. void CDungeon::JumpGuild(CGuild* pGuild, long lFromMapIndex, int x, int y)
  301. {
  302. x *= 100;
  303. y *= 100;
  304. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
  305. if (!pMap)
  306. {
  307. sys_err("cannot find map by index %d", lFromMapIndex);
  308. return;
  309. }
  310. if (pGuild->GetDungeon_for_Only_guild() == NULL)
  311. {
  312. if (m_pGuild == NULL)
  313. {
  314. m_pGuild = pGuild;
  315. }
  316. else if (m_pGuild != pGuild)
  317. {
  318. sys_err ("Dungeon already has guild. Another guild cannot jump in dungeon : index %d", GetMapIndex());
  319. return;
  320. }
  321. pGuild->SetDungeon_for_Only_guild (this);
  322. }
  323. FWarpToPosition f(m_lMapIndex, x, y);
  324. pGuild->ForEachOnMapMember(f, lFromMapIndex);
  325. }
  326. #endif
  327. void CDungeon::JumpParty(LPPARTY pParty, long lFromMapIndex, int x, int y)
  328. {
  329. x *= 100;
  330. y *= 100;
  331. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
  332. if (!pMap)
  333. {
  334. sys_err("cannot find map by index %d", lFromMapIndex);
  335. return;
  336. }
  337. if (pParty->GetDungeon_for_Only_party() == NULL)
  338. {
  339. if (m_pParty == NULL)
  340. {
  341. m_pParty = pParty;
  342. }
  343. else if (m_pParty != pParty)
  344. {
  345. sys_err ("Dungeon already has party. Another party cannot jump in dungeon : index %d", GetMapIndex());
  346. return;
  347. }
  348. pParty->SetDungeon_for_Only_party (this);
  349. }
  350. FWarpToPosition f(m_lMapIndex, x, y);
  351. pParty->ForEachOnMapMember(f, lFromMapIndex);
  352. }
  353. void CDungeon::SetPartyNull()
  354. {
  355. m_pParty = NULL;
  356. }
  357. void CDungeonManager::Destroy(CDungeon::IdType dungeon_id)
  358. {
  359. sys_log(0, "DUNGEON destroy : map index %u", dungeon_id);
  360. LPDUNGEON pDungeon = Find(dungeon_id);
  361. if (pDungeon == NULL) {
  362. return;
  363. }
  364. m_map_pkDungeon.erase(dungeon_id);
  365. long lMapIndex = pDungeon->m_lMapIndex;
  366. m_map_pkMapDungeon.erase(lMapIndex);
  367. DWORD server_timer_arg = lMapIndex;
  368. quest::CQuestManager::instance().CancelServerTimers(server_timer_arg);
  369. SECTREE_MANAGER::instance().DestroyPrivateMap(lMapIndex);
  370. M2_DELETE(pDungeon);
  371. }
  372. LPDUNGEON CDungeonManager::Find(CDungeon::IdType dungeon_id)
  373. {
  374. itertype(m_map_pkDungeon) it = m_map_pkDungeon.find(dungeon_id);
  375. if (it != m_map_pkDungeon.end())
  376. return it->second;
  377. return NULL;
  378. }
  379. LPDUNGEON CDungeonManager::FindByMapIndex(long lMapIndex)
  380. {
  381. itertype(m_map_pkMapDungeon) it = m_map_pkMapDungeon.find(lMapIndex);
  382. if (it != m_map_pkMapDungeon.end()) {
  383. return it->second;
  384. }
  385. return NULL;
  386. }
  387. LPDUNGEON CDungeonManager::Create(long lOriginalMapIndex)
  388. {
  389. DWORD lMapIndex = SECTREE_MANAGER::instance().CreatePrivateMap(lOriginalMapIndex);
  390. if (!lMapIndex)
  391. {
  392. sys_log( 0, "Fail to Create Dungeon : OrginalMapindex %d NewMapindex %d", lOriginalMapIndex, lMapIndex );
  393. return NULL;
  394. }
  395. // <Factor> TODO: Change id assignment, or drop it
  396. CDungeon::IdType id = next_id_++;
  397. while (Find(id) != NULL) {
  398. id = next_id_++;
  399. }
  400. LPDUNGEON pDungeon = M2_NEW CDungeon(id, lOriginalMapIndex, lMapIndex);
  401. m_map_pkDungeon.insert(std::make_pair(id, pDungeon));
  402. m_map_pkMapDungeon.insert(std::make_pair(lMapIndex, pDungeon));
  403. return pDungeon;
  404. }
  405. CDungeonManager::CDungeonManager()
  406. : next_id_(0)
  407. {
  408. }
  409. CDungeonManager::~CDungeonManager()
  410. {
  411. }
  412. void CDungeon::UniqueSetMaxHP(const std::string& key, int iMaxHP)
  413. {
  414. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  415. if (it == m_map_UniqueMob.end())
  416. {
  417. sys_err("Unknown Key : %s", key.c_str());
  418. return;
  419. }
  420. it->second->SetMaxHP(iMaxHP);
  421. }
  422. void CDungeon::UniqueSetHP(const std::string& key, int iHP)
  423. {
  424. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  425. if (it == m_map_UniqueMob.end())
  426. {
  427. sys_err("Unknown Key : %s", key.c_str());
  428. return;
  429. }
  430. it->second->SetHP(iHP);
  431. }
  432. void CDungeon::UniqueSetDefGrade(const std::string& key, int iGrade)
  433. {
  434. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  435. if (it == m_map_UniqueMob.end())
  436. {
  437. sys_err("Unknown Key : %s", key.c_str());
  438. return;
  439. }
  440. it->second->PointChange(POINT_DEF_GRADE,iGrade - it->second->GetPoint(POINT_DEF_GRADE));
  441. }
  442. void CDungeon::SpawnMoveUnique(const char* key, DWORD vnum, const char* pos_from, const char* pos_to)
  443. {
  444. TAreaMap::iterator it_to = m_map_Area.find(pos_to);
  445. if (it_to == m_map_Area.end())
  446. {
  447. sys_err("Wrong position string : %s", pos_to);
  448. return;
  449. }
  450. TAreaMap::iterator it_from = m_map_Area.find(pos_from);
  451. if (it_from == m_map_Area.end())
  452. {
  453. sys_err("Wrong position string : %s", pos_from);
  454. return;
  455. }
  456. TAreaInfo & ai = it_from->second;
  457. TAreaInfo & ai_to = it_to->second;
  458. int dir = ai.dir;
  459. if (dir==-1)
  460. dir = number(0,359);
  461. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  462. if (pkSectreeMap == NULL) {
  463. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  464. return;
  465. }
  466. for (int i=0;i<100;i++)
  467. {
  468. int dx = number(ai.sx, ai.ex);
  469. int dy = number(ai.sy, ai.ey);
  470. int tx = number(ai_to.sx, ai_to.ex);
  471. int ty = number(ai_to.sy, ai_to.ey);
  472. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+dx, pkSectreeMap->m_setting.iBaseY+dy, 0, false, dir);
  473. if (ch)
  474. {
  475. m_map_UniqueMob.insert(make_pair(std::string(key), ch));
  476. ch->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
  477. ch->SetDungeon(this);
  478. if (ch->Goto(pkSectreeMap->m_setting.iBaseX+tx, pkSectreeMap->m_setting.iBaseY+ty))
  479. ch->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
  480. }
  481. else
  482. {
  483. sys_err("Cannot spawn at %d %d", pkSectreeMap->m_setting.iBaseX+((ai.sx+ai.ex)>>1), pkSectreeMap->m_setting.iBaseY+((ai.sy+ai.ey)>>1));
  484. }
  485. }
  486. }
  487. void CDungeon::SpawnUnique(const char* key, DWORD vnum, const char* pos)
  488. {
  489. TAreaMap::iterator it = m_map_Area.find(pos);
  490. if (it == m_map_Area.end())
  491. {
  492. sys_err("Wrong position string : %s", pos);
  493. return;
  494. }
  495. TAreaInfo & ai = it->second;
  496. int dir = ai.dir;
  497. if (dir==-1)
  498. dir = number(0,359);
  499. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  500. if (pkSectreeMap == NULL) {
  501. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  502. return;
  503. }
  504. for (int i=0;i<100;i++)
  505. {
  506. int dx = number(ai.sx, ai.ex);
  507. int dy = number(ai.sy, ai.ey);
  508. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+dx, pkSectreeMap->m_setting.iBaseY+dy, 0, false, dir);
  509. if (ch)
  510. {
  511. m_map_UniqueMob.insert(make_pair(std::string(key), ch));
  512. ch->SetDungeon(this);
  513. ch->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
  514. break;
  515. }
  516. else
  517. {
  518. sys_err("Cannot spawn at %d %d", pkSectreeMap->m_setting.iBaseX+((ai.sx+ai.ex)>>1), pkSectreeMap->m_setting.iBaseY+((ai.sy+ai.ey)>>1));
  519. }
  520. }
  521. }
  522. void CDungeon::SetUnique(const char* key, DWORD vid)
  523. {
  524. LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(vid);
  525. if (ch)
  526. {
  527. m_map_UniqueMob.insert(make_pair(std::string(key), ch));
  528. ch->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
  529. }
  530. }
  531. void CDungeon::SpawnStoneDoor(const char* key, const char* pos)
  532. {
  533. SpawnUnique(key, 13001, pos);
  534. }
  535. void CDungeon::SpawnWoodenDoor(const char* key, const char* pos)
  536. {
  537. SpawnUnique(key, 13000, pos);
  538. UniqueSetMaxHP(key, 10000);
  539. UniqueSetHP(key, 10000);
  540. UniqueSetDefGrade(key, 300);
  541. }
  542. void CDungeon::PurgeUnique(const std::string& key)
  543. {
  544. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  545. if (it == m_map_UniqueMob.end())
  546. {
  547. sys_err("Unknown Key or Dead: %s", key.c_str());
  548. return;
  549. }
  550. LPCHARACTER ch = it->second;
  551. m_map_UniqueMob.erase(it);
  552. M2_DESTROY_CHARACTER(ch);
  553. }
  554. void CDungeon::KillUnique(const std::string& key)
  555. {
  556. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  557. if (it == m_map_UniqueMob.end())
  558. {
  559. sys_err("Unknown Key or Dead: %s", key.c_str());
  560. return;
  561. }
  562. LPCHARACTER ch = it->second;
  563. m_map_UniqueMob.erase(it);
  564. ch->Dead();
  565. }
  566. DWORD CDungeon::GetUniqueVid(const std::string& key)
  567. {
  568. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  569. if (it == m_map_UniqueMob.end())
  570. {
  571. sys_err("Unknown Key or Dead: %s", key.c_str());
  572. return 0;
  573. }
  574. LPCHARACTER ch = it->second;
  575. return ch->GetVID();
  576. }
  577. float CDungeon::GetUniqueHpPerc(const std::string& key)
  578. {
  579. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  580. if (it == m_map_UniqueMob.end())
  581. {
  582. sys_err("Unknown Key : %s", key.c_str());
  583. return false;
  584. }
  585. return (100.f*it->second->GetHP())/it->second->GetMaxHP();
  586. }
  587. void CDungeon::DeadCharacter(LPCHARACTER ch)
  588. {
  589. if (!ch->IsPC())
  590. {
  591. TUniqueMobMap::iterator it = m_map_UniqueMob.begin();
  592. while (it!=m_map_UniqueMob.end())
  593. {
  594. if (it->second == ch)
  595. {
  596. //sys_log(0,"Dead unique %s", it->first.c_str());
  597. m_map_UniqueMob.erase(it);
  598. break;
  599. }
  600. ++it;
  601. }
  602. }
  603. }
  604. bool CDungeon::IsUniqueDead(const std::string& key)
  605. {
  606. TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
  607. if (it == m_map_UniqueMob.end())
  608. {
  609. sys_err("Unknown Key or Dead : %s", key.c_str());
  610. return true;
  611. }
  612. return it->second->IsDead();
  613. }
  614. void CDungeon::Spawn(DWORD vnum, const char* pos)
  615. {
  616. //sys_log(0,"DUNGEON Spawn %u %s", vnum, pos);
  617. TAreaMap::iterator it = m_map_Area.find(pos);
  618. if (it == m_map_Area.end())
  619. {
  620. sys_err("Wrong position string : %s", pos);
  621. return;
  622. }
  623. TAreaInfo & ai = it->second;
  624. int dir = ai.dir;
  625. if (dir==-1)
  626. dir = number(0,359);
  627. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  628. if (pkSectreeMap == NULL)
  629. {
  630. sys_err("cannot find map by index %d", m_lMapIndex);
  631. return;
  632. }
  633. int dx = number(ai.sx, ai.ex);
  634. int dy = number(ai.sy, ai.ey);
  635. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+dx, pkSectreeMap->m_setting.iBaseY+dy, 0, false, dir);
  636. if (ch)
  637. ch->SetDungeon(this);
  638. }
  639. LPCHARACTER CDungeon::SpawnMob(DWORD vnum, int x, int y, int dir)
  640. {
  641. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  642. if (pkSectreeMap == NULL) {
  643. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  644. return NULL;
  645. }
  646. sys_log(0, "CDungeon::SpawnMob %u %d %d", vnum, x, y);
  647. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+x*100, pkSectreeMap->m_setting.iBaseY+y*100, 0, false, dir == 0 ? -1 : (dir - 1) * 45);
  648. if (ch)
  649. {
  650. ch->SetDungeon(this);
  651. sys_log(0, "CDungeon::SpawnMob name %s", ch->GetName());
  652. }
  653. return ch;
  654. }
  655. LPCHARACTER CDungeon::SpawnMob_ac_dir(DWORD vnum, int x, int y, int dir)
  656. {
  657. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  658. if (pkSectreeMap == NULL) {
  659. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  660. return NULL;
  661. }
  662. sys_log(0, "CDungeon::SpawnMob %u %d %d", vnum, x, y);
  663. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+x*100, pkSectreeMap->m_setting.iBaseY+y*100, 0, false, dir);
  664. if (ch)
  665. {
  666. ch->SetDungeon(this);
  667. sys_log(0, "CDungeon::SpawnMob name %s", ch->GetName());
  668. }
  669. return ch;
  670. }
  671. void CDungeon::SpawnNameMob(DWORD vnum, int x, int y, const char* name)
  672. {
  673. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  674. if (pkSectreeMap == NULL) {
  675. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  676. return;
  677. }
  678. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+x, pkSectreeMap->m_setting.iBaseY+y, 0, false, -1);
  679. if (ch)
  680. {
  681. ch->SetName(name);
  682. ch->SetDungeon(this);
  683. }
  684. }
  685. void CDungeon::SpawnGotoMob(long lFromX, long lFromY, long lToX, long lToY)
  686. {
  687. const int MOB_GOTO_VNUM = 20039;
  688. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  689. if (pkSectreeMap == NULL) {
  690. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  691. return;
  692. }
  693. sys_log(0, "SpawnGotoMob %d %d to %d %d", lFromX, lFromY, lToX, lToY);
  694. lFromX = pkSectreeMap->m_setting.iBaseX+lFromX*100;
  695. lFromY = pkSectreeMap->m_setting.iBaseY+lFromY*100;
  696. LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(MOB_GOTO_VNUM, m_lMapIndex, lFromX, lFromY, 0, false, -1);
  697. if (ch)
  698. {
  699. char buf[30+1];
  700. snprintf(buf, sizeof(buf), ". %ld %ld", lToX, lToY);
  701. ch->SetName(buf);
  702. ch->SetDungeon(this);
  703. }
  704. }
  705. LPCHARACTER CDungeon::SpawnGroup(DWORD vnum, long x, long y, float radius, bool bAggressive, int count)
  706. {
  707. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  708. if (pkSectreeMap == NULL) {
  709. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  710. return NULL;
  711. }
  712. int iRadius = (int) radius;
  713. int sx = pkSectreeMap->m_setting.iBaseX + x - iRadius;
  714. int sy = pkSectreeMap->m_setting.iBaseY + y - iRadius;
  715. int ex = sx + iRadius;
  716. int ey = sy + iRadius;
  717. LPCHARACTER ch = NULL;
  718. while (count--)
  719. {
  720. LPCHARACTER chLeader = CHARACTER_MANAGER::instance().SpawnGroup(vnum, m_lMapIndex, sx, sy, ex, ey, NULL, bAggressive, this);
  721. if (chLeader && !ch)
  722. ch = chLeader;
  723. }
  724. return ch;
  725. }
  726. void CDungeon::SpawnRegen(const char* filename, bool bOnce)
  727. {
  728. if (!filename)
  729. {
  730. sys_err("CDungeon::SpawnRegen(filename=NULL, bOnce=%d) - m_lMapIndex[%d]", bOnce, m_lMapIndex);
  731. return;
  732. }
  733. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  734. if (!pkSectreeMap)
  735. {
  736. sys_err("CDungeon::SpawnRegen(filename=%s, bOnce=%d) - m_lMapIndex[%d]", filename, bOnce, m_lMapIndex);
  737. return;
  738. }
  739. regen_do(filename, m_lMapIndex, pkSectreeMap->m_setting.iBaseX, pkSectreeMap->m_setting.iBaseY, this, bOnce);
  740. }
  741. void CDungeon::AddRegen(LPREGEN regen)
  742. {
  743. regen->id = regen_id_++;
  744. m_regen.push_back(regen);
  745. }
  746. void CDungeon::ClearRegen()
  747. {
  748. for (itertype(m_regen) it = m_regen.begin(); it != m_regen.end(); ++it)
  749. {
  750. LPREGEN regen = *it;
  751. event_cancel(&regen->event);
  752. M2_DELETE(regen);
  753. }
  754. m_regen.clear();
  755. }
  756. bool CDungeon::IsValidRegen(LPREGEN regen, size_t regen_id) {
  757. itertype(m_regen) it = std::find(m_regen.begin(), m_regen.end(), regen);
  758. if (it == m_regen.end()) {
  759. return false;
  760. }
  761. LPREGEN found = *it;
  762. return (found->id == regen_id);
  763. }
  764. void CDungeon::SpawnMoveGroup(DWORD vnum, const char* pos_from, const char* pos_to, int count)
  765. {
  766. TAreaMap::iterator it_to = m_map_Area.find(pos_to);
  767. if (it_to == m_map_Area.end())
  768. {
  769. sys_err("Wrong position string : %s", pos_to);
  770. return;
  771. }
  772. TAreaMap::iterator it_from = m_map_Area.find(pos_from);
  773. if (it_from == m_map_Area.end())
  774. {
  775. sys_err("Wrong position string : %s", pos_from);
  776. return;
  777. }
  778. TAreaInfo & ai = it_from->second;
  779. TAreaInfo & ai_to = it_to->second;
  780. int dir = ai.dir;
  781. if (dir == -1)
  782. dir = number(0,359);
  783. LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  784. if (pkSectreeMap == NULL) {
  785. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  786. return;
  787. }
  788. while (count--)
  789. {
  790. int tx = number(ai_to.sx, ai_to.ex)+pkSectreeMap->m_setting.iBaseX;
  791. int ty = number(ai_to.sy, ai_to.ey)+pkSectreeMap->m_setting.iBaseY;
  792. CHARACTER_MANAGER::instance().SpawnMoveGroup(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+ai.sx, pkSectreeMap->m_setting.iBaseY+ai.sy, pkSectreeMap->m_setting.iBaseX+ai.ex, pkSectreeMap->m_setting.iBaseY+ai.ey, tx, ty, NULL, true);
  793. }
  794. }
  795. namespace
  796. {
  797. // DUNGEON_KILL_ALL_BUG_FIX
  798. struct FKillSectree
  799. {
  800. void operator () (LPENTITY ent)
  801. {
  802. if (ent->IsType(ENTITY_CHARACTER))
  803. {
  804. LPCHARACTER ch = (LPCHARACTER) ent;
  805. if (!ch->IsPC() && !ch->IsPet()
  806. #ifdef __DEFENSE_WAVE__
  807. && ch->GetRaceNum() != 20434
  808. && ch->GetRaceNum() != 20436
  809. && !(ch->GetRaceNum() >= 3960 && ch->GetRaceNum() <= 3964)
  810. #endif
  811. )
  812. }
  813. };
  814. // END_OF_DUNGEON_KILL_ALL_BUG_FIX
  815. struct FPurgeSectree
  816. {
  817. void operator () (LPENTITY ent)
  818. {
  819. if (ent->IsType(ENTITY_CHARACTER))
  820. {
  821. LPCHARACTER ch = (LPCHARACTER) ent;
  822. if (!ch->IsPC() && !ch->IsPet()
  823. #ifdef __DEFENSE_WAVE__
  824. && ch->GetRaceNum() != 20434
  825. && ch->GetRaceNum() != 20436
  826. && !(ch->GetRaceNum() >= 3960 && ch->GetRaceNum() <= 3964)
  827. #endif
  828. )
  829. else if (ent->IsType(ENTITY_ITEM))
  830. {
  831. LPITEM item = (LPITEM) ent;
  832. M2_DESTROY_ITEM(item);
  833. }
  834. else
  835. sys_err("unknown entity type %d is in dungeon", ent->GetType());
  836. }
  837. };
  838. }
  839. // DUNGEON_KILL_ALL_BUG_FIX
  840. void CDungeon::KillAll()
  841. {
  842. LPSECTREE_MAP pkMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  843. if (pkMap == NULL)
  844. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  845. return;
  846. }
  847. FKillSectree f;
  848. pkMap->for_each(f);
  849. }
  850. // END_OF_DUNGEON_KILL_ALL_BUG_FIX
  851. void CDungeon::Purge()
  852. {
  853. LPSECTREE_MAP pkMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  854. if (pkMap == NULL) {
  855. sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
  856. return;
  857. }
  858. FPurgeSectree f;
  859. pkMap->for_each(f);
  860. }
  861. void CDungeon::IncKillCount(LPCHARACTER pkKiller, LPCHARACTER pkVictim)
  862. {
  863. if (pkVictim->IsStone())
  864. m_iStoneKill ++;
  865. else
  866. m_iMobKill ++;
  867. }
  868. void CDungeon::UsePotion(LPCHARACTER ch)
  869. {
  870. m_bUsePotion = true;
  871. }
  872. void CDungeon::UseRevive(LPCHARACTER ch)
  873. {
  874. m_bUseRevive = true;
  875. }
  876. bool CDungeon::IsUsePotion()
  877. {
  878. return m_bUsePotion;
  879. }
  880. bool CDungeon::IsUseRevive()
  881. {
  882. return m_bUseRevive;
  883. }
  884. int CDungeon::GetKillMobCount()
  885. {
  886. return m_iMobKill;
  887. }
  888. int CDungeon::GetKillStoneCount()
  889. {
  890. return m_iStoneKill;
  891. }
  892. struct FCountMonster
  893. {
  894. int n;
  895. FCountMonster() : n(0) {};
  896. void operator()(LPENTITY ent)
  897. {
  898. if (ent->IsType(ENTITY_CHARACTER))
  899. {
  900. LPCHARACTER ch = (LPCHARACTER) ent;
  901. if (!ch->IsPC())
  902. n++;
  903. }
  904. }
  905. };
  906. int CDungeon::CountRealMonster()
  907. {
  908. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lOrigMapIndex);
  909. if (!pMap)
  910. {
  911. sys_err("cannot find map by index %d", m_lOrigMapIndex);
  912. return 0;
  913. }
  914. FCountMonster f;
  915. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  916. pMap->for_each(f);
  917. return f.n;
  918. }
  919. struct FExitDungeon
  920. {
  921. void operator()(LPENTITY ent)
  922. {
  923. if (ent->IsType(ENTITY_CHARACTER))
  924. {
  925. LPCHARACTER ch = (LPCHARACTER) ent;
  926. if (ch->IsPC())
  927. ch->ExitToSavedLocation();
  928. }
  929. }
  930. };
  931. void CDungeon::ExitAll()
  932. {
  933. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  934. if (!pMap)
  935. {
  936. sys_err("cannot find map by index %d", m_lMapIndex);
  937. return;
  938. }
  939. FExitDungeon f;
  940. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  941. pMap->for_each(f);
  942. }
  943. // DUNGEON_NOTICE
  944. namespace
  945. {
  946. struct FNotice
  947. {
  948. FNotice(const char * psz) : m_psz(psz)
  949. {
  950. }
  951. void operator() (LPENTITY ent)
  952. {
  953. if (ent->IsType(ENTITY_CHARACTER))
  954. {
  955. LPCHARACTER ch = (LPCHARACTER) ent;
  956. ch->ChatPacket(CHAT_TYPE_NOTICE, "%s", m_psz);
  957. }
  958. }
  959. const char * m_psz;
  960. };
  961. }
  962. void CDungeon::Notice(const char* msg)
  963. {
  964. sys_log(0, "XXX Dungeon Notice %p %s", this, msg);
  965. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  966. if (!pMap)
  967. {
  968. sys_err("cannot find map by index %d", m_lMapIndex);
  969. return;
  970. }
  971. FNotice f(msg);
  972. pMap->for_each(f);
  973. }
  974. // END_OF_DUNGEON_NOTICE
  975. struct FExitDungeonToStartPosition
  976. {
  977. void operator () (LPENTITY ent)
  978. {
  979. if (ent->IsType(ENTITY_CHARACTER))
  980. {
  981. LPCHARACTER ch = (LPCHARACTER) ent;
  982. if (ch->IsPC())
  983. {
  984. PIXEL_POSITION posWarp;
  985. // 현재 맵 인덱스를 넣는 것이 아니라 시작하는 맵 인덱스를 넣는다.
  986. if (SECTREE_MANAGER::instance().GetRecallPositionByEmpire(g_start_map[ch->GetEmpire()], ch->GetEmpire(), posWarp))
  987. ch->WarpSet(posWarp.x, posWarp.y);
  988. else
  989. ch->ExitToSavedLocation();
  990. }
  991. }
  992. }
  993. };
  994. void CDungeon::ExitAllToStartPosition()
  995. {
  996. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  997. if (!pMap)
  998. {
  999. sys_err("cannot find map by index %d", m_lMapIndex);
  1000. return;
  1001. }
  1002. FExitDungeonToStartPosition f;
  1003. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  1004. pMap->for_each(f);
  1005. }
  1006. EVENTFUNC(dungeon_jump_to_event)
  1007. {
  1008. dungeon_id_info * info = dynamic_cast<dungeon_id_info *>(event->info);
  1009. if ( info == NULL )
  1010. {
  1011. sys_err( "dungeon_jump_to_event> <Factor> Null pointer" );
  1012. return 0;
  1013. }
  1014. LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
  1015. pDungeon->jump_to_event_ = NULL;
  1016. if (pDungeon)
  1017. pDungeon->JumpToEliminateLocation();
  1018. else
  1019. sys_err("cannot find dungeon with map index %u", info->dungeon_id);
  1020. return 0;
  1021. }
  1022. EVENTFUNC(dungeon_exit_all_event)
  1023. {
  1024. dungeon_id_info * info = dynamic_cast<dungeon_id_info *>(event->info);
  1025. if ( info == NULL )
  1026. {
  1027. sys_err( "dungeon_exit_all_event> <Factor> Null pointer" );
  1028. return 0;
  1029. }
  1030. LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
  1031. pDungeon->exit_all_event_ = NULL;
  1032. if (pDungeon)
  1033. pDungeon->ExitAll();
  1034. return 0;
  1035. }
  1036. void CDungeon::CheckEliminated()
  1037. {
  1038. if (m_iMonsterCount > 0)
  1039. return;
  1040. if (m_bExitAllAtEliminate)
  1041. {
  1042. sys_log(0, "CheckEliminated: exit");
  1043. m_bExitAllAtEliminate = false;
  1044. if (m_iWarpDelay)
  1045. {
  1046. dungeon_id_info* info = AllocEventInfo<dungeon_id_info>();
  1047. info->dungeon_id = m_id;
  1048. event_cancel(&exit_all_event_);
  1049. exit_all_event_ = event_create(dungeon_exit_all_event, info, PASSES_PER_SEC(m_iWarpDelay));
  1050. }
  1051. else
  1052. {
  1053. ExitAll();
  1054. }
  1055. }
  1056. else if (m_bWarpAtEliminate)
  1057. {
  1058. sys_log(0, "CheckEliminated: warp");
  1059. m_bWarpAtEliminate = false;
  1060. if (m_iWarpDelay)
  1061. {
  1062. dungeon_id_info* info = AllocEventInfo<dungeon_id_info>();
  1063. info->dungeon_id = m_id;
  1064. event_cancel(&jump_to_event_);
  1065. jump_to_event_ = event_create(dungeon_jump_to_event, info, PASSES_PER_SEC(m_iWarpDelay));
  1066. }
  1067. else
  1068. {
  1069. JumpToEliminateLocation();
  1070. }
  1071. }
  1072. else
  1073. sys_log(0, "CheckEliminated: none");
  1074. }
  1075. void CDungeon::SetExitAllAtEliminate(long time)
  1076. {
  1077. sys_log(0, "SetExitAllAtEliminate: time %d", time);
  1078. m_bExitAllAtEliminate = true;
  1079. m_iWarpDelay = time;
  1080. }
  1081. void CDungeon::SetWarpAtEliminate(long time, long lMapIndex, int x, int y, const char* regen_file)
  1082. {
  1083. m_bWarpAtEliminate = true;
  1084. m_iWarpDelay = time;
  1085. m_lWarpMapIndex = lMapIndex;
  1086. m_lWarpX = x;
  1087. m_lWarpY = y;
  1088. if (!regen_file || !*regen_file)
  1089. m_stRegenFile.clear();
  1090. else
  1091. m_stRegenFile = regen_file;
  1092. sys_log(0, "SetWarpAtEliminate: time %d map %d %dx%d regenfile %s", time, lMapIndex, x, y, m_stRegenFile.c_str());
  1093. }
  1094. void CDungeon::JumpToEliminateLocation()
  1095. {
  1096. LPDUNGEON pDungeon = CDungeonManager::instance().FindByMapIndex(m_lWarpMapIndex);
  1097. if (pDungeon)
  1098. {
  1099. pDungeon->JumpAll(m_lMapIndex, m_lWarpX, m_lWarpY);
  1100. if (!m_stRegenFile.empty())
  1101. {
  1102. pDungeon->SpawnRegen(m_stRegenFile.c_str());
  1103. m_stRegenFile.clear();
  1104. }
  1105. }
  1106. else
  1107. {
  1108. // 일반 맵으로 워프
  1109. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  1110. if (!pMap)
  1111. {
  1112. sys_err("no map by index %d", m_lMapIndex);
  1113. return;
  1114. }
  1115. FWarpToPosition f(m_lWarpMapIndex, m_lWarpX * 100, m_lWarpY * 100);
  1116. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  1117. pMap->for_each(f);
  1118. }
  1119. }
  1120. struct FNearPosition
  1121. {
  1122. long x;
  1123. long y;
  1124. int dist;
  1125. bool ret;
  1126. FNearPosition(long x, long y, int d) :
  1127. x(x), y(y), dist(d), ret(true)
  1128. {
  1129. }
  1130. void operator()(LPENTITY ent)
  1131. {
  1132. if (ret == false)
  1133. return;
  1134. if (ent->IsType(ENTITY_CHARACTER))
  1135. {
  1136. LPCHARACTER ch = (LPCHARACTER) ent;
  1137. if (ch->IsPC())
  1138. {
  1139. if (DISTANCE_APPROX(ch->GetX() - x * 100, ch->GetY() - y * 100) > dist * 100)
  1140. ret = false;
  1141. }
  1142. }
  1143. }
  1144. };
  1145. bool CDungeon::IsAllPCNearTo(int x, int y, int dist)
  1146. {
  1147. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  1148. if (!pMap)
  1149. {
  1150. sys_err("cannot find map by index %d", m_lMapIndex);
  1151. return false;
  1152. }
  1153. FNearPosition f(x, y, dist);
  1154. // <Factor> SECTREE::for_each -> SECTREE::for_each_entity
  1155. pMap->for_each(f);
  1156. return f.ret;
  1157. }
  1158. #ifdef __DEFENSE_WAVE__
  1159. struct SUpdateMastHp
  1160. {
  1161. SUpdateMastHp(LPCHARACTER Mast) : m_Mast(Mast) {}
  1162. void operator () (LPENTITY ent)
  1163. {
  1164. if (ent->IsType(ENTITY_CHARACTER))
  1165. {
  1166. LPCHARACTER ch = (LPCHARACTER) ent;
  1167. ch->ChatPacket(CHAT_TYPE_COMMAND, "BINARY_Update_Mast_HP %d", m_Mast->GetHP());
  1168. }
  1169. }
  1170. LPCHARACTER m_Mast;
  1171. };
  1172. void CDungeon::UpdateMastHP()
  1173. {
  1174. LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
  1175. if (!pMap)
  1176. {
  1177. sys_err("cannot find map by index %d", m_lMapIndex);
  1178. return;
  1179. }
  1180. SUpdateMastHp f(GetMast());
  1181. pMap->for_each(f);
  1182. }
  1183. #endif
  1184. void CDungeon::CreateItemGroup (std::string& group_name, ItemGroup& item_group)
  1185. {
  1186. m_map_ItemGroup.insert (ItemGroupMap::value_type (group_name, item_group));
  1187. }
  1188. const CDungeon::ItemGroup* CDungeon::GetItemGroup (std::string& group_name)
  1189. {
  1190. ItemGroupMap::iterator it = m_map_ItemGroup.find (group_name);
  1191. if (it != m_map_ItemGroup.end())
  1192. return &(it->second);
  1193. else
  1194. return NULL;
  1195. }