summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt10
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/pc.c3
-rw-r--r--src/map/script.c2
-rw-r--r--src/map/script.h2
-rw-r--r--src/map/status.c295
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)--;