instance.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "instance.hpp"
  4. #include <stdlib.h>
  5. #include "../common/cbasetypes.hpp"
  6. #include "../common/db.hpp"
  7. #include "../common/ers.hpp" // ers_destroy
  8. #include "../common/malloc.hpp"
  9. #include "../common/nullpo.hpp"
  10. #include "../common/showmsg.hpp"
  11. #include "../common/socket.hpp"
  12. #include "../common/strlib.hpp"
  13. #include "../common/timer.hpp"
  14. #include "clan.hpp"
  15. #include "clif.hpp"
  16. #include "guild.hpp"
  17. #include "map.hpp"
  18. #include "npc.hpp"
  19. #include "party.hpp"
  20. #include "pc.hpp"
  21. #define INSTANCE_INTERVAL 60000 // Interval used to check when an instance is to be destroyed (ms)
  22. struct instance_data instance_data[MAX_INSTANCE_DATA];
  23. struct eri *instance_maps_ers = NULL; ///< Array of maps per instance
  24. static DBMap *InstanceDB; /// Instance DB: struct instance_db, key: id
  25. static DBMap *InstanceNameDB; /// instance id, key: name
  26. static struct {
  27. int id[MAX_INSTANCE_DATA];
  28. int count;
  29. int timer;
  30. } instance_wait;
  31. /*==========================================
  32. * Searches for an instance ID in the database
  33. *------------------------------------------*/
  34. struct instance_db *instance_searchtype_db(unsigned short instance_id) {
  35. return (struct instance_db *)uidb_get(InstanceDB,instance_id);
  36. }
  37. static uint16 instance_name2id(const char *instance_name) {
  38. return (uint16)strdb_uiget(InstanceNameDB,instance_name);
  39. }
  40. /*==========================================
  41. * Searches for an instance name in the database
  42. *------------------------------------------*/
  43. struct instance_db *instance_searchname_db(const char *instance_name) {
  44. uint16 id = instance_name2id(instance_name);
  45. if (id == 0)
  46. return NULL;
  47. return (struct instance_db *)uidb_get(InstanceDB,id);
  48. }
  49. /**
  50. * Search for a sd of an Instance
  51. * @param instance_id: Instance ID
  52. * @param sd: Player data to attach
  53. * @param target: Target display type
  54. */
  55. void instance_getsd(unsigned short instance_id, struct map_session_data **sd, enum send_target *target) {
  56. switch(instance_data[instance_id].mode) {
  57. case IM_NONE:
  58. (*sd) = NULL;
  59. (*target) = SELF;
  60. break;
  61. case IM_GUILD:
  62. (*sd) = guild_getavailablesd(guild_search(instance_data[instance_id].owner_id));
  63. (*target) = GUILD;
  64. break;
  65. case IM_PARTY:
  66. (*sd) = party_getavailablesd(party_search(instance_data[instance_id].owner_id));
  67. (*target) = PARTY;
  68. break;
  69. case IM_CHAR:
  70. (*sd) = map_charid2sd(instance_data[instance_id].owner_id);
  71. (*target) = SELF;
  72. break;
  73. case IM_CLAN:
  74. (*sd) = clan_getavailablesd(clan_search(instance_data[instance_id].owner_id));
  75. (*target) = CLAN;
  76. }
  77. return;
  78. }
  79. /*==========================================
  80. * Deletes an instance timer (Destroys instance)
  81. *------------------------------------------*/
  82. static TIMER_FUNC(instance_delete_timer){
  83. instance_destroy(id);
  84. return 0;
  85. }
  86. /*==========================================
  87. * Create subscription timer
  88. *------------------------------------------*/
  89. static TIMER_FUNC(instance_subscription_timer){
  90. int i, ret;
  91. unsigned short instance_id = instance_wait.id[0];
  92. struct map_session_data *sd = NULL;
  93. struct party_data *pd = NULL;
  94. struct guild *gd = NULL;
  95. struct clan *cd = NULL;
  96. enum instance_mode mode;
  97. if(instance_wait.count == 0 || instance_id == 0)
  98. return 0;
  99. // Check that maps have been added
  100. ret = instance_addmap(instance_id);
  101. mode = instance_data[instance_id].mode;
  102. switch(mode) {
  103. case IM_NONE:
  104. break;
  105. case IM_CHAR:
  106. if (ret == 0 && (sd = map_charid2sd(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell player to wait
  107. clif_instance_changewait(instance_id, 0xffff);
  108. break;
  109. case IM_PARTY:
  110. if (ret == 0 && (pd = party_search(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell party to wait
  111. clif_instance_changewait(instance_id, 0xffff);
  112. break;
  113. case IM_GUILD:
  114. if (ret == 0 && (gd = guild_search(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell guild to wait
  115. clif_instance_changewait(instance_id, 0xffff);
  116. break;
  117. case IM_CLAN:
  118. if (ret == 0 && (cd = clan_search(instance_data[instance_id].owner_id)) != NULL) // If no maps are created, tell clan to wait
  119. clif_instance_changewait(instance_id, 0xffff);
  120. break;
  121. default:
  122. return 0;
  123. }
  124. instance_wait.count--;
  125. memmove(&instance_wait.id[0],&instance_wait.id[1],sizeof(instance_wait.id[0])*instance_wait.count);
  126. memset(&instance_wait.id[instance_wait.count], 0, sizeof(instance_wait.id[0]));
  127. for(i = 0; i < instance_wait.count; i++) {
  128. if( instance_data[instance_wait.id[i]].state == INSTANCE_IDLE &&
  129. ((mode == IM_CHAR && sd != NULL) || (mode == IM_GUILD && gd != NULL) || (mode == IM_PARTY && pd != NULL) || (mode == IM_CLAN && cd != NULL))
  130. ){
  131. clif_instance_changewait(instance_id, i + 1);
  132. }
  133. }
  134. if(instance_wait.count)
  135. instance_wait.timer = add_timer(gettick()+INSTANCE_INTERVAL, instance_subscription_timer, 0, 0);
  136. else
  137. instance_wait.timer = INVALID_TIMER;
  138. return 0;
  139. }
  140. /*==========================================
  141. * Adds timer back to members entering instance
  142. *------------------------------------------*/
  143. static int instance_startkeeptimer(struct instance_data *im, unsigned short instance_id)
  144. {
  145. struct instance_db *db;
  146. nullpo_retr(0, im);
  147. // No timer
  148. if(im->keep_timer != INVALID_TIMER)
  149. return 1;
  150. if((db = instance_searchtype_db(im->type)) == NULL)
  151. return 1;
  152. // Add timer
  153. im->keep_limit = (unsigned int)time(NULL) + db->limit;
  154. im->keep_timer = add_timer(gettick()+db->limit*1000, instance_delete_timer, instance_id, 0);
  155. switch(im->mode) {
  156. case IM_NONE:
  157. break;
  158. case IM_CHAR:
  159. if (map_charid2sd(im->owner_id) != NULL) // Notify player of the added instance timer
  160. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  161. break;
  162. case IM_PARTY:
  163. if (party_search(im->owner_id) != NULL) // Notify party of the added instance timer
  164. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  165. break;
  166. case IM_GUILD:
  167. if (guild_search(im->owner_id) != NULL) // Notify guild of the added instance timer
  168. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  169. break;
  170. case IM_CLAN:
  171. if (clan_search(im->owner_id) != NULL) // Notify clan of the added instance timer
  172. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  173. break;
  174. default:
  175. return 1;
  176. }
  177. return 0;
  178. }
  179. /*==========================================
  180. * Creates idle timer
  181. * Default before instance destroy is 5 minutes
  182. *------------------------------------------*/
  183. static int instance_startidletimer(struct instance_data *im, unsigned short instance_id)
  184. {
  185. struct instance_db *db;
  186. nullpo_retr(1, im);
  187. // No current timer
  188. if(im->idle_timer != INVALID_TIMER)
  189. return 1;
  190. if ((db = instance_searchtype_db(im->type)) == NULL)
  191. return 1;
  192. // Add the timer
  193. im->idle_limit = (unsigned int)time(NULL) + db->timeout;
  194. im->idle_timer = add_timer(gettick() + db->timeout * 1000, instance_delete_timer, instance_id, 0);
  195. switch(im->mode) {
  196. case IM_NONE:
  197. break;
  198. case IM_CHAR:
  199. if (map_charid2sd(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify player of added instance timer
  200. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  201. break;
  202. case IM_PARTY:
  203. if (party_search(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify party of added instance timer
  204. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  205. break;
  206. case IM_GUILD:
  207. if (guild_search(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify guild of added instance timer
  208. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  209. break;
  210. case IM_CLAN:
  211. if (clan_search(im->owner_id) != NULL && instance_searchtype_db(im->type) != NULL) // Notify clan of added instance timer
  212. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  213. break;
  214. default:
  215. return 1;
  216. }
  217. return 0;
  218. }
  219. /*==========================================
  220. * Delete the idle timer
  221. *------------------------------------------*/
  222. static int instance_stopidletimer(struct instance_data *im, unsigned short instance_id)
  223. {
  224. nullpo_retr(0, im);
  225. // No timer
  226. if(im->idle_timer == INVALID_TIMER)
  227. return 1;
  228. // Delete the timer - Party has returned or instance is destroyed
  229. im->idle_limit = 0;
  230. delete_timer(im->idle_timer, instance_delete_timer);
  231. im->idle_timer = INVALID_TIMER;
  232. switch(im->mode) {
  233. case IM_NONE:
  234. break;
  235. case IM_CHAR:
  236. if (map_charid2sd(im->owner_id) != NULL) // Notify the player
  237. clif_instance_changestatus(instance_id, 0, im->idle_limit);
  238. break;
  239. case IM_PARTY:
  240. if (party_search(im->owner_id) != NULL) // Notify the party
  241. clif_instance_changestatus(instance_id, 0, im->idle_limit);
  242. break;
  243. case IM_GUILD:
  244. if (guild_search(im->owner_id) != NULL) // Notify the guild
  245. clif_instance_changestatus(instance_id, 0, im->idle_limit);
  246. break;
  247. case IM_CLAN:
  248. if (clan_search(im->owner_id) != NULL) // Notify the clan
  249. clif_instance_changestatus(instance_id, 0, im->idle_limit);
  250. break;
  251. default:
  252. return 1;
  253. }
  254. return 0;
  255. }
  256. /*==========================================
  257. * Run the OnInstanceInit events for duplicated NPCs
  258. *------------------------------------------*/
  259. static int instance_npcinit(struct block_list *bl, va_list ap)
  260. {
  261. struct npc_data* nd;
  262. nullpo_retr(0, bl);
  263. nullpo_retr(0, ap);
  264. nullpo_retr(0, nd = (struct npc_data *)bl);
  265. return npc_instanceinit(nd);
  266. }
  267. /*==========================================
  268. * Run the OnInstanceDestroy events for duplicated NPCs
  269. *------------------------------------------*/
  270. static int instance_npcdestroy(struct block_list *bl, va_list ap)
  271. {
  272. struct npc_data* nd;
  273. nullpo_retr(0, bl);
  274. nullpo_retr(0, ap);
  275. nullpo_retr(0, nd = (struct npc_data *)bl);
  276. return npc_instancedestroy(nd);
  277. }
  278. /*==========================================
  279. * Add an NPC to an instance
  280. *------------------------------------------*/
  281. static int instance_addnpc_sub(struct block_list *bl, va_list ap)
  282. {
  283. struct npc_data* nd;
  284. nullpo_retr(0, bl);
  285. nullpo_retr(0, ap);
  286. nullpo_retr(0, nd = (struct npc_data *)bl);
  287. return npc_duplicate4instance(nd, va_arg(ap, int));
  288. }
  289. // Separate function used for reloading
  290. void instance_addnpc(struct instance_data *im)
  291. {
  292. int i;
  293. // First add the NPCs
  294. for(i = 0; i < im->cnt_map; i++)
  295. map_foreachinallarea(instance_addnpc_sub, im->map[i]->src_m, 0, 0, map[im->map[i]->src_m].xs, map[im->map[i]->src_m].ys, BL_NPC, im->map[i]->m);
  296. // Now run their OnInstanceInit
  297. for(i = 0; i < im->cnt_map; i++)
  298. map_foreachinallarea(instance_npcinit, im->map[i]->m, 0, 0, map[im->map[i]->m].xs, map[im->map[i]->m].ys, BL_NPC, im->map[i]->m);
  299. }
  300. /*--------------------------------------
  301. * name : instance name
  302. * Return value could be
  303. * -4 = no free instances | -3 = already exists | -2 = character/party/guild not found | -1 = invalid type
  304. * On success return instance_id
  305. *--------------------------------------*/
  306. int instance_create(int owner_id, const char *name, enum instance_mode mode) {
  307. struct instance_db *db = instance_searchname_db(name);
  308. struct map_session_data *sd = NULL;
  309. struct party_data *pd = NULL;
  310. struct guild *gd = NULL;
  311. struct clan* cd = NULL;
  312. unsigned short i;
  313. nullpo_retr(-1, db);
  314. switch(mode) {
  315. case IM_NONE:
  316. break;
  317. case IM_CHAR:
  318. if ((sd = map_charid2sd(owner_id)) == NULL) {
  319. ShowError("instance_create: character %d not found for instance '%s'.\n", owner_id, name);
  320. return -2;
  321. }
  322. if (sd->instance_id)
  323. return -3; // Player already instancing
  324. break;
  325. case IM_PARTY:
  326. if ((pd = party_search(owner_id)) == NULL) {
  327. ShowError("instance_create: party %d not found for instance '%s'.\n", owner_id, name);
  328. return -2;
  329. }
  330. if (pd->instance_id)
  331. return -3; // Party already instancing
  332. break;
  333. case IM_GUILD:
  334. if ((gd = guild_search(owner_id)) == NULL) {
  335. ShowError("instance_create: guild %d not found for instance '%s'.\n", owner_id, name);
  336. return -2;
  337. }
  338. if (gd->instance_id)
  339. return -3; // Guild already instancing
  340. break;
  341. case IM_CLAN:
  342. if ((cd = clan_search(owner_id)) == NULL) {
  343. ShowError("instance_create: clan %d not found for instance '%s'.\n", owner_id, name);
  344. return -2;
  345. }
  346. if (cd->instance_id)
  347. return -3; // Clan already instancing
  348. break;
  349. default:
  350. ShowError("instance_create: unknown mode %u for owner_id %d and name %s.\n", mode, owner_id, name);
  351. return -2;
  352. }
  353. // Searching a Free Instance
  354. // 0 is ignored as this means "no instance" on maps
  355. ARR_FIND(1, MAX_INSTANCE_DATA, i, instance_data[i].state == INSTANCE_FREE);
  356. if( i >= MAX_INSTANCE_DATA )
  357. return -4;
  358. instance_data[i].type = db->id;
  359. instance_data[i].state = INSTANCE_IDLE;
  360. instance_data[i].owner_id = owner_id;
  361. instance_data[i].mode = mode;
  362. instance_data[i].keep_limit = 0;
  363. instance_data[i].keep_timer = INVALID_TIMER;
  364. instance_data[i].idle_limit = 0;
  365. instance_data[i].idle_timer = INVALID_TIMER;
  366. instance_data[i].regs.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
  367. instance_data[i].regs.arrays = NULL;
  368. instance_data[i].cnt_map = 0;
  369. switch(mode) {
  370. case IM_CHAR:
  371. sd->instance_id = i;
  372. break;
  373. case IM_PARTY:
  374. pd->instance_id = i;
  375. break;
  376. case IM_GUILD:
  377. gd->instance_id = i;
  378. break;
  379. case IM_CLAN:
  380. cd->instance_id = i;
  381. break;
  382. }
  383. instance_wait.id[instance_wait.count++] = i;
  384. clif_instance_create(i, instance_wait.count);
  385. instance_subscription_timer(0,0,0,0);
  386. ShowInfo("[Instance] Created: %s (%hu).\n", name, i);
  387. return i;
  388. }
  389. /*--------------------------------------
  390. * Adds maps to the instance
  391. *--------------------------------------*/
  392. int instance_addmap(unsigned short instance_id) {
  393. int i, m;
  394. struct instance_data *im;
  395. struct instance_db *db;
  396. struct s_instance_map *entry;
  397. if (instance_id == 0)
  398. return 0;
  399. im = &instance_data[instance_id];
  400. // If the instance isn't idle, we can't do anything
  401. if (im->state != INSTANCE_IDLE)
  402. return 0;
  403. if ((db = instance_searchtype_db(im->type)) == NULL)
  404. return 0;
  405. // Set to busy, update timers
  406. im->state = INSTANCE_BUSY;
  407. im->idle_limit = (unsigned int)time(NULL) + db->timeout;
  408. im->idle_timer = add_timer(gettick() + db->timeout * 1000, instance_delete_timer, instance_id, 0);
  409. // Add the maps
  410. if (db->maplist_count > MAX_MAP_PER_INSTANCE) {
  411. ShowError("instance_addmap: Too many maps (%d) created for a single instance '%s' (%hu).\n", db->maplist_count, StringBuf_Value(db->name), instance_id);
  412. return 0;
  413. }
  414. // Add initial map
  415. if ((m = map_addinstancemap(StringBuf_Value(db->enter.mapname), instance_id)) < 0) {
  416. ShowError("instance_addmap: Failed to create initial map for instance '%s' (%hu).\n", StringBuf_Value(db->name), instance_id);
  417. return 0;
  418. }
  419. entry = ers_alloc(instance_maps_ers, struct s_instance_map);
  420. entry->m = m;
  421. entry->src_m = map_mapname2mapid(StringBuf_Value(db->enter.mapname));
  422. RECREATE(im->map, struct s_instance_map *, im->cnt_map + 1);
  423. im->map[im->cnt_map++] = entry;
  424. // Add extra maps (if any)
  425. for(i = 0; i < db->maplist_count; i++) {
  426. if(strlen(StringBuf_Value(db->maplist[i])) < 1)
  427. continue;
  428. else if( (m = map_addinstancemap(StringBuf_Value(db->maplist[i]), instance_id)) < 0) {
  429. // An error occured adding a map
  430. ShowError("instance_addmap: No maps added to instance '%s' (%hu).\n", StringBuf_Value(db->name), instance_id);
  431. return 0;
  432. } else {
  433. entry = ers_alloc(instance_maps_ers, struct s_instance_map);
  434. entry->m = m;
  435. entry->src_m = map_mapname2mapid(StringBuf_Value(db->maplist[i]));
  436. RECREATE(im->map, struct s_instance_map *, im->cnt_map + 1);
  437. im->map[im->cnt_map++] = entry;
  438. }
  439. }
  440. // Create NPCs on all maps
  441. instance_addnpc(im);
  442. switch(im->mode) {
  443. case IM_NONE:
  444. break;
  445. case IM_CHAR:
  446. if (map_charid2sd(im->owner_id) != NULL) // Inform player of the created instance
  447. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  448. break;
  449. case IM_PARTY:
  450. if (party_search(im->owner_id) != NULL) // Inform party members of the created instance
  451. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  452. break;
  453. case IM_GUILD:
  454. if (guild_search(im->owner_id) != NULL) // Inform guild members of the created instance
  455. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  456. break;
  457. case IM_CLAN:
  458. if (clan_search(im->owner_id) != NULL) // Inform clan members of the created instance
  459. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  460. break;
  461. default:
  462. return 0;
  463. }
  464. return im->cnt_map;
  465. }
  466. /*==========================================
  467. * Returns an instance map ID using a map name
  468. * name : source map
  469. * instance_id : where to search
  470. * result : mapid of map "name" in this instance
  471. *------------------------------------------*/
  472. int16 instance_mapname2mapid(const char *name, unsigned short instance_id)
  473. {
  474. struct instance_data *im;
  475. int16 m = map_mapname2mapid(name);
  476. char iname[MAP_NAME_LENGTH];
  477. int i;
  478. if(m < 0) {
  479. ShowError("instance_mapname2mapid: map name %s does not exist.\n",name);
  480. return m;
  481. }
  482. strcpy(iname,name);
  483. if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA)
  484. return m;
  485. im = &instance_data[instance_id];
  486. if(im->state != INSTANCE_BUSY)
  487. return m;
  488. for(i = 0; i < im->cnt_map; i++)
  489. if(im->map[i]->src_m == m) {
  490. char alt_name[MAP_NAME_LENGTH];
  491. if((strchr(iname,'@') == NULL) && strlen(iname) > 8) {
  492. memmove(iname, iname+(strlen(iname)-9), strlen(iname));
  493. snprintf(alt_name, sizeof(alt_name),"%hu#%s", instance_id, iname);
  494. } else
  495. snprintf(alt_name, sizeof(alt_name),"%.3hu%s", instance_id, iname);
  496. return map_mapname2mapid(alt_name);
  497. }
  498. return m;
  499. }
  500. /*==========================================
  501. * Removes a instance, all its maps and npcs.
  502. *------------------------------------------*/
  503. int instance_destroy(unsigned short instance_id)
  504. {
  505. struct instance_data *im;
  506. struct map_session_data *sd = NULL;
  507. struct party_data *pd = NULL;
  508. struct guild *gd = NULL;
  509. struct clan *cd = NULL;
  510. int i, type = 0;
  511. unsigned int now = (unsigned int)time(NULL);
  512. enum instance_mode mode;
  513. if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA)
  514. return 1;
  515. im = &instance_data[instance_id];
  516. if(im->state == INSTANCE_FREE)
  517. return 1;
  518. mode = im->mode;
  519. switch(mode) {
  520. case IM_NONE:
  521. break;
  522. case IM_CHAR:
  523. sd = map_charid2sd(im->owner_id);
  524. break;
  525. case IM_PARTY:
  526. pd = party_search(im->owner_id);
  527. break;
  528. case IM_GUILD:
  529. gd = guild_search(im->owner_id);
  530. break;
  531. case IM_CLAN:
  532. cd = clan_search(im->owner_id);
  533. break;
  534. }
  535. if(im->state == INSTANCE_IDLE) {
  536. for(i = 0; i < instance_wait.count; i++) {
  537. if(instance_wait.id[i] == instance_id) {
  538. instance_wait.count--;
  539. memmove(&instance_wait.id[i],&instance_wait.id[i+1],sizeof(instance_wait.id[0])*(instance_wait.count-i));
  540. memset(&instance_wait.id[instance_wait.count], 0, sizeof(instance_wait.id[0]));
  541. for(i = 0; i < instance_wait.count; i++)
  542. if(instance_data[instance_wait.id[i]].state == INSTANCE_IDLE)
  543. if ((mode == IM_CHAR && sd) || (mode == IM_PARTY && pd) || (mode == IM_GUILD && gd) || (mode == IM_CLAN && cd))
  544. clif_instance_changewait(instance_id, i + 1);
  545. if(instance_wait.count)
  546. instance_wait.timer = add_timer(gettick()+INSTANCE_INTERVAL, instance_subscription_timer, 0, 0);
  547. else
  548. instance_wait.timer = INVALID_TIMER;
  549. type = 0;
  550. break;
  551. }
  552. }
  553. } else {
  554. if(im->keep_limit && im->keep_limit <= now)
  555. type = 1;
  556. else if(im->idle_limit && im->idle_limit <= now)
  557. type = 2;
  558. else
  559. type = 3;
  560. // Run OnInstanceDestroy on all NPCs in the instance
  561. for(i = 0; i < im->cnt_map; i++){
  562. map_foreachinallarea(instance_npcdestroy, im->map[i]->m, 0, 0, map[im->map[i]->m].xs, map[im->map[i]->m].ys, BL_NPC, im->map[i]->m);
  563. }
  564. for(i = 0; i < im->cnt_map; i++) {
  565. map_delinstancemap(im->map[i]->m);
  566. ers_free(instance_maps_ers, im->map[i]);
  567. }
  568. im->cnt_map = 0;
  569. aFree(im->map);
  570. im->map = NULL;
  571. }
  572. if(im->keep_timer != INVALID_TIMER) {
  573. delete_timer(im->keep_timer, instance_delete_timer);
  574. im->keep_timer = INVALID_TIMER;
  575. }
  576. if(im->idle_timer != INVALID_TIMER) {
  577. delete_timer(im->idle_timer, instance_delete_timer);
  578. im->idle_timer = INVALID_TIMER;
  579. }
  580. if (mode == IM_CHAR && sd)
  581. sd->instance_id = 0;
  582. else if (mode == IM_PARTY && pd)
  583. pd->instance_id = 0;
  584. else if (mode == IM_GUILD && gd)
  585. gd->instance_id = 0;
  586. else if (mode == IM_CLAN && cd)
  587. cd->instance_id = 0;
  588. if (mode != IM_NONE) {
  589. if(type)
  590. clif_instance_changestatus(instance_id, type, 0);
  591. else
  592. clif_instance_changewait(instance_id, 0xffff);
  593. }
  594. if( im->regs.vars ) {
  595. db_destroy(im->regs.vars);
  596. im->regs.vars = NULL;
  597. }
  598. if( im->regs.arrays )
  599. instance_data[instance_id].regs.arrays->destroy(instance_data[instance_id].regs.arrays, script_free_array_db);
  600. ShowInfo("[Instance] Destroyed %hu.\n", instance_id);
  601. memset(&instance_data[instance_id], 0, sizeof(instance_data[instance_id]));
  602. return 0;
  603. }
  604. /*==========================================
  605. * Warp a user into instance
  606. *------------------------------------------*/
  607. enum e_instance_enter instance_enter(struct map_session_data *sd, unsigned short instance_id, const char *name, short x, short y)
  608. {
  609. struct instance_data *im = NULL;
  610. struct instance_db *db = NULL;
  611. struct party_data *pd = NULL;
  612. struct guild *gd = NULL;
  613. struct clan *cd = NULL;
  614. enum instance_mode mode;
  615. int16 m;
  616. nullpo_retr(IE_OTHER, sd);
  617. if( (db = instance_searchname_db(name)) == NULL ){
  618. ShowError( "instance_enter: Unknown instance \"%s\".\n", name );
  619. return IE_OTHER;
  620. }
  621. // If one of the two coordinates was not given or is below zero, we use the entry point from the database
  622. if( x < 0 || y < 0 ){
  623. x = db->enter.x;
  624. y = db->enter.y;
  625. }
  626. // Check if it is a valid instance
  627. if( instance_id == 0 ){
  628. // im will stay NULL and by default party checks will be used
  629. mode = IM_PARTY;
  630. }else{
  631. im = &instance_data[instance_id];
  632. mode = im->mode;
  633. }
  634. switch(mode) {
  635. case IM_NONE:
  636. break;
  637. case IM_CHAR:
  638. if (sd->instance_id == 0) // Player must have an instance
  639. return IE_NOINSTANCE;
  640. if (im->owner_id != sd->status.char_id)
  641. return IE_OTHER;
  642. break;
  643. case IM_PARTY:
  644. if (sd->status.party_id == 0) // Character must be in instance party
  645. return IE_NOMEMBER;
  646. if ((pd = party_search(sd->status.party_id)) == NULL)
  647. return IE_NOMEMBER;
  648. if (pd->instance_id == 0 || im == NULL) // Party must have an instance
  649. return IE_NOINSTANCE;
  650. if (im->owner_id != pd->party.party_id)
  651. return IE_OTHER;
  652. break;
  653. case IM_GUILD:
  654. if (sd->status.guild_id == 0) // Character must be in instance guild
  655. return IE_NOMEMBER;
  656. if ((gd = guild_search(sd->status.guild_id)) == NULL)
  657. return IE_NOMEMBER;
  658. if (gd->instance_id == 0) // Guild must have an instance
  659. return IE_NOINSTANCE;
  660. if (im->owner_id != gd->guild_id)
  661. return IE_OTHER;
  662. break;
  663. case IM_CLAN:
  664. if (sd->status.clan_id == 0) // Character must be in instance clan
  665. return IE_NOMEMBER;
  666. if ((cd = clan_search(sd->status.clan_id)) == NULL)
  667. return IE_NOMEMBER;
  668. if (cd->instance_id == 0) // Clan must have an instance
  669. return IE_NOINSTANCE;
  670. if (im->owner_id != cd->id)
  671. return IE_OTHER;
  672. break;
  673. }
  674. if (im->state != INSTANCE_BUSY)
  675. return IE_OTHER;
  676. if (im->type != db->id)
  677. return IE_OTHER;
  678. // Does the instance match?
  679. if ((m = instance_mapname2mapid(StringBuf_Value(db->enter.mapname), instance_id)) < 0)
  680. return IE_OTHER;
  681. if (pc_setpos(sd, map_id2index(m), x, y, CLR_OUTSIGHT))
  682. return IE_OTHER;
  683. // If there was an idle timer, let's stop it
  684. instance_stopidletimer(im, instance_id);
  685. // Now we start the instance timer
  686. instance_startkeeptimer(im, instance_id);
  687. return IE_OK;
  688. }
  689. /*==========================================
  690. * Request some info about the instance
  691. *------------------------------------------*/
  692. int instance_reqinfo(struct map_session_data *sd, unsigned short instance_id)
  693. {
  694. struct instance_data *im;
  695. nullpo_retr(1, sd);
  696. if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA)
  697. return 1;
  698. im = &instance_data[instance_id];
  699. if(instance_searchtype_db(im->type) == NULL)
  700. return 1;
  701. // Say it's created if instance is not busy
  702. if(im->state == INSTANCE_IDLE) {
  703. int i;
  704. for(i = 0; i < instance_wait.count; i++) {
  705. if(instance_wait.id[i] == instance_id) {
  706. clif_instance_create(instance_id, i + 1);
  707. break;
  708. }
  709. }
  710. } else if(im->state == INSTANCE_BUSY) // Give info on the instance if busy
  711. clif_instance_status(instance_id, im->keep_limit, im->idle_limit);
  712. return 0;
  713. }
  714. /*==========================================
  715. * Add players to the instance (for timers)
  716. *------------------------------------------*/
  717. int instance_addusers(unsigned short instance_id)
  718. {
  719. struct instance_data *im;
  720. if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA)
  721. return 1;
  722. im = &instance_data[instance_id];
  723. if(im->state != INSTANCE_BUSY)
  724. return 1;
  725. // Stop the idle timer if we had one
  726. instance_stopidletimer(im, instance_id);
  727. // Start the instance keep timer
  728. instance_startkeeptimer(im, instance_id);
  729. return 0;
  730. }
  731. /*==========================================
  732. * Delete players from the instance (for timers)
  733. *------------------------------------------*/
  734. int instance_delusers(unsigned short instance_id)
  735. {
  736. struct instance_data *im;
  737. int i, users = 0;
  738. if(instance_id == 0 || instance_id > MAX_INSTANCE_DATA)
  739. return 1;
  740. im = &instance_data[instance_id];
  741. if(im->state != INSTANCE_BUSY)
  742. return 1;
  743. // If no one is in the instance, start the idle timer
  744. for(i = 0; i < im->cnt_map && im->map[i]->m; i++)
  745. users += max(map[im->map[i]->m].users,0);
  746. // We check the actual map.users before being updated, hence the 1
  747. // The instance should be empty if users are now <= 1
  748. if(users <= 1)
  749. instance_startidletimer(im, instance_id);
  750. return 0;
  751. }
  752. static bool instance_db_free_sub(struct instance_db *db);
  753. /*==========================================
  754. * Read the instance_db.txt file
  755. *------------------------------------------*/
  756. static bool instance_readdb_sub(char* str[], int columns, int current)
  757. {
  758. uint8 i,j;
  759. char *ptr;
  760. int id = strtol(str[0], &ptr, 10);
  761. struct instance_db *db;
  762. bool isNew = false;
  763. if (!id || id > USHRT_MAX || *ptr) {
  764. ShowError("instance_readdb_sub: Cannot add instance with ID '%d'. Valid IDs are 1 ~ %d, skipping...\n", id, USHRT_MAX);
  765. return false;
  766. }
  767. if (mapindex_name2id(str[4]) == 0) {
  768. ShowError("instance_readdb_sub: Invalid map '%s' as entrance map, skipping...\n", str[4]);
  769. return false;
  770. }
  771. if (!(db = (struct instance_db *)uidb_get(InstanceDB, id))) {
  772. CREATE(db, struct instance_db, 1);
  773. db->id = id;
  774. db->name = StringBuf_Malloc();
  775. db->enter.mapname = StringBuf_Malloc();
  776. isNew = true;
  777. } else {
  778. StringBuf_Clear(db->name);
  779. StringBuf_Clear(db->enter.mapname);
  780. if (db->maplist_count) {
  781. for (i = 0; i < db->maplist_count; i++)
  782. StringBuf_Free(db->maplist[i]);
  783. aFree(db->maplist);
  784. db->maplist = NULL;
  785. }
  786. db->maplist_count = 0;
  787. }
  788. StringBuf_AppendStr(db->name, str[1]);
  789. db->limit = strtol(str[2], &ptr, 10);
  790. if (*ptr) {
  791. ShowError("instance_readdb_sub: TimeLimit must be an integer value for instance '%d', skipping...\n", id);
  792. instance_db_free_sub(db);
  793. return false;
  794. }
  795. db->timeout = strtol(str[3], &ptr, 10);
  796. if (*ptr) {
  797. ShowError("instance_readdb_sub: IdleTimeOut must be an integer value for instance '%d', skipping...\n", id);
  798. instance_db_free_sub(db);
  799. return false;
  800. }
  801. StringBuf_AppendStr(db->enter.mapname, str[4]);
  802. db->enter.x = (short)strtol(str[5], &ptr, 10);
  803. if (*ptr) {
  804. ShowError("instance_readdb_sub: EnterX must be an integer value for instance '%d', skipping...\n", id);
  805. instance_db_free_sub(db);
  806. return false;
  807. }
  808. db->enter.y = (short)strtol(str[6], &ptr, 10);
  809. if (*ptr) {
  810. ShowError("instance_readdb_sub: EnterY must be an integer value for instance '%d', skipping...\n", id);
  811. instance_db_free_sub(db);
  812. return false;
  813. }
  814. //Instance maps
  815. for (i = 7; i < columns; i++) {
  816. if (strlen(str[i])) {
  817. if (mapindex_name2id(str[i]) == 0) {
  818. ShowWarning("instance_readdb_sub: Invalid map '%s' in maplist, skipping...\n", str[i]);
  819. continue;
  820. }
  821. if (strcmpi(str[4], str[i]) == 0) {
  822. ShowWarning("instance_readdb_sub: '%s'(Map%d) must not be equal to EnterMap for instance id '%d', skipping...\n", str[i], i - 5, id);
  823. continue;
  824. }
  825. // Check if the map is in the list already
  826. for (j = 7; j < i; j++) {
  827. // Skip empty columns
  828. if (!strlen(str[j])) {
  829. continue;
  830. }
  831. if (strcmpi(str[j], str[i]) == 0) {
  832. break;
  833. }
  834. }
  835. // If it was already in the list
  836. if (j < i) {
  837. ShowWarning("instance_readdb_sub: '%s'(Map%d) was already added for instance id '%d', skipping...\n", str[i], i - 5, id);
  838. continue; // Skip it
  839. }
  840. RECREATE(db->maplist, StringBuf *, db->maplist_count+1);
  841. db->maplist[db->maplist_count] = StringBuf_Malloc();
  842. StringBuf_AppendStr(db->maplist[db->maplist_count], str[i]);
  843. db->maplist_count++;
  844. }
  845. }
  846. if (isNew) {
  847. uidb_put(InstanceDB, id, db);
  848. strdb_uiput(InstanceNameDB, StringBuf_Value(db->name), id);
  849. }
  850. return true;
  851. }
  852. /**
  853. * Free InstanceDB single entry
  854. * @param db Instance Db entry
  855. **/
  856. static bool instance_db_free_sub(struct instance_db *db) {
  857. if (!db)
  858. return 1;
  859. StringBuf_Free(db->name);
  860. StringBuf_Free(db->enter.mapname);
  861. if (db->maplist_count) {
  862. uint8 i;
  863. for (i = 0; i < db->maplist_count; i++)
  864. StringBuf_Free(db->maplist[i]);
  865. aFree(db->maplist);
  866. }
  867. aFree(db);
  868. return 0;
  869. }
  870. /**
  871. * Free InstanceDB entries
  872. **/
  873. static int instance_db_free(DBKey key, DBData *data, va_list ap) {
  874. struct instance_db *db = (struct instance_db *)db_data2ptr(data);
  875. return instance_db_free_sub(db);
  876. }
  877. /**
  878. * Read instance_db.txt files
  879. **/
  880. void instance_readdb(void) {
  881. const char* filename[] = { DBPATH"instance_db.txt", "import/instance_db.txt"};
  882. int f;
  883. for (f = 0; f<ARRAYLENGTH(filename); f++) {
  884. sv_readdb(db_path, filename[f], ',', 7, 7+MAX_MAP_PER_INSTANCE, -1, &instance_readdb_sub, f > 0);
  885. }
  886. }
  887. /**
  888. * Reload Instance DB
  889. **/
  890. void instance_reload(void) {
  891. InstanceDB->clear(InstanceDB, instance_db_free);
  892. db_clear(InstanceNameDB);
  893. instance_readdb();
  894. }
  895. /*==========================================
  896. * Reloads the instance in runtime (reloadscript)
  897. *------------------------------------------*/
  898. void do_reload_instance(void)
  899. {
  900. struct instance_data *im;
  901. struct instance_db *db = NULL;
  902. struct s_mapiterator* iter;
  903. struct map_session_data *sd;
  904. unsigned short i;
  905. for( i = 1; i < MAX_INSTANCE_DATA; i++ ) {
  906. im = &instance_data[i];
  907. if(!im->cnt_map)
  908. continue;
  909. else {
  910. // First we load the NPCs again
  911. instance_addnpc(im);
  912. // Create new keep timer
  913. if((db = instance_searchtype_db(im->type)) != NULL)
  914. im->keep_limit = (unsigned int)time(NULL) + db->limit;
  915. }
  916. }
  917. // Reset player to instance beginning
  918. iter = mapit_getallusers();
  919. for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
  920. if(sd && map[sd->bl.m].instance_id) {
  921. struct party_data *pd = NULL;
  922. struct guild *gd = NULL;
  923. struct clan *cd = NULL;
  924. unsigned short instance_id;
  925. im = &instance_data[map[sd->bl.m].instance_id];
  926. switch (im->mode) {
  927. case IM_NONE:
  928. continue;
  929. case IM_CHAR:
  930. if (sd->instance_id != map[sd->bl.m].instance_id) // Someone who is not instance owner is on instance map
  931. continue;
  932. instance_id = sd->instance_id;
  933. break;
  934. case IM_PARTY:
  935. if ((!(pd = party_search(sd->status.party_id)) || pd->instance_id != map[sd->bl.m].instance_id)) // Someone not in party is on instance map
  936. continue;
  937. instance_id = pd->instance_id;
  938. break;
  939. case IM_GUILD:
  940. if (!(gd = guild_search(sd->status.guild_id)) || gd->instance_id != map[sd->bl.m].instance_id) // Someone not in guild is on instance map
  941. continue;
  942. instance_id = gd->instance_id;
  943. break;
  944. case IM_CLAN:
  945. if (!(cd = clan_search(sd->status.clan_id)) || cd->instance_id != map[sd->bl.m].instance_id) // Someone not in clan is on instance map
  946. continue;
  947. instance_id = cd->instance_id;
  948. break;
  949. default:
  950. ShowError("do_reload_instance: Unexpected instance mode for instance %s (id=%u, mode=%u).\n", (db) ? StringBuf_Value(db->name) : "Unknown", map[sd->bl.m].instance_id, (unsigned short)im->mode);
  951. continue;
  952. }
  953. if((db = instance_searchtype_db(im->type)) != NULL && !instance_enter(sd, instance_id, StringBuf_Value(db->name), -1, -1)) { // All good
  954. clif_displaymessage(sd->fd, msg_txt(sd,515)); // Instance has been reloaded
  955. instance_reqinfo(sd,instance_id);
  956. } else // Something went wrong
  957. ShowError("do_reload_instance: Error setting character at instance start: character_id=%d instance=%s.\n",sd->status.char_id,StringBuf_Value(db->name));
  958. }
  959. mapit_free(iter);
  960. }
  961. void do_init_instance(void) {
  962. InstanceDB = uidb_alloc(DB_OPT_BASE);
  963. InstanceNameDB = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),0);
  964. instance_readdb();
  965. memset(instance_data, 0, sizeof(instance_data));
  966. memset(&instance_wait, 0, sizeof(instance_wait));
  967. instance_wait.timer = -1;
  968. instance_maps_ers = ers_new(sizeof(struct s_instance_map),"instance.cpp::instance_maps_ers", ERS_OPT_NONE);
  969. add_timer_func_list(instance_delete_timer,"instance_delete_timer");
  970. add_timer_func_list(instance_subscription_timer,"instance_subscription_timer");
  971. }
  972. void do_final_instance(void) {
  973. int i;
  974. ers_destroy(instance_maps_ers);
  975. for( i = 1; i < MAX_INSTANCE_DATA; i++ )
  976. instance_destroy(i);
  977. InstanceDB->destroy(InstanceDB, instance_db_free);
  978. db_destroy(InstanceNameDB);
  979. }