Pārlūkot izejas kodu

Quickfix

Follow up hash:0f2dd7fcf, fixed a typo on packet lenght for storagelist
this should fix bugreport:8344
Hotfix for bugreport:8333, (we're now checking if we fully add object on
map before attempting to spawn it)
lighta 11 gadi atpakaļ
vecāks
revīzija
854f8fc502
11 mainītis faili ar 212 papildinājumiem un 65 dzēšanām
  1. 11 4
      src/map/chat.c
  2. 10 6
      src/map/clif.c
  3. 8 1
      src/map/elemental.c
  4. 43 9
      src/map/homunculus.c
  5. 27 13
      src/map/map.c
  6. 8 1
      src/map/mercenary.c
  7. 25 10
      src/map/mob.c
  8. 67 14
      src/map/npc.c
  9. 4 2
      src/map/pet.c
  10. 4 2
      src/map/skill.c
  11. 5 3
      src/map/unit.c

+ 11 - 4
src/map/chat.c

@@ -167,7 +167,10 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
 
 
 /*==========================================
- * leave a chatroom
+ * Make player *sd leave a chatroom
+ * @param *sd : player pointer
+ * @param kicked : for clif notification, kicked=1 or regular leave
+ * @return 0:sucess, 1:failed
  *------------------------------------------*/
 int chat_leavechat(struct map_session_data* sd, bool kicked)
 {
@@ -229,8 +232,8 @@ int chat_leavechat(struct map_session_data* sd, bool kicked)
 		map_delblock( &cd->bl );
 		cd->bl.x=cd->usersd[0]->bl.x;
 		cd->bl.y=cd->usersd[0]->bl.y;
-		map_addblock( &cd->bl );
-
+		if(map_addblock( &cd->bl ))
+			return 1;
 		clif_dispchat(cd,0);
 	}
 	else
@@ -241,6 +244,9 @@ int chat_leavechat(struct map_session_data* sd, bool kicked)
 
 /*==========================================
  * change a chatroom's owner
+ * @param *sd : player pointer
+ * @param *nextownername : string of new owner (name should be in chatroom)
+ * @return 0:sucess, 1:failure
  *------------------------------------------*/
 int chat_changechatowner(struct map_session_data* sd, const char* nextownername)
 {
@@ -274,7 +280,8 @@ int chat_changechatowner(struct map_session_data* sd, const char* nextownername)
 	map_delblock( &cd->bl );
 	cd->bl.x = cd->owner->x;
 	cd->bl.y = cd->owner->y;
-	map_addblock( &cd->bl );
+	if(map_addblock( &cd->bl ))
+		return 1;
 
 	// and display again
 	clif_dispchat(cd,0);

+ 10 - 6
src/map/clif.c

@@ -2567,7 +2567,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items
 		WBUFW(bufn,0)=0x995;
 		memset((char*)WBUFP(buf,4),0,24); //storename
 #endif
-		WBUFW(bufn,2)=4+nn*s;
+		WBUFW(bufn,2)=sidx+nn*s;
 		clif_send(bufn, WBUFW(bufn,2), &sd->bl, SELF);
 	}
 	for (i = 0; i < ne;) // Loop through equipable items
@@ -2583,7 +2583,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items
 		WBUFW(bufn,0)=0x996;
 		memset((char*)WBUFP(bufn,4),0,24); //storename
 #endif
-		WBUFW(bufn,2)=4+nn*se;
+		WBUFW(bufn,2)=sidxe+nn*se;
 		clif_send(bufn, WBUFW(bufn,2), &sd->bl, SELF);
 	}
 
@@ -9482,7 +9482,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 	// reset the callshop flag if the player changes map
 	sd->state.callshop = 0;
 
-	map_addblock(&sd->bl);
+	if(map_addblock(&sd->bl))
+		return;
 	clif_spawn(&sd->bl);
 
 	// Party
@@ -9524,7 +9525,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 			clif_displaymessage(sd->fd, msg_txt(sd,666));
 			pet_menu(sd, 3); //Option 3 is return to egg.
 		} else {
-			map_addblock(&sd->pd->bl);
+			if(map_addblock(&sd->pd->bl))
+				return;
 			clif_spawn(&sd->pd->bl);
 			clif_send_petdata(sd,sd->pd,0,0);
 			clif_send_petstatus(sd);
@@ -9534,7 +9536,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 
 	//homunculus [blackhole89]
 	if( merc_is_hom_active(sd->hd) ) {
-		map_addblock(&sd->hd->bl);
+		if(map_addblock(&sd->hd->bl))
+			return;
 		clif_spawn(&sd->hd->bl);
 		clif_send_homdata(sd,SP_ACK,0);
 		clif_hominfo(sd,sd->hd,1);
@@ -9547,7 +9550,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 	}
 
 	if( sd->md ) {
-		map_addblock(&sd->md->bl);
+		if(map_addblock(&sd->md->bl))
+			return;
 		clif_spawn(&sd->md->bl);
 		clif_mercenary_info(sd);
 		clif_mercenary_skillblock(sd);

+ 8 - 1
src/map/elemental.c

@@ -222,6 +222,12 @@ void elemental_summon_init(struct elemental_data *ed) {
 	ed->regen.state.block = 0;
 }
 
+/**
+ * Inter-serv has sent us the elemental data from sql, fill it in map-serv memory
+ * @param ele : The elemental data received from char-serv
+ * @param flag : 0:not created, 1:was saved/loaded
+ * @return 0:failed, 1:sucess
+ */
 int elemental_data_received(struct s_elemental *ele, bool flag) {
 	struct map_session_data *sd;
 	struct elemental_data *ed;
@@ -271,7 +277,8 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
 	sd->status.ele_id = ele->elemental_id;
 
 	if( ed->bl.prev == NULL && sd->bl.prev != NULL ) {
-		map_addblock(&ed->bl);
+		if(map_addblock(&ed->bl))
+			return 0;
 		clif_spawn(&ed->bl);
 		clif_elemental_info(sd);
 		clif_elemental_updatestatus(sd,SP_HP);

+ 43 - 9
src/map/homunculus.c

@@ -406,6 +406,11 @@ int merc_hom_change_class(struct homun_data *hd, short class_)
 	return 1;
 }
 
+/**
+ * Make an homonculus evolve, (changing in evolution class and apply bonus)
+ * @param hd : homonculus datas
+ * @return 0:failure, 1:success
+ */
 int merc_hom_evolution(struct homun_data *hd)
 {
 	struct s_homunculus *hom;
@@ -442,7 +447,8 @@ int merc_hom_evolution(struct homun_data *hd)
 	hom->intimacy = 500;
 
 	unit_remove_map(&hd->bl, CLR_OUTSIGHT);
-	map_addblock(&hd->bl);
+	if(map_addblock(&hd->bl))
+		return 0;
 
 	clif_spawn(&hd->bl);
 	clif_emotion(&sd->bl, E_NO1);
@@ -459,6 +465,12 @@ int merc_hom_evolution(struct homun_data *hd)
 	return 1 ;
 }
 
+/**
+ * Make an homonculus mutate in renewal homon
+ * @param hd : homonculus datas
+ * @param homun_id : id to make it transform into (must be a valid homon class)
+ * @return 0:failure, 1:sucess
+ */
 int hom_mutate(struct homun_data *hd, int homun_id)
 {
 	struct s_homunculus *hom;
@@ -486,7 +498,8 @@ int hom_mutate(struct homun_data *hd, int homun_id)
 	}
 
 	unit_remove_map(&hd->bl, CLR_OUTSIGHT);
-	map_addblock(&hd->bl);
+	if(map_addblock(&hd->bl))
+		return 0;
 
 	clif_spawn(&hd->bl);
 	clif_emotion(&sd->bl, E_NO1);
@@ -827,6 +840,11 @@ void merc_hom_init_timers(struct homun_data * hd)
 	hd->masterteleport_timer = INVALID_TIMER;
 }
 
+/**
+ * Make a player spawn a homonculus (call)
+ * @param sd
+ * @return 0:failure, 1:sucess
+ */
 int merc_call_homunculus(struct map_session_data *sd)
 {
 	struct homun_data *hd;
@@ -853,7 +871,8 @@ int merc_call_homunculus(struct map_session_data *sd)
 		hd->bl.x = sd->bl.x;
 		hd->bl.y = sd->bl.y;
 		hd->bl.m = sd->bl.m;
-		map_addblock(&hd->bl);
+		if(map_addblock(&hd->bl))
+			return 0;
 		clif_spawn(&hd->bl);
 		clif_send_homdata(sd,SP_ACK,0);
 		clif_hominfo(sd,hd,1);
@@ -868,7 +887,13 @@ int merc_call_homunculus(struct map_session_data *sd)
 	return 1;
 }
 
-// Recv homunculus data from char server
+/**
+ * Receive homunculus data from char server
+ * @param account_id : owner account_id of the homon 
+ * @param sh : homonculus data from char-serv
+ * @param flag : does the creation in inter-serv was a success (0:no,1:yes)
+ * @return 0:failure, 1:sucess
+ */
 int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
 {
 	struct map_session_data *sd;
@@ -899,7 +924,8 @@ int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
 	hd = sd->hd;
 	if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL)
 	{
-		map_addblock(&hd->bl);
+		if(map_addblock(&hd->bl))
+			return 0;
 		clif_spawn(&hd->bl);
 		clif_send_homdata(sd,SP_ACK,0);
 		clif_hominfo(sd,hd,1);
@@ -947,6 +973,14 @@ int merc_create_homunculus_request(struct map_session_data *sd, int class_)
 	return 1;
 }
 
+/**
+ * Make a player resurect an homon (player must have one)
+ * @param sd : player pointer
+ * @param per : hp percentage to revive homon
+ * @param x : x map coordinate
+ * @param y : Y map coordinate
+ * @return 0:failure, 1:success
+ */
 int merc_resurrect_homunculus(struct map_session_data* sd, unsigned char per, short x, short y)
 {
 	struct homun_data* hd;
@@ -960,7 +994,7 @@ int merc_resurrect_homunculus(struct map_session_data* sd, unsigned char per, sh
 
 	hd = sd->hd;
 
-  	if (hd->homunculus.vaporize == HOM_ST_REST)
+	if (hd->homunculus.vaporize == HOM_ST_REST)
 		return 0; // vaporized homunculi need to be 'called'
 
 	if (!status_isdead(&hd->bl))
@@ -973,11 +1007,11 @@ int merc_resurrect_homunculus(struct map_session_data* sd, unsigned char per, sh
 		hd->bl.m = sd->bl.m;
 		hd->bl.x = x;
 		hd->bl.y = y;
-		map_addblock(&hd->bl);
+		if(map_addblock(&hd->bl))
+			return 0;
 		clif_spawn(&hd->bl);
 	}
-	status_revive(&hd->bl, per, 0);
-	return 1;
+	return status_revive(&hd->bl, per, 0);
 }
 
 void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)

+ 27 - 13
src/map/map.c

@@ -328,7 +328,7 @@ int map_delblock(struct block_list* bl)
 	int pos;
 	nullpo_ret(bl);
 
-    // blocklist (2ways chainlist)
+	// blocklist (2ways chainlist)
 	if (bl->prev == NULL) {
 		if (bl->next != NULL) {
 			// can't delete block (already at the begining of the chain)
@@ -361,11 +361,16 @@ int map_delblock(struct block_list* bl)
 	return 0;
 }
 
-/*==========================================
+/**
  * Moves a block a x/y target position. [Skotlex]
  * Pass flag as 1 to prevent doing skill_unit_move checks
  * (which are executed by default on BL_CHAR types)
- *------------------------------------------*/
+ * @param bl : block(object) to move
+ * @param x1 : new x position
+ * @param y1 : new y position
+ * @param tick : when this was scheduled
+ * @return 0:sucess, 1:fail
+ */
 int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
 {
 	int x0 = bl->x, y0 = bl->y;
@@ -404,7 +409,10 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
 #endif
 	bl->x = x1;
 	bl->y = y1;
-	if (moveblock) map_addblock(bl);
+	if (moveblock) {
+		if(map_addblock(bl))
+			return 1;
+	}
 #ifdef CELL_NOSTACK
 	else map_addblcell(bl);
 #endif
@@ -677,7 +685,7 @@ int map_foreachinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0
 	int blockcount = bl_list_count, i;
 	va_list ap;
 
-	if ( m < 0 )
+	if ( m < 0 || m >= map_num)
 		return 0;
 
 	if ( x1 < x0 )
@@ -1417,13 +1425,18 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 }
 
 /*==========================================
- * Add an item to location (m,x,y)
- * Parameters
- * @item_data item attributes
- * @amount quantity
- * @m, @x, @y mapid,x,y
- * @first_charid, @second_charid, @third_charid, looting priority
- * @flag: &1 MVP item. &2 do stacking check. &4 bypass droppable check.
+ * Add an item in floor to location (m,x,y) and add restriction for those who could pickup later
+ * NB : If charids are null their no restriction for pickup
+ * @param item_data : item attributes
+ * @param amount : items quantity
+ * @param m : mapid
+ * @param x : x coordinates
+ * @param y : y coordinates
+ * @param first_charid : 1st player that could loot the item (only charid that could loot for first_get_tick duration)
+ * @param second_charid :  2nd player that could loot the item (2nd charid that could loot for second_get_charid duration)
+ * @param third_charid : 3rd player that could loot the item (3rd charid that could loot for third_get_charid duration)
+ * @param flag: &1 MVP item. &2 do stacking check. &4 bypass droppable check.
+ * @return 0:failure, x:item_gid [MIN_FLOORITEM;MAX_FLOORITEM]==[2;START_ACCOUNT_NUM]
  *------------------------------------------*/
 int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags)
 {
@@ -1465,7 +1478,8 @@ int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,i
 	fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);
 
 	map_addiddb(&fitem->bl);
-	map_addblock(&fitem->bl);
+	if(map_addblock(&fitem->bl))
+		return 0;
 	clif_dropflooritem(fitem);
 
 	return fitem->bl.id;

+ 8 - 1
src/map/mercenary.c

@@ -280,6 +280,12 @@ void merc_contract_init(struct mercenary_data *md)
 	md->regen.state.block = 0;
 }
 
+/**
+ * Received mercenary data from char-serv
+ * @param merc : mercenary datas
+ * @param flag : if inter-serv request was sucessfull
+ * @return 0:failure, 1:sucess
+ */
 int merc_data_received(struct s_mercenary *merc, bool flag)
 {
 	struct map_session_data *sd;
@@ -336,7 +342,8 @@ int merc_data_received(struct s_mercenary *merc, bool flag)
 
 	if( md && md->bl.prev == NULL && sd->bl.prev != NULL )
 	{
-		map_addblock(&md->bl);
+		if(map_addblock(&md->bl))
+			return 0;
 		clif_spawn(&md->bl);
 		clif_mercenary_info(sd);
 		clif_mercenary_skillblock(sd);

+ 25 - 10
src/map/mob.c

@@ -122,9 +122,13 @@ static int mobdb_searchname_array_sub(struct mob_db* mob, const char *str)
 	return strcmpi(mob->jname,str);
 }
 
-/*==========================================
- *              MvP Tomb [GreenBox]
- *------------------------------------------*/
+/**
+ * Create and display a tombstone on the map
+ * @author [GreenBox]
+ * @param md : the mob to create a tombstone for
+ * @param killer : name of who has killed the mob
+ * @param time : time at wich the killed happen
+ */
 void mvptomb_create(struct mob_data *md, char *killer, time_t time)
 {
 	struct npc_data *nd;
@@ -157,7 +161,8 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
 		nd->u.tomb.killer_name[0] = '\0';
 
 	map_addnpc(nd->bl.m, nd);
-	map_addblock(&nd->bl);
+	if(map_addblock(&nd->bl))
+		return;
 	status_set_viewdata(&nd->bl, nd->class_);
 	status_change_init(&nd->bl);
 	unit_dataset(&nd->bl);
@@ -894,9 +899,11 @@ int mob_count_sub(struct block_list *bl, va_list ap) {
     return 1; //backward compatibility
 }
 
-/*==========================================
- * Mob spawning. Initialization is also variously here.
- *------------------------------------------*/
+/**
+ * Mob spawning. Initialization is also variously here. (Spawn a mob in a map)
+ * @param md : mob data to spawn
+ * @return 0:spawned, 1:delayed, 2:error
+ */
 int mob_spawn (struct mob_data *md)
 {
 	int i=0;
@@ -981,7 +988,8 @@ int mob_spawn (struct mob_data *md)
 	if ( md->tomb_nid )
 		mvptomb_destroy(md);
 
-	map_addblock(&md->bl);
+	if(map_addblock(&md->bl))
+		return 2;
 	if( map[md->bl.m].users )
 		clif_spawn(&md->bl);
 	skill_unit_move(&md->bl,tick,1);
@@ -2656,6 +2664,11 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 	return 3; //Remove from map.
 }
 
+/**
+ * Resurect a mob with x hp (reset value and respawn on map)
+ * @param md : mob pointer
+ * @param hp : hp to resurect him with, @FIXME unused atm
+ */
 void mob_revive(struct mob_data *md, unsigned int hp)
 {
 	unsigned int tick = gettick();
@@ -2666,8 +2679,10 @@ void mob_revive(struct mob_data *md, unsigned int hp)
 	md->last_pcneartime = 0;
 	memset(md->dmglog, 0, sizeof(md->dmglog));	// Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris]
 	md->tdmg = 0;
-	if (!md->bl.prev)
-		map_addblock(&md->bl);
+	if (!md->bl.prev){
+		if(map_addblock(&md->bl))
+			return;
+	}
 	clif_spawn(&md->bl);
 	skill_unit_move(&md->bl,tick,1);
 	mobskill_use(md, tick, MSC_SPAWN);

+ 67 - 14
src/map/npc.c

@@ -2158,7 +2158,19 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
 	}
 }
 
-//Add then display an npc warp on map
+/**
+ * Add then display an npc warp on map
+ * @param name : warp unique name
+ * @param from_mapid : mapid to warp from
+ * @param from_x : x coordinate of warp
+ * @param from_y : y coordinate of warp
+ * @param xs : x lenght of warp (for trigger activation)
+ * @param ys : y lenght of warp (for trigger activation)
+ * @param to_mapindex : mapid to warp to
+ * @param to_x : x coordinate to warp to
+ * @param to_y : y coordinate to warp to
+ * @return NULL:failed creation, npc_data* new warp
+ */
 struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y)
 {
 	int i, flag = 0;
@@ -2197,7 +2209,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
 	nd->bl.type = BL_NPC;
 	nd->subtype = WARP;
 	npc_setcells(nd);
-	map_addblock(&nd->bl);
+	if(map_addblock(&nd->bl))
+		return NULL;
 	status_set_viewdata(&nd->bl, nd->class_);
 	status_change_init(&nd->bl);
 	unit_dataset(&nd->bl);
@@ -2208,7 +2221,18 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
 	return nd;
 }
 
-/// Parses a warp npc.
+/**
+ * Parses a warp npc.
+ * Line definition <from mapname>,<fromX>,<fromY>,<facing>%TAB%warp%TAB%<warp name>%TAB%<spanx>,<spany>,<to mapname>,<toX>,<toY>
+ * @param w1 : word 1 before tab (<from map name>,<fromX>,<fromY>,<facing>)
+ * @param w2 : word 2 before tab (warp), keyword that sent us in this parsing
+ * @param w3 : word 3 before tab (<warp name>)
+ * @param w4 : word 4 before tab (<spanx>,<spany>,<to mapname>,<toX>,<toY>)
+ * @param start : index to start parsing
+ * @param buffer : lines to parses
+ * @param filepath : filename with path wich we are parsing
+ * @return new index for next parsing
+ */
 static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
 {
 	int x, y, xs, ys, to_x, to_y, m;
@@ -2262,7 +2286,8 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
 	nd->bl.type = BL_NPC;
 	nd->subtype = WARP;
 	npc_setcells(nd);
-	map_addblock(&nd->bl);
+	if(map_addblock(&nd->bl)) //couldn't add on map
+		return strchr(start,'\n');
 	status_set_viewdata(&nd->bl, nd->class_);
 	status_change_init(&nd->bl);
 	unit_dataset(&nd->bl);
@@ -2273,7 +2298,22 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
 	return strchr(start,'\n');// continue
 }
 
-/// Parses a shop/cashshop npc.
+/**
+ * Parses a shop/cashshop npc.
+ * Line definition :
+ * <map name>,<x>,<y>,<facing>%TAB%shop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>{,<itemid>:<price>...}
+ * <map name>,<x>,<y>,<facing>%TAB%itemshop%TAB%<NPC Name>%TAB%<sprite id>,<costitemid>{:<discount>},<itemid>:<price>{,<itemid>:<price>...}
+ * <map name>,<x>,<y>,<facing>%TAB%pointshop%TAB%<NPC Name>%TAB%<sprite id>,<costvariable>{:<discount>},<itemid>:<price>{,<itemid>:<price>...}
+ * @TODO missing cashshop line definition
+ * @param w1 : word 1 before tab (<from map name>,<x>,<y>,<facing>)
+ * @param w2 : word 2 before tab (shop|cashshop|itemshop|pointshop), keyword that sent us in this parsing
+ * @param w3 : word 3 before tab (<NPC Name>)
+ * @param w4 : word 4 before tab (<sprited id>,<shop definition...>)
+ * @param start : index to start parsing
+ * @param buffer : lines to parses
+ * @param filepath : filename with path wich we are parsing
+ * @return new index for next parsing
+ */
 static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
 {
 	//TODO: could be rewritten to NOT need this temp array [ultramage]
@@ -2419,7 +2459,8 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
 	if( m >= 0 )
 	{// normal shop npc
 		map_addnpc(m,nd);
-		map_addblock(&nd->bl);
+		if(map_addblock(&nd->bl))
+			return strchr(start,'\n');
 		status_set_viewdata(&nd->bl, nd->class_);
 		status_change_init(&nd->bl);
 		unit_dataset(&nd->bl);
@@ -2555,11 +2596,20 @@ static const char* npc_skip_script(const char* start, const char* buffer, const
 	return p+1;// return after the last '}'
 }
 
-/// Parses a npc script.
-///
-/// -%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>}
-/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
-/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>}
+/**
+ * Parses a npc script.
+ * Line definition :
+ * <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
+ * <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>} * @TODO missing cashshop line definition
+ * @param w1 : word 1 before tab (<from map name>,<x>,<y>,<facing>)
+ * @param w2 : word 2 before tab (script), keyword that sent us in this parsing
+ * @param w3 : word 3 before tab (<NPC Name>)
+ * @param w4 : word 4 before tab (<sprited id>,<code>)
+ * @param start : index to start parsing
+ * @param buffer : lines to parses
+ * @param filepath : filename with path wich we are parsing
+ * @return new index for next parsing
+ */
 static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) {
 	int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0;	// [Valaris] thanks to fov
 	char mapname[32];
@@ -2648,7 +2698,8 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
 		unit_dataset(&nd->bl);
 		nd->ud.dir = dir;
 		npc_setcells(nd);
-		map_addblock(&nd->bl);
+		if(map_addblock(&nd->bl))
+			return NULL;
 		if( class_ >= 0 )
 		{
 			status_set_viewdata(&nd->bl, nd->class_);
@@ -2808,7 +2859,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
 		unit_dataset(&nd->bl);
 		nd->ud.dir = dir;
 		npc_setcells(nd);
-		map_addblock(&nd->bl);
+		if(map_addblock(&nd->bl))
+			return end;
 		if( class_ >= 0 ) {
 			status_set_viewdata(&nd->bl, nd->class_);
 			if( map[nd->bl.m].users )
@@ -2892,7 +2944,8 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
 		wnd->bl.type = BL_NPC;
 		wnd->subtype = WARP;
 		npc_setcells(wnd);
-		map_addblock(&wnd->bl);
+		if(map_addblock(&wnd->bl))
+			return 1;
 		status_set_viewdata(&wnd->bl, wnd->class_);
 		status_change_init(&wnd->bl);
 		unit_dataset(&wnd->bl);

+ 4 - 2
src/map/pet.c

@@ -411,7 +411,8 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet)
 		chrif_save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex]
 
 	if(sd->bl.prev != NULL) {
-		map_addblock(&sd->pd->bl);
+		if(map_addblock(&sd->pd->bl))
+			return 1;
 		clif_spawn(&sd->pd->bl);
 		clif_send_petdata(sd,sd->pd, 0,0);
 		clif_send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style);
@@ -452,7 +453,8 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag)
 	} else {
 		pet_data_init(sd,p);
 		if(sd->pd && sd->bl.prev != NULL) {
-			map_addblock(&sd->pd->bl);
+			if(map_addblock(&sd->pd->bl))
+				return 1;
 			clif_spawn(&sd->pd->bl);
 			clif_send_petdata(sd,sd->pd,0,0);
 			clif_send_petdata(sd,sd->pd,5,battle_config.pet_hair_style);

+ 4 - 2
src/map/skill.c

@@ -6124,7 +6124,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			skill_get_splash(skill_id, skill_lv), splash_target(src),
 			src, skill_id, skill_lv, tick, flag|i,
 			skill_castend_damage_id);
-		map_addblock(src);
+		if(map_addblock(src))
+			return 1;
 		status_damage(src, src, sstatus->max_hp,0,0,1);
 		break;
 
@@ -15985,7 +15986,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
 
 	idb_put(skillunit_db, unit->bl.id, unit);
 	map_addiddb(&unit->bl);
-	map_addblock(&unit->bl);
+	if(map_addblock(&unit->bl))
+		return NULL;
 
 	// perform oninit actions
 	switch (group->skill_id) {

+ 5 - 3
src/map/unit.c

@@ -199,7 +199,8 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
 		case BL_PET : max_dist = AREA_SIZE; break;
 		case BL_MER : max_dist = MAX_MER_DISTANCE; break;
 	}
-	if(msd && max_dist){ // If there is a master and it's a valid type
+	// If there is a master and it's a valid type 
+	if(msd && (msd->bl.type&BL_PC) && max_dist){ ///TODO the bl.type is an hotfix please dig it to remove it
 		int *msd_tid = unit_get_masterteleport_timer(sbl);
 		if(msd_tid == NULL) return 0;
 		if (!check_distance_bl(&msd->bl, sbl, max_dist)) {
@@ -941,7 +942,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
 * @param x: Destination cell X
 * @param y: Destination cell Y
 * @param type: Clear type used in clif_clearunit_area()
-* @return Success(0); Failed(1); Error(2); unit_remove_map() Failed(3)
+* @return Success(0); Failed(1); Error(2); unit_remove_map() Failed(3); map_addblock Failed(4)
 **/
 int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
 {
@@ -1001,7 +1002,8 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
 	bl->y=ud->to_y=y;
 	bl->m=m;
 
-	map_addblock(bl);
+	if(map_addblock(bl))
+		return 4; //error on adding bl to map
 	clif_spawn(bl);
 	skill_unit_move(bl,gettick(),1);