/src/map/mob.c
C | 5316 lines | 4209 code | 620 blank | 487 comment | 1598 complexity | fe609cbf4779ab22df05854d298ea26e MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- // $Id: mob.c,v 1.7 2004/09/25 05:32:18 MouseJstr Exp $
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include "timer.h"
- #include "socket.h"
- #include "db.h"
- #include "nullpo.h"
- #include "malloc.h"
- #include "map.h"
- #include "clif.h"
- #include "intif.h"
- #include "pc.h"
- #include "mob.h"
- #include "guild.h"
- #include "itemdb.h"
- #include "skill.h"
- #include "battle.h"
- #include "party.h"
- #include "npc.h"
- #include "tmw.h"
- #ifdef MEMWATCH
- #include "memwatch.h"
- #endif
- #ifndef max
- #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
- #endif
- #define MIN_MOBTHINKTIME 100
- #define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute)
- #define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute)
- struct mob_db mob_db[2001];
- /*==========================================
- * Local prototype declaration (only required thing)
- *------------------------------------------
- */
- static int distance (int, int, int, int);
- static int mob_makedummymobdb (int);
- static int mob_timer (int, unsigned int, int, int);
- //int mobskill_use (struct mob_data *md, unsigned int tick, int event);
- int mobskill_deltimer (struct mob_data *md);
- int mob_skillid2skillidx (int class, int skillid);
- int mobskill_use_id (struct mob_data *md, struct block_list *target,
- int skill_idx);
- static int mob_unlocktarget (struct mob_data *md, int tick);
- /*==========================================
- * Mob is searched with a name.
- *------------------------------------------
- */
- int mobdb_searchname (const char *str)
- {
- if (!str)
- return 0;
- int i;
- for (i = 0; i < sizeof (mob_db) / sizeof (mob_db[0]); i++)
- {
- if (strcmpi (mob_db[i].name, str) == 0
- || strcmp (mob_db[i].jname, str) == 0
- || memcmp (mob_db[i].name, str, 24) == 0
- || memcmp (mob_db[i].jname, str, 24) == 0)
- return i;
- }
- return 0;
- }
- /*==========================================
- * Id Mob is checked.
- *------------------------------------------
- */
- int mobdb_checkid (const int id)
- {
- if (id <= 0 || id >= (sizeof (mob_db) / sizeof (mob_db[0]))
- || mob_db[id].name[0] == '\0')
- return 0;
- return id;
- }
- static void mob_init (struct mob_data *md);
- /*==========================================
- * The minimum data set for MOB spawning
- *------------------------------------------
- */
- int mob_spawn_dataset (struct mob_data *md, const char *mobname, int class)
- {
- nullpo_retr (0, md);
- nullpo_retr (0, mobname);
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- if (strcmp (mobname, "--en--") == 0)
- memcpy (md->name, mob_db[class].name, 24);
- else if (strcmp (mobname, "--ja--") == 0)
- memcpy (md->name, mob_db[class].jname, 24);
- else
- memcpy (md->name, mobname, 24);
- md->bl.prev = NULL;
- md->bl.next = NULL;
- md->n = 0;
- md->base_class = md->class = class;
- md->bl.id = npc_get_new_npc_id ();
- memset (&md->state, 0, sizeof (md->state));
- md->timer = -1;
- md->target_id = 0;
- md->attacked_id = 0;
- mob_init (md);
- return 0;
- }
- // Mutation values indicate how `valuable' a change to each stat is, XP wise.
- // For one 256th of change, we give out that many 1024th fractions of XP change
- // (i.e., 1024 means a 100% XP increase for a single point of adjustment, 4 means 100% XP bonus for doubling the value)
- static int mutation_value[MOB_XP_BONUS] = {
- 2, // MOB_LV
- 3, // MOB_MAX_HP
- 1, // MOB_STR
- 2, // MOB_AGI
- 1, // MOB_VIT
- 0, // MOB_INT
- 2, // MOB_DEX
- 2, // MOB_LUK
- 1, // MOB_ATK1
- 1, // MOB_ATK2
- 2, // MOB_ADELAY
- 2, // MOB_DEF
- 2, // MOB_MDEF
- 2, // MOB_SPEED
- };
- // The mutation scale indicates how far `up' we can go, with 256 indicating 100% Note that this may stack with multiple
- // calls to `mutate'.
- static int mutation_scale[MOB_XP_BONUS] = {
- 16, // MOB_LV
- 256, // MOB_MAX_HP
- 32, // MOB_STR
- 48, // MOB_AGI
- 48, // MOB_VIT
- 48, // MOB_INT
- 48, // MOB_DEX
- 64, // MOB_LUK
- 48, // MOB_ATK1
- 48, // MOB_ATK2
- 80, // MOB_ADELAY
- 48, // MOB_DEF
- 48, // MOB_MDEF
- 80, // MOB_SPEED
- };
- // The table below indicates the `average' value for each of the statistics, or -1 if there is none.
- // This average is used to determine XP modifications for mutations. The experience point bonus is
- // based on mutation_value and mutation_base as follows:
- // (1) first, compute the percentage change of the attribute (p0)
- // (2) second, determine the absolute stat change
- // (3) third, compute the percentage stat change relative to mutation_base (p1)
- // (4) fourth, compute the XP mofication based on the smaller of (p0, p1).
- static int mutation_base[MOB_XP_BONUS] = {
- 30, // MOB_LV
- -1, // MOB_MAX_HP
- 20, // MOB_STR
- 20, // MOB_AGI
- 20, // MOB_VIT
- 20, // MOB_INT
- 20, // MOB_DEX
- 20, // MOB_LUK
- -1, // MOB_ATK1
- -1, // MOB_ATK2
- -1, // MOB_ADELAY
- -1, // MOB_DEF
- 20, // MOB_MDEF
- -1, // MOB_SPEED
- };
- /*========================================
- * Mutates a MOB. For large `direction' values, calling this multiple times will give bigger XP boni.
- *----------------------------------------
- */
- static void mob_mutate (struct mob_data *md, int stat, int intensity) // intensity: positive: strengthen, negative: weaken. 256 = 100%.
- {
- if (!md || stat < 0 || stat >= MOB_XP_BONUS || intensity == 0)
- return;
- int old_stat;
- int new_stat;
- int real_intensity; // relative intensity
- const int mut_base = mutation_base[stat];
- int sign = 1;
- while (intensity > mutation_scale[stat])
- {
- mob_mutate (md, stat, mutation_scale[stat]); // give better XP assignments
- intensity -= mutation_scale[stat];
- }
- while (intensity < -mutation_scale[stat])
- {
- mob_mutate (md, stat, mutation_scale[stat]); // give better XP assignments
- intensity += mutation_scale[stat];
- }
- if (!intensity)
- return;
- // MOB_ADELAY and MOB_SPEED are special because going DOWN is good here.
- if (stat == MOB_ADELAY || stat == MOB_SPEED)
- sign = -1;
- // Now compute the new stat
- old_stat = md->stats[stat];
- new_stat = old_stat + ((old_stat * sign * intensity) / 256);
- if (new_stat < 0)
- new_stat = 0;
- if (old_stat == 0)
- real_intensity = 0;
- else
- real_intensity = (((new_stat - old_stat) << 8) / old_stat);
- if (mut_base != -1)
- {
- // Now compute the mutation intensity relative to an absolute value.
- // Take the lesser of the two effects.
- int real_intensity2 = (((new_stat - old_stat) << 8) / mut_base);
- if (real_intensity < 0)
- if (real_intensity2 > real_intensity)
- real_intensity = real_intensity2;
- if (real_intensity > 0)
- if (real_intensity2 < real_intensity)
- real_intensity = real_intensity2;
- }
- real_intensity *= sign;
- md->stats[stat] = new_stat;
- // Adjust XP value
- md->stats[MOB_XP_BONUS] += mutation_value[stat] * real_intensity;
- if (md->stats[MOB_XP_BONUS] <= 0)
- md->stats[MOB_XP_BONUS] = 1;
- // Sanitise
- if (md->stats[MOB_ATK1] > md->stats[MOB_ATK2])
- {
- int swap = md->stats[MOB_ATK2];
- md->stats[MOB_ATK2] = md->stats[MOB_ATK1];
- md->stats[MOB_ATK1] = swap;
- }
- }
- // This calculates the exp of a given mob
- int mob_gen_exp (struct mob_db *mob)
- {
- if (!mob)
- return 1;
- if (mob->max_hp <= 1)
- return 1;
- double mod_def = 100 - mob->def;
- if (mod_def == 0)
- mod_def = 1;
- double effective_hp =
- ((50 - mob->luk) * mob->max_hp / 50.0) +
- (2 * mob->luk * mob->max_hp / mod_def);
- double attack_factor =
- (mob->atk1 + mob->atk2 + mob->str / 3.0 + mob->dex / 2.0 +
- mob->luk) * (1872.0 / mob->adelay) / 4;
- double dodge_factor =
- pow (mob->lv + mob->agi + mob->luk / 2.0, 4.0 / 3.0);
- double persuit_factor =
- (3 + mob->range) * (mob->mode % 2) * 1000 / mob->speed;
- double aggression_factor = (mob->mode & 4) == 4 ? 10.0 / 9.0 : 1.0;
- int xp =
- (int) floor (effective_hp *
- pow (sqrt (attack_factor) + sqrt (dodge_factor) +
- sqrt (persuit_factor) + 55,
- 3) * aggression_factor / 2000000.0 *
- (double) battle_config.base_exp_rate / 100.);
- if (xp < 1)
- xp = 1;
- printf ("Exp for mob '%s' generated: %d\n", mob->name, xp);
- return xp;
- }
- static void mob_init (struct mob_data *md)
- {
- if (!md)
- return;
- int i;
- const int class = md->class;
- const int mutations_nr = mob_db[class].mutations_nr;
- const int mutation_power = mob_db[class].mutation_power;
- md->stats[MOB_LV] = mob_db[class].lv;
- md->stats[MOB_MAX_HP] = mob_db[class].max_hp;
- md->stats[MOB_STR] = mob_db[class].str;
- md->stats[MOB_AGI] = mob_db[class].agi;
- md->stats[MOB_VIT] = mob_db[class].vit;
- md->stats[MOB_INT] = mob_db[class].int_;
- md->stats[MOB_DEX] = mob_db[class].dex;
- md->stats[MOB_LUK] = mob_db[class].luk;
- md->stats[MOB_ATK1] = mob_db[class].atk1;
- md->stats[MOB_ATK2] = mob_db[class].atk2;
- md->stats[MOB_ADELAY] = mob_db[class].adelay;
- md->stats[MOB_DEF] = mob_db[class].def;
- md->stats[MOB_MDEF] = mob_db[class].mdef;
- md->stats[MOB_SPEED] = mob_db[class].speed;
- md->stats[MOB_XP_BONUS] = MOB_XP_BONUS_BASE;
- if (!(mutation_power >> 1))
- return;
- for (i = 0; i < mutations_nr; i++)
- {
- int stat_nr = MRAND (MOB_XP_BONUS + 1);
- int strength;
- if (stat_nr >= MOB_XP_BONUS)
- stat_nr = MOB_MAX_HP;
- strength =
- ((MRAND ((mutation_power >> 1)) +
- (MRAND ((mutation_power >> 1))) +
- 2) * mutation_scale[stat_nr]) / 100;
- strength = MRAND (2) ? strength : -strength;
- if (strength < -240)
- strength = -240; /* Don't go too close to zero */
- mob_mutate (md, stat_nr, strength);
- }
- }
- /*==========================================
- * The MOB appearance for one time (for scripts)
- *------------------------------------------
- */
- int mob_once_spawn (struct map_session_data *sd, char *mapname,
- int x, int y, const char *mobname, int class, int amount,
- const char *event)
- {
- if (!mapname)
- return 0;
- struct mob_data *md = NULL;
- int m, count, lv = 255, r = class;
- if (sd)
- lv = sd->status.base_level;
- if (sd && strcmp (mapname, "this") == 0)
- m = sd->bl.m;
- else
- m = map_mapname2mapid (mapname);
- if (m < 0 || amount <= 0 || (class >= 0 && class <= 1000) || class > 2000) // 値が異常なら召喚を止める
- return 0;
- if (class < 0)
- { // ランダムに召喚
- int j = -class - 1;
- if (j >= 0 && j < MAX_RANDOMMONSTER)
- {
- int i = 0;
- int k;
- do
- {
- class = MPRAND (1001, 1000);
- k = MRAND (1000000);
- }
- while ((mob_db[class].max_hp <= 0
- || mob_db[class].summonper[j] <= k
- || (lv < mob_db[class].lv
- && battle_config.random_monster_checklv == 1))
- && (i++) < 2000);
- if (i >= 2000)
- {
- class = mob_db[0].summonper[j];
- }
- }
- else
- {
- return 0;
- }
- // if(battle_config.etc_log==1)
- // printf("mobclass=%d try=%d\n",class,i);
- }
- if (sd)
- {
- if (x <= 0)
- x = sd->bl.x;
- if (y <= 0)
- y = sd->bl.y;
- }
- else if (x <= 0 || y <= 0)
- {
- printf ("mob_once_spawn: ??\n");
- }
- for (count = 0; count < amount; count++)
- {
- md = (struct mob_data *) aCalloc (1, sizeof (struct mob_data));
- memset (md, '\0', sizeof *md);
- if (mob_db[class].mode & 0x02)
- md->lootitem =
- (struct item *) aCalloc (LOOTITEM_SIZE, sizeof (struct item));
- else
- md->lootitem = NULL;
- mob_spawn_dataset (md, mobname, class);
- md->bl.m = m;
- md->bl.x = x;
- md->bl.y = y;
- if (r < 0 && battle_config.dead_branch_active == 1)
- md->mode = 0x1 + 0x4 + 0x80; //移動してアクティブで反撃する
- md->m = m;
- md->x0 = x;
- md->y0 = y;
- md->xs = 0;
- md->ys = 0;
- md->spawndelay1 = -1; // Only once is a flag.
- md->spawndelay2 = -1; // Only once is a flag.
- memcpy (md->npc_event, event, sizeof (md->npc_event));
- md->bl.type = BL_MOB;
- map_addiddb (&md->bl);
- mob_spawn (md->bl.id);
- if (class == 1288)
- { // emperium hp based on defense level [Valaris]
- struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
- if (gc)
- {
- mob_db[class].max_hp += 2000 * gc->defense;
- md->hp = mob_db[class].max_hp;
- }
- } // end addition [Valaris]
- }
- return (amount > 0) ? md->bl.id : 0;
- }
- /*==========================================
- * The MOB appearance for one time (& area specification for scripts)
- *------------------------------------------
- */
- int mob_once_spawn_area (struct map_session_data *sd, char *mapname,
- int x0, int y0, int x1, int y1,
- const char *mobname, int class, int amount,
- const char *event)
- {
- if (!mapname)
- return 0;
- int x, y, i, c, max, lx = -1, ly = -1, id = 0;
- int m;
- if (strcmp (mapname, "this") == 0)
- {
- if (!sd)
- return 0;
- m = sd->bl.m;
- }
- else
- m = map_mapname2mapid (mapname);
- max = (y1 - y0 + 1) * (x1 - x0 + 1) * 3;
- if (max > 1000)
- max = 1000;
- if (m < 0 || amount <= 0 || (class >= 0 && class <= 1000) || class > 2000) // A summon is stopped if a value is unusual
- return 0;
- for (i = 0; i < amount; i++)
- {
- int j = 0;
- do
- {
- x = MPRAND (x0, (x1 - x0 + 1));
- y = MPRAND (y0, (y1 - y0 + 1));
- }
- while (((c = map_getcell (m, x, y)) == 1 || c == 5) && (++j) < max);
- if (j >= max)
- {
- if (lx >= 0)
- { // Since reference went wrong, the place which boiled before is used.
- x = lx;
- y = ly;
- }
- else
- return 0; // Since reference of the place which boils first went wrong, it stops.
- }
- id = mob_once_spawn (sd, mapname, x, y, mobname, class, 1, event);
- lx = x;
- ly = y;
- }
- return id;
- }
- /*==========================================
- * Summoning Guardians [Valaris]
- *------------------------------------------
- */
- int mob_spawn_guardian (struct map_session_data *sd, char *mapname,
- int x, int y, const char *mobname, int class,
- int amount, const char *event, int guardian)
- {
- if (!mapname)
- return 0;
- struct mob_data *md = NULL;
- int m, count = 1;
- if (sd && strcmp (mapname, "this") == 0)
- m = sd->bl.m;
- else
- m = map_mapname2mapid (mapname);
- if (m < 0 || amount <= 0 || (class >= 0 && class <= 1000) || class > 2000) // 値が異常なら召喚を止める
- return 0;
- if (class < 0)
- return 0;
- if (sd)
- {
- if (x <= 0)
- x = sd->bl.x;
- if (y <= 0)
- y = sd->bl.y;
- }
- else if (x <= 0 || y <= 0)
- printf ("mob_spawn_guardian: ??\n");
- for (count = 0; count < amount; count++)
- {
- struct guild_castle *gc;
- md = calloc (sizeof (struct mob_data), 1);
- if (md == NULL)
- {
- printf ("mob_spawn_guardian: out of memory !\n");
- exit (1);
- }
- memset (md, '\0', sizeof *md);
- mob_spawn_dataset (md, mobname, class);
- md->bl.m = m;
- md->bl.x = x;
- md->bl.y = y;
- md->m = m;
- md->x0 = x;
- md->y0 = y;
- md->xs = 0;
- md->ys = 0;
- md->spawndelay1 = -1; // Only once is a flag.
- md->spawndelay2 = -1; // Only once is a flag.
- memcpy (md->npc_event, event, sizeof (md->npc_event));
- md->bl.type = BL_MOB;
- map_addiddb (&md->bl);
- mob_spawn (md->bl.id);
- gc = guild_mapname2gc (map[md->bl.m].name);
- if (gc)
- {
- mob_db[class].max_hp += 2000 * gc->defense;
- if (guardian == 0)
- {
- md->hp = gc->Ghp0;
- gc->GID0 = md->bl.id;
- }
- if (guardian == 1)
- {
- md->hp = gc->Ghp1;
- gc->GID1 = md->bl.id;
- }
- if (guardian == 2)
- {
- md->hp = gc->Ghp2;
- gc->GID2 = md->bl.id;
- }
- if (guardian == 3)
- {
- md->hp = gc->Ghp3;
- gc->GID3 = md->bl.id;
- }
- if (guardian == 4)
- {
- md->hp = gc->Ghp4;
- gc->GID4 = md->bl.id;
- }
- if (guardian == 5)
- {
- md->hp = gc->Ghp5;
- gc->GID5 = md->bl.id;
- }
- if (guardian == 6)
- {
- md->hp = gc->Ghp6;
- gc->GID6 = md->bl.id;
- }
- if (guardian == 7)
- {
- md->hp = gc->Ghp7;
- gc->GID7 = md->bl.id;
- }
- }
- }
- return (amount > 0) ? md->bl.id : 0;
- }
- /*==========================================
- * Appearance income of mob
- *------------------------------------------
- */
- int mob_get_viewclass (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].view_class;
- }
- int mob_get_sex (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].sex;
- }
- short mob_get_hair (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].hair;
- }
- short mob_get_hair_color (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].hair_color;
- }
- short mob_get_weapon (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].weapon;
- }
- short mob_get_shield (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].shield;
- }
- short mob_get_head_top (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].head_top;
- }
- short mob_get_head_mid (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].head_mid;
- }
- short mob_get_head_buttom (int class)
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].head_buttom;
- }
- short mob_get_clothes_color (int class) // Add for player monster dye - Valaris
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].clothes_color; // End
- }
- int mob_get_equip (int class) // mob equip [Valaris]
- {
- if (class < 0 || class >= (sizeof (mob_db) / sizeof (mob_db[0])))
- return 0;
- return mob_db[class].equip;
- }
- /*==========================================
- * Is MOB in the state in which the present movement is possible or not?
- *------------------------------------------
- */
- int mob_can_move (struct mob_data *md)
- {
- nullpo_retr (0, md);
- if (md->canmove_tick > gettick () || (md->opt1 > 0 && md->opt1 != 6)
- || md->option & 2)
- return 0;
- // アンクル中で動けないとか
- if (md->sc_data[SC_ANKLE].timer != -1 || //アンクルスネア
- md->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
- md->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
- md->sc_data[SC_SPIDERWEB].timer != -1 //スパイダーウェッブ
- )
- return 0;
- return 1;
- }
- /*==========================================
- * Time calculation concerning one step next to mob
- *------------------------------------------
- */
- static int calc_next_walk_step (struct mob_data *md)
- {
- nullpo_retr (0, md);
- if (md->walkpath.path_pos >= md->walkpath.path_len)
- return -1;
- if (md->walkpath.path[md->walkpath.path_pos] & 1)
- return battle_get_speed (&md->bl) * 14 / 10;
- return battle_get_speed (&md->bl);
- }
- static int mob_walktoxy_sub (struct mob_data *md);
- /*==========================================
- * Mob Walk processing
- *------------------------------------------
- */
- static int mob_walk (struct mob_data *md, unsigned int tick, int data)
- {
- int i;
- static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
- static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
- nullpo_retr (0, md);
- md->state.state = MS_IDLE;
- if (md->walkpath.path_pos >= md->walkpath.path_len
- || md->walkpath.path_pos != data)
- return 0;
- md->walkpath.path_half ^= 1;
- if (md->walkpath.path_half == 0)
- {
- md->walkpath.path_pos++;
- if (md->state.change_walk_target)
- {
- mob_walktoxy_sub (md);
- return 0;
- }
- }
- else
- {
- int moveblock;
- int ctype;
- int x, y, dx, dy;
- if (md->walkpath.path[md->walkpath.path_pos] >= 8)
- return 1;
- x = md->bl.x;
- y = md->bl.y;
- ctype = map_getcell (md->bl.m, x, y);
- if (ctype == 1 || ctype == 5)
- {
- mob_stop_walking (md, 1);
- return 0;
- }
- md->dir = md->walkpath.path[md->walkpath.path_pos];
- dx = dirx[md->dir];
- dy = diry[md->dir];
- ctype = map_getcell (md->bl.m, x + dx, y + dy);
- if (ctype == 1 || ctype == 5)
- {
- mob_walktoxy_sub (md);
- return 0;
- }
- moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
- || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
- md->state.state = MS_WALK;
- map_foreachinmovearea (clif_moboutsight, md->bl.m, x - AREA_SIZE,
- y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
- dx, dy, BL_PC, md);
- x += dx;
- y += dy;
- if (md->min_chase > 13)
- md->min_chase--;
- if (moveblock)
- map_delblock (&md->bl);
- md->bl.x = x;
- md->bl.y = y;
- if (moveblock)
- map_addblock (&md->bl);
- map_foreachinmovearea (clif_mobinsight, md->bl.m, x - AREA_SIZE,
- y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
- -dx, -dy, BL_PC, md);
- md->state.state = MS_IDLE;
- if (md->option & 4)
- skill_check_cloaking (&md->bl);
- skill_unit_move (&md->bl, tick, 1); // Inspection of a skill unit
- }
- if ((i = calc_next_walk_step (md)) > 0)
- {
- i = i >> 1;
- if (i < 1 && md->walkpath.path_half == 0)
- i = 1;
- md->timer =
- add_timer (tick + i, mob_timer, md->bl.id, md->walkpath.path_pos);
- md->state.state = MS_WALK;
- if (md->walkpath.path_pos >= md->walkpath.path_len)
- clif_fixmobpos (md); // When mob stops, retransmission current of a position.
- }
- return 0;
- }
- /*==========================================
- * Check if mob should be attempting to attack
- *------------------------------------------
- */
- static int mob_check_attack (struct mob_data *md)
- {
- struct block_list *tbl = NULL;
- struct map_session_data *tsd = NULL;
- struct mob_data *tmd = NULL;
- int mode, race, range;
- nullpo_retr (0, md);
- md->min_chase = 13;
- md->state.state = MS_IDLE;
- md->state.skillstate = MSS_IDLE;
- if (md->skilltimer != -1)
- return 0;
- if (md->opt1 > 0 || md->option & 2)
- return 0;
- if (md->sc_data[SC_AUTOCOUNTER].timer != -1)
- return 0;
- if (md->sc_data[SC_BLADESTOP].timer != -1)
- return 0;
- if ((tbl = map_id2bl (md->target_id)) == NULL)
- {
- md->target_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- return 0;
- }
- if (tbl->type == BL_PC)
- tsd = (struct map_session_data *) tbl;
- else if (tbl->type == BL_MOB)
- tmd = (struct mob_data *) tbl;
- else
- return 0;
- if (tsd)
- {
- if (pc_isdead (tsd) || tsd->invincible_timer != -1
- || pc_isinvisible (tsd) || md->bl.m != tbl->m || tbl->prev == NULL
- || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
- {
- md->target_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- return 0;
- }
- }
- if (tmd)
- {
- if (md->bl.m != tbl->m || tbl->prev == NULL
- || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
- {
- md->target_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- return 0;
- }
- }
- if (!md->mode)
- mode = mob_db[md->class].mode;
- else
- mode = md->mode;
- race = mob_db[md->class].race;
- if (!(mode & 0x80) && !(mode & 0x10000))
- {
- md->target_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- return 0;
- }
- if (tsd && !(mode & 0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 ||
- ((pc_ishiding (tsd)
- || tsd->state.gangsterparadise)
- && race != 4 && race != 6)))
- {
- md->target_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- return 0;
- }
- range = mob_db[md->class].range;
- if (mode & 1)
- range++;
- if (distance (md->bl.x, md->bl.y, tbl->x, tbl->y) > range)
- return 0;
- return 1;
- }
- /*==========================================
- * Attack processing of mob
- *------------------------------------------
- */
- static int mob_attack (struct mob_data *md, unsigned int tick,
- int data __attribute__ ((unused)))
- {
- struct block_list *tbl = NULL;
- int mode;
- nullpo_retr (0, md);
- if (!mob_check_attack (md))
- return 0;
- if ((tbl = map_id2bl (md->target_id)) == NULL)
- return 0;
- if (battle_config.monster_attack_direction_change)
- md->dir = map_calc_dir (&md->bl, tbl->x, tbl->y); // 向き設定
- //clif_fixmobpos(md);
- md->state.skillstate = MSS_ATTACK;
- if (mobskill_use (md, tick, -2)) // スキル使用
- return 0;
- if (!md->mode)
- mode = mob_db[md->class].mode;
- else
- mode = md->mode;
- if (mode & 0x80)
- md->target_lv = battle_weapon_attack (&md->bl, tbl, tick, 0);
- else
- md->target_lv = 0;
- if (!(battle_config.monster_cloak_check_type & 2)
- && md->sc_data[SC_CLOAKING].timer != -1)
- skill_status_change_end (&md->bl, SC_CLOAKING, -1);
- md->attackabletime = tick + battle_get_adelay (&md->bl);
- md->timer = add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
- md->state.state = MS_ATTACK;
- return 0;
- }
- /*==========================================
- * The attack of PC which is attacking id is stopped.
- * The callback function of clif_foreachclient
- *------------------------------------------
- */
- int mob_stopattacked (struct map_session_data *sd, va_list ap)
- {
- int id;
- nullpo_retr (0, sd);
- nullpo_retr (0, ap);
- id = va_arg (ap, int);
- if (sd->attacktarget == id)
- pc_stopattack (sd);
- return 0;
- }
- /*==========================================
- * The timer in which the mob's states changes
- *------------------------------------------
- */
- int mob_changestate (struct mob_data *md, int state, int type)
- {
- unsigned int tick;
- int i;
- nullpo_retr (0, md);
- if (md->timer != -1)
- delete_timer (md->timer, mob_timer);
- md->timer = -1;
- md->state.state = state;
- switch (state)
- {
- case MS_WALK:
- if ((i = calc_next_walk_step (md)) > 0)
- {
- i = i >> 2;
- md->timer =
- add_timer (gettick () + i, mob_timer, md->bl.id, 0);
- }
- else
- md->state.state = MS_IDLE;
- break;
- case MS_ATTACK:
- tick = gettick ();
- i = DIFF_TICK (md->attackabletime, tick);
- if (i > 0 && i < 2000)
- md->timer =
- add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
- else if (type)
- {
- md->attackabletime = tick + battle_get_amotion (&md->bl);
- md->timer =
- add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
- }
- else
- {
- md->attackabletime = tick + 1;
- md->timer =
- add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
- }
- break;
- case MS_DELAY:
- md->timer =
- add_timer (gettick () + type, mob_timer, md->bl.id, 0);
- break;
- case MS_DEAD:
- skill_castcancel (&md->bl, 0);
- // mobskill_deltimer(md);
- md->state.skillstate = MSS_DEAD;
- md->last_deadtime = gettick ();
- // Since it died, all aggressors' attack to this mob is stopped.
- clif_foreachclient (mob_stopattacked, md->bl.id);
- skill_unit_out_all (&md->bl, gettick (), 1);
- skill_status_change_clear (&md->bl, 2); // The abnormalities in status are canceled.
- skill_clear_unitgroup (&md->bl); // All skill unit groups are deleted.
- skill_cleartimerskill (&md->bl);
- if (md->deletetimer != -1)
- delete_timer (md->deletetimer, mob_timer_delete);
- md->deletetimer = -1;
- md->hp = md->target_id = md->attacked_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- break;
- default:
- break;
- }
- return 0;
- }
- /*==========================================
- * timer processing of mob (timer function)
- * It branches to a walk and an attack.
- *------------------------------------------
- */
- static int mob_timer (int tid, unsigned int tick, int id, int data)
- {
- struct mob_data *md;
- struct block_list *bl;
- if ((bl = map_id2bl (id)) == NULL)
- { //攻撃してきた敵がもういないのは正常のようだ
- return 1;
- }
- if (!bl || !bl->type || bl->type != BL_MOB)
- return 1;
- nullpo_retr (1, md = (struct mob_data *) bl);
- if (!md->bl.type || md->bl.type != BL_MOB)
- return 1;
- if (md->timer != tid)
- {
- if (battle_config.error_log == 1)
- printf ("mob_timer %d != %d\n", md->timer, tid);
- return 0;
- }
- md->timer = -1;
- if (md->bl.prev == NULL || md->state.state == MS_DEAD)
- return 1;
- map_freeblock_lock ();
- switch (md->state.state)
- {
- case MS_WALK:
- mob_check_attack (md);
- mob_walk (md, tick, data);
- break;
- case MS_ATTACK:
- mob_attack (md, tick, data);
- break;
- case MS_DELAY:
- mob_changestate (md, MS_IDLE, 0);
- break;
- default:
- if (battle_config.error_log == 1)
- printf ("mob_timer : %d ?\n", md->state.state);
- break;
- }
- map_freeblock_unlock ();
- return 0;
- }
- /*==========================================
- *
- *------------------------------------------
- */
- static int mob_walktoxy_sub (struct mob_data *md)
- {
- struct walkpath_data wpd;
- nullpo_retr (0, md);
- if (path_search
- (&wpd, md->bl.m, md->bl.x, md->bl.y, md->to_x, md->to_y,
- md->state.walk_easy))
- return 1;
- memcpy (&md->walkpath, &wpd, sizeof (wpd));
- md->state.change_walk_target = 0;
- mob_changestate (md, MS_WALK, 0);
- clif_movemob (md);
- return 0;
- }
- /*==========================================
- * mob move start
- *------------------------------------------
- */
- int mob_walktoxy (struct mob_data *md, int x, int y, int easy)
- {
- struct walkpath_data wpd;
- nullpo_retr (0, md);
- if (md->state.state == MS_WALK
- && path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, x, y, easy))
- return 1;
- md->state.walk_easy = easy;
- md->to_x = x;
- md->to_y = y;
- if (md->state.state == MS_WALK)
- {
- md->state.change_walk_target = 1;
- }
- else
- {
- return mob_walktoxy_sub (md);
- }
- return 0;
- }
- /*==========================================
- * mob spawn with delay (timer function)
- *------------------------------------------
- */
- static int mob_delayspawn (int tid __attribute__ ((unused)),
- unsigned int tick __attribute__ ((unused)),
- int m, int n __attribute__ ((unused)))
- {
- mob_spawn (m);
- return 0;
- }
- /*==========================================
- * spawn timing calculation
- *------------------------------------------
- */
- int mob_setdelayspawn (int id)
- {
- unsigned int spawntime, spawntime1, spawntime2, spawntime3;
- struct mob_data *md;
- struct block_list *bl;
- if ((bl = map_id2bl (id)) == NULL)
- return -1;
- if (!bl || !bl->type || bl->type != BL_MOB)
- return -1;
- nullpo_retr (-1, md = (struct mob_data *) bl);
- if (!md || md->bl.type != BL_MOB)
- return -1;
- // Processing of MOB which is not revitalized
- if (md->spawndelay1 == -1 && md->spawndelay2 == -1 && md->n == 0)
- {
- map_deliddb (&md->bl);
- if (md->lootitem)
- {
- map_freeblock (md->lootitem);
- md->lootitem = NULL;
- }
- map_freeblock (md); // Instead of [ of free ]
- return 0;
- }
- spawntime1 = md->last_spawntime + md->spawndelay1;
- spawntime2 = md->last_deadtime + md->spawndelay2;
- spawntime3 = gettick () + 5000;
- // spawntime = max(spawntime1,spawntime2,spawntime3);
- if (DIFF_TICK (spawntime1, spawntime2) > 0)
- {
- spawntime = spawntime1;
- }
- else
- {
- spawntime = spawntime2;
- }
- if (DIFF_TICK (spawntime3, spawntime) > 0)
- {
- spawntime = spawntime3;
- }
- add_timer (spawntime, mob_delayspawn, id, 0);
- return 0;
- }
- /*==========================================
- * Mob spawning. Initialization is also variously here.
- *------------------------------------------
- */
- int mob_spawn (int id)
- {
- int x = 0, y = 0, i = 0, c;
- unsigned int tick = gettick ();
- struct mob_data *md;
- struct block_list *bl;
- nullpo_retr (-1, bl = map_id2bl (id));
- if (!bl || !bl->type || bl->type != BL_MOB)
- return -1;
- nullpo_retr (-1, md = (struct mob_data *) bl);
- if (!md || !md->bl.type || md->bl.type != BL_MOB || map[md->bl.m].mob_num > battle_config.mob_map_limit)
- return -1;
- md->last_spawntime = tick;
- if (md->bl.prev != NULL)
- {
- // clif_clearchar_area(&md->bl,3);
- skill_unit_out_all (&md->bl, gettick (), 1);
- map_delblock (&md->bl);
- }
- else
- md->class = md->base_class;
- md->bl.m = md->m;
- do
- {
- if (md->x0 == 0 && md->y0 == 0)
- {
- x = MPRAND (1, (map[md->bl.m].xs - 2));
- y = MPRAND (1, (map[md->bl.m].ys - 2));
- }
- else
- {
- x = MPRAND (md->x0, (md->xs + 1)) - md->xs / 2;
- y = MPRAND (md->y0, (md->ys + 1)) - md->ys / 2;
- }
- i++;
- }
- while (((c = map_getcell (md->bl.m, x, y)) == 1 || c == 5) && i < 50);
- if (i >= 50)
- {
- // if(battle_config.error_log==1)
- // printf("MOB spawn error %d @ %s\n",id,map[md->bl.m].name);
- add_timer (tick + 5000, mob_delayspawn, id, 0);
- return 1;
- }
- md->to_x = md->bl.x = x;
- md->to_y = md->bl.y = y;
- md->dir = 0;
- map_addblock (&md->bl);
- memset (&md->state, 0, sizeof (md->state));
- md->attacked_id = 0;
- md->target_id = 0;
- md->move_fail_count = 0;
- mob_init (md);
- if (!md->stats[MOB_SPEED])
- md->stats[MOB_SPEED] = mob_db[md->class].speed;
- md->def_ele = mob_db[md->class].element;
- // md->master_id = 0;
- md->master_dist = 0;
- md->state.state = MS_IDLE;
- md->state.skillstate = MSS_IDLE;
- md->timer = -1;
- md->last_thinktime = tick;
- md->next_walktime = tick + MPRAND (5000, 50);
- md->attackabletime = tick;
- md->canmove_tick = tick;
- md->sg_count = 0;
- md->deletetimer = -1;
- md->skilltimer = -1;
- for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
- md->skilldelay[i] = c;
- md->skillid = 0;
- md->skilllv = 0;
- memset (md->dmglog, 0, sizeof (md->dmglog));
- if (md->lootitem)
- memset (md->lootitem, 0, sizeof (md->lootitem));
- md->lootitem_count = 0;
- for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
- md->skilltimerskill[i].timer = -1;
- for (i = 0; i < MAX_STATUSCHANGE; i++)
- {
- md->sc_data[i].timer = -1;
- md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 =
- md->sc_data[i].val4 = 0;
- }
- md->sc_count = 0;
- md->opt1 = md->opt2 = md->opt3 = md->option = 0;
- memset (md->skillunit, 0, sizeof (md->skillunit));
- memset (md->skillunittick, 0, sizeof (md->skillunittick));
- md->hp = battle_get_max_hp (&md->bl);
- if (md->hp <= 0)
- {
- mob_makedummymobdb (md->class);
- md->hp = battle_get_max_hp (&md->bl);
- }
- md->max_hp = md->hp;
- clif_spawnmob (md);
- return 0;
- }
- /*==========================================
- * Distance calculation between two points
- *------------------------------------------
- */
- static int distance (int x0, int y0, int x1, int y1)
- {
- int dx, dy;
- dx = abs (x0 - x1);
- dy = abs (y0 - y1);
- return dx > dy ? dx : dy;
- }
- /*==========================================
- * The stop of MOB's attack
- *------------------------------------------
- */
- int mob_stopattack (struct mob_data *md)
- {
- nullpo_retr (0, md);
- md->target_id = 0;
- md->state.targettype = NONE_ATTACKABLE;
- md->attacked_id = 0;
- return 0;
- }
- /*==========================================
- * The stop of MOB's walking
- *------------------------------------------
- */
- int mob_stop_walking (struct mob_data *md, int type)
- {
- nullpo_retr (0, md);
- if (md->state.state == MS_WALK || md->state.state == MS_IDLE)
- {
- int dx = 0, dy = 0;
- md->walkpath.path_len = 0;
- if (type & 4)
- {
- dx = md->to_x - md->bl.x;
- if (dx < 0)
- dx = -1;
- else if (dx > 0)
- dx = 1;
- dy = md->to_y - md->bl.y;
- if (dy < 0)
- dy = -1;
- else if (dy > 0)
- dy = 1;
- }
- md->to_x = md->bl.x + dx;
- md->to_y = md->bl.y + dy;
- if (dx != 0 || dy != 0)
- {
- mob_walktoxy_sub (md);
- return 0;
- }
- mob_changestate (md, MS_IDLE, 0);
- }
- if (type & 0x01)
- clif_fixmobpos (md);
- if (type & 0x02)
- {
- int delay = battle_get_dmotion (&md->bl);
- unsigned int tick = gettick ();
- if (md->canmove_tick < tick)
- md->canmove_tick = tick + delay;
- }
- return 0;
- }
- /*==========================================
- * Reachability to a Specification ID existence place
- *------------------------------------------
- */
- int mob_can_reach (struct mob_data *md, struct block_list *bl, int range)
- {
- int dx, dy;
- struct walkpath_data wpd;
- int i;
- nullpo_retr (0, md);
- nullpo_retr (0, bl);
- dx = abs (bl->x - md->bl.x);
- dy = abs (bl->y - md->bl.y);
- //=========== guildcastle guardian no search start===========
- //when players are the guild castle member not attack them !
- if (md->class == 1285 || md->class == 1286 || md->class == 1287)
- {
- struct map_session_data *sd;
- struct guild *g = NULL;
- struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
- if (gc && agit_flag == 0) // Guardians will not attack during non-woe time [Valaris]
- return 0; // end addition [Valaris]
- if (bl && bl->type == BL_PC)
- {
- if ((sd = (struct map_session_data *) bl) == NULL)
- {
- printf ("mob_can_reach nullpo\n");
- return 0;
- }
- if (gc && sd && sd->status.guild_id && sd->status.guild_id > 0)
- {
- g = guild_search (sd->status.guild_id); // don't attack guild members [Valaris]
- if (g && g->guild_id > 0 && g->guild_id == gc->guild_id)
- return 0;
- if (g && gc && guild_isallied (g, gc))
- return 0;
- }
- }
- }
- //========== guildcastle guardian no search eof==============
- if (bl && bl->type == BL_PC && battle_config.monsters_ignore_gm == 1)
- { // option to have monsters ignore GMs [Valaris]
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *) bl) != NULL && pc_isGM (sd))
- return 0;
- }
- if (md->bl.m != bl->m) // 違うャbプ
- return 0;
- if (range > 0 && range < ((dx > dy) ? dx : dy)) // 遠すぎる
- return 0;
- if (md->bl.x == bl->x && md->bl.y == bl->y) // 同じャX
- return 1;
- // Obstacle judging
- wpd.path_len = 0;
- wpd.path_pos = 0;
- wpd.path_half = 0;
- if (path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0) !=
- -1)
- return 1;
- if (bl->type != BL_PC && bl->type != BL_MOB)
- return 0;
- // It judges whether it can adjoin or not.
- dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
- dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
- if (path_search
- (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - dx, bl->y - dy, 0) != -1)
- return 1;
- for (i = 0; i < 9; i++)
- {
- if (path_search
- (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - 1 + i / 3,
- bl->y - 1 + i % 3, 0) != -1)
- return 1;
- }
- return 0;
- }
- /*==========================================
- * Determination for an attack of a monster
- *------------------------------------------
- */
- int mob_target (struct mob_data *md, struct block_list *bl, int dist)
- {
- struct map_session_data *sd;
- struct status_change *sc_data;
- short *option;
- int mode, race;
- nullpo_retr (0, md);
- nullpo_retr (0, bl);
- sc_data = battle_get_sc_data (bl);
- option = battle_get_option (bl);
- race = mob_db[md->class].race;
- if (!md->mode)
- {
- mode = mob_db[md->class].mode;
- }
- else
- {
- mode = md->mode;
- }
- if (!(mode & 0x80))
- {
- md->target_id = 0;
- return 0;
- }
- // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
- if ((md->target_id > 0 && md->state.targettype == ATTACKABLE)
- && (!(mode & 0x04) || MRAND (100) > 25))
- return 0;
- if (mode & 0x20 || // Coercion is exerted if it is MVPMOB.
- (sc_data && sc_data[SC_TRICKDEAD].timer == -1 &&
- ((option && !(*option & 0x06)) || race == 4 || race == 6)))
- {
- if (bl->type == BL_PC)
- {
- nullpo_retr (0, sd = (struct map_session_data *) bl);
- if (sd->invincible_timer != -1 || pc_isinvisible (sd))
- return 0;
- if (!(mode & 0x20) && race != 4 && race != 6
- && sd->state.gangsterparadise)
- return 0;
- }
- md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
- if (bl->type == BL_PC || bl->type == BL_MOB)
- md->state.targettype = ATTACKABLE;
- else
- md->state.targettype = NONE_ATTACKABLE;
- md->min_chase = dist + 13;
- if (md->min_chase > 26)
- md->min_chase = 26;
- }
- return 0;
- }
- /*==========================================
- * The ?? routine of an active monster
- *------------------------------------------
- */
- static int mob_ai_sub_hard_activesearch (struct block_list *bl, va_list ap)
- {
- struct map_session_data *tsd = NULL;
- struct mob_data *smd, *tmd = NULL;
- int mode, *pcc;
- nullpo_retr (0, bl);
- nullpo_retr (0, ap);
- nullpo_retr (0, smd = va_arg (ap, struct mob_data *));
- nullpo_retr (0, pcc = va_arg (ap, int *));
- if (bl->type == BL_PC)
- tsd = (struct map_session_data *) bl;
- else if (bl->type == BL_MOB)
- tmd = (struct mob_data *) bl;
- else
- return 0;
- //敵味方判定
- if (battle_check_target (&smd->bl, bl, BCT_ENEMY) == 0)
- return 0;
- if (!smd->mode)
- mode = mob_db[smd->class].mode;
- else
- mode = smd->mode;
- // アクティブでターゲット射程内にいるなら、ロックする
- if (mode & 0x04)
- {
- int race;
- race = mob_db[smd->class].race;
- //対象がPCの場合
- if (tsd &&
- !pc_isdead (tsd) &&
- tsd->bl.m == smd->bl.m &&
- tsd->invincible_timer == -1 &&
- !pc_isinvisible (tsd) &&
- (distance (smd->bl.x, smd->bl.y, tsd->bl.x, tsd->bl.y)) < 9)
- {
- if (mode & 0x20 ||
- (tsd->sc_data[SC_TRICKDEAD].timer == -1 &&
- ((!pc_ishiding (tsd) && !tsd->state.gangsterparadise)
- || race == 4 || race == 6)))
- { // 妨害がないか判定
- if (mob_can_reach (smd, bl, 12) && // 到達可能性判定
- MRAND (1000) < 1000 / (++(*pcc)))
- { // 範囲内PCで等確率にする
- smd->target_id = tsd->bl.id;
- smd->state.targettype = ATTACKABLE;
- smd->min_chase = 13;
- }
- }
- }
- //対象がMobの場合
- else if (tmd &&
- tmd->bl.m == smd->bl.m &&
- (distance (smd->bl.x, smd->bl.y, tmd->bl.x, tmd->bl.y)) < 9)
- {
- if (mob_can_reach (smd, bl, 12) && // 到達可能性判定
- MRAND (1000) < 1000 / (++(*pcc)))
- { // 範囲内で等確率にする
- smd->target_id = bl->id;
- smd->state.targettype = ATTACKABLE;
- smd->min_chase = 13;
- }
- }
- }
- return 0;
- }
- /*==========================================
- * loot monster item search
- *------------------------------------------
- */
- static int mob_ai_sub_hard_lootsearch (struct block_list *bl, va_list ap)
- {
- struct mob_data *md;
- int mode, *itc;
- nullpo_retr (0, bl);
- nullpo_retr (0, ap);
- nullpo_retr (0, md = va_arg (ap, struct mob_data *));
- nullpo_retr (0, itc = va_arg (ap, int *));
- if (!md->mode)
- {
- mode = mob_db[md->class].mode;
- }
- else
- {
- mode = md->mode;
- }
- if (!md->target_id && mode & 0x02)
- {
- if (!md->lootitem
- || (battle_config.monster_loot_type == 1
- && md->lootitem_count >= LOOTITEM_SIZE))
- return 0;
- if (bl->m == md->bl.m
- && distance (md->bl.x, md->bl.y, bl->x, bl->y) < 9)
- {
- if (mob_can_reach (md, bl, 12) && // Reachability judging
- MRAND (1000) < 1000 / (++(*itc)))
- { // It is made a probability, such as within the limits PC.
- md->target_id = bl->id;
- md->state.targettype = NONE_ATTACKABLE;
- md->min_chase = 13;
- }
- }
- }
- return 0;
- }
- /*==========================================
- * The ?? routine of a link monster
- *------------------------------------------
- */
- static int mob_ai_sub_hard_linksearch (struct block_list *bl, va_list ap)
- {
- struct mob_data *tmd;
- struct mob_data *md;
- struct block_list *target;
- nullpo_retr (0, bl);
- nullpo_retr (0, ap);
- nullpo_retr (0, tmd = (struct mob_data *) bl);
- nullpo_retr (0, md = va_arg (ap, struct mob_data *));
- nullpo_retr (0, target = va_a…
Large files files are truncated, but you can click here to view the full file