summaryrefslogtreecommitdiff
path: root/src/map/mob.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/mob.c')
-rw-r--r--src/map/mob.c1798
1 files changed, 1016 insertions, 782 deletions
diff --git a/src/map/mob.c b/src/map/mob.c
index ef67341f8..f076b7530 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -13,6 +13,7 @@
#include "clif.h"
#include "intif.h"
#include "pc.h"
+#include "status.h"
#include "mob.h"
#include "guild.h"
#include "itemdb.h"
@@ -21,6 +22,7 @@
#include "party.h"
#include "npc.h"
#include "log.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -31,7 +33,9 @@
#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];
+struct mob_db mob_db[MAX_MOB_DB+1];
+
+#define CLASSCHANGE_BOSS_NUM 21
/*==========================================
* Local prototype declaration (only required thing)
@@ -42,7 +46,7 @@ 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 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);
@@ -67,7 +71,7 @@ int mobdb_searchname(const char *str)
* Id Mob is checked.
*------------------------------------------
*/
-int mobdb_checkid(const int id)
+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;
@@ -79,28 +83,28 @@ int mobdb_checkid(const int id)
* The minimum data set for MOB spawning
*------------------------------------------
*/
-int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class)
+int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class_)
{
nullpo_retr(0, md);
md->bl.prev=NULL;
md->bl.next=NULL;
if(strcmp(mobname,"--en--")==0)
- memcpy(md->name,mob_db[class].name,24);
+ memcpy(md->name,mob_db[class_].name,24);
else if(strcmp(mobname,"--ja--")==0)
- memcpy(md->name,mob_db[class].jname,24);
+ memcpy(md->name,mob_db[class_].jname,24);
else
memcpy(md->name,mobname,24);
md->n = 0;
- md->base_class = md->class = class;
+ 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;
- md->speed=mob_db[class].speed;
+ md->speed=mob_db[class_].speed;
return 0;
}
@@ -110,97 +114,108 @@ int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class)
* 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)
+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)
{
- struct mob_data *md=NULL;
- int m,count,lv=255,r=class;
-
- if( sd )
- lv=sd->status.base_level;
+ struct mob_data *md = NULL;
+ int m, count, lv = 255;
+ int i, j;
+
+ if(sd) lv = sd->status.base_level;
- if( sd && strcmp(mapname,"this")==0)
- m=sd->bl.m;
+ if(sd && strcmp(mapname,"this")==0)
+ m = sd->bl.m;
else
- m=map_mapname2mapid(mapname);
+ m = map_mapname2mapid(mapname);
- if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // 値が異常なら召喚を止める
+ if (m < 0 || amount <= 0 || (class_ >= 0 && class_ <= 1000) || class_ > MAX_MOB_DB + 4000) // 値が異常なら召喚を止める
return 0;
- if(class<0){ // ランダムに召喚
- int i=0;
- int j=-class-1;
+ if (class_ < 0) { // ランダムに召喚
int k;
- if(j>=0 && j<MAX_RANDOMMONSTER){
- do{
- class=rand()%1000+1001;
- k=rand()%1000000;
- }while((mob_db[class].max_hp <= 0 || mob_db[class].summonper[j] <= k ||
- (lv<mob_db[class].lv && battle_config.random_monster_checklv)) && (i++) < 2000);
- if(i>=2000){
- class=mob_db[0].summonper[j];
- }
- }else{
+ i = 0;
+ j = -class_-1;
+ if(j >= 0 && j < MAX_RANDOMMONSTER) {
+ do {
+ class_ = rand() % 1000 + 1001;
+ k = rand() % 1000000;
+ } while ((mob_db[class_].max_hp <= 0 || mob_db[class_].summonper[j] <= k ||
+ (battle_config.random_monster_checklv && lv < mob_db[class_].lv)) && (i++) < 2000);
+ if(i >= 2000)
+ class_ = mob_db[0].summonper[j];
+ } else
return 0;
- }
// if(battle_config.etc_log)
-// printf("mobclass=%d try=%d\n",class,i);
+// 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");
+ if (sd) { //even if the coords were wrong, spawn mob anyways (but look for most suitable coords first) Got from Freya [Lupus]
+ if (x <= 0 || y <= 0) {
+ if (x <= 0) x = sd->bl.x + rand() % 3 - 1;
+ if (y <= 0) y = sd->bl.y + rand() % 3 - 1;
+ if (map_getcell(m, x, y, CELL_CHKNOPASS)) {
+ x = sd->bl.x;
+ y = sd->bl.y;
+ }
+ }
+ } else if (x <= 0 || y <= 0) {
+ i = j = 0;
+ printf("mob_once_spawn: %i at %s x:%i y:%i\n ??\n",class_,map[m].name,x,y); //got idea from Freya [Lupus]
+ do {
+ x = rand() % (map[m].xs - 2) + 1;
+ y = rand() % (map[m].ys - 2) + 1;
+ } while ((i = map_getcell(m, x, y, CELL_CHKNOPASS)) && j++ < 64);
+ if (i) { // not solved?
+ x = 0;
+ y = 0;
+ }
}
- for(count=0;count<amount;count++){
- md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
- memset(md, '\0', sizeof *md);
+ for (count = 0; count < amount; count++) {
+ md = (struct mob_data *)aCalloc(1,sizeof(struct mob_data));
+ memset (md, '\0', sizeof *md);
- if(class>4000) { // large/tiny mobs [Valaris]
- md->size=2;
- class-=4000;
- }
- else if(class>2000) {
- md->size=1;
- class-=2000;
+ if (class_ > MAX_MOB_DB + 2000) { // large/tiny mobs [Valaris]
+ md->size = 2;
+ class_ -= (MAX_MOB_DB + 2000);
+ } else if (class_ > MAX_MOB_DB) {
+ md->size = 1;
+ class_ -= MAX_MOB_DB;
}
- if(mob_db[class].mode&0x02)
- md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
+ 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) md->mode=0x1+0x4+0x80; //移動してアクティブで反撃する
- md->m =m;
- md->x0=x;
- md->y0=y;
- md->xs=0;
- md->ys=0;
- md->spawndelay1=-1; // 一度のみフラグ
- md->spawndelay2=-1; // 一度のみフラグ
+ md->lootitem = NULL;
- 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);
+ mob_spawn_dataset (md, mobname, class_);
+ md->bl.m = m;
+ md->bl.x = x;
+ md->bl.y = y;
+ if (class_ < 0 && battle_config.dead_branch_active)
+ md->mode = 0x1 + 0x4 + 0x80; //移動してアクティブで反撃する
+ md->m = m;
+ md->x0 = x;
+ md->y0 = y;
+ //md->xs = 0;
+ //md->ys = 0;
+ md->spawndelay1 = -1; // 一度のみフラグ
+ md->spawndelay2 = -1; // 一度のみフラグ
+
+ memcpy(md->npc_event, event, strlen(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;
+ 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;
+ return (amount > 0) ? md->bl.id : 0;
}
/*==========================================
* The MOB appearance for one time (& area specification for scripts)
@@ -208,9 +223,9 @@ int mob_once_spawn(struct map_session_data *sd,char *mapname,
*/
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)
+ const char *mobname,int class_,int amount,const char *event)
{
- int x,y,i,c,max,lx=-1,ly=-1,id=0;
+ int x,y,i,max,lx=-1,ly=-1,id=0;
int m;
if(strcmp(mapname,"this")==0)
@@ -221,7 +236,7 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
max=(y1-y0+1)*(x1-x0+1)*3;
if(max>1000)max=1000;
- if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // A summon is stopped if a value is unusual
+ if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // A summon is stopped if a value is unusual
return 0;
for(i=0;i<amount;i++){
@@ -229,15 +244,17 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
do{
x=rand()%(x1-x0+1)+x0;
y=rand()%(y1-y0+1)+y0;
- }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
+ } while (map_getcell(m,x,y,CELL_CHKNOPASS) && (++j)<max);
+ // freya }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
if(j>=max){
- if(lx>=0){ // 検索に失敗したので以前に沸いた場所を使う
+ if(lx>=0){ // Since reference went wrong, the place which boiled before is used.
x=lx;
y=ly;
}else
- return 0; // 最初に沸く場所の検索を失敗したのでやめる
+ 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);
+ if(x==0||y==0) printf("xory=0, x=%d,y=%d,x0=%d,y0=%d\n",x,y,x0,y0);
+ id=mob_once_spawn(sd,mapname,x,y,mobname,class_,1,event);
lx=x;
ly=y;
}
@@ -249,7 +266,7 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
*------------------------------------------
*/
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)
+ int x,int y,const char *mobname,int class_,int amount,const char *event,int guardian)
{
struct mob_data *md=NULL;
int m,count=1,lv=255;
@@ -262,33 +279,27 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
else
m=map_mapname2mapid(mapname);
- if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>2000) // 値が異常なら召喚を止める
+ if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // Invalid monster classes
return 0;
- if(class<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);
- }
+ md=(struct mob_data *) aCalloc(sizeof(struct mob_data), 1);
memset(md, '\0', sizeof *md);
-
-
- mob_spawn_dataset(md,mobname,class);
+ mob_spawn_dataset(md,mobname,class_);
md->bl.m=m;
md->bl.x=x;
md->bl.y=y;
@@ -308,7 +319,7 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
gc=guild_mapname2gc(map[md->bl.m].name);
if(gc) {
- mob_db[class].max_hp+=2000*gc->defense;
+ 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; }
@@ -317,7 +328,6 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
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; }
-
}
}
@@ -366,49 +376,49 @@ int mob_exclusion_check(struct mob_data *md,struct map_session_data *sd)
* Appearance income of mob
*------------------------------------------
*/
-int mob_get_viewclass(int class)
+int mob_get_viewclass(int class_)
{
- return mob_db[class].view_class;
+ return mob_db[class_].view_class;
}
-int mob_get_sex(int class)
+int mob_get_sex(int class_)
{
- return mob_db[class].sex;
+ return mob_db[class_].sex;
}
-short mob_get_hair(int class)
+short mob_get_hair(int class_)
{
- return mob_db[class].hair;
+ return mob_db[class_].hair;
}
-short mob_get_hair_color(int class)
+short mob_get_hair_color(int class_)
{
- return mob_db[class].hair_color;
+ return mob_db[class_].hair_color;
}
-short mob_get_weapon(int class)
+short mob_get_weapon(int class_)
{
- return mob_db[class].weapon;
+ return mob_db[class_].weapon;
}
-short mob_get_shield(int class)
+short mob_get_shield(int class_)
{
- return mob_db[class].shield;
+ return mob_db[class_].shield;
}
-short mob_get_head_top(int class)
+short mob_get_head_top(int class_)
{
- return mob_db[class].head_top;
+ return mob_db[class_].head_top;
}
-short mob_get_head_mid(int class)
+short mob_get_head_mid(int class_)
{
- return mob_db[class].head_mid;
+ return mob_db[class_].head_mid;
}
-short mob_get_head_buttom(int class)
+short mob_get_head_buttom(int class_)
{
- return mob_db[class].head_buttom;
+ return mob_db[class_].head_buttom;
}
-short mob_get_clothes_color(int class) // Add for player monster dye - Valaris
+short mob_get_clothes_color(int class_) // Add for player monster dye - Valaris
{
- return mob_db[class].clothes_color; // End
+ return mob_db[class_].clothes_color; // End
}
-int mob_get_equip(int class) // mob equip [Valaris]
+int mob_get_equip(int class_) // mob equip [Valaris]
{
- return mob_db[class].equip;
+ return mob_db[class_].equip;
}
/*==========================================
* Is MOB in the state in which the present movement is possible or not?
@@ -425,7 +435,7 @@ int mob_can_move(struct mob_data *md)
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;
@@ -442,8 +452,8 @@ static int calc_next_walk_step(struct mob_data *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);
+ return status_get_speed(&md->bl)*14/10;
+ return status_get_speed(&md->bl);
}
static int mob_walktoxy_sub(struct mob_data *md);
@@ -455,7 +465,7 @@ static int mob_walktoxy_sub(struct mob_data *md);
static int mob_walk(struct mob_data *md,unsigned int tick,int data)
{
int moveblock;
- int i,ctype;
+ 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};
int x,y,dx,dy;
@@ -480,8 +490,7 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
x = md->bl.x;
y = md->bl.y;
- ctype = map_getcell(md->bl.m,x,y);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS)) {
mob_stop_walking(md,1);
return 0;
}
@@ -489,12 +498,20 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
dx = dirx[md->dir];
dy = diry[md->dir];
- ctype = map_getcell(md->bl.m,x+dx,y+dy);
- if(ctype == 1 || ctype == 5) {
+ if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) {
+ mob_stop_walking(md,1);
+ return 0;
+ }
+
+ if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) {
mob_walktoxy_sub(md);
return 0;
}
+ if (skill_check_moonlit (&md->bl,x+dx,y+dy)) {
+ 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;
@@ -505,18 +522,18 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
if(md->min_chase>13)
md->min_chase--;
+ skill_unit_move(&md->bl,tick,0);
if(moveblock) map_delblock(&md->bl);
md->bl.x = x;
md->bl.y = y;
if(moveblock) map_addblock(&md->bl);
+ skill_unit_move(&md->bl,tick,1);
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); // スキルユニットの検査
}
if((i=calc_next_walk_step(md))>0){
i = i>>1;
@@ -591,11 +608,11 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
- race=mob_db[md->class].race;
+ race=mob_db[md->class_].race;
if(!(mode&0x80)){
md->target_id=0;
md->state.targettype = NONE_ATTACKABLE;
@@ -604,11 +621,11 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
if(tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 ||
((pc_ishiding(tsd) || tsd->state.gangsterparadise) && !((race == 4 || race == 6) && !tsd->perfect_hiding) ) ) ) {
md->target_id=0;
- md->state.targettype = NONE_ATTACKABLE;
+ md->state.targettype = NONE_ATTACKABLE;
return 0;
}
- range = mob_db[md->class].range;
+ range = mob_db[md->class_].range;
if(mode&1)
range++;
if(distance(md->bl.x,md->bl.y,tbl->x,tbl->y) > range)
@@ -625,9 +642,9 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
md->target_lv = battle_weapon_attack(&md->bl,tbl,tick,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);
+ status_change_end(&md->bl,SC_CLOAKING,-1);
- md->attackabletime = tick + battle_get_adelay(&md->bl);
+ md->attackabletime = tick + status_get_adelay(&md->bl);
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
md->state.state=MS_ATTACK;
@@ -684,7 +701,7 @@ int mob_changestate(struct mob_data *md,int state,int type)
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->attackabletime = tick + status_get_amotion(&md->bl);
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
}
else {
@@ -702,8 +719,8 @@ int mob_changestate(struct mob_data *md,int state,int type)
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); // ステータス異常を解除する
+ skill_unit_move(&md->bl,gettick(),0);
+ status_change_clear(&md->bl,2); // ステータス異常を解除する
skill_clear_unitgroup(&md->bl); // 全てのスキルユニットグループを削除する
skill_cleartimerskill(&md->bl);
if(md->deletetimer!=-1)
@@ -730,15 +747,12 @@ static int mob_timer(int tid,unsigned int tick,int id,int data)
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)
printf("mob_timer %d != %d\n",md->timer,tid);
@@ -764,6 +778,10 @@ static int mob_timer(int tid,unsigned int tick,int id,int data)
printf("mob_timer : %d ?\n",md->state.state);
break;
}
+
+ if (md->timer == -1)
+ mob_changestate(md,MS_WALK,0);
+
map_freeblock_unlock();
return 0;
}
@@ -775,11 +793,25 @@ static int mob_timer(int tid,unsigned int tick,int id,int data)
static int mob_walktoxy_sub(struct mob_data *md)
{
struct walkpath_data wpd;
+ int x,y;
+ 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);
+ memset(&wpd, 0, sizeof(wpd));
+
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;
+ if (wpd.path[0] >= 8)
+ return 1;
+ x = md->bl.x+dirx[wpd.path[0]];
+ y = md->bl.y+diry[wpd.path[0]];
+ if (map_getcell(md->bl.m,x,y,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) {
+ md->state.change_walk_target=0;
+ return 1;
+ }
+
memcpy(&md->walkpath,&wpd,sizeof(wpd));
md->state.change_walk_target=0;
@@ -857,7 +889,7 @@ int mob_setdelayspawn(int id)
spawntime1=md->last_spawntime+md->spawndelay1;
spawntime2=md->last_deadtime+md->spawndelay2;
- spawntime3=gettick()+5000;
+ spawntime3=gettick()+5000+rand()%5000; //Lupus
// spawntime = max(spawntime1,spawntime2,spawntime3);
if(DIFF_TICK(spawntime1,spawntime2)>0)
spawntime=spawntime1;
@@ -882,7 +914,8 @@ int mob_spawn(int id)
struct mob_data *md;
struct block_list *bl;
- nullpo_retr(-1, bl=map_id2bl(id));
+ //nullpo_retr(-1, bl=map_id2bl(id));
+ bl=map_id2bl(id);
if(!bl || !bl->type || bl->type!=BL_MOB)
return -1;
@@ -891,15 +924,15 @@ int mob_spawn(int id)
if(!md || !md->bl.type || md->bl.type!=BL_MOB)
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);
+// skill_unit_move(&md->bl,tick,0);
map_delblock(&md->bl);
}
else
- md->class = md->base_class;
+ md->class_ = md->base_class;
md->bl.m =md->m;
do {
@@ -911,7 +944,7 @@ int mob_spawn(int id)
y=md->y0+rand()%(md->ys+1)-md->ys/2;
}
i++;
- } while(((c=map_getcell(md->bl.m,x,y))==1 || c==5) && i<50);
+ } while(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS) && i<50);
if(i>=50){
// if(battle_config.error_log==1)
@@ -923,8 +956,7 @@ int mob_spawn(int id)
md->to_x=md->bl.x=x;
md->to_y=md->bl.y=y;
md->dir=0;
-
- map_addblock(&md->bl);
+ md->target_dir=0;
memset(&md->state,0,sizeof(md->state));
md->attacked_id = 0;
@@ -932,11 +964,11 @@ int mob_spawn(int id)
md->move_fail_count = 0;
if(!md->speed)
- md->speed = mob_db[md->class].speed;
- md->def_ele = mob_db[md->class].element;
+ md->speed = mob_db[md->class_].speed;
+ md->def_ele = mob_db[md->class_].element;
if(!md->level) // [Valaris]
- md->level=mob_db[md->class].lv;
+ md->level=mob_db[md->class_].lv;
md->master_id=0;
md->master_dist=0;
@@ -950,13 +982,12 @@ int mob_spawn(int id)
md->canmove_tick = tick;
md->guild_id = 0;
- if (md->class >= 1285 && md->class <= 1288) {
+ if (md->class_ >= 1285 && md->class_ <= 1288) {
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc)
md->guild_id = gc->guild_id;
}
-
- md->sg_count=0;
+
md->deletetimer=-1;
md->skilltimer=-1;
@@ -983,12 +1014,15 @@ int mob_spawn(int id)
memset(md->skillunit,0,sizeof(md->skillunit));
memset(md->skillunittick,0,sizeof(md->skillunittick));
- md->hp = battle_get_max_hp(&md->bl);
+ md->hp = status_get_max_hp(&md->bl);
if(md->hp<=0){
- mob_makedummymobdb(md->class);
- md->hp = battle_get_max_hp(&md->bl);
+ mob_makedummymobdb(md->class_);
+ md->hp = status_get_max_hp(&md->bl);
}
+ map_addblock(&md->bl);
+ skill_unit_move(&md->bl,tick,1);
+
clif_spawnmob(md);
return 0;
@@ -1026,10 +1060,9 @@ 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;
@@ -1054,9 +1087,9 @@ int mob_stop_walking(struct mob_data *md,int type)
if(type&0x01)
clif_fixmobpos(md);
if(type&0x02) {
- int delay=battle_get_dmotion(&md->bl);
+ int delay=status_get_dmotion(&md->bl);
unsigned int tick = gettick();
- if(md->canmove_tick < tick)
+ if(battle_config.monster_damage_delay && md->canmove_tick < tick)
md->canmove_tick = tick + delay;
}
@@ -1079,46 +1112,43 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range)
dx=abs(bl->x - md->bl.x);
dy=abs(bl->y - md->bl.y);
+ 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 ) // 同じマス
+ return 1;
+
//=========== guildcastle guardian no search start===========
//when players are the guild castle member not attack them !
- if(md->class >= 1285 && md->class <= 1287){
+ /*if(md->class_ >= 1285 && 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(gc && bl->type == BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)bl);
- if(!gc)
- return 0;
- if(gc && sd && sd->status.guild_id) {
- g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris]
+ if(gc && sd->status.guild_id > 0) {
+ g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris]
if(g && 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) { // option to have monsters ignore GMs [Valaris]
+ /*if(bl->type == BL_PC && battle_config.monsters_ignore_gm) { // option to have monsters ignore GMs [Valaris]
struct map_session_data *sd;
if((sd=(struct map_session_data *)bl) != NULL && pc_isGM(sd) >= battle_config.monsters_ignore_gm)
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 ) // 同じマス
- return 1;
+ }*/
// Obstacle judging
wpd.path_len=0;
@@ -1156,12 +1186,12 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
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;
+ sc_data = status_get_sc_data(bl);
+ option = status_get_option(bl);
+ race=mob_db[md->class_].race;
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
@@ -1170,7 +1200,9 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
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) || rand()%100>25) )
+ if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && (!(mode&0x04) || rand()%100>25) &&
+ // if the monster was provoked ignore the above rule [celest]
+ !(md->state.provoke_flag && md->state.provoke_flag == bl->id))
return 0;
if(mode&0x20 || // Coercion is exerted if it is MVPMOB.
@@ -1184,11 +1216,13 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
return 0;
}
- md->target_id=bl->id; // Since there was no disturbance, it locks on to target.
+ 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;
+ if (md->state.provoke_flag)
+ md->state.provoke_flag = 0;
md->min_chase=dist+13;
if(md->min_chase>26)
md->min_chase=26;
@@ -1223,18 +1257,18 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
return 0;
if(!smd->mode)
- mode=mob_db[smd->class].mode;
+ mode=mob_db[smd->class_].mode;
else
mode=smd->mode;
// アクティブでターゲット射程内にいるなら、ロックする
if( mode&0x04 ){
- race=mob_db[smd->class].race;
+ race=mob_db[smd->class_].race;
//対象がPCの場合
if(tsd &&
- !pc_isdead(tsd) &&
- tsd->bl.m == smd->bl.m &&
- tsd->invincible_timer == -1 &&
+ !pc_isdead(tsd) &&
+ tsd->bl.m == smd->bl.m &&
+ tsd->invincible_timer == -1 &&
!pc_isinvisible(tsd) &&
(dist=distance(smd->bl.x,smd->bl.y,tsd->bl.x,tsd->bl.y))<9
)
@@ -1246,7 +1280,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
rand()%1000<1000/(++(*pcc)) ){ // 範囲内PCで等確率にする
smd->target_id=tsd->bl.id;
smd->state.targettype = ATTACKABLE;
- smd->min_chase=13;
+ smd->min_chase=13;
}
}
}
@@ -1282,10 +1316,10 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
nullpo_retr(0, itc=va_arg(ap,int *));
if(!md->mode)
- mode=mob_db[md->class].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) )
@@ -1319,8 +1353,8 @@ static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap)
nullpo_retr(0, target=va_arg(ap,struct block_list *));
// same family free in a range at a link monster -- it will be made to lock if MOB is
-/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class].mode&0x08){
- if( tmd->class==md->class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
+/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class_].mode&0x08){
+ if( tmd->class_==md->class_ && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
if( mob_can_reach(tmd,target,12) ){ // Reachability judging
tmd->target_id=md->target_id;
tmd->state.targettype = ATTACKABLE;
@@ -1328,8 +1362,8 @@ static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap)
}
}
}*/
- if( md->attacked_id > 0 && mob_db[md->class].mode&0x08){
- if( tmd->class==md->class && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){
+ if( md->attacked_id > 0 && mob_db[md->class_].mode&0x08){
+ if( tmd->class_==md->class_ && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){
if( mob_can_reach(tmd,target,12) ){ // Reachability judging
tmd->target_id=md->attacked_id;
tmd->state.targettype = ATTACKABLE;
@@ -1355,12 +1389,24 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
if((bl=map_id2bl(md->master_id)) != NULL )
mmd=(struct mob_data *)bl;
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
// It is not main monster/leader.
if(!mmd || mmd->bl.type!=BL_MOB || mmd->bl.id!=md->master_id)
return 0;
+ // 呼び戻し
+ if(mmd->recall_flag == 1){
+ if (mmd->recallcount < (mmd->recallmob_count+2) ){
+ mob_warp(md,-1,mmd->bl.x,mmd->bl.y,3);
+ mmd->recallcount += 1;
+ } else{
+ mmd->recall_flag = 0;
+ mmd->recallcount=0;
+ }
+ md->state.master_check = 1;
+ return 0;
+ }
// Since it is in the map on which the master is not, teleport is carried out and it pursues.
if( mmd->bl.m != md->bl.m ){
mob_warp(md,mmd->bl.m,mmd->bl.x,mmd->bl.y,3);
@@ -1380,7 +1426,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
}
// Although there is the master, since it is somewhat far, it approaches.
- if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
+ if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
(md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0) && md->master_dist<15){
int i=0,dx,dy,ret;
if(md->master_dist>4) {
@@ -1426,7 +1472,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
struct map_session_data *sd=map_id2sd(mmd->target_id);
if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
- race=mob_db[md->class].race;
+ race=mob_db[md->class_].race;
if(mode&0x20 ||
(sd->sc_data[SC_TRICKDEAD].timer == -1 && sd->sc_data[SC_BASILICA].timer == -1 &&
( (!pc_ishiding(sd) && !sd->state.gangsterparadise) || ((race == 4 || race == 6) && !sd->perfect_hiding) ) ) ){ // 妨害がないか判定
@@ -1444,7 +1490,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
struct map_session_data *sd=map_id2sd(md->target_id);
if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
- race=mob_db[mmd->class].race;
+ race=mob_db[mmd->class_].race;
if(mode&0x20 ||
(sd->sc_data[SC_TRICKDEAD].timer == -1 &&
(!(sd->status.option&0x06) || race==4 || race==6)
@@ -1485,23 +1531,34 @@ static int mob_randomwalk(struct mob_data *md,int tick)
nullpo_retr(0, md);
- speed=battle_get_speed(&md->bl);
+ speed=status_get_speed(&md->bl);
if(DIFF_TICK(md->next_walktime,tick)<0){
int i,x,y,c,d=12-md->move_fail_count;
+ int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
if(d<5) d=5;
for(i=0;i<retrycount;i++){ // Search of a movable place
int r=rand();
- x=md->bl.x+r%(d*2+1)-d;
- y=md->bl.y+r/(d*2+1)%(d*2+1)-d;
- if((c=map_getcell(md->bl.m,x,y))!=1 && c!=5 && mob_walktoxy(md,x,y,1)==0){
+ x=r%(d*2+1)-d;
+ y=r/(d*2+1)%(d*2+1)-d;
+ if (md->target_dir){
+ if (x<0) x=0-x;
+ if (y<0) y=0-y;
+ x *= mask[md->target_dir-1][0];
+ y *= mask[md->target_dir-1][1];
+ }
+ x+=md->bl.x;
+ y+=md->bl.y;
+
+ if((map_getcell(md->bl.m,x,y,CELL_CHKPASS)) && mob_walktoxy(md,x,y,1)==0){
md->move_fail_count=0;
break;
}
if(i+1>=retrycount){
md->move_fail_count++;
+ md->target_dir = 0;
if(md->move_fail_count>1000){
if(battle_config.error_log)
- printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class);
+ printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class_);
md->move_fail_count=0;
mob_spawn(md->bl.id);
}
@@ -1534,6 +1591,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
int i,dx,dy,ret,dist;
int attack_type=0;
int mode,race;
+ int search_size = AREA_SIZE*2;
+ int blind_flag = 0;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
@@ -1541,7 +1600,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
tick=va_arg(ap,unsigned int);
-
if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME)
return 0;
md->last_thinktime=tick;
@@ -1553,16 +1611,19 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
}
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
- race=mob_db[md->class].race;
+ race=mob_db[md->class_].race;
// Abnormalities
if((md->opt1 > 0 && md->opt1 != 6) || md->state.state==MS_DELAY || md->sc_data[SC_BLADESTOP].timer != -1)
return 0;
+ if (md->sc_data && md->sc_data[SC_BLIND].timer != -1)
+ blind_flag = 1;
+
if(!(mode&0x80) && md->target_id > 0)
md->target_id = 0;
@@ -1587,7 +1648,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
if(abl->type==BL_PC)
asd=(struct map_session_data *)abl;
if(asd==NULL || md->bl.m != abl->m || abl->prev == NULL || asd->invincible_timer != -1 || pc_isinvisible(asd) ||
- (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0)
+ (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0 ||
+ (blind_flag && dist>3))
md->attacked_id=0;
else {
//距離が遠い場合はタゲを変更しない
@@ -1614,15 +1676,16 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
if( (!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mode&0x04 && !md->state.master_check &&
battle_config.monster_active_enable){
i=0;
+ search_size = (blind_flag) ? 3 : AREA_SIZE*2;
if(md->state.special_mob_ai){
map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
- md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
- md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
+ md->bl.x-search_size,md->bl.y-search_size,
+ md->bl.x+search_size,md->bl.y+search_size,
0,md,&i);
}else{
map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
- md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
- md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
+ md->bl.x-search_size,md->bl.y-search_size,
+ md->bl.x+search_size,md->bl.y+search_size,
BL_PC,md,&i);
}
}
@@ -1630,9 +1693,10 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
// The item search of a route monster
if( !md->target_id && mode&0x02 && !md->state.master_check){
i=0;
+ search_size = (blind_flag) ? 3 : AREA_SIZE*2;
map_foreachinarea(mob_ai_sub_hard_lootsearch,md->bl.m,
- md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
- md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
+ md->bl.x-search_size,md->bl.y-search_size,
+ md->bl.x+search_size,md->bl.y+search_size,
BL_ITEM,md,&i);
}
@@ -1644,13 +1708,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
else if(tbl->type==BL_MOB)
tmd=(struct mob_data *)tbl;
if(tsd || tmd) {
- if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase)
+ if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y)) >= search_size || (blind_flag && dist>3))
mob_unlocktarget(md,tick); // 別マップか、視界外
else if( tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 ||
((pc_ishiding(tsd) || tsd->state.gangsterparadise) &&
!((race == 4 || race == 6) && !tsd->perfect_hiding) )) )
mob_unlocktarget(md,tick); // スキルなどによる策敵妨害
- else if(!battle_check_range(&md->bl,tbl,mob_db[md->class].range)){
+ else if(!battle_check_range(&md->bl,tbl,mob_db[md->class_].range)){
// 攻撃範囲外なので移動
if(!(mode&1)){ // 移動しないモード
mob_unlocktarget(md,tick);
@@ -1663,9 +1727,11 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
// if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) )
if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
return 0; // 既に移動中
- if( !mob_can_reach(md,tbl,(md->min_chase>13)?md->min_chase:13) )
+ search_size = (blind_flag) ? 3 :
+ ((md->min_chase > 13) ? md->min_chase : 13);
+ if(!mob_can_reach(md,tbl, search_size))
mob_unlocktarget(md,tick); // 移動できないのでタゲ解除(IWとか?)
- else{
+ else {
// 追跡
md->next_walktime=tick+500;
i=0;
@@ -1692,15 +1758,15 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
i++;
} while(ret && i<5);
-
+
if(ret){ // 移動不可能な所からの攻撃なら2歩下る
if(dx<0) dx=2;
else if(dx>0) dx=-2;
if(dy<0) dy=2;
else if(dy>0) dy=-2;
mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
+ }
}
- }
} else { // 攻撃射程範囲内
md->state.skillstate=MSS_ATTACK;
if(md->state.state==MS_WALK)
@@ -1708,23 +1774,17 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
if(md->state.state==MS_ATTACK)
return 0; // 既に攻撃中
mob_changestate(md,MS_ATTACK,attack_type);
-
-/* if(mode&0x08){ // リンクモンスター
- map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
- md->bl.x-13,md->bl.y-13,
- md->bl.x+13,md->bl.y+13,
- BL_MOB,md,&tsd->bl);
- }*/
}
return 0;
- }else{ // ルートモンスター処理
+ } else { // ルートモンスター処理
if(tbl == NULL || tbl->type != BL_ITEM ||tbl->m != md->bl.m ||
- (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem){
+ (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem |
+ (blind_flag && dist>=4)){
// 遠すぎるかアイテムがなくなった
mob_unlocktarget(md,tick);
if(md->state.state==MS_WALK)
mob_stop_walking(md,1); // 歩行中なら停止
- }else if(dist){
+ } else if(dist) {
if(!(mode&1)){ // 移動しないモード
mob_unlocktarget(md,tick);
return 0;
@@ -1838,7 +1898,8 @@ static int mob_ai_hard(int tid,unsigned int tick,int id,int data)
*/
static int mob_ai_sub_lazy(void * key,void * data,va_list app)
{
- struct mob_data *md=data;
+ struct mob_data *md=(struct mob_data *)data;
+ struct mob_data *mmd=NULL;
unsigned int tick;
va_list ap;
@@ -1849,8 +1910,9 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
if(md->bl.type!=BL_MOB)
return 0;
- if(!md->bl.type || md->bl.type!=BL_MOB)
- return 0;
+ if (md->master_id > 0) {
+ mmd = (struct mob_data *)map_id2bl(md->master_id); //自分のBOSSの情報
+ }
tick=va_arg(ap,unsigned int);
@@ -1864,8 +1926,14 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
return 0;
}
+ // 取り巻きモンスターの処理(呼び戻しされた時)
+ if(mmd && md->state.special_mob_ai == 0 && mmd->recall_flag == 1) {
+ mob_ai_sub_hard_slavemob (md,tick);
+ return 0;
+ }
+
if(DIFF_TICK(md->next_walktime,tick)<0 &&
- (mob_db[md->class].mode&1) && mob_can_move(md) ){
+ (mob_db[md->class_].mode&1) && mob_can_move(md) ){
if( map[md->bl.m].users>0 ){
// Since PC is in the same map, somewhat better negligent processing is carried out.
@@ -1876,7 +1944,7 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
// MOB which is not not the summons MOB but BOSS, either sometimes reboils.
else if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
- mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
+ mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode & 0x20))
mob_spawn(md->bl.id);
}else{
@@ -1884,7 +1952,7 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
// MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
- mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
+ mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode & 0x20))
mob_warp(md,-1,-1,-1,-1);
}
@@ -1931,7 +1999,7 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
{
struct delay_item_drop *ditem;
struct item temp_item;
- int flag;
+ int flag, drop_flag = 1;
nullpo_retr(0, ditem=(struct delay_item_drop *)id);
@@ -1940,18 +2008,45 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
temp_item.amount = ditem->amount;
temp_item.identify = !itemdb_isequip3(temp_item.nameid);
- if(battle_config.item_auto_get){
- if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){
- clif_additem(ditem->first_sd,0,0,flag);
- map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (ditem->first_sd){
+ #if 0
+ if (ditem->first_sd->status.party_id > 0){
+ struct party *p;
+ if((p=party_search(ditem->first_sd->status.party_id)) && p->item){
+ struct map_session_data *sd = NULL;
+ int i;
+ for (i = p->itemc + 1; i!=p->itemc; i++) { // initialise counter and loop through the party
+ if (i >= MAX_PARTY)
+ i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
+ if ((sd=p->member[i].sd)!=NULL && sd->bl.m == ditem->first_sd->bl.m)
+ break;
+ }
+ if (sd){ // if an appropiate party member was found
+ drop_flag = 0;
+ if ((p->itemc++) >= MAX_PARTY)
+ p->itemc = 0;
+ if ((flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))) {
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
+ }
+ }
+ } else
+ #endif
+ if(battle_config.item_auto_get || ditem->first_sd->autoloot){//Autoloot added by Upa-Kun
+ drop_flag = 0;
+ if((flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
}
- free(ditem);
- return 0;
}
- map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (drop_flag) {
+ map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ }
- free(ditem);
+ aFree(ditem);
return 0;
}
@@ -1962,22 +2057,49 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data)
{
struct delay_item_drop2 *ditem;
- int flag;
+ int flag, drop_flag = 1;
nullpo_retr(0, ditem=(struct delay_item_drop2 *)id);
- if(battle_config.item_auto_get){
- if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
- clif_additem(ditem->first_sd,0,0,flag);
- map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (ditem->first_sd){
+ #if 0
+ if (ditem->first_sd->status.party_id > 0){
+ struct party *p;
+ if((p=party_search(ditem->first_sd->status.party_id)) && p->item){
+ struct map_session_data *sd = NULL;
+ int i;
+ for (i = p->itemc + 1; i!=p->itemc; i++) { // initialise counter and loop through the party
+ if (i >= MAX_PARTY)
+ i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
+ if ((sd=p->member[i].sd)!=NULL && sd->bl.m == ditem->first_sd->bl.m)
+ break;
+ }
+ if (sd){ // if an appropiate party member was found
+ drop_flag = 0;
+ if ((p->itemc++) >= MAX_PARTY)
+ p->itemc = 0;
+ if((flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
+ }
+ }
+ } else
+ #endif
+ if(battle_config.item_auto_get || ditem->first_sd->autoloot){//Autoloot added by Upa-Kun
+ drop_flag = 0;
+ if((flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
}
- free(ditem);
- return 0;
}
- map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (drop_flag) {
+ map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ }
- free(ditem);
+ aFree(ditem);
return 0;
}
@@ -1985,44 +2107,49 @@ static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data)
* mob data is erased.
*------------------------------------------
*/
-int mob_delete(struct mob_data *md)
+void mob_unload(struct mob_data *md)
+{
+ nullpo_retv(md);
+ mob_remove_map(md, 0);
+ map_deliddb(&md->bl);
+ aFree(md);
+ md = NULL;
+}
+int mob_remove_map(struct mob_data *md, int type)
{
nullpo_retr(1, md);
if(md->bl.prev == NULL)
return 1;
mob_changestate(md,MS_DEAD,0);
- clif_clearchar_area(&md->bl,1);
+ clif_clearchar_area(&md->bl,type);
map_delblock(&md->bl);
- if(mob_get_viewclass(md->class) <= 1000)
- clif_clearchar_delay(gettick()+3000,&md->bl,0);
- mob_deleteslave(md);
- mob_setdelayspawn(md->bl.id);
+ if (md->lootitem){
+ aFree(md->lootitem);
+ md->lootitem = NULL;
+ }
+
return 0;
}
-
-int mob_catch_delete(struct mob_data *md,int type)
+int mob_delete(struct mob_data *md)
{
nullpo_retr(1, md);
- if(md->bl.prev == NULL)
- return 1;
- mob_changestate(md,MS_DEAD,0);
- clif_clearchar_area(&md->bl,type);
- map_delblock(&md->bl);
+ mob_remove_map(md, 1);
+ if (mob_get_viewclass(md->class_) <= 1000)
+ clif_clearchar_delay(gettick()+3000,&md->bl,0);
+ mob_deleteslave(md);
mob_setdelayspawn(md->bl.id);
return 0;
}
-
int mob_timer_delete(int tid, unsigned int tick, int id, int data)
{
- struct block_list *bl=map_id2bl(id);
- struct mob_data *md;
-
- nullpo_retr(0, bl);
+ struct mob_data *md=(struct mob_data *)map_id2bl(id);
+ nullpo_retr(0, md);
- md = (struct mob_data *)bl;
- mob_catch_delete(md,3);
+//for Alchemist CANNIBALIZE [Lupus]
+ mob_remove_map(md, 3);
+ mob_setdelayspawn(md->bl.id);
return 0;
}
@@ -2074,15 +2201,17 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
int mvp_damage,max_hp;
unsigned int tick = gettick();
struct map_session_data *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL;
- double dmg_rate,tdmg,temp;
+ struct block_list *master = NULL;
+ double tdmg,temp;
struct item item;
int ret;
int drop_rate;
- int skill,sp;
-
+ int race;
+
nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
+ race = status_get_race(&md->bl);
if(src && src->type == BL_PC) {
sd = (struct map_session_data *)src;
@@ -2108,7 +2237,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
return 0;
}
- if(md->sc_data[SC_ENDURE].timer == -1)
+ if(battle_config.monster_damage_delay && md->sc_data[SC_ENDURE].timer == -1)
mob_stop_walking(md,3);
if(damage > max_hp>>2)
skill_stop_dancing(&md->bl,0);
@@ -2123,7 +2252,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(!(type&2)) {
if(sd!=NULL){
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
- if(md->dmglog[i].id==sd->bl.id)
+ //if(md->dmglog[i].id==sd->bl.id)
+ if(md->dmglog[i].id==sd->status.char_id)
break;
if(md->dmglog[i].id==0){
minpos=i;
@@ -2137,7 +2267,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=damage;
else {
- md->dmglog[minpos].id=sd->bl.id;
+ //md->dmglog[minpos].id=sd->bl.id;
+ md->dmglog[minpos].id=sd->status.char_id;
md->dmglog[minpos].dmg=damage;
}
@@ -2148,7 +2279,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
struct pet_data *pd = (struct pet_data *)src;
nullpo_retr(0, pd);
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
- if(md->dmglog[i].id==pd->msd->bl.id)
+ //if(md->dmglog[i].id==pd->msd->bl.id)
+ if(md->dmglog[i].id==pd->msd->status.char_id)
break;
if(md->dmglog[i].id==0){
minpos=i;
@@ -2162,7 +2294,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=(damage*battle_config.pet_attack_exp_rate)/100;
else {
- md->dmglog[minpos].id=pd->msd->bl.id;
+ //md->dmglog[minpos].id=pd->msd->bl.id;
+ md->dmglog[minpos].id=pd->msd->status.char_id;
md->dmglog[minpos].dmg=(damage*battle_config.pet_attack_exp_rate)/100;
}
}
@@ -2195,88 +2328,92 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
md->hp-=damage;
-
- if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris]
+
+ if(md->class_ >= 1285 && md->class_ <=1287) { // guardian hp update [Valaris]
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc) {
- if(md->bl.id==gc->GID0) {
+ if(md->bl.id==gc->GID0) {
gc->Ghp0=md->hp;
if(gc->Ghp0<=0) {
guild_castledatasave(gc->castle_id,10,0);
guild_castledatasave(gc->castle_id,18,0);
}
- }
- if(md->bl.id==gc->GID1) {
+ }
+ if(md->bl.id==gc->GID1) {
gc->Ghp1=md->hp;
if(gc->Ghp1<=0) {
guild_castledatasave(gc->castle_id,11,0);
guild_castledatasave(gc->castle_id,19,0);
}
}
- if(md->bl.id==gc->GID2) {
+ if(md->bl.id==gc->GID2) {
gc->Ghp2=md->hp;
if(gc->Ghp2<=0) {
guild_castledatasave(gc->castle_id,12,0);
guild_castledatasave(gc->castle_id,20,0);
}
}
- if(md->bl.id==gc->GID3) {
+ if(md->bl.id==gc->GID3) {
gc->Ghp3=md->hp;
if(gc->Ghp3<=0) {
guild_castledatasave(gc->castle_id,13,0);
guild_castledatasave(gc->castle_id,21,0);
}
}
- if(md->bl.id==gc->GID4) {
+ if(md->bl.id==gc->GID4) {
gc->Ghp4=md->hp;
if(gc->Ghp4<=0) {
guild_castledatasave(gc->castle_id,14,0);
guild_castledatasave(gc->castle_id,22,0);
}
}
- if(md->bl.id==gc->GID5) {
+ if(md->bl.id==gc->GID5) {
gc->Ghp5=md->hp;
if(gc->Ghp5<=0) {
guild_castledatasave(gc->castle_id,15,0);
guild_castledatasave(gc->castle_id,23,0);
}
}
- if(md->bl.id==gc->GID6) {
+ if(md->bl.id==gc->GID6) {
gc->Ghp6=md->hp;
if(gc->Ghp6<=0) {
guild_castledatasave(gc->castle_id,16,0);
guild_castledatasave(gc->castle_id,24,0);
}
}
- if(md->bl.id==gc->GID7) {
+ if(md->bl.id==gc->GID7) {
gc->Ghp7=md->hp;
if(gc->Ghp7<=0) {
guild_castledatasave(gc->castle_id,17,0);
guild_castledatasave(gc->castle_id,25,0);
-
+
}
}
}
} // end addition [Valaris]
-
+
if(md->option&2 )
- skill_status_change_end(&md->bl, SC_HIDING, -1);
+ status_change_end(&md->bl, SC_HIDING, -1);
if(md->option&4 )
- skill_status_change_end(&md->bl, SC_CLOAKING, -1);
+ status_change_end(&md->bl, SC_CLOAKING, -1);
if(md->state.special_mob_ai == 2){//スフィアーマイン
int skillidx=0;
-
- if((skillidx=mob_skillid2skillidx(md->class,NPC_SELFDESTRUCTION2))>=0){
+
+ if((skillidx=mob_skillid2skillidx(md->class_,NPC_SELFDESTRUCTION2))>=0){
md->mode |= 0x1;
md->next_walktime=tick;
mobskill_use_id(md,&md->bl,skillidx);//自爆詠唱開始
md->state.special_mob_ai++;
}
+ if (src && md->master_id==src->id)
+ md->target_dir=map_calc_dir(src,md->bl.x,md->bl.y)+1;
}
if(md->hp>0){
+ if (battle_config.show_mob_hp)
+ clif_update_mobhp (md);
return 0;
}
@@ -2289,19 +2426,33 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
memset(tmpsd,0,sizeof(tmpsd));
memset(pt,0,sizeof(pt));
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
if(src && src->type == BL_MOB)
mob_unlocktarget((struct mob_data *)src,tick);
- /* ソウルドレイン */
- if(sd && (skill=pc_checkskill(sd,HW_SOULDRAIN))>0){
- clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,skill,1);
- sp = (battle_get_lv(&md->bl))*(65+15*skill)/100;
- if(sd->status.sp + sp > sd->status.max_sp)
- sp = sd->status.max_sp - sd->status.sp;
- sd->status.sp += sp;
- clif_heal(sd->fd,SP_SP,sp);
+
+ if(sd) {
+ int sp = 0, hp = 0;
+ if (sd->state.attack_type == BF_MAGIC && (i=pc_checkskill(sd,HW_SOULDRAIN))>0){ /* ソウルドレイン */
+ clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,i,1);
+ sp += (status_get_lv(&md->bl))*(65+15*i)/100;
+ }
+ sp += sd->sp_gain_value;
+ sp += sd->sp_gain_race[race];
+ hp += sd->hp_gain_value;
+ if (sp > 0) {
+ if(sd->status.sp + sp > sd->status.max_sp)
+ sp = sd->status.max_sp - sd->status.sp;
+ sd->status.sp += sp;
+ clif_heal(sd->fd,SP_SP,sp);
+ }
+ if (hp > 0) {
+ if(sd->status.hp + hp > sd->status.max_hp)
+ hp = sd->status.max_hp - sd->status.hp;
+ sd->status.hp += hp;
+ clif_heal(sd->fd,SP_HP,hp);
+ }
}
// map外に消えた人は計算から除くので
@@ -2311,7 +2462,12 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
for(i=0,count=0,mvp_damage=0;i<DAMAGELOG_SIZE;i++){
if(md->dmglog[i].id==0)
continue;
- tmpsd[i] = map_id2sd(md->dmglog[i].id);
+ // Will this slow things down too much?
+ tmpsd[i] = map_charid2sd(md->dmglog[i].id);
+ // try finding again
+ if(tmpsd[i] == NULL)
+ tmpsd[i] = map_id2sd(md->dmglog[i].id);
+ // if we still can't find the player
if(tmpsd[i] == NULL)
continue;
count++;
@@ -2327,64 +2483,81 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
}
- // [MouseJstr]
- if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
-
- if((double)max_hp < tdmg)
- dmg_rate = ((double)max_hp) / tdmg;
- else dmg_rate = 1;
+ // [MouseJstr]
+ if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
// 経験値の分配
for(i=0;i<DAMAGELOG_SIZE;i++){
int pid,base_exp,job_exp,flag=1,zeny=0;
double per;
struct party *p;
- if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m)
+ if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i]))
continue;
-/* jAthena's exp formula
- per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
- temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
- base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
- if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1;
- if(base_exp < 0) base_exp = 0;
- temp = ((double)mob_db[md->class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
- job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
- if(mob_db[md->class].job_exp > 0 && job_exp < 1) job_exp = 1;
- if(job_exp < 0) job_exp = 0;
-*/
-//eAthena's exp formula rather than jAthena's
- per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
- if(per>512) per=512;
- if(per<1) per=1;
- base_exp=mob_db[md->class].base_exp*per/256;
-
- if(base_exp < 1) base_exp = 1;
- if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) {
- base_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
- }
- job_exp=mob_db[md->class].job_exp*per/256;
- if(job_exp < 1) job_exp = 1;
- if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) {
- job_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
+
+ if (battle_config.exp_calc_type == 0) {
+ // jAthena's exp formula
+ per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./tdmg;
+ temp = (double)mob_db[md->class_].base_exp * per;
+ base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
+ if(mob_db[md->class_].base_exp > 0 && base_exp < 1) base_exp = 1;
+ if(base_exp < 0) base_exp = 0;
+ temp = (double)mob_db[md->class_].job_exp * per;
+ job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
+ if(mob_db[md->class_].job_exp > 0 && job_exp < 1) job_exp = 1;
+ if(job_exp < 0) job_exp = 0;
}
- if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) { // for summoned creatures [Valaris]
- base_exp = 0;
- job_exp = 0;
+ else if (battle_config.exp_calc_type == 1) {
+ //eAthena's exp formula rather than jAthena's
+ per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
+ if(per>512) per=512;
+ if(per<1) per=1;
+ base_exp=(int) (mob_db[md->class_].base_exp*per/256);
+ if(base_exp < 1) base_exp = 1;
+ job_exp=(int) (mob_db[md->class_].job_exp*per/256);
+ if(job_exp < 1) job_exp = 1;
}
else {
- if(battle_config.zeny_from_mobs) {
- if(md->level > 0) zeny=(md->level+rand()%md->level)*per/256; // zeny calculation moblv + random moblv [Valaris]
- if(mob_db[md->class].mexp > 0)
+ //eAthena's exp formula rather than jAthena's, but based on total damage dealt
+ per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/tdmg;
+ if(per>512) per=512;
+ if(per<1) per=1;
+ base_exp=(int) (mob_db[md->class_].base_exp*per/256);
+ if(base_exp < 1) base_exp = 1;
+ job_exp=(int) (mob_db[md->class_].job_exp*per/256);
+ if(job_exp < 1) job_exp = 1;
+ }
+
+ if(sd) {
+ int rate;
+ if ((rate = sd->expaddrace[race]) > 0) {
+ base_exp = (100+rate)*base_exp/100;
+ job_exp = (100+rate)*job_exp/100;
+ }
+ if (battle_config.pk_mode && (mob_db[md->class_].lv - sd->status.base_level >= 20)) {
+ base_exp = (int) (base_exp *1.15); // pk_mode additional exp if monster >20 levels [Valaris]
+ job_exp = (int) (job_exp * 1.15);
+ }
+ }
+ if(md->master_id) {
+ if(((master = map_id2bl(md->master_id)) && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses)
+ (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) { // for summoned creatures [Valaris]
+ base_exp = 0;
+ job_exp = 0;
+ }
+ } else {
+ if(battle_config.zeny_from_mobs) {
+ if(md->level > 0) zeny=(int) ((md->level+rand()%md->level)*per/256); // zeny calculation moblv + random moblv [Valaris]
+ if(mob_db[md->class_].mexp > 0)
zeny*=rand()%250;
}
- if(battle_config.mobs_level_up && md->level > mob_db[md->class].lv) { // [Valaris]
- job_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].job_exp*.03)*per/256;
- base_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].base_exp*.03)*per/256;
+ if(battle_config.mobs_level_up && md->level > mob_db[md->class_].lv) { // [Valaris]
+ job_exp+=(int) (((md->level-mob_db[md->class_].lv)*mob_db[md->class_].job_exp*.03)*per/256);
+ base_exp+=(int) (((md->level-mob_db[md->class_].lv)*mob_db[md->class_].base_exp*.03)*per/256);
}
}
-
+
if((pid=tmpsd[i]->status.party_id)>0){ // パーティに入っている
- int j=0;
+ int j;
for(j=0;j<pnum;j++) // 公平パーティリストにいるかどうか
if(pt[j].id==pid)
break;
@@ -2422,26 +2595,31 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
// item drop
if(!(type&1)) {
- int log_item[8] = {0};
- for(i=0;i<8;i++){
+ int log_item[10] = {0}; //8 -> 10 Lupus
+ int drop_ore = -1,drop_items=0; //slot N for DROP LOG, number of dropped items
+ for(i=0;i<10;i++){ // 8 -> 10 Lupus
struct delay_item_drop *ditem;
int drop_rate;
- if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris]
+ if((master && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses)
+ (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) // Added [Valaris]
break; // End
- if(mob_db[md->class].dropitem[i].nameid <= 0)
+ if(mob_db[md->class_].dropitem[i].nameid <= 0)
continue;
- drop_rate = mob_db[md->class].dropitem[i].p;
- if(drop_rate <= 0 && battle_config.drop_rate0item)
+ drop_rate = mob_db[md->class_].dropitem[i].p;
+ if(drop_rate <= 0 && !battle_config.drop_rate0item)
drop_rate = 1;
if(battle_config.drops_by_luk>0 && sd && md) drop_rate+=(sd->status.luk*battle_config.drops_by_luk)/100; // drops affected by luk [Valaris]
- if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) drop_rate*=1.25; // pk_mode increase drops if 20 level difference [Valaris]
- if(drop_rate <= rand()%10000)
+ if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class_].lv - sd->status.base_level >= 20)) drop_rate = (int) (drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris]
+ if(drop_rate < rand() % 10000 + 1) { //fixed 0.01% impossible drops bug [Lupus]
+ drop_ore = i; //we remember an empty slot to put there ORE DISCOVERY drop later.
continue;
+ }
+ drop_items++; //we count if there were any drops
ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
- ditem->nameid = mob_db[md->class].dropitem[i].nameid;
+ ditem->nameid = mob_db[md->class_].dropitem[i].nameid;
log_item[i] = ditem->nameid;
ditem->amount = 1;
ditem->m = md->bl.m;
@@ -2453,18 +2631,14 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0);
}
- #ifndef TXT_ONLY
- if(log_config.drop > 0)
- log_drop(mvp_sd, md->class, log_item);
- #endif
-
// Ore Discovery [Celest]
- if (pc_checkskill(sd,BS_FINDINGORE)>0 && 1 >= rand()%1000) {
+ if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/100 >= rand()%1000) {
struct delay_item_drop *ditem;
- int itemid[17] = { 714, 756, 757, 969, 984, 985, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1002 };
ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
- ditem->nameid = itemid[rand()%17];
- log_item[i] = ditem->nameid;
+ ditem->nameid = itemdb_searchrandomid(6);
+ if (drop_ore<0) i=8; //we have only 10 slots in LOG, there's a check to not overflow (9th item usually a card, so we use 8th slot)
+ log_item[i] = ditem->nameid; //it's for logging only
+ drop_items++; //we count if there were any drops
ditem->amount = 1;
ditem->m = md->bl.m;
ditem->x = md->bl.x;
@@ -2475,20 +2649,18 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0);
}
- #ifndef TXT_ONLY
- if(log_config.drop > 0)
- log_drop(mvp_sd, md->class, log_item);
- #endif
+ //this drop log contains ALL dropped items + ORE (if there was ORE Recovery) [Lupus]
+ if(sd && log_config.drop > 0 && drop_items) //we check were there any drops.. and if not - don't write the log
+ log_drop(sd, md->class_, log_item); //mvp_sd
if(sd && sd->state.attack_type == BF_WEAPON) {
for(i=0;i<sd->monster_drop_item_count;i++) {
struct delay_item_drop *ditem;
- int race = battle_get_race(&md->bl);
if(sd->monster_drop_itemid[i] <= 0)
continue;
- if(sd->monster_drop_race[i] & (1<<race) ||
- (mob_db[md->class].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) ||
- (!(mob_db[md->class].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) {
+ if(sd->monster_drop_race[i] & (1<<race) ||
+ (mob_db[md->class_].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) ||
+ (!(mob_db[md->class_].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) {
if(sd->monster_drop_itemrate[i] <= rand()%10000)
continue;
@@ -2505,7 +2677,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
}
if(sd->get_zeny_num > 0)
- pc_getzeny(sd,mob_db[md->class].lv*10 + rand()%(sd->get_zeny_num+1));
+ pc_getzeny(sd,mob_db[md->class_].lv*10 + rand()%(sd->get_zeny_num+1));
}
if(md->lootitem) {
for(i=0;i<md->lootitem_count;i++) {
@@ -2525,11 +2697,11 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
// mvp処理
- if(mvp_sd && mob_db[md->class].mexp > 0 ){
+ if(mvp_sd && mob_db[md->class_].mexp > 0 ){
int log_mvp[2] = {0};
int j;
int mexp;
- temp = ((double)mob_db[md->class].mexp * (double)battle_config.mvp_exp_rate * (9.+(double)count)/1000.);
+ temp = ((double)mob_db[md->class_].mexp * (9.+(double)count)/10.); //[Gengar]
mexp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
if(mexp < 1) mexp = 1;
clif_mvp_effect(mvp_sd); // エフェクト
@@ -2538,19 +2710,20 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
log_mvp[1] = mexp;
for(j=0;j<3;j++){
i = rand() % 3;
- if(mob_db[md->class].mvpitem[i].nameid <= 0)
+ if(mob_db[md->class_].mvpitem[i].nameid <= 0)
continue;
- drop_rate = mob_db[md->class].mvpitem[i].p;
- if(drop_rate <= 0 && battle_config.drop_rate0item)
+ drop_rate = mob_db[md->class_].mvpitem[i].p;
+ if(drop_rate <= 0 && !battle_config.drop_rate0item)
drop_rate = 1;
- if(drop_rate < battle_config.item_drop_mvp_min)
+/* if(drop_rate < battle_config.item_drop_mvp_min)
drop_rate = battle_config.item_drop_mvp_min;
- if(drop_rate > battle_config.item_drop_mvp_max)
+ else if(drop_rate > battle_config.item_drop_mvp_max) //fixed
drop_rate = battle_config.item_drop_mvp_max;
- if(drop_rate <= rand()%10000)
+*/
+ if(drop_rate <= rand()%10000+1) //if ==0, then it doesn't drop
continue;
memset(&item,0,sizeof(item));
- item.nameid=mob_db[md->class].mvpitem[i].nameid;
+ item.nameid=mob_db[md->class_].mvpitem[i].nameid;
item.identify=!itemdb_isequip3(item.nameid);
clif_mvp_item(mvp_sd,item.nameid);
log_mvp[0] = item.nameid;
@@ -2562,10 +2735,9 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
break;
}
- #ifndef TXT_ONLY
- if(log_config.mvpdrop > 0)
- log_mvpdrop(mvp_sd, md->class, log_mvp);
- #endif
+
+ if(log_config.mvpdrop > 0)
+ log_mvpdrop(mvp_sd, md->class_, log_mvp);
}
} // [MouseJstr]
@@ -2574,7 +2746,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(md->npc_event[0] && strcmp(((md->npc_event)+strlen(md->npc_event)-13),"::OnAgitBreak") == 0) {
printf("MOB.C: Run NPC_Event[OnAgitBreak].\n");
if (agit_flag == 1) //Call to Run NPC_Event[OnAgitBreak]
- guild_agit_break(md);
+ guild_agit_break(md);
}
// SCRIPT実行
@@ -2590,7 +2762,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
struct map_session_data *tmpsd;
int i;
for(i=0;i<fd_max;i++){
- if(session[i] && (tmpsd=session[i]->session_data) && tmpsd->state.auth) {
+ if(session[i] && (tmpsd= (struct map_session_data *) session[i]->session_data) && tmpsd->state.auth) {
if(md->bl.m == tmpsd->bl.m) {
sd = tmpsd;
break;
@@ -2606,7 +2778,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
clif_clearchar_area(&md->bl,1);
if(md->level) md->level=0;
map_delblock(&md->bl);
- if(mob_get_viewclass(md->class) <= 1000)
+ if(mob_get_viewclass(md->class_) <= 1000)
clif_clearchar_delay(tick+3000,&md->bl,0);
mob_deleteslave(md);
mob_setdelayspawn(md->bl.id);
@@ -2622,26 +2794,26 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
int mob_class_change(struct mob_data *md,int *value)
{
unsigned int tick = gettick();
- int i,c,hp_rate,max_hp,class,count = 0;
+ int i,c,hp_rate,max_hp,class_,count = 0;
nullpo_retr(0, md);
nullpo_retr(0, value);
- if(value[0]<=1000 || value[0]>2000)
+ if(value[0]<=1000 || value[0]>MAX_MOB_DB)
return 0;
if(md->bl.prev == NULL) return 0;
- while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
+ while(count < 5 && value[count] > 1000 && value[count] <= MAX_MOB_DB) count++;
if(count < 1) return 0;
- class = value[rand()%count];
- if(class<=1000 || class>2000) return 0;
+ class_ = value[rand()%count];
+ if(class_<=1000 || class_>MAX_MOB_DB) return 0;
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
hp_rate = md->hp*100/max_hp;
- clif_mob_class_change(md,class);
- md->class = class;
- max_hp = battle_get_max_hp(&md->bl);
+ clif_mob_class_change(md,class_);
+ md->class_ = class_;
+ max_hp = status_get_max_hp(&md->bl);
if(battle_config.monster_class_change_full_recover==1) {
md->hp = max_hp;
memset(md->dmglog,0,sizeof(md->dmglog));
@@ -2651,14 +2823,14 @@ int mob_class_change(struct mob_data *md,int *value)
if(md->hp > max_hp) md->hp = max_hp;
else if(md->hp < 1) md->hp = 1;
- memcpy(md->name,mob_db[class].jname,24);
+ memcpy(md->name,mob_db[class_].jname,24);
memset(&md->state,0,sizeof(md->state));
md->attacked_id = 0;
md->target_id = 0;
md->move_fail_count = 0;
- md->speed = mob_db[md->class].speed;
- md->def_ele = mob_db[md->class].element;
+ md->speed = mob_db[md->class_].speed;
+ md->def_ele = mob_db[md->class_].element;
mob_changestate(md,MS_IDLE,0);
skill_castcancel(&md->bl,0);
@@ -2667,14 +2839,13 @@ int mob_class_change(struct mob_data *md,int *value)
md->next_walktime = tick+rand()%50+5000;
md->attackabletime = tick;
md->canmove_tick = tick;
- md->sg_count=0;
for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++)
md->skilldelay[i] = c;
md->skillid=0;
md->skilllv=0;
- if(md->lootitem == NULL && mob_db[class].mode&0x02)
+ if(md->lootitem == NULL && mob_db[class_].mode&0x02)
md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
skill_clear_unitgroup(&md->bl);
@@ -2692,15 +2863,16 @@ int mob_class_change(struct mob_data *md,int *value)
*/
int mob_heal(struct mob_data *md,int heal)
{
- int max_hp = battle_get_max_hp(&md->bl);
+ int max_hp;
nullpo_retr(0, md);
+ max_hp = status_get_max_hp(&md->bl);
md->hp += heal;
if( max_hp < md->hp )
md->hp = max_hp;
- if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris]
+ if(md->class_ >= 1285 && md->class_ <=1287) { // guardian hp update [Valaris]
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc) {
if(md->bl.id==gc->GID0) gc->Ghp0=md->hp;
@@ -2714,6 +2886,9 @@ int mob_heal(struct mob_data *md,int heal)
}
} // end addition [Valaris]
+ if (battle_config.show_mob_hp)
+ clif_update_mobhp(md);
+
return 0;
}
@@ -2755,7 +2930,8 @@ int mob_warpslave(struct mob_data *md,int x, int y)
*/
int mob_warp(struct mob_data *md,int m,int x,int y,int type)
{
- int i=0,c,xs=0,ys=0,bx=x,by=y;
+ int i=0,xs=0,ys=0,bx=x,by=y;
+ int tick = gettick();
nullpo_retr(0, md);
@@ -2769,14 +2945,14 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
return 0;
clif_clearchar_area(&md->bl,type);
}
- skill_unit_out_all(&md->bl,gettick(),1);
+ skill_unit_move(&md->bl,tick,0);
map_delblock(&md->bl);
if(bx>0 && by>0){ // 位置指定の場合周囲9セルを探索
xs=ys=9;
}
- while( ( x<0 || y<0 || ((c=read_gat(m,x,y))==1 || c==5) ) && (i++)<1000 ){
+ while( ( x<0 || y<0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<1000 ){
if( xs>0 && ys>0 && i<250 ){ // 指定位置付近の探索
x=bx+rand()%xs-xs/2;
y=by+rand()%ys-ys/2;
@@ -2793,7 +2969,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
}else {
m=md->bl.m;
if(battle_config.error_log==1)
- printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class);
+ printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class_);
}
md->target_id=0; // タゲを解除する
@@ -2804,10 +2980,11 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
if(type>0 && i==1000) {
if(battle_config.battle_log)
- printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class);
+ printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class_);
}
map_addblock(&md->bl);
+ skill_unit_move(&md->bl,tick,1);
if(type>0)
{
clif_spawnmob(md);
@@ -2833,7 +3010,6 @@ int mob_countslave_sub(struct block_list *bl,va_list ap)
nullpo_retr(0, c=va_arg(ap,int *));
nullpo_retr(0, md = (struct mob_data *)bl);
-
if( md->master_id==id )
(*c)++;
return 0;
@@ -2860,7 +3036,7 @@ int mob_countslave(struct mob_data *md)
int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
{
struct mob_data *md;
- int bx,by,m,count = 0,class,k,a = amount;
+ int bx,by,m,count = 0,class_,k,a = amount;
nullpo_retr(0, md2);
nullpo_retr(0, value);
@@ -2869,24 +3045,24 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
by=md2->bl.y;
m=md2->bl.m;
- if(value[0]<=1000 || value[0]>2000) // 値が異常なら召喚を止める
+ if(value[0]<=1000 || value[0]>MAX_MOB_DB) // 値が異常なら召喚を止める
return 0;
- while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
+ while(count < 21 && value[count] > 1000 && value[count] <= 2000) count++;
if(count < 1) return 0;
for(k=0;k<count;k++) {
amount = a;
- class = value[k];
- if(class<=1000 || class>2000) continue;
+ class_ = value[k];
+ if(class_<=1000 || class_>MAX_MOB_DB) continue;
for(;amount>0;amount--){
- int x=0,y=0,c=0,i=0;
+ int x=0,y=0,i=0;
md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
- if(mob_db[class].mode&0x02)
+ if(mob_db[class_].mode&0x02)
md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
else
md->lootitem=NULL;
- while((x<=0 || y<=0 || (c=map_getcell(m,x,y))==1 || c==5 ) && (i++)<100){
+ while((x<=0 || y<=0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<100){
x=rand()%9-4+bx;
y=rand()%9-4+by;
}
@@ -2895,7 +3071,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
y=by;
}
- mob_spawn_dataset(md,"--ja--",class);
+ mob_spawn_dataset(md,"--ja--",class_);
md->bl.m=m;
md->bl.x=x;
md->bl.y=y;
@@ -2976,15 +3152,15 @@ int mob_counttargeted(struct mob_data *md,struct block_list *src,int target_lv)
*MOBskillから該当skillidのskillidxを返す
*------------------------------------------
*/
-int mob_skillid2skillidx(int class,int skillid)
+int mob_skillid2skillidx(int class_,int skillid)
{
int i;
- struct mob_skill *ms=mob_db[class].skill;
-
+ struct mob_skill *ms=mob_db[class_].skill;
+
if(ms==NULL)
return -1;
- for(i=0;i<mob_db[class].maxskill;i++){
+ for(i=0;i<mob_db[class_].maxskill;i++){
if(ms[i].skill_id == skillid)
return i;
}
@@ -3023,7 +3199,9 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
md->skilltimer=-1;
//沈黙や状態異常など
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3033,7 +3211,7 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
return 0;
}
if(md->skillid != NPC_EMOTION)
- md->last_thinktime=tick + battle_get_adelay(&md->bl);
+ md->last_thinktime=tick + status_get_adelay(&md->bl);
if((bl = map_id2bl(md->skilltarget)) == NULL || bl->prev==NULL){ //スキルターゲットが存在しない
//printf("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了
@@ -3043,12 +3221,12 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
return 0;
if(md->skillid == PR_LEXAETERNA) {
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)))
return 0;
}
else if(md->skillid == RG_BACKSTAP) {
- int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
+ int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = status_get_dir(bl);
int dist = distance(md->bl.x,md->bl.y,bl->x,bl->y);
if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir)))
return 0;
@@ -3058,14 +3236,14 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
return 0;
range = skill_get_range(md->skillid,md->skilllv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,bl->x,bl->y))
return 0;
md->skilldelay[md->skillidx]=tick;
if(battle_config.mob_skill_log)
- printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class);
+ printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_);
// mob_stop_walking(md,0);
switch( skill_get_nk(md->skillid) )
@@ -3075,8 +3253,8 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
break;
case 1:// 支援系
- if(!mob_db[md->class].skill[md->skillidx].val[0] &&
- (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) )
+ if(!mob_db[md->class_].skill[md->skillidx].val[0] &&
+ (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) )
skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
else
skill_castend_nodamage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
@@ -3094,15 +3272,10 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
{
struct mob_data* md=NULL;
- struct block_list *bl;
int range,maxcount;
- //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外
- if((bl=map_id2bl(id))==NULL)
- return 0;
+ nullpo_retr(0, md=(struct mob_data *)map_id2bl(id));
- nullpo_retr(0, md=(struct mob_data *)bl);
-
if( md->bl.type!=BL_MOB || md->bl.prev==NULL )
return 0;
@@ -3111,7 +3284,9 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
md->skilltimer=-1;
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3121,59 +3296,16 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
return 0;
}
- if(battle_config.monster_skill_reiteration == 0) {
- range = -1;
- switch(md->skillid) {
- case MG_SAFETYWALL:
- case WZ_FIREPILLAR:
- case HT_SKIDTRAP:
- case HT_LANDMINE:
- case HT_ANKLESNARE:
- case HT_SHOCKWAVE:
- case HT_SANDMAN:
- case HT_FLASHER:
- case HT_FREEZINGTRAP:
- case HT_BLASTMINE:
- case HT_CLAYMORETRAP:
- case PF_SPIDERWEB: /* スパイダーウェッブ */
- range = 0;
- break;
- case AL_PNEUMA:
- case AL_WARP:
- range = 1;
- break;
- }
- if(range >= 0) {
- if(skill_check_unit_range(md->bl.m,md->skillx,md->skilly,range,md->skillid) > 0)
- return 0;
- }
- }
- if(battle_config.monster_skill_nofootset) {
- range = -1;
- switch(md->skillid) {
- case WZ_FIREPILLAR:
- case HT_SKIDTRAP:
- case HT_LANDMINE:
- case HT_ANKLESNARE:
- case HT_SHOCKWAVE:
- case HT_SANDMAN:
- case HT_FLASHER:
- case HT_FREEZINGTRAP:
- case HT_BLASTMINE:
- case HT_CLAYMORETRAP:
- case AM_DEMONSTRATION:
- case PF_SPIDERWEB: /* スパイダーウェッブ */
- range = 1;
- break;
- case AL_WARP:
- range = 0;
- break;
- }
- if(range >= 0) {
- if(skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,range) > 0)
- return 0;
- }
- }
+ if (!battle_config.monster_skill_reiteration &&
+ skill_get_unit_flag (md->skillid) & UF_NOREITERATION &&
+ skill_check_unit_range (md->bl.m, md->skillx, md->skilly, md->skillid, md->skilllv))
+ return 0;
+
+ if(battle_config.monster_skill_nofootset &&
+ skill_get_unit_flag (md->skillid) & UF_NOFOOTSET &&
+ skill_check_unit_range2(&md->bl, md->bl.m, md->skillx, md->skilly, md->skillid, md->skilllv))
+ return 0;
+
if(battle_config.monster_land_skill_limit) {
maxcount = skill_get_maxcount(md->skillid);
@@ -3190,13 +3322,13 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
range = skill_get_range(md->skillid,md->skilllv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,md->skillx,md->skilly))
return 0;
md->skilldelay[md->skillidx]=tick;
if(battle_config.mob_skill_log)
- printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class);
+ printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_);
// mob_stop_walking(md,0);
skill_castend_pos2(&md->bl,md->skillx,md->skilly,md->skillid,md->skilllv,tick,0);
@@ -3216,8 +3348,8 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
int skill_id, skill_lv, forcecast = 0;
nullpo_retr(0, md);
- nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]);
-
+ nullpo_retr(0, ms=&mob_db[md->class_].skill[skill_idx]);
+
if( target==NULL && (target=map_id2bl(md->target_id))==NULL )
return 0;
@@ -3229,7 +3361,9 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
// 沈黙や異常
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3244,17 +3378,15 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
if(md->option&2 && skill_id!=TF_HIDING && skill_id!=AS_GRIMTOOTH && skill_id!=RG_BACKSTAP && skill_id!=RG_RAID)
return 0;
- if(map[md->bl.m].flag.gvg && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT || skill_id == AL_WARP ||
- skill_id == WZ_ICEWALL || skill_id == TF_BACKSLIDING))
+ if(map[md->bl.m].flag.gvg && skill_db[skill_id].nocast & 4)
return 0;
-
if(skill_get_inf2(skill_id)&0x200 && md->bl.id == target->id)
return 0;
// 射程と障害物チェック
range = skill_get_range(skill_id,skill_lv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(!battle_check_range(&md->bl,target,range))
return 0;
@@ -3266,7 +3398,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
switch(skill_id){ /* 何か特殊な処理が必要 */
case ALL_RESURRECTION: /* リザレクション */
- if(target->type != BL_PC && battle_check_undead(battle_get_race(target),battle_get_elem_type(target))){ /* 敵がアンデッドなら */
+ if(target->type != BL_PC && battle_check_undead(status_get_race(target),status_get_elem_type(target))){ /* 敵がアンデッドなら */
forcecast=1; /* ターンアンデットと同じ詠唱時間 */
casttime=skill_castfix(&md->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) );
}
@@ -3276,10 +3408,15 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
case SA_SPELLBREAKER:
forcecast=1;
break;
+ case NPC_SUMMONSLAVE:
+ case NPC_SUMMONMONSTER:
+ if(md->master_id!=0)
+ return 0;
+ break;
}
if(battle_config.mob_skill_log)
- printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class);
+ printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class_);
if(casttime>0 || forcecast){ // 詠唱が必要
// struct mob_data *md2;
@@ -3288,8 +3425,9 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
md->bl.id, target->id, 0,0, skill_id,casttime);
// 詠唱反応モンスター
-/* if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->class].mode&0x10 &&
- md2->state.state!=MS_ATTACK){
+ // future homunculus support?
+/* if(md->master_id && target->type==BL_MOB && (md2=(struct mob_data *)target) &&
+ mob_db[md2->class_].mode&0x10 && md2->state.state!=MS_ATTACK){
md2->target_id=md->bl.id;
md->state.targettype = ATTACKABLE;
md2->min_chase=13;
@@ -3307,7 +3445,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
md->skillidx = skill_idx;
if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
- skill_status_change_end(&md->bl,SC_CLOAKING,-1);
+ status_change_end(&md->bl,SC_CLOAKING,-1);
if( casttime>0 ){
md->skilltimer =
@@ -3332,7 +3470,7 @@ int mobskill_use_pos( struct mob_data *md,
int skill_id, skill_lv;
nullpo_retr(0, md);
- nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]);
+ nullpo_retr(0, ms=&mob_db[md->class_].skill[skill_idx]);
if( md->bl.prev==NULL )
return 0;
@@ -3342,7 +3480,9 @@ int mobskill_use_pos( struct mob_data *md,
//沈黙や状態異常など
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3366,7 +3506,7 @@ int mobskill_use_pos( struct mob_data *md,
bl.y = skill_y;
range = skill_get_range(skill_id,skill_lv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(!battle_check_range(&md->bl,&bl,range))
return 0;
@@ -3377,7 +3517,7 @@ int mobskill_use_pos( struct mob_data *md,
if(battle_config.mob_skill_log)
printf("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, class = %d\n",
- skill_x,skill_y,skill_id,skill_lv,casttime,md->class);
+ skill_x,skill_y,skill_id,skill_lv,casttime,md->class_);
if( casttime>0 ) { // A cast time is required.
mob_stop_walking(md,0); // 歩行停止
@@ -3396,7 +3536,7 @@ int mobskill_use_pos( struct mob_data *md,
md->skilllv = skill_lv;
md->skillidx = skill_idx;
if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
- skill_status_change_end(&md->bl,SC_CLOAKING,-1);
+ status_change_end(&md->bl,SC_CLOAKING,-1);
if( casttime>0 ){
md->skilltimer =
add_timer( gettick()+casttime, mobskill_castend_pos, md->bl.id, 0 );
@@ -3428,7 +3568,7 @@ int mob_getfriendhpltmaxrate_sub(struct block_list *bl,va_list ap)
return 0;
rate=va_arg(ap,int);
fr=va_arg(ap,struct mob_data **);
- if( md->hp < mob_db[md->class].max_hp*rate/100 )
+ if( md->hp < mob_db[md->class_].max_hp*rate/100 )
(*fr)=md;
return 0;
}
@@ -3500,9 +3640,9 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event)
int i,max_hp;
nullpo_retr(0, md);
- nullpo_retr(0, ms = mob_db[md->class].skill);
+ nullpo_retr(0, ms = mob_db[md->class_].skill);
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
if(battle_config.mob_skill_use == 0 || md->skilltimer != -1)
return 0;
@@ -3513,7 +3653,7 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event)
if(md->sc_data[SC_SELFDESTRUCTION].timer!=-1) //自爆中はスキルを使わない
return 0;
- for(i=0;i<mob_db[md->class].maxskill;i++){
+ for(i=0;i<mob_db[md->class_].maxskill;i++){
int c2=ms[i].cond2,flag=0;
struct mob_data *fmd=NULL;
@@ -3579,24 +3719,24 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event)
continue;
// 自分の周囲
if( ms[i].target>=MST_AROUND1 ){
- int bx=x, by=y, i=0, c, m=bl->m, r=ms[i].target-MST_AROUND1;
+ int bx=x, by=y, i=0, m=bl->m, r=ms[i].target-MST_AROUND1;
do{
bx=x + rand()%(r*2+3) - r;
by=y + rand()%(r*2+3) - r;
}while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys ||
- ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000);
+ map_getcell(m,bx,by,CELL_CHKNOPASS)) && (i++)<1000);
if(i<1000){
x=bx; y=by;
}
}
// 相手の周囲
if( ms[i].target>=MST_AROUND5 ){
- int bx=x, by=y, i=0, c, m=bl->m, r=(ms[i].target-MST_AROUND5)+1;
+ int bx=x, by=y, i=0,m=bl->m, r=(ms[i].target-MST_AROUND5)+1;
do{
bx=x + rand()%(r*2+1) - r;
by=y + rand()%(r*2+1) - r;
}while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys ||
- ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000);
+ map_getcell(m,bx,by,CELL_CHKNOPASS)) && (i++)<1000);
if(i<1000){
x=bx; y=by;
}
@@ -3645,27 +3785,30 @@ int mobskill_event(struct mob_data *md,int flag)
int mob_gvmobcheck(struct map_session_data *sd, struct block_list *bl)
{
struct mob_data *md=NULL;
-
+
nullpo_retr(0,sd);
nullpo_retr(0,bl);
-
+
if(bl->type==BL_MOB && (md=(struct mob_data *)bl) &&
- (md->class == 1288 || md->class == 1287 || md->class == 1286 || md->class == 1285))
+ (md->class_ == 1288 || md->class_ == 1287 || md->class_ == 1286 || md->class_ == 1285))
{
struct guild_castle *gc=guild_mapname2gc(map[sd->bl.m].name);
struct guild *g=guild_search(sd->status.guild_id);
- if(g == NULL && md->class == 1288)
+ if(g == NULL && md->class_ == 1288)
return 0;//ギルド未加入ならダメージ無し
else if(gc != NULL && !map[sd->bl.m].flag.gvg)
return 0;//砦内でGvじゃないときはダメージなし
- else if(g && gc != NULL && g->guild_id == gc->guild_id)
- return 0;//自占領ギルドのエンペならダメージ無し
- else if(g && guild_checkskill(g,GD_APPROVAL) <= 0 && md->class == 1288)
- return 0;//正規ギルド承認がないとダメージ無し
-
+ else if(g) {
+ if (gc != NULL && g->guild_id == gc->guild_id)
+ return 0;//自占領ギルドのエンペならダメージ無し
+ else if(guild_checkskill(g,GD_APPROVAL) <= 0 && md->class_ == 1288)
+ return 0;//正規ギルド承認がないとダメージ無し
+ else if (gc && guild_check_alliance(gc->guild_id, g->guild_id, 0) == 1)
+ return 0; // 同盟ならダメージ無し
+ }
}
-
+
return 1;
}
/*==========================================
@@ -3692,53 +3835,53 @@ int mobskill_deltimer(struct mob_data *md )
* Since un-setting [ mob ] up was used, it is an initial provisional value setup.
*------------------------------------------
*/
-static int mob_makedummymobdb(int class)
+static int mob_makedummymobdb(int class_)
{
int i;
- sprintf(mob_db[class].name,"mob%d",class);
- sprintf(mob_db[class].jname,"mob%d",class);
- mob_db[class].lv=1;
- mob_db[class].max_hp=1000;
- mob_db[class].max_sp=1;
- mob_db[class].base_exp=2;
- mob_db[class].job_exp=1;
- mob_db[class].range=1;
- mob_db[class].atk1=7;
- mob_db[class].atk2=10;
- mob_db[class].def=0;
- mob_db[class].mdef=0;
- mob_db[class].str=1;
- mob_db[class].agi=1;
- mob_db[class].vit=1;
- mob_db[class].int_=1;
- mob_db[class].dex=6;
- mob_db[class].luk=2;
- mob_db[class].range2=10;
- mob_db[class].range3=10;
- mob_db[class].size=0;
- mob_db[class].race=0;
- mob_db[class].element=0;
- mob_db[class].mode=0;
- mob_db[class].speed=300;
- mob_db[class].adelay=1000;
- mob_db[class].amotion=500;
- mob_db[class].dmotion=500;
- mob_db[class].dropitem[0].nameid=909; // Jellopy
- mob_db[class].dropitem[0].p=1000;
- for(i=1;i<8;i++){
- mob_db[class].dropitem[i].nameid=0;
- mob_db[class].dropitem[i].p=0;
+ sprintf(mob_db[class_].name,"mob%d",class_);
+ sprintf(mob_db[class_].jname,"mob%d",class_);
+ mob_db[class_].lv=1;
+ mob_db[class_].max_hp=1000;
+ mob_db[class_].max_sp=1;
+ mob_db[class_].base_exp=2;
+ mob_db[class_].job_exp=1;
+ mob_db[class_].range=1;
+ mob_db[class_].atk1=7;
+ mob_db[class_].atk2=10;
+ mob_db[class_].def=0;
+ mob_db[class_].mdef=0;
+ mob_db[class_].str=1;
+ mob_db[class_].agi=1;
+ mob_db[class_].vit=1;
+ mob_db[class_].int_=1;
+ mob_db[class_].dex=6;
+ mob_db[class_].luk=2;
+ mob_db[class_].range2=10;
+ mob_db[class_].range3=10;
+ mob_db[class_].size=0;
+ mob_db[class_].race=0;
+ mob_db[class_].element=0;
+ mob_db[class_].mode=0;
+ mob_db[class_].speed=300;
+ mob_db[class_].adelay=1000;
+ mob_db[class_].amotion=500;
+ mob_db[class_].dmotion=500;
+ //mob_db[class_].dropitem[0].nameid=909; // Jellopy
+ //mob_db[class_].dropitem[0].p=1000;
+ for(i=1;i<10;i++){ // 8-> 10 Lupus
+ mob_db[class_].dropitem[i].nameid=0;
+ mob_db[class_].dropitem[i].p=0;
}
// Item1,Item2
- mob_db[class].mexp=0;
- mob_db[class].mexpper=0;
+ mob_db[class_].mexp=0;
+ mob_db[class_].mexpper=0;
for(i=0;i<3;i++){
- mob_db[class].mvpitem[i].nameid=0;
- mob_db[class].mvpitem[i].p=0;
+ mob_db[class_].mvpitem[i].nameid=0;
+ mob_db[class_].mvpitem[i].p=0;
}
for(i=0;i<MAX_RANDOMMONSTER;i++)
- mob_db[class].summonper[i]=0;
+ mob_db[class_].summonper[i]=0;
return 0;
}
@@ -3764,13 +3907,13 @@ static int mob_readdb(void)
return -1;
}
while(fgets(line,1020,fp)){
- int class,i;
- char *str[55],*p,*np;
+ int class_,i;
+ char *str[60],*p,*np; // 55->60 Lupus
if(line[0] == '/' && line[1] == '/')
continue;
- for(i=0,p=line;i<55;i++){
+ for(i=0,p=line;i<60;i++){
if((np=strchr(p,','))!=NULL){
str[i]=p;
*np=0;
@@ -3779,113 +3922,122 @@ static int mob_readdb(void)
str[i]=p;
}
- class=atoi(str[0]);
- if(class<=1000 || class>2000)
+ class_=atoi(str[0]);
+ if(class_<=1000 || class_>MAX_MOB_DB)
continue;
- mob_db[class].view_class=class;
- memcpy(mob_db[class].name,str[1],24);
- memcpy(mob_db[class].jname,str[2],24);
- mob_db[class].lv=atoi(str[3]);
- mob_db[class].max_hp=atoi(str[4]);
- mob_db[class].max_sp=atoi(str[5]);
-
- mob_db[class].base_exp=atoi(str[6]);
- if(mob_db[class].base_exp < 0)
- mob_db[class].base_exp = 0;
- else if(mob_db[class].base_exp > 0 && (mob_db[class].base_exp*battle_config.base_exp_rate/100 > 1000000000 ||
- mob_db[class].base_exp*battle_config.base_exp_rate/100 < 0))
- mob_db[class].base_exp=1000000000;
- else
- mob_db[class].base_exp*= battle_config.base_exp_rate/100;
-
- mob_db[class].job_exp=atoi(str[7]);
- if(mob_db[class].job_exp < 0)
- mob_db[class].job_exp = 0;
- else if(mob_db[class].job_exp > 0 && (mob_db[class].job_exp*battle_config.job_exp_rate/100 > 1000000000 ||
- mob_db[class].job_exp*battle_config.job_exp_rate/100 < 0))
- mob_db[class].job_exp=1000000000;
- else
- mob_db[class].job_exp*=battle_config.job_exp_rate/100;
-
- mob_db[class].range=atoi(str[8]);
- mob_db[class].atk1=atoi(str[9]);
- mob_db[class].atk2=atoi(str[10]);
- mob_db[class].def=atoi(str[11]);
- mob_db[class].mdef=atoi(str[12]);
- mob_db[class].str=atoi(str[13]);
- mob_db[class].agi=atoi(str[14]);
- mob_db[class].vit=atoi(str[15]);
- mob_db[class].int_=atoi(str[16]);
- mob_db[class].dex=atoi(str[17]);
- mob_db[class].luk=atoi(str[18]);
- mob_db[class].range2=atoi(str[19]);
- mob_db[class].range3=atoi(str[20]);
- mob_db[class].size=atoi(str[21]);
- mob_db[class].race=atoi(str[22]);
- mob_db[class].element=atoi(str[23]);
- mob_db[class].mode=atoi(str[24]);
- mob_db[class].speed=atoi(str[25]);
- mob_db[class].adelay=atoi(str[26]);
- mob_db[class].amotion=atoi(str[27]);
- mob_db[class].dmotion=atoi(str[28]);
-
- for(i=0;i<8;i++){
+ mob_db[class_].view_class=class_;
+ memcpy(mob_db[class_].name,str[1],24);
+ memcpy(mob_db[class_].jname,str[2],24);
+ mob_db[class_].lv=atoi(str[3]);
+ mob_db[class_].max_hp=atoi(str[4]);
+ mob_db[class_].max_sp=atoi(str[5]);
+
+ mob_db[class_].base_exp = atoi(str[6]);
+ if (mob_db[class_].base_exp <= 0)
+ mob_db[class_].base_exp = 0;
+ else if (mob_db[class_].base_exp * battle_config.base_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].base_exp * battle_config.base_exp_rate / 100 < 0)
+ mob_db[class_].base_exp = 1000000000;
+ else {
+ mob_db[class_].base_exp = mob_db[class_].base_exp * battle_config.base_exp_rate / 100;
+ if (mob_db[class_].base_exp < 1)
+ mob_db[class_].base_exp = 1;
+ }
+
+ mob_db[class_].job_exp = atoi(str[7]);
+ if (mob_db[class_].job_exp <= 0)
+ mob_db[class_].job_exp = 0;
+ else if (mob_db[class_].job_exp * battle_config.job_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].job_exp * battle_config.job_exp_rate / 100 < 0)
+ mob_db[class_].job_exp = 1000000000;
+ else {
+ mob_db[class_].job_exp = mob_db[class_].job_exp * battle_config.job_exp_rate / 100;
+ if (mob_db[class_].job_exp < 1)
+ mob_db[class_].job_exp = 1;
+ }
+
+ mob_db[class_].range=atoi(str[8]);
+ mob_db[class_].atk1=atoi(str[9]);
+ mob_db[class_].atk2=atoi(str[10]);
+ mob_db[class_].def=atoi(str[11]);
+ mob_db[class_].mdef=atoi(str[12]);
+ mob_db[class_].str=atoi(str[13]);
+ mob_db[class_].agi=atoi(str[14]);
+ mob_db[class_].vit=atoi(str[15]);
+ mob_db[class_].int_=atoi(str[16]);
+ mob_db[class_].dex=atoi(str[17]);
+ mob_db[class_].luk=atoi(str[18]);
+ mob_db[class_].range2=atoi(str[19]);
+ mob_db[class_].range3=atoi(str[20]);
+ mob_db[class_].size=atoi(str[21]);
+ mob_db[class_].race=atoi(str[22]);
+ mob_db[class_].element=atoi(str[23]);
+ mob_db[class_].mode=atoi(str[24]);
+ mob_db[class_].speed=atoi(str[25]);
+ mob_db[class_].adelay=atoi(str[26]);
+ mob_db[class_].amotion=atoi(str[27]);
+ mob_db[class_].dmotion=atoi(str[28]);
+
+ for(i=0;i<10;i++){ // 8 -> 10 Lupus
int rate = 0,type,ratemin,ratemax;
- mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]);
- type = itemdb_type(mob_db[class].dropitem[i].nameid);
- if (type == 0) { // Added [Valaris]
- rate = battle_config.item_rate_heal;
+ mob_db[class_].dropitem[i].nameid=atoi(str[29+i*2]);
+ type = itemdb_type(mob_db[class_].dropitem[i].nameid);
+ if (type == 0) {
+ rate = battle_config.item_rate_heal * atoi(str[30+i*2]) / 100; //fix by Yor
ratemin = battle_config.item_drop_heal_min;
ratemax = battle_config.item_drop_heal_max;
}
else if (type == 2) {
- rate = battle_config.item_rate_use;
+ rate = battle_config.item_rate_use * atoi(str[30+i*2]) / 100; //fix by Yor
ratemin = battle_config.item_drop_use_min;
ratemax = battle_config.item_drop_use_max; // End
}
else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip
- rate = battle_config.item_rate_equip;
+ rate = battle_config.item_rate_equip * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_equip_min;
ratemax = battle_config.item_drop_equip_max;
}
else if (type == 6) {
- rate = battle_config.item_rate_card;
+ rate = battle_config.item_rate_card * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_card_min;
ratemax = battle_config.item_drop_card_max;
}
else {
- rate = battle_config.item_rate_common;
+ rate = battle_config.item_rate_common * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_common_min;
ratemax = battle_config.item_drop_common_max;
}
- rate = (rate / 100) * atoi(str[30+i*2]);
- rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
- mob_db[class].dropitem[i].p = rate;
+ mob_db[class_].dropitem[i].p = (rate < ratemin) ? ratemin : (rate > ratemax) ? ratemax: rate;
}
- // Item1,Item2
- mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100;
- mob_db[class].mexpper=atoi(str[46]);
+ // MVP EXP Bonus, Chance: MEXP,ExpPer
+ mob_db[class_].mexp=atoi(str[49])*battle_config.mvp_exp_rate/100;
+ mob_db[class_].mexpper=atoi(str[50]);
+ // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
for(i=0;i<3;i++){
- mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]);
- mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100;
+ int rate=atoi(str[52+i*2])*battle_config.mvp_item_rate/100; //idea of the fix from Freya
+ mob_db[class_].mvpitem[i].nameid=atoi(str[51+i*2]);
+ mob_db[class_].mvpitem[i].p= (rate < battle_config.item_drop_mvp_min)
+ ? battle_config.item_drop_mvp_min : (rate > battle_config.item_drop_mvp_max)
+ ? battle_config.item_drop_mvp_max : rate;
}
for(i=0;i<MAX_RANDOMMONSTER;i++)
- mob_db[class].summonper[i]=0;
- mob_db[class].maxskill=0;
-
- mob_db[class].sex=0;
- mob_db[class].hair=0;
- mob_db[class].hair_color=0;
- mob_db[class].weapon=0;
- mob_db[class].shield=0;
- mob_db[class].head_top=0;
- mob_db[class].head_mid=0;
- mob_db[class].head_buttom=0;
- mob_db[class].clothes_color=0; //Add for player monster dye - Valaris
+ mob_db[class_].summonper[i]=0;
+ mob_db[class_].maxskill=0;
+
+ mob_db[class_].sex=0;
+ mob_db[class_].hair=0;
+ mob_db[class_].hair_color=0;
+ mob_db[class_].weapon=0;
+ mob_db[class_].shield=0;
+ mob_db[class_].head_top=0;
+ mob_db[class_].head_mid=0;
+ mob_db[class_].head_buttom=0;
+ mob_db[class_].clothes_color=0; //Add for player monster dye - Valaris
}
fclose(fp);
- printf("read %s done\n",filename[i]);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[i]);
+ ShowStatus(tmp_output);
}
return 0;
}
@@ -3899,7 +4051,7 @@ static int mob_readdb_mobavail(void)
FILE *fp;
char line[1024];
int ln=0;
- int class,j,k;
+ int class_,j,k;
char *str[20],*p,*np;
if( (fp=fopen("db/mob_avail.txt","r"))==NULL ){
@@ -3918,39 +4070,42 @@ static int mob_readdb_mobavail(void)
*np=0;
p=np+1;
} else
- str[j]=p;
- }
+ str[j]=p;
+ }
if(str[0]==NULL)
continue;
- class=atoi(str[0]);
-
- if(class<=1000 || class>2000) // 値が異常なら処理しない。
+ class_=atoi(str[0]);
+ if(class_<=1000 || class_>MAX_MOB_DB) // 値が異常なら処理しない。
continue;
+
k=atoi(str[1]);
- if(k >= 0)
- mob_db[class].view_class=k;
-
- if((mob_db[class].view_class < 24) || (mob_db[class].view_class > 4000)) {
- mob_db[class].sex=atoi(str[2]);
- mob_db[class].hair=atoi(str[3]);
- mob_db[class].hair_color=atoi(str[4]);
- mob_db[class].weapon=atoi(str[5]);
- mob_db[class].shield=atoi(str[6]);
- mob_db[class].head_top=atoi(str[7]);
- mob_db[class].head_mid=atoi(str[8]);
- mob_db[class].head_buttom=atoi(str[9]);
- mob_db[class].option=atoi(str[10])&~0x46;
- mob_db[class].clothes_color=atoi(str[11]); // Monster player dye option - Valaris
+ if(k < 0)
+ continue;
+ if (j > 3 && k > 23 && k < 69)
+ k += 3977; // advanced job/baby class
+ mob_db[class_].view_class=k;
+
+ if((k < 24) || (k > 4000)) {
+ mob_db[class_].sex=atoi(str[2]);
+ mob_db[class_].hair=atoi(str[3]);
+ mob_db[class_].hair_color=atoi(str[4]);
+ mob_db[class_].weapon=atoi(str[5]);
+ mob_db[class_].shield=atoi(str[6]);
+ mob_db[class_].head_top=atoi(str[7]);
+ mob_db[class_].head_mid=atoi(str[8]);
+ mob_db[class_].head_buttom=atoi(str[9]);
+ mob_db[class_].option=atoi(str[10])&~0x46;
+ mob_db[class_].clothes_color=atoi(str[11]); // Monster player dye option - Valaris
}
-
- else if(atoi(str[2]) > 0) mob_db[class].equip=atoi(str[2]); // mob equipment [Valaris]
+ else if(atoi(str[2]) > 0) mob_db[class_].equip=atoi(str[2]); // mob equipment [Valaris]
ln++;
}
fclose(fp);
- printf("read db/mob_avail.txt done (count=%d)\n",ln);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/mob_avail.txt");
+ ShowStatus(tmp_output);
return 0;
}
@@ -3978,7 +4133,7 @@ static int mob_read_randommonster(void)
return -1;
}
while(fgets(line,1020,fp)){
- int class,per;
+ int class_,per;
if(line[0] == '/' && line[1] == '/')
continue;
memset(str,0,sizeof(str));
@@ -3991,13 +4146,14 @@ static int mob_read_randommonster(void)
if(str[0]==NULL || str[2]==NULL)
continue;
- class = atoi(str[0]);
+ class_ = atoi(str[0]);
per=atoi(str[2]);
- if((class>1000 && class<=2000) || class==0)
- mob_db[class].summonper[i]=per;
+ if((class_>1000 && class_<=MAX_MOB_DB) || class_==0)
+ mob_db[class_].summonper[i]=per;
}
fclose(fp);
- printf("read %s done\n",mobfile[i]);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]);
+ ShowStatus(tmp_output);
}
return 0;
}
@@ -4116,7 +4272,10 @@ static int mob_readskilldb(void)
ms->state=state[j].id;
}
ms->skill_id=atoi(sp[3]);
- ms->skill_lv=atoi(sp[4]);
+ j=atoi(sp[4]);
+ if (j<=0 || j>MAX_SKILL_DB)
+ continue;
+ ms->skill_lv=j;
ms->permillage=atoi(sp[5]);
ms->casttime=atoi(sp[6]);
ms->delay=atoi(sp[7]);
@@ -4149,21 +4308,61 @@ static int mob_readskilldb(void)
mob_db[mob_id].maxskill=i+1;
}
fclose(fp);
- printf("read %s done\n",filename[x]);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[x]);
+ ShowStatus(tmp_output);
}
return 0;
}
-
-void mob_reload(void)
+/*==========================================
+ * db/mob_race_db.txt reading
+ *------------------------------------------
+ */
+static int mob_readdb_race(void)
{
- /*
+ FILE *fp;
+ char line[1024];
+ int race,j,k;
+ char *str[20],*p,*np;
- <empty monster database>
- mob_read();
+ if( (fp=fopen("db/mob_race2_db.txt","r"))==NULL ){
+ printf("can't read db/mob_race2_db.txt\n");
+ return -1;
+ }
+
+ while(fgets(line,1020,fp)){
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ memset(str,0,sizeof(str));
- */
+ for(j=0,p=line;j<12;j++){
+ if((np=strchr(p,','))!=NULL){
+ str[j]=p;
+ *np=0;
+ p=np+1;
+ } else
+ str[j]=p;
+ }
+ if(str[0]==NULL)
+ continue;
+
+ race=atoi(str[0]);
+ if (race < 0 || race >= MAX_MOB_RACE_DB)
+ continue;
- do_init_mob();
+ for (j=1; j<20; j++) {
+ if (!str[j])
+ break;
+ k=atoi(str[j]);
+ if (k < 1000 || k > MAX_MOB_DB)
+ continue;
+ mob_db[k].race2 = race;
+ //mob_race_db[race][j] = k;
+ }
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/mob_race2_db.txt");
+ ShowStatus(tmp_output);
+ return 0;
}
#ifndef TXT_ONLY
@@ -4174,11 +4373,12 @@ void mob_reload(void)
static int mob_read_sqldb(void)
{
char line[1024];
- int i,class,ln=0;
- char *str[55],*p,*np;
-
+ int i,class_;
+ long unsigned int ln=0;
+ char *str[60],*p,*np; // 55->60 Lupus
+
memset(mob_db,0,sizeof(mob_db));
-
+
sprintf (tmp_sql, "SELECT * FROM `%s`",mob_db_db);
if(mysql_query(&mmysql_handle, tmp_sql) ) {
printf("DB server Error (select %s to Memory)- %s\n",mob_db_db,mysql_error(&mmysql_handle) );
@@ -4186,7 +4386,7 @@ static int mob_read_sqldb(void)
sql_res = mysql_store_result(&mmysql_handle);
if (sql_res) {
while((sql_row = mysql_fetch_row(sql_res))){
- sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
+ sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
sql_row[0],sql_row[1],sql_row[2],sql_row[3],sql_row[4],
sql_row[5],sql_row[6],sql_row[7],sql_row[8],sql_row[9],
sql_row[10],sql_row[11],sql_row[12],sql_row[13],sql_row[14],
@@ -4197,9 +4397,10 @@ static int mob_read_sqldb(void)
sql_row[35],sql_row[36],sql_row[37],sql_row[38],sql_row[39],
sql_row[40],sql_row[41],sql_row[42],sql_row[43],sql_row[44],
sql_row[45],sql_row[46],sql_row[47],sql_row[48],sql_row[49],
- sql_row[50],sql_row[51],sql_row[52]);
+ sql_row[50],sql_row[51],sql_row[52],sql_row[53],sql_row[54],
+ sql_row[55],sql_row[56]);
- for(i=0,p=line;i<55;i++){
+ for(i=0,p=line;i<57;i++){
if((np=strchr(p,','))!=NULL){
str[i]=p;
*np=0;
@@ -4207,109 +4408,141 @@ static int mob_read_sqldb(void)
} else
str[i]=p;
}
-
- class=atoi(str[0]);
- if(class<=1000 || class>2000)
+
+ class_=atoi(str[0]);
+ if(class_<=1000 || class_>MAX_MOB_DB)
continue;
-
+
ln++;
-
- mob_db[class].view_class=class;
- memcpy(mob_db[class].name,str[1],24);
- memcpy(mob_db[class].jname,str[2],24);
- mob_db[class].lv=atoi(str[3]);
- mob_db[class].max_hp=atoi(str[4]);
- mob_db[class].max_sp=atoi(str[5]);
- mob_db[class].base_exp=atoi(str[6])*
- battle_config.base_exp_rate/100;
- if(mob_db[class].base_exp <= 0)
- mob_db[class].base_exp = 1;
- mob_db[class].job_exp=atoi(str[7])*
- battle_config.job_exp_rate/100;
- if(mob_db[class].job_exp <= 0)
- mob_db[class].job_exp = 1;
- mob_db[class].range=atoi(str[8]);
- mob_db[class].atk1=atoi(str[9]);
- mob_db[class].atk2=atoi(str[10]);
- mob_db[class].def=atoi(str[11]);
- mob_db[class].mdef=atoi(str[12]);
- mob_db[class].str=atoi(str[13]);
- mob_db[class].agi=atoi(str[14]);
- mob_db[class].vit=atoi(str[15]);
- mob_db[class].int_=atoi(str[16]);
- mob_db[class].dex=atoi(str[17]);
- mob_db[class].luk=atoi(str[18]);
- mob_db[class].range2=atoi(str[19]);
- mob_db[class].range3=atoi(str[20]);
- mob_db[class].size=atoi(str[21]);
- mob_db[class].race=atoi(str[22]);
- mob_db[class].element=atoi(str[23]);
- mob_db[class].mode=atoi(str[24]);
- mob_db[class].speed=atoi(str[25]);
- mob_db[class].adelay=atoi(str[26]);
- mob_db[class].amotion=atoi(str[27]);
- mob_db[class].dmotion=atoi(str[28]);
-
- for(i=0;i<8;i++){
+
+ mob_db[class_].view_class=class_;
+ memcpy(mob_db[class_].name,str[1],24);
+ memcpy(mob_db[class_].jname,str[2],24);
+ mob_db[class_].lv=atoi(str[3]);
+ mob_db[class_].max_hp=atoi(str[4]);
+ mob_db[class_].max_sp=atoi(str[5]);
+
+ mob_db[class_].base_exp = atoi(str[6]);
+ if (mob_db[class_].base_exp <= 0)
+ mob_db[class_].base_exp = 0;
+ else if (mob_db[class_].base_exp * battle_config.base_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].base_exp * battle_config.base_exp_rate / 100 < 0)
+ mob_db[class_].base_exp = 1000000000;
+ else {
+ mob_db[class_].base_exp = mob_db[class_].base_exp * battle_config.base_exp_rate / 100;
+ if (mob_db[class_].base_exp < 1)
+ mob_db[class_].base_exp = 1;
+ }
+ mob_db[class_].job_exp = atoi(str[7]);
+ if (mob_db[class_].job_exp <= 0)
+ mob_db[class_].job_exp = 0;
+ else if (mob_db[class_].job_exp * battle_config.job_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].job_exp * battle_config.job_exp_rate / 100 < 0)
+ mob_db[class_].job_exp = 1000000000;
+ else {
+ mob_db[class_].job_exp = mob_db[class_].job_exp * battle_config.job_exp_rate / 100;
+ if (mob_db[class_].job_exp < 1)
+ mob_db[class_].job_exp = 1;
+ }
+
+ mob_db[class_].range=atoi(str[8]);
+ mob_db[class_].atk1=atoi(str[9]);
+ mob_db[class_].atk2=atoi(str[10]);
+ mob_db[class_].def=atoi(str[11]);
+ mob_db[class_].mdef=atoi(str[12]);
+ mob_db[class_].str=atoi(str[13]);
+ mob_db[class_].agi=atoi(str[14]);
+ mob_db[class_].vit=atoi(str[15]);
+ mob_db[class_].int_=atoi(str[16]);
+ mob_db[class_].dex=atoi(str[17]);
+ mob_db[class_].luk=atoi(str[18]);
+ mob_db[class_].range2=atoi(str[19]);
+ mob_db[class_].range3=atoi(str[20]);
+ mob_db[class_].size=atoi(str[21]);
+ mob_db[class_].race=atoi(str[22]);
+ mob_db[class_].element=atoi(str[23]);
+ mob_db[class_].mode=atoi(str[24]);
+ mob_db[class_].speed=atoi(str[25]);
+ mob_db[class_].adelay=atoi(str[26]);
+ mob_db[class_].amotion=atoi(str[27]);
+ mob_db[class_].dmotion=atoi(str[28]);
+
+ for(i=0;i<10;i++){ // 8 -> 10 Lupus
int rate = 0,type,ratemin,ratemax;
- mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]);
- type = itemdb_type(mob_db[class].dropitem[i].nameid);
+ mob_db[class_].dropitem[i].nameid=atoi(str[29+i*2]);
+ type = itemdb_type(mob_db[class_].dropitem[i].nameid);
if (type == 0) { // Added by Valaris
- rate = battle_config.item_rate_heal;
+ rate = battle_config.item_rate_heal * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_heal_min;
ratemax = battle_config.item_drop_heal_max;
}
else if (type == 2) {
- rate = battle_config.item_rate_use;
+ rate = battle_config.item_rate_use * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_use_min;
ratemax = battle_config.item_drop_use_max; // End
}
else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip
- rate = battle_config.item_rate_equip;
+ rate = battle_config.item_rate_equip * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_equip_min;
ratemax = battle_config.item_drop_equip_max;
}
else if (type == 6) {
- rate = battle_config.item_rate_card;
+ rate = battle_config.item_rate_card * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_card_min;
ratemax = battle_config.item_drop_card_max;
}
else {
- rate = battle_config.item_rate_common;
+ rate = battle_config.item_rate_common * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_common_min;
ratemax = battle_config.item_drop_common_max;
}
- rate = (rate / 100) * atoi(str[30+i*2]);
- rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
- mob_db[class].dropitem[i].p = rate;
+
+ mob_db[class_].dropitem[i].p = (rate < ratemin) ? ratemin : (rate > ratemax) ? ratemax: rate;
}
-
- mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100;
- mob_db[class].mexpper=atoi(str[46]);
+ // MVP EXP Bonus, Chance: MEXP,ExpPer
+ mob_db[class_].mexp=atoi(str[49])*battle_config.mvp_exp_rate/100;
+ mob_db[class_].mexpper=atoi(str[50]);
+ // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
for(i=0;i<3;i++){
- mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]);
- mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100;
+ mob_db[class_].mvpitem[i].nameid=atoi(str[51+i*2]);
+ mob_db[class_].mvpitem[i].p=atoi(str[52+i*2])*battle_config.mvp_item_rate/100;
}
for(i=0;i<MAX_RANDOMMONSTER;i++)
- mob_db[class].summonper[i]=0;
- mob_db[class].maxskill=0;
-
- mob_db[class].sex=0;
- mob_db[class].hair=0;
- mob_db[class].hair_color=0;
- mob_db[class].weapon=0;
- mob_db[class].shield=0;
- mob_db[class].head_top=0;
- mob_db[class].head_mid=0;
- mob_db[class].head_buttom=0;
+ mob_db[class_].summonper[i]=0;
+ mob_db[class_].maxskill=0;
+
+ mob_db[class_].sex=0;
+ mob_db[class_].hair=0;
+ mob_db[class_].hair_color=0;
+ mob_db[class_].weapon=0;
+ mob_db[class_].shield=0;
+ mob_db[class_].head_top=0;
+ mob_db[class_].head_mid=0;
+ mob_db[class_].head_buttom=0;
}
mysql_free_result(sql_res);
- printf("read %s done (count=%d)\n",mob_db_db,ln);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,mob_db_db);
+ ShowStatus(tmp_output);
}
return 0;
}
-
#endif /* not TXT_ONLY */
+
+void mob_reload(void)
+{
+#ifndef TXT_ONLY
+ if(db_use_sqldbs)
+ mob_read_sqldb();
+ else
+#endif /* TXT_ONLY */
+ mob_readdb();
+
+ mob_readdb_mobavail();
+ mob_read_randommonster();
+ mob_readskilldb();
+ mob_readdb_race();
+}
+
/*==========================================
* Circumference initialization of mob
*------------------------------------------
@@ -4319,13 +4552,14 @@ int do_init_mob(void)
#ifndef TXT_ONLY
if(db_use_sqldbs)
mob_read_sqldb();
- else
+ else
#endif /* TXT_ONLY */
mob_readdb();
mob_readdb_mobavail();
mob_read_randommonster();
mob_readskilldb();
+ mob_readdb_race();
add_timer_func_list(mob_timer,"mob_timer");
add_timer_func_list(mob_delayspawn,"mob_delayspawn");