PageRenderTime 63ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/map/instance.c

https://gitlab.com/evol/hercules
C | 794 lines | 574 code | 123 blank | 97 comment | 163 complexity | 3e5479d3916f9d56fc3077735172d0f7 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0
  1. /**
  2. * This file is part of Hercules.
  3. * http://herc.ws - http://github.com/HerculesWS/Hercules
  4. *
  5. * Copyright (C) 2012-2015 Hercules Dev Team
  6. * Copyright (C) Athena Dev Teams
  7. *
  8. * Hercules is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #define HERCULES_CORE
  22. #include "config/core.h" // CELL_NOSTACK
  23. #include "instance.h"
  24. #include "map/channel.h"
  25. #include "map/clif.h"
  26. #include "map/guild.h"
  27. #include "map/map.h"
  28. #include "map/npc.h"
  29. #include "map/party.h"
  30. #include "map/pc.h"
  31. #include "common/HPM.h"
  32. #include "common/cbasetypes.h"
  33. #include "common/db.h"
  34. #include "common/memmgr.h"
  35. #include "common/nullpo.h"
  36. #include "common/showmsg.h"
  37. #include "common/socket.h"
  38. #include "common/strlib.h"
  39. #include "common/timer.h"
  40. #include "common/utils.h"
  41. #include <stdarg.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <time.h>
  46. struct instance_interface instance_s;
  47. struct instance_interface *instance;
  48. /// Checks whether given instance id is valid or not.
  49. bool instance_is_valid(int instance_id) {
  50. if( instance_id < 0 || instance_id >= instance->instances ) {// out of range
  51. return false;
  52. }
  53. if( instance->list[instance_id].state == INSTANCE_FREE ) {// uninitialized/freed instance slot
  54. return false;
  55. }
  56. return true;
  57. }
  58. /*--------------------------------------
  59. * name : instance name
  60. * Return value could be
  61. * -4 = already exists | -3 = no free instances | -2 = owner not found | -1 = invalid type
  62. * On success return instance_id
  63. *--------------------------------------*/
  64. int instance_create(int owner_id, const char *name, enum instance_owner_type type) {
  65. struct map_session_data *sd = NULL;
  66. unsigned short *icptr = NULL;
  67. struct party_data *p = NULL;
  68. struct guild *g = NULL;
  69. short *iptr = NULL;
  70. int i;
  71. nullpo_retr(-1, name);
  72. switch ( type ) {
  73. case IOT_NONE:
  74. break;
  75. case IOT_CHAR:
  76. if( ( sd = map->id2sd(owner_id) ) == NULL ) {
  77. ShowError("instance_create: character %d not found for instance '%s'.\n", owner_id, name);
  78. return -2;
  79. }
  80. iptr = sd->instance;
  81. icptr = &sd->instances;
  82. break;
  83. case IOT_PARTY:
  84. if( ( p = party->search(owner_id) ) == NULL ) {
  85. ShowError("instance_create: party %d not found for instance '%s'.\n", owner_id, name);
  86. return -2;
  87. }
  88. iptr = p->instance;
  89. icptr = &p->instances;
  90. break;
  91. case IOT_GUILD:
  92. if( ( g = guild->search(owner_id) ) == NULL ) {
  93. ShowError("instance_create: guild %d not found for instance '%s'.\n", owner_id, name);
  94. return -2;
  95. }
  96. iptr = g->instance;
  97. icptr = &g->instances;
  98. break;
  99. default:
  100. ShowError("instance_create: unknown type %d for owner_id %d and name %s.\n", type,owner_id,name);
  101. return -1;
  102. }
  103. if( type != IOT_NONE && *icptr ) {
  104. ARR_FIND(0, *icptr, i, iptr[i] != -1 && strcmp(instance->list[iptr[i]].name, name) == 0 );
  105. if( i != *icptr )
  106. return -4; /* already got this instance */
  107. }
  108. ARR_FIND(0, instance->instances, i, instance->list[i].state == INSTANCE_FREE);
  109. if( i == instance->instances )
  110. RECREATE(instance->list, struct instance_data, ++instance->instances);
  111. instance->list[i].state = INSTANCE_IDLE;
  112. instance->list[i].id = i;
  113. instance->list[i].idle_timer = INVALID_TIMER;
  114. instance->list[i].idle_timeout = instance->list[i].idle_timeoutval = 0;
  115. instance->list[i].progress_timer = INVALID_TIMER;
  116. instance->list[i].progress_timeout = 0;
  117. instance->list[i].users = 0;
  118. instance->list[i].map = NULL;
  119. instance->list[i].num_map = 0;
  120. instance->list[i].owner_id = owner_id;
  121. instance->list[i].owner_type = type;
  122. instance->list[i].regs.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
  123. instance->list[i].regs.arrays = NULL;
  124. instance->list[i].respawn.map = 0;
  125. instance->list[i].respawn.y = 0;
  126. instance->list[i].respawn.x = 0;
  127. safestrncpy( instance->list[i].name, name, sizeof(instance->list[i].name) );
  128. if( type != IOT_NONE ) {
  129. int j;
  130. ARR_FIND(0, *icptr, j, iptr[j] == -1);
  131. if (j == *icptr) {
  132. switch( type ) {
  133. case IOT_CHAR:
  134. RECREATE(sd->instance, short, ++*icptr);
  135. sd->instance[sd->instances-1] = i;
  136. break;
  137. case IOT_PARTY:
  138. RECREATE(p->instance, short, ++*icptr);
  139. p->instance[p->instances-1] = i;
  140. break;
  141. case IOT_GUILD:
  142. RECREATE(g->instance, short, ++*icptr);
  143. g->instance[g->instances-1] = i;
  144. break;
  145. }
  146. } else {
  147. iptr[j] = i;
  148. }
  149. }
  150. clif->instance(i, 1, 0); // Start instancing window
  151. return i;
  152. }
  153. /**
  154. * Add a map to the instance using src map "name"
  155. *
  156. * @param name Source map name.
  157. * @param instance_id The destination instance ID.
  158. * @param usebasename Whether to generate a standard instance map name (only used if map_name is not NULL).
  159. * @param map_name The name for the instanced map (may be NULL to generate a new one).
  160. * @return The generated map's index.
  161. * @retval -1 Map or instance not found.
  162. * @retval -2 Duplicate map name.
  163. * @retval -3 No more map indices available.
  164. * @retval -4 Source map is already an instance.
  165. **/
  166. int instance_add_map(const char *name, int instance_id, bool usebasename, const char *map_name) {
  167. int16 m = map->mapname2mapid(name);
  168. int i, im = -1;
  169. size_t num_cell, size, j;
  170. nullpo_retr(-1, name);
  171. if( m < 0 )
  172. return -1; // source map not found
  173. if( !instance->valid(instance_id) ) {
  174. ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id);
  175. return -1;
  176. }
  177. if( map_name != NULL && strdb_iget(mapindex->db, map_name) ) {
  178. ShowError("instance_add_map: trying to create instanced map with existent name '%s'\n", map_name);
  179. return -2;
  180. }
  181. if( map->list[m].instance_id >= 0 ) {
  182. // Source map already belong to a Instance.
  183. ShowError("instance_add_map: trying to instance already instanced map %s.\n", name);
  184. return -4;
  185. }
  186. ARR_FIND( instance->start_id, map->count, i, map->list[i].name[0] == 0 ); // Searching for a Free Map
  187. if( i < map->count )
  188. im = i; // Unused map found (old instance)
  189. else {
  190. im = map->count; // Using next map index
  191. RECREATE(map->list,struct map_data,++map->count);
  192. }
  193. if( map->list[m].cell == (struct mapcell *)0xdeadbeaf )
  194. map->cellfromcache(&map->list[m]);
  195. memcpy( &map->list[im], &map->list[m], sizeof(struct map_data) ); // Copy source map
  196. if( map_name != NULL ) {
  197. snprintf(map->list[im].name, MAP_NAME_LENGTH, "%s", map_name);
  198. map->list[im].custom_name = true;
  199. } else
  200. snprintf(map->list[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map
  201. map->list[im].index = mapindex->addmap(-1, map->list[im].name); // Add map index
  202. map->list[im].channel = NULL;
  203. if( !map->list[im].index ) {
  204. map->list[im].name[0] = '\0';
  205. ShowError("instance_add_map: no more free map indexes.\n");
  206. return -3; // No free map index
  207. }
  208. // Reallocate cells
  209. num_cell = map->list[im].xs * map->list[im].ys;
  210. CREATE( map->list[im].cell, struct mapcell, num_cell );
  211. memcpy( map->list[im].cell, map->list[m].cell, num_cell * sizeof(struct mapcell) );
  212. // Appropriately clear cell data
  213. for(j = 0; j < num_cell; j++) {
  214. #ifdef CELL_NOSTACK
  215. map->list[im].cell[j].cell_bl = 0;
  216. #endif // CELL_NOSTACK
  217. map->list[im].cell[j].basilica = 0;
  218. map->list[im].cell[j].icewall = 0;
  219. map->list[im].cell[j].npc = 0;
  220. map->list[im].cell[j].landprotector = 0;
  221. }
  222. size = map->list[im].bxs * map->list[im].bys * sizeof(struct block_list*);
  223. map->list[im].block = (struct block_list**)aCalloc(size, 1);
  224. map->list[im].block_mob = (struct block_list**)aCalloc(size, 1);
  225. memset(map->list[im].npc, 0x00, sizeof(map->list[i].npc));
  226. map->list[im].npc_num = 0;
  227. memset(map->list[im].moblist, 0x00, sizeof(map->list[im].moblist));
  228. map->list[im].mob_delete_timer = INVALID_TIMER;
  229. //Mimic unit
  230. if( map->list[m].unit_count ) {
  231. map->list[im].unit_count = map->list[m].unit_count;
  232. CREATE( map->list[im].units, struct mapflag_skill_adjust*, map->list[im].unit_count );
  233. for(i = 0; i < map->list[im].unit_count; i++) {
  234. CREATE( map->list[im].units[i], struct mapflag_skill_adjust, 1);
  235. memcpy( map->list[im].units[i],map->list[m].units[i],sizeof(struct mapflag_skill_adjust));
  236. }
  237. }
  238. //Mimic skills
  239. if( map->list[m].skill_count ) {
  240. map->list[im].skill_count = map->list[m].skill_count;
  241. CREATE( map->list[im].skills, struct mapflag_skill_adjust*, map->list[im].skill_count );
  242. for(i = 0; i < map->list[im].skill_count; i++) {
  243. CREATE( map->list[im].skills[i], struct mapflag_skill_adjust, 1);
  244. memcpy( map->list[im].skills[i],map->list[m].skills[i],sizeof(struct mapflag_skill_adjust));
  245. }
  246. }
  247. //Mimic zone mf
  248. if( map->list[m].zone_mf_count ) {
  249. map->list[im].zone_mf_count = map->list[m].zone_mf_count;
  250. CREATE( map->list[im].zone_mf, char *, map->list[im].zone_mf_count );
  251. for(i = 0; i < map->list[im].zone_mf_count; i++) {
  252. CREATE(map->list[im].zone_mf[i], char, MAP_ZONE_MAPFLAG_LENGTH);
  253. safestrncpy(map->list[im].zone_mf[i],map->list[m].zone_mf[i],MAP_ZONE_MAPFLAG_LENGTH);
  254. }
  255. }
  256. //Mimic questinfo
  257. if( map->list[m].qi_count ) {
  258. map->list[im].qi_count = map->list[m].qi_count;
  259. CREATE( map->list[im].qi_data, struct questinfo, map->list[im].qi_count );
  260. memcpy( map->list[im].qi_data, map->list[m].qi_data, map->list[im].qi_count * sizeof(struct questinfo) );
  261. }
  262. map->list[im].m = im;
  263. map->list[im].instance_id = instance_id;
  264. map->list[im].instance_src_map = m;
  265. map->list[im].flag.src4instance = 0; //clear
  266. map->list[m].flag.src4instance = 1; // Flag this map as a src map for instances
  267. RECREATE(instance->list[instance_id].map, unsigned short, ++instance->list[instance_id].num_map);
  268. instance->list[instance_id].map[instance->list[instance_id].num_map - 1] = im; // Attach to actual instance
  269. map->addmap2db(&map->list[im]);
  270. return im;
  271. }
  272. /*--------------------------------------
  273. * m : source map of this instance
  274. * party_id : source party of this instance
  275. * type : result (0 = map id | 1 = instance id)
  276. *--------------------------------------*/
  277. int instance_map2imap(int16 m, int instance_id) {
  278. int i;
  279. if( !instance->valid(instance_id) ) {
  280. return -1;
  281. }
  282. for( i = 0; i < instance->list[instance_id].num_map; i++ ) {
  283. if( instance->list[instance_id].map[i] && map->list[instance->list[instance_id].map[i]].instance_src_map == m )
  284. return instance->list[instance_id].map[i];
  285. }
  286. return -1;
  287. }
  288. int instance_mapname2imap(const char *map_name, int instance_id) {
  289. int i;
  290. nullpo_retr(-1, map_name);
  291. if( !instance->valid(instance_id) ) {
  292. return -1;
  293. }
  294. for( i = 0; i < instance->list[instance_id].num_map; i++ ) {
  295. if( instance->list[instance_id].map[i] && !strcmpi(map->list[map->list[instance->list[instance_id].map[i]].instance_src_map].name,map_name) )
  296. return instance->list[instance_id].map[i];
  297. }
  298. return -1;
  299. }
  300. /*--------------------------------------
  301. * m : source map
  302. * instance_id : where to search
  303. * result : mapid of map "m" in this instance
  304. *--------------------------------------*/
  305. int instance_mapid2imapid(int16 m, int instance_id) {
  306. Assert_retr(-1, m >= 0 && m < map->count);
  307. if( map->list[m].flag.src4instance == 0 )
  308. return m; // not instances found for this map
  309. else if( map->list[m].instance_id >= 0 ) { // This map is a instance, not a src map instance
  310. ShowError("map_instance_mapid2imapid: already instanced (%d / %d)\n", m, instance_id);
  311. return -1;
  312. }
  313. if( !instance->valid(instance_id) )
  314. return -1;
  315. return instance->map2imap(m, instance_id);
  316. }
  317. /*--------------------------------------
  318. * Used on Init instance. Duplicates each script on source map
  319. *--------------------------------------*/
  320. int instance_map_npcsub(struct block_list* bl, va_list args)
  321. {
  322. struct npc_data *nd = NULL;
  323. int16 m = va_arg(args, int); // Destination Map
  324. nullpo_ret(bl);
  325. Assert_ret(bl->type == BL_NPC);
  326. nd = BL_UCAST(BL_NPC, bl);
  327. if (npc->duplicate4instance(nd, m))
  328. ShowDebug("instance_map_npcsub:npc_duplicate4instance failed (%s/%d)\n",nd->name,m);
  329. return 1;
  330. }
  331. int instance_init_npc(struct block_list* bl, va_list args)
  332. {
  333. struct npc_data *nd = NULL;
  334. struct event_data *ev;
  335. char evname[EVENT_NAME_LENGTH];
  336. nullpo_ret(bl);
  337. Assert_ret(bl->type == BL_NPC);
  338. nd = BL_UCAST(BL_NPC, bl);
  339. snprintf(evname, EVENT_NAME_LENGTH, "%s::OnInstanceInit", nd->exname);
  340. if( ( ev = strdb_get(npc->ev_db, evname) ) )
  341. script->run_npc(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id);
  342. return 1;
  343. }
  344. /*--------------------------------------
  345. * Init all map on the instance. Npcs are created here
  346. *--------------------------------------*/
  347. void instance_init(int instance_id) {
  348. int i;
  349. if( !instance->valid(instance_id) )
  350. return; // nothing to do
  351. for( i = 0; i < instance->list[instance_id].num_map; i++ )
  352. map->foreachinmap(instance->map_npcsub, map->list[instance->list[instance_id].map[i]].instance_src_map, BL_NPC, instance->list[instance_id].map[i]);
  353. /* cant be together with the previous because it will rely on all of them being up */
  354. map->foreachininstance(instance->init_npc, instance_id, BL_NPC);
  355. instance->list[instance_id].state = INSTANCE_BUSY;
  356. }
  357. /*--------------------------------------
  358. * Used on instance deleting process.
  359. * Warps all players on each instance map to its save points.
  360. *--------------------------------------*/
  361. int instance_del_load(struct map_session_data* sd, va_list args) {
  362. int16 m = va_arg(args,int);
  363. if( !sd || sd->bl.m != m )
  364. return 0;
  365. pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT);
  366. return 1;
  367. }
  368. /* for npcs behave differently when being unloaded within a instance */
  369. int instance_cleanup_sub(struct block_list *bl, va_list ap) {
  370. nullpo_ret(bl);
  371. switch(bl->type) {
  372. case BL_PC:
  373. map->quit(BL_UCAST(BL_PC, bl));
  374. break;
  375. case BL_NPC:
  376. npc->unload(BL_UCAST(BL_NPC, bl), true);
  377. break;
  378. case BL_MOB:
  379. unit->free(bl,CLR_OUTSIGHT);
  380. break;
  381. case BL_PET:
  382. //There is no need for this, the pet is removed together with the player. [Skotlex]
  383. break;
  384. case BL_ITEM:
  385. map->clearflooritem(bl);
  386. break;
  387. case BL_SKILL:
  388. skill->delunit(BL_UCAST(BL_SKILL, bl));
  389. break;
  390. }
  391. return 1;
  392. }
  393. /*--------------------------------------
  394. * Removes a simple instance map
  395. *--------------------------------------*/
  396. void instance_del_map(int16 m) {
  397. int i;
  398. if( m <= 0 || map->list[m].instance_id == -1 ) {
  399. ShowError("instance_del_map: tried to remove non-existing instance map (%d)\n", m);
  400. return;
  401. }
  402. map->foreachpc(instance_del_load, m);
  403. map->foreachinmap(instance_cleanup_sub, m, BL_ALL);
  404. if( map->list[m].mob_delete_timer != INVALID_TIMER )
  405. timer->delete(map->list[m].mob_delete_timer, map->removemobs_timer);
  406. mapindex->removemap(map_id2index(m));
  407. // Free memory
  408. aFree(map->list[m].cell);
  409. aFree(map->list[m].block);
  410. aFree(map->list[m].block_mob);
  411. if (map->list[m].unit_count && map->list[m].units) {
  412. for(i = 0; i < map->list[m].unit_count; i++) {
  413. aFree(map->list[m].units[i]);
  414. }
  415. aFree(map->list[m].units);
  416. }
  417. if (map->list[m].skill_count && map->list[m].skills) {
  418. for(i = 0; i < map->list[m].skill_count; i++) {
  419. aFree(map->list[m].skills[i]);
  420. }
  421. aFree(map->list[m].skills);
  422. }
  423. if (map->list[m].zone_mf_count && map->list[m].zone_mf) {
  424. for(i = 0; i < map->list[m].zone_mf_count; i++) {
  425. aFree(map->list[m].zone_mf[i]);
  426. }
  427. aFree(map->list[m].zone_mf);
  428. }
  429. if( map->list[m].qi_data )
  430. aFree(map->list[m].qi_data);
  431. // Remove from instance
  432. for( i = 0; i < instance->list[map->list[m].instance_id].num_map; i++ ) {
  433. if( instance->list[map->list[m].instance_id].map[i] == m ) {
  434. instance->list[map->list[m].instance_id].num_map--;
  435. for( ; i < instance->list[map->list[m].instance_id].num_map; i++ )
  436. instance->list[map->list[m].instance_id].map[i] = instance->list[map->list[m].instance_id].map[i+1];
  437. i = -1;
  438. break;
  439. }
  440. }
  441. if( i == instance->list[map->list[m].instance_id].num_map )
  442. ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map->list[m].name, instance->list[map->list[m].instance_id].name, m);
  443. if( map->list[m].channel )
  444. channel->delete(map->list[m].channel);
  445. map->removemapdb(&map->list[m]);
  446. memset(&map->list[m], 0x00, sizeof(map->list[0]));
  447. map->list[m].name[0] = 0;
  448. map->list[m].instance_id = -1;
  449. map->list[m].mob_delete_timer = INVALID_TIMER;
  450. }
  451. /*--------------------------------------
  452. * Timer to destroy instance by process or idle
  453. *--------------------------------------*/
  454. int instance_destroy_timer(int tid, int64 tick, int id, intptr_t data) {
  455. instance->destroy(id);
  456. return 0;
  457. }
  458. /*--------------------------------------
  459. * Removes a instance, all its maps and npcs.
  460. *--------------------------------------*/
  461. void instance_destroy(int instance_id) {
  462. struct map_session_data *sd = NULL;
  463. unsigned short *icptr = NULL;
  464. struct party_data *p = NULL;
  465. struct guild *g = NULL;
  466. short *iptr = NULL;
  467. int type, j;
  468. unsigned int now = (unsigned int)time(NULL);
  469. if( !instance->valid(instance_id) )
  470. return; // nothing to do
  471. if( instance->list[instance_id].progress_timeout && instance->list[instance_id].progress_timeout <= now )
  472. type = 1;
  473. else if( instance->list[instance_id].idle_timeout && instance->list[instance_id].idle_timeout <= now )
  474. type = 2;
  475. else
  476. type = 3;
  477. clif->instance(instance_id, 5, type); // Report users this instance has been destroyed
  478. switch ( instance->list[instance_id].owner_type ) {
  479. case IOT_NONE:
  480. break;
  481. case IOT_CHAR:
  482. if( ( sd = map->id2sd(instance->list[instance_id].owner_id) ) == NULL ) {
  483. break;
  484. }
  485. iptr = sd->instance;
  486. icptr = &sd->instances;
  487. break;
  488. case IOT_PARTY:
  489. if( ( p = party->search(instance->list[instance_id].owner_id) ) == NULL ) {
  490. break;
  491. }
  492. iptr = p->instance;
  493. icptr = &p->instances;
  494. break;
  495. case IOT_GUILD:
  496. if( ( g = guild->search(instance->list[instance_id].owner_id) ) == NULL ) {
  497. break;
  498. }
  499. iptr = g->instance;
  500. icptr = &g->instances;
  501. break;
  502. default:
  503. ShowError("instance_destroy: unknown type %d for owner_id %d and name '%s'.\n", instance->list[instance_id].owner_type,instance->list[instance_id].owner_id,instance->list[instance_id].name);
  504. break;
  505. }
  506. if( iptr != NULL ) {
  507. ARR_FIND(0, *icptr, j, iptr[j] == instance_id);
  508. if( j != *icptr )
  509. iptr[j] = -1;
  510. }
  511. if (instance->list[instance_id].map) {
  512. int last = 0;
  513. while (instance->list[instance_id].num_map && last != instance->list[instance_id].map[0]) {
  514. // Remove all maps from instance
  515. last = instance->list[instance_id].map[0];
  516. instance->del_map( instance->list[instance_id].map[0] );
  517. }
  518. }
  519. if( instance->list[instance_id].regs.vars )
  520. db_destroy(instance->list[instance_id].regs.vars);
  521. if( instance->list[instance_id].regs.arrays )
  522. instance->list[instance_id].regs.arrays->destroy(instance->list[instance_id].regs.arrays, script->array_free_db);
  523. if( instance->list[instance_id].progress_timer != INVALID_TIMER )
  524. timer->delete( instance->list[instance_id].progress_timer, instance->destroy_timer);
  525. if( instance->list[instance_id].idle_timer != INVALID_TIMER )
  526. timer->delete( instance->list[instance_id].idle_timer, instance->destroy_timer);
  527. instance->list[instance_id].regs.vars = NULL;
  528. if( instance->list[instance_id].map )
  529. aFree(instance->list[instance_id].map);
  530. instance->list[instance_id].map = NULL;
  531. instance->list[instance_id].state = INSTANCE_FREE;
  532. instance->list[instance_id].num_map = 0;
  533. HPM->data_store_destroy(&instance->list[instance_id].hdata);
  534. }
  535. /*--------------------------------------
  536. * Checks if there are users in the instance or not to start idle timer
  537. *--------------------------------------*/
  538. void instance_check_idle(int instance_id) {
  539. bool idle = true;
  540. unsigned int now = (unsigned int)time(NULL);
  541. if( !instance->valid(instance_id) || instance->list[instance_id].idle_timeoutval == 0 )
  542. return;
  543. if( instance->list[instance_id].users )
  544. idle = false;
  545. if( instance->list[instance_id].idle_timer != INVALID_TIMER && !idle ) {
  546. timer->delete(instance->list[instance_id].idle_timer, instance->destroy_timer);
  547. instance->list[instance_id].idle_timer = INVALID_TIMER;
  548. instance->list[instance_id].idle_timeout = 0;
  549. clif->instance(instance_id, 3, 0); // Notify instance users normal instance expiration
  550. } else if( instance->list[instance_id].idle_timer == INVALID_TIMER && idle ) {
  551. instance->list[instance_id].idle_timeout = now + instance->list[instance_id].idle_timeoutval;
  552. instance->list[instance_id].idle_timer = timer->add( timer->gettick() + instance->list[instance_id].idle_timeoutval * 1000, instance->destroy_timer, instance_id, 0);
  553. clif->instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time
  554. }
  555. }
  556. /*--------------------------------------
  557. * Set instance Timers
  558. *--------------------------------------*/
  559. void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout)
  560. {
  561. unsigned int now = (unsigned int)time(0);
  562. if( !instance->valid(instance_id) )
  563. return;
  564. if( instance->list[instance_id].progress_timer != INVALID_TIMER )
  565. timer->delete( instance->list[instance_id].progress_timer, instance->destroy_timer);
  566. if( instance->list[instance_id].idle_timer != INVALID_TIMER )
  567. timer->delete( instance->list[instance_id].idle_timer, instance->destroy_timer);
  568. if( progress_timeout ) {
  569. instance->list[instance_id].progress_timeout = now + progress_timeout;
  570. instance->list[instance_id].progress_timer = timer->add( timer->gettick() + progress_timeout * 1000, instance->destroy_timer, instance_id, 0);
  571. instance->list[instance_id].original_progress_timeout = progress_timeout;
  572. } else {
  573. instance->list[instance_id].progress_timeout = 0;
  574. instance->list[instance_id].progress_timer = INVALID_TIMER;
  575. instance->list[instance_id].original_progress_timeout = 0;
  576. }
  577. if( idle_timeout ) {
  578. instance->list[instance_id].idle_timeoutval = idle_timeout;
  579. instance->list[instance_id].idle_timer = INVALID_TIMER;
  580. instance->check_idle(instance_id);
  581. } else {
  582. instance->list[instance_id].idle_timeoutval = 0;
  583. instance->list[instance_id].idle_timeout = 0;
  584. instance->list[instance_id].idle_timer = INVALID_TIMER;
  585. }
  586. if( instance->list[instance_id].idle_timer == INVALID_TIMER && instance->list[instance_id].progress_timer != INVALID_TIMER )
  587. clif->instance(instance_id, 3, 0);
  588. }
  589. /*--------------------------------------
  590. * Checks if sd in on a instance and should be kicked from it
  591. *--------------------------------------*/
  592. void instance_check_kick(struct map_session_data *sd) {
  593. int16 m = sd->bl.m;
  594. nullpo_retv(sd);
  595. clif->instance_leave(sd->fd);
  596. if( map->list[m].instance_id >= 0 ) { // User was on the instance map
  597. if( map->list[m].save.map )
  598. pc->setpos(sd, map->list[m].save.map, map->list[m].save.x, map->list[m].save.y, CLR_TELEPORT);
  599. else
  600. pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
  601. }
  602. }
  603. void do_reload_instance(void) {
  604. struct s_mapiterator *iter;
  605. struct map_session_data *sd;
  606. int i, k;
  607. for(i = 0; i < instance->instances; i++) {
  608. for(k = 0; k < instance->list[i].num_map; k++) {
  609. if( !map->list[map->list[instance->list[i].map[k]].instance_src_map].flag.src4instance )
  610. break;
  611. }
  612. if( k != instance->list[i].num_map ) /* any (or all) of them were disabled, we destroy */
  613. instance->destroy(i);
  614. else {
  615. /* populate the instance again */
  616. instance->start(i);
  617. /* restart timers */
  618. instance->set_timeout(i,instance->list[i].original_progress_timeout,instance->list[i].idle_timeoutval);
  619. }
  620. }
  621. iter = mapit_getallusers();
  622. for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
  623. if(sd && map->list[sd->bl.m].instance_id >= 0) {
  624. pc->setpos(sd,instance->list[map->list[sd->bl.m].instance_id].respawn.map,instance->list[map->list[sd->bl.m].instance_id].respawn.x,instance->list[map->list[sd->bl.m].instance_id].respawn.y,CLR_TELEPORT);
  625. }
  626. }
  627. mapit->free(iter);
  628. }
  629. void do_final_instance(void) {
  630. int i;
  631. for(i = 0; i < instance->instances; i++) {
  632. instance->destroy(i);
  633. }
  634. if( instance->list )
  635. aFree(instance->list);
  636. instance->list = NULL;
  637. instance->instances = 0;
  638. }
  639. void do_init_instance(bool minimal) {
  640. if (minimal)
  641. return;
  642. timer->add_func_list(instance->destroy_timer, "instance_destroy_timer");
  643. }
  644. void instance_defaults(void) {
  645. instance = &instance_s;
  646. instance->init = do_init_instance;
  647. instance->final = do_final_instance;
  648. instance->reload = do_reload_instance;
  649. /* start point */
  650. instance->start_id = 0;
  651. /* count */
  652. instance->instances = 0;
  653. /* */
  654. instance->list = NULL;
  655. /* */
  656. instance->create = instance_create;
  657. instance->add_map = instance_add_map;
  658. instance->del_map = instance_del_map;
  659. instance->map2imap = instance_map2imap;
  660. instance->mapid2imapid = instance_mapid2imapid;
  661. instance->mapname2imap = instance_mapname2imap;
  662. instance->map_npcsub = instance_map_npcsub;
  663. instance->init_npc = instance_init_npc;
  664. instance->destroy = instance_destroy;
  665. instance->start = instance_init;
  666. instance->check_idle = instance_check_idle;
  667. instance->check_kick = instance_check_kick;
  668. instance->set_timeout = instance_set_timeout;
  669. instance->valid = instance_is_valid;
  670. instance->destroy_timer = instance_destroy_timer;
  671. }