summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/script.c17
-rw-r--r--src/map/skill.c5
-rw-r--r--src/map/status.c44
-rw-r--r--src/map/status.h3
4 files changed, 61 insertions, 8 deletions
diff --git a/src/map/script.c b/src/map/script.c
index cf1ae0c17..1571d7d5d 100644
--- a/src/map/script.c
+++ b/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);
diff --git a/src/map/skill.c b/src/map/skill.c
index 3749ce6d2..266e1201c 100644
--- a/src/map/skill.c
+++ b/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;
diff --git a/src/map/status.c b/src/map/status.c
index 39034a9b7..971bc3f88 100644
--- a/src/map/status.c
+++ b/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;
diff --git a/src/map/status.h b/src/map/status.h
index d41e08b25..a15a6c0d7 100644
--- a/src/map/status.h
+++ b/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);