summaryrefslogtreecommitdiff
path: root/src
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
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')
-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
5 files changed, 169 insertions, 135 deletions
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)--;