PageRenderTime 91ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/src/map/mob.c

https://gitlab.com/evol/evol-server-code-old
C | 5316 lines | 4209 code | 620 blank | 487 comment | 1598 complexity | fe609cbf4779ab22df05854d298ea26e MD5 | raw file
Possible License(s): GPL-2.0
  1. // $Id: mob.c,v 1.7 2004/09/25 05:32:18 MouseJstr Exp $
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <stdarg.h>
  6. #include <string.h>
  7. #include "timer.h"
  8. #include "socket.h"
  9. #include "db.h"
  10. #include "nullpo.h"
  11. #include "malloc.h"
  12. #include "map.h"
  13. #include "clif.h"
  14. #include "intif.h"
  15. #include "pc.h"
  16. #include "mob.h"
  17. #include "guild.h"
  18. #include "itemdb.h"
  19. #include "skill.h"
  20. #include "battle.h"
  21. #include "party.h"
  22. #include "npc.h"
  23. #include "tmw.h"
  24. #ifdef MEMWATCH
  25. #include "memwatch.h"
  26. #endif
  27. #ifndef max
  28. #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
  29. #endif
  30. #define MIN_MOBTHINKTIME 100
  31. #define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute)
  32. #define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute)
  33. struct mob_db mob_db[2001];
  34. /*==========================================
  35. * Local prototype declaration (only required thing)
  36. *------------------------------------------
  37. */
  38. static int distance (int, int, int, int);
  39. static int mob_makedummymobdb (int);
  40. static int mob_timer (int, unsigned int, int, int);
  41. //int mobskill_use (struct mob_data *md, unsigned int tick, int event);
  42. int mobskill_deltimer (struct mob_data *md);
  43. int mob_skillid2skillidx (int class, int skillid);
  44. int mobskill_use_id (struct mob_data *md, struct block_list *target,
  45. int skill_idx);
  46. static int mob_unlocktarget (struct mob_data *md, int tick);
  47. /*==========================================
  48. * Mob is searched with a name.
  49. *------------------------------------------
  50. */
  51. int mobdb_searchname (const char *str)
  52. {
  53. if (!str)
  54. return 0;
  55. int i;
  56. for (i = 0; i < sizeof (mob_db) / sizeof (mob_db[0]); i++)
  57. {
  58. if (strcmpi (mob_db[i].name, str) == 0
  59. || strcmp (mob_db[i].jname, str) == 0
  60. || memcmp (mob_db[i].name, str, 24) == 0
  61. || memcmp (mob_db[i].jname, str, 24) == 0)
  62. return i;
  63. }
  64. return 0;
  65. }
  66. /*==========================================
  67. * Id Mob is checked.
  68. *------------------------------------------
  69. */
  70. int mobdb_checkid (const int id)
  71. {
  72. if (id <= 0 || id >= (sizeof (mob_db) / sizeof (mob_db[0]))
  73. || mob_db[id].name[0] == '\0')
  74. return 0;
  75. return id;
  76. }
  77. static void mob_init (struct mob_data *md);
  78. /*==========================================
  79. * The minimum data set for MOB spawning
  80. *------------------------------------------
  81. */
  82. int mob_spawn_dataset (struct mob_data *md, const char *mobname, int class)
  83. {
  84. nullpo_retr (0, md);
  85. nullpo_retr (0, mobname);
  86. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  87. return 0;
  88. if (strcmp (mobname, "--en--") == 0)
  89. memcpy (md->name, mob_db[class].name, 24);
  90. else if (strcmp (mobname, "--ja--") == 0)
  91. memcpy (md->name, mob_db[class].jname, 24);
  92. else
  93. memcpy (md->name, mobname, 24);
  94. md->bl.prev = NULL;
  95. md->bl.next = NULL;
  96. md->n = 0;
  97. md->base_class = md->class = class;
  98. md->bl.id = npc_get_new_npc_id ();
  99. memset (&md->state, 0, sizeof (md->state));
  100. md->timer = -1;
  101. md->target_id = 0;
  102. md->attacked_id = 0;
  103. mob_init (md);
  104. return 0;
  105. }
  106. // Mutation values indicate how `valuable' a change to each stat is, XP wise.
  107. // For one 256th of change, we give out that many 1024th fractions of XP change
  108. // (i.e., 1024 means a 100% XP increase for a single point of adjustment, 4 means 100% XP bonus for doubling the value)
  109. static int mutation_value[MOB_XP_BONUS] = {
  110. 2, // MOB_LV
  111. 3, // MOB_MAX_HP
  112. 1, // MOB_STR
  113. 2, // MOB_AGI
  114. 1, // MOB_VIT
  115. 0, // MOB_INT
  116. 2, // MOB_DEX
  117. 2, // MOB_LUK
  118. 1, // MOB_ATK1
  119. 1, // MOB_ATK2
  120. 2, // MOB_ADELAY
  121. 2, // MOB_DEF
  122. 2, // MOB_MDEF
  123. 2, // MOB_SPEED
  124. };
  125. // The mutation scale indicates how far `up' we can go, with 256 indicating 100% Note that this may stack with multiple
  126. // calls to `mutate'.
  127. static int mutation_scale[MOB_XP_BONUS] = {
  128. 16, // MOB_LV
  129. 256, // MOB_MAX_HP
  130. 32, // MOB_STR
  131. 48, // MOB_AGI
  132. 48, // MOB_VIT
  133. 48, // MOB_INT
  134. 48, // MOB_DEX
  135. 64, // MOB_LUK
  136. 48, // MOB_ATK1
  137. 48, // MOB_ATK2
  138. 80, // MOB_ADELAY
  139. 48, // MOB_DEF
  140. 48, // MOB_MDEF
  141. 80, // MOB_SPEED
  142. };
  143. // The table below indicates the `average' value for each of the statistics, or -1 if there is none.
  144. // This average is used to determine XP modifications for mutations. The experience point bonus is
  145. // based on mutation_value and mutation_base as follows:
  146. // (1) first, compute the percentage change of the attribute (p0)
  147. // (2) second, determine the absolute stat change
  148. // (3) third, compute the percentage stat change relative to mutation_base (p1)
  149. // (4) fourth, compute the XP mofication based on the smaller of (p0, p1).
  150. static int mutation_base[MOB_XP_BONUS] = {
  151. 30, // MOB_LV
  152. -1, // MOB_MAX_HP
  153. 20, // MOB_STR
  154. 20, // MOB_AGI
  155. 20, // MOB_VIT
  156. 20, // MOB_INT
  157. 20, // MOB_DEX
  158. 20, // MOB_LUK
  159. -1, // MOB_ATK1
  160. -1, // MOB_ATK2
  161. -1, // MOB_ADELAY
  162. -1, // MOB_DEF
  163. 20, // MOB_MDEF
  164. -1, // MOB_SPEED
  165. };
  166. /*========================================
  167. * Mutates a MOB. For large `direction' values, calling this multiple times will give bigger XP boni.
  168. *----------------------------------------
  169. */
  170. static void mob_mutate (struct mob_data *md, int stat, int intensity) // intensity: positive: strengthen, negative: weaken. 256 = 100%.
  171. {
  172. if (!md || stat < 0 || stat >= MOB_XP_BONUS || intensity == 0)
  173. return;
  174. int old_stat;
  175. int new_stat;
  176. int real_intensity; // relative intensity
  177. const int mut_base = mutation_base[stat];
  178. int sign = 1;
  179. while (intensity > mutation_scale[stat])
  180. {
  181. mob_mutate (md, stat, mutation_scale[stat]); // give better XP assignments
  182. intensity -= mutation_scale[stat];
  183. }
  184. while (intensity < -mutation_scale[stat])
  185. {
  186. mob_mutate (md, stat, mutation_scale[stat]); // give better XP assignments
  187. intensity += mutation_scale[stat];
  188. }
  189. if (!intensity)
  190. return;
  191. // MOB_ADELAY and MOB_SPEED are special because going DOWN is good here.
  192. if (stat == MOB_ADELAY || stat == MOB_SPEED)
  193. sign = -1;
  194. // Now compute the new stat
  195. old_stat = md->stats[stat];
  196. new_stat = old_stat + ((old_stat * sign * intensity) / 256);
  197. if (new_stat < 0)
  198. new_stat = 0;
  199. if (old_stat == 0)
  200. real_intensity = 0;
  201. else
  202. real_intensity = (((new_stat - old_stat) << 8) / old_stat);
  203. if (mut_base != -1)
  204. {
  205. // Now compute the mutation intensity relative to an absolute value.
  206. // Take the lesser of the two effects.
  207. int real_intensity2 = (((new_stat - old_stat) << 8) / mut_base);
  208. if (real_intensity < 0)
  209. if (real_intensity2 > real_intensity)
  210. real_intensity = real_intensity2;
  211. if (real_intensity > 0)
  212. if (real_intensity2 < real_intensity)
  213. real_intensity = real_intensity2;
  214. }
  215. real_intensity *= sign;
  216. md->stats[stat] = new_stat;
  217. // Adjust XP value
  218. md->stats[MOB_XP_BONUS] += mutation_value[stat] * real_intensity;
  219. if (md->stats[MOB_XP_BONUS] <= 0)
  220. md->stats[MOB_XP_BONUS] = 1;
  221. // Sanitise
  222. if (md->stats[MOB_ATK1] > md->stats[MOB_ATK2])
  223. {
  224. int swap = md->stats[MOB_ATK2];
  225. md->stats[MOB_ATK2] = md->stats[MOB_ATK1];
  226. md->stats[MOB_ATK1] = swap;
  227. }
  228. }
  229. // This calculates the exp of a given mob
  230. int mob_gen_exp (struct mob_db *mob)
  231. {
  232. if (!mob)
  233. return 1;
  234. if (mob->max_hp <= 1)
  235. return 1;
  236. double mod_def = 100 - mob->def;
  237. if (mod_def == 0)
  238. mod_def = 1;
  239. double effective_hp =
  240. ((50 - mob->luk) * mob->max_hp / 50.0) +
  241. (2 * mob->luk * mob->max_hp / mod_def);
  242. double attack_factor =
  243. (mob->atk1 + mob->atk2 + mob->str / 3.0 + mob->dex / 2.0 +
  244. mob->luk) * (1872.0 / mob->adelay) / 4;
  245. double dodge_factor =
  246. pow (mob->lv + mob->agi + mob->luk / 2.0, 4.0 / 3.0);
  247. double persuit_factor =
  248. (3 + mob->range) * (mob->mode % 2) * 1000 / mob->speed;
  249. double aggression_factor = (mob->mode & 4) == 4 ? 10.0 / 9.0 : 1.0;
  250. int xp =
  251. (int) floor (effective_hp *
  252. pow (sqrt (attack_factor) + sqrt (dodge_factor) +
  253. sqrt (persuit_factor) + 55,
  254. 3) * aggression_factor / 2000000.0 *
  255. (double) battle_config.base_exp_rate / 100.);
  256. if (xp < 1)
  257. xp = 1;
  258. printf ("Exp for mob '%s' generated: %d\n", mob->name, xp);
  259. return xp;
  260. }
  261. static void mob_init (struct mob_data *md)
  262. {
  263. if (!md)
  264. return;
  265. int i;
  266. const int class = md->class;
  267. const int mutations_nr = mob_db[class].mutations_nr;
  268. const int mutation_power = mob_db[class].mutation_power;
  269. md->stats[MOB_LV] = mob_db[class].lv;
  270. md->stats[MOB_MAX_HP] = mob_db[class].max_hp;
  271. md->stats[MOB_STR] = mob_db[class].str;
  272. md->stats[MOB_AGI] = mob_db[class].agi;
  273. md->stats[MOB_VIT] = mob_db[class].vit;
  274. md->stats[MOB_INT] = mob_db[class].int_;
  275. md->stats[MOB_DEX] = mob_db[class].dex;
  276. md->stats[MOB_LUK] = mob_db[class].luk;
  277. md->stats[MOB_ATK1] = mob_db[class].atk1;
  278. md->stats[MOB_ATK2] = mob_db[class].atk2;
  279. md->stats[MOB_ADELAY] = mob_db[class].adelay;
  280. md->stats[MOB_DEF] = mob_db[class].def;
  281. md->stats[MOB_MDEF] = mob_db[class].mdef;
  282. md->stats[MOB_SPEED] = mob_db[class].speed;
  283. md->stats[MOB_XP_BONUS] = MOB_XP_BONUS_BASE;
  284. if (!(mutation_power >> 1))
  285. return;
  286. for (i = 0; i < mutations_nr; i++)
  287. {
  288. int stat_nr = MRAND (MOB_XP_BONUS + 1);
  289. int strength;
  290. if (stat_nr >= MOB_XP_BONUS)
  291. stat_nr = MOB_MAX_HP;
  292. strength =
  293. ((MRAND ((mutation_power >> 1)) +
  294. (MRAND ((mutation_power >> 1))) +
  295. 2) * mutation_scale[stat_nr]) / 100;
  296. strength = MRAND (2) ? strength : -strength;
  297. if (strength < -240)
  298. strength = -240; /* Don't go too close to zero */
  299. mob_mutate (md, stat_nr, strength);
  300. }
  301. }
  302. /*==========================================
  303. * The MOB appearance for one time (for scripts)
  304. *------------------------------------------
  305. */
  306. int mob_once_spawn (struct map_session_data *sd, char *mapname,
  307. int x, int y, const char *mobname, int class, int amount,
  308. const char *event)
  309. {
  310. if (!mapname)
  311. return 0;
  312. struct mob_data *md = NULL;
  313. int m, count, lv = 255, r = class;
  314. if (sd)
  315. lv = sd->status.base_level;
  316. if (sd && strcmp (mapname, "this") == 0)
  317. m = sd->bl.m;
  318. else
  319. m = map_mapname2mapid (mapname);
  320. if (m < 0 || amount <= 0 || (class >= 0 && class <= 1000) || class > 2000) // 値が異常なら召喚を止める
  321. return 0;
  322. if (class < 0)
  323. { // ランダムに召喚
  324. int j = -class - 1;
  325. if (j >= 0 && j < MAX_RANDOMMONSTER)
  326. {
  327. int i = 0;
  328. int k;
  329. do
  330. {
  331. class = MPRAND (1001, 1000);
  332. k = MRAND (1000000);
  333. }
  334. while ((mob_db[class].max_hp <= 0
  335. || mob_db[class].summonper[j] <= k
  336. || (lv < mob_db[class].lv
  337. && battle_config.random_monster_checklv == 1))
  338. && (i++) < 2000);
  339. if (i >= 2000)
  340. {
  341. class = mob_db[0].summonper[j];
  342. }
  343. }
  344. else
  345. {
  346. return 0;
  347. }
  348. // if(battle_config.etc_log==1)
  349. // printf("mobclass=%d try=%d\n",class,i);
  350. }
  351. if (sd)
  352. {
  353. if (x <= 0)
  354. x = sd->bl.x;
  355. if (y <= 0)
  356. y = sd->bl.y;
  357. }
  358. else if (x <= 0 || y <= 0)
  359. {
  360. printf ("mob_once_spawn: ??\n");
  361. }
  362. for (count = 0; count < amount; count++)
  363. {
  364. md = (struct mob_data *) aCalloc (1, sizeof (struct mob_data));
  365. memset (md, '\0', sizeof *md);
  366. if (mob_db[class].mode & 0x02)
  367. md->lootitem =
  368. (struct item *) aCalloc (LOOTITEM_SIZE, sizeof (struct item));
  369. else
  370. md->lootitem = NULL;
  371. mob_spawn_dataset (md, mobname, class);
  372. md->bl.m = m;
  373. md->bl.x = x;
  374. md->bl.y = y;
  375. if (r < 0 && battle_config.dead_branch_active == 1)
  376. md->mode = 0x1 + 0x4 + 0x80; //移動してアクティブで反撃する
  377. md->m = m;
  378. md->x0 = x;
  379. md->y0 = y;
  380. md->xs = 0;
  381. md->ys = 0;
  382. md->spawndelay1 = -1; // Only once is a flag.
  383. md->spawndelay2 = -1; // Only once is a flag.
  384. memcpy (md->npc_event, event, sizeof (md->npc_event));
  385. md->bl.type = BL_MOB;
  386. map_addiddb (&md->bl);
  387. mob_spawn (md->bl.id);
  388. if (class == 1288)
  389. { // emperium hp based on defense level [Valaris]
  390. struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
  391. if (gc)
  392. {
  393. mob_db[class].max_hp += 2000 * gc->defense;
  394. md->hp = mob_db[class].max_hp;
  395. }
  396. } // end addition [Valaris]
  397. }
  398. return (amount > 0) ? md->bl.id : 0;
  399. }
  400. /*==========================================
  401. * The MOB appearance for one time (& area specification for scripts)
  402. *------------------------------------------
  403. */
  404. int mob_once_spawn_area (struct map_session_data *sd, char *mapname,
  405. int x0, int y0, int x1, int y1,
  406. const char *mobname, int class, int amount,
  407. const char *event)
  408. {
  409. if (!mapname)
  410. return 0;
  411. int x, y, i, c, max, lx = -1, ly = -1, id = 0;
  412. int m;
  413. if (strcmp (mapname, "this") == 0)
  414. {
  415. if (!sd)
  416. return 0;
  417. m = sd->bl.m;
  418. }
  419. else
  420. m = map_mapname2mapid (mapname);
  421. max = (y1 - y0 + 1) * (x1 - x0 + 1) * 3;
  422. if (max > 1000)
  423. max = 1000;
  424. if (m < 0 || amount <= 0 || (class >= 0 && class <= 1000) || class > 2000) // A summon is stopped if a value is unusual
  425. return 0;
  426. for (i = 0; i < amount; i++)
  427. {
  428. int j = 0;
  429. do
  430. {
  431. x = MPRAND (x0, (x1 - x0 + 1));
  432. y = MPRAND (y0, (y1 - y0 + 1));
  433. }
  434. while (((c = map_getcell (m, x, y)) == 1 || c == 5) && (++j) < max);
  435. if (j >= max)
  436. {
  437. if (lx >= 0)
  438. { // Since reference went wrong, the place which boiled before is used.
  439. x = lx;
  440. y = ly;
  441. }
  442. else
  443. return 0; // Since reference of the place which boils first went wrong, it stops.
  444. }
  445. id = mob_once_spawn (sd, mapname, x, y, mobname, class, 1, event);
  446. lx = x;
  447. ly = y;
  448. }
  449. return id;
  450. }
  451. /*==========================================
  452. * Summoning Guardians [Valaris]
  453. *------------------------------------------
  454. */
  455. int mob_spawn_guardian (struct map_session_data *sd, char *mapname,
  456. int x, int y, const char *mobname, int class,
  457. int amount, const char *event, int guardian)
  458. {
  459. if (!mapname)
  460. return 0;
  461. struct mob_data *md = NULL;
  462. int m, count = 1;
  463. if (sd && strcmp (mapname, "this") == 0)
  464. m = sd->bl.m;
  465. else
  466. m = map_mapname2mapid (mapname);
  467. if (m < 0 || amount <= 0 || (class >= 0 && class <= 1000) || class > 2000) // 値が異常なら召喚を止める
  468. return 0;
  469. if (class < 0)
  470. return 0;
  471. if (sd)
  472. {
  473. if (x <= 0)
  474. x = sd->bl.x;
  475. if (y <= 0)
  476. y = sd->bl.y;
  477. }
  478. else if (x <= 0 || y <= 0)
  479. printf ("mob_spawn_guardian: ??\n");
  480. for (count = 0; count < amount; count++)
  481. {
  482. struct guild_castle *gc;
  483. md = calloc (sizeof (struct mob_data), 1);
  484. if (md == NULL)
  485. {
  486. printf ("mob_spawn_guardian: out of memory !\n");
  487. exit (1);
  488. }
  489. memset (md, '\0', sizeof *md);
  490. mob_spawn_dataset (md, mobname, class);
  491. md->bl.m = m;
  492. md->bl.x = x;
  493. md->bl.y = y;
  494. md->m = m;
  495. md->x0 = x;
  496. md->y0 = y;
  497. md->xs = 0;
  498. md->ys = 0;
  499. md->spawndelay1 = -1; // Only once is a flag.
  500. md->spawndelay2 = -1; // Only once is a flag.
  501. memcpy (md->npc_event, event, sizeof (md->npc_event));
  502. md->bl.type = BL_MOB;
  503. map_addiddb (&md->bl);
  504. mob_spawn (md->bl.id);
  505. gc = guild_mapname2gc (map[md->bl.m].name);
  506. if (gc)
  507. {
  508. mob_db[class].max_hp += 2000 * gc->defense;
  509. if (guardian == 0)
  510. {
  511. md->hp = gc->Ghp0;
  512. gc->GID0 = md->bl.id;
  513. }
  514. if (guardian == 1)
  515. {
  516. md->hp = gc->Ghp1;
  517. gc->GID1 = md->bl.id;
  518. }
  519. if (guardian == 2)
  520. {
  521. md->hp = gc->Ghp2;
  522. gc->GID2 = md->bl.id;
  523. }
  524. if (guardian == 3)
  525. {
  526. md->hp = gc->Ghp3;
  527. gc->GID3 = md->bl.id;
  528. }
  529. if (guardian == 4)
  530. {
  531. md->hp = gc->Ghp4;
  532. gc->GID4 = md->bl.id;
  533. }
  534. if (guardian == 5)
  535. {
  536. md->hp = gc->Ghp5;
  537. gc->GID5 = md->bl.id;
  538. }
  539. if (guardian == 6)
  540. {
  541. md->hp = gc->Ghp6;
  542. gc->GID6 = md->bl.id;
  543. }
  544. if (guardian == 7)
  545. {
  546. md->hp = gc->Ghp7;
  547. gc->GID7 = md->bl.id;
  548. }
  549. }
  550. }
  551. return (amount > 0) ? md->bl.id : 0;
  552. }
  553. /*==========================================
  554. * Appearance income of mob
  555. *------------------------------------------
  556. */
  557. int mob_get_viewclass (int class)
  558. {
  559. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  560. return 0;
  561. return mob_db[class].view_class;
  562. }
  563. int mob_get_sex (int class)
  564. {
  565. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  566. return 0;
  567. return mob_db[class].sex;
  568. }
  569. short mob_get_hair (int class)
  570. {
  571. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  572. return 0;
  573. return mob_db[class].hair;
  574. }
  575. short mob_get_hair_color (int class)
  576. {
  577. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  578. return 0;
  579. return mob_db[class].hair_color;
  580. }
  581. short mob_get_weapon (int class)
  582. {
  583. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  584. return 0;
  585. return mob_db[class].weapon;
  586. }
  587. short mob_get_shield (int class)
  588. {
  589. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  590. return 0;
  591. return mob_db[class].shield;
  592. }
  593. short mob_get_head_top (int class)
  594. {
  595. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  596. return 0;
  597. return mob_db[class].head_top;
  598. }
  599. short mob_get_head_mid (int class)
  600. {
  601. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  602. return 0;
  603. return mob_db[class].head_mid;
  604. }
  605. short mob_get_head_buttom (int class)
  606. {
  607. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  608. return 0;
  609. return mob_db[class].head_buttom;
  610. }
  611. short mob_get_clothes_color (int class) // Add for player monster dye - Valaris
  612. {
  613. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  614. return 0;
  615. return mob_db[class].clothes_color; // End
  616. }
  617. int mob_get_equip (int class) // mob equip [Valaris]
  618. {
  619. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  620. return 0;
  621. return mob_db[class].equip;
  622. }
  623. /*==========================================
  624. * Is MOB in the state in which the present movement is possible or not?
  625. *------------------------------------------
  626. */
  627. int mob_can_move (struct mob_data *md)
  628. {
  629. nullpo_retr (0, md);
  630. if (md->canmove_tick > gettick () || (md->opt1 > 0 && md->opt1 != 6)
  631. || md->option & 2)
  632. return 0;
  633. // アンクル中で動けないとか
  634. if (md->sc_data[SC_ANKLE].timer != -1 || //アンクルスネア
  635. md->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
  636. md->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
  637. md->sc_data[SC_SPIDERWEB].timer != -1 //スパイダーウェッブ
  638. )
  639. return 0;
  640. return 1;
  641. }
  642. /*==========================================
  643. * Time calculation concerning one step next to mob
  644. *------------------------------------------
  645. */
  646. static int calc_next_walk_step (struct mob_data *md)
  647. {
  648. nullpo_retr (0, md);
  649. if (md->walkpath.path_pos >= md->walkpath.path_len)
  650. return -1;
  651. if (md->walkpath.path[md->walkpath.path_pos] & 1)
  652. return battle_get_speed (&md->bl) * 14 / 10;
  653. return battle_get_speed (&md->bl);
  654. }
  655. static int mob_walktoxy_sub (struct mob_data *md);
  656. /*==========================================
  657. * Mob Walk processing
  658. *------------------------------------------
  659. */
  660. static int mob_walk (struct mob_data *md, unsigned int tick, int data)
  661. {
  662. int i;
  663. static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
  664. static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
  665. nullpo_retr (0, md);
  666. md->state.state = MS_IDLE;
  667. if (md->walkpath.path_pos >= md->walkpath.path_len
  668. || md->walkpath.path_pos != data)
  669. return 0;
  670. md->walkpath.path_half ^= 1;
  671. if (md->walkpath.path_half == 0)
  672. {
  673. md->walkpath.path_pos++;
  674. if (md->state.change_walk_target)
  675. {
  676. mob_walktoxy_sub (md);
  677. return 0;
  678. }
  679. }
  680. else
  681. {
  682. int moveblock;
  683. int ctype;
  684. int x, y, dx, dy;
  685. if (md->walkpath.path[md->walkpath.path_pos] >= 8)
  686. return 1;
  687. x = md->bl.x;
  688. y = md->bl.y;
  689. ctype = map_getcell (md->bl.m, x, y);
  690. if (ctype == 1 || ctype == 5)
  691. {
  692. mob_stop_walking (md, 1);
  693. return 0;
  694. }
  695. md->dir = md->walkpath.path[md->walkpath.path_pos];
  696. dx = dirx[md->dir];
  697. dy = diry[md->dir];
  698. ctype = map_getcell (md->bl.m, x + dx, y + dy);
  699. if (ctype == 1 || ctype == 5)
  700. {
  701. mob_walktoxy_sub (md);
  702. return 0;
  703. }
  704. moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
  705. || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
  706. md->state.state = MS_WALK;
  707. map_foreachinmovearea (clif_moboutsight, md->bl.m, x - AREA_SIZE,
  708. y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
  709. dx, dy, BL_PC, md);
  710. x += dx;
  711. y += dy;
  712. if (md->min_chase > 13)
  713. md->min_chase--;
  714. if (moveblock)
  715. map_delblock (&md->bl);
  716. md->bl.x = x;
  717. md->bl.y = y;
  718. if (moveblock)
  719. map_addblock (&md->bl);
  720. map_foreachinmovearea (clif_mobinsight, md->bl.m, x - AREA_SIZE,
  721. y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
  722. -dx, -dy, BL_PC, md);
  723. md->state.state = MS_IDLE;
  724. if (md->option & 4)
  725. skill_check_cloaking (&md->bl);
  726. skill_unit_move (&md->bl, tick, 1); // Inspection of a skill unit
  727. }
  728. if ((i = calc_next_walk_step (md)) > 0)
  729. {
  730. i = i >> 1;
  731. if (i < 1 && md->walkpath.path_half == 0)
  732. i = 1;
  733. md->timer =
  734. add_timer (tick + i, mob_timer, md->bl.id, md->walkpath.path_pos);
  735. md->state.state = MS_WALK;
  736. if (md->walkpath.path_pos >= md->walkpath.path_len)
  737. clif_fixmobpos (md); // When mob stops, retransmission current of a position.
  738. }
  739. return 0;
  740. }
  741. /*==========================================
  742. * Check if mob should be attempting to attack
  743. *------------------------------------------
  744. */
  745. static int mob_check_attack (struct mob_data *md)
  746. {
  747. struct block_list *tbl = NULL;
  748. struct map_session_data *tsd = NULL;
  749. struct mob_data *tmd = NULL;
  750. int mode, race, range;
  751. nullpo_retr (0, md);
  752. md->min_chase = 13;
  753. md->state.state = MS_IDLE;
  754. md->state.skillstate = MSS_IDLE;
  755. if (md->skilltimer != -1)
  756. return 0;
  757. if (md->opt1 > 0 || md->option & 2)
  758. return 0;
  759. if (md->sc_data[SC_AUTOCOUNTER].timer != -1)
  760. return 0;
  761. if (md->sc_data[SC_BLADESTOP].timer != -1)
  762. return 0;
  763. if ((tbl = map_id2bl (md->target_id)) == NULL)
  764. {
  765. md->target_id = 0;
  766. md->state.targettype = NONE_ATTACKABLE;
  767. return 0;
  768. }
  769. if (tbl->type == BL_PC)
  770. tsd = (struct map_session_data *) tbl;
  771. else if (tbl->type == BL_MOB)
  772. tmd = (struct mob_data *) tbl;
  773. else
  774. return 0;
  775. if (tsd)
  776. {
  777. if (pc_isdead (tsd) || tsd->invincible_timer != -1
  778. || pc_isinvisible (tsd) || md->bl.m != tbl->m || tbl->prev == NULL
  779. || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
  780. {
  781. md->target_id = 0;
  782. md->state.targettype = NONE_ATTACKABLE;
  783. return 0;
  784. }
  785. }
  786. if (tmd)
  787. {
  788. if (md->bl.m != tbl->m || tbl->prev == NULL
  789. || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
  790. {
  791. md->target_id = 0;
  792. md->state.targettype = NONE_ATTACKABLE;
  793. return 0;
  794. }
  795. }
  796. if (!md->mode)
  797. mode = mob_db[md->class].mode;
  798. else
  799. mode = md->mode;
  800. race = mob_db[md->class].race;
  801. if (!(mode & 0x80) && !(mode & 0x10000))
  802. {
  803. md->target_id = 0;
  804. md->state.targettype = NONE_ATTACKABLE;
  805. return 0;
  806. }
  807. if (tsd && !(mode & 0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 ||
  808. ((pc_ishiding (tsd)
  809. || tsd->state.gangsterparadise)
  810. && race != 4 && race != 6)))
  811. {
  812. md->target_id = 0;
  813. md->state.targettype = NONE_ATTACKABLE;
  814. return 0;
  815. }
  816. range = mob_db[md->class].range;
  817. if (mode & 1)
  818. range++;
  819. if (distance (md->bl.x, md->bl.y, tbl->x, tbl->y) > range)
  820. return 0;
  821. return 1;
  822. }
  823. /*==========================================
  824. * Attack processing of mob
  825. *------------------------------------------
  826. */
  827. static int mob_attack (struct mob_data *md, unsigned int tick,
  828. int data __attribute__ ((unused)))
  829. {
  830. struct block_list *tbl = NULL;
  831. int mode;
  832. nullpo_retr (0, md);
  833. if (!mob_check_attack (md))
  834. return 0;
  835. if ((tbl = map_id2bl (md->target_id)) == NULL)
  836. return 0;
  837. if (battle_config.monster_attack_direction_change)
  838. md->dir = map_calc_dir (&md->bl, tbl->x, tbl->y); // 向き設定
  839. //clif_fixmobpos(md);
  840. md->state.skillstate = MSS_ATTACK;
  841. if (mobskill_use (md, tick, -2)) // スキル使用
  842. return 0;
  843. if (!md->mode)
  844. mode = mob_db[md->class].mode;
  845. else
  846. mode = md->mode;
  847. if (mode & 0x80)
  848. md->target_lv = battle_weapon_attack (&md->bl, tbl, tick, 0);
  849. else
  850. md->target_lv = 0;
  851. if (!(battle_config.monster_cloak_check_type & 2)
  852. && md->sc_data[SC_CLOAKING].timer != -1)
  853. skill_status_change_end (&md->bl, SC_CLOAKING, -1);
  854. md->attackabletime = tick + battle_get_adelay (&md->bl);
  855. md->timer = add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
  856. md->state.state = MS_ATTACK;
  857. return 0;
  858. }
  859. /*==========================================
  860. * The attack of PC which is attacking id is stopped.
  861. * The callback function of clif_foreachclient
  862. *------------------------------------------
  863. */
  864. int mob_stopattacked (struct map_session_data *sd, va_list ap)
  865. {
  866. int id;
  867. nullpo_retr (0, sd);
  868. nullpo_retr (0, ap);
  869. id = va_arg (ap, int);
  870. if (sd->attacktarget == id)
  871. pc_stopattack (sd);
  872. return 0;
  873. }
  874. /*==========================================
  875. * The timer in which the mob's states changes
  876. *------------------------------------------
  877. */
  878. int mob_changestate (struct mob_data *md, int state, int type)
  879. {
  880. unsigned int tick;
  881. int i;
  882. nullpo_retr (0, md);
  883. if (md->timer != -1)
  884. delete_timer (md->timer, mob_timer);
  885. md->timer = -1;
  886. md->state.state = state;
  887. switch (state)
  888. {
  889. case MS_WALK:
  890. if ((i = calc_next_walk_step (md)) > 0)
  891. {
  892. i = i >> 2;
  893. md->timer =
  894. add_timer (gettick () + i, mob_timer, md->bl.id, 0);
  895. }
  896. else
  897. md->state.state = MS_IDLE;
  898. break;
  899. case MS_ATTACK:
  900. tick = gettick ();
  901. i = DIFF_TICK (md->attackabletime, tick);
  902. if (i > 0 && i < 2000)
  903. md->timer =
  904. add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
  905. else if (type)
  906. {
  907. md->attackabletime = tick + battle_get_amotion (&md->bl);
  908. md->timer =
  909. add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
  910. }
  911. else
  912. {
  913. md->attackabletime = tick + 1;
  914. md->timer =
  915. add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
  916. }
  917. break;
  918. case MS_DELAY:
  919. md->timer =
  920. add_timer (gettick () + type, mob_timer, md->bl.id, 0);
  921. break;
  922. case MS_DEAD:
  923. skill_castcancel (&md->bl, 0);
  924. // mobskill_deltimer(md);
  925. md->state.skillstate = MSS_DEAD;
  926. md->last_deadtime = gettick ();
  927. // Since it died, all aggressors' attack to this mob is stopped.
  928. clif_foreachclient (mob_stopattacked, md->bl.id);
  929. skill_unit_out_all (&md->bl, gettick (), 1);
  930. skill_status_change_clear (&md->bl, 2); // The abnormalities in status are canceled.
  931. skill_clear_unitgroup (&md->bl); // All skill unit groups are deleted.
  932. skill_cleartimerskill (&md->bl);
  933. if (md->deletetimer != -1)
  934. delete_timer (md->deletetimer, mob_timer_delete);
  935. md->deletetimer = -1;
  936. md->hp = md->target_id = md->attacked_id = 0;
  937. md->state.targettype = NONE_ATTACKABLE;
  938. break;
  939. default:
  940. break;
  941. }
  942. return 0;
  943. }
  944. /*==========================================
  945. * timer processing of mob (timer function)
  946. * It branches to a walk and an attack.
  947. *------------------------------------------
  948. */
  949. static int mob_timer (int tid, unsigned int tick, int id, int data)
  950. {
  951. struct mob_data *md;
  952. struct block_list *bl;
  953. if ((bl = map_id2bl (id)) == NULL)
  954. { //攻撃してきた敵がもういないのは正常のようだ
  955. return 1;
  956. }
  957. if (!bl || !bl->type || bl->type != BL_MOB)
  958. return 1;
  959. nullpo_retr (1, md = (struct mob_data *) bl);
  960. if (!md->bl.type || md->bl.type != BL_MOB)
  961. return 1;
  962. if (md->timer != tid)
  963. {
  964. if (battle_config.error_log == 1)
  965. printf ("mob_timer %d != %d\n", md->timer, tid);
  966. return 0;
  967. }
  968. md->timer = -1;
  969. if (md->bl.prev == NULL || md->state.state == MS_DEAD)
  970. return 1;
  971. map_freeblock_lock ();
  972. switch (md->state.state)
  973. {
  974. case MS_WALK:
  975. mob_check_attack (md);
  976. mob_walk (md, tick, data);
  977. break;
  978. case MS_ATTACK:
  979. mob_attack (md, tick, data);
  980. break;
  981. case MS_DELAY:
  982. mob_changestate (md, MS_IDLE, 0);
  983. break;
  984. default:
  985. if (battle_config.error_log == 1)
  986. printf ("mob_timer : %d ?\n", md->state.state);
  987. break;
  988. }
  989. map_freeblock_unlock ();
  990. return 0;
  991. }
  992. /*==========================================
  993. *
  994. *------------------------------------------
  995. */
  996. static int mob_walktoxy_sub (struct mob_data *md)
  997. {
  998. struct walkpath_data wpd;
  999. nullpo_retr (0, md);
  1000. if (path_search
  1001. (&wpd, md->bl.m, md->bl.x, md->bl.y, md->to_x, md->to_y,
  1002. md->state.walk_easy))
  1003. return 1;
  1004. memcpy (&md->walkpath, &wpd, sizeof (wpd));
  1005. md->state.change_walk_target = 0;
  1006. mob_changestate (md, MS_WALK, 0);
  1007. clif_movemob (md);
  1008. return 0;
  1009. }
  1010. /*==========================================
  1011. * mob move start
  1012. *------------------------------------------
  1013. */
  1014. int mob_walktoxy (struct mob_data *md, int x, int y, int easy)
  1015. {
  1016. struct walkpath_data wpd;
  1017. nullpo_retr (0, md);
  1018. if (md->state.state == MS_WALK
  1019. && path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, x, y, easy))
  1020. return 1;
  1021. md->state.walk_easy = easy;
  1022. md->to_x = x;
  1023. md->to_y = y;
  1024. if (md->state.state == MS_WALK)
  1025. {
  1026. md->state.change_walk_target = 1;
  1027. }
  1028. else
  1029. {
  1030. return mob_walktoxy_sub (md);
  1031. }
  1032. return 0;
  1033. }
  1034. /*==========================================
  1035. * mob spawn with delay (timer function)
  1036. *------------------------------------------
  1037. */
  1038. static int mob_delayspawn (int tid __attribute__ ((unused)),
  1039. unsigned int tick __attribute__ ((unused)),
  1040. int m, int n __attribute__ ((unused)))
  1041. {
  1042. mob_spawn (m);
  1043. return 0;
  1044. }
  1045. /*==========================================
  1046. * spawn timing calculation
  1047. *------------------------------------------
  1048. */
  1049. int mob_setdelayspawn (int id)
  1050. {
  1051. unsigned int spawntime, spawntime1, spawntime2, spawntime3;
  1052. struct mob_data *md;
  1053. struct block_list *bl;
  1054. if ((bl = map_id2bl (id)) == NULL)
  1055. return -1;
  1056. if (!bl || !bl->type || bl->type != BL_MOB)
  1057. return -1;
  1058. nullpo_retr (-1, md = (struct mob_data *) bl);
  1059. if (!md || md->bl.type != BL_MOB)
  1060. return -1;
  1061. // Processing of MOB which is not revitalized
  1062. if (md->spawndelay1 == -1 && md->spawndelay2 == -1 && md->n == 0)
  1063. {
  1064. map_deliddb (&md->bl);
  1065. if (md->lootitem)
  1066. {
  1067. map_freeblock (md->lootitem);
  1068. md->lootitem = NULL;
  1069. }
  1070. map_freeblock (md); // Instead of [ of free ]
  1071. return 0;
  1072. }
  1073. spawntime1 = md->last_spawntime + md->spawndelay1;
  1074. spawntime2 = md->last_deadtime + md->spawndelay2;
  1075. spawntime3 = gettick () + 5000;
  1076. // spawntime = max(spawntime1,spawntime2,spawntime3);
  1077. if (DIFF_TICK (spawntime1, spawntime2) > 0)
  1078. {
  1079. spawntime = spawntime1;
  1080. }
  1081. else
  1082. {
  1083. spawntime = spawntime2;
  1084. }
  1085. if (DIFF_TICK (spawntime3, spawntime) > 0)
  1086. {
  1087. spawntime = spawntime3;
  1088. }
  1089. add_timer (spawntime, mob_delayspawn, id, 0);
  1090. return 0;
  1091. }
  1092. /*==========================================
  1093. * Mob spawning. Initialization is also variously here.
  1094. *------------------------------------------
  1095. */
  1096. int mob_spawn (int id)
  1097. {
  1098. int x = 0, y = 0, i = 0, c;
  1099. unsigned int tick = gettick ();
  1100. struct mob_data *md;
  1101. struct block_list *bl;
  1102. nullpo_retr (-1, bl = map_id2bl (id));
  1103. if (!bl || !bl->type || bl->type != BL_MOB)
  1104. return -1;
  1105. nullpo_retr (-1, md = (struct mob_data *) bl);
  1106. if (!md || !md->bl.type || md->bl.type != BL_MOB || map[md->bl.m].mob_num > battle_config.mob_map_limit)
  1107. return -1;
  1108. md->last_spawntime = tick;
  1109. if (md->bl.prev != NULL)
  1110. {
  1111. // clif_clearchar_area(&md->bl,3);
  1112. skill_unit_out_all (&md->bl, gettick (), 1);
  1113. map_delblock (&md->bl);
  1114. }
  1115. else
  1116. md->class = md->base_class;
  1117. md->bl.m = md->m;
  1118. do
  1119. {
  1120. if (md->x0 == 0 && md->y0 == 0)
  1121. {
  1122. x = MPRAND (1, (map[md->bl.m].xs - 2));
  1123. y = MPRAND (1, (map[md->bl.m].ys - 2));
  1124. }
  1125. else
  1126. {
  1127. x = MPRAND (md->x0, (md->xs + 1)) - md->xs / 2;
  1128. y = MPRAND (md->y0, (md->ys + 1)) - md->ys / 2;
  1129. }
  1130. i++;
  1131. }
  1132. while (((c = map_getcell (md->bl.m, x, y)) == 1 || c == 5) && i < 50);
  1133. if (i >= 50)
  1134. {
  1135. // if(battle_config.error_log==1)
  1136. // printf("MOB spawn error %d @ %s\n",id,map[md->bl.m].name);
  1137. add_timer (tick + 5000, mob_delayspawn, id, 0);
  1138. return 1;
  1139. }
  1140. md->to_x = md->bl.x = x;
  1141. md->to_y = md->bl.y = y;
  1142. md->dir = 0;
  1143. map_addblock (&md->bl);
  1144. memset (&md->state, 0, sizeof (md->state));
  1145. md->attacked_id = 0;
  1146. md->target_id = 0;
  1147. md->move_fail_count = 0;
  1148. mob_init (md);
  1149. if (!md->stats[MOB_SPEED])
  1150. md->stats[MOB_SPEED] = mob_db[md->class].speed;
  1151. md->def_ele = mob_db[md->class].element;
  1152. // md->master_id = 0;
  1153. md->master_dist = 0;
  1154. md->state.state = MS_IDLE;
  1155. md->state.skillstate = MSS_IDLE;
  1156. md->timer = -1;
  1157. md->last_thinktime = tick;
  1158. md->next_walktime = tick + MPRAND (5000, 50);
  1159. md->attackabletime = tick;
  1160. md->canmove_tick = tick;
  1161. md->sg_count = 0;
  1162. md->deletetimer = -1;
  1163. md->skilltimer = -1;
  1164. for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
  1165. md->skilldelay[i] = c;
  1166. md->skillid = 0;
  1167. md->skilllv = 0;
  1168. memset (md->dmglog, 0, sizeof (md->dmglog));
  1169. if (md->lootitem)
  1170. memset (md->lootitem, 0, sizeof (md->lootitem));
  1171. md->lootitem_count = 0;
  1172. for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
  1173. md->skilltimerskill[i].timer = -1;
  1174. for (i = 0; i < MAX_STATUSCHANGE; i++)
  1175. {
  1176. md->sc_data[i].timer = -1;
  1177. md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 =
  1178. md->sc_data[i].val4 = 0;
  1179. }
  1180. md->sc_count = 0;
  1181. md->opt1 = md->opt2 = md->opt3 = md->option = 0;
  1182. memset (md->skillunit, 0, sizeof (md->skillunit));
  1183. memset (md->skillunittick, 0, sizeof (md->skillunittick));
  1184. md->hp = battle_get_max_hp (&md->bl);
  1185. if (md->hp <= 0)
  1186. {
  1187. mob_makedummymobdb (md->class);
  1188. md->hp = battle_get_max_hp (&md->bl);
  1189. }
  1190. md->max_hp = md->hp;
  1191. clif_spawnmob (md);
  1192. return 0;
  1193. }
  1194. /*==========================================
  1195. * Distance calculation between two points
  1196. *------------------------------------------
  1197. */
  1198. static int distance (int x0, int y0, int x1, int y1)
  1199. {
  1200. int dx, dy;
  1201. dx = abs (x0 - x1);
  1202. dy = abs (y0 - y1);
  1203. return dx > dy ? dx : dy;
  1204. }
  1205. /*==========================================
  1206. * The stop of MOB's attack
  1207. *------------------------------------------
  1208. */
  1209. int mob_stopattack (struct mob_data *md)
  1210. {
  1211. nullpo_retr (0, md);
  1212. md->target_id = 0;
  1213. md->state.targettype = NONE_ATTACKABLE;
  1214. md->attacked_id = 0;
  1215. return 0;
  1216. }
  1217. /*==========================================
  1218. * The stop of MOB's walking
  1219. *------------------------------------------
  1220. */
  1221. int mob_stop_walking (struct mob_data *md, int type)
  1222. {
  1223. nullpo_retr (0, md);
  1224. if (md->state.state == MS_WALK || md->state.state == MS_IDLE)
  1225. {
  1226. int dx = 0, dy = 0;
  1227. md->walkpath.path_len = 0;
  1228. if (type & 4)
  1229. {
  1230. dx = md->to_x - md->bl.x;
  1231. if (dx < 0)
  1232. dx = -1;
  1233. else if (dx > 0)
  1234. dx = 1;
  1235. dy = md->to_y - md->bl.y;
  1236. if (dy < 0)
  1237. dy = -1;
  1238. else if (dy > 0)
  1239. dy = 1;
  1240. }
  1241. md->to_x = md->bl.x + dx;
  1242. md->to_y = md->bl.y + dy;
  1243. if (dx != 0 || dy != 0)
  1244. {
  1245. mob_walktoxy_sub (md);
  1246. return 0;
  1247. }
  1248. mob_changestate (md, MS_IDLE, 0);
  1249. }
  1250. if (type & 0x01)
  1251. clif_fixmobpos (md);
  1252. if (type & 0x02)
  1253. {
  1254. int delay = battle_get_dmotion (&md->bl);
  1255. unsigned int tick = gettick ();
  1256. if (md->canmove_tick < tick)
  1257. md->canmove_tick = tick + delay;
  1258. }
  1259. return 0;
  1260. }
  1261. /*==========================================
  1262. * Reachability to a Specification ID existence place
  1263. *------------------------------------------
  1264. */
  1265. int mob_can_reach (struct mob_data *md, struct block_list *bl, int range)
  1266. {
  1267. int dx, dy;
  1268. struct walkpath_data wpd;
  1269. int i;
  1270. nullpo_retr (0, md);
  1271. nullpo_retr (0, bl);
  1272. dx = abs (bl->x - md->bl.x);
  1273. dy = abs (bl->y - md->bl.y);
  1274. //=========== guildcastle guardian no search start===========
  1275. //when players are the guild castle member not attack them !
  1276. if (md->class == 1285 || md->class == 1286 || md->class == 1287)
  1277. {
  1278. struct map_session_data *sd;
  1279. struct guild *g = NULL;
  1280. struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
  1281. if (gc && agit_flag == 0) // Guardians will not attack during non-woe time [Valaris]
  1282. return 0; // end addition [Valaris]
  1283. if (bl && bl->type == BL_PC)
  1284. {
  1285. if ((sd = (struct map_session_data *) bl) == NULL)
  1286. {
  1287. printf ("mob_can_reach nullpo\n");
  1288. return 0;
  1289. }
  1290. if (gc && sd && sd->status.guild_id && sd->status.guild_id > 0)
  1291. {
  1292. g = guild_search (sd->status.guild_id); // don't attack guild members [Valaris]
  1293. if (g && g->guild_id > 0 && g->guild_id == gc->guild_id)
  1294. return 0;
  1295. if (g && gc && guild_isallied (g, gc))
  1296. return 0;
  1297. }
  1298. }
  1299. }
  1300. //========== guildcastle guardian no search eof==============
  1301. if (bl && bl->type == BL_PC && battle_config.monsters_ignore_gm == 1)
  1302. { // option to have monsters ignore GMs [Valaris]
  1303. struct map_session_data *sd;
  1304. if ((sd = (struct map_session_data *) bl) != NULL && pc_isGM (sd))
  1305. return 0;
  1306. }
  1307. if (md->bl.m != bl->m) // 違うャbプ
  1308. return 0;
  1309. if (range > 0 && range < ((dx > dy) ? dx : dy)) // 遠すぎる
  1310. return 0;
  1311. if (md->bl.x == bl->x && md->bl.y == bl->y) // 同じャX
  1312. return 1;
  1313. // Obstacle judging
  1314. wpd.path_len = 0;
  1315. wpd.path_pos = 0;
  1316. wpd.path_half = 0;
  1317. if (path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0) !=
  1318. -1)
  1319. return 1;
  1320. if (bl->type != BL_PC && bl->type != BL_MOB)
  1321. return 0;
  1322. // It judges whether it can adjoin or not.
  1323. dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
  1324. dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
  1325. if (path_search
  1326. (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - dx, bl->y - dy, 0) != -1)
  1327. return 1;
  1328. for (i = 0; i < 9; i++)
  1329. {
  1330. if (path_search
  1331. (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - 1 + i / 3,
  1332. bl->y - 1 + i % 3, 0) != -1)
  1333. return 1;
  1334. }
  1335. return 0;
  1336. }
  1337. /*==========================================
  1338. * Determination for an attack of a monster
  1339. *------------------------------------------
  1340. */
  1341. int mob_target (struct mob_data *md, struct block_list *bl, int dist)
  1342. {
  1343. struct map_session_data *sd;
  1344. struct status_change *sc_data;
  1345. short *option;
  1346. int mode, race;
  1347. nullpo_retr (0, md);
  1348. nullpo_retr (0, bl);
  1349. sc_data = battle_get_sc_data (bl);
  1350. option = battle_get_option (bl);
  1351. race = mob_db[md->class].race;
  1352. if (!md->mode)
  1353. {
  1354. mode = mob_db[md->class].mode;
  1355. }
  1356. else
  1357. {
  1358. mode = md->mode;
  1359. }
  1360. if (!(mode & 0x80))
  1361. {
  1362. md->target_id = 0;
  1363. return 0;
  1364. }
  1365. // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
  1366. if ((md->target_id > 0 && md->state.targettype == ATTACKABLE)
  1367. && (!(mode & 0x04) || MRAND (100) > 25))
  1368. return 0;
  1369. if (mode & 0x20 || // Coercion is exerted if it is MVPMOB.
  1370. (sc_data && sc_data[SC_TRICKDEAD].timer == -1 &&
  1371. ((option && !(*option & 0x06)) || race == 4 || race == 6)))
  1372. {
  1373. if (bl->type == BL_PC)
  1374. {
  1375. nullpo_retr (0, sd = (struct map_session_data *) bl);
  1376. if (sd->invincible_timer != -1 || pc_isinvisible (sd))
  1377. return 0;
  1378. if (!(mode & 0x20) && race != 4 && race != 6
  1379. && sd->state.gangsterparadise)
  1380. return 0;
  1381. }
  1382. md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
  1383. if (bl->type == BL_PC || bl->type == BL_MOB)
  1384. md->state.targettype = ATTACKABLE;
  1385. else
  1386. md->state.targettype = NONE_ATTACKABLE;
  1387. md->min_chase = dist + 13;
  1388. if (md->min_chase > 26)
  1389. md->min_chase = 26;
  1390. }
  1391. return 0;
  1392. }
  1393. /*==========================================
  1394. * The ?? routine of an active monster
  1395. *------------------------------------------
  1396. */
  1397. static int mob_ai_sub_hard_activesearch (struct block_list *bl, va_list ap)
  1398. {
  1399. struct map_session_data *tsd = NULL;
  1400. struct mob_data *smd, *tmd = NULL;
  1401. int mode, *pcc;
  1402. nullpo_retr (0, bl);
  1403. nullpo_retr (0, ap);
  1404. nullpo_retr (0, smd = va_arg (ap, struct mob_data *));
  1405. nullpo_retr (0, pcc = va_arg (ap, int *));
  1406. if (bl->type == BL_PC)
  1407. tsd = (struct map_session_data *) bl;
  1408. else if (bl->type == BL_MOB)
  1409. tmd = (struct mob_data *) bl;
  1410. else
  1411. return 0;
  1412. //敵味方判定
  1413. if (battle_check_target (&smd->bl, bl, BCT_ENEMY) == 0)
  1414. return 0;
  1415. if (!smd->mode)
  1416. mode = mob_db[smd->class].mode;
  1417. else
  1418. mode = smd->mode;
  1419. // アクティブでターゲット射程内にいるなら、ロックする
  1420. if (mode & 0x04)
  1421. {
  1422. int race;
  1423. race = mob_db[smd->class].race;
  1424. //対象がPCの場合
  1425. if (tsd &&
  1426. !pc_isdead (tsd) &&
  1427. tsd->bl.m == smd->bl.m &&
  1428. tsd->invincible_timer == -1 &&
  1429. !pc_isinvisible (tsd) &&
  1430. (distance (smd->bl.x, smd->bl.y, tsd->bl.x, tsd->bl.y)) < 9)
  1431. {
  1432. if (mode & 0x20 ||
  1433. (tsd->sc_data[SC_TRICKDEAD].timer == -1 &&
  1434. ((!pc_ishiding (tsd) && !tsd->state.gangsterparadise)
  1435. || race == 4 || race == 6)))
  1436. { // 妨害がないか判定
  1437. if (mob_can_reach (smd, bl, 12) && // 到達可能性判定
  1438. MRAND (1000) < 1000 / (++(*pcc)))
  1439. { // 範囲内PCで等確率にする
  1440. smd->target_id = tsd->bl.id;
  1441. smd->state.targettype = ATTACKABLE;
  1442. smd->min_chase = 13;
  1443. }
  1444. }
  1445. }
  1446. //対象がMobの場合
  1447. else if (tmd &&
  1448. tmd->bl.m == smd->bl.m &&
  1449. (distance (smd->bl.x, smd->bl.y, tmd->bl.x, tmd->bl.y)) < 9)
  1450. {
  1451. if (mob_can_reach (smd, bl, 12) && // 到達可能性判定
  1452. MRAND (1000) < 1000 / (++(*pcc)))
  1453. { // 範囲内で等確率にする
  1454. smd->target_id = bl->id;
  1455. smd->state.targettype = ATTACKABLE;
  1456. smd->min_chase = 13;
  1457. }
  1458. }
  1459. }
  1460. return 0;
  1461. }
  1462. /*==========================================
  1463. * loot monster item search
  1464. *------------------------------------------
  1465. */
  1466. static int mob_ai_sub_hard_lootsearch (struct block_list *bl, va_list ap)
  1467. {
  1468. struct mob_data *md;
  1469. int mode, *itc;
  1470. nullpo_retr (0, bl);
  1471. nullpo_retr (0, ap);
  1472. nullpo_retr (0, md = va_arg (ap, struct mob_data *));
  1473. nullpo_retr (0, itc = va_arg (ap, int *));
  1474. if (!md->mode)
  1475. {
  1476. mode = mob_db[md->class].mode;
  1477. }
  1478. else
  1479. {
  1480. mode = md->mode;
  1481. }
  1482. if (!md->target_id && mode & 0x02)
  1483. {
  1484. if (!md->lootitem
  1485. || (battle_config.monster_loot_type == 1
  1486. && md->lootitem_count >= LOOTITEM_SIZE))
  1487. return 0;
  1488. if (bl->m == md->bl.m
  1489. && distance (md->bl.x, md->bl.y, bl->x, bl->y) < 9)
  1490. {
  1491. if (mob_can_reach (md, bl, 12) && // Reachability judging
  1492. MRAND (1000) < 1000 / (++(*itc)))
  1493. { // It is made a probability, such as within the limits PC.
  1494. md->target_id = bl->id;
  1495. md->state.targettype = NONE_ATTACKABLE;
  1496. md->min_chase = 13;
  1497. }
  1498. }
  1499. }
  1500. return 0;
  1501. }
  1502. /*==========================================
  1503. * The ?? routine of a link monster
  1504. *------------------------------------------
  1505. */
  1506. static int mob_ai_sub_hard_linksearch (struct block_list *bl, va_list ap)
  1507. {
  1508. struct mob_data *tmd;
  1509. struct mob_data *md;
  1510. struct block_list *target;
  1511. nullpo_retr (0, bl);
  1512. nullpo_retr (0, ap);
  1513. nullpo_retr (0, tmd = (struct mob_data *) bl);
  1514. nullpo_retr (0, md = va_arg (ap, struct mob_data *));
  1515. nullpo_retr (0, target = va_arg (ap, struct block_list *));
  1516. // same family free in a range at a link monster -- it will be made to lock if MOB is
  1517. /* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class].mode&0x08){
  1518. if( tmd->class==md->class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
  1519. if( mob_can_reach(tmd,target,12) ){ // Reachability judging
  1520. tmd->target_id=md->target_id;
  1521. tmd->state.targettype = ATTACKABLE;
  1522. tmd->min_chase=13;
  1523. }
  1524. }
  1525. }*/
  1526. if (md->attacked_id > 0 && mob_db[md->class].mode & 0x08)
  1527. {
  1528. if (tmd->class == md->class && tmd->bl.m == md->bl.m
  1529. && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE))
  1530. {
  1531. if (mob_can_reach (tmd, target, 12))
  1532. { // Reachability judging
  1533. tmd->target_id = md->attacked_id;
  1534. tmd->state.targettype = ATTACKABLE;
  1535. tmd->min_chase = 13;
  1536. }
  1537. }
  1538. }
  1539. return 0;
  1540. }
  1541. /*==========================================
  1542. * Processing of slave monsters
  1543. *------------------------------------------
  1544. */
  1545. static int mob_ai_sub_hard_slavemob (struct mob_data *md, unsigned int tick)
  1546. {
  1547. struct mob_data *mmd = NULL;
  1548. struct block_list *bl;
  1549. int mode, old_dist;
  1550. nullpo_retr (0, md);
  1551. if ((bl = map_id2bl (md->master_id)) != NULL)
  1552. mmd = (struct mob_data *) bl;
  1553. mode = mob_db[md->class].mode;
  1554. // It is not main monster/leader.
  1555. if (!mmd || mmd->bl.type != BL_MOB || mmd->bl.id != md->master_id)
  1556. return 0;
  1557. // Since it is in the map on which the master is not, teleport is carried out and it pursues.
  1558. if (mmd->bl.m != md->bl.m)
  1559. {
  1560. mob_warp (md, mmd->bl.m, mmd->bl.x, mmd->bl.y, 3);
  1561. md->state.master_check = 1;
  1562. return 0;
  1563. }
  1564. // Distance with between slave and master is measured.
  1565. old_dist = md->master_dist;
  1566. md->master_dist = distance (md->bl.x, md->bl.y, mmd->bl.x, mmd->bl.y);
  1567. // Since the master was in near immediately before, teleport is carried out and it pursues.
  1568. if (old_dist < 10 && md->master_dist > 18)
  1569. {
  1570. mob_warp (md, -1, mmd->bl.x, mmd->bl.y, 3);
  1571. md->state.master_check = 1;
  1572. return 0;
  1573. }
  1574. // Although there is the master, since it is somewhat far, it approaches.
  1575. if ((!md->target_id || md->state.targettype == NONE_ATTACKABLE)
  1576. && mob_can_move (md)
  1577. && (md->walkpath.path_pos >= md->walkpath.path_len
  1578. || md->walkpath.path_len == 0) && md->master_dist < 15)
  1579. {
  1580. int i = 0, dx, dy, ret;
  1581. if (md->master_dist > 4)
  1582. {
  1583. do
  1584. {
  1585. if (i <= 5)
  1586. {
  1587. dx = mmd->bl.x - md->bl.x;
  1588. dy = mmd->bl.y - md->bl.y;
  1589. if (dx < 0)
  1590. dx += (MPRAND (1, ((dx < -3) ? 3 : -dx)));
  1591. else if (dx > 0)
  1592. dx -= (MPRAND (1, ((dx > 3) ? 3 : dx)));
  1593. if (dy < 0)
  1594. dy += (MPRAND (1, ((dy < -3) ? 3 : -dy)));
  1595. else if (dy > 0)
  1596. dy -= (MPRAND (1, ((dy > 3) ? 3 : dy)));
  1597. }
  1598. else
  1599. {
  1600. dx = mmd->bl.x - md->bl.x + MRAND (7) - 3;
  1601. dy = mmd->bl.y - md->bl.y + MRAND (7) - 3;
  1602. }
  1603. ret = mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy, 0);
  1604. i++;
  1605. }
  1606. while (ret && i < 10);
  1607. }
  1608. else
  1609. {
  1610. do
  1611. {
  1612. dx = MRAND (9) - 5;
  1613. dy = MRAND (9) - 5;
  1614. if (dx == 0 && dy == 0)
  1615. {
  1616. dx = (MRAND (1)) ? 1 : -1;
  1617. dy = (MRAND (1)) ? 1 : -1;
  1618. }
  1619. dx += mmd->bl.x;
  1620. dy += mmd->bl.y;
  1621. ret = mob_walktoxy (md, mmd->bl.x + dx, mmd->bl.y + dy, 0);
  1622. i++;
  1623. }
  1624. while (ret && i < 10);
  1625. }
  1626. md->next_walktime = tick + 500;
  1627. md->state.master_check = 1;
  1628. }
  1629. // There is the master, the master locks a target and he does not lock.
  1630. if ((mmd->target_id > 0 && mmd->state.targettype == ATTACKABLE)
  1631. && (!md->target_id || md->state.targettype == NONE_ATTACKABLE))
  1632. {
  1633. struct map_session_data *sd = map_id2sd (mmd->target_id);
  1634. if (sd != NULL && !pc_isdead (sd) && sd->invincible_timer == -1
  1635. && !pc_isinvisible (sd))
  1636. {
  1637. int race;
  1638. race = mob_db[md->class].race;
  1639. if (mode & 0x20 ||
  1640. (sd->sc_data[SC_TRICKDEAD].timer == -1 &&
  1641. ((!pc_ishiding (sd) && !sd->state.gangsterparadise)
  1642. || race == 4 || race == 6)))
  1643. { // 妨害がないか判定
  1644. md->target_id = sd->bl.id;
  1645. md->state.targettype = ATTACKABLE;
  1646. md->min_chase =
  1647. 5 + distance (md->bl.x, md->bl.y, sd->bl.x, sd->bl.y);
  1648. md->state.master_check = 1;
  1649. }
  1650. }
  1651. }
  1652. // There is the master, the master locks a target and he does not lock.
  1653. /* if( (md->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!mmd->target_id || mmd->state.targettype == NONE_ATTACKABLE) ){
  1654. struct map_session_data *sd=map_id2sd(md->target_id);
  1655. if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
  1656. race=mob_db[mmd->class].race;
  1657. if(mode&0x20 ||
  1658. (sd->sc_data[SC_TRICKDEAD].timer == -1 &&
  1659. (!(sd->status.option&0x06) || race==4 || race==6)
  1660. ) ){ // It judges whether there is any disturbance.
  1661. mmd->target_id=sd->bl.id;
  1662. mmd->state.targettype = ATTACKABLE;
  1663. mmd->min_chase=5+distance(mmd->bl.x,mmd->bl.y,sd->bl.x,sd->bl.y);
  1664. }
  1665. }
  1666. }*/
  1667. return 0;
  1668. }
  1669. /*==========================================
  1670. * A lock of target is stopped and mob moves to a standby state.
  1671. *------------------------------------------
  1672. */
  1673. static int mob_unlocktarget (struct mob_data *md, int tick)
  1674. {
  1675. nullpo_retr (0, md);
  1676. md->target_id = 0;
  1677. md->state.targettype = NONE_ATTACKABLE;
  1678. md->state.skillstate = MSS_IDLE;
  1679. md->next_walktime = tick + MPRAND (3000, 3000);
  1680. return 0;
  1681. }
  1682. /*==========================================
  1683. * Random walk
  1684. *------------------------------------------
  1685. */
  1686. static int mob_randomwalk (struct mob_data *md, int tick)
  1687. {
  1688. const int retrycount = 20;
  1689. int speed;
  1690. nullpo_retr (0, md);
  1691. speed = battle_get_speed (&md->bl);
  1692. if (DIFF_TICK (md->next_walktime, tick) < 0)
  1693. {
  1694. int i, x, y, c, d = 12 - md->move_fail_count;
  1695. if (d < 5)
  1696. d = 5;
  1697. for (i = 0; i < retrycount; i++)
  1698. { // Search of a movable place
  1699. int r = mt_random ();
  1700. x = md->bl.x + r % (d * 2 + 1) - d;
  1701. y = md->bl.y + r / (d * 2 + 1) % (d * 2 + 1) - d;
  1702. if ((c = map_getcell (md->bl.m, x, y)) != 1 && c != 5
  1703. && mob_walktoxy (md, x, y, 1) == 0)
  1704. {
  1705. md->move_fail_count = 0;
  1706. break;
  1707. }
  1708. if (i + 1 >= retrycount)
  1709. {
  1710. md->move_fail_count++;
  1711. if (md->move_fail_count > 1000)
  1712. {
  1713. if (battle_config.error_log == 1)
  1714. printf
  1715. ("MOB cant move. random spawn %d, class = %d\n",
  1716. md->bl.id, md->class);
  1717. md->move_fail_count = 0;
  1718. mob_spawn (md->bl.id);
  1719. }
  1720. }
  1721. }
  1722. for (i = c = 0; i < md->walkpath.path_len; i++)
  1723. { // The next walk start time is calculated.
  1724. if (md->walkpath.path[i] & 1)
  1725. c += speed * 14 / 10;
  1726. else
  1727. c += speed;
  1728. }
  1729. md->next_walktime = tick + MPRAND (3000, 3000) + c;
  1730. md->state.skillstate = MSS_WALK;
  1731. return 1;
  1732. }
  1733. return 0;
  1734. }
  1735. /*==========================================
  1736. * AI of MOB whose is near a Player
  1737. *------------------------------------------
  1738. */
  1739. static int mob_ai_sub_hard (struct block_list *bl, va_list ap)
  1740. {
  1741. struct mob_data *md, *tmd = NULL;
  1742. struct map_session_data *tsd = NULL;
  1743. struct block_list *tbl = NULL;
  1744. struct flooritem_data *fitem;
  1745. unsigned int tick;
  1746. int i, dist;
  1747. int attack_type = 0;
  1748. int mode, race;
  1749. nullpo_retr (0, bl);
  1750. nullpo_retr (0, ap);
  1751. nullpo_retr (0, md = (struct mob_data *) bl);
  1752. tick = va_arg (ap, unsigned int);
  1753. if (DIFF_TICK (tick, md->last_thinktime) < MIN_MOBTHINKTIME)
  1754. return 0;
  1755. md->last_thinktime = tick;
  1756. if (md->skilltimer != -1 || md->bl.prev == NULL)
  1757. { // Under a skill aria and death
  1758. if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME)
  1759. md->next_walktime = tick;
  1760. return 0;
  1761. }
  1762. if (!md->mode)
  1763. mode = mob_db[md->class].mode;
  1764. else
  1765. mode = md->mode;
  1766. race = mob_db[md->class].race;
  1767. // Abnormalities
  1768. if ((md->opt1 > 0 && md->opt1 != 6) || md->state.state == MS_DELAY
  1769. || md->sc_data[SC_BLADESTOP].timer != -1)
  1770. return 0;
  1771. if (!(mode & 0x80) && md->target_id > 0)
  1772. md->target_id = 0;
  1773. if (md->attacked_id > 0 && mode & 0x08)
  1774. { // Link monster
  1775. struct map_session_data *asd = map_id2sd (md->attacked_id);
  1776. if (asd)
  1777. {
  1778. if (asd->invincible_timer == -1 && !pc_isinvisible (asd) && !pc_isdead(asd))
  1779. {
  1780. map_foreachinarea (mob_ai_sub_hard_linksearch, md->bl.m,
  1781. md->bl.x - 13, md->bl.y - 13,
  1782. md->bl.x + 13, md->bl.y + 13,
  1783. BL_MOB, md, &asd->bl);
  1784. }
  1785. }
  1786. }
  1787. // It checks to see it was attacked first (if active, it is target change at 25% of probability).
  1788. if (mode > 0 && md->attacked_id > 0
  1789. && (!md->target_id || md->state.targettype == NONE_ATTACKABLE
  1790. || (mode & 0x04 && MRAND (100) < 25)))
  1791. {
  1792. struct block_list *abl = map_id2bl (md->attacked_id);
  1793. struct map_session_data *asd = NULL;
  1794. if (abl)
  1795. {
  1796. if (abl->type == BL_PC)
  1797. asd = (struct map_session_data *) abl;
  1798. if (asd == NULL || md->bl.m != abl->m || abl->prev == NULL
  1799. || asd->invincible_timer != -1 || pc_isinvisible (asd)
  1800. || (dist =
  1801. distance (md->bl.x, md->bl.y, abl->x, abl->y)) >= 32
  1802. || battle_check_target (bl, abl, BCT_ENEMY) == 0)
  1803. md->attacked_id = 0;
  1804. else
  1805. {
  1806. md->target_id = md->attacked_id; // set target
  1807. md->state.targettype = ATTACKABLE;
  1808. attack_type = 1;
  1809. md->attacked_id = 0;
  1810. md->min_chase = dist + 13;
  1811. if (md->min_chase > 26)
  1812. md->min_chase = 26;
  1813. }
  1814. }
  1815. }
  1816. md->state.master_check = 0;
  1817. // Processing of slave monster
  1818. if (md->master_id > 0 && md->state.special_mob_ai == 0)
  1819. mob_ai_sub_hard_slavemob (md, tick);
  1820. // アクティヴモンスターの策敵 (?? of a bitter taste TIVU monster)
  1821. if ((!md->target_id || md->state.targettype == NONE_ATTACKABLE)
  1822. && mode & 0x04 && !md->state.master_check
  1823. && battle_config.monster_active_enable == 1)
  1824. {
  1825. i = 0;
  1826. if (md->state.special_mob_ai)
  1827. {
  1828. map_foreachinarea (mob_ai_sub_hard_activesearch, md->bl.m,
  1829. md->bl.x - AREA_SIZE * 2,
  1830. md->bl.y - AREA_SIZE * 2,
  1831. md->bl.x + AREA_SIZE * 2,
  1832. md->bl.y + AREA_SIZE * 2, 0, md, &i);
  1833. }
  1834. else
  1835. {
  1836. map_foreachinarea (mob_ai_sub_hard_activesearch, md->bl.m,
  1837. md->bl.x - AREA_SIZE * 2,
  1838. md->bl.y - AREA_SIZE * 2,
  1839. md->bl.x + AREA_SIZE * 2,
  1840. md->bl.y + AREA_SIZE * 2, BL_PC, md, &i);
  1841. }
  1842. }
  1843. // The item search of a route monster
  1844. if (!md->target_id && mode & 0x02 && !md->state.master_check)
  1845. {
  1846. i = 0;
  1847. map_foreachinarea (mob_ai_sub_hard_lootsearch, md->bl.m,
  1848. md->bl.x - AREA_SIZE * 2, md->bl.y - AREA_SIZE * 2,
  1849. md->bl.x + AREA_SIZE * 2, md->bl.y + AREA_SIZE * 2,
  1850. BL_ITEM, md, &i);
  1851. }
  1852. // It will attack, if the candidate for an attack is.
  1853. if (md->target_id > 0)
  1854. {
  1855. if ((tbl = map_id2bl (md->target_id)))
  1856. {
  1857. int ret;
  1858. int dx, dy;
  1859. if (tbl->type == BL_PC)
  1860. tsd = (struct map_session_data *) tbl;
  1861. else if (tbl->type == BL_MOB)
  1862. tmd = (struct mob_data *) tbl;
  1863. if (tsd || tmd)
  1864. {
  1865. if (tbl->m != md->bl.m || tbl->prev == NULL
  1866. || (dist =
  1867. distance (md->bl.x, md->bl.y, tbl->x,
  1868. tbl->y)) >= md->min_chase)
  1869. mob_unlocktarget (md, tick); // 別マップか、視界外
  1870. else if (tsd && !(mode & 0x20)
  1871. && (tsd->sc_data[SC_TRICKDEAD].timer != -1
  1872. ||
  1873. ((pc_ishiding (tsd)
  1874. || tsd->state.gangsterparadise) && race != 4
  1875. && race != 6)))
  1876. mob_unlocktarget (md, tick); // スキルなどによる策敵妨害
  1877. else if (!battle_check_range
  1878. (&md->bl, tbl, mob_db[md->class].range))
  1879. {
  1880. // 攻撃範囲外なので移動
  1881. if (!(mode & 1))
  1882. { // 移動しないモード
  1883. mob_unlocktarget (md, tick);
  1884. return 0;
  1885. }
  1886. if (!mob_can_move (md)) // 動けない状態にある
  1887. return 0;
  1888. md->state.skillstate = MSS_CHASE; // 突撃時スキル
  1889. mobskill_use (md, tick, -1);
  1890. // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) )
  1891. if (md->timer != -1 && md->state.state != MS_ATTACK
  1892. && (DIFF_TICK (md->next_walktime, tick) < 0
  1893. || distance (md->to_x, md->to_y, tbl->x,
  1894. tbl->y) < 2))
  1895. return 0; // 既に移動中
  1896. if (!mob_can_reach
  1897. (md, tbl, (md->min_chase > 13) ? md->min_chase : 13))
  1898. mob_unlocktarget (md, tick); // 移動できないのでタゲ解除(IWとか?)
  1899. else
  1900. {
  1901. // 追跡
  1902. md->next_walktime = tick + 500;
  1903. i = 0;
  1904. do
  1905. {
  1906. if (i == 0)
  1907. { // 最初はAEGISと同じ方法で検索
  1908. dx = tbl->x - md->bl.x;
  1909. dy = tbl->y - md->bl.y;
  1910. if (dx < 0)
  1911. dx++;
  1912. else if (dx > 0)
  1913. dx--;
  1914. if (dy < 0)
  1915. dy++;
  1916. else if (dy > 0)
  1917. dy--;
  1918. }
  1919. else
  1920. { // だめならAthena式(ランダム)
  1921. dx = tbl->x - md->bl.x + MRAND (3) - 1;
  1922. dy = tbl->y - md->bl.y + MRAND (3) - 1;
  1923. }
  1924. /* if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
  1925. * dx=tsd->bl.x - md->bl.x;
  1926. * dy=tsd->bl.y - md->bl.y;
  1927. * if(dx<0) dx--;
  1928. * else if(dx>0) dx++;
  1929. * if(dy<0) dy--;
  1930. * else if(dy>0) dy++;
  1931. * } */
  1932. ret =
  1933. mob_walktoxy (md, md->bl.x + dx,
  1934. md->bl.y + dy, 0);
  1935. i++;
  1936. }
  1937. while (ret && i < 5);
  1938. if (ret)
  1939. { // 移動不可能な所からの攻撃なら2歩下る
  1940. if (dx < 0)
  1941. dx = 2;
  1942. else if (dx > 0)
  1943. dx = -2;
  1944. if (dy < 0)
  1945. dy = 2;
  1946. else if (dy > 0)
  1947. dy = -2;
  1948. mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy,
  1949. 0);
  1950. }
  1951. }
  1952. }
  1953. else
  1954. { // 攻撃射程範囲内
  1955. md->state.skillstate = MSS_ATTACK;
  1956. if (md->state.state == MS_WALK)
  1957. mob_stop_walking (md, 1); // 歩行中なら停止
  1958. if (md->state.state == MS_ATTACK)
  1959. return 0; // 既に攻撃中
  1960. mob_changestate (md, MS_ATTACK, attack_type);
  1961. /* if(mode&0x08){ // リンクモンスター
  1962. map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
  1963. md->bl.x-13,md->bl.y-13,
  1964. md->bl.x+13,md->bl.y+13,
  1965. BL_MOB,md,&tsd->bl);
  1966. }*/
  1967. }
  1968. return 0;
  1969. }
  1970. else
  1971. { // ルートモンスター処理
  1972. if (tbl == NULL || tbl->type != BL_ITEM || tbl->m != md->bl.m
  1973. || (dist =
  1974. distance (md->bl.x, md->bl.y, tbl->x,
  1975. tbl->y)) >= md->min_chase || !md->lootitem)
  1976. {
  1977. // 遠すぎるかアイテムがなくなった
  1978. mob_unlocktarget (md, tick);
  1979. if (md->state.state == MS_WALK)
  1980. mob_stop_walking (md, 1); // 歩行中なら停止
  1981. }
  1982. else if (dist)
  1983. {
  1984. if (!(mode & 1))
  1985. { // 移動しないモード
  1986. mob_unlocktarget (md, tick);
  1987. return 0;
  1988. }
  1989. if (!mob_can_move (md)) // 動けない状態にある
  1990. return 0;
  1991. md->state.skillstate = MSS_LOOT; // ルート時スキル使用
  1992. mobskill_use (md, tick, -1);
  1993. // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
  1994. if (md->timer != -1 && md->state.state != MS_ATTACK
  1995. && (DIFF_TICK (md->next_walktime, tick) < 0
  1996. || distance (md->to_x, md->to_y, tbl->x,
  1997. tbl->y) <= 0))
  1998. return 0; // 既に移動中
  1999. md->next_walktime = tick + 500;
  2000. dx = tbl->x - md->bl.x;
  2001. dy = tbl->y - md->bl.y;
  2002. /* if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
  2003. dx=tbl->x - md->bl.x;
  2004. dy=tbl->y - md->bl.y;
  2005. }*/
  2006. ret = mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy, 0);
  2007. if (ret)
  2008. mob_unlocktarget (md, tick); // 移動できないのでタゲ解除(IWとか?)
  2009. }
  2010. else
  2011. { // アイテムまでたどり着いた
  2012. if (md->state.state == MS_ATTACK)
  2013. return 0; // 攻撃中
  2014. if (md->state.state == MS_WALK)
  2015. mob_stop_walking (md, 1); // 歩行中なら停止
  2016. fitem = (struct flooritem_data *) tbl;
  2017. if (md->lootitem_count < LOOTITEM_SIZE)
  2018. memcpy (&md->lootitem[md->lootitem_count++],
  2019. &fitem->item_data, sizeof (md->lootitem[0]));
  2020. else if (battle_config.monster_loot_type == 1
  2021. && md->lootitem_count >= LOOTITEM_SIZE)
  2022. {
  2023. mob_unlocktarget (md, tick);
  2024. return 0;
  2025. }
  2026. else
  2027. {
  2028. for (i = 0; i < LOOTITEM_SIZE - 1; i++)
  2029. memcpy (&md->lootitem[i], &md->lootitem[i + 1],
  2030. sizeof (md->lootitem[0]));
  2031. memcpy (&md->lootitem[LOOTITEM_SIZE - 1],
  2032. &fitem->item_data, sizeof (md->lootitem[0]));
  2033. }
  2034. map_clearflooritem (tbl->id);
  2035. mob_unlocktarget (md, tick);
  2036. }
  2037. return 0;
  2038. }
  2039. }
  2040. else
  2041. {
  2042. mob_unlocktarget (md, tick);
  2043. if (md->state.state == MS_WALK)
  2044. mob_stop_walking (md, 4); // 歩行中なら停止
  2045. return 0;
  2046. }
  2047. }
  2048. // It is skill use at the time of /standby at the time of a walk.
  2049. if (mobskill_use (md, tick, -1))
  2050. return 0;
  2051. // 歩行処理
  2052. if (mode & 1 && mob_can_move (md) && // 移動可能MOB&動ける状態にある
  2053. (md->master_id == 0 || md->state.special_mob_ai
  2054. || md->master_dist > 10))
  2055. { //取り巻きMOBじゃない
  2056. if (DIFF_TICK (md->next_walktime, tick) > +7000 &&
  2057. (md->walkpath.path_len == 0
  2058. || md->walkpath.path_pos >= md->walkpath.path_len))
  2059. {
  2060. md->next_walktime = tick + 3000 * MRAND (2000);
  2061. }
  2062. // Random movement
  2063. if (mob_randomwalk (md, tick))
  2064. return 0;
  2065. }
  2066. // Since he has finished walking, it stands by.
  2067. if (md->walkpath.path_len == 0
  2068. || md->walkpath.path_pos >= md->walkpath.path_len)
  2069. md->state.skillstate = MSS_IDLE;
  2070. return 0;
  2071. }
  2072. /*==========================================
  2073. * Serious processing for mob in PC field of view (foreachclient)
  2074. *------------------------------------------
  2075. */
  2076. static int mob_ai_sub_foreachclient (struct map_session_data *sd, va_list ap)
  2077. {
  2078. unsigned int tick;
  2079. nullpo_retr (0, sd);
  2080. nullpo_retr (0, ap);
  2081. tick = va_arg (ap, unsigned int);
  2082. map_foreachinarea (mob_ai_sub_hard, sd->bl.m,
  2083. sd->bl.x - AREA_SIZE * 2, sd->bl.y - AREA_SIZE * 2,
  2084. sd->bl.x + AREA_SIZE * 2, sd->bl.y + AREA_SIZE * 2,
  2085. BL_MOB, tick);
  2086. return 0;
  2087. }
  2088. /*==========================================
  2089. * Serious processing for mob in PC field of view (interval timer function)
  2090. *------------------------------------------
  2091. */
  2092. static int mob_ai_hard (int tid __attribute__ ((unused)),
  2093. unsigned int tick, int id __attribute__ ((unused)),
  2094. int data __attribute__ ((unused)))
  2095. {
  2096. clif_foreachclient (mob_ai_sub_foreachclient, tick);
  2097. return 0;
  2098. }
  2099. /*==========================================
  2100. * Negligent mode MOB AI (PC is not in near)
  2101. *------------------------------------------
  2102. */
  2103. static int mob_ai_sub_lazy (void *key __attribute__ ((unused)),
  2104. void *data, va_list app)
  2105. {
  2106. struct mob_data *md = data;
  2107. unsigned int tick;
  2108. va_list ap;
  2109. nullpo_retr (0, md);
  2110. nullpo_retr (0, app);
  2111. nullpo_retr (0, ap = va_arg (app, va_list));
  2112. if (md == NULL)
  2113. return 0;
  2114. if (!md->bl.type || md->bl.type != BL_MOB)
  2115. return 0;
  2116. tick = va_arg (ap, unsigned int);
  2117. if (DIFF_TICK (tick, md->last_thinktime) < MIN_MOBTHINKTIME * 10)
  2118. return 0;
  2119. md->last_thinktime = tick;
  2120. if (md->bl.prev == NULL || md->skilltimer != -1)
  2121. {
  2122. if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME * 10)
  2123. md->next_walktime = tick;
  2124. return 0;
  2125. }
  2126. if (DIFF_TICK (md->next_walktime, tick) < 0 &&
  2127. (mob_db[md->class].mode & 1) && mob_can_move (md))
  2128. {
  2129. if (map[md->bl.m].users > 0)
  2130. {
  2131. // Since PC is in the same map, somewhat better negligent processing is carried out.
  2132. // It sometimes moves.
  2133. if (MRAND (1000) < MOB_LAZYMOVEPERC)
  2134. mob_randomwalk (md, tick);
  2135. // MOB which is not not the summons MOB but BOSS, either sometimes reboils.
  2136. else if (MRAND (1000) < MOB_LAZYWARPPERC && md->x0 <= 0
  2137. && md->master_id != 0 && mob_db[md->class].mexp <= 0
  2138. && !(mob_db[md->class].mode & 0x20))
  2139. mob_spawn (md->bl.id);
  2140. }
  2141. else
  2142. {
  2143. // Since PC is not even in the same map, suitable processing is carried out even if it takes.
  2144. // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
  2145. if (MRAND (1000) < MOB_LAZYWARPPERC && md->x0 <= 0
  2146. && md->master_id != 0 && mob_db[md->class].mexp <= 0
  2147. && !(mob_db[md->class].mode & 0x20))
  2148. mob_warp (md, -1, -1, -1, -1);
  2149. }
  2150. md->next_walktime = tick + MPRAND (5000, 10000);
  2151. }
  2152. return 0;
  2153. }
  2154. /*==========================================
  2155. * Negligent processing for mob outside PC field of view (interval timer function)
  2156. *------------------------------------------
  2157. */
  2158. static int mob_ai_lazy (int tid __attribute__ ((unused)), unsigned int tick,
  2159. int id __attribute__ ((unused)),
  2160. int data __attribute__ ((unused)))
  2161. {
  2162. map_foreachiddb (mob_ai_sub_lazy, tick);
  2163. return 0;
  2164. }
  2165. /*==========================================
  2166. * The structure object for item drop with delay
  2167. * Since it is only two being able to pass [ int ] a timer function
  2168. * Data is put in and passed to this structure object.
  2169. *------------------------------------------
  2170. */
  2171. struct delay_item_drop
  2172. {
  2173. int m, x, y;
  2174. int nameid, amount;
  2175. struct map_session_data *first_sd, *second_sd, *third_sd;
  2176. };
  2177. struct delay_item_drop2
  2178. {
  2179. int m, x, y;
  2180. struct item item_data;
  2181. struct map_session_data *first_sd, *second_sd, *third_sd;
  2182. };
  2183. /*==========================================
  2184. * item drop with delay (timer function)
  2185. *------------------------------------------
  2186. */
  2187. static int mob_delay_item_drop (int tid __attribute__ ((unused)),
  2188. unsigned int tick __attribute__ ((unused)),
  2189. int id, int data __attribute__ ((unused)))
  2190. {
  2191. struct delay_item_drop *ditem;
  2192. struct item temp_item;
  2193. nullpo_retr (0, ditem = (struct delay_item_drop *) id);
  2194. memset (&temp_item, 0, sizeof (temp_item));
  2195. temp_item.nameid = ditem->nameid;
  2196. temp_item.amount = ditem->amount;
  2197. temp_item.identify = !itemdb_isequip3 (temp_item.nameid);
  2198. if (battle_config.item_auto_get == 1)
  2199. {
  2200. int flag;
  2201. if (ditem->first_sd
  2202. && (flag =
  2203. pc_additem (ditem->first_sd, &temp_item, ditem->amount)))
  2204. {
  2205. clif_additem (ditem->first_sd, 0, 0, flag);
  2206. map_addflooritem (&temp_item, 1, ditem->m, ditem->x, ditem->y,
  2207. ditem->first_sd, ditem->second_sd,
  2208. ditem->third_sd, 0);
  2209. }
  2210. free (ditem);
  2211. return 0;
  2212. }
  2213. map_addflooritem (&temp_item, 1, ditem->m, ditem->x, ditem->y,
  2214. ditem->first_sd, ditem->second_sd, ditem->third_sd, 0);
  2215. free (ditem);
  2216. return 0;
  2217. }
  2218. /*==========================================
  2219. * item drop (timer function)-lootitem with delay
  2220. *------------------------------------------
  2221. */
  2222. static int mob_delay_item_drop2 (int tid __attribute__ ((unused)),
  2223. unsigned int tick __attribute__ ((unused)),
  2224. int id, int data __attribute__ ((unused)))
  2225. {
  2226. struct delay_item_drop2 *ditem;
  2227. nullpo_retr (0, ditem = (struct delay_item_drop2 *) id);
  2228. if (battle_config.item_auto_get == 1)
  2229. {
  2230. int flag;
  2231. if (ditem->first_sd
  2232. && (flag =
  2233. pc_additem (ditem->first_sd, &ditem->item_data,
  2234. ditem->item_data.amount)))
  2235. {
  2236. clif_additem (ditem->first_sd, 0, 0, flag);
  2237. map_addflooritem (&ditem->item_data, ditem->item_data.amount,
  2238. ditem->m, ditem->x, ditem->y, ditem->first_sd,
  2239. ditem->second_sd, ditem->third_sd, 0);
  2240. }
  2241. free (ditem);
  2242. return 0;
  2243. }
  2244. map_addflooritem (&ditem->item_data, ditem->item_data.amount, ditem->m,
  2245. ditem->x, ditem->y, ditem->first_sd, ditem->second_sd,
  2246. ditem->third_sd, 0);
  2247. free (ditem);
  2248. return 0;
  2249. }
  2250. /*==========================================
  2251. * mob data is erased.
  2252. *------------------------------------------
  2253. */
  2254. int mob_delete (struct mob_data *md)
  2255. {
  2256. nullpo_retr (1, md);
  2257. if (md->bl.prev == NULL)
  2258. return 1;
  2259. mob_changestate (md, MS_DEAD, 0);
  2260. clif_clearchar_area (&md->bl, 1);
  2261. map_delblock (&md->bl);
  2262. if (mob_get_viewclass (md->class) <= 1000)
  2263. clif_clearchar_delay (gettick () + 3000, &md->bl, 0);
  2264. mob_deleteslave (md);
  2265. mob_setdelayspawn (md->bl.id);
  2266. return 0;
  2267. }
  2268. int mob_catch_delete (struct mob_data *md, int type)
  2269. {
  2270. nullpo_retr (1, md);
  2271. if (md->bl.prev == NULL)
  2272. return 1;
  2273. mob_changestate (md, MS_DEAD, 0);
  2274. clif_clearchar_area (&md->bl, type);
  2275. map_delblock (&md->bl);
  2276. mob_setdelayspawn (md->bl.id);
  2277. return 0;
  2278. }
  2279. int mob_timer_delete (int tid __attribute__ ((unused)), unsigned int tick __attribute__ ((unused)), int id, int data __attribute__ ((unused)))
  2280. {
  2281. struct block_list *bl = map_id2bl (id);
  2282. struct mob_data *md;
  2283. nullpo_retr (0, bl);
  2284. md = (struct mob_data *) bl;
  2285. mob_catch_delete (md, 3);
  2286. return 0;
  2287. }
  2288. /*==========================================
  2289. *
  2290. *------------------------------------------
  2291. */
  2292. int mob_deleteslave_sub (struct block_list *bl, va_list ap)
  2293. {
  2294. struct mob_data *md;
  2295. int id;
  2296. nullpo_retr (0, bl);
  2297. nullpo_retr (0, ap);
  2298. nullpo_retr (0, md = (struct mob_data *) bl);
  2299. id = va_arg (ap, int);
  2300. if (md->master_id > 0 && md->master_id == id)
  2301. {
  2302. if (mob_db[md->class].mode & 0x20000)
  2303. {
  2304. md->master_id = 0;
  2305. md->master_dist = 0;
  2306. }
  2307. else
  2308. {
  2309. mob_damage (NULL, md, md->hp, 1);
  2310. }
  2311. }
  2312. return 0;
  2313. }
  2314. /*==========================================
  2315. *
  2316. *------------------------------------------
  2317. */
  2318. int mob_deleteslave (struct mob_data *md)
  2319. {
  2320. nullpo_retr (0, md);
  2321. map_foreachinarea (mob_deleteslave_sub, md->bl.m,
  2322. 0, 0, map[md->bl.m].xs, map[md->bl.m].ys,
  2323. BL_MOB, md->bl.id);
  2324. return 0;
  2325. }
  2326. #define DAMAGE_BONUS_COUNT 6 // max. number of players to account for
  2327. const static double damage_bonus_factor[DAMAGE_BONUS_COUNT + 1] = {
  2328. 1.0, 1.0, 2.0, 2.5, 2.75, 2.9, 3.0
  2329. };
  2330. /*==========================================
  2331. * It is the damage of sd to damage to md.
  2332. *------------------------------------------
  2333. */
  2334. int mob_damage (struct block_list *src, struct mob_data *md, int damage,
  2335. int type)
  2336. {
  2337. nullpo_retr (0, md);
  2338. int i, count, minpos, mindmg;
  2339. struct map_session_data *sd = NULL, *tmpsd[DAMAGELOG_SIZE];
  2340. struct
  2341. {
  2342. struct party *p;
  2343. int id, base_exp, job_exp;
  2344. } pt[DAMAGELOG_SIZE];
  2345. int pnum = 0;
  2346. int mvp_damage, max_hp;
  2347. unsigned int tick = gettick ();
  2348. struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd =
  2349. NULL;
  2350. double temp;
  2351. // double tdmg, temp;
  2352. struct item item;
  2353. int ret;
  2354. int drop_rate;
  2355. int skill, sp;
  2356. nullpo_retr (0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
  2357. if (src && src->id == md->master_id
  2358. && md->mode & MOB_MODE_TURNS_AGAINST_BAD_MASTER)
  2359. {
  2360. /* If the master hits a monster, have the monster turn against him */
  2361. md->master_id = 0;
  2362. md->mode = 0x85; /* Regular war mode */
  2363. md->target_id = src->id;
  2364. md->attacked_id = src->id;
  2365. }
  2366. max_hp = battle_get_max_hp (&md->bl);
  2367. if (src && src->type == BL_PC)
  2368. {
  2369. sd = (struct map_session_data *) src;
  2370. mvp_sd = sd;
  2371. }
  2372. // if(battle_config.battle_log)
  2373. // printf("mob_damage %d %d %d\n",md->hp,max_hp,damage);
  2374. if (md->bl.prev == NULL)
  2375. {
  2376. if (battle_config.error_log == 1)
  2377. printf ("mob_damage : BlockError!!\n");
  2378. return 0;
  2379. }
  2380. if (md->state.state == MS_DEAD || md->hp <= 0)
  2381. {
  2382. if (md->bl.prev != NULL)
  2383. {
  2384. mob_changestate (md, MS_DEAD, 0);
  2385. mobskill_use (md, tick, -1); // It is skill at the time of death.
  2386. clif_clearchar_area (&md->bl, 1);
  2387. map_delblock (&md->bl);
  2388. mob_setdelayspawn (md->bl.id);
  2389. }
  2390. return 0;
  2391. }
  2392. if (md->sc_data[SC_ENDURE].timer == -1)
  2393. mob_stop_walking (md, 3);
  2394. if (damage > max_hp >> 2)
  2395. skill_stop_dancing (&md->bl, 0);
  2396. if (md->hp > max_hp)
  2397. md->hp = max_hp;
  2398. // The amount of overkill rounds to hp.
  2399. if (damage > md->hp)
  2400. damage = md->hp;
  2401. if (!(type & 2))
  2402. {
  2403. if (sd != NULL)
  2404. {
  2405. for (i = 0, minpos = 0, mindmg = 0x7fffffff; i < DAMAGELOG_SIZE;
  2406. i++)
  2407. {
  2408. if (md->dmglog[i].id == sd->bl.id)
  2409. break;
  2410. if (md->dmglog[i].id == 0)
  2411. {
  2412. minpos = i;
  2413. mindmg = 0;
  2414. }
  2415. else if (md->dmglog[i].dmg < mindmg)
  2416. {
  2417. minpos = i;
  2418. mindmg = md->dmglog[i].dmg;
  2419. }
  2420. }
  2421. if (i < DAMAGELOG_SIZE)
  2422. md->dmglog[i].dmg += damage;
  2423. else
  2424. {
  2425. md->dmglog[minpos].id = sd->bl.id;
  2426. md->dmglog[minpos].dmg = damage;
  2427. }
  2428. if (md->attacked_id <= 0 && md->state.special_mob_ai == 0)
  2429. md->attacked_id = sd->bl.id;
  2430. }
  2431. if (src && src->type == BL_MOB
  2432. && ((struct mob_data *) src)->state.special_mob_ai)
  2433. {
  2434. struct mob_data *md2 = (struct mob_data *) src;
  2435. struct block_list *master_bl = map_id2bl (md2->master_id);
  2436. if (master_bl && master_bl->type == BL_PC)
  2437. {
  2438. MAP_LOG_PC (((struct map_session_data *) master_bl),
  2439. "MOB-TO-MOB-DMG FROM MOB%d %d TO MOB%d %d FOR %d",
  2440. md2->bl.id, md2->class, md->bl.id, md->class,
  2441. damage);
  2442. }
  2443. nullpo_retr (0, md2);
  2444. for (i = 0, minpos = 0, mindmg = 0x7fffffff; i < DAMAGELOG_SIZE;
  2445. i++)
  2446. {
  2447. if (md->dmglog[i].id == md2->master_id)
  2448. break;
  2449. if (md->dmglog[i].id == 0)
  2450. {
  2451. minpos = i;
  2452. mindmg = 0;
  2453. }
  2454. else if (md->dmglog[i].dmg < mindmg)
  2455. {
  2456. minpos = i;
  2457. mindmg = md->dmglog[i].dmg;
  2458. }
  2459. }
  2460. if (i < DAMAGELOG_SIZE)
  2461. md->dmglog[i].dmg += damage;
  2462. else
  2463. {
  2464. md->dmglog[minpos].id = md2->master_id;
  2465. md->dmglog[minpos].dmg = damage;
  2466. if (md->attacked_id <= 0 && md->state.special_mob_ai == 0)
  2467. md->attacked_id = md2->master_id;
  2468. }
  2469. }
  2470. }
  2471. md->hp -= damage;
  2472. if (md->class >= 1285 && md->class <= 1287)
  2473. { // guardian hp update [Valaris]
  2474. struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
  2475. if (gc)
  2476. {
  2477. if (md->bl.id == gc->GID0)
  2478. {
  2479. gc->Ghp0 = md->hp;
  2480. if (gc->Ghp0 <= 0)
  2481. {
  2482. guild_castledatasave (gc->castle_id, 10, 0);
  2483. guild_castledatasave (gc->castle_id, 18, 0);
  2484. }
  2485. }
  2486. if (md->bl.id == gc->GID1)
  2487. {
  2488. gc->Ghp1 = md->hp;
  2489. if (gc->Ghp1 <= 0)
  2490. {
  2491. guild_castledatasave (gc->castle_id, 11, 0);
  2492. guild_castledatasave (gc->castle_id, 19, 0);
  2493. }
  2494. }
  2495. if (md->bl.id == gc->GID2)
  2496. {
  2497. gc->Ghp2 = md->hp;
  2498. if (gc->Ghp2 <= 0)
  2499. {
  2500. guild_castledatasave (gc->castle_id, 12, 0);
  2501. guild_castledatasave (gc->castle_id, 20, 0);
  2502. }
  2503. }
  2504. if (md->bl.id == gc->GID3)
  2505. {
  2506. gc->Ghp3 = md->hp;
  2507. if (gc->Ghp3 <= 0)
  2508. {
  2509. guild_castledatasave (gc->castle_id, 13, 0);
  2510. guild_castledatasave (gc->castle_id, 21, 0);
  2511. }
  2512. }
  2513. if (md->bl.id == gc->GID4)
  2514. {
  2515. gc->Ghp4 = md->hp;
  2516. if (gc->Ghp4 <= 0)
  2517. {
  2518. guild_castledatasave (gc->castle_id, 14, 0);
  2519. guild_castledatasave (gc->castle_id, 22, 0);
  2520. }
  2521. }
  2522. if (md->bl.id == gc->GID5)
  2523. {
  2524. gc->Ghp5 = md->hp;
  2525. if (gc->Ghp5 <= 0)
  2526. {
  2527. guild_castledatasave (gc->castle_id, 15, 0);
  2528. guild_castledatasave (gc->castle_id, 23, 0);
  2529. }
  2530. }
  2531. if (md->bl.id == gc->GID6)
  2532. {
  2533. gc->Ghp6 = md->hp;
  2534. if (gc->Ghp6 <= 0)
  2535. {
  2536. guild_castledatasave (gc->castle_id, 16, 0);
  2537. guild_castledatasave (gc->castle_id, 24, 0);
  2538. }
  2539. }
  2540. if (md->bl.id == gc->GID7)
  2541. {
  2542. gc->Ghp7 = md->hp;
  2543. if (gc->Ghp7 <= 0)
  2544. {
  2545. guild_castledatasave (gc->castle_id, 17, 0);
  2546. guild_castledatasave (gc->castle_id, 25, 0);
  2547. }
  2548. }
  2549. }
  2550. } // end addition [Valaris]
  2551. if (md->option & 2)
  2552. skill_status_change_end (&md->bl, SC_HIDING, -1);
  2553. if (md->option & 4)
  2554. skill_status_change_end (&md->bl, SC_CLOAKING, -1);
  2555. if (md->state.special_mob_ai == 2)
  2556. { //スフィアーマイン
  2557. int skillidx = 0;
  2558. if ((skillidx =
  2559. mob_skillid2skillidx (md->class, NPC_SELFDESTRUCTION2)) >= 0)
  2560. {
  2561. md->mode |= 0x1;
  2562. md->next_walktime = tick;
  2563. mobskill_use_id (md, &md->bl, skillidx); //自爆詠唱開始
  2564. md->state.special_mob_ai++;
  2565. }
  2566. }
  2567. if (md->hp > 0)
  2568. {
  2569. return 0;
  2570. }
  2571. MAP_LOG ("MOB%d DEAD", md->bl.id);
  2572. // ----- ここから死亡処理 -----
  2573. map_freeblock_lock ();
  2574. mob_changestate (md, MS_DEAD, 0);
  2575. mobskill_use (md, tick, -1); // 死亡時スキル
  2576. memset (tmpsd, 0, sizeof (tmpsd));
  2577. memset (pt, 0, sizeof (pt));
  2578. max_hp = battle_get_max_hp (&md->bl);
  2579. if (src && src->type == BL_MOB)
  2580. mob_unlocktarget ((struct mob_data *) src, tick);
  2581. /* ソウルドレイン */
  2582. if (sd && (skill = pc_checkskill (sd, HW_SOULDRAIN)) > 0)
  2583. {
  2584. clif_skill_nodamage (src, &md->bl, HW_SOULDRAIN, skill, 1);
  2585. sp = (battle_get_lv (&md->bl)) * (65 + 15 * skill) / 100;
  2586. if (sd->status.sp + sp > sd->status.max_sp)
  2587. sp = sd->status.max_sp - sd->status.sp;
  2588. sd->status.sp += sp;
  2589. clif_heal (sd->fd, SP_SP, sp);
  2590. }
  2591. // map外に消えた人は計算から除くので
  2592. // overkill分は無いけどsumはmax_hpとは違う
  2593. // tdmg = 0;
  2594. for (i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE; i++)
  2595. {
  2596. if (md->dmglog[i].id == 0)
  2597. continue;
  2598. tmpsd[i] = map_id2sd (md->dmglog[i].id);
  2599. if (tmpsd[i] == NULL)
  2600. continue;
  2601. count++;
  2602. if (tmpsd[i]->bl.m != md->bl.m || pc_isdead (tmpsd[i]))
  2603. continue;
  2604. // tdmg += (double) md->dmglog[i].dmg;
  2605. if (mvp_damage < md->dmglog[i].dmg)
  2606. {
  2607. third_sd = second_sd;
  2608. second_sd = mvp_sd;
  2609. mvp_sd = tmpsd[i];
  2610. mvp_damage = md->dmglog[i].dmg;
  2611. }
  2612. }
  2613. // [MouseJstr]
  2614. if ((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1))
  2615. {
  2616. /*
  2617. if ((double) max_hp < tdmg)
  2618. dmg_rate = ((double) max_hp) / tdmg;
  2619. else
  2620. dmg_rate = 1;
  2621. */
  2622. // 経験値の分配
  2623. for (i = 0; i < DAMAGELOG_SIZE; i++)
  2624. {
  2625. int pid, base_exp, job_exp, flag = 1;
  2626. double per;
  2627. struct party *p;
  2628. if (tmpsd[i] == NULL || tmpsd[i]->bl.m != md->bl.m)
  2629. continue;
  2630. /* jAthena's exp formula
  2631. per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
  2632. temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
  2633. base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
  2634. if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1;
  2635. if(base_exp < 0) base_exp = 0;
  2636. temp = ((double)mob_db[md->class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
  2637. job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
  2638. if(mob_db[md->class].job_exp > 0 && job_exp < 1) job_exp = 1;
  2639. if(job_exp < 0) job_exp = 0;
  2640. */
  2641. //eAthena's exp formula rather than jAthena's
  2642. // per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
  2643. // [Fate] The above is the old formula. We do a more involved computation below.
  2644. if (max_hp)
  2645. per = (double) md->dmglog[i].dmg * 256 / (double) max_hp; // 256 = 100% of the score
  2646. else
  2647. per = 1;
  2648. per *= damage_bonus_factor[count > DAMAGE_BONUS_COUNT ? DAMAGE_BONUS_COUNT : count]; // Bonus for party attack
  2649. if (per > 512)
  2650. per = 512; // [Fate] Retained from before. The maximum a single individual can get is double the original value.
  2651. if (per < 1)
  2652. per = 1;
  2653. base_exp =
  2654. ((mob_db[md->class].base_exp *
  2655. md->stats[MOB_XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256;
  2656. if (base_exp < 1)
  2657. base_exp = 1;
  2658. if (sd && md && battle_config.pk_mode == 1
  2659. && (mob_db[md->class].lv - sd->status.base_level >= 20))
  2660. {
  2661. base_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris]
  2662. }
  2663. if (md->state.special_mob_ai >= 1
  2664. && battle_config.alchemist_summon_reward != 1)
  2665. base_exp = 0; // Added [Valaris]
  2666. job_exp = mob_db[md->class].job_exp * per / 256;
  2667. if (job_exp < 1)
  2668. job_exp = 1;
  2669. if (sd && md && battle_config.pk_mode == 1
  2670. && (mob_db[md->class].lv - sd->status.base_level >= 20))
  2671. {
  2672. job_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris]
  2673. }
  2674. if (md->state.special_mob_ai >= 1
  2675. && battle_config.alchemist_summon_reward != 1)
  2676. job_exp = 0; // Added [Valaris]
  2677. if ((pid = tmpsd[i]->status.party_id) > 0)
  2678. { // パーティに入っている
  2679. int j = 0;
  2680. for (j = 0; j < pnum; j++) // 公平パーティリストにいるかどうか
  2681. if (pt[j].id == pid)
  2682. break;
  2683. if (j == pnum)
  2684. { // いないときは公平かどうか確認
  2685. if ((p = party_search (pid)) != NULL && p->exp != 0)
  2686. {
  2687. pt[pnum].id = pid;
  2688. pt[pnum].p = p;
  2689. pt[pnum].base_exp = base_exp;
  2690. pt[pnum].job_exp = job_exp;
  2691. pnum++;
  2692. flag = 0;
  2693. }
  2694. }
  2695. else
  2696. { // いるときは公平
  2697. pt[j].base_exp += base_exp;
  2698. pt[j].job_exp += job_exp;
  2699. flag = 0;
  2700. }
  2701. }
  2702. if (flag) // 各自所得
  2703. pc_gainexp (tmpsd[i], base_exp, job_exp);
  2704. }
  2705. // 公平分配
  2706. for (i = 0; i < pnum; i++)
  2707. party_exp_share (pt[i].p, md->bl.m, pt[i].base_exp,
  2708. pt[i].job_exp);
  2709. // item drop
  2710. if (!(type & 1))
  2711. {
  2712. for (i = 0; i < 8; i++)
  2713. {
  2714. struct delay_item_drop *ditem;
  2715. int drop_rate;
  2716. if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris]
  2717. break; // End
  2718. if (mob_db[md->class].dropitem[i].nameid <= 0)
  2719. continue;
  2720. drop_rate = mob_db[md->class].dropitem[i].p;
  2721. if (drop_rate <= 0 && battle_config.drop_rate0item == 1)
  2722. drop_rate = 1;
  2723. if (battle_config.drops_by_luk > 0 && sd && md)
  2724. drop_rate += (sd->status.luk * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris]
  2725. if (sd && md && battle_config.pk_mode == 1
  2726. && (mob_db[md->class].lv - sd->status.base_level >= 20))
  2727. drop_rate *= 1.25; // pk_mode increase drops if 20 level difference [Valaris]
  2728. if (drop_rate <= MRAND (10000))
  2729. continue;
  2730. ditem =
  2731. (struct delay_item_drop *) aCalloc (1,
  2732. sizeof (struct
  2733. delay_item_drop));
  2734. ditem->nameid = mob_db[md->class].dropitem[i].nameid;
  2735. ditem->amount = 1;
  2736. ditem->m = md->bl.m;
  2737. ditem->x = md->bl.x;
  2738. ditem->y = md->bl.y;
  2739. ditem->first_sd = mvp_sd;
  2740. ditem->second_sd = second_sd;
  2741. ditem->third_sd = third_sd;
  2742. add_timer (tick + 500 + i, mob_delay_item_drop, (int) ditem,
  2743. 0);
  2744. }
  2745. if (sd && sd->state.attack_type == BF_WEAPON)
  2746. {
  2747. for (i = 0; i < sd->monster_drop_item_count; i++)
  2748. {
  2749. struct delay_item_drop *ditem;
  2750. int race = battle_get_race (&md->bl);
  2751. if (sd->monster_drop_itemid[i] <= 0)
  2752. continue;
  2753. if (sd->monster_drop_race[i] & (1 << race) ||
  2754. (mob_db[md->class].mode & 0x20
  2755. && sd->monster_drop_race[i] & 1 << 10)
  2756. || (!(mob_db[md->class].mode & 0x20)
  2757. && sd->monster_drop_race[i] & 1 << 11))
  2758. {
  2759. if (sd->monster_drop_itemrate[i] <= MRAND (10000))
  2760. continue;
  2761. ditem =
  2762. (struct delay_item_drop *) aCalloc (1,
  2763. sizeof (struct
  2764. delay_item_drop));
  2765. ditem->nameid = sd->monster_drop_itemid[i];
  2766. ditem->amount = 1;
  2767. ditem->m = md->bl.m;
  2768. ditem->x = md->bl.x;
  2769. ditem->y = md->bl.y;
  2770. ditem->first_sd = mvp_sd;
  2771. ditem->second_sd = second_sd;
  2772. ditem->third_sd = third_sd;
  2773. add_timer (tick + 520 + i, mob_delay_item_drop,
  2774. (int) ditem, 0);
  2775. }
  2776. }
  2777. if (sd->get_zeny_num > 0)
  2778. pc_getzeny (sd,
  2779. mob_db[md->class].lv * 10 +
  2780. MRAND ((sd->get_zeny_num + 1)));
  2781. }
  2782. if (md->lootitem)
  2783. {
  2784. for (i = 0; i < md->lootitem_count; i++)
  2785. {
  2786. struct delay_item_drop2 *ditem;
  2787. ditem =
  2788. (struct delay_item_drop2 *) aCalloc (1,
  2789. sizeof (struct
  2790. delay_item_drop2));
  2791. memcpy (&ditem->item_data, &md->lootitem[i],
  2792. sizeof (md->lootitem[0]));
  2793. ditem->m = md->bl.m;
  2794. ditem->x = md->bl.x;
  2795. ditem->y = md->bl.y;
  2796. ditem->first_sd = mvp_sd;
  2797. ditem->second_sd = second_sd;
  2798. ditem->third_sd = third_sd;
  2799. add_timer (tick + 540 + i, mob_delay_item_drop2,
  2800. (int) ditem, 0);
  2801. }
  2802. }
  2803. }
  2804. // mvp処理
  2805. if (mvp_sd && mob_db[md->class].mexp > 0)
  2806. {
  2807. int j;
  2808. int mexp = battle_get_mexp (&md->bl);
  2809. temp =
  2810. ((double) mexp * (double) battle_config.mvp_exp_rate *
  2811. (9. + (double) count) / 1000.);
  2812. mexp = (temp > 2147483647.) ? 0x7fffffff : (int) temp;
  2813. if (mexp < 1)
  2814. mexp = 1;
  2815. clif_mvp_effect (mvp_sd); // エフェクト
  2816. clif_mvp_exp (mvp_sd, mexp);
  2817. pc_gainexp (mvp_sd, mexp, 0);
  2818. for (j = 0; j < 3; j++)
  2819. {
  2820. i = MRAND (3);
  2821. if (mob_db[md->class].mvpitem[i].nameid <= 0)
  2822. continue;
  2823. drop_rate = mob_db[md->class].mvpitem[i].p;
  2824. if (drop_rate <= 0 && battle_config.drop_rate0item == 1)
  2825. drop_rate = 1;
  2826. if (drop_rate < battle_config.item_drop_mvp_min)
  2827. drop_rate = battle_config.item_drop_mvp_min;
  2828. if (drop_rate > battle_config.item_drop_mvp_max)
  2829. drop_rate = battle_config.item_drop_mvp_max;
  2830. if (drop_rate <= MRAND (10000))
  2831. continue;
  2832. memset (&item, 0, sizeof (item));
  2833. item.nameid = mob_db[md->class].mvpitem[i].nameid;
  2834. item.identify = !itemdb_isequip3 (item.nameid);
  2835. clif_mvp_item (mvp_sd, item.nameid);
  2836. if (mvp_sd->weight * 2 > mvp_sd->max_weight)
  2837. map_addflooritem (&item, 1, mvp_sd->bl.m, mvp_sd->bl.x,
  2838. mvp_sd->bl.y, mvp_sd, second_sd,
  2839. third_sd, 1);
  2840. else if ((ret = pc_additem (mvp_sd, &item, 1)))
  2841. {
  2842. clif_additem (sd, 0, 0, ret);
  2843. map_addflooritem (&item, 1, mvp_sd->bl.m, mvp_sd->bl.x,
  2844. mvp_sd->bl.y, mvp_sd, second_sd,
  2845. third_sd, 1);
  2846. }
  2847. break;
  2848. }
  2849. }
  2850. } // [MouseJstr]
  2851. // <Agit> NPC Event [OnAgitBreak]
  2852. if (md->npc_event[0]
  2853. && strcmp (((md->npc_event) + strlen (md->npc_event) - 13),
  2854. "::OnAgitBreak") == 0)
  2855. {
  2856. printf ("MOB.C: Run NPC_Event[OnAgitBreak].\n");
  2857. if (agit_flag == 1) //Call to Run NPC_Event[OnAgitBreak]
  2858. guild_agit_break (md);
  2859. }
  2860. // SCRIPT実行
  2861. if (md->npc_event[0])
  2862. {
  2863. if (sd == NULL)
  2864. {
  2865. if (mvp_sd != NULL)
  2866. sd = mvp_sd;
  2867. else
  2868. {
  2869. struct map_session_data *tmpsd;
  2870. int i;
  2871. for (i = 0; i < fd_max; i++)
  2872. {
  2873. if (session[i] && (tmpsd = session[i]->session_data)
  2874. && tmpsd->state.auth)
  2875. {
  2876. if (md->bl.m == tmpsd->bl.m)
  2877. {
  2878. sd = tmpsd;
  2879. break;
  2880. }
  2881. }
  2882. }
  2883. }
  2884. }
  2885. if (sd)
  2886. npc_event (sd, md->npc_event, 0);
  2887. }
  2888. clif_clearchar_area (&md->bl, 1);
  2889. map_delblock (&md->bl);
  2890. if (mob_get_viewclass (md->class) <= 1000)
  2891. clif_clearchar_delay (tick + 3000, &md->bl, 0);
  2892. mob_deleteslave (md);
  2893. mob_setdelayspawn (md->bl.id);
  2894. map_freeblock_unlock ();
  2895. return 0;
  2896. }
  2897. /*==========================================
  2898. *
  2899. *------------------------------------------
  2900. */
  2901. int mob_class_change (struct mob_data *md, int *value)
  2902. {
  2903. unsigned int tick = gettick ();
  2904. int i, c, hp_rate, max_hp, class, count = 0;
  2905. nullpo_retr (0, md);
  2906. nullpo_retr (0, value);
  2907. if (value[0] <= 1000 || value[0] > 2000)
  2908. return 0;
  2909. if (md->bl.prev == NULL)
  2910. return 0;
  2911. while (count < 5 && value[count] > 1000 && value[count] <= 2000)
  2912. count++;
  2913. if (count < 1)
  2914. return 0;
  2915. class = value[MRAND (count)];
  2916. if (class <= 1000 || class > 2000)
  2917. return 0;
  2918. max_hp = battle_get_max_hp (&md->bl);
  2919. hp_rate = md->hp * 100 / max_hp;
  2920. clif_mob_class_change (md, class);
  2921. md->class = class;
  2922. max_hp = battle_get_max_hp (&md->bl);
  2923. if (battle_config.monster_class_change_full_recover == 1)
  2924. {
  2925. md->hp = max_hp;
  2926. memset (md->dmglog, 0, sizeof (md->dmglog));
  2927. }
  2928. else
  2929. md->hp = max_hp * hp_rate / 100;
  2930. if (md->hp > max_hp)
  2931. md->hp = max_hp;
  2932. else if (md->hp < 1)
  2933. md->hp = 1;
  2934. memcpy (md->name, mob_db[class].jname, 24);
  2935. memset (&md->state, 0, sizeof (md->state));
  2936. md->attacked_id = 0;
  2937. md->target_id = 0;
  2938. md->move_fail_count = 0;
  2939. md->stats[MOB_SPEED] = mob_db[md->class].speed;
  2940. md->def_ele = mob_db[md->class].element;
  2941. mob_changestate (md, MS_IDLE, 0);
  2942. skill_castcancel (&md->bl, 0);
  2943. md->state.skillstate = MSS_IDLE;
  2944. md->last_thinktime = tick;
  2945. md->next_walktime = tick + MPRAND (5000, 50);
  2946. md->attackabletime = tick;
  2947. md->canmove_tick = tick;
  2948. md->sg_count = 0;
  2949. for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
  2950. md->skilldelay[i] = c;
  2951. md->skillid = 0;
  2952. md->skilllv = 0;
  2953. if (md->lootitem == NULL && mob_db[class].mode & 0x02)
  2954. md->lootitem =
  2955. (struct item *) aCalloc (LOOTITEM_SIZE, sizeof (struct item));
  2956. skill_clear_unitgroup (&md->bl);
  2957. skill_cleartimerskill (&md->bl);
  2958. clif_clearchar_area (&md->bl, 0);
  2959. clif_spawnmob (md);
  2960. return 0;
  2961. }
  2962. /*==========================================
  2963. * mob回復
  2964. *------------------------------------------
  2965. */
  2966. int mob_heal (struct mob_data *md, int heal)
  2967. {
  2968. int max_hp = battle_get_max_hp (&md->bl);
  2969. nullpo_retr (0, md);
  2970. md->hp += heal;
  2971. if (max_hp < md->hp)
  2972. md->hp = max_hp;
  2973. if (md->class >= 1285 && md->class <= 1287)
  2974. { // guardian hp update [Valaris]
  2975. struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
  2976. if (gc)
  2977. {
  2978. if (md->bl.id == gc->GID0)
  2979. gc->Ghp0 = md->hp;
  2980. if (md->bl.id == gc->GID1)
  2981. gc->Ghp1 = md->hp;
  2982. if (md->bl.id == gc->GID2)
  2983. gc->Ghp2 = md->hp;
  2984. if (md->bl.id == gc->GID3)
  2985. gc->Ghp3 = md->hp;
  2986. if (md->bl.id == gc->GID4)
  2987. gc->Ghp4 = md->hp;
  2988. if (md->bl.id == gc->GID5)
  2989. gc->Ghp5 = md->hp;
  2990. if (md->bl.id == gc->GID6)
  2991. gc->Ghp6 = md->hp;
  2992. if (md->bl.id == gc->GID7)
  2993. gc->Ghp7 = md->hp;
  2994. }
  2995. } // end addition [Valaris]
  2996. return 0;
  2997. }
  2998. /*==========================================
  2999. * Added by RoVeRT
  3000. *------------------------------------------
  3001. */
  3002. int mob_warpslave_sub (struct block_list *bl, va_list ap)
  3003. {
  3004. nullpo_retr (0, bl);
  3005. nullpo_retr (0, ap);
  3006. struct mob_data *md = (struct mob_data *) bl;
  3007. int id, x, y;
  3008. id = va_arg (ap, int);
  3009. x = va_arg (ap, int);
  3010. y = va_arg (ap, int);
  3011. if (md->master_id == id)
  3012. {
  3013. mob_warp (md, -1, x, y, 2);
  3014. }
  3015. return 0;
  3016. }
  3017. /*==========================================
  3018. * Added by RoVeRT
  3019. *------------------------------------------
  3020. */
  3021. int mob_warpslave (struct mob_data *md, int x, int y)
  3022. {
  3023. nullpo_retr (0, md);
  3024. //printf("warp slave\n");
  3025. map_foreachinarea (mob_warpslave_sub, md->bl.m,
  3026. x - AREA_SIZE, y - AREA_SIZE,
  3027. x + AREA_SIZE, y + AREA_SIZE, BL_MOB,
  3028. md->bl.id, md->bl.x, md->bl.y);
  3029. return 0;
  3030. }
  3031. /*==========================================
  3032. * mobワープ
  3033. *------------------------------------------
  3034. */
  3035. int mob_warp (struct mob_data *md, int m, int x, int y, int type)
  3036. {
  3037. int i = 0, c, xs = 0, ys = 0, bx = x, by = y;
  3038. nullpo_retr (0, md);
  3039. if (md->bl.prev == NULL)
  3040. return 0;
  3041. if (m < 0)
  3042. m = md->bl.m;
  3043. if (type >= 0)
  3044. {
  3045. if (map[md->bl.m].flag.monster_noteleport)
  3046. return 0;
  3047. clif_clearchar_area (&md->bl, type);
  3048. }
  3049. skill_unit_out_all (&md->bl, gettick (), 1);
  3050. map_delblock (&md->bl);
  3051. if (bx > 0 && by > 0)
  3052. { // 位置指定の場合周囲9セルを探索
  3053. xs = ys = 9;
  3054. }
  3055. while ((x < 0 || y < 0 || ((c = read_gat (m, x, y)) == 1 || c == 5))
  3056. && (i++) < 1000)
  3057. {
  3058. if (xs > 0 && ys > 0 && i < 250)
  3059. { // 指定位置付近の探索
  3060. x = MPRAND (bx, xs) - xs / 2;
  3061. y = MPRAND (by, ys) - ys / 2;
  3062. }
  3063. else
  3064. { // 完全ランダム探索
  3065. x = MPRAND (1, (map[m].xs - 2));
  3066. y = MPRAND (1, (map[m].ys - 2));
  3067. }
  3068. }
  3069. md->dir = 0;
  3070. if (i < 1000)
  3071. {
  3072. md->bl.x = md->to_x = x;
  3073. md->bl.y = md->to_y = y;
  3074. md->bl.m = m;
  3075. }
  3076. else
  3077. {
  3078. m = md->bl.m;
  3079. if (battle_config.error_log == 1)
  3080. printf ("MOB %d warp failed, class = %d\n", md->bl.id, md->class);
  3081. }
  3082. md->target_id = 0; // タゲを解除する
  3083. md->state.targettype = NONE_ATTACKABLE;
  3084. md->attacked_id = 0;
  3085. md->state.skillstate = MSS_IDLE;
  3086. mob_changestate (md, MS_IDLE, 0);
  3087. if (type > 0 && i == 1000)
  3088. {
  3089. if (battle_config.battle_log == 1)
  3090. printf ("MOB %d warp to (%d,%d), class = %d\n", md->bl.id, x, y,
  3091. md->class);
  3092. }
  3093. map_addblock (&md->bl);
  3094. if (type > 0)
  3095. {
  3096. clif_spawnmob (md);
  3097. mob_warpslave (md, md->bl.x, md->bl.y);
  3098. }
  3099. return 0;
  3100. }
  3101. /*==========================================
  3102. * 画面内の取り巻きの数計算用(foreachinarea)
  3103. *------------------------------------------
  3104. */
  3105. int mob_countslave_sub (struct block_list *bl, va_list ap)
  3106. {
  3107. nullpo_retr (0, bl);
  3108. nullpo_retr (0, ap);
  3109. int id, *c;
  3110. struct mob_data *md;
  3111. id = va_arg (ap, int);
  3112. nullpo_retr (0, ap);
  3113. nullpo_retr (0, c = va_arg (ap, int *));
  3114. nullpo_retr (0, md = (struct mob_data *) bl);
  3115. if (md->master_id == id)
  3116. (*c)++;
  3117. return 0;
  3118. }
  3119. /*==========================================
  3120. * 画面内の取り巻きの数計算
  3121. *------------------------------------------
  3122. */
  3123. int mob_countslave (struct mob_data *md)
  3124. {
  3125. int c = 0;
  3126. nullpo_retr (0, md);
  3127. map_foreachinarea (mob_countslave_sub, md->bl.m,
  3128. 0, 0, map[md->bl.m].xs - 1, map[md->bl.m].ys - 1,
  3129. BL_MOB, md->bl.id, &c);
  3130. return c;
  3131. }
  3132. static int mob_find_slave (struct block_list *bl, va_list ap)
  3133. {
  3134. struct mob_data *tmd;
  3135. struct mob_data *md;
  3136. int class;
  3137. int *amount;
  3138. nullpo_retr (0, bl);
  3139. nullpo_retr (0, ap);
  3140. nullpo_retr (0, tmd = (struct mob_data *) bl);
  3141. nullpo_retr (0, md = va_arg (ap, struct mob_data *));
  3142. nullpo_retr (0, class = va_arg (ap, int));
  3143. nullpo_retr (0, amount = va_arg (ap, int*));
  3144. if ((*amount) <= 0)
  3145. return 1;
  3146. if (!tmd->master_id && tmd->class == class && mob_db[tmd->class].mode & 0x40000)
  3147. {
  3148. tmd->master_id = md->bl.id;
  3149. tmd->master_dist = distance (md->bl.x, md->bl.y, tmd->bl.x, tmd->bl.y);
  3150. (*amount) --;
  3151. if ((*amount) <= 0)
  3152. return 1;
  3153. }
  3154. return 0;
  3155. }
  3156. /*==========================================
  3157. * 手下MOB召喚
  3158. *------------------------------------------
  3159. */
  3160. int mob_summonslave (struct mob_data *md2, int *value, int amount, int flag)
  3161. {
  3162. struct mob_data *md;
  3163. int bx, by, m, count = 0, class, k, a = amount;
  3164. nullpo_retr (0, md2);
  3165. nullpo_retr (0, value);
  3166. bx = md2->bl.x;
  3167. by = md2->bl.y;
  3168. m = md2->bl.m;
  3169. if (value[0] <= 1000 || value[0] > 2000) // 値が異常なら召喚を止める
  3170. return 0;
  3171. while (count < 5 && value[count] > 1000 && value[count] <= 2000)
  3172. count++;
  3173. if (count < 1)
  3174. return 0;
  3175. if (mob_countslave (md2) > battle_config.mob_skill_spawn_limit)
  3176. return 0;
  3177. for (k = 0; k < count; k++)
  3178. {
  3179. amount = a;
  3180. class = value[k];
  3181. if (class <= 1000 || class > 2000)
  3182. continue;
  3183. if (flag)
  3184. {
  3185. map_foreachinarea_cond (mob_find_slave, md2->bl.m,
  3186. md2->bl.x - 13, md2->bl.y - 13,
  3187. md2->bl.x + 13, md2->bl.y + 13,
  3188. BL_MOB, md2, class, &amount);
  3189. }
  3190. for (; amount > 0; amount--)
  3191. {
  3192. int x = 0, y = 0, c = 0, i = 0;
  3193. md = (struct mob_data *) aCalloc (1, sizeof (struct mob_data));
  3194. md->master_id = 0;
  3195. if (mob_db[class].mode & 0x02)
  3196. md->lootitem =
  3197. (struct item *) aCalloc (LOOTITEM_SIZE,
  3198. sizeof (struct item));
  3199. else
  3200. md->lootitem = NULL;
  3201. while ((x <= 0 || y <= 0 || (c = map_getcell (m, x, y)) == 1
  3202. || c == 5) && (i++) < 100)
  3203. {
  3204. x = MPRAND (bx, 9) - 4;
  3205. y = MPRAND (by, 9) - 4;
  3206. }
  3207. if (i >= 100)
  3208. {
  3209. x = bx;
  3210. y = by;
  3211. }
  3212. mob_spawn_dataset (md, "--ja--", class);
  3213. md->bl.prev = NULL;
  3214. md->bl.next = NULL;
  3215. md->bl.m = m;
  3216. md->bl.x = x;
  3217. md->bl.y = y;
  3218. md->m = m;
  3219. md->x0 = x;
  3220. md->y0 = y;
  3221. md->xs = 0;
  3222. md->ys = 0;
  3223. md->stats[MOB_SPEED] = md2->stats[MOB_SPEED];
  3224. md->spawndelay1 = -1; // 一度のみフラグ
  3225. md->spawndelay2 = -1; // 一度のみフラグ
  3226. memset (md->npc_event, 0, sizeof (md->npc_event));
  3227. md->bl.type = BL_MOB;
  3228. map_addiddb (&md->bl);
  3229. mob_spawn (md->bl.id);
  3230. clif_skill_nodamage (&md->bl, &md->bl,
  3231. (flag) ? NPC_SUMMONSLAVE : NPC_SUMMONMONSTER,
  3232. a, 1);
  3233. if (flag)
  3234. md->master_id = md2->bl.id;
  3235. }
  3236. }
  3237. return 0;
  3238. }
  3239. /*==========================================
  3240. * 自分をロックしているPCの数を数える(foreachclient)
  3241. *------------------------------------------
  3242. */
  3243. static int mob_counttargeted_sub (struct block_list *bl, va_list ap)
  3244. {
  3245. int id, *c, target_lv;
  3246. struct block_list *src;
  3247. nullpo_retr (0, ap);
  3248. id = va_arg (ap, int);
  3249. nullpo_retr (0, bl);
  3250. nullpo_retr (0, c = va_arg (ap, int *));
  3251. src = va_arg (ap, struct block_list *);
  3252. target_lv = va_arg (ap, int);
  3253. if (id == bl->id || (src && id == src->id))
  3254. return 0;
  3255. if (bl->type == BL_PC)
  3256. {
  3257. struct map_session_data *sd = (struct map_session_data *) bl;
  3258. if (sd && sd->attacktarget == id && sd->attacktimer != -1
  3259. && sd->attacktarget_lv >= target_lv)
  3260. (*c)++;
  3261. }
  3262. else if (bl->type == BL_MOB)
  3263. {
  3264. struct mob_data *md = (struct mob_data *) bl;
  3265. if (md && md->target_id == id && md->timer != -1
  3266. && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
  3267. (*c)++;
  3268. }
  3269. return 0;
  3270. }
  3271. /*==========================================
  3272. * 自分をロックしているPCの数を数える
  3273. *------------------------------------------
  3274. */
  3275. int mob_counttargeted (struct mob_data *md, struct block_list *src,
  3276. int target_lv)
  3277. {
  3278. int c = 0;
  3279. nullpo_retr (0, md);
  3280. map_foreachinarea (mob_counttargeted_sub, md->bl.m,
  3281. md->bl.x - AREA_SIZE, md->bl.y - AREA_SIZE,
  3282. md->bl.x + AREA_SIZE, md->bl.y + AREA_SIZE, 0,
  3283. md->bl.id, &c, src, target_lv);
  3284. return c;
  3285. }
  3286. /*==========================================
  3287. *MOBskillから該当skillidのskillidxを返す
  3288. *------------------------------------------
  3289. */
  3290. int mob_skillid2skillidx (int class, int skillid)
  3291. {
  3292. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  3293. return -1;
  3294. int i;
  3295. struct mob_skill *ms = mob_db[class].skill;
  3296. if (ms == NULL)
  3297. return -1;
  3298. for (i = 0; i < mob_db[class].maxskill; i++)
  3299. {
  3300. if (ms[i].skill_id == skillid)
  3301. return i;
  3302. }
  3303. return -1;
  3304. }
  3305. //
  3306. // MOBスキル
  3307. //
  3308. /*==========================================
  3309. * スキル使用(詠唱完了、ID指定)
  3310. *------------------------------------------
  3311. */
  3312. int mobskill_castend_id (int tid, unsigned int tick, int id, int data __attribute__ ((unused)))
  3313. {
  3314. struct mob_data *md = NULL;
  3315. struct block_list *bl;
  3316. struct block_list *mbl;
  3317. int range;
  3318. if ((mbl = map_id2bl (id)) == NULL) //詠唱したMobがもういないというのは良くある正常処理
  3319. return 0;
  3320. if ((md = (struct mob_data *) mbl) == NULL)
  3321. {
  3322. printf ("mobskill_castend_id nullpo mbl->id:%d\n", mbl->id);
  3323. return 0;
  3324. }
  3325. if (md->bl.type != BL_MOB || md->bl.prev == NULL)
  3326. return 0;
  3327. if (md->skilltimer != tid) // タイマIDの確認
  3328. return 0;
  3329. md->skilltimer = -1;
  3330. //沈黙や状態異常など
  3331. if (md->sc_data)
  3332. {
  3333. if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
  3334. || md->sc_data[SC_ROKISWEIL].timer != -1
  3335. || md->sc_data[SC_STEELBODY].timer != -1)
  3336. return 0;
  3337. if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  3338. return 0;
  3339. if (md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  3340. return 0;
  3341. if (md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  3342. return 0;
  3343. }
  3344. if (md->skillid != NPC_EMOTION)
  3345. md->last_thinktime = tick + battle_get_adelay (&md->bl);
  3346. if ((bl = map_id2bl (md->skilltarget)) == NULL || bl->prev == NULL)
  3347. { //スキルターゲットが存在しない
  3348. //printf("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了
  3349. return 0;
  3350. }
  3351. if (md->bl.m != bl->m)
  3352. return 0;
  3353. if (md->skillid == PR_LEXAETERNA)
  3354. {
  3355. struct status_change *sc_data = battle_get_sc_data (bl);
  3356. if (sc_data
  3357. && (sc_data[SC_FREEZE].timer != -1
  3358. || (sc_data[SC_STONE].timer != -1
  3359. && sc_data[SC_STONE].val2 == 0)))
  3360. return 0;
  3361. }
  3362. else if (md->skillid == RG_BACKSTAP)
  3363. {
  3364. int dir = map_calc_dir (&md->bl, bl->x, bl->y), t_dir =
  3365. battle_get_dir (bl);
  3366. int dist = distance (md->bl.x, md->bl.y, bl->x, bl->y);
  3367. if (bl->type != BL_SKILL && (dist == 0 || map_check_dir (dir, t_dir)))
  3368. return 0;
  3369. }
  3370. if (((skill_get_inf (md->skillid) & 1) || (skill_get_inf2 (md->skillid) & 4)) && // 彼我敵対関係チェック
  3371. battle_check_target (&md->bl, bl, BCT_ENEMY) <= 0)
  3372. return 0;
  3373. range = skill_get_range (md->skillid, md->skilllv);
  3374. if (range < 0)
  3375. range = battle_get_range (&md->bl) - (range + 1);
  3376. if (range + battle_config.mob_skill_add_range <
  3377. distance (md->bl.x, md->bl.y, bl->x, bl->y))
  3378. return 0;
  3379. md->skilldelay[md->skillidx] = tick;
  3380. if (battle_config.mob_skill_log == 1)
  3381. printf ("MOB skill castend skill=%d, class = %d\n", md->skillid,
  3382. md->class);
  3383. mob_stop_walking (md, 0);
  3384. switch (skill_get_nk (md->skillid))
  3385. {
  3386. // 攻撃系/吹き飛ばし系
  3387. case 0:
  3388. case 2:
  3389. skill_castend_damage_id (&md->bl, bl, md->skillid, md->skilllv,
  3390. tick, 0);
  3391. break;
  3392. case 1: // 支援系
  3393. if (!mob_db[md->class].skill[md->skillidx].val[0] &&
  3394. (md->skillid == AL_HEAL
  3395. || (md->skillid == ALL_RESURRECTION && bl->type != BL_PC))
  3396. && battle_check_undead (battle_get_race (bl),
  3397. battle_get_elem_type (bl)))
  3398. skill_castend_damage_id (&md->bl, bl, md->skillid,
  3399. md->skilllv, tick, 0);
  3400. else
  3401. skill_castend_nodamage_id (&md->bl, bl, md->skillid,
  3402. md->skilllv, tick, 0);
  3403. break;
  3404. default:
  3405. break;
  3406. }
  3407. return 0;
  3408. }
  3409. /*==========================================
  3410. * スキル使用(詠唱完了、場所指定)
  3411. *------------------------------------------
  3412. */
  3413. int mobskill_castend_pos (int tid, unsigned int tick, int id, int data __attribute__ ((unused)))
  3414. {
  3415. struct mob_data *md = NULL;
  3416. struct block_list *bl;
  3417. int range;
  3418. //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外
  3419. if ((bl = map_id2bl (id)) == NULL)
  3420. return 0;
  3421. nullpo_retr (0, md = (struct mob_data *) bl);
  3422. if (md->bl.type != BL_MOB || md->bl.prev == NULL)
  3423. return 0;
  3424. if (md->skilltimer != tid) // タイマIDの確認
  3425. return 0;
  3426. md->skilltimer = -1;
  3427. if (md->sc_data)
  3428. {
  3429. if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
  3430. || md->sc_data[SC_ROKISWEIL].timer != -1
  3431. || md->sc_data[SC_STEELBODY].timer != -1)
  3432. return 0;
  3433. if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  3434. return 0;
  3435. if (md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  3436. return 0;
  3437. if (md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  3438. return 0;
  3439. }
  3440. if (battle_config.monster_skill_reiteration == 0)
  3441. {
  3442. range = -1;
  3443. switch (md->skillid)
  3444. {
  3445. case MG_SAFETYWALL:
  3446. case WZ_FIREPILLAR:
  3447. case HT_SKIDTRAP:
  3448. case HT_LANDMINE:
  3449. case HT_ANKLESNARE:
  3450. case HT_SHOCKWAVE:
  3451. case HT_SANDMAN:
  3452. case HT_FLASHER:
  3453. case HT_FREEZINGTRAP:
  3454. case HT_BLASTMINE:
  3455. case HT_CLAYMORETRAP:
  3456. case PF_SPIDERWEB: /* スパイダーウェッブ */
  3457. range = 0;
  3458. break;
  3459. case AL_PNEUMA:
  3460. case AL_WARP:
  3461. range = 1;
  3462. break;
  3463. default:
  3464. break;
  3465. }
  3466. if (range >= 0)
  3467. {
  3468. if (skill_check_unit_range
  3469. (md->bl.m, md->skillx, md->skilly, range, md->skillid) > 0)
  3470. return 0;
  3471. }
  3472. }
  3473. if (battle_config.monster_skill_nofootset == 1)
  3474. {
  3475. range = -1;
  3476. switch (md->skillid)
  3477. {
  3478. case WZ_FIREPILLAR:
  3479. case HT_SKIDTRAP:
  3480. case HT_LANDMINE:
  3481. case HT_ANKLESNARE:
  3482. case HT_SHOCKWAVE:
  3483. case HT_SANDMAN:
  3484. case HT_FLASHER:
  3485. case HT_FREEZINGTRAP:
  3486. case HT_BLASTMINE:
  3487. case HT_CLAYMORETRAP:
  3488. case AM_DEMONSTRATION:
  3489. case PF_SPIDERWEB: /* スパイダーウェッブ */
  3490. range = 1;
  3491. break;
  3492. case AL_WARP:
  3493. range = 0;
  3494. break;
  3495. default:
  3496. break;
  3497. }
  3498. if (range >= 0)
  3499. {
  3500. if (skill_check_unit_range2
  3501. (md->bl.m, md->skillx, md->skilly, range) > 0)
  3502. return 0;
  3503. }
  3504. }
  3505. if (battle_config.monster_land_skill_limit == 1)
  3506. {
  3507. int maxcount;
  3508. maxcount = skill_get_maxcount (md->skillid);
  3509. if (maxcount > 0)
  3510. {
  3511. int i, c;
  3512. for (i = c = 0; i < MAX_MOBSKILLUNITGROUP; i++)
  3513. {
  3514. if (md->skillunit[i].alive_count > 0
  3515. && md->skillunit[i].skill_id == md->skillid)
  3516. c++;
  3517. }
  3518. if (c >= maxcount)
  3519. return 0;
  3520. }
  3521. }
  3522. range = skill_get_range (md->skillid, md->skilllv);
  3523. if (range < 0)
  3524. range = battle_get_range (&md->bl) - (range + 1);
  3525. if (range + battle_config.mob_skill_add_range <
  3526. distance (md->bl.x, md->bl.y, md->skillx, md->skilly))
  3527. return 0;
  3528. md->skilldelay[md->skillidx] = tick;
  3529. if (battle_config.mob_skill_log == 1)
  3530. printf ("MOB skill castend skill=%d, class = %d\n", md->skillid,
  3531. md->class);
  3532. mob_stop_walking (md, 0);
  3533. skill_castend_pos2 (&md->bl, md->skillx, md->skilly, md->skillid,
  3534. md->skilllv, tick, 0);
  3535. return 0;
  3536. }
  3537. /*==========================================
  3538. * Skill use (an aria start, ID specification)
  3539. *------------------------------------------
  3540. */
  3541. int mobskill_use_id (struct mob_data *md, struct block_list *target,
  3542. int skill_idx)
  3543. {
  3544. int casttime, range;
  3545. struct mob_skill *ms;
  3546. int skill_id, skill_lv, forcecast = 0;
  3547. nullpo_retr (0, md);
  3548. if (skill_idx < 0 || skill_idx >= MAX_MOBSKILL)
  3549. return 0;
  3550. nullpo_retr (0, ms = &mob_db[md->class].skill[skill_idx]);
  3551. if (target == NULL && (target = map_id2bl (md->target_id)) == NULL)
  3552. return 0;
  3553. if (target->prev == NULL || md->bl.prev == NULL)
  3554. return 0;
  3555. skill_id = ms->skill_id;
  3556. skill_lv = ms->skill_lv;
  3557. // 沈黙や異常
  3558. if (md->sc_data)
  3559. {
  3560. if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
  3561. || md->sc_data[SC_ROKISWEIL].timer != -1
  3562. || md->sc_data[SC_STEELBODY].timer != -1)
  3563. return 0;
  3564. if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  3565. return 0;
  3566. if (md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  3567. return 0;
  3568. if (md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  3569. return 0;
  3570. }
  3571. if (md->option & 4 && skill_id == TF_HIDING)
  3572. return 0;
  3573. if (md->option & 2 && skill_id != TF_HIDING && skill_id != AS_GRIMTOOTH
  3574. && skill_id != RG_BACKSTAP && skill_id != RG_RAID)
  3575. return 0;
  3576. if (map[md->bl.m].flag.gvg
  3577. && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT
  3578. || skill_id == AL_WARP || skill_id == WZ_ICEWALL
  3579. || skill_id == TF_BACKSLIDING))
  3580. return 0;
  3581. if (skill_get_inf2 (skill_id) & 0x200 && md->bl.id == target->id)
  3582. return 0;
  3583. // 射程と障害物チェック
  3584. range = skill_get_range (skill_id, skill_lv);
  3585. if (range < 0)
  3586. range = battle_get_range (&md->bl) - (range + 1);
  3587. if (!battle_check_range (&md->bl, target, range))
  3588. return 0;
  3589. // delay=skill_delayfix(&md->bl, skill_get_delay( skill_id,skill_lv) );
  3590. casttime = skill_castfix (&md->bl, ms->casttime);
  3591. md->state.skillcastcancel = ms->cancel;
  3592. md->skilldelay[skill_idx] = gettick ();
  3593. switch (skill_id)
  3594. { /* 何か特殊な処理が必要 */
  3595. case ALL_RESURRECTION: /* リザレクション */
  3596. if (target->type != BL_PC
  3597. && battle_check_undead (battle_get_race (target),
  3598. battle_get_elem_type (target)))
  3599. { /* 敵がアンデッドなら */
  3600. forcecast = 1; /* ターンアンデットと同じ詠唱時間 */
  3601. casttime =
  3602. skill_castfix (&md->bl,
  3603. skill_get_cast (PR_TURNUNDEAD, skill_lv));
  3604. }
  3605. break;
  3606. case MO_EXTREMITYFIST: /*阿修羅覇鳳拳 */
  3607. case SA_MAGICROD:
  3608. case SA_SPELLBREAKER:
  3609. forcecast = 1;
  3610. break;
  3611. default:
  3612. break;
  3613. }
  3614. if (battle_config.mob_skill_log == 1)
  3615. printf
  3616. ("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",
  3617. target->id, skill_id, skill_lv, casttime, md->class);
  3618. if (casttime > 0 || forcecast)
  3619. { // 詠唱が必要
  3620. // struct mob_data *md2;
  3621. clif_skillcasting (&md->bl,
  3622. md->bl.id, target->id, 0, 0, skill_id, casttime);
  3623. // 詠唱反応モンスター
  3624. /* if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->class].mode&0x10 &&
  3625. md2->state.state!=MS_ATTACK){
  3626. md2->target_id=md->bl.id;
  3627. md->state.targettype = ATTACKABLE;
  3628. md2->min_chase=13;
  3629. }*/
  3630. }
  3631. if (casttime <= 0) // 詠唱の無いものはキャンセルされない
  3632. md->state.skillcastcancel = 0;
  3633. md->skilltarget = target->id;
  3634. md->skillx = 0;
  3635. md->skilly = 0;
  3636. md->skillid = skill_id;
  3637. md->skilllv = skill_lv;
  3638. md->skillidx = skill_idx;
  3639. if (!(battle_config.monster_cloak_check_type & 2)
  3640. && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
  3641. skill_status_change_end (&md->bl, SC_CLOAKING, -1);
  3642. if (casttime > 0)
  3643. {
  3644. md->skilltimer =
  3645. add_timer (gettick () + casttime, mobskill_castend_id, md->bl.id,
  3646. 0);
  3647. }
  3648. else
  3649. {
  3650. md->skilltimer = -1;
  3651. mobskill_castend_id (md->skilltimer, gettick (), md->bl.id, 0);
  3652. }
  3653. return 1;
  3654. }
  3655. /*==========================================
  3656. * スキル使用(場所指定)
  3657. *------------------------------------------
  3658. */
  3659. int mobskill_use_pos (struct mob_data *md,
  3660. int skill_x, int skill_y, int skill_idx)
  3661. {
  3662. int casttime = 0, range;
  3663. struct mob_skill *ms;
  3664. struct block_list bl;
  3665. int skill_id, skill_lv;
  3666. nullpo_retr (0, md);
  3667. if (skill_idx < 0 || skill_idx >= MAX_MOBSKILL)
  3668. return 0;
  3669. nullpo_retr (0, ms = &mob_db[md->class].skill[skill_idx]);
  3670. if (md->bl.prev == NULL)
  3671. return 0;
  3672. skill_id = ms->skill_id;
  3673. skill_lv = ms->skill_lv;
  3674. //沈黙や状態異常など
  3675. if (md->sc_data)
  3676. {
  3677. if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
  3678. || md->sc_data[SC_ROKISWEIL].timer != -1
  3679. || md->sc_data[SC_STEELBODY].timer != -1)
  3680. return 0;
  3681. if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  3682. return 0;
  3683. if (md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  3684. return 0;
  3685. if (md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  3686. return 0;
  3687. }
  3688. if (md->option & 2)
  3689. return 0;
  3690. if (map[md->bl.m].flag.gvg
  3691. && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT
  3692. || skill_id == AL_WARP || skill_id == WZ_ICEWALL
  3693. || skill_id == TF_BACKSLIDING))
  3694. return 0;
  3695. // 射程と障害物チェック
  3696. bl.type = BL_NUL;
  3697. bl.m = md->bl.m;
  3698. bl.x = skill_x;
  3699. bl.y = skill_y;
  3700. range = skill_get_range (skill_id, skill_lv);
  3701. if (range < 0)
  3702. range = battle_get_range (&md->bl) - (range + 1);
  3703. if (!battle_check_range (&md->bl, &bl, range))
  3704. return 0;
  3705. // delay=skill_delayfix(&sd->bl, skill_get_delay( skill_id,skill_lv) );
  3706. casttime = skill_castfix (&md->bl, ms->casttime);
  3707. md->skilldelay[skill_idx] = gettick ();
  3708. md->state.skillcastcancel = ms->cancel;
  3709. if (battle_config.mob_skill_log == 1)
  3710. printf
  3711. ("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, class = %d\n",
  3712. skill_x, skill_y, skill_id, skill_lv, casttime, md->class);
  3713. if (casttime > 0) // A cast time is required.
  3714. clif_skillcasting (&md->bl,
  3715. md->bl.id, 0, skill_x, skill_y, skill_id,
  3716. casttime);
  3717. if (casttime <= 0) // A skill without a cast time wont be cancelled.
  3718. md->state.skillcastcancel = 0;
  3719. md->skillx = skill_x;
  3720. md->skilly = skill_y;
  3721. md->skilltarget = 0;
  3722. md->skillid = skill_id;
  3723. md->skilllv = skill_lv;
  3724. md->skillidx = skill_idx;
  3725. if (!(battle_config.monster_cloak_check_type & 2)
  3726. && md->sc_data[SC_CLOAKING].timer != -1)
  3727. skill_status_change_end (&md->bl, SC_CLOAKING, -1);
  3728. if (casttime > 0)
  3729. {
  3730. md->skilltimer =
  3731. add_timer (gettick () + casttime, mobskill_castend_pos, md->bl.id,
  3732. 0);
  3733. }
  3734. else
  3735. {
  3736. md->skilltimer = -1;
  3737. mobskill_castend_pos (md->skilltimer, gettick (), md->bl.id, 0);
  3738. }
  3739. return 1;
  3740. }
  3741. /*==========================================
  3742. * Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
  3743. *------------------------------------------
  3744. */
  3745. int mob_getfriendhpltmaxrate_sub (struct block_list *bl, va_list ap)
  3746. {
  3747. int rate;
  3748. struct mob_data **fr, *md, *mmd;
  3749. nullpo_retr (0, bl);
  3750. nullpo_retr (0, ap);
  3751. nullpo_retr (0, mmd = va_arg (ap, struct mob_data *));
  3752. md = (struct mob_data *) bl;
  3753. if (mmd->bl.id == bl->id)
  3754. return 0;
  3755. rate = va_arg (ap, int);
  3756. fr = va_arg (ap, struct mob_data **);
  3757. if (!fr)
  3758. return 0;
  3759. if (md->hp < mob_db[md->class].max_hp * rate / 100)
  3760. (*fr) = md;
  3761. return 0;
  3762. }
  3763. struct mob_data *mob_getfriendhpltmaxrate (struct mob_data *md, int rate)
  3764. {
  3765. struct mob_data *fr = NULL;
  3766. const int r = 8;
  3767. nullpo_retr (NULL, md);
  3768. map_foreachinarea (mob_getfriendhpltmaxrate_sub, md->bl.m,
  3769. md->bl.x - r, md->bl.y - r, md->bl.x + r, md->bl.y + r,
  3770. BL_MOB, md, rate, &fr);
  3771. return fr;
  3772. }
  3773. /*==========================================
  3774. * What a status state suits by nearby MOB is looked for.
  3775. *------------------------------------------
  3776. */
  3777. int mob_getfriendstatus_sub (struct block_list *bl, va_list ap)
  3778. {
  3779. int cond1, cond2;
  3780. struct mob_data **fr, *md, *mmd;
  3781. int flag = 0;
  3782. nullpo_retr (0, bl);
  3783. nullpo_retr (0, ap);
  3784. nullpo_retr (0, md = (struct mob_data *) bl);
  3785. nullpo_retr (0, mmd = va_arg (ap, struct mob_data *));
  3786. if (mmd->bl.id == bl->id)
  3787. return 0;
  3788. cond1 = va_arg (ap, int);
  3789. cond2 = va_arg (ap, int);
  3790. fr = va_arg (ap, struct mob_data **);
  3791. if (!fr)
  3792. return 0;
  3793. if (cond2 == -1)
  3794. {
  3795. int j;
  3796. for (j = SC_STONE; j <= SC_BLIND && !flag; j++)
  3797. {
  3798. flag = (md->sc_data[j].timer != -1);
  3799. }
  3800. }
  3801. else
  3802. flag = (md->sc_data[cond2].timer != -1);
  3803. if (flag ^ (cond1 == MSC_FRIENDSTATUSOFF))
  3804. (*fr) = md;
  3805. return 0;
  3806. }
  3807. struct mob_data *mob_getfriendstatus (struct mob_data *md, int cond1,
  3808. int cond2)
  3809. {
  3810. struct mob_data *fr = NULL;
  3811. const int r = 8;
  3812. nullpo_retr (0, md);
  3813. map_foreachinarea (mob_getfriendstatus_sub, md->bl.m,
  3814. md->bl.x - r, md->bl.y - r, md->bl.x + r, md->bl.y + r,
  3815. BL_MOB, md, cond1, cond2, &fr);
  3816. return fr;
  3817. }
  3818. /*==========================================
  3819. * Skill use judging
  3820. *------------------------------------------
  3821. */
  3822. int mobskill_use (struct mob_data *md, unsigned int tick, int event)
  3823. {
  3824. struct mob_skill *ms;
  3825. // struct block_list *target=NULL;
  3826. int i, max_hp;
  3827. nullpo_retr (0, md);
  3828. nullpo_retr (0, ms = mob_db[md->class].skill);
  3829. max_hp = battle_get_max_hp (&md->bl);
  3830. if (battle_config.mob_skill_use == 0 || md->skilltimer != -1)
  3831. return 0;
  3832. if (md->state.special_mob_ai)
  3833. return 0;
  3834. if (md->sc_data[SC_SELFDESTRUCTION].timer != -1) //自爆中はスキルを使わない
  3835. return 0;
  3836. for (i = 0; i < mob_db[md->class].maxskill; i++)
  3837. {
  3838. int c2 = ms[i].cond2, c3 = ms[i].cond3, flag = 0;
  3839. struct mob_data *fmd = NULL;
  3840. // ディレイ中
  3841. if (DIFF_TICK (tick, md->skilldelay[i]) < ms[i].delay)
  3842. continue;
  3843. // 状態判定
  3844. if (ms[i].state >= 0 && ms[i].state != md->state.skillstate)
  3845. continue;
  3846. // 条件判定
  3847. flag = (event == ms[i].cond1);
  3848. if (!flag)
  3849. {
  3850. switch (ms[i].cond1)
  3851. {
  3852. case MSC_ALWAYS:
  3853. flag = 1;
  3854. break;
  3855. case MSC_MYHPLTMAXRATE: // HP< maxhp%
  3856. if (c3 > battle_config.mob_skill_spawn_limit)
  3857. c3 = battle_config.mob_skill_spawn_limit;
  3858. if (!c3 || mob_countslave (md) < c3)
  3859. flag = (md->hp < max_hp * c2 / 100);
  3860. else
  3861. flag = 0;
  3862. break;
  3863. case MSC_MYSTATUSON: // status[num] on
  3864. case MSC_MYSTATUSOFF: // status[num] off
  3865. if (ms[i].cond2 == -1)
  3866. {
  3867. int j;
  3868. for (j = SC_STONE; j <= SC_BLIND && !flag; j++)
  3869. {
  3870. flag = (md->sc_data[j].timer != -1);
  3871. }
  3872. }
  3873. else
  3874. flag = (md->sc_data[ms[i].cond2].timer != -1);
  3875. flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF);
  3876. break;
  3877. case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
  3878. flag =
  3879. ((fmd =
  3880. mob_getfriendhpltmaxrate (md,
  3881. ms[i].cond2)) != NULL);
  3882. break;
  3883. case MSC_FRIENDSTATUSON: // friend status[num] on
  3884. case MSC_FRIENDSTATUSOFF: // friend status[num] off
  3885. flag =
  3886. ((fmd =
  3887. mob_getfriendstatus (md, ms[i].cond1,
  3888. ms[i].cond2)) != NULL);
  3889. break;
  3890. case MSC_NOTINTOWN: // Only outside of towns.
  3891. flag = !map[md->bl.m].flag.town;
  3892. break;
  3893. case MSC_SLAVELT: // slave < num
  3894. if (c2 > battle_config.mob_skill_spawn_limit)
  3895. c2 = battle_config.mob_skill_spawn_limit;
  3896. flag = (mob_countslave (md) < c2);
  3897. break;
  3898. case MSC_ATTACKPCGT: // attack pc > num
  3899. if (c2 > battle_config.mob_skill_spawn_limit)
  3900. c2 = battle_config.mob_skill_spawn_limit;
  3901. flag = (mob_counttargeted (md, NULL, 0) > c2);
  3902. break;
  3903. case MSC_SLAVELE: // slave <= num
  3904. if (c2 > battle_config.mob_skill_spawn_limit)
  3905. c2 = battle_config.mob_skill_spawn_limit;
  3906. flag = (mob_countslave (md) <= c2);
  3907. break;
  3908. case MSC_ATTACKPCGE: // attack pc >= num
  3909. if (c2 > battle_config.mob_skill_spawn_limit)
  3910. c2 = battle_config.mob_skill_spawn_limit;
  3911. flag = (mob_counttargeted (md, NULL, 0) >= c2);
  3912. break;
  3913. case MSC_SKILLUSED: // specificated skill used
  3914. flag = ((event & 0xffff) == MSC_SKILLUSED
  3915. && ((event >> 16) == c2 || c2 == 0));
  3916. break;
  3917. default:
  3918. break;
  3919. }
  3920. }
  3921. // 確率判定
  3922. if (flag && MRAND (10000) < ms[i].permillage)
  3923. {
  3924. if (skill_get_inf (ms[i].skill_id) & 2)
  3925. {
  3926. // 場所指定
  3927. struct block_list *bl = NULL;
  3928. int x = 0, y = 0;
  3929. if (ms[i].target <= MST_AROUND)
  3930. {
  3931. if (ms[i].target == MST_MASTER)
  3932. {
  3933. bl = &md->bl;
  3934. if (md->master_id)
  3935. bl = map_id2bl (md->master_id);
  3936. }
  3937. else
  3938. {
  3939. bl = ((ms[i].target == MST_TARGET
  3940. || ms[i].target ==
  3941. MST_AROUND5) ? map_id2bl (md->
  3942. target_id)
  3943. : (ms[i].target ==
  3944. MST_FRIEND) ? &fmd->bl : &md->bl);
  3945. }
  3946. if (bl)
  3947. {
  3948. x = bl->x;
  3949. y = bl->y;
  3950. }
  3951. }
  3952. if (x <= 0 || y <= 0)
  3953. continue;
  3954. // 自分の周囲
  3955. if (ms[i].target >= MST_AROUND1)
  3956. {
  3957. int bx = x, by = y, i = 0, c, m = bl->m, r =
  3958. ms[i].target - MST_AROUND1;
  3959. do
  3960. {
  3961. bx = x + MRAND ((r * 2 + 3)) - r;
  3962. by = y + MRAND ((r * 2 + 3)) - r;
  3963. }
  3964. while ((bx <= 0 || by <= 0 || bx >= map[m].xs
  3965. || by >= map[m].ys
  3966. || ((c = read_gat (m, bx, by)) == 1 || c == 5))
  3967. && (i++) < 1000);
  3968. if (i < 1000)
  3969. {
  3970. x = bx;
  3971. y = by;
  3972. }
  3973. }
  3974. // 相手の周囲
  3975. if (ms[i].target >= MST_AROUND5)
  3976. {
  3977. int bx = x, by = y, i = 0, c, m = bl->m, r =
  3978. (ms[i].target - MST_AROUND5) + 1;
  3979. do
  3980. {
  3981. bx = x + MRAND ((r * 2 + 1)) - r;
  3982. by = y + MRAND ((r * 2 + 1)) - r;
  3983. }
  3984. while ((bx <= 0 || by <= 0 || bx >= map[m].xs
  3985. || by >= map[m].ys
  3986. || ((c = read_gat (m, bx, by)) == 1 || c == 5))
  3987. && (i++) < 1000);
  3988. if (i < 1000)
  3989. {
  3990. x = bx;
  3991. y = by;
  3992. }
  3993. }
  3994. if (!mobskill_use_pos (md, x, y, i))
  3995. return 0;
  3996. }
  3997. else
  3998. {
  3999. if (ms[i].target == MST_MASTER)
  4000. {
  4001. struct block_list *bl = &md->bl;
  4002. if (md->master_id)
  4003. bl = map_id2bl (md->master_id);
  4004. if (bl && !mobskill_use_id (md, bl, i))
  4005. return 0;
  4006. }
  4007. // ID指定
  4008. if (ms[i].target <= MST_FRIEND)
  4009. {
  4010. struct block_list *bl = NULL;
  4011. bl = ((ms[i].target ==
  4012. MST_TARGET) ? map_id2bl (md->
  4013. target_id) : (ms[i].target
  4014. ==
  4015. MST_FRIEND)
  4016. ? &fmd->bl : &md->bl);
  4017. if (bl && !mobskill_use_id (md, bl, i))
  4018. return 0;
  4019. }
  4020. }
  4021. if (ms[i].emotion >= 0)
  4022. clif_emotion (&md->bl, ms[i].emotion);
  4023. return 1;
  4024. }
  4025. }
  4026. return 0;
  4027. }
  4028. /*==========================================
  4029. * Skill use event processing
  4030. *------------------------------------------
  4031. */
  4032. int mobskill_event (struct mob_data *md, int flag)
  4033. {
  4034. nullpo_retr (0, md);
  4035. if (flag == -1 && mobskill_use (md, gettick (), MSC_CASTTARGETED))
  4036. return 1;
  4037. if ((flag & BF_SHORT)
  4038. && mobskill_use (md, gettick (), MSC_CLOSEDATTACKED))
  4039. return 1;
  4040. if ((flag & BF_LONG)
  4041. && mobskill_use (md, gettick (), MSC_LONGRANGEATTACKED))
  4042. return 1;
  4043. return 0;
  4044. }
  4045. /*==========================================
  4046. * Mobがエンペリウムなどの場合の判定
  4047. *------------------------------------------
  4048. */
  4049. int mob_gvmobcheck (struct map_session_data *sd, struct block_list *bl)
  4050. {
  4051. struct mob_data *md = NULL;
  4052. nullpo_retr (0, sd);
  4053. nullpo_retr (0, bl);
  4054. if (bl->type == BL_MOB && (md = (struct mob_data *) bl) &&
  4055. (md->class == 1288 || md->class == 1287 || md->class == 1286
  4056. || md->class == 1285))
  4057. {
  4058. struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
  4059. struct guild *g = guild_search (sd->status.guild_id);
  4060. if (g == NULL && md->class == 1288)
  4061. return 0; //ギルド未加入ならダメージ無し
  4062. else if (gc != NULL && !map[sd->bl.m].flag.gvg)
  4063. return 0; //砦内でGvじゃないときはダメージなし
  4064. else if (g && gc != NULL && g->guild_id == gc->guild_id)
  4065. return 0; //自占領ギルドのエンペならダメージ無し
  4066. else if (g && guild_checkskill (g, GD_APPROVAL) <= 0
  4067. && md->class == 1288)
  4068. return 0; //正規ギルド承認がないとダメージ無し
  4069. }
  4070. return 1;
  4071. }
  4072. /*==========================================
  4073. * スキル用タイマー削除
  4074. *------------------------------------------
  4075. */
  4076. int mobskill_deltimer (struct mob_data *md)
  4077. {
  4078. nullpo_retr (0, md);
  4079. if (md->skilltimer != -1)
  4080. {
  4081. if (skill_get_inf (md->skillid) & 2)
  4082. delete_timer (md->skilltimer, mobskill_castend_pos);
  4083. else
  4084. delete_timer (md->skilltimer, mobskill_castend_id);
  4085. md->skilltimer = -1;
  4086. }
  4087. return 0;
  4088. }
  4089. //
  4090. // 初期化
  4091. //
  4092. /*==========================================
  4093. * Since un-setting [ mob ] up was used, it is an initial provisional value setup.
  4094. *------------------------------------------
  4095. */
  4096. static int mob_makedummymobdb (int class)
  4097. {
  4098. if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
  4099. return 0;
  4100. int i;
  4101. sprintf (mob_db[class].name, "mob%d", class);
  4102. sprintf (mob_db[class].jname, "mob%d", class);
  4103. mob_db[class].lv = 1;
  4104. mob_db[class].max_hp = 1000;
  4105. mob_db[class].max_sp = 1;
  4106. mob_db[class].base_exp = 2;
  4107. mob_db[class].job_exp = 1;
  4108. mob_db[class].range = 1;
  4109. mob_db[class].atk1 = 7;
  4110. mob_db[class].atk2 = 10;
  4111. mob_db[class].def = 0;
  4112. mob_db[class].mdef = 0;
  4113. mob_db[class].str = 1;
  4114. mob_db[class].agi = 1;
  4115. mob_db[class].vit = 1;
  4116. mob_db[class].int_ = 1;
  4117. mob_db[class].dex = 6;
  4118. mob_db[class].luk = 2;
  4119. mob_db[class].range2 = 10;
  4120. mob_db[class].range3 = 10;
  4121. mob_db[class].size = 0;
  4122. mob_db[class].race = 0;
  4123. mob_db[class].element = 0;
  4124. mob_db[class].mode = 0;
  4125. mob_db[class].speed = 300;
  4126. mob_db[class].adelay = 1000;
  4127. mob_db[class].amotion = 500;
  4128. mob_db[class].dmotion = 500;
  4129. mob_db[class].dropitem[0].nameid = 909; // Jellopy
  4130. mob_db[class].dropitem[0].p = 1000;
  4131. for (i = 1; i < 8; i++)
  4132. {
  4133. mob_db[class].dropitem[i].nameid = 0;
  4134. mob_db[class].dropitem[i].p = 0;
  4135. }
  4136. // Item1,Item2
  4137. mob_db[class].mexp = 0;
  4138. mob_db[class].mexpper = 0;
  4139. for (i = 0; i < 3; i++)
  4140. {
  4141. mob_db[class].mvpitem[i].nameid = 0;
  4142. mob_db[class].mvpitem[i].p = 0;
  4143. }
  4144. for (i = 0; i < MAX_RANDOMMONSTER; i++)
  4145. mob_db[class].summonper[i] = 0;
  4146. return 0;
  4147. }
  4148. /*==========================================
  4149. * db/mob_db.txt reading
  4150. *------------------------------------------
  4151. */
  4152. static int mob_readdb (void)
  4153. {
  4154. FILE *fp;
  4155. char line[2024];
  4156. char *filename[] = { "db/mob_db.txt", "db/mob_db2.txt" };
  4157. int i;
  4158. memset (mob_db, 0, sizeof (mob_db));
  4159. for (i = 0; i < 2; i++)
  4160. {
  4161. fp = fopen_ (filename[i], "r");
  4162. if (fp == NULL)
  4163. {
  4164. if (i > 0)
  4165. continue;
  4166. return -1;
  4167. }
  4168. while (fgets (line, 2020, fp))
  4169. {
  4170. int class, i;
  4171. char *str[57], *p, *np;
  4172. if (line[0] == '/' && line[1] == '/')
  4173. continue;
  4174. for (i = 0, p = line; i < 57; i++)
  4175. {
  4176. while (*p == '\t' || *p == ' ')
  4177. p++;
  4178. if ((np = strchr (p, ',')) != NULL)
  4179. {
  4180. str[i] = p;
  4181. *np = 0;
  4182. p = np + 1;
  4183. }
  4184. else
  4185. str[i] = p;
  4186. }
  4187. class = atoi (str[0]);
  4188. if (class <= 1000 || class > 2000)
  4189. continue;
  4190. mob_db[class].view_class = class;
  4191. memcpy (mob_db[class].name, str[1], 24);
  4192. memcpy (mob_db[class].jname, str[2], 24);
  4193. mob_db[class].lv = atoi (str[3]);
  4194. if (!mob_db[class].lv)
  4195. {
  4196. printf("mob level error. Id %d\n", class);
  4197. }
  4198. mob_db[class].max_hp = atoi (str[4]);
  4199. if (!mob_db[class].max_hp)
  4200. {
  4201. printf("mob hp error. Id %d\n", class);
  4202. }
  4203. mob_db[class].max_sp = atoi (str[5]);
  4204. mob_db[class].base_exp = atoi (str[6]);
  4205. if (mob_db[class].base_exp < 0)
  4206. mob_db[class].base_exp = 0;
  4207. else if (mob_db[class].base_exp > 0
  4208. && (mob_db[class].base_exp *
  4209. battle_config.base_exp_rate / 100 > 1000000000
  4210. || mob_db[class].base_exp *
  4211. battle_config.base_exp_rate / 100 < 0))
  4212. mob_db[class].base_exp = 1000000000;
  4213. else
  4214. mob_db[class].base_exp *= battle_config.base_exp_rate / 100;
  4215. mob_db[class].job_exp = atoi (str[7]);
  4216. if (mob_db[class].job_exp < 0)
  4217. mob_db[class].job_exp = 0;
  4218. else if (mob_db[class].job_exp > 0
  4219. && (mob_db[class].job_exp * battle_config.job_exp_rate /
  4220. 100 > 1000000000
  4221. || mob_db[class].job_exp *
  4222. battle_config.job_exp_rate / 100 < 0))
  4223. mob_db[class].job_exp = 1000000000;
  4224. else
  4225. mob_db[class].job_exp *= battle_config.job_exp_rate / 100;
  4226. mob_db[class].range = atoi (str[8]);
  4227. mob_db[class].atk1 = atoi (str[9]);
  4228. mob_db[class].atk2 = atoi (str[10]);
  4229. mob_db[class].def = atoi (str[11]);
  4230. mob_db[class].mdef = atoi (str[12]);
  4231. mob_db[class].str = atoi (str[13]);
  4232. mob_db[class].agi = atoi (str[14]);
  4233. mob_db[class].vit = atoi (str[15]);
  4234. mob_db[class].int_ = atoi (str[16]);
  4235. mob_db[class].dex = atoi (str[17]);
  4236. mob_db[class].luk = atoi (str[18]);
  4237. mob_db[class].range2 = atoi (str[19]);
  4238. mob_db[class].range3 = atoi (str[20]);
  4239. mob_db[class].size = atoi (str[21]);
  4240. mob_db[class].race = atoi (str[22]);
  4241. mob_db[class].element = atoi (str[23]);
  4242. mob_db[class].mode = atoi (str[24]);
  4243. mob_db[class].speed = atoi (str[25]);
  4244. mob_db[class].adelay = atoi (str[26]);
  4245. mob_db[class].amotion = atoi (str[27]);
  4246. if (!mob_db[class].amotion)
  4247. {
  4248. printf("mob amotion error. Id %d\n", class);
  4249. }
  4250. mob_db[class].dmotion = atoi (str[28]);
  4251. if (!mob_db[class].dmotion)
  4252. {
  4253. printf("mob dmotion error. Id %d\n", class);
  4254. }
  4255. for (i = 0; i < 8; i++)
  4256. {
  4257. int rate = 0, type, ratemin, ratemax;
  4258. mob_db[class].dropitem[i].nameid = atoi (str[29 + i * 2]);
  4259. type = itemdb_type (mob_db[class].dropitem[i].nameid);
  4260. if (type == 0)
  4261. { // Added [Valaris]
  4262. rate = battle_config.item_rate_heal;
  4263. ratemin = battle_config.item_drop_heal_min;
  4264. ratemax = battle_config.item_drop_heal_max;
  4265. }
  4266. else if (type == 2)
  4267. {
  4268. rate = battle_config.item_rate_use;
  4269. ratemin = battle_config.item_drop_use_min;
  4270. ratemax = battle_config.item_drop_use_max; // End
  4271. }
  4272. else if (type == 4 || type == 5 || type == 8)
  4273. {
  4274. rate = battle_config.item_rate_equip;
  4275. ratemin = battle_config.item_drop_equip_min;
  4276. ratemax = battle_config.item_drop_equip_max;
  4277. }
  4278. else if (type == 6)
  4279. {
  4280. rate = battle_config.item_rate_card;
  4281. ratemin = battle_config.item_drop_card_min;
  4282. ratemax = battle_config.item_drop_card_max;
  4283. }
  4284. else
  4285. {
  4286. rate = battle_config.item_rate_common;
  4287. ratemin = battle_config.item_drop_common_min;
  4288. ratemax = battle_config.item_drop_common_max;
  4289. }
  4290. rate = (rate / 100) * atoi (str[30 + i * 2]);
  4291. rate =
  4292. (rate < ratemin) ? ratemin : (rate >
  4293. ratemax) ? ratemax : rate;
  4294. mob_db[class].dropitem[i].p = rate;
  4295. }
  4296. // Item1,Item2
  4297. mob_db[class].mexp =
  4298. atoi (str[45]) * battle_config.mvp_exp_rate / 100;
  4299. mob_db[class].mexpper = atoi (str[46]);
  4300. for (i = 0; i < 3; i++)
  4301. {
  4302. mob_db[class].mvpitem[i].nameid = atoi (str[47 + i * 2]);
  4303. mob_db[class].mvpitem[i].p =
  4304. atoi (str[48 + i * 2]) * battle_config.mvp_item_rate /
  4305. 100;
  4306. }
  4307. // skip two positions
  4308. mob_db[class].mutations_nr = atoi (str[55]);
  4309. mob_db[class].mutation_power = atoi (str[56]);
  4310. if (mob_db[class].mutation_power && !mob_db[class].mutations_nr)
  4311. {
  4312. printf("mob mutations error. Id %d\n", class);
  4313. }
  4314. for (i = 0; i < MAX_RANDOMMONSTER; i++)
  4315. mob_db[class].summonper[i] = 0;
  4316. mob_db[class].maxskill = 0;
  4317. mob_db[class].sex = 0;
  4318. mob_db[class].hair = 0;
  4319. mob_db[class].hair_color = 0;
  4320. mob_db[class].weapon = 0;
  4321. mob_db[class].shield = 0;
  4322. mob_db[class].head_top = 0;
  4323. mob_db[class].head_mid = 0;
  4324. mob_db[class].head_buttom = 0;
  4325. mob_db[class].clothes_color = 0; //Add for player monster dye - Valaris
  4326. if (mob_db[class].base_exp == 0)
  4327. mob_db[class].base_exp = mob_gen_exp (&mob_db[class]);
  4328. }
  4329. fclose_ (fp);
  4330. printf ("read %s done\n", filename[i]);
  4331. }
  4332. return 0;
  4333. }
  4334. /*==========================================
  4335. * MOB display graphic change data reading
  4336. *------------------------------------------
  4337. */
  4338. static int mob_readdb_mobavail (void)
  4339. {
  4340. FILE *fp;
  4341. char line[2024];
  4342. int ln = 0;
  4343. int class, j, k;
  4344. char *str[20], *p, *np;
  4345. if ((fp = fopen_ ("db/mob_avail.txt", "r")) == NULL)
  4346. {
  4347. printf ("can't read db/mob_avail.txt\n");
  4348. return -1;
  4349. }
  4350. while (fgets (line, 2020, fp))
  4351. {
  4352. if (line[0] == '/' && line[1] == '/')
  4353. continue;
  4354. memset (str, 0, sizeof (str));
  4355. for (j = 0, p = line; j < 12; j++)
  4356. {
  4357. if ((np = strchr (p, ',')) != NULL)
  4358. {
  4359. str[j] = p;
  4360. *np = 0;
  4361. p = np + 1;
  4362. }
  4363. else
  4364. str[j] = p;
  4365. }
  4366. if (str[0] == NULL)
  4367. continue;
  4368. class = atoi (str[0]);
  4369. if (class <= 1000 || class > 2000) // 値が異常なら処理しない。
  4370. continue;
  4371. k = atoi (str[1]);
  4372. if (k >= 0)
  4373. mob_db[class].view_class = k;
  4374. if ((mob_db[class].view_class < 24)
  4375. || (mob_db[class].view_class > 4000))
  4376. {
  4377. mob_db[class].sex = atoi (str[2]);
  4378. mob_db[class].hair = atoi (str[3]);
  4379. mob_db[class].hair_color = atoi (str[4]);
  4380. mob_db[class].weapon = atoi (str[5]);
  4381. mob_db[class].shield = atoi (str[6]);
  4382. mob_db[class].head_top = atoi (str[7]);
  4383. mob_db[class].head_mid = atoi (str[8]);
  4384. mob_db[class].head_buttom = atoi (str[9]);
  4385. mob_db[class].option = atoi (str[10]) & ~0x46;
  4386. mob_db[class].clothes_color = atoi (str[11]); // Monster player dye option - Valaris
  4387. }
  4388. else if (atoi (str[2]) > 0)
  4389. mob_db[class].equip = atoi (str[2]); // mob equipment [Valaris]
  4390. ln++;
  4391. }
  4392. fclose_ (fp);
  4393. printf ("read db/mob_avail.txt done (count=%d)\n", ln);
  4394. return 0;
  4395. }
  4396. /*==========================================
  4397. * Reading of random monster data
  4398. *------------------------------------------
  4399. */
  4400. static int mob_read_randommonster (void)
  4401. {
  4402. FILE *fp;
  4403. char line[2024];
  4404. char *str[10], *p;
  4405. int i, j;
  4406. const char *mobfile[] = {
  4407. "db/mob_branch.txt",
  4408. "db/mob_poring.txt",
  4409. "db/mob_boss.txt"
  4410. };
  4411. for (i = 0; i < MAX_RANDOMMONSTER; i++)
  4412. {
  4413. mob_db[0].summonper[i] = 1002; // 設定し忘れた場合はポリンが出るようにしておく
  4414. fp = fopen_ (mobfile[i], "r");
  4415. if (fp == NULL)
  4416. {
  4417. printf ("can't read %s\n", mobfile[i]);
  4418. return -1;
  4419. }
  4420. while (fgets (line, 2020, fp))
  4421. {
  4422. int class, per;
  4423. if (line[0] == '/' && line[1] == '/')
  4424. continue;
  4425. memset (str, 0, sizeof (str));
  4426. for (j = 0, p = line; j < 3 && p; j++)
  4427. {
  4428. str[j] = p;
  4429. p = strchr (p, ',');
  4430. if (p)
  4431. *p++ = 0;
  4432. }
  4433. if (str[0] == NULL || str[2] == NULL)
  4434. continue;
  4435. class = atoi (str[0]);
  4436. per = atoi (str[2]);
  4437. if ((class > 1000 && class <= 2000) || class == 0)
  4438. mob_db[class].summonper[i] = per;
  4439. }
  4440. fclose_ (fp);
  4441. printf ("read %s done\n", mobfile[i]);
  4442. }
  4443. return 0;
  4444. }
  4445. /*==========================================
  4446. * db/mob_skill_db.txt reading
  4447. *------------------------------------------
  4448. */
  4449. static int mob_readskilldb (void)
  4450. {
  4451. FILE *fp;
  4452. char line[2028];
  4453. int i;
  4454. const struct
  4455. {
  4456. char str[32];
  4457. int id;
  4458. } cond1[] =
  4459. {
  4460. {
  4461. "always", MSC_ALWAYS},
  4462. {
  4463. "myhpltmaxrate", MSC_MYHPLTMAXRATE},
  4464. {
  4465. "friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE},
  4466. {
  4467. "mystatuson", MSC_MYSTATUSON},
  4468. {
  4469. "mystatusoff", MSC_MYSTATUSOFF},
  4470. {
  4471. "friendstatuson", MSC_FRIENDSTATUSON},
  4472. {
  4473. "friendstatusoff", MSC_FRIENDSTATUSOFF},
  4474. {
  4475. "notintown", MSC_NOTINTOWN},
  4476. {
  4477. "attackpcgt", MSC_ATTACKPCGT},
  4478. {
  4479. "attackpcge", MSC_ATTACKPCGE},
  4480. {
  4481. "slavelt", MSC_SLAVELT},
  4482. {
  4483. "slavele", MSC_SLAVELE},
  4484. {
  4485. "closedattacked", MSC_CLOSEDATTACKED},
  4486. {
  4487. "longrangeattacked", MSC_LONGRANGEATTACKED},
  4488. {
  4489. "skillused", MSC_SKILLUSED},
  4490. {
  4491. "casttargeted", MSC_CASTTARGETED},}, cond2[] =
  4492. {
  4493. {
  4494. "anybad", -1},
  4495. {
  4496. "stone", SC_STONE},
  4497. {
  4498. "freeze", SC_FREEZE},
  4499. {
  4500. "stan", SC_STAN},
  4501. {
  4502. "sleep", SC_SLEEP},
  4503. {
  4504. "poison", SC_POISON},
  4505. {
  4506. "curse", SC_CURSE},
  4507. {
  4508. "silence", SC_SILENCE},
  4509. {
  4510. "confusion", SC_CONFUSION},
  4511. {
  4512. "blind", SC_BLIND},
  4513. {
  4514. "hiding", SC_HIDING},
  4515. {
  4516. "sight", SC_SIGHT},}, state[] =
  4517. {
  4518. {
  4519. "any", -1},
  4520. {
  4521. "idle", MSS_IDLE},
  4522. {
  4523. "walk", MSS_WALK},
  4524. {
  4525. "attack", MSS_ATTACK},
  4526. {
  4527. "dead", MSS_DEAD},
  4528. {
  4529. "loot", MSS_LOOT},
  4530. {
  4531. "chase", MSS_CHASE},}, target[] =
  4532. {
  4533. {
  4534. "target", MST_TARGET},
  4535. {
  4536. "self", MST_SELF},
  4537. {
  4538. "friend", MST_FRIEND},
  4539. {
  4540. "master", MST_MASTER},
  4541. {
  4542. "around5", MST_AROUND5},
  4543. {
  4544. "around6", MST_AROUND6},
  4545. {
  4546. "around7", MST_AROUND7},
  4547. {
  4548. "around8", MST_AROUND8},
  4549. {
  4550. "around1", MST_AROUND1},
  4551. {
  4552. "around2", MST_AROUND2},
  4553. {
  4554. "around3", MST_AROUND3},
  4555. {
  4556. "around4", MST_AROUND4},
  4557. {
  4558. "around", MST_AROUND},};
  4559. int x;
  4560. char *filename[] = { "db/mob_skill_db.txt", "db/mob_skill_db2.txt" };
  4561. for (x = 0; x < 2; x++)
  4562. {
  4563. fp = fopen_ (filename[x], "r");
  4564. if (fp == NULL)
  4565. {
  4566. if (x == 0)
  4567. printf ("can't read %s\n", filename[x]);
  4568. continue;
  4569. }
  4570. while (fgets (line, 2020, fp))
  4571. {
  4572. char *sp[20], *p;
  4573. int mob_id;
  4574. struct mob_skill *ms;
  4575. int j = 0;
  4576. if (line[0] == '/' && line[1] == '/')
  4577. continue;
  4578. memset (sp, 0, sizeof (sp));
  4579. for (i = 0, p = line; i < 19 && p; i++)
  4580. {
  4581. sp[i] = p;
  4582. if ((p = strchr (p, ',')) != NULL)
  4583. *p++ = 0;
  4584. }
  4585. if ((mob_id = atoi (sp[0])) <= 0)
  4586. continue;
  4587. tmw_TrimStr(sp[1]);
  4588. if (strcmp (sp[1], "clear") == 0)
  4589. {
  4590. memset (mob_db[mob_id].skill, 0,
  4591. sizeof (mob_db[mob_id].skill));
  4592. mob_db[mob_id].maxskill = 0;
  4593. continue;
  4594. }
  4595. for (i = 0; i < MAX_MOBSKILL; i++)
  4596. if ((ms = &mob_db[mob_id].skill[i])->skill_id == 0)
  4597. break;
  4598. if (i == MAX_MOBSKILL)
  4599. {
  4600. printf
  4601. ("mob_skill: readdb: too many skill ! [%s] in %d[%s]\n",
  4602. sp[1], mob_id, mob_db[mob_id].jname);
  4603. continue;
  4604. }
  4605. tmw_TrimStr(sp[2]);
  4606. ms->state = atoi (sp[2]);
  4607. for (j = 0; j < sizeof (state) / sizeof (state[0]); j++)
  4608. {
  4609. if (strcmp (sp[2], state[j].str) == 0)
  4610. ms->state = state[j].id;
  4611. }
  4612. ms->skill_id = atoi (sp[3]);
  4613. ms->skill_lv = atoi (sp[4]);
  4614. ms->permillage = atoi (sp[5]);
  4615. ms->casttime = atoi (sp[6]);
  4616. ms->delay = atoi (sp[7]);
  4617. ms->cancel = atoi (sp[8]);
  4618. tmw_TrimStr(sp[8]);
  4619. if (strcmp (sp[8], "yes") == 0)
  4620. ms->cancel = 1;
  4621. tmw_TrimStr(sp[9]);
  4622. ms->target = atoi (sp[9]);
  4623. for (j = 0; j < sizeof (target) / sizeof (target[0]); j++)
  4624. {
  4625. if (strcmp (sp[9], target[j].str) == 0)
  4626. ms->target = target[j].id;
  4627. }
  4628. ms->cond1 = -1;
  4629. tmw_TrimStr(sp[10]);
  4630. for (j = 0; j < sizeof (cond1) / sizeof (cond1[0]); j++)
  4631. {
  4632. if (strcmp (sp[10], cond1[j].str) == 0)
  4633. ms->cond1 = cond1[j].id;
  4634. }
  4635. tmw_TrimStr(sp[11]);
  4636. ms->cond2 = atoi (sp[11]);
  4637. for (j = 0; j < sizeof (cond2) / sizeof (cond2[0]); j++)
  4638. {
  4639. if (strcmp (sp[11], cond2[j].str) == 0)
  4640. ms->cond2 = cond2[j].id;
  4641. }
  4642. tmw_TrimStr(sp[12]);
  4643. ms->cond3 = atoi (sp[12]);
  4644. ms->val[0] = atoi (sp[13]);
  4645. ms->val[1] = atoi (sp[14]);
  4646. ms->val[2] = atoi (sp[15]);
  4647. ms->val[3] = atoi (sp[16]);
  4648. ms->val[4] = atoi (sp[17]);
  4649. if (sp[17] != NULL && strlen (sp[18]) > 2)
  4650. ms->emotion = atoi (sp[18]);
  4651. else
  4652. ms->emotion = -1;
  4653. mob_db[mob_id].maxskill = i + 1;
  4654. }
  4655. fclose_ (fp);
  4656. printf ("read %s done\n", filename[x]);
  4657. }
  4658. return 0;
  4659. }
  4660. void mob_reload (void)
  4661. {
  4662. /*
  4663. *
  4664. * <empty monster database>
  4665. * mob_read();
  4666. *
  4667. */
  4668. do_init_mob ();
  4669. }
  4670. /*==========================================
  4671. * Circumference initialization of mob
  4672. *------------------------------------------
  4673. */
  4674. int do_init_mob (void)
  4675. {
  4676. mob_readdb ();
  4677. mob_readdb_mobavail ();
  4678. mob_read_randommonster ();
  4679. mob_readskilldb ();
  4680. add_timer_func_list (mob_timer, "mob_timer");
  4681. add_timer_func_list (mob_delayspawn, "mob_delayspawn");
  4682. add_timer_func_list (mob_delay_item_drop, "mob_delay_item_drop");
  4683. add_timer_func_list (mob_delay_item_drop2, "mob_delay_item_drop2");
  4684. add_timer_func_list (mob_ai_hard, "mob_ai_hard");
  4685. add_timer_func_list (mob_ai_lazy, "mob_ai_lazy");
  4686. add_timer_func_list (mobskill_castend_id, "mobskill_castend_id");
  4687. add_timer_func_list (mobskill_castend_pos, "mobskill_castend_pos");
  4688. add_timer_func_list (mob_timer_delete, "mob_timer_delete");
  4689. add_timer_interval (gettick () + MIN_MOBTHINKTIME, mob_ai_hard, 0, 0,
  4690. MIN_MOBTHINKTIME);
  4691. add_timer_interval (gettick () + MIN_MOBTHINKTIME * 10, mob_ai_lazy, 0, 0,
  4692. MIN_MOBTHINKTIME * 10);
  4693. return 0;
  4694. }