From 9827189a901458193bbc0c66081ae9a50576fd20 Mon Sep 17 00:00:00 2001 From: ultramage Date: Sun, 6 Jan 2008 16:37:06 +0000 Subject: Cleaned up mob_once_spawn() and mob_once_spawn_area(). - now they use mapid instead of mapname as input parameter - moved the responsibility to perform "this" -> mapid resolution to the caller - added a pair of swap() operations to prevent working with a negative-dimensioned area (fixes bugreport:87) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12022 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/atcommand.c | 6 +-- src/map/mob.c | 117 +++++++++++++++++++++++++++++----------------------- src/map/mob.h | 7 +--- src/map/script.c | 75 +++++++++++++++++++++------------ src/map/skill.c | 4 +- 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=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); } -- cgit v1.2.3-70-g09d2