diff options
author | shennetsind <ind@henn.et> | 2013-08-22 16:59:09 -0300 |
---|---|---|
committer | shennetsind <ind@henn.et> | 2013-08-22 16:59:09 -0300 |
commit | 7f9f6e1b84061a7d393debf37395c8b4a2667db1 (patch) | |
tree | 8bc09c3f8bc0ca5f7fa0ecaed9f3fa42829f67b5 /src/map/status.c | |
parent | 02251a52a5f62122a54434399638dd7f66ea67d4 (diff) | |
download | hercules-7f9f6e1b84061a7d393debf37395c8b4a2667db1.tar.gz hercules-7f9f6e1b84061a7d393debf37395c8b4a2667db1.tar.bz2 hercules-7f9f6e1b84061a7d393debf37395c8b4a2667db1.tar.xz hercules-7f9f6e1b84061a7d393debf37395c8b4a2667db1.zip |
Fixed Bug #7652
damage storage has been changed from int32 to int64 within areas where it could otherwise modified beyond the limit and get screwed up, this solves all related problems within any skills, not only asura.
http://hercules.ws/board/tracker/issue-7652-asura-strike-overdamage/
Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 73 |
1 files changed, 40 insertions, 33 deletions
diff --git a/src/map/status.c b/src/map/status.c index e7c3eaece..c79fff44e 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1120,10 +1120,10 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag) return status_zap(bl, 0, status->sp - sp); } -int status_charge(struct block_list* bl, int hp, int sp) +int status_charge(struct block_list* bl, int64 hp, int64 sp) { if(!(bl->type&BL_CONSUME)) - return hp+sp; //Assume all was charged so there are no 'not enough' fails. + return (int)(hp+sp); //Assume all was charged so there are no 'not enough' fails. return iStatus->damage(NULL, bl, hp, sp, 0, 3); } @@ -1132,11 +1132,14 @@ int status_charge(struct block_list* bl, int hp, int sp) //If flag&2, fail if target does not has enough to substract. //If flag&4, if killed, mob must not give exp/loot. //flag will be set to &8 when damaging sp of a dead character -int status_damage(struct block_list *src,struct block_list *target,int hp, int sp, int walkdelay, int flag) -{ +int status_damage(struct block_list *src,struct block_list *target,int64 hp, int64 sp, int walkdelay, int flag) { struct status_data *status; struct status_change *sc; + /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */ + hp = cap_value(hp,INT_MIN,INT_MAX); + sp = cap_value(sp,INT_MIN,INT_MAX); + if(sp && !(target->type&BL_CONSUME)) sp = 0; //Not a valid SP target. @@ -1254,7 +1257,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s { //Still lives or has been dead before this damage. if (walkdelay) unit_set_walkdelay(target, iTimer->gettick(), walkdelay, 0); - return hp+sp; + return (int)(hp+sp); } status->hp = 1; //To let the dead function cast skills and all that. @@ -1275,7 +1278,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s } if(!flag) //Death cancelled. - return hp+sp; + return (int)(hp+sp); //Normal death status->hp = 0; @@ -1310,7 +1313,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if( target->type == BL_MOB ) ((TBL_MOB*)target)->state.rebirth = 1; - return hp+sp; + return (int)(hp+sp); } if(target->type == BL_PC){ TBL_PC *sd = BL_CAST(BL_PC,target); @@ -1319,7 +1322,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s clif->skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill->get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage clif->skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, iStatus->revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); - return hp + sp; + return (int)(hp + sp); } } if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {// Ensure the monster has not already rebirthed before doing so. @@ -1327,32 +1330,30 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s iStatus->change_clear(target,0); ((TBL_MOB*)target)->state.rebirth = 1; - return hp+sp; + return (int)(hp+sp); } iStatus->change_clear(target,0); if(flag&4) //Delete from memory. (also invokes map removal code) unit_free(target,CLR_DEAD); - else - if(flag&2) //remove from map - unit_remove_map(target,CLR_DEAD); - else - { //Some death states that would normally be handled by unit_remove_map - unit_stop_attack(target); - unit_stop_walking(target,1); - unit_skillcastcancel(target,0); - clif->clearunit_area(target,CLR_DEAD); - skill->unit_move(target,iTimer->gettick(),4); - skill->cleartimerskill(target); - } - - return hp+sp; + else if(flag&2) //remove from map + unit_remove_map(target,CLR_DEAD); + else { //Some death states that would normally be handled by unit_remove_map + unit_stop_attack(target); + unit_stop_walking(target,1); + unit_skillcastcancel(target,0); + clif->clearunit_area(target,CLR_DEAD); + skill->unit_move(target,iTimer->gettick(),4); + skill->cleartimerskill(target); + } + + return (int)(hp+sp); } //Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it) //If flag&2, when the player is healed, show the HP/SP heal effect. -int status_heal(struct block_list *bl,int hp,int sp, int flag) +int status_heal(struct block_list *bl,int64 hp,int64 sp, int flag) { struct status_data *status; struct status_change *sc; @@ -1362,6 +1363,10 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) if (status == &dummy_status || !status->hp) return 0; + /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */ + hp = cap_value(hp,INT_MIN,INT_MAX); + sp = cap_value(sp,INT_MIN,INT_MAX); + sc = iStatus->get_sc(bl); if (sc && !sc->count) sc = NULL; @@ -1410,14 +1415,14 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) // send hp update to client switch(bl->type) { - case BL_PC: pc->heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; - case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; - case BL_HOM: homun->healed((TBL_HOM*)bl); break; - case BL_MER: mercenary->heal((TBL_MER*)bl,hp,sp); break; - case BL_ELEM: elemental->heal((TBL_ELEM*)bl,hp,sp); break; + case BL_PC: pc->heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; + case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; + case BL_HOM: homun->healed((TBL_HOM*)bl); break; + case BL_MER: mercenary->heal((TBL_MER*)bl,hp,sp); break; + case BL_ELEM: elemental->heal((TBL_ELEM*)bl,hp,sp); break; } - return hp+sp; + return (int)(hp+sp); } //Does percentual non-flinching damage/heal. If mob is killed this way, @@ -1513,11 +1518,13 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per if (bl->prev) //Animation only if character is already on a map. clif->resurrection(bl, 1); + switch (bl->type) { - case BL_PC: pc->revive((TBL_PC*)bl, hp, sp); break; - case BL_MOB: mob_revive((TBL_MOB*)bl, hp); break; - case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break; + case BL_PC: pc->revive((TBL_PC*)bl, hp, sp); break; + case BL_MOB: mob_revive((TBL_MOB*)bl, hp); break; + case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break; } + return 1; } |