Browse Source

Follow up to 2cee5b6
* Updated setunitdata to recalculate the object's information and update the client immediately.
* For setunitdata, map name can also be passed in as a valid value instead of map ID.
* Added mapid2name script command.
* Added status_set_maxhp and status_set_maxsp functions.
* Updated documentation to reflect changes.

aleos89 10 years ago
parent
commit
2dc38e77ca
4 changed files with 230 additions and 139 deletions
  1. 27 18
      doc/script_commands.txt
  2. 147 119
      src/map/script.c
  3. 54 2
      src/map/status.c
  4. 2 0
      src/map/status.h

+ 27 - 18
doc/script_commands.txt

@@ -2872,7 +2872,7 @@ Type is the type of object to search for:
   0 - Character object
   0 - Character object
   1 - NPC object
   1 - NPC object
   2 - Pet object
   2 - Pet object
-  3 - Monster object
+  3 - Monster object -- See 'getunitdata' for monster.
   4 - Homunculus object
   4 - Homunculus object
   5 - Mercenary object
   5 - Mercenary object
   6 - Elemental object
   6 - Elemental object
@@ -2910,6 +2910,13 @@ Notice that NPC objects disabled with 'disablenpc' will still be located.
 
 
 ---------------------------------------
 ---------------------------------------
 
 
+*mapid2name(<map ID>)
+
+Returns the map name of the given map ID. Returns an empty string if given
+map ID doesn't exist.
+
+---------------------------------------
+
 *getgmlevel()
 *getgmlevel()
 
 
 This function will return the (GM) level associated with the player group to which
 This function will return the (GM) level associated with the player group to which
@@ -7064,7 +7071,7 @@ Changing a homunculus or pet name will be permanent.
 ---------------------------------------
 ---------------------------------------
 
 
 *getunitdata <GID>,<arrayname>;
 *getunitdata <GID>,<arrayname>;
-*setsetdata <GID>,<parameter>,<new value>;
+*setunitdata <GID>,<parameter>,<new value>;
 
 
 This is used to get and set special data related to the unit.
 This is used to get and set special data related to the unit.
 With getunitdata, the array given will be filled with the current data. In setunitdata
 With getunitdata, the array given will be filled with the current data. In setunitdata
@@ -7072,17 +7079,17 @@ the indexes in the array would be used to set that data on the unit.
 
 
 Parameters (indexes) for monsters are:
 Parameters (indexes) for monsters are:
 
 
-	0 - size (big, small, normal)	7  - y							14 - hair style			21 - weapon			28 - DEX
-	1 - level						8  - speed						15 - hair color			22 - shield (again)	29 - LUK
-	2 - HP							9  - mode 						16 - head gear bottom	23 - looking dir	30 - for slave to copy master's mode
-	3 - max HP						10 - special AI state	 		17 - head gear middle	24 - STR			31 - immune from attacks state
-	4 - master AID					11 - SC option					18 - head gear top		25 - AGI
-	5 - map index					12 - sex						19 - cloth color		26 - VIT
-	6 - x							13 - class (Monster ID, Job ID)	20 - shield				27 - INT
+	0 - size (big, small, normal)	7  - y							14 - hair style			21 - weapon			28 - LUK
+	1 - level						8  - speed						15 - hair color			22 - looking dir	29 - for slave to copy master's mode
+	2 - HP							9  - mode 						16 - head gear bottom	23 - STR			30 - immune from attacks state
+	3 - max HP						10 - special AI state	 		17 - head gear middle	24 - AGI
+	4 - master AID					11 - SC option					18 - head gear top		25 - VIT
+	5 - map ID						12 - sex						19 - cloth color		26 - INT
+	6 - x							13 - class (Monster ID, Job ID)	20 - shield				27 - DEX
 
 
 Parameter (indexes) for homunculi are:
 Parameter (indexes) for homunculi are:
 
 
-	0 - size (big, small, normal)	7  - map index		14 - canmove_tick	21 - immune from attacks state
+	0 - size (big, small, normal)	7  - map ID			14 - canmove_tick	21 - immune from attacks state
 	1 - level						8  - x				15 - STR
 	1 - level						8  - x				15 - STR
 	2 - HP							9  - y				16 - AGI
 	2 - HP							9  - y				16 - AGI
 	3 - max HP						10 - hunger			17 - VIT
 	3 - max HP						10 - hunger			17 - VIT
@@ -7097,7 +7104,7 @@ Parameter (indexes) for pets are:
 	2 - HP							9  - intimacy		16 - INT
 	2 - HP							9  - intimacy		16 - INT
 	3 - max HP						10 - speed			17 - DEX
 	3 - max HP						10 - speed			17 - DEX
 	4 - master AID					11 - looking dir	18 - LUK
 	4 - master AID					11 - looking dir	18 - LUK
-	5 - map index					12 - canmove_tick	19 - immune from attacks state
+	5 - map ID						12 - canmove_tick	19 - immune from attacks state
 	6 - x							13 - STR
 	6 - x							13 - STR
 
 
 Parameter (indexes) for mercenaries are:
 Parameter (indexes) for mercenaries are:
@@ -7106,7 +7113,7 @@ Parameter (indexes) for mercenaries are:
 	1 - HP							8  - life time		15 - INT
 	1 - HP							8  - life time		15 - INT
 	2 - max HP						9  - speed 			16 - DEX
 	2 - max HP						9  - speed 			16 - DEX
 	3 - master Character ID			10 - looking dir	17 - LUK
 	3 - master Character ID			10 - looking dir	17 - LUK
-	4 - map index					11 - canmove_tick	18 - immune from attacks state
+	4 - map ID						11 - canmove_tick	18 - immune from attacks state
 	5 - x							12 - STR
 	5 - x							12 - STR
 	6 - y							13 - AGI
 	6 - y							13 - AGI
 
 
@@ -7118,7 +7125,7 @@ Parameter (indexes) for elementals are:
 	3 - SP							10 - mode			17 - INT
 	3 - SP							10 - mode			17 - INT
 	4 - max SP						11 - speed			18 - DEX
 	4 - max SP						11 - speed			18 - DEX
 	5 - master Character ID			12 - looking dir	19 - LUK
 	5 - master Character ID			12 - looking dir	19 - LUK
-	6 - map index					13 - canmove_tick	20 - immune from attacks state
+	6 - map ID						13 - canmove_tick	20 - immune from attacks state
 
 
 Parameter (indexes) for NPCs are:
 Parameter (indexes) for NPCs are:
 
 
@@ -7126,26 +7133,28 @@ Parameter (indexes) for NPCs are:
 	1 - level		8  - STR
 	1 - level		8  - STR
 	2 - HP			9  - AGI
 	2 - HP			9  - AGI
 	3 - max HP		10 - VIT
 	3 - max HP		10 - VIT
-	4 - map index	11 - INT
+	4 - map ID		11 - INT
 	5 - x			12 - DEX
 	5 - x			12 - DEX
 	6 - y			13 - LUK
 	6 - y			13 - LUK
 
 
-*Note: For mode, see doc/mob_db_mode_list.txt
+*Notes: For mode, see doc/mob_db_mode_list.txt
+	    For map ID, this refers to the map_data index (from src/map/map.c), not the mapindex_db index (from src/common/mapindex.c)
+	    For 'setunitdata', map name can also be passed in as a valid value instead of map ID
 
 
 Example:
 Example:
 	// Spawn some Porings and save the Game ID.
 	// Spawn some Porings and save the Game ID.
 	// - Keep in mind, when the 'monster' script command is used,
 	// - Keep in mind, when the 'monster' script command is used,
 	// - all the spawned monster GID's are stored in an array
 	// - all the spawned monster GID's are stored in an array
 	// - called $@mobid[].
 	// - called $@mobid[].
-	monster "prontera",123,42,"Poring",1002,10;
+	monster "prontera",149,190,"Poring",1002,10;
 	.GID = $@mobid[9]; // Store and modify the 10th Poring spawned to make him stronger!
 	.GID = $@mobid[9]; // Store and modify the 10th Poring spawned to make him stronger!
 
 
 	// Save the strong Poring's mob data in the @por_arr[] variable. (@por_arr[1] being level, @por_arr[13] being class, etc.)
 	// Save the strong Poring's mob data in the @por_arr[] variable. (@por_arr[1] being level, @por_arr[13] being class, etc.)
+	// With this data we can have the NPC display or manipulate it how we want. This does not have to be ran before 'setunitdata'.
 	getunitdata .GID,@por_arr;
 	getunitdata .GID,@por_arr;
 
 
-	// Set the max HP of the Poring to 1000 and update the current HP to match.
+	// Set the max HP of the Poring to 1000 (current HP will also get updated to 1000).
 	setunitdata .GID,3,1000;
 	setunitdata .GID,3,1000;
-	setunitdata .GID,2,1000;
 
 
 ---------------------------------------
 ---------------------------------------
 \\
 \\

+ 147 - 119
src/map/script.c

@@ -13904,7 +13904,7 @@ BUILDIN_FUNC(getsavepoint)
 }
 }
 
 
 /*==========================================
 /*==========================================
-  * Get position for  char/npc/pet/mob objects. Added by Lorky
+  * Get position for  char/NPC/pet/hom/merc/elem objects. Added by Lorky
   *
   *
   *     int getMapXY(MapName$,MapX,MapY,type,[CharName$]);
   *     int getMapXY(MapName$,MapX,MapY,type,[CharName$]);
   *             where type:
   *             where type:
@@ -13915,7 +13915,7 @@ BUILDIN_FUNC(getsavepoint)
   *                                0 - Character coord
   *                                0 - Character coord
   *                                1 - NPC coord
   *                                1 - NPC coord
   *                                2 - Pet coord
   *                                2 - Pet coord
-  *                                3 - Mob coord (not released)
+  *                                3 - Mob coord (see 'getunitdata')
   *                                4 - Homun coord
   *                                4 - Homun coord
   *                                5 - Mercenary coord
   *                                5 - Mercenary coord
   *                                6 - Elemental coord
   *                                6 - Elemental coord
@@ -13986,7 +13986,7 @@ BUILDIN_FUNC(getmapxy)
 				bl = &sd->pd->bl;
 				bl = &sd->pd->bl;
 			break;
 			break;
 		case 3:	//Get Mob Position
 		case 3:	//Get Mob Position
-			break; //Not supported?
+			break; //see 'getunitdata'
 		case 4:	//Get Homun Position
 		case 4:	//Get Homun Position
 			if(script_hasdata(st,6))
 			if(script_hasdata(st,6))
 				sd=map_nick2sd(script_getstr(st,6));
 				sd=map_nick2sd(script_getstr(st,6));
@@ -14066,6 +14066,23 @@ BUILDIN_FUNC(getmapxy)
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 
+/// Returns the map name of given map ID.
+///
+/// mapid2name <map ID>;
+BUILDIN_FUNC(mapid2name)
+{
+	uint16 m = script_getnum(st, 2);
+
+	if (m < 0 || m >= MAX_MAP_PER_SERVER) {
+		script_pushstr(st, "");
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	script_pushstrcopy(st, map_mapid2mapname(m));
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
 /*==========================================
 /*==========================================
  * Allows player to write NPC logs (i.e. Bank NPC, etc) [Lupus]
  * Allows player to write NPC logs (i.e. Bank NPC, etc) [Lupus]
  *------------------------------------------*/
  *------------------------------------------*/
@@ -16252,16 +16269,15 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(19,md->vd->cloth_color);
 			getunitdata_sub(19,md->vd->cloth_color);
 			getunitdata_sub(20,md->vd->shield);
 			getunitdata_sub(20,md->vd->shield);
 			getunitdata_sub(21,md->vd->weapon);
 			getunitdata_sub(21,md->vd->weapon);
-			getunitdata_sub(22,md->vd->shield);
-			getunitdata_sub(23,md->ud.dir);
-			getunitdata_sub(24,md->status.str);
-			getunitdata_sub(25,md->status.agi);
-			getunitdata_sub(26,md->status.vit);
-			getunitdata_sub(27,md->status.int_);
-			getunitdata_sub(28,md->status.dex);
-			getunitdata_sub(29,md->status.luk);
-			getunitdata_sub(30,md->state.copy_master_mode);
-			getunitdata_sub(31,md->ud.immune_attack);
+			getunitdata_sub(22,md->ud.dir);
+			getunitdata_sub(23,md->status.str);
+			getunitdata_sub(24,md->status.agi);
+			getunitdata_sub(25,md->status.vit);
+			getunitdata_sub(26,md->status.int_);
+			getunitdata_sub(27,md->status.dex);
+			getunitdata_sub(28,md->status.luk);
+			getunitdata_sub(29,md->state.copy_master_mode);
+			getunitdata_sub(30,md->ud.immune_attack);
 			break;
 			break;
 
 
 		case BL_HOM:
 		case BL_HOM:
@@ -16411,6 +16427,8 @@ BUILDIN_FUNC(getunitdata)
 BUILDIN_FUNC(setunitdata)
 BUILDIN_FUNC(setunitdata)
 {
 {
 	struct block_list* bl = NULL;
 	struct block_list* bl = NULL;
+	struct script_data* data;
+	const char *mapname = NULL;
 	TBL_MOB* md = NULL;
 	TBL_MOB* md = NULL;
 	TBL_HOM* hd = NULL;
 	TBL_HOM* hd = NULL;
 	TBL_MER* mc = NULL;
 	TBL_MER* mc = NULL;
@@ -16436,7 +16454,17 @@ BUILDIN_FUNC(setunitdata)
 	}
 	}
 
 
 	type = script_getnum(st, 3);
 	type = script_getnum(st, 3);
-	value = script_getnum(st, 4);
+	data = script_getdata(st, 4);
+	get_val(st, data);
+
+	if (type == 5 && data_isstring(data))
+		mapname = conv_str(st, data);
+	else if (data_isint(data))
+		value = conv_num(st, data);
+	else {
+		ShowError("buildin_setunitdata: Invalid data type for argument #3 (%d).", data->type);
+		return SCRIPT_CMD_FAILURE;
+	}
 
 
 	switch (bl->type) {
 	switch (bl->type) {
 	case BL_MOB:
 	case BL_MOB:
@@ -16447,36 +16475,35 @@ BUILDIN_FUNC(setunitdata)
 		switch (type) {
 		switch (type) {
 			case 0: md->status.size = (unsigned char)value; break;
 			case 0: md->status.size = (unsigned char)value; break;
 			case 1: md->level = (unsigned short)value; break;
 			case 1: md->level = (unsigned short)value; break;
-			case 2: md->status.hp = (unsigned int)value; break;
-			case 3: md->status.max_hp = (unsigned int)value; break;
+			case 2: status_set_hp(bl, (unsigned int)value, 0); break;
+			case 3: status_set_maxhp(bl, (unsigned int)value, 0); break;
 			case 4: md->master_id = value; break;
 			case 4: md->master_id = value; break;
-			case 5: md->bl.m = (short)value; break;
-			case 6: md->bl.x = (short)value; break;
-			case 7: md->bl.y = (short)value; break;
-			case 8: md->status.speed = (unsigned short)value; break;
-			case 9: md->status.mode = (enum e_mode)value; break;
+			case 5: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, 3); break;
+			case 6: if (!unit_walktoxy(bl, (short)value, md->bl.y, 2)) unit_movepos(bl, (short)value, md->bl.y, 0, 0); break;
+			case 7: if (!unit_walktoxy(bl, md->bl.x, (short)value, 2)) unit_movepos(bl, md->bl.x, (short)value, 0, 0); break;
+			case 8: md->status.speed = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 9: md->status.mode = (enum e_mode)value; status_calc_bl(bl, SCB_MODE); break;
 			case 10: md->special_state.ai = (enum mob_ai)value; break;
 			case 10: md->special_state.ai = (enum mob_ai)value; break;
 			case 11: md->sc.option = (unsigned short)value; break;
 			case 11: md->sc.option = (unsigned short)value; break;
 			case 12: md->vd->sex = (char)value; break;
 			case 12: md->vd->sex = (char)value; break;
-			case 13: md->vd->class_ = (unsigned short)value; break;
-			case 14: md->vd->hair_style = (unsigned short)value; break;
-			case 15: md->vd->hair_color = (unsigned short)value; break;
-			case 16: md->vd->head_bottom = (unsigned short)value; break;
-			case 17: md->vd->head_mid = (unsigned short)value; break;
-			case 18: md->vd->head_top = (unsigned short)value; break;
-			case 19: md->vd->cloth_color = (unsigned short)value; break;
-			case 20: md->vd->shield = (unsigned short)value; break;
-			case 21: md->vd->weapon = (unsigned short)value; break;
-			case 22: md->vd->shield = (unsigned short)value; break;
-			case 23: md->ud.dir = (unsigned char)value; break;
-			case 24: md->status.str = (unsigned int)value; break;
-			case 25: md->status.agi = (unsigned int)value; break;
-			case 26: md->status.vit = (unsigned int)value; break;
-			case 27: md->status.int_ = (unsigned int)value; break;
-			case 28: md->status.dex = (unsigned int)value; break;
-			case 29: md->status.luk = (unsigned int)value; break;
-			case 30: md->state.copy_master_mode = value > 0 ? 1 : 0; break;
-			case 31: md->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
+			case 13: status_set_viewdata(bl, (unsigned short)value); break;
+			case 14: clif_changelook(bl, LOOK_HAIR, (unsigned short)value); break;
+			case 15: clif_changelook(bl, LOOK_HAIR_COLOR, (unsigned short)value); break;
+			case 16: clif_changelook(bl, LOOK_HEAD_BOTTOM, (unsigned short)value); break;
+			case 17: clif_changelook(bl, LOOK_HEAD_MID, (unsigned short)value); break;
+			case 18: clif_changelook(bl, LOOK_HEAD_TOP, (unsigned short)value); break;
+			case 19: clif_changelook(bl, LOOK_CLOTHES_COLOR, (unsigned short)value); break;
+			case 20: clif_changelook(bl, LOOK_SHIELD, (unsigned short)value); break;
+			case 21: clif_changelook(bl, LOOK_WEAPON, (unsigned short)value); break;
+			case 22: unit_setdir(bl, (uint8)value); break;
+			case 23: md->status.str = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 24: md->status.agi = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 25: md->status.vit = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 26: md->status.int_ = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 27: md->status.dex = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 28: md->status.luk = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 29: md->state.copy_master_mode = value > 0 ? 1 : 0; status_calc_bl(bl, SCB_MODE); break;
+			case 30: md->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			default:
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MOB.\n", type);
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MOB.\n", type);
 				return SCRIPT_CMD_FAILURE;
 				return SCRIPT_CMD_FAILURE;
@@ -16491,25 +16518,25 @@ BUILDIN_FUNC(setunitdata)
 		switch (type) {
 		switch (type) {
 			case 0: hd->base_status.size = (unsigned char)value; break;
 			case 0: hd->base_status.size = (unsigned char)value; break;
 			case 1: hd->homunculus.level = (unsigned short)value; break;
 			case 1: hd->homunculus.level = (unsigned short)value; break;
-			case 2: hd->homunculus.hp = (unsigned int)value; break;
-			case 3: hd->homunculus.max_hp = (unsigned int)value; break;
-			case 4: hd->homunculus.sp = (unsigned int)value; break;
-			case 5: hd->homunculus.max_sp = (unsigned int)value; break;
-			case 6: hd->homunculus.char_id = (unsigned int)value; break;
-			case 7: hd->bl.m = (short)value; break;
-			case 8: hd->bl.x = (short)value; break;
-			case 9: hd->bl.y = (short)value; break;
-			case 10: hd->homunculus.hunger = (short)value; break;
-			case 11: hd->homunculus.intimacy = (unsigned int)value; break;
-			case 12: hd->base_status.speed = (unsigned short)value; break;
-			case 13: hd->ud.dir = (unsigned char)value; break;
+			case 2: status_set_hp(bl, (unsigned int)value, 0); break;
+			case 3: status_set_maxhp(bl, (unsigned int)value, 0); break;
+			case 4: status_set_sp(bl, (unsigned int)value, 0); break;
+			case 5: status_set_maxsp(bl, (unsigned int)value, 0); break;
+			case 6: hd->homunculus.char_id = (uint32)value; break;
+			case 7: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, 3); break;
+			case 8: if (!unit_walktoxy(bl, (short)value, hd->bl.y, 2)) unit_movepos(bl, (short)value, hd->bl.y, 0, 0); break;
+			case 9: if (!unit_walktoxy(bl, hd->bl.x, (short)value, 2)) unit_movepos(bl, hd->bl.x, (short)value, 0, 0); break;
+			case 10: hd->homunculus.hunger = (short)value; clif_send_homdata(map_charid2sd(hd->homunculus.char_id), SP_HUNGRY, hd->homunculus.hunger); break;
+			case 11: hom_increase_intimacy(hd, (unsigned int)value); clif_send_homdata(map_charid2sd(hd->homunculus.char_id), SP_INTIMATE, hd->homunculus.intimacy / 100); break;
+			case 12: hd->base_status.speed = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 13: unit_setdir(bl, (uint8)value); break;
 			case 14: hd->ud.canmove_tick = value > 0 ? 1 : 0; break;
 			case 14: hd->ud.canmove_tick = value > 0 ? 1 : 0; break;
-			case 15: hd->base_status.str = (unsigned int)value; break;
-			case 16: hd->base_status.agi = (unsigned int)value; break;
-			case 17: hd->base_status.vit = (unsigned int)value; break;
-			case 18: hd->base_status.int_ = (unsigned int)value; break;
-			case 19: hd->base_status.dex = (unsigned int)value; break;
-			case 20: hd->base_status.luk = (unsigned int)value; break;
+			case 15: hd->base_status.str = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 16: hd->base_status.agi = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 17: hd->base_status.vit = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 18: hd->base_status.int_ = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 19: hd->base_status.dex = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 20: hd->base_status.luk = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
 			case 21: hd->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			case 21: hd->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			default:
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_HOM.\n", type);
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_HOM.\n", type);
@@ -16525,23 +16552,23 @@ BUILDIN_FUNC(setunitdata)
 		switch (type) {
 		switch (type) {
 			case 0: pd->status.size = (unsigned char)value; break;
 			case 0: pd->status.size = (unsigned char)value; break;
 			case 1: pd->pet.level = (unsigned short)value; break;
 			case 1: pd->pet.level = (unsigned short)value; break;
-			case 2: pd->status.hp = (unsigned int)value; break;
-			case 3: pd->status.max_hp = (unsigned int)value; break;
+			case 2: status_set_hp(bl, (unsigned int)value, 0); break;
+			case 3: status_set_maxhp(bl, (unsigned int)value, 0); break;
 			case 4: pd->pet.account_id = (unsigned int)value; break;
 			case 4: pd->pet.account_id = (unsigned int)value; break;
-			case 5: pd->bl.m = (short)value; break;
-			case 6: pd->bl.x = (short)value; break;
-			case 7: pd->bl.y = (short)value; break;
-			case 8: pd->pet.hungry = (short)value; break;
-			case 9: pd->pet.intimate = (unsigned int)value; break;
-			case 10: pd->status.speed = (unsigned short)value; break;
-			case 11: pd->ud.dir = (unsigned char)value; break;
+			case 5: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, 3); break;
+			case 6: if (!unit_walktoxy(bl, (short)value, pd->bl.y, 2)) unit_movepos(bl, (short)value, md->bl.y, 0, 0); break;
+			case 7: if (!unit_walktoxy(bl, pd->bl.x, (short)value, 2)) unit_movepos(bl, pd->bl.x, (short)value, 0, 0); break;
+			case 8: pd->pet.hungry = (short)value; clif_send_petdata(map_id2sd(pd->pet.account_id), pd, 2, pd->pet.hungry); break;
+			case 9: pet_set_intimate(pd, (unsigned int)value); clif_send_petdata(map_id2sd(pd->pet.account_id), pd, 1, pd->pet.intimate); break;
+			case 10: pd->status.speed = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 11: unit_setdir(bl, (uint8)value); break;
 			case 12: pd->ud.canmove_tick = value > 0 ? 1 : 0; break;
 			case 12: pd->ud.canmove_tick = value > 0 ? 1 : 0; break;
-			case 13: pd->status.str = (unsigned int)value; break;
-			case 14: pd->status.agi = (unsigned int)value; break;
-			case 15: pd->status.vit = (unsigned int)value; break;
-			case 16: pd->status.int_ = (unsigned int)value; break;
-			case 17: pd->status.dex = (unsigned int)value; break;
-			case 18: pd->status.luk = (unsigned int)value; break;
+			case 13: pd->status.str = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 14: pd->status.agi = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 15: pd->status.vit = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 16: pd->status.int_ = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 17: pd->status.dex = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 18: pd->status.luk = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
 			case 19: pd->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			case 19: pd->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			default:
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_PET.\n", type);
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_PET.\n", type);
@@ -16556,23 +16583,23 @@ BUILDIN_FUNC(setunitdata)
 		}
 		}
 		switch (type) {
 		switch (type) {
 			case 0: mc->base_status.size = (unsigned char)value; break;
 			case 0: mc->base_status.size = (unsigned char)value; break;
-			case 1: mc->base_status.hp = (unsigned int)value; break;
-			case 2: mc->base_status.max_hp = (unsigned int)value; break;
-			case 3: mc->mercenary.char_id = (unsigned int)value; break;
-			case 4: mc->bl.m = (short)value; break;
-			case 5: mc->bl.x = (short)value; break;
-			case 6: mc->bl.y = (short)value; break;
+			case 1: status_set_hp(bl, (unsigned int)value, 0); break;
+			case 2: status_set_maxhp(bl, (unsigned int)value, 0); break;
+			case 3: mc->mercenary.char_id = (uint32)value; break;
+			case 4: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, 3); break;
+			case 5: if (!unit_walktoxy(bl, (short)value, mc->bl.y, 2)) unit_movepos(bl, (short)value, mc->bl.y, 0, 0); break;
+			case 6: if (!unit_walktoxy(bl, mc->bl.x, (short)value, 2)) unit_movepos(bl, mc->bl.x, (short)value, 0, 0); break;
 			case 7: mc->mercenary.kill_count = (unsigned int)value; break;
 			case 7: mc->mercenary.kill_count = (unsigned int)value; break;
 			case 8: mc->mercenary.life_time = (unsigned int)value; break;
 			case 8: mc->mercenary.life_time = (unsigned int)value; break;
-			case 9: mc->base_status.speed = (unsigned short)value; break;
-			case 10: mc->ud.dir = (unsigned char)value; break;
+			case 9: mc->base_status.speed = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 10: unit_setdir(bl, (uint8)value); break;
 			case 11: mc->ud.canmove_tick = value > 0 ? 1 : 0; break;
 			case 11: mc->ud.canmove_tick = value > 0 ? 1 : 0; break;
-			case 12: mc->base_status.str = (unsigned int)value; break;
-			case 13: mc->base_status.agi = (unsigned int)value; break;
-			case 14: mc->base_status.vit = (unsigned int)value; break;
-			case 15: mc->base_status.int_ = (unsigned int)value; break;
-			case 16: mc->base_status.dex = (unsigned int)value; break;
-			case 17: mc->base_status.luk = (unsigned int)value; break;
+			case 12: mc->base_status.str = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 13: mc->base_status.agi = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 14: mc->base_status.vit = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 15: mc->base_status.int_ = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 16: mc->base_status.dex = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 17: mc->base_status.luk = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
 			case 18: mc->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			case 18: mc->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			default:
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MER.\n", type);
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MER.\n", type);
@@ -16587,25 +16614,25 @@ BUILDIN_FUNC(setunitdata)
 		}
 		}
 		switch (type) {
 		switch (type) {
 			case 0: ed->base_status.size = (unsigned char)value; break;
 			case 0: ed->base_status.size = (unsigned char)value; break;
-			case 1: ed->elemental.hp = (unsigned int)value; break;
-			case 2: ed->elemental.max_hp = (unsigned int)value; break;
-			case 3: ed->elemental.sp = (unsigned int)value; break;
-			case 4: ed->elemental.max_sp = (unsigned int)value; break;
-			case 5: ed->elemental.char_id = (unsigned int)value; break;
-			case 6: ed->bl.m = (short)value; break;
-			case 7: ed->bl.x = (short)value; break;
-			case 8: ed->bl.y = (short)value; break;
+			case 1: status_set_hp(bl, (unsigned int)value, 0); break;
+			case 2: status_set_maxhp(bl, (unsigned int)value, 0); break;
+			case 3: status_set_sp(bl, (unsigned int)value, 0); break;
+			case 4: status_set_maxsp(bl, (unsigned int)value, 0); break;
+			case 5: ed->elemental.char_id = (uint32)value; break;
+			case 6: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, 3); break;
+			case 7: if (!unit_walktoxy(bl, (short)value, ed->bl.y, 2)) unit_movepos(bl, (short)value, ed->bl.y, 0, 0); break;
+			case 8: if (!unit_walktoxy(bl, ed->bl.x, (short)value, 2)) unit_movepos(bl, ed->bl.x, (short)value, 0, 0); break;
 			case 9: ed->elemental.life_time = (unsigned int)value; break;
 			case 9: ed->elemental.life_time = (unsigned int)value; break;
-			case 10: ed->elemental.mode = (unsigned int)value; break;
-			case 11: ed->base_status.speed = (unsigned short)value; break;
-			case 12: ed->ud.dir = (unsigned char)value; break;
+			case 10: ed->elemental.mode = (unsigned int)value; status_calc_bl(bl, SCB_MODE); break;
+			case 11: ed->base_status.speed = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 12: unit_setdir(bl, (uint8)value); break;
 			case 13: ed->ud.canmove_tick = value > 0 ? 1 : 0; break;
 			case 13: ed->ud.canmove_tick = value > 0 ? 1 : 0; break;
-			case 14: ed->base_status.str = (unsigned int)value; break;
-			case 15: ed->base_status.agi = (unsigned int)value; break;
-			case 16: ed->base_status.vit = (unsigned int)value; break;
-			case 17: ed->base_status.int_ = (unsigned int)value; break;
-			case 18: ed->base_status.dex = (unsigned int)value; break;
-			case 19: ed->base_status.luk = (unsigned int)value; break;
+			case 14: ed->base_status.str = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 15: ed->base_status.agi = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 16: ed->base_status.vit = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 17: ed->base_status.int_ = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 18: ed->base_status.dex = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 19: ed->base_status.luk = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
 			case 20: ed->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			case 20: ed->ud.immune_attack = (bool)value > 0 ? 1 : 0; break;
 			default:
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_ELEM.\n", type);
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_ELEM.\n", type);
@@ -16619,20 +16646,20 @@ BUILDIN_FUNC(setunitdata)
 			return SCRIPT_CMD_FAILURE;
 			return SCRIPT_CMD_FAILURE;
 		}
 		}
 		switch (type) {
 		switch (type) {
-			case 0: nd->class_ = (unsigned int)value; break;
+			case 0: status_set_viewdata(bl, (unsigned short)value); break;
 			case 1: nd->level = (unsigned int)value; break;
 			case 1: nd->level = (unsigned int)value; break;
-			case 2: nd->status.hp = (unsigned int)value; break;
-			case 3: nd->status.max_hp = (unsigned int)value; break;
-			case 4: nd->bl.m = (short)value; break;
-			case 5: nd->bl.x = (short)value; break;
-			case 6: nd->bl.y = (short)value; break;
-			case 7: nd->ud.dir = (unsigned char)value; break;
-			case 8: nd->status.str = (unsigned int)value; break;
-			case 9: nd->status.agi = (unsigned int)value; break;
-			case 10: nd->status.vit = (unsigned int)value; break;
-			case 11: nd->status.int_ = (unsigned int)value; break;
-			case 12: nd->status.dex = (unsigned int)value; break;
-			case 13: nd->status.luk = (unsigned int)value; break;
+			case 2: status_set_hp(bl, (unsigned int)value, 0); break;
+			case 3: status_set_maxhp(bl, (unsigned int)value, 0); break;
+			case 4: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, 3); break;
+			case 5: if (!unit_walktoxy(bl, (short)value, nd->bl.y, 2)) unit_movepos(bl, (short)value, nd->bl.x, 0, 0); break;
+			case 6: if (!unit_walktoxy(bl, nd->bl.x, (short)value, 2)) unit_movepos(bl, nd->bl.x, (short)value, 0, 0); break;
+			case 7: unit_setdir(bl, (uint8)value); break;
+			case 8: nd->status.str = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 9: nd->status.agi = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 10: nd->status.vit = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 11: nd->status.int_ = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 12: nd->status.dex = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
+			case 13: nd->status.luk = (unsigned short)value; status_calc_bl(bl, SCB_ALL); break;
 			default:
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_NPC.\n", type);
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_NPC.\n", type);
 				return SCRIPT_CMD_FAILURE;
 				return SCRIPT_CMD_FAILURE;
@@ -16938,7 +16965,7 @@ BUILDIN_FUNC(unittalk)
 ///
 ///
 /// unitemote <unit_id>,<emotion>;
 /// unitemote <unit_id>,<emotion>;
 ///
 ///
-/// @see e_* in const.txt
+/// @see e_* in db/const.txt
 BUILDIN_FUNC(unitemote)
 BUILDIN_FUNC(unitemote)
 {
 {
 	int unit_id;
 	int unit_id;
@@ -17008,7 +17035,7 @@ BUILDIN_FUNC(unitskillusepos)
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 
-// <--- [zBuffer] List of mob control commands
+// <--- [zBuffer] List of unit control commands
 
 
 /// Pauses the execution of the script, detaching the player
 /// Pauses the execution of the script, detaching the player
 ///
 ///
@@ -20085,6 +20112,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(npcwalkto,"ii"), // [Valaris]
 	BUILDIN_DEF(npcwalkto,"ii"), // [Valaris]
 	BUILDIN_DEF(npcstop,""), // [Valaris]
 	BUILDIN_DEF(npcstop,""), // [Valaris]
 	BUILDIN_DEF(getmapxy,"rrri?"),	//by Lorky [Lupus]
 	BUILDIN_DEF(getmapxy,"rrri?"),	//by Lorky [Lupus]
+	BUILDIN_DEF(mapid2name,"i"),
 	BUILDIN_DEF(checkoption1,"i"),
 	BUILDIN_DEF(checkoption1,"i"),
 	BUILDIN_DEF(checkoption2,"i"),
 	BUILDIN_DEF(checkoption2,"i"),
 	BUILDIN_DEF(guildgetexp,"i"),
 	BUILDIN_DEF(guildgetexp,"i"),

+ 54 - 2
src/map/status.c

@@ -1275,8 +1275,8 @@ static inline void status_cpy(struct status_data* a, const struct status_data* b
 
 
 /**
 /**
  * Sets HP to a given value
  * Sets HP to a given value
- * Will always succeed (overrides heal impedement statuses) but can't kill an object
- * @param bl: Object whose HP will be set [PC|MOB|HOM|MER|ELEM]
+ * Will always succeed (overrides heal impediment statuses) but can't kill an object
+ * @param bl: Object whose HP will be set [PC|MOB|HOM|MER|ELEM|NPC]
  * @param hp: What the HP is to be set as
  * @param hp: What the HP is to be set as
  * @param flag: Used in case final value is higher than current
  * @param flag: Used in case final value is higher than current
  *		Use 2 to display healing effect
  *		Use 2 to display healing effect
@@ -1297,6 +1297,32 @@ int status_set_hp(struct block_list *bl, unsigned int hp, int flag)
 	return status_zap(bl, status->hp - hp, 0);
 	return status_zap(bl, status->hp - hp, 0);
 }
 }
 
 
+/**
+ * Sets Max HP to a given value
+ * @param bl: Object whose Max HP will be set [PC|MOB|HOM|MER|ELEM|NPC]
+ * @param maxhp: What the Max HP is to be set as
+ * @param flag: Used in case final value is higher than current
+ *		Use 2 to display healing effect
+ * @return heal or zapped HP if valid
+ */
+int status_set_maxhp(struct block_list *bl, unsigned int maxhp, int flag)
+{
+	struct status_data *status;
+	if (maxhp < 1) return 0;
+	status = status_get_status_data(bl);
+	if (status == &dummy_status)
+		return 0;
+
+	if (maxhp == status->max_hp) return 0;
+	if (maxhp > status->max_hp) {
+		status_heal(bl, maxhp - status->max_hp, 0, 1|flag);
+	} else
+		status_zap(bl, status->max_hp - maxhp, 0);
+
+	status->max_hp = maxhp;
+	return maxhp;
+}
+
 /**
 /**
  * Sets SP to a given value
  * Sets SP to a given value
  * @param bl: Object whose SP will be set [PC|HOM|MER|ELEM]
  * @param bl: Object whose SP will be set [PC|HOM|MER|ELEM]
@@ -1320,6 +1346,32 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag)
 	return status_zap(bl, 0, status->sp - sp);
 	return status_zap(bl, 0, status->sp - sp);
 }
 }
 
 
+/**
+ * Sets Max SP to a given value
+ * @param bl: Object whose Max SP will be set [PC|HOM|MER|ELEM]
+ * @param maxsp: What the Max SP is to be set as
+ * @param flag: Used in case final value is higher than current
+ *		Use 2 to display healing effect
+ * @return heal or zapped HP if valid
+ */
+int status_set_maxsp(struct block_list *bl, unsigned int maxsp, int flag)
+{
+	struct status_data *status;
+	if (maxsp < 1) return 0;
+	status = status_get_status_data(bl);
+	if (status == &dummy_status)
+		return 0;
+
+	if (maxsp == status->max_sp) return 0;
+	if (maxsp > status->max_sp) {
+		status_heal(bl, maxsp - status->max_sp, 0, 1|flag);
+	} else
+		status_zap(bl, status->max_sp - maxsp, 0);
+
+	status->max_sp = maxsp;
+	return maxsp;
+}
+
 /**
 /**
  * Takes HP/SP from an Object
  * Takes HP/SP from an Object
  * @param bl: Object who will have HP/SP taken [PC|MOB|HOM|MER|ELEM]
  * @param bl: Object who will have HP/SP taken [PC|MOB|HOM|MER|ELEM]

+ 2 - 0
src/map/status.h

@@ -2003,7 +2003,9 @@ int status_percent_change(struct block_list *src, struct block_list *target, int
 #define status_kill(bl) status_percent_damage(NULL, bl, 100, 0, true)
 #define status_kill(bl) status_percent_damage(NULL, bl, 100, 0, true)
 //Used to set the hp/sp of an object to an absolute value (can't kill)
 //Used to set the hp/sp of an object to an absolute value (can't kill)
 int status_set_hp(struct block_list *bl, unsigned int hp, int flag);
 int status_set_hp(struct block_list *bl, unsigned int hp, int flag);
+int status_set_maxhp(struct block_list *bl, unsigned int hp, int flag);
 int status_set_sp(struct block_list *bl, unsigned int sp, int flag);
 int status_set_sp(struct block_list *bl, unsigned int sp, int flag);
+int status_set_maxsp(struct block_list *bl, unsigned int hp, int flag);
 int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag);
 int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag);
 int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
 int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp);