summaryrefslogtreecommitdiff
path: root/src/map/status.c
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-12-20 15:54:11 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-12-20 15:54:11 +0000
commitdb09034d6836abbd1c8988cd0d07236e3c8f2bf1 (patch)
tree577cced26eef0a0d31d896f3cc1c83d6dd1a385d /src/map/status.c
parent71f3bdc9d000855ce363c8ef9f481c1526f8b480 (diff)
downloadhercules-db09034d6836abbd1c8988cd0d07236e3c8f2bf1.tar.gz
hercules-db09034d6836abbd1c8988cd0d07236e3c8f2bf1.tar.bz2
hercules-db09034d6836abbd1c8988cd0d07236e3c8f2bf1.tar.xz
hercules-db09034d6836abbd1c8988cd0d07236e3c8f2bf1.zip
- Added an answer to a FlavioJS's comment, and added a question myself (npc.c/script.c respectively)
- Fixed add_str in script.h not being updated to const char as well. But why do we really need such a script-engine low-level function exposed to the rest of files? :/ - Moved the strip unequip code to before deleting the timer, this fixes trying to "re-strip" someone causing the skill to fail and on top of that terminate their current strip effect. - Added an ugly work around to the issue of skills with additional effect causing opt1 status when they have just terminated them (in short, you shouldn't be able to hit someone with, say, sleep, and then have the same skill cause them stun, since both are opt1 values). - Reading of TK Mission variables will now happen if you are a TK-class character regardless of whether you know TK_MISSION or not. Should fix being able to reset skills to reset your Mission data. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9537 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/status.c')
-rw-r--r--src/map/status.c295
1 files changed, 164 insertions, 131 deletions
diff --git a/src/map/status.c b/src/map/status.c
index dab6861ea..dfd5279d3 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -4533,99 +4533,159 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
//Check for inmunities / sc fails
switch (type) {
- case SC_FREEZE:
- case SC_STONE:
- //Undead are inmune to Freeze/Stone
- if (undead_flag && !(flag&1))
- return 0;
- case SC_SLEEP:
- case SC_STUN:
- if (sc->opt1)
- return 0; //Cannot override other opt1 status changes. [Skotlex]
- break;
- case SC_CURSE:
- //Dark Elementals are inmune to curse.
- if (status->def_ele == ELE_DARK && !(flag&1))
- return 0;
- break;
- case SC_COMA:
- //Dark elementals and Demons are inmune to coma.
- if((status->def_ele == ELE_DARK || status->race == RC_DEMON) && !(flag&1))
- return 0;
+ case SC_FREEZE:
+ case SC_STONE:
+ //Undead are inmune to Freeze/Stone
+ if (undead_flag && !(flag&1))
+ return 0;
+ case SC_SLEEP:
+ case SC_STUN:
+ if (sc->opt1)
+ return 0; //Cannot override other opt1 status changes. [Skotlex]
+ break;
+ case SC_CURSE:
+ //Dark Elementals are inmune to curse.
+ if (status->def_ele == ELE_DARK && !(flag&1))
+ return 0;
+ break;
+ case SC_COMA:
+ //Dark elementals and Demons are inmune to coma.
+ if((status->def_ele == ELE_DARK || status->race == RC_DEMON) && !(flag&1))
+ return 0;
+ break;
+ case SC_SIGNUMCRUCIS:
+ //Only affects demons and undead.
+ if(status->race != RC_DEMON && !undead_flag)
+ return 0;
break;
- case SC_SIGNUMCRUCIS:
- //Only affects demons and undead.
- if(status->race != RC_DEMON && !undead_flag)
- return 0;
- break;
- case SC_AETERNA:
- if (sc->data[SC_STONE].timer != -1 || sc->data[SC_FREEZE].timer != -1)
- return 0;
+ case SC_AETERNA:
+ if (sc->data[SC_STONE].timer != -1 || sc->data[SC_FREEZE].timer != -1)
+ return 0;
+ break;
+ case SC_OVERTHRUST:
+ if (sc->data[SC_MAXOVERTHRUST].timer != -1)
+ return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex]
+ break;
+ case SC_ADRENALINE:
+ if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE)))
+ return 0;
+ if (sc->data[SC_QUAGMIRE].timer!=-1 ||
+ sc->data[SC_DONTFORGETME].timer!=-1 ||
+ sc->data[SC_DECREASEAGI].timer!=-1
+ )
+ return 0;
+ break;
+ case SC_ADRENALINE2:
+ if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2)))
+ return 0;
+ if (sc->data[SC_QUAGMIRE].timer!=-1 ||
+ sc->data[SC_DONTFORGETME].timer!=-1 ||
+ sc->data[SC_DECREASEAGI].timer!=-1
+ )
+ return 0;
+ break;
+ case SC_ONEHAND:
+ case SC_TWOHANDQUICKEN:
+ if(sc->data[SC_DECREASEAGI].timer!=-1)
+ return 0;
+ case SC_CONCENTRATE:
+ case SC_INCREASEAGI:
+ case SC_SPEARQUICKEN:
+ case SC_TRUESIGHT:
+ case SC_WINDWALK:
+ case SC_CARTBOOST:
+ case SC_ASSNCROS:
+ if (sc->data[SC_QUAGMIRE].timer!=-1 || sc->data[SC_DONTFORGETME].timer!=-1)
+ return 0;
+ break;
+ case SC_CLOAKING:
+ //Avoid cloaking with no wall and low skill level. [Skotlex]
+ //Due to the cloaking card, we have to check the wall versus to known
+ //skill level rather than the used one. [Skotlex]
+ //if (sd && val1 < 3 && skill_check_cloaking(bl))
+ if (sd && pc_checkskill(sd, AS_CLOAKING)< 3 && skill_check_cloaking(bl,sc))
+ return 0;
break;
- case SC_OVERTHRUST:
- if (sc->data[SC_MAXOVERTHRUST].timer != -1)
- return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex]
+ case SC_MODECHANGE:
+ {
+ int mode;
+ struct status_data *bstatus = status_get_base_status(bl);
+ if (!bstatus) return 0;
+ if (sc->data[type].timer != -1)
+ { //Pile up with previous values.
+ if(!val2) val2 = sc->data[type].val2;
+ val3 |= sc->data[type].val3;
+ val4 |= sc->data[type].val4;
+ }
+ mode = val2?val2:bstatus->mode; //Base mode
+ if (val4) mode&=~val4; //Del mode
+ if (val3) mode|= val3; //Add mode
+ if (mode == bstatus->mode) { //No change.
+ if (sc->data[type].timer != -1) //Abort previous status
+ return status_change_end(bl, type, -1);
+ return 0;
+ }
break;
- case SC_ADRENALINE:
- if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE)))
- return 0;
- if (sc->data[SC_QUAGMIRE].timer!=-1 ||
- sc->data[SC_DONTFORGETME].timer!=-1 ||
- sc->data[SC_DECREASEAGI].timer!=-1
- )
+ }
+ //Strip skills, need to divest something or it fails.
+ case SC_STRIPWEAPON:
+ if (sd) {
+ int i;
+ opt_flag = 0; //Reuse to check success condition.
+ if(sd->unstripable_equip&EQP_WEAPON)
return 0;
+ i = sd->equip_index[EQI_HAND_L];
+ if (i>=0 && sd->inventory_data[i] &&
+ sd->inventory_data[i]->type == IT_WEAPON)
+ {
+ opt_flag|=1;
+ pc_unequipitem(sd,i,3); //L-hand weapon
+ }
+
+ i = sd->equip_index[EQI_HAND_R];
+ if (i>=0 && sd->inventory_data[i] &&
+ sd->inventory_data[i]->type == IT_WEAPON)
+ {
+ opt_flag|=2;
+ pc_unequipitem(sd,i,3);
+ }
+ if (!opt_flag) return 0;
+ }
break;
- case SC_ADRENALINE2:
- if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2)))
+ case SC_STRIPSHIELD:
+ if (sd) {
+ int i;
+ if(sd->unstripable_equip&EQP_SHIELD)
return 0;
- if (sc->data[SC_QUAGMIRE].timer!=-1 ||
- sc->data[SC_DONTFORGETME].timer!=-1 ||
- sc->data[SC_DECREASEAGI].timer!=-1
- )
+ i = sd->equip_index[EQI_HAND_L];
+ if (i<0 || !sd->inventory_data[i] ||
+ sd->inventory_data[i]->type != IT_ARMOR)
return 0;
+ pc_unequipitem(sd,i,3);
+ }
break;
- case SC_ONEHAND:
- case SC_TWOHANDQUICKEN:
- if(sc->data[SC_DECREASEAGI].timer!=-1)
+ case SC_STRIPARMOR:
+ if (sd) {
+ int i;
+ if(sd->unstripable_equip&EQP_ARMOR)
return 0;
- case SC_CONCENTRATE:
- case SC_INCREASEAGI:
- case SC_SPEARQUICKEN:
- case SC_TRUESIGHT:
- case SC_WINDWALK:
- case SC_CARTBOOST:
- case SC_ASSNCROS:
- if (sc->data[SC_QUAGMIRE].timer!=-1 || sc->data[SC_DONTFORGETME].timer!=-1)
+ i = sd->equip_index[EQI_ARMOR];
+ if (i<0 || !sd->inventory_data[i])
return 0;
+ pc_unequipitem(sd,i,3);
+ }
break;
- case SC_CLOAKING:
- //Avoid cloaking with no wall and low skill level. [Skotlex]
- //Due to the cloaking card, we have to check the wall versus to known
- //skill level rather than the used one. [Skotlex]
- //if (sd && val1 < 3 && skill_check_cloaking(bl))
- if (sd && pc_checkskill(sd, AS_CLOAKING)< 3 && skill_check_cloaking(bl,sc))
+ case SC_STRIPHELM:
+ if (sd) {
+ int i;
+ if(sd->unstripable_equip&EQP_HELM)
return 0;
- break;
- case SC_MODECHANGE:
- {
- int mode;
- struct status_data *bstatus = status_get_base_status(bl);
- if (!bstatus) return 0;
- if (sc->data[type].timer != -1)
- { //Pile up with previous values.
- if(!val2) val2 = sc->data[type].val2;
- val3 |= sc->data[type].val3;
- val4 |= sc->data[type].val4;
- }
- mode = val2?val2:bstatus->mode; //Base mode
- if (val4) mode&=~val4; //Del mode
- if (val3) mode|= val3; //Add mode
- if (mode == bstatus->mode) { //No change.
- if (sc->data[type].timer != -1) //Abort previous status
- return status_change_end(bl, type, -1);
+ i = sd->equip_index[EQI_HEAD_TOP];
+ if (i<0 || !sd->inventory_data[i])
return 0;
- }
+ pc_unequipitem(sd,i,3);
}
+ break;
}
//Check for BOSS resistances
@@ -4929,65 +4989,19 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
}
break;
case SC_STRIPWEAPON:
- if (sd) {
- int i;
- opt_flag = 0; //Reuse to check success condition.
- if(sd->unstripable_equip&EQP_WEAPON)
- return 0;
- i = sd->equip_index[EQI_HAND_L];
- if (i>=0 && sd->inventory_data[i] &&
- sd->inventory_data[i]->type == IT_WEAPON)
- {
- opt_flag|=1;
- pc_unequipitem(sd,i,3); //L-hand weapon
- }
-
- i = sd->equip_index[EQI_HAND_R];
- if (i>=0 && sd->inventory_data[i] &&
- sd->inventory_data[i]->type == IT_WEAPON)
- {
- opt_flag|=2;
- pc_unequipitem(sd,i,3);
- }
- if (!opt_flag) return 0;
- } else //Watk reduction
+ if (!sd) //Watk reduction
val2 = 5*val1;
break;
case SC_STRIPSHIELD:
- if (sd) {
- int i;
- if(sd->unstripable_equip&EQP_SHIELD)
- return 0;
- i = sd->equip_index[EQI_HAND_L];
- if (i<0 || !sd->inventory_data[i] ||
- sd->inventory_data[i]->type != IT_ARMOR)
- return 0;
- pc_unequipitem(sd,i,3);
- } else //Def reduction
+ if (!sd) //Def reduction
val2 = 3*val1;
break;
case SC_STRIPARMOR:
- if (sd) {
- int i;
- if(sd->unstripable_equip&EQP_ARMOR)
- return 0;
- i = sd->equip_index[EQI_ARMOR];
- if (i<0 || !sd->inventory_data[i])
- return 0;
- pc_unequipitem(sd,i,3);
- } else //Vit reduction
+ if (!sd) //Vit reduction
val2 = 8*val1;
break;
case SC_STRIPHELM:
- if (sd) {
- int i;
- if(sd->unstripable_equip&EQP_HELM)
- return 0;
- i = sd->equip_index[EQI_HEAD_TOP];
- if (i<0 || !sd->inventory_data[i])
- return 0;
- pc_unequipitem(sd,i,3);
- } else //Int reduction
+ if (!sd) //Int reduction
val2 = 8*val1;
break;
case SC_AUTOSPELL:
@@ -6034,9 +6048,28 @@ int status_change_end( struct block_list* bl , int type,int tid )
if (sc->data[type].timer == -1 ||
(sc->data[type].timer != tid && tid != -1))
return 0;
-
- if (tid == -1)
+
+ if (tid == -1) {
delete_timer(sc->data[type].timer,status_change_timer);
+ if (sc->opt1)
+ switch (type) {
+ //"Ugly workaround" [Skotlex]
+ //delays status change ending so that a skill that sets opt1 fails to
+ //trigger when it also removed one
+ case SC_STONE:
+ case SC_FREEZE:
+ case SC_STUN:
+ case SC_SLEEP:
+ if (sc->data[type].val1) {
+ //Removing the 'level' shouldn't affect anything in the code
+ //since these SC are not affected by it, and it lets us know
+ //if we have already delayed this attack or not.
+ sc->data[type].val1 = 0;
+ sc->data[type].timer = add_timer(gettick()+10, status_change_timer, bl->id, type);
+ return 1;
+ }
+ }
+ }
sc->data[type].timer=-1;
(sc->count)--;