summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/atcommand.c6
-rw-r--r--src/map/mob.c117
-rw-r--r--src/map/mob.h7
-rw-r--r--src/map/script.c75
-rw-r--r--src/map/skill.c4
5 files changed, 121 insertions, 88 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 816484cdd..b9ec2c72c 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2454,7 +2454,7 @@ int atcommand_monster(const int fd, struct map_session_data* sd, const char* com
range = (int)sqrt(number) +2; // calculation of an odd number (+ 4 area around)
for (i = 0; i < number; i++) {
map_search_freecell(&sd->bl, 0, &mx, &my, range, range, 0);
- k = mob_once_spawn(sd, "this", mx, my, name, mob_id, 1, "");
+ k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, "");
count += (k != 0) ? 1 : 0;
}
@@ -2539,7 +2539,7 @@ int atcommand_monstersmall(const int fd, struct map_session_data* sd, const char
my = sd->bl.y + (rand() % 11 - 5);
else
my = y;
- count += (mob_once_spawn((struct map_session_data*)sd, "this", mx, my, name, mob_id, 1, "2") != 0) ? 1 : 0;
+ count += (mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, "2") != 0) ? 1 : 0;
}
if (count != 0)
@@ -2615,7 +2615,7 @@ int atcommand_monsterbig(const int fd, struct map_session_data* sd, const char*
my = sd->bl.y + (rand() % 11 - 5);
else
my = y;
- count += (mob_once_spawn((struct map_session_data*)sd, "this", mx, my, name, mob_id, 1, "4") != 0) ? 1 : 0;
+ count += (mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, "4") != 0) ? 1 : 0;
}
if (count != 0)
diff --git a/src/map/mob.c b/src/map/mob.c
index 900cc7da1..ff5fa49c7 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -285,7 +285,7 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short
data.num = 1;
data.class_ = class_;
if (mobname)
- strncpy(data.name, mobname, NAME_LENGTH-1);
+ safestrncpy(data.name, mobname, sizeof(data.name));
else
if(battle_config.override_mob_names==1)
strcpy(data.name,"--en--");
@@ -293,11 +293,13 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short
strcpy(data.name,"--ja--");
if (event)
- strncpy(data.eventname, event, 50);
+ safestrncpy(data.eventname, event, sizeof(data.eventname));
- if (bl && (x < 0 || y < 0))//Locate spot around player.
+ // Locate spot next to player.
+ if (bl && (x < 0 || y < 0))
map_search_freecell(bl, m, &x, &y, 1, 1, 0);
+ // if none found, pick random position on map
if (x <= 0 || y <= 0 || map_getcell(m,x,y,CELL_CHKNOREACH))
map_search_freecell(NULL, m, &x, &y, -1, -1, 1);
@@ -309,35 +311,32 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short
return mob_spawn_dataset(&data);
}
+
/*==========================================
- * The MOB appearance for one time (for scripts)
+ * Spawn a single mob on the specified coordinates.
*------------------------------------------*/
-int mob_once_spawn (struct map_session_data* sd, const char* mapname, short x, short y, const char* mobname, int class_, int amount, const char* event)
+int mob_once_spawn(struct map_session_data* sd, int m, short x, short y, const char* mobname, int class_, int amount, const char* event)
{
struct mob_data* md = NULL;
- int m, count, lv = 255;
+ int count, lv;
- if(sd) lv = sd->status.base_level;
+ if (m < 0 || amount <= 0)
+ return 0; // invalid input
- if(sd && strcmp(mapname,"this")==0)
- m = sd->bl.m;
+ if(sd)
+ lv = sd->status.base_level;
else
- m = map_mapname2mapid(mapname);
+ lv = 255;
- if (m < 0 || amount <= 0) // 値が異常なら召喚を止める
- return 0;
-
for (count = 0; count < amount; count++)
{
- md = mob_once_spawn_sub(sd?&sd->bl:NULL, m, x, y, mobname,
- class_<0?
- mob_get_random_id(-class_-1, battle_config.random_monster_checklv?3:1, lv):
- class_, event);
+ int c = ( class_ >= 0 ) ? class_ : mob_get_random_id(-class_-1, battle_config.random_monster_checklv?3:1, lv);
+ md = mob_once_spawn_sub(sd?&sd->bl:NULL, m, x, y, mobname, c, event);
if (!md) continue;
if(class_ == MOBID_EMPERIUM) {
- struct guild_castle* gc = guild_mapname2gc(map[md->bl.m].name);
+ struct guild_castle* gc = guild_mapindex2gc(map[m].index);
struct guild* g = gc?guild_search(gc->guild_id):NULL;
if(gc) {
md->guardian_data = aCalloc(1, sizeof(struct guardian_data));
@@ -353,55 +352,71 @@ int mob_once_spawn (struct map_session_data* sd, const char* mapname, short x, s
add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id);
}
} // end addition [Valaris]
- mob_spawn (md);
+
+ mob_spawn(md);
+
if (class_ < 0 && battle_config.dead_branch_active)
//Behold Aegis's masterful decisions yet again...
//"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3
sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE, 0, 60000);
}
- return (md)?md->bl.id : 0;
+
+ return (md)?md->bl.id : 0; // id of last spawned mob
}
+
/*==========================================
- * The MOB appearance for one time (& area specification for scripts)
+ * Spawn mobs in the specified area.
*------------------------------------------*/
-int mob_once_spawn_area(struct map_session_data *sd,const char *mapname,
- int x0,int y0,int x1,int y1,
- const char *mobname,int class_,int amount,const char *event)
+int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,int y1,const char* mobname,int class_,int amount,const char* event)
{
- int x,y,i,max,lx=-1,ly=-1,id=0;
- int m;
+ int i,max,id=0;
+ int lx=-1,ly=-1;
- if(strcmp(mapname,"this")==0)
- m=sd->bl.m;
- else
- m=map_mapname2mapid(mapname);
+ if (m < 0 || amount <= 0)
+ return 0; // invalid input
- max=(y1-y0+1)*(x1-x0+1)*3;
- if(max>1000)max=1000;
+ // normalize x/y coordinates
+ if( x0 > x1 ) swap(x0,x1);
+ if( y0 > y1 ) swap(y0,y1);
- if (m < 0 || amount <= 0) // 値が異常なら召喚を止める
- return 0;
+ // choose a suitable max. number of attempts
+ max = (y1-y0+1)*(x1-x0+1)*3;
+ if( max > 1000 )
+ max = 1000;
- for(i=0;i<amount;i++){
- int j=0;
- do{
- x=rand()%(x1-x0+1)+x0;
- y=rand()%(y1-y0+1)+y0;
- } while (map_getcell(m,x,y,CELL_CHKNOPASS) && (++j)<max);
- if(j>=max){
- if(lx>=0){ // Since reference went wrong, the place which boiled before is used.
- x=lx;
- y=ly;
- }else
- return 0; // Since reference of the place which boils first went wrong, it stops.
+ // spawn mobs, one by one
+ for( i = 0; i < amount; i++)
+ {
+ int x,y;
+ int j = 0;
+
+ // find a suitable map cell
+ do {
+ x = rand()%(x1-x0+1)+x0;
+ y = rand()%(y1-y0+1)+y0;
+ j++;
+ } while( map_getcell(m,x,y,CELL_CHKNOPASS) && j < max );
+
+ if( j == max )
+ {// attempt to find an available cell failed
+ if( lx == -1 && ly == -1 )
+ return 0; // total failure
+
+ // fallback to last good x/y pair
+ x = lx;
+ y = ly;
}
- if(x==0||y==0) ShowWarning("mob_once_spawn_area: 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;
+
+ // record last successful coordinates
+ lx = x;
+ ly = y;
+
+ id = mob_once_spawn(sd,m,x,y,mobname,class_,1,event);
}
- return id;
+
+ return id; // id of last spawned mob
}
+
/*==========================================
* Set a Guardian's guild data [Skotlex]
*------------------------------------------*/
diff --git a/src/map/mob.h b/src/map/mob.h
index 69b555deb..bdb35a21f 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -154,11 +154,8 @@ int mobdb_checkid(const int id);
struct view_data* mob_get_viewdata(int class_);
struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m,
short x, short y, const char *mobname, int class_, const char *event);
-int mob_once_spawn(struct map_session_data *sd,const char *mapname,
- short x,short y,const char *mobname,int class_,int amount,const char *event);
-int mob_once_spawn_area(struct map_session_data *sd,const char *mapname,
- int x0,int y0,int x1,int y1,
- const char *mobname,int class_,int amount,const char *event);
+int mob_once_spawn(struct map_session_data* sd,int m,short x,short y,const char* mobname,int class_,int amount,const char* event);
+int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,int y1,const char* mobname,int class_,int amount,const char* event);
int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian); // Spawning Guardians [Valaris]
int mob_guardian_guildchange(struct block_list *bl,va_list ap); //Change Guardian's ownership. [Skotlex]
diff --git a/src/map/script.c b/src/map/script.c
index 67a0d235b..90df0f884 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -7334,17 +7334,20 @@ BUILDIN_FUNC(guildchangegm)
*------------------------------------------*/
BUILDIN_FUNC(monster)
{
- int class_,amount,x,y;
- const char *str,*map,*event="";
+ const char* map = script_getstr(st,2);
+ int x = script_getnum(st,3);
+ int y = script_getnum(st,4);
+ const char* str = script_getstr(st,5);
+ int class_ = script_getnum(st,6);
+ int amount = script_getnum(st,7);
+ const char* event = "";
+
+ struct map_session_data* sd;
+ int m;
- map =script_getstr(st,2);
- x =script_getnum(st,3);
- y =script_getnum(st,4);
- str =script_getstr(st,5);
- class_=script_getnum(st,6);
- amount=script_getnum(st,7);
- if( script_hasdata(st,8) ){
- event=script_getstr(st,8);
+ if( script_hasdata(st,8) )
+ {
+ event = script_getstr(st,8);
check_event(st, event);
}
@@ -7352,7 +7355,15 @@ BUILDIN_FUNC(monster)
ShowWarning("buildin_monster: Attempted to spawn non-existing monster class %d\n", class_);
return 1;
}
- mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class_,amount,event);
+
+ sd = map_id2sd(st->rid);
+
+ if( sd && strcmp(map,"this") == 0 )
+ m = sd->bl.m;
+ else
+ m = map_mapname2mapid(map);
+
+ mob_once_spawn(sd,m,x,y,str,class_,amount,event);
return 0;
}
/*==========================================
@@ -7360,23 +7371,33 @@ BUILDIN_FUNC(monster)
*------------------------------------------*/
BUILDIN_FUNC(areamonster)
{
- int class_,amount,x0,y0,x1,y1;
- const char *str,*map,*event="";
-
- map =script_getstr(st,2);
- x0 =script_getnum(st,3);
- y0 =script_getnum(st,4);
- x1 =script_getnum(st,5);
- y1 =script_getnum(st,6);
- str =script_getstr(st,7);
- class_=script_getnum(st,8);
- amount=script_getnum(st,9);
- if( script_hasdata(st,10) ){
- event=script_getstr(st,10);
+ const char* map = script_getstr(st,2);
+ int x0 = script_getnum(st,3);
+ int y0 = script_getnum(st,4);
+ int x1 = script_getnum(st,5);
+ int y1 = script_getnum(st,6);
+ const char* str = script_getstr(st,7);
+ int class_ = script_getnum(st,8);
+ int amount = script_getnum(st,9);
+ const char* event = "";
+
+ struct map_session_data* sd;
+ int m;
+
+ if( script_hasdata(st,10) )
+ {
+ event = script_getstr(st,10);
check_event(st, event);
}
- mob_once_spawn_area(map_id2sd(st->rid),map,x0,y0,x1,y1,str,class_,amount,event);
+ sd = map_id2sd(st->rid);
+
+ if( sd && strcmp(map,"this") == 0 )
+ m = sd->bl.m;
+ else
+ m = map_mapname2mapid(map);
+
+ mob_once_spawn_area(sd,m,x0,y0,x1,y1,str,class_,amount,event);
return 0;
}
/*==========================================
@@ -12290,8 +12311,8 @@ BUILDIN_FUNC(mobspawn)
map =script_getstr(st,4);
x =script_getnum(st,5);
y =script_getnum(st,6);
-
- id = mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class_,1,"");
+
+ id = mob_once_spawn(map_id2sd(st->rid),map_mapname2mapid(map),x,y,str,class_,1,"");
script_pushint(st,id);
return 0;
diff --git a/src/map/skill.c b/src/map/skill.c
index a2c636ddc..ae934d983 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -3072,7 +3072,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case SA_SUMMONMONSTER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if (sd) mob_once_spawn(sd,map[src->m].name,src->x,src->y,"--ja--",-1,1,"");
+ if (sd) mob_once_spawn(sd,src->m,src->x,src->y,"--ja--",-1,1,"");
break;
case SA_LEVELUP:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -5804,7 +5804,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
pc_delitem(sd,j,skill_db[skillid].amount[i],0);
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
if (rand()%100 < 50)
- mob_once_spawn(sd, "this", x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6), 1, "");
+ mob_once_spawn(sd, sd->bl.m, x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6), 1, "");
else
clif_skill_fail(sd,skillid,0,0);
}