Explorar o código

- Fixed getmonsterinfo to return "null" when returning the name of a non-existing mob instead of -1.
- Extended the status_percent_damage define to include a bolean to specify whether or not the target can be killed from it.
- Corrected CR_CULTIVATION to fail when the target cell has some BL_CHAR on it already.
- Changed the meaning of 'flag' in status_percent_change, to enable differentiation between damage that can kill the object and damage that cannot.
- Script command percentheal will no longer kill the player if the specified amount is negative (and not -100).


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12051 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex %!s(int64=17) %!d(string=hai) anos
pai
achega
ced9aada8c
Modificáronse 9 ficheiros con 45 adicións e 28 borrados
  1. 6 0
      Changelog-Trunk.txt
  2. 2 2
      doc/script_commands.txt
  3. 1 1
      src/map/battle.c
  4. 1 1
      src/map/clif.c
  5. 4 4
      src/map/pc.c
  6. 4 1
      src/map/script.c
  7. 12 9
      src/map/skill.c
  8. 12 7
      src/map/status.c
  9. 3 3
      src/map/status.h

+ 6 - 0
Changelog-Trunk.txt

@@ -4,6 +4,12 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2008/01/10
+	* Fixed getmonsterinfo to return "null" when returning the name of a
+	  non-existing mob instead of -1.
+	* Corrected CR_CULTIVATION to fail when the target cell has some BL_CHAR on
+	  it already.
+	* Script command percentheal will no longer kill the player if the
+	  specified amount is negative (and not -100).
 	* Fixed Abracadabra unable to cast non-targeted skills (bugreport:186)
 	* Another round of login server cleaning [ultramage]
 	- fixed passwordencrypt on SQL not behaving correctly (since r10753)

+ 2 - 2
doc/script_commands.txt

@@ -2839,8 +2839,8 @@ set @i, petstat(PET_CLASS);
 
 This function will look up the monster with the specified ID number in the
 mob database and return the info set by TYPE argument.
-It will return -1 if there is no such item. Due to specific of MOB DB routines,
-it's better to check monster name. It'd return "Dummy" for a non-existing mob.
+It will return -1 if there is no such monster (or the type value is invalid),
+or "null" if you requested the monster's name.
 
 Valid types are listed in const.txt:
 	MOB_NAME	0		MOB_LV	1

+ 1 - 1
src/map/battle.c

@@ -2724,7 +2724,7 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage,
 	}
 
 	if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate)
-		status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per);
+		status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false);
 	if (!thp && !tsp) return;
 
 	status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);

+ 1 - 1
src/map/clif.c

@@ -10238,7 +10238,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
 		break;
 	}
 	case BL_MOB:
-		status_percent_damage(&sd->bl, target, 100, 0);
+		status_percent_damage(&sd->bl, target, 100, 0, true);
 		if(log_config.gm && lv >= log_config.gm) {
 			char message[NAME_LENGTH+16];
 			sprintf(message, "/kick %s (%d)", status_get_name(target), status_get_class(target));

+ 4 - 4
src/map/pc.c

@@ -5494,22 +5494,22 @@ int pc_percentheal(struct map_session_data *sd,int hp,int sp)
 	if(hp >= 0 && sp >= 0) //Heal
 		return status_percent_heal(&sd->bl, hp, sp);
 
-	if(hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current)
-		return status_percent_damage(NULL, &sd->bl, hp, sp);
+	if(hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current), and only kill target IF the specified amount is 100%
+		return status_percent_damage(NULL, &sd->bl, hp, sp, hp==-100);
 
 	//Crossed signs
 	if(hp) {
 		if(hp > 0)
 			status_percent_heal(&sd->bl, hp, 0);
 		else
-			status_percent_damage(NULL, &sd->bl, hp, 0);
+			status_percent_damage(NULL, &sd->bl, hp, 0, hp==-100);
 	}
 	
 	if(sp) {
 		if(sp > 0)
 			status_percent_heal(&sd->bl, 0, sp);
 		else
-			status_percent_damage(NULL, &sd->bl, 0, sp);
+			status_percent_damage(NULL, &sd->bl, 0, sp, false);
 	}
 	return 0;
 }

+ 4 - 1
src/map/script.c

@@ -12104,7 +12104,10 @@ BUILDIN_FUNC(getmonsterinfo)
 	mob_id	= script_getnum(st,2);
 	if (!mobdb_checkid(mob_id)) {
 		ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i", mob_id);
-		script_pushint(st,-1);
+		if ( !script_getnum(st,3) ) //requested a string
+			script_pushconststr(st,"null");
+		else
+			script_pushint(st,-1);
 		return -1;
 	}
 	mob = mob_db(mob_id);

+ 12 - 9
src/map/skill.c

@@ -561,7 +561,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		break;
 
 	case HT_SHOCKWAVE:
-		status_percent_damage(src, bl, 0, 15*skilllv+5);
+		status_percent_damage(src, bl, 0, 15*skilllv+5, false);
 		break;
 
 	case HT_SANDMAN:
@@ -603,7 +603,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		break;
 
 	case PA_PRESSURE:
-		status_percent_damage(src, bl, 0, 15+5*skilllv);
+		status_percent_damage(src, bl, 0, 15+5*skilllv, false);
 		break;
 
 	case RG_RAID:
@@ -2710,12 +2710,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
 			if (skilllv == 5)
 				skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
-			status_percent_damage(src, bl, 0, 100);
+			status_percent_damage(src, bl, 0, 100, false);
 		} else {
 			clif_skill_nodamage(src,src,skillid,skilllv,1);
 			if (skilllv == 5)
 				skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,flag);
-			status_percent_damage(src, src, 0, 100);
+			status_percent_damage(src, src, 0, 100, false);
 		}		
 		if (sd) skill_blockpc_start (sd, skillid, (skilllv < 5 ? 10000: 15000));
 		break;
@@ -4261,7 +4261,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				if(sp < 1) sp = 1;
 				status_heal(bl,0,sp,2);
 				clif_skill_nodamage(bl,bl,SA_MAGICROD,tsc->data[SC_MAGICROD]->val1,1);
-				status_percent_damage(bl, src, 0, -20); //20% max SP damage.
+				status_percent_damage(bl, src, 0, -20, false); //20% max SP damage.
 			} else {
 				struct unit_data *ud = unit_bl2ud(bl);
 				int bl_skillid=0,bl_skilllv=0,hp = 0;
@@ -4787,7 +4787,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				switch (eff)
 				{
 				case 0:	// heals SP to 0
-					status_percent_damage(src, bl, 0, 100);
+					status_percent_damage(src, bl, 0, 100, false);
 					break;
 				case 1:	// matk halved
 					sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv));
@@ -5815,14 +5815,17 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			int i = skilllv - 1;
 			int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
 			if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL ||
-				sd->status.inventory[j].amount < skill_db[skillid].amount[i]) {
+				sd->status.inventory[j].amount < skill_db[skillid].amount[i] ||
+				map_count_oncell(src->m,x,y,BL_CHAR) > 0
+			) {
 				clif_skill_fail(sd,skillid,0,0);
 				return 1;
 			}
+
 			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, sd->bl.m, x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6), 1, "");
+				mob_once_spawn(sd, src->m, x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6), 1, "");
 			else
 				clif_skill_fail(sd,skillid,0,0);
 		}
@@ -10263,7 +10266,7 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
 	} else {
 		switch (skill_id) {
 			case ASC_CDP: //25% Damage yourself, and display same effect as failed potion.
-				status_percent_damage(NULL, &sd->bl, -25, 0);
+				status_percent_damage(NULL, &sd->bl, -25, 0, true);
 			case AM_PHARMACY:
 			case AM_TWILIGHT1:
 			case AM_TWILIGHT2:

+ 12 - 7
src/map/status.c

@@ -851,7 +851,8 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
 //no exp/drops will be awarded if there is no src (or src is target)
 //If rates are > 0, percent is of current HP/SP
 //If rates are < 0, percent is of max HP/SP
-//If flag, this is heal, otherwise it is damage.
+//If !flag, this is heal, otherwise it is damage.
+//Furthermore, if flag==2, then the target must not die from the substraction.
 int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag)
 {
 	struct status_data *status;
@@ -878,6 +879,9 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
 	if (hp_rate && !hp)
 		hp = 1;
 
+	if (flag == 2 && hp >= status->hp)
+		hp = status->hp-1; //Must not kill target.
+
 	//Should be safe to not do overflow protection here, noone should have
 	//millions upon millions of SP
 	if (sp_rate > 99)
@@ -896,19 +900,20 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
 	if (hp > INT_MAX) {
 	  	hp -= INT_MAX;
 		if (flag)
-		  	status_heal(target, INT_MAX, 0, 0);
-		else
 			status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
+		else
+		  	status_heal(target, INT_MAX, 0, 0);
 	}
   	if (sp > INT_MAX) {
 		sp -= INT_MAX;
 		if (flag)
-		  	status_heal(target, 0, INT_MAX, 0);
-		else
 			status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
+		else
+		  	status_heal(target, 0, INT_MAX, 0);
 	}	
-	if (flag) return status_heal(target, hp, sp, 0);
-	return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1));
+	if (flag)
+		return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1));
+	return status_heal(target, hp, sp, 0);
 }
 
 int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp)

+ 3 - 3
src/map/status.h

@@ -588,10 +588,10 @@ int status_damage(struct block_list *src,struct block_list *target,int hp,int sp
 int status_charge(struct block_list* bl, int hp, int sp);
 int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
 //Easier handling of status_percent_change
-#define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 1)
-#define status_percent_damage(src, target, hp_rate, sp_rate) status_percent_change(src, target, hp_rate, sp_rate, 0)
+#define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 0)
+#define status_percent_damage(src, target, hp_rate, sp_rate, kill) status_percent_change(src, target, hp_rate, sp_rate, (kill)?1:2)
 //Instant kill with no drops/exp/etc
-#define status_kill(bl) status_percent_damage(NULL, bl, 100, 0)
+#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)
 int status_set_hp(struct block_list *bl, unsigned int hp, int flag);
 int status_set_sp(struct block_list *bl, unsigned int sp, int flag);