Jelajahi Sumber

- Now when you set the guardian's HP, if the guardian is spawned, it's HP will be updated accordingly (and if you set it to 0, the guardian is killed)
- Added functions status_set_hp/status_set_sp to set hp/sp to a given value. Applied usage of these on the Berserk and Soul Change code.


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

skotlex 19 tahun lalu
induk
melakukan
932107f772
5 mengubah file dengan 67 tambahan dan 8 penghapusan
  1. 6 0
      Changelog-Trunk.txt
  2. 16 1
      src/map/script.c
  3. 2 3
      src/map/skill.c
  4. 40 4
      src/map/status.c
  5. 3 0
      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.
 
 2006/07/27
+	* Now when you set the guardian's HP, if the guardian is spawned, it's HP
+	  will be updated accordingly (and if you set it to 0, the guardian is
+	  killed) [Skotlex]
+	* Added functions status_set_hp/status_set_sp to set hp/sp to a given
+	  value. Applied usage of these on the Berserk and Soul Change code.
+	  [Skotlex]
 	* Added config setting "party_hp_mode" (battle/party.conf) which determines
 	  method to use to update party-mate hp bars. Aegis style is to update HP
 	  bars whenever HP changes, while eAthena style is to update it together with

+ 16 - 1
src/map/script.c

@@ -7553,7 +7553,22 @@ int buildin_setcastledata(struct script_state *st)
 				case 23:
 				case 24:
 				case 25:
-					gc->guardian[index-18].hp = value; break;
+					gc->guardian[index-18].hp = value;
+					if (gc->guardian[index-18].id)
+				  	{	//Update this mob's HP.
+						struct block_list *bl = map_id2bl(gc->guardian[index-18].id);
+						if (!bl)
+					  	{	//Wrong target?
+							gc->guardian[index-18].id = 0;
+							break;
+						}
+						if (value < 1) {
+							status_kill(bl);
+							break;
+						}
+						status_set_hp(bl, value, 0);
+					}
+					break;
 				default: return 0;
 				}
 				guild_castledatasave(gc->castle_id,index,value);

+ 2 - 3
src/map/skill.c

@@ -5200,9 +5200,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			}
 			sp1 = sstatus->sp;
 			sp2 = tstatus->sp;
-			//TODO: Will this work correctly once sp1/sp2 go above INT_MAX?
-			status_heal(src, 0, (signed int)(sp2-sp1), 3);
-			status_heal(bl, 0, (signed int)(sp1-sp2), 3);
+			status_set_sp(src, sp2, 3);
+			status_set_sp(bl, sp1, 3);
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		}
 		break;

+ 40 - 4
src/map/status.c

@@ -495,6 +495,42 @@ int status_getrefinebonus(int lv,int type)
 	return 0;
 }
 
+//Sets HP to given value. Flag is the flag passed to status_heal in case
+//final value is higher than current (use 2 to make a healing effect display 
+//on players) It will always succeed (overrides Berserk block), but it can't kill.
+int status_set_hp(struct block_list *bl, unsigned int hp, int flag)
+{
+	struct status_data *status;
+	if (hp < 1) return 0;
+	status = status_get_status_data(bl);
+	if (status == &dummy_status)
+		return 0;
+
+	if (hp > status->max_hp) hp = status->max_hp;
+	if (hp == status->hp) return 0;
+	if (hp > status->hp)
+		return status_heal(bl, hp - status->hp, 0, 1|flag);
+	return status_zap(bl, status->hp - hp, 0);
+}
+
+//Sets SP to given value. Flag is the flag passed to status_heal in case
+//final value is higher than current (use 2 to make a healing effect display 
+//on players)
+int status_set_sp(struct block_list *bl, unsigned int sp, int flag)
+{
+	struct status_data *status;
+	
+	status = status_get_status_data(bl);
+	if (status == &dummy_status)
+		return 0;
+
+	if (sp > status->max_sp) sp = status->max_sp;
+	if (sp == status->sp) return 0;
+	if (sp > status->sp)
+		return status_heal(bl, 0, sp - status->sp, 1|flag);
+	return status_zap(bl, 0, status->sp - sp);
+}
+
 //Inflicts damage on the target with the according walkdelay.
 //If flag&1, damage is passive and does not triggers cancelling status changes.
 //If flag&2, fail if target does not has enough to substract.
@@ -504,8 +540,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 	struct status_data *status;
 	struct status_change *sc;
 
-	if(sp && target->type != BL_PC && target->type != BL_HOMUNCULUS)	//[orn]
-		sp = 0; //Only players and Homunculus get SP damage.
+	if(sp && !(target->type&BL_CONSUME))
+		sp = 0; //Not a valid SP target.
 	
 	if (hp < 0) { //Assume absorbed damage.
 		status_heal(target, -hp, 0, 1);
@@ -5548,7 +5584,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 	if (type==SC_BERSERK) {
 		sc->data[type].val2 = 5*status->max_hp/100;
 		status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
-		status_percent_damage(NULL, bl, 0, 100); //Damage all SP
+		status_set_sp(bl, 0, 0); //Damage all SP
 	}
 
 	if (type==SC_RUN) {
@@ -5822,7 +5858,7 @@ int status_change_end( struct block_list* bl , int type,int tid )
 		case SC_BERSERK:
 			//If val2 is removed, no HP penalty (dispelled?) [Skotlex]
 			if(status->hp > 100 && sc->data[type].val2)
-				status_zap(bl, status->hp-100, 0); 
+				status_set_hp(bl, 100, 0); 
 			if(sc->data[SC_ENDURE].timer != -1)
 				status_change_end(bl, SC_ENDURE, -1);
 			break;

+ 3 - 0
src/map/status.h

@@ -532,6 +532,9 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
 //Instant kill with no drops/exp/etc
 //
 #define status_kill(bl) status_percent_damage(NULL, bl, 100, 0)
+//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);
 int status_heal(struct block_list *bl,int hp,int sp, int flag);
 int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp);