- 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://svn.code.sf.net/p/rathena/svn/trunk@9537 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
72bebf27fc
commit
6bbec4a65d
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[];
|
||||
|
317
src/map/status.c
317
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]
|
||||
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_CURSE:
|
||||
//Dark Elementals are inmune to curse.
|
||||
if (status->def_ele == ELE_DARK && !(flag&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_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_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_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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
//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_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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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)--;
|
||||
|
Loading…
x
Reference in New Issue
Block a user