PageRenderTime 68ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 1ms

/src/map/mob.c

https://gitlab.com/evol/hercules
C | 5162 lines | 4030 code | 610 blank | 522 comment | 1590 complexity | f32c89bc52be7585eb3ac97e712f712c MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /**
  2. * This file is part of Hercules.
  3. * http://herc.ws - http://github.com/HerculesWS/Hercules
  4. *
  5. * Copyright (C) 2012-2015 Hercules Dev Team
  6. * Copyright (C) Athena Dev Teams
  7. *
  8. * Hercules is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #define HERCULES_CORE
  22. #include "config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP
  23. #include "mob.h"
  24. #include "map/atcommand.h"
  25. #include "map/battle.h"
  26. #include "map/clif.h"
  27. #include "map/date.h"
  28. #include "map/elemental.h"
  29. #include "map/guild.h"
  30. #include "map/homunculus.h"
  31. #include "map/intif.h"
  32. #include "map/itemdb.h"
  33. #include "map/log.h"
  34. #include "map/map.h"
  35. #include "map/mercenary.h"
  36. #include "map/npc.h"
  37. #include "map/party.h"
  38. #include "map/path.h"
  39. #include "map/pc.h"
  40. #include "map/pet.h"
  41. #include "map/quest.h"
  42. #include "map/script.h"
  43. #include "map/skill.h"
  44. #include "map/status.h"
  45. #include "common/HPM.h"
  46. #include "common/cbasetypes.h"
  47. #include "common/db.h"
  48. #include "common/ers.h"
  49. #include "common/memmgr.h"
  50. #include "common/nullpo.h"
  51. #include "common/random.h"
  52. #include "common/showmsg.h"
  53. #include "common/socket.h"
  54. #include "common/strlib.h"
  55. #include "common/timer.h"
  56. #include "common/utils.h"
  57. #include <math.h>
  58. #include <stdarg.h>
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. struct mob_interface mob_s;
  63. struct mob_interface *mob;
  64. #define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode.
  65. #define IDLE_SKILL_INTERVAL 10 //Active idle skills should be triggered every 1 second (1000/MIN_MOBTHINKTIME)
  66. // Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute)
  67. // in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
  68. #define MOB_LAZYSKILLPERC(md) (md->state.spotted?1000:0)
  69. // Move probability for mobs away from players (rate of 1000 minute)
  70. // in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
  71. #define MOB_LAZYMOVEPERC(md) ((md)->state.spotted?1000:0)
  72. #define MOB_MAX_DELAY (24*3600*1000)
  73. #define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
  74. #define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
  75. //Dynamic item drop ratio database for per-item drop ratio modifiers overriding global drop ratios.
  76. #define MAX_ITEMRATIO_MOBS 10
  77. struct item_drop_ratio {
  78. int drop_ratio;
  79. int mob_id[MAX_ITEMRATIO_MOBS];
  80. };
  81. static struct item_drop_ratio *item_drop_ratio_db[MAX_ITEMDB];
  82. static struct eri *item_drop_ers; //For loot drops delay structures.
  83. static struct eri *item_drop_list_ers;
  84. static struct {
  85. int qty;
  86. int class_[350];
  87. } summon[MAX_RANDOMMONSTER];
  88. struct mob_db *mob_db(int index) {
  89. if (index < 0 || index > MAX_MOB_DB || mob->db_data[index] == NULL)
  90. return mob->dummy;
  91. return mob->db_data[index];
  92. }
  93. struct mob_chat *mob_chat(short id) {
  94. if(id <= 0 || id > MAX_MOB_CHAT || mob->chat_db[id] == NULL)
  95. return NULL;
  96. return mob->chat_db[id];
  97. }
  98. /*==========================================
  99. * Mob is searched with a name.
  100. *------------------------------------------*/
  101. int mobdb_searchname(const char *str)
  102. {
  103. int i;
  104. nullpo_ret(str);
  105. for(i=0;i<=MAX_MOB_DB;i++){
  106. struct mob_db *monster = mob->db(i);
  107. if(monster == mob->dummy) //Skip dummy mobs.
  108. continue;
  109. if(strcmpi(monster->name,str)==0 || strcmpi(monster->jname,str)==0)
  110. return i;
  111. if(battle_config.case_sensitive_aegisnames && strcmp(monster->sprite,str)==0)
  112. return i;
  113. if(!battle_config.case_sensitive_aegisnames && strcasecmp(monster->sprite,str)==0)
  114. return i;
  115. }
  116. return 0;
  117. }
  118. int mobdb_searchname_array_sub(struct mob_db* monster, const char *str, int flag) {
  119. nullpo_ret(monster);
  120. if (monster == mob->dummy)
  121. return 1;
  122. if(!monster->base_exp && !monster->job_exp && monster->spawn[0].qty < 1)
  123. return 1; // Monsters with no base/job exp and no spawn point are, by this criteria, considered "slave mobs" and excluded from search results
  124. nullpo_ret(str);
  125. if( !flag ) {
  126. if(stristr(monster->jname,str))
  127. return 0;
  128. if(stristr(monster->name,str))
  129. return 0;
  130. } else {
  131. if(strcmpi(monster->jname,str) == 0)
  132. return 0;
  133. if(strcmpi(monster->name,str) == 0)
  134. return 0;
  135. }
  136. if (battle_config.case_sensitive_aegisnames)
  137. return strcmp(monster->sprite,str);
  138. return strcasecmp(monster->sprite,str);
  139. }
  140. /*==========================================
  141. * MvP Tomb [GreenBox]
  142. *------------------------------------------*/
  143. void mvptomb_create(struct mob_data *md, char *killer, time_t time)
  144. {
  145. struct npc_data *nd;
  146. nullpo_retv(md);
  147. if ( md->tomb_nid )
  148. mob->mvptomb_destroy(md);
  149. nd = npc->create_npc(TOMB, md->bl.m, md->bl.x, md->bl.y, md->ud.dir, MOB_TOMB);
  150. md->tomb_nid = nd->bl.id;
  151. safestrncpy(nd->name, msg_txt(856), sizeof(nd->name)); // "Tomb"
  152. nd->u.tomb.md = md;
  153. nd->u.tomb.kill_time = time;
  154. if (killer)
  155. safestrncpy(nd->u.tomb.killer_name, killer, NAME_LENGTH);
  156. else
  157. nd->u.tomb.killer_name[0] = '\0';
  158. map->addnpc(nd->bl.m, nd);
  159. map->addblock(&nd->bl);
  160. status->set_viewdata(&nd->bl, nd->class_);
  161. clif->spawn(&nd->bl);
  162. }
  163. void mvptomb_destroy(struct mob_data *md) {
  164. struct npc_data *nd;
  165. nullpo_retv(md);
  166. if ( (nd = map->id2nd(md->tomb_nid)) ) {
  167. int16 m, i;
  168. m = nd->bl.m;
  169. clif->clearunit_area(&nd->bl,CLR_OUTSIGHT);
  170. map->delblock(&nd->bl);
  171. ARR_FIND( 0, map->list[m].npc_num, i, map->list[m].npc[i] == nd );
  172. if( !(i == map->list[m].npc_num) ) {
  173. map->list[m].npc_num--;
  174. map->list[m].npc[i] = map->list[m].npc[map->list[m].npc_num];
  175. map->list[m].npc[map->list[m].npc_num] = NULL;
  176. }
  177. map->deliddb(&nd->bl);
  178. aFree(nd);
  179. }
  180. md->tomb_nid = 0;
  181. }
  182. /*==========================================
  183. * Founds up to N matches. Returns number of matches [Skotlex]
  184. *------------------------------------------*/
  185. int mobdb_searchname_array(struct mob_db** data, int size, const char *str, int flag)
  186. {
  187. int count = 0, i;
  188. struct mob_db* monster;
  189. nullpo_ret(data);
  190. for(i=0;i<=MAX_MOB_DB;i++){
  191. monster = mob->db(i);
  192. if (monster == mob->dummy || mob->is_clone(i) ) //keep clones out (or you leak player stats)
  193. continue;
  194. if (!mob->db_searchname_array_sub(monster, str, flag)) {
  195. if (count < size)
  196. data[count] = monster;
  197. count++;
  198. }
  199. }
  200. return count;
  201. }
  202. /*==========================================
  203. * Id Mob is checked.
  204. *------------------------------------------*/
  205. int mobdb_checkid(const int id)
  206. {
  207. if (mob->db(id) == mob->dummy)
  208. return 0;
  209. if (mob->is_clone(id)) //checkid is used mostly for random ID based code, therefore clone mobs are out of the question.
  210. return 0;
  211. return id;
  212. }
  213. /*==========================================
  214. * Returns the view data associated to this mob class.
  215. *------------------------------------------*/
  216. struct view_data * mob_get_viewdata(int class_)
  217. {
  218. if (mob->db(class_) == mob->dummy)
  219. return 0;
  220. return &mob->db(class_)->vd;
  221. }
  222. /*==========================================
  223. * Cleans up mob-spawn data to make it "valid"
  224. *------------------------------------------*/
  225. int mob_parse_dataset(struct spawn_data *data)
  226. {
  227. size_t len;
  228. nullpo_ret(data);
  229. if ((!mob->db_checkid(data->class_) && !mob->is_clone(data->class_)) || !data->num)
  230. return 0;
  231. if( ( len = strlen(data->eventname) ) > 0 )
  232. {
  233. if( data->eventname[len-1] == '"' )
  234. data->eventname[len-1] = '\0'; //Remove trailing quote.
  235. if( data->eventname[0] == '"' ) //Strip leading quotes
  236. memmove(data->eventname, data->eventname+1, len-1);
  237. }
  238. if(strcmp(data->name,"--en--")==0)
  239. safestrncpy(data->name, mob->db(data->class_)->name, sizeof(data->name));
  240. else if(strcmp(data->name,"--ja--")==0)
  241. safestrncpy(data->name, mob->db(data->class_)->jname, sizeof(data->name));
  242. return 1;
  243. }
  244. /*==========================================
  245. * Generates the basic mob data using the spawn_data provided.
  246. *------------------------------------------*/
  247. struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
  248. struct mob_data *md = NULL;
  249. nullpo_retr(NULL, data);
  250. CREATE(md, struct mob_data, 1);
  251. md->bl.id= npc->get_new_npc_id();
  252. md->bl.type = BL_MOB;
  253. md->bl.m = data->m;
  254. md->bl.x = data->x;
  255. md->bl.y = data->y;
  256. md->class_ = data->class_;
  257. md->state.boss = data->state.boss;
  258. md->db = mob->db(md->class_);
  259. if (data->level > 0 && data->level <= MAX_LEVEL)
  260. md->level = data->level;
  261. memcpy(md->name, data->name, NAME_LENGTH);
  262. if (data->state.ai)
  263. md->special_state.ai = data->state.ai;
  264. if (data->state.size)
  265. md->special_state.size = data->state.size;
  266. if (data->eventname[0] && strlen(data->eventname) >= 4)
  267. memcpy(md->npc_event, data->eventname, 50);
  268. if(md->db->status.mode&MD_LOOTER)
  269. md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  270. md->spawn_timer = INVALID_TIMER;
  271. md->deletetimer = INVALID_TIMER;
  272. md->skill_idx = -1;
  273. status->set_viewdata(&md->bl, md->class_);
  274. status->change_init(&md->bl);
  275. unit->dataset(&md->bl);
  276. map->addiddb(&md->bl);
  277. return md;
  278. }
  279. /*==========================================
  280. * Fetches a random mob_id [Skotlex]
  281. * type: Where to fetch from:
  282. * 0: dead branch list
  283. * 1: poring list
  284. * 2: bloody branch list
  285. * flag:
  286. * &1: Apply the summon success chance found in the list (otherwise get any monster from the db)
  287. * &2: Apply a monster check level.
  288. * &4: Selected monster should not be a boss type
  289. * &8: Selected monster must have normal spawn.
  290. * lv: Mob level to check against
  291. *------------------------------------------*/
  292. int mob_get_random_id(int type, int flag, int lv)
  293. {
  294. struct mob_db *monster;
  295. int i=0, class_;
  296. if(type < 0 || type >= MAX_RANDOMMONSTER) {
  297. ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type);
  298. return 0;
  299. }
  300. Assert_ret(type >= 0 && type < MAX_RANDOMMONSTER);
  301. do {
  302. if (type)
  303. class_ = summon[type].class_[rnd()%summon[type].qty];
  304. else //Dead branch
  305. class_ = rnd() % MAX_MOB_DB;
  306. monster = mob->db(class_);
  307. } while ((monster == mob->dummy ||
  308. mob->is_clone(class_) ||
  309. (flag&1 && monster->summonper[type] <= rnd() % 1000000) ||
  310. (flag&2 && lv < monster->lv) ||
  311. (flag&4 && monster->status.mode&MD_BOSS) ||
  312. (flag&8 && monster->spawn[0].qty < 1)
  313. ) && (i++) < MAX_MOB_DB);
  314. if(i >= MAX_MOB_DB) // no suitable monster found, use fallback for given list
  315. class_ = mob->db_data[0]->summonper[type];
  316. return class_;
  317. }
  318. /*==========================================
  319. * Kill Steal Protection [Zephyrus]
  320. *------------------------------------------*/
  321. bool mob_ksprotected(struct block_list *src, struct block_list *target) {
  322. struct block_list *s_bl, *t_bl;
  323. struct map_session_data
  324. *sd, // Source
  325. *pl_sd, // Owner
  326. *t_sd; // Mob Target
  327. struct mob_data *md;
  328. int64 tick = timer->gettick();
  329. char output[128];
  330. if( !battle_config.ksprotection )
  331. return false; // KS Protection Disabled
  332. if( !(md = BL_CAST(BL_MOB,target)) )
  333. return false; // Target is not MOB
  334. if( (s_bl = battle->get_master(src)) == NULL )
  335. s_bl = src;
  336. if( !(sd = BL_CAST(BL_PC,s_bl)) )
  337. return false; // Master is not PC
  338. t_bl = map->id2bl(md->target_id);
  339. if( !t_bl || (s_bl = battle->get_master(t_bl)) == NULL )
  340. s_bl = t_bl;
  341. t_sd = BL_CAST(BL_PC,s_bl);
  342. do {
  343. struct status_change_entry *sce;
  344. if( map->list[md->bl.m].flag.allowks || map_flag_ks(md->bl.m) )
  345. return false; // Ignores GVG, PVP and AllowKS map flags
  346. if( md->db->mexp || md->master_id )
  347. return false; // MVP, Slaves mobs ignores KS
  348. if( (sce = md->sc.data[SC_KSPROTECTED]) == NULL )
  349. break; // No KS Protected
  350. if( sd->bl.id == sce->val1 || // Same Owner
  351. (sce->val2 == KSPROTECT_PARTY && sd->status.party_id && sd->status.party_id == sce->val3) || // Party KS allowed
  352. (sce->val2 == KSPROTECT_GUILD && sd->status.guild_id && sd->status.guild_id == sce->val4) ) // Guild KS allowed
  353. break;
  354. if( t_sd && (
  355. (sce->val2 == KSPROTECT_SELF && sce->val1 != t_sd->bl.id) ||
  356. (sce->val2 == KSPROTECT_PARTY && sce->val3 && sce->val3 != t_sd->status.party_id) ||
  357. (sce->val2 == KSPROTECT_GUILD && sce->val4 && sce->val4 != t_sd->status.guild_id)) )
  358. break;
  359. if( (pl_sd = map->id2sd(sce->val1)) == NULL || pl_sd->bl.m != md->bl.m )
  360. break;
  361. if( !pl_sd->state.noks )
  362. return false; // No KS Protected, but normal players should be protected too
  363. // Message to KS
  364. if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 )
  365. {
  366. sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name);
  367. clif_disp_onlyself(sd, output, strlen(output));
  368. sd->ks_floodprotect_tick = tick + 2000;
  369. }
  370. // Message to Owner
  371. if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 )
  372. {
  373. sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name);
  374. clif_disp_onlyself(pl_sd, output, strlen(output));
  375. pl_sd->ks_floodprotect_tick = tick + 2000;
  376. }
  377. return true;
  378. } while(0);
  379. status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks,
  380. sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, SCFLAG_NONE);
  381. return false;
  382. }
  383. struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai)
  384. {
  385. struct spawn_data data;
  386. memset(&data, 0, sizeof(struct spawn_data));
  387. data.m = m;
  388. data.num = 1;
  389. data.class_ = class_;
  390. data.state.size = size;
  391. data.state.ai = ai;
  392. if (mobname)
  393. safestrncpy(data.name, mobname, sizeof(data.name));
  394. else
  395. if (battle_config.override_mob_names == 1)
  396. strcpy(data.name, "--en--");
  397. else
  398. strcpy(data.name, "--ja--");
  399. if (event)
  400. safestrncpy(data.eventname, event, sizeof(data.eventname));
  401. // Locate spot next to player.
  402. if (bl && (x < 0 || y < 0))
  403. map->search_freecell(bl, m, &x, &y, 1, 1, 0);
  404. // if none found, pick random position on map
  405. if (x <= 0 || x >= map->list[m].xs || y <= 0 || y >= map->list[m].ys)
  406. map->search_freecell(NULL, m, &x, &y, -1, -1, 1);
  407. data.x = x;
  408. data.y = y;
  409. if (!mob->parse_dataset(&data))
  410. return NULL;
  411. return mob->spawn_dataset(&data);
  412. }
  413. /*==========================================
  414. * Spawn a single mob on the specified coordinates.
  415. *------------------------------------------*/
  416. int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) {
  417. struct mob_data* md = NULL;
  418. int count, lv;
  419. bool no_guardian_data = false;
  420. if( ai && ai&0x200 ) {
  421. no_guardian_data = true;
  422. ai &=~ 0x200;
  423. }
  424. if (m < 0 || amount <= 0)
  425. return 0; // invalid input
  426. lv = (sd) ? sd->status.base_level : 255;
  427. for (count = 0; count < amount; count++) {
  428. int c = (class_ >= 0) ? class_ : mob->get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv);
  429. md = mob->once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai);
  430. if (!md)
  431. continue;
  432. if (class_ == MOBID_EMPELIUM && !no_guardian_data) {
  433. struct guild_castle* gc = guild->mapindex2gc(map_id2index(m));
  434. struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL;
  435. if( gc ) {
  436. md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data));
  437. md->guardian_data->castle = gc;
  438. md->guardian_data->number = MAX_GUARDIANS;
  439. if( g )
  440. md->guardian_data->g = g;
  441. else if( gc->guild_id ) //Guild not yet available, retry in 5.
  442. timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id);
  443. }
  444. } // end addition [Valaris]
  445. mob->spawn(md);
  446. if (class_ < 0 && battle_config.dead_branch_active) {
  447. //Behold Aegis's masterful decisions yet again...
  448. //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3
  449. sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000);
  450. }
  451. }
  452. return (md) ? md->bl.id : 0; // id of last spawned mob
  453. }
  454. /*==========================================
  455. * Spawn mobs in the specified area.
  456. *------------------------------------------*/
  457. int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai)
  458. {
  459. int i, max, id = 0;
  460. int lx = -1, ly = -1;
  461. if (m < 0 || amount <= 0)
  462. return 0; // invalid input
  463. // normalize x/y coordinates
  464. if (x0 > x1)
  465. swap(x0, x1);
  466. if (y0 > y1)
  467. swap(y0, y1);
  468. // choose a suitable max. number of attempts
  469. max = (y1 - y0 + 1)*(x1 - x0 + 1)*3;
  470. if (max > 1000)
  471. max = 1000;
  472. // spawn mobs, one by one
  473. for (i = 0; i < amount; i++)
  474. {
  475. int x, y;
  476. int j = 0;
  477. // find a suitable map cell
  478. do {
  479. x = rnd()%(x1-x0+1)+x0;
  480. y = rnd()%(y1-y0+1)+y0;
  481. j++;
  482. } while (map->getcell(m, NULL, x, y, CELL_CHKNOPASS) && j < max);
  483. if (j == max)
  484. {// attempt to find an available cell failed
  485. if (lx == -1 && ly == -1)
  486. return 0; // total failure
  487. // fallback to last good x/y pair
  488. x = lx;
  489. y = ly;
  490. }
  491. // record last successful coordinates
  492. lx = x;
  493. ly = y;
  494. id = mob->once_spawn(sd, m, x, y, mobname, class_, 1, event, size, ai);
  495. }
  496. return id; // id of last spawned mob
  497. }
  498. /**
  499. * Sets a guardian's guild data and liberates castle if couldn't retrieve guild data
  500. * @param data (int)guild_id
  501. * @retval Always 0
  502. * @author Skotlex
  503. **/
  504. int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) {
  505. //Needed because the guild data may not be available at guardian spawn time.
  506. struct block_list* bl = map->id2bl(id);
  507. struct mob_data* md;
  508. struct guild* g;
  509. if( bl == NULL ) //It is possible mob was already removed from map when the castle has no owner. [Skotlex]
  510. return 0;
  511. Assert_ret(bl->type == BL_MOB);
  512. md = BL_UCAST(BL_MOB, bl);
  513. nullpo_ret(md->guardian_data);
  514. g = guild->search((int)data);
  515. if( g == NULL ) { //Liberate castle, if the guild is not found this is an error! [Skotlex]
  516. ShowError("mob_spawn_guardian_sub: Couldn't load guild %d!\n", (int)data);
  517. //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on.
  518. if (md->class_ == MOBID_EMPELIUM && md->guardian_data) {
  519. md->guardian_data->g = NULL;
  520. if( md->guardian_data->castle->guild_id ) {//Free castle up.
  521. ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name);
  522. guild->castledatasave(md->guardian_data->castle->castle_id, 1, 0);
  523. }
  524. } else {
  525. if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS
  526. && md->guardian_data->castle->guardian[md->guardian_data->number].visible )
  527. guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
  528. unit->free(&md->bl,CLR_OUTSIGHT); // Remove guardian.
  529. }
  530. return 0;
  531. }
  532. if( guild->checkskill(g,GD_GUARDUP) )
  533. status_calc_mob(md, SCO_NONE); // Give bonuses.
  534. return 0;
  535. }
  536. //++++++++
  537. /*==========================================
  538. * Summoning Guardians [Valaris]
  539. *------------------------------------------*/
  540. int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index)
  541. {
  542. struct mob_data *md=NULL;
  543. struct spawn_data data;
  544. struct guild *g=NULL;
  545. struct guild_castle *gc;
  546. int16 m;
  547. memset(&data, 0, sizeof(struct spawn_data));
  548. data.num = 1;
  549. m=map->mapname2mapid(mapname);
  550. if(m<0)
  551. {
  552. ShowWarning("mob_spawn_guardian: Map [%s] not found.\n", mapname);
  553. return 0;
  554. }
  555. data.m = m;
  556. data.num = 1;
  557. if(class_<=0) {
  558. class_ = mob->get_random_id(-class_-1, 1, 99);
  559. if (!class_) return 0;
  560. }
  561. data.class_ = class_;
  562. if( !has_index ) {
  563. guardian = -1;
  564. } else if( guardian < 0 || guardian >= MAX_GUARDIANS ) {
  565. ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map->list[m].name);
  566. return 0;
  567. }
  568. if((x<=0 || y<=0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1)) {
  569. ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map->list[m].name);
  570. return 0;
  571. }
  572. data.x = x;
  573. data.y = y;
  574. safestrncpy(data.name, mobname, sizeof(data.name));
  575. safestrncpy(data.eventname, event, sizeof(data.eventname));
  576. if (!mob->parse_dataset(&data))
  577. return 0;
  578. gc=guild->mapname2gc(map->list[m].name);
  579. if (gc == NULL) {
  580. ShowError("mob_spawn_guardian: No castle set at map %s\n", map->list[m].name);
  581. return 0;
  582. }
  583. if (!gc->guild_id)
  584. ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map->list[m].name);
  585. else
  586. g = guild->search(gc->guild_id);
  587. if( has_index && gc->guardian[guardian].id ) {
  588. //Check if guardian already exists, refuse to spawn if so.
  589. struct block_list *bl2 = map->id2bl(gc->guardian[guardian].id); // TODO: Why does this not use map->id2md?
  590. struct mob_data *md2 = BL_CAST(BL_MOB, bl2);
  591. if (md2 != NULL && md2->guardian_data != NULL && md2->guardian_data->number == guardian) {
  592. ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map->list[m].name);
  593. return 0;
  594. }
  595. }
  596. md = mob->spawn_dataset(&data);
  597. md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data));
  598. md->guardian_data->number = guardian;
  599. md->guardian_data->castle = gc;
  600. if( has_index )
  601. {// permanent guardian
  602. gc->guardian[guardian].id = md->bl.id;
  603. }
  604. else
  605. {// temporary guardian
  606. int i;
  607. ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == 0);
  608. if( i == gc->temp_guardians_max )
  609. {
  610. ++(gc->temp_guardians_max);
  611. RECREATE(gc->temp_guardians, int, gc->temp_guardians_max);
  612. }
  613. gc->temp_guardians[i] = md->bl.id;
  614. }
  615. if( g )
  616. md->guardian_data->g = g;
  617. else if( gc->guild_id )
  618. timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id);
  619. mob->spawn(md);
  620. return md->bl.id;
  621. }
  622. /*==========================================
  623. * Summoning BattleGround [Zephyrus]
  624. *------------------------------------------*/
  625. int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, unsigned int bg_id)
  626. {
  627. struct mob_data *md = NULL;
  628. struct spawn_data data;
  629. int16 m;
  630. if( (m = map->mapname2mapid(mapname)) < 0 ) {
  631. ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname);
  632. return 0;
  633. }
  634. memset(&data, 0, sizeof(struct spawn_data));
  635. data.m = m;
  636. data.num = 1;
  637. if( class_ <= 0 )
  638. {
  639. class_ = mob->get_random_id(-class_-1,1,99);
  640. if( !class_ ) return 0;
  641. }
  642. data.class_ = class_;
  643. if( (x <= 0 || y <= 0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1) ) {
  644. ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map->list[m].name);
  645. return 0;
  646. }
  647. data.x = x;
  648. data.y = y;
  649. safestrncpy(data.name, mobname, sizeof(data.name));
  650. safestrncpy(data.eventname, event, sizeof(data.eventname));
  651. if( !mob->parse_dataset(&data) )
  652. return 0;
  653. md = mob->spawn_dataset(&data);
  654. mob->spawn(md);
  655. md->bg_id = bg_id; // BG Team ID
  656. return md->bl.id;
  657. }
  658. /*==========================================
  659. * Reachability to a Specification ID existence place
  660. * state indicates type of 'seek' mob should do:
  661. * - MSS_LOOT: Looking for item, path must be easy.
  662. * - MSS_RUSH: Chasing attacking player, path is complex
  663. * - MSS_FOLLOW: Initiative/support seek, path is complex
  664. *------------------------------------------*/
  665. int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state)
  666. {
  667. int easy = 0;
  668. nullpo_ret(md);
  669. nullpo_ret(bl);
  670. switch (state) {
  671. case MSS_RUSH:
  672. case MSS_FOLLOW:
  673. easy = 0; //(battle_config.mob_ai&0x1?0:1);
  674. break;
  675. case MSS_LOOT:
  676. default:
  677. easy = 1;
  678. break;
  679. }
  680. return unit->can_reach_bl(&md->bl, bl, range, easy, NULL, NULL);
  681. }
  682. /*==========================================
  683. * Links nearby mobs (supportive mobs)
  684. *------------------------------------------*/
  685. int mob_linksearch(struct block_list *bl,va_list ap)
  686. {
  687. struct mob_data *md = NULL;
  688. int class_ = va_arg(ap, int);
  689. struct block_list *target = va_arg(ap, struct block_list *);
  690. int64 tick = va_arg(ap, int64);
  691. nullpo_ret(bl);
  692. Assert_ret(bl->type == BL_MOB);
  693. md = BL_UCAST(BL_MOB, bl);
  694. if (md->class_ == class_ && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME
  695. && !md->target_id)
  696. {
  697. md->last_linktime = tick;
  698. if (mob->can_reach(md,target,md->db->range2, MSS_FOLLOW)) {
  699. // Reachability judging
  700. md->target_id = target->id;
  701. md->min_chase=md->db->range3;
  702. return 1;
  703. }
  704. }
  705. return 0;
  706. }
  707. /*==========================================
  708. * mob spawn with delay (timer function)
  709. *------------------------------------------*/
  710. int mob_delayspawn(int tid, int64 tick, int id, intptr_t data) {
  711. struct block_list* bl = map->id2bl(id); // TODO: Why does this not use map->bl2md?
  712. struct mob_data* md = BL_CAST(BL_MOB, bl);
  713. if( md )
  714. {
  715. if( md->spawn_timer != tid )
  716. {
  717. ShowError("mob_delayspawn: Timer mismatch: %d != %d\n", tid, md->spawn_timer);
  718. return 0;
  719. }
  720. md->spawn_timer = INVALID_TIMER;
  721. mob->spawn(md);
  722. }
  723. return 0;
  724. }
  725. /*==========================================
  726. * spawn timing calculation
  727. *------------------------------------------*/
  728. int mob_setdelayspawn(struct mob_data *md)
  729. {
  730. unsigned int spawntime, mode;
  731. struct mob_db *db;
  732. if (!md->spawn) //Doesn't has respawn data!
  733. return unit->free(&md->bl,CLR_DEAD);
  734. spawntime = md->spawn->delay1; //Base respawn time
  735. if (md->spawn->delay2) //random variance
  736. spawntime+= rnd()%md->spawn->delay2;
  737. //Apply the spawn delay fix [Skotlex]
  738. db = mob->db(md->spawn->class_);
  739. mode = db->status.mode;
  740. if (mode & MD_BOSS) {
  741. //Bosses
  742. if (battle_config.boss_spawn_delay != 100) {
  743. // Divide by 100 first to prevent overflows
  744. //(precision loss is minimal as duration is in ms already)
  745. spawntime = spawntime/100*battle_config.boss_spawn_delay;
  746. }
  747. } else if (mode&MD_PLANT) {
  748. //Plants
  749. if (battle_config.plant_spawn_delay != 100) {
  750. spawntime = spawntime/100*battle_config.plant_spawn_delay;
  751. }
  752. } else if (battle_config.mob_spawn_delay != 100) {
  753. //Normal mobs
  754. spawntime = spawntime/100*battle_config.mob_spawn_delay;
  755. }
  756. if (spawntime < 5000) //Monsters should never respawn faster than within 5 seconds
  757. spawntime = 5000;
  758. if( md->spawn_timer != INVALID_TIMER )
  759. timer->delete(md->spawn_timer, mob->delayspawn);
  760. md->spawn_timer = timer->add(timer->gettick()+spawntime, mob->delayspawn, md->bl.id, 0);
  761. return 0;
  762. }
  763. int mob_count_sub(struct block_list *bl, va_list ap) {
  764. int mobid[10] = { 0 }, i;
  765. ARR_FIND(0, 10, i, (mobid[i] = va_arg(ap, int)) == 0); //fetch till 0
  766. if (mobid[0]) { //if there one let's check it otherwise go backward
  767. struct mob_data *md = BL_CAST(BL_MOB, bl);
  768. nullpo_ret(md);
  769. ARR_FIND(0, 10, i, md->class_ == mobid[i]);
  770. return (i < 10) ? 1 : 0;
  771. }
  772. return 1; //backward compatibility
  773. }
  774. /*==========================================
  775. * Mob spawning. Initialization is also variously here.
  776. *------------------------------------------*/
  777. int mob_spawn (struct mob_data *md)
  778. {
  779. int i=0;
  780. int64 tick = timer->gettick();
  781. int64 c = 0;
  782. md->last_thinktime = tick;
  783. if (md->bl.prev != NULL)
  784. unit->remove_map(&md->bl,CLR_RESPAWN,ALC_MARK);
  785. else if (md->spawn && md->class_ != md->spawn->class_) {
  786. md->class_ = md->spawn->class_;
  787. status->set_viewdata(&md->bl, md->class_);
  788. md->db = mob->db(md->class_);
  789. memcpy(md->name,md->spawn->name,NAME_LENGTH);
  790. }
  791. if (md->spawn) { //Respawn data
  792. md->bl.m = md->spawn->m;
  793. md->bl.x = md->spawn->x;
  794. md->bl.y = md->spawn->y;
  795. if( (md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs || md->spawn->ys ) {
  796. //Monster can be spawned on an area.
  797. if( !map->search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs, md->spawn->ys, battle_config.no_spawn_on_player?4:0) ) {
  798. // retry again later
  799. if( md->spawn_timer != INVALID_TIMER )
  800. timer->delete(md->spawn_timer, mob->delayspawn);
  801. md->spawn_timer = timer->add(tick+5000,mob->delayspawn,md->bl.id,0);
  802. return 1;
  803. }
  804. } else if( battle_config.no_spawn_on_player > 99 && map->foreachinrange(mob->count_sub, &md->bl, AREA_SIZE, BL_PC) ) {
  805. // retry again later (players on sight)
  806. if( md->spawn_timer != INVALID_TIMER )
  807. timer->delete(md->spawn_timer, mob->delayspawn);
  808. md->spawn_timer = timer->add(tick+5000,mob->delayspawn,md->bl.id,0);
  809. return 1;
  810. }
  811. }
  812. memset(&md->state, 0, sizeof(md->state));
  813. status_calc_mob(md, SCO_FIRST);
  814. md->attacked_id = 0;
  815. md->target_id = 0;
  816. md->move_fail_count = 0;
  817. md->ud.state.attack_continue = 0;
  818. md->ud.target_to = 0;
  819. md->ud.dir = 0;
  820. if( md->spawn_timer != INVALID_TIMER )
  821. {
  822. timer->delete(md->spawn_timer, mob->delayspawn);
  823. md->spawn_timer = INVALID_TIMER;
  824. }
  825. //md->master_id = 0;
  826. md->master_dist = 0;
  827. md->state.aggressive = (md->status.mode&MD_ANGRY) ? 1 : 0;
  828. md->state.skillstate = MSS_IDLE;
  829. md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME;
  830. md->last_linktime = tick;
  831. md->dmgtick = tick - 5000;
  832. md->last_pcneartime = 0;
  833. for (i = 0, c = tick-MOB_MAX_DELAY; i < MAX_MOBSKILL; i++)
  834. md->skilldelay[i] = c;
  835. memset(md->dmglog, 0, sizeof(md->dmglog));
  836. md->tdmg = 0;
  837. if (md->lootitem)
  838. memset(md->lootitem, 0, sizeof(*md->lootitem));
  839. md->lootitem_count = 0;
  840. if(md->db->option)
  841. // Added for carts, falcons and pecos for cloned monsters. [Valaris]
  842. md->sc.option = md->db->option;
  843. // MvP tomb [GreenBox]
  844. if ( md->tomb_nid )
  845. mob->mvptomb_destroy(md);
  846. map->addblock(&md->bl);
  847. if( map->list[md->bl.m].users )
  848. clif->spawn(&md->bl);
  849. skill->unit_move(&md->bl,tick,1);
  850. mob->skill_use(md, tick, MSC_SPAWN);
  851. return 0;
  852. }
  853. /*==========================================
  854. * Determines if the mob can change target. [Skotlex]
  855. *------------------------------------------*/
  856. int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mode)
  857. {
  858. // if the monster was provoked ignore the above rule [celest]
  859. if(md->state.provoke_flag)
  860. {
  861. if (md->state.provoke_flag == target->id)
  862. return 1;
  863. else if (!(battle_config.mob_ai&0x4))
  864. return 0;
  865. }
  866. switch (md->state.skillstate) {
  867. case MSS_BERSERK:
  868. if (!(mode&MD_CHANGETARGET_MELEE))
  869. return 0;
  870. return (battle_config.mob_ai&0x4 || check_distance_bl(&md->bl, target, 3));
  871. case MSS_RUSH:
  872. return (mode&MD_CHANGETARGET_CHASE);
  873. case MSS_FOLLOW:
  874. case MSS_ANGRY:
  875. case MSS_IDLE:
  876. case MSS_WALK:
  877. case MSS_LOOT:
  878. return 1;
  879. default:
  880. return 0;
  881. }
  882. }
  883. /*==========================================
  884. * Determination for an attack of a monster
  885. *------------------------------------------*/
  886. int mob_target(struct mob_data *md,struct block_list *bl,int dist)
  887. {
  888. nullpo_ret(md);
  889. nullpo_ret(bl);
  890. // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
  891. if(md->target_id && !mob->can_changetarget(md, bl, status_get_mode(&md->bl)))
  892. return 0;
  893. if(!status->check_skilluse(&md->bl, bl, 0, 0))
  894. return 0;
  895. md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
  896. if (md->state.provoke_flag && bl->id != md->state.provoke_flag)
  897. md->state.provoke_flag = 0;
  898. md->min_chase=dist+md->db->range3;
  899. if(md->min_chase>MAX_MINCHASE)
  900. md->min_chase=MAX_MINCHASE;
  901. return 0;
  902. }
  903. /*==========================================
  904. * The ?? routine of an active monster
  905. *------------------------------------------*/
  906. int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
  907. {
  908. struct mob_data *md;
  909. struct block_list **target;
  910. int mode;
  911. int dist;
  912. nullpo_ret(bl);
  913. md=va_arg(ap,struct mob_data *);
  914. target= va_arg(ap,struct block_list**);
  915. mode= va_arg(ap,int);
  916. //If can't seek yet, not an enemy, or you can't attack it, skip.
  917. if (md->bl.id == bl->id || (*target) == bl || !status->check_skilluse(&md->bl, bl, 0, 0))
  918. return 0;
  919. if ((mode&MD_TARGETWEAK) && status->get_lv(bl) >= md->level-5)
  920. return 0;
  921. if(battle->check_target(&md->bl,bl,BCT_ENEMY)<=0)
  922. return 0;
  923. switch (bl->type) {
  924. case BL_PC:
  925. if (BL_UCCAST(BL_PC, bl)->state.gangsterparadise && !(status_get_mode(&md->bl)&MD_BOSS))
  926. return 0; //Gangster paradise protection.
  927. default:
  928. if (battle_config.hom_setting&0x4 &&
  929. (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM)
  930. return 0; //For some reason Homun targets are never overridden.
  931. dist = distance_bl(&md->bl, bl);
  932. if(
  933. ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) &&
  934. battle->check_range(&md->bl,bl,md->db->range2)
  935. ) { //Pick closest target?
  936. #ifdef ACTIVEPATHSEARCH
  937. struct walkpath_data wpd;
  938. if (!path->search(&wpd, &md->bl, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells
  939. return 0;
  940. //Standing monsters use range2, walking monsters use range3
  941. if ((md->ud.walktimer == INVALID_TIMER && wpd.path_len > md->db->range2)
  942. || (md->ud.walktimer != INVALID_TIMER && wpd.path_len > md->db->range3))
  943. return 0;
  944. #endif
  945. (*target) = bl;
  946. md->target_id=bl->id;
  947. md->min_chase= dist + md->db->range3;
  948. if(md->min_chase>MAX_MINCHASE)
  949. md->min_chase=MAX_MINCHASE;
  950. return 1;
  951. }
  952. break;
  953. }
  954. return 0;
  955. }
  956. /*==========================================
  957. * chase target-change routine.
  958. *------------------------------------------*/
  959. int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) {
  960. struct mob_data *md;
  961. struct block_list **target;
  962. nullpo_ret(bl);
  963. md=va_arg(ap,struct mob_data *);
  964. target= va_arg(ap,struct block_list**);
  965. //If can't seek yet, not an enemy, or you can't attack it, skip.
  966. if( md->bl.id == bl->id || *target == bl
  967. || battle->check_target(&md->bl,bl,BCT_ENEMY) <= 0
  968. || !status->check_skilluse(&md->bl, bl, 0, 0)
  969. )
  970. return 0;
  971. if(battle->check_range (&md->bl, bl, md->status.rhw.range)) {
  972. (*target) = bl;
  973. md->target_id=bl->id;
  974. md->min_chase= md->db->range3;
  975. }
  976. return 1;
  977. }
  978. /*==========================================
  979. * finds nearby bg ally for guardians looking for users to follow.
  980. *------------------------------------------*/
  981. int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
  982. struct mob_data *md;
  983. struct block_list **target;
  984. nullpo_ret(bl);
  985. md=va_arg(ap,struct mob_data *);
  986. target= va_arg(ap,struct block_list**);
  987. if( status->check_skilluse(&md->bl, bl, 0, 0) && battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ) {
  988. (*target) = bl;
  989. }
  990. return 1;
  991. }
  992. /*==========================================
  993. * loot monster item search
  994. *------------------------------------------*/
  995. int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
  996. {
  997. struct mob_data* md;
  998. struct block_list **target;
  999. int dist;
  1000. md=va_arg(ap,struct mob_data *);
  1001. target= va_arg(ap,struct block_list**);
  1002. dist=distance_bl(&md->bl, bl);
  1003. if(mob->can_reach(md,bl,dist+1, MSS_LOOT) &&
  1004. ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one.
  1005. ) {
  1006. (*target) = bl;
  1007. md->target_id=bl->id;
  1008. md->min_chase=md->db->range3;
  1009. }
  1010. return 0;
  1011. }
  1012. int mob_warpchase_sub(struct block_list *bl,va_list ap) {
  1013. int cur_distance;
  1014. struct block_list *target = va_arg(ap, struct block_list *);
  1015. struct npc_data **target_nd = va_arg(ap, struct npc_data **);
  1016. int *min_distance = va_arg(ap, int *);
  1017. struct npc_data *nd = NULL;
  1018. nullpo_ret(bl);
  1019. Assert_ret(bl->type == BL_NPC);
  1020. nd = BL_UCAST(BL_NPC, bl);
  1021. if(nd->subtype != WARP)
  1022. return 0; //Not a warp
  1023. if(nd->u.warp.mapindex != map_id2index(target->m))
  1024. return 0; //Does not lead to the same map.
  1025. cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y);
  1026. if (cur_distance < *min_distance) {
  1027. //Pick warp that leads closest to target.
  1028. *target_nd = nd;
  1029. *min_distance = cur_distance;
  1030. return 1;
  1031. }
  1032. return 0;
  1033. }
  1034. /*==========================================
  1035. * Processing of slave monsters
  1036. *------------------------------------------*/
  1037. int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
  1038. struct block_list *bl;
  1039. bl=map->id2bl(md->master_id);
  1040. if (!bl || status->isdead(bl)) {
  1041. status_kill(&md->bl);
  1042. return 1;
  1043. }
  1044. if (bl->prev == NULL)
  1045. return 0; //Master not on a map? Could be warping, do not process.
  1046. if (status_get_mode(&md->bl)&MD_CANMOVE) {
  1047. //If the mob can move, follow around. [Check by Skotlex]
  1048. int old_dist;
  1049. // Distance with between slave and master is measured.
  1050. old_dist=md->master_dist;
  1051. md->master_dist=distance_bl(&md->bl, bl);
  1052. // Since the master was in near immediately before, teleport is carried out and it pursues.
  1053. if(bl->m != md->bl.m ||
  1054. (old_dist<10 && md->master_dist>18) ||
  1055. md->master_dist > MAX_MINCHASE
  1056. ){
  1057. md->master_dist = 0;
  1058. unit->warp(&md->bl,bl->m,bl->x,bl->y,CLR_TELEPORT);
  1059. return 1;
  1060. }
  1061. if(md->target_id) //Slave is busy with a target.
  1062. return 0;
  1063. // Approach master if within view range, chase back to Master's area also if standing on top of the master.
  1064. if( (md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0)
  1065. && unit->can_move(&md->bl)
  1066. ) {
  1067. short x = bl->x, y = bl->y;
  1068. mob_stop_attack(md);
  1069. if(map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1)
  1070. && unit->walktoxy(&md->bl, x, y, 0))
  1071. return 1;
  1072. }
  1073. } else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) {
  1074. //Delete the summoned mob if it's in a gvg ground and the master is elsewhere. [Skotlex]
  1075. status_kill(&md->bl);
  1076. return 1;
  1077. }
  1078. //Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex]
  1079. if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) {
  1080. struct unit_data *ud = unit->bl2ud(bl);
  1081. md->last_linktime = tick;
  1082. if (ud) {
  1083. struct block_list *tbl=NULL;
  1084. if (ud->target && ud->state.attack_continue)
  1085. tbl=map->id2bl(ud->target);
  1086. else if (ud->skilltarget) {
  1087. tbl = map->id2bl(ud->skilltarget);
  1088. //Required check as skilltarget is not always an enemy. [Skotlex]
  1089. if (tbl && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0)
  1090. tbl = NULL;
  1091. }
  1092. if (tbl && status->check_skilluse(&md->bl, tbl, 0, 0)) {
  1093. md->target_id=tbl->id;
  1094. md->min_chase=md->db->range3+distance_bl(&md->bl, tbl);
  1095. if(md->min_chase>MAX_MINCHASE)
  1096. md->min_chase=MAX_MINCHASE;
  1097. return 1;
  1098. }
  1099. }
  1100. }
  1101. return 0;
  1102. }
  1103. /*==========================================
  1104. * A lock of target is stopped and mob moves to a standby state.
  1105. * This also triggers idle skill/movement since the AI can get stuck
  1106. * when trying to pick new targets when the current chosen target is
  1107. * unreachable.
  1108. *------------------------------------------*/
  1109. int mob_unlocktarget(struct mob_data *md, int64 tick) {
  1110. nullpo_ret(md);
  1111. switch (md->state.skillstate) {
  1112. case MSS_WALK:
  1113. if (md->ud.walktimer != INVALID_TIMER)
  1114. break;
  1115. //Because it is not unset when the mob finishes walking.
  1116. md->state.skillstate = MSS_IDLE;
  1117. case MSS_IDLE:
  1118. // Idle skill.
  1119. if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mob->skill_use(md, tick, -1))
  1120. break;
  1121. //Random walk.
  1122. if (!md->master_id &&
  1123. DIFF_TICK(md->next_walktime, tick) <= 0 &&
  1124. !mob->randomwalk(md,tick))
  1125. //Delay next random walk when this one failed.
  1126. md->next_walktime = tick+rnd()%1000;
  1127. break;
  1128. default:
  1129. mob_stop_attack(md);
  1130. mob_stop_walking(md, STOPWALKING_FLAG_FIXPOS); //Stop chasing.
  1131. md->state.skillstate = MSS_IDLE;
  1132. if(battle_config.mob_ai&0x8) //Walk instantly after dropping target
  1133. md->next_walktime = tick+rnd()%1000;
  1134. else
  1135. md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME;
  1136. break;
  1137. }
  1138. if (md->target_id) {
  1139. md->target_id=0;
  1140. md->ud.target_to = 0;
  1141. unit->set_target(&md->ud, 0);
  1142. }
  1143. if(battle_config.official_cell_stack_limit && map->count_oncell(md->bl.m, md->bl.x, md->bl.y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) {
  1144. unit->walktoxy(&md->bl, md->bl.x, md->bl.y, 8);
  1145. }
  1146. return 0;
  1147. }
  1148. /*==========================================
  1149. * Random walk
  1150. *------------------------------------------*/
  1151. int mob_randomwalk(struct mob_data *md, int64 tick) {
  1152. const int retrycount=20;
  1153. int i,c,d;
  1154. int speed;
  1155. nullpo_ret(md);
  1156. if(DIFF_TICK(md->next_walktime,tick)>0 ||
  1157. !unit->can_move(&md->bl) ||
  1158. !(status_get_mode(&md->bl)&MD_CANMOVE))
  1159. return 0;
  1160. d =12-md->move_fail_count;
  1161. if(d<5) d=5;
  1162. if(d>7) d=7;
  1163. for (i = 0; i < retrycount; i++) {
  1164. // Search of a movable place
  1165. int r=rnd();
  1166. int x=r%(d*2+1)-d;
  1167. int y=r/(d*2+1)%(d*2+1)-d;
  1168. x+=md->bl.x;
  1169. y+=md->bl.y;
  1170. if (((x != md->bl.x) || (y != md->bl.y)) && map->getcell(md->bl.m, &md->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&md->bl, x, y, 8)) {
  1171. break;
  1172. }
  1173. }
  1174. if(i==retrycount){
  1175. md->move_fail_count++;
  1176. if(md->move_fail_count>1000){
  1177. ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->class_,map->list[md->bl.m].name, md->bl.x, md->bl.y);
  1178. md->move_fail_count=0;
  1179. mob->spawn(md);
  1180. }
  1181. return 0;
  1182. }
  1183. speed=status->get_speed(&md->bl);
  1184. for(i=c=0;i<md->ud.walkpath.path_len;i++) {
  1185. // The next walk start time is calculated.
  1186. if(md->ud.walkpath.path[i]&1)
  1187. c+=speed*MOVE_DIAGONAL_COST/MOVE_COST;
  1188. else
  1189. c+=speed;
  1190. }
  1191. md->state.skillstate=MSS_WALK;
  1192. md->move_fail_count=0;
  1193. md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME+c;
  1194. return 1;
  1195. }
  1196. int mob_warpchase(struct mob_data *md, struct block_list *target)
  1197. {
  1198. struct npc_data *warp = NULL;
  1199. int distance = AREA_SIZE;
  1200. if (!(target && battle_config.mob_ai&0x40 && battle_config.mob_warp&1))
  1201. return 0; //Can't warp chase.
  1202. if (target->m == md->bl.m && check_distance_bl(&md->bl, target, AREA_SIZE))
  1203. return 0; //No need to do a warp chase.
  1204. if (md->ud.walktimer != INVALID_TIMER &&
  1205. map->getcell(md->bl.m, &md->bl, md->ud.to_x, md->ud.to_y, CELL_CHKNPC))
  1206. return 1; //Already walking to a warp.
  1207. //Search for warps within mob's viewing range.
  1208. map->foreachinrange(mob->warpchase_sub, &md->bl,
  1209. md->db->range2, BL_NPC, target, &warp, &distance);
  1210. if (warp && unit->walktobl(&md->bl, &warp->bl, 1, 1))
  1211. return 1;
  1212. return 0;
  1213. }
  1214. /*==========================================
  1215. * AI of MOB whose is near a Player
  1216. *------------------------------------------*/
  1217. bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
  1218. struct block_list *tbl = NULL, *abl = NULL;
  1219. int mode;
  1220. int view_range, can_move;
  1221. if(md->bl.prev == NULL || md->status.hp <= 0)
  1222. return false;
  1223. if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME)
  1224. return false;
  1225. md->last_thinktime = tick;
  1226. if (md->ud.skilltimer != INVALID_TIMER)
  1227. return false;
  1228. // Abnormalities
  1229. if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE )
  1230. || md->sc.data[SC_DEEP_SLEEP] || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {
  1231. //Should reset targets.
  1232. md->target_id = md->attacked_id = 0;
  1233. return false;
  1234. }
  1235. if (md->sc.count && md->sc.data[SC_BLIND])
  1236. view_range = 3;
  1237. else
  1238. view_range = md->db->range2;
  1239. mode = status_get_mode(&md->bl);
  1240. can_move = (mode&MD_CANMOVE)&&unit->can_move(&md->bl);
  1241. if (md->target_id) {
  1242. //Check validity of current target. [Skotlex]
  1243. struct map_session_data *tsd = NULL;
  1244. tbl = map->id2bl(md->target_id);
  1245. tsd = BL_CAST(BL_PC, tbl);
  1246. if (tbl == NULL || tbl->m != md->bl.m
  1247. || (md->ud.attacktimer == INVALID_TIMER && !status->check_skilluse(&md->bl, tbl, 0, 0))
  1248. || (md->ud.walktimer != INVALID_TIMER && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase))
  1249. || (tsd != NULL && ((tsd->state.gangsterparadise && !(mode&MD_BOSS)) || tsd->invincible_timer != INVALID_TIMER))
  1250. ) {
  1251. //No valid target
  1252. if (mob->warpchase(md, tbl))
  1253. return true; //Chasing this target.
  1254. if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)
  1255. && (tbl || md->ud.walkpath.path_pos == 0))
  1256. return true; //Walk at least "mob_chase_refresh" cells before dropping the target unless target is non-existent
  1257. mob->unlocktarget(md, tick); //Unlock target
  1258. tbl = NULL;
  1259. }
  1260. }
  1261. // Check for target change.
  1262. if (md->attacked_id && mode&MD_CANATTACK) {
  1263. if (md->attacked_id == md->target_id) {
  1264. //Rude attacked check.
  1265. if (!battle->check_range(&md->bl, tbl, md->status.rhw.range)
  1266. && ( //Can't attack back and can't reach back.
  1267. (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
  1268. || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
  1269. || md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
  1270. || md->walktoxy_fail_count > 0)
  1271. )
  1272. || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH)
  1273. )
  1274. && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
  1275. && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
  1276. && can_move && unit->escape(&md->bl, tbl, rnd()%10 +1) // Attempt escape
  1277. ) {
  1278. //Escaped
  1279. md->attacked_id = 0;
  1280. return true;
  1281. }
  1282. }
  1283. else
  1284. if( (abl = map->id2bl(md->attacked_id)) && (!tbl || mob->can_changetarget(md, abl, mode) || (md->sc.count && md->sc.data[SC__CHAOS]))) {
  1285. int dist;
  1286. if( md->bl.m != abl->m || abl->prev == NULL
  1287. || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area
  1288. || battle->check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob
  1289. || (battle_config.mob_ai&0x2 && !status->check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker
  1290. || (!battle->check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ...
  1291. && ( // Reach check
  1292. (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
  1293. || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
  1294. || md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
  1295. || md->walktoxy_fail_count > 0)
  1296. )
  1297. || !mob->can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
  1298. )
  1299. )
  1300. ) {
  1301. // Rude attacked
  1302. if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
  1303. && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move
  1304. && !tbl && unit->escape(&md->bl, abl, rnd()%10 +1)
  1305. ) {
  1306. //Escaped.
  1307. //TODO: Maybe it shouldn't attempt to run if it has another, valid target?
  1308. md->attacked_id = 0;
  1309. return true;
  1310. }
  1311. }
  1312. else
  1313. if (!(battle_config.mob_ai&0x2) && !status->check_skilluse(&md->bl, abl, 0, 0)) {
  1314. //Can't attack back, but didn't invoke a rude attacked skill...
  1315. } else {
  1316. //Attackable
  1317. if (!tbl || dist < md->status.rhw.range
  1318. || !check_distance_bl(&md->bl, tbl, dist)
  1319. || battle->get_target(tbl) != md->bl.id
  1320. ) {
  1321. //Change if the new target is closer than the actual one
  1322. //or if the previous target is not attacking the mob. [Skotlex]
  1323. md->target_id = md->attacked_id; // set target
  1324. if (md->state.attacked_count)
  1325. md->state.attacked_count--; //Should we reset rude attack count?
  1326. md->min_chase = dist+md->db->range3;
  1327. if(md->min_chase>MAX_MINCHASE)
  1328. md->min_chase=MAX_MINCHASE;
  1329. tbl = abl; //Set the new target
  1330. }
  1331. }
  1332. }
  1333. //Clear it since it's been checked for already.
  1334. md->attacked_id = 0;
  1335. }
  1336. // Processing of slave monster
  1337. if (md->master_id > 0 && mob->ai_sub_hard_slavemob(md, tick))
  1338. return true;
  1339. // Scan area for targets
  1340. if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0
  1341. && (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1)
  1342. ) {
  1343. // Scan area for items to loot, avoid trying to loot if the mob is full and can't consume the items.
  1344. map->foreachinrange (mob->ai_sub_hard_lootsearch, &md->bl, view_range, BL_ITEM, md, &tbl);
  1345. }
  1346. if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) {
  1347. map->foreachinrange (mob->ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode);
  1348. } else if ((mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) || (md->sc.count && md->sc.data[SC__CHAOS])) {
  1349. int search_size;
  1350. search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range;
  1351. map->foreachinrange (mob->ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl);
  1352. }
  1353. if (!tbl) { //No targets available.
  1354. if (mode&MD_ANGRY && !md->state.aggressive)
  1355. md->state.aggressive = 1; //Restore angry state when no targets are available.
  1356. /* bg guardians follow allies when no targets nearby */
  1357. if( md->bg_id && mode&MD_CANATTACK ) {
  1358. if( md->ud.walktimer != INVALID_TIMER )
  1359. return true;/* we are already moving */
  1360. map->foreachinrange (mob->ai_sub_hard_bg_ally, &md->bl, view_range, BL_PC, md, &tbl, mode);
  1361. if( tbl ) {
  1362. if( distance_blxy(&md->bl, tbl->x, tbl->y) <= 3 || unit->walktobl(&md->bl, tbl, 1, 1) )
  1363. return true;/* we're moving or close enough don't unlock the target. */
  1364. }
  1365. }
  1366. //This handles triggering idle/walk skill.
  1367. mob->unlocktarget(md, tick);
  1368. return true;
  1369. }
  1370. //Target exists, attack or loot as applicable.
  1371. if (tbl->type == BL_ITEM) {
  1372. //Loot time.
  1373. struct flooritem_data *fitem = BL_UCAST(BL_ITEM, tbl);
  1374. if (md->ud.target == tbl->id && md->ud.walktimer != INVALID_TIMER)
  1375. return true; //Already locked.
  1376. if (md->lootitem == NULL) {
  1377. //Can't loot...
  1378. mob->unlocktarget (md, tick);
  1379. return true;
  1380. }
  1381. if (!check_distance_bl(&md->bl, tbl, 1)) {
  1382. //Still…

Large files files are truncated, but you can click here to view the full file