diff options
-rw-r--r-- | Changelog-Trunk.txt | 10 | ||||
-rw-r--r-- | src/map/npc.c | 2 | ||||
-rw-r--r-- | src/map/pc.c | 3 | ||||
-rw-r--r-- | src/map/script.c | 2 | ||||
-rw-r--r-- | src/map/script.h | 2 | ||||
-rw-r--r-- | src/map/status.c | 295 |
6 files changed, 179 insertions, 135 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 275bc172d..60791db70 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,16 @@ 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/12/20 + * 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. + * 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. + * 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). [Skotlex] * Now root script functions calls can have parenthesis (will take any parenthesis after the function as the start of the argument list). - This means "func (exp),exp;" isn't valid anymore. diff --git a/src/map/npc.c b/src/map/npc.c index 447d04d7a..8e2a0d009 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2943,7 +2943,7 @@ int do_final_npc(void) if ((bl = map_id2bl(i))){ if (bl->type == BL_NPC) npc_unload((struct npc_data *)bl); - else if (bl->type&(BL_MOB|BL_PET))//## why BL_PET? [FlavioJS] + else if (bl->type&(BL_MOB|BL_PET))//## why BL_PET? [FlavioJS] //## Because this is invoked after saving/wiping all players, which would include all pets. This bit of code will take care of any pets without a master that are still lingering in the map. [Skotlex] unit_free(bl, 0); } } diff --git a/src/map/pc.c b/src/map/pc.c index f6923a8c2..5fdb19378 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -795,7 +795,8 @@ int pc_reg_received(struct map_session_data *sd) sd->change_level = pc_readglobalreg(sd,"jobchange_level"); sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER"); - if (pc_checkskill(sd, TK_MISSION)) { + if ((sd->class_&MAPID_BASEMASK)==MAPID_TAEKWON) + { //Better check for class rather than skill to prevent "skill resets" from unsetting this sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID"); sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT"); } diff --git a/src/map/script.c b/src/map/script.c index 4684d745c..f94b0163a 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -499,7 +499,7 @@ static const char *skip_word(const char *p) if(*p=='#') p++; // account変数用 if(*p=='#') p++; // ワールドaccount変数用 - while(isalnum(*p)||*p=='_'|| *p>=0x81) { + while(isalnum(*p)||*p=='_'|| *p>=0x81) { //#FIXME: Changing from unsigned char to signed char makes p never be able to go above 0x81, but what IS 0x81 for? if(*p>=0x81 && p[1]){ p+=2; } else diff --git a/src/map/script.h b/src/map/script.h index 274bc9022..bc142c125 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -82,7 +82,7 @@ struct dbt* script_get_userfunc_db(void); int script_config_read(char *cfgName); int do_init_script(void); int do_final_script(void); -int add_str(const unsigned char *p); +int add_str(const char *p); int script_reload(void); extern char mapreg_txt[]; 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)--; |