- 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:
skotlex 2006-12-20 15:54:11 +00:00
parent 72bebf27fc
commit 6bbec4a65d
6 changed files with 190 additions and 146 deletions

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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");
}

View File

@ -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

View File

@ -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[];

View File

@ -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:
@ -6035,8 +6049,27 @@ int status_change_end( struct block_list* bl , int type,int tid )
(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)--;