diff options
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 331 |
1 files changed, 158 insertions, 173 deletions
diff --git a/src/map/status.c b/src/map/status.c index 95d7f3796..449ea8f56 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -8,6 +8,7 @@ #include "../common/malloc.h" #include "../common/utils.h" #include "../common/ers.h" +#include "../common/strlib.h" #include "map.h" #include "path.h" @@ -831,16 +832,16 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_clear(target,0); if(flag&4) //Delete from memory. (also invokes map removal code) - unit_free(target,1); + unit_free(target,CLR_DEAD); else if(flag&2) //remove from map - unit_remove_map(target,1); + unit_remove_map(target,CLR_DEAD); else { //Some death states that would normally be handled by unit_remove_map unit_stop_attack(target); unit_stop_walking(target,1); unit_skillcastcancel(target,0); - clif_clearunit_area(target,1); + clif_clearunit_area(target,CLR_DEAD); skill_unit_move(target,gettick(),4); skill_cleartimerskill(target); } @@ -1083,7 +1084,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int if (sc->data[SC_WINKCHARM] && target && !flag) { //Prevents skill usage - clif_emotion(src, 3); + clif_emotion(src, E_LV); return 0; } @@ -1546,8 +1547,13 @@ int status_calc_pet_(struct pet_data *pd, bool first) if (first) { memcpy(&pd->status, &pd->db->status, sizeof(struct status_data)); - pd->status.mode|= MD_CANMOVE; //so they can chase their master! + pd->status.mode = MD_CANMOVE; // pets discard all modes, except walking pd->status.speed = pd->petDB->speed; + + if(battle_config.pet_attack_support || battle_config.pet_damage_support) + {// attack support requires the pet to be able to attack + pd->status.mode|= MD_CANATTACK; + } } if (battle_config.pet_lv_rate && pd->msd) @@ -1840,6 +1846,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) + sizeof(sd->aspd_add) + sizeof(sd->setitem_hash) + sizeof(sd->setitem_hash2) + + sizeof(sd->itemhealrate2) // shorts + sizeof(sd->splash_range) + sizeof(sd->splash_add_range) @@ -1859,8 +1866,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first) // Autobonus pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); - pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus),true); - pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus),true); + pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),true); + pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true); // Parse equipment. for(i=0;i<EQI_MAX-1;i++) { @@ -3091,6 +3098,9 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) } } + if( bl->type == BL_PET ) + return; // pets are not affected by statuses + if( first && bl->type == BL_MOB ) return; // assume there will be no statuses active @@ -4915,51 +4925,51 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; // Stats only for Mercenaries break; case SC_STRFOOD: - if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > sc->data[type]->val1) + if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1) return 0; break; case SC_AGIFOOD: - if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > sc->data[type]->val1) + if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1) return 0; break; case SC_VITFOOD: - if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > sc->data[type]->val1) + if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1) return 0; break; case SC_INTFOOD: - if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > sc->data[type]->val1) + if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1) return 0; break; case SC_DEXFOOD: - if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > sc->data[type]->val1) + if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1) return 0; break; case SC_LUKFOOD: - if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > sc->data[type]->val1) + if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) return 0; break; case SC_FOOD_STR_CASH: - if (sc->data[SC_STRFOOD] && sc->data[SC_STRFOOD]->val1 > sc->data[type]->val1) + if (sc->data[SC_STRFOOD] && sc->data[SC_STRFOOD]->val1 > val1) return 0; break; case SC_FOOD_AGI_CASH: - if (sc->data[SC_AGIFOOD] && sc->data[SC_AGIFOOD]->val1 > sc->data[type]->val1) + if (sc->data[SC_AGIFOOD] && sc->data[SC_AGIFOOD]->val1 > val1) return 0; break; case SC_FOOD_VIT_CASH: - if (sc->data[SC_VITFOOD] && sc->data[SC_VITFOOD]->val1 > sc->data[type]->val1) + if (sc->data[SC_VITFOOD] && sc->data[SC_VITFOOD]->val1 > val1) return 0; break; case SC_FOOD_INT_CASH: - if (sc->data[SC_INTFOOD] && sc->data[SC_INTFOOD]->val1 > sc->data[type]->val1) + if (sc->data[SC_INTFOOD] && sc->data[SC_INTFOOD]->val1 > val1) return 0; break; case SC_FOOD_DEX_CASH: - if (sc->data[SC_DEXFOOD] && sc->data[SC_DEXFOOD]->val1 > sc->data[type]->val1) + if (sc->data[SC_DEXFOOD] && sc->data[SC_DEXFOOD]->val1 > val1) return 0; break; case SC_FOOD_LUK_CASH: - if (sc->data[SC_LUKFOOD] && sc->data[SC_LUKFOOD]->val1 > sc->data[type]->val1) + if (sc->data[SC_LUKFOOD] && sc->data[SC_LUKFOOD]->val1 > val1) return 0; break; } @@ -5084,52 +5094,40 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl,SC_INCREASEAGI,-1); break; case SC_STRFOOD: - if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_FOOD_STR_CASH,-1); + status_change_end(bl,SC_FOOD_STR_CASH,-1); break; case SC_AGIFOOD: - if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_FOOD_AGI_CASH,-1); + status_change_end(bl,SC_FOOD_AGI_CASH,-1); break; case SC_VITFOOD: - if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_FOOD_VIT_CASH,-1); + status_change_end(bl,SC_FOOD_VIT_CASH,-1); break; case SC_INTFOOD: - if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_FOOD_INT_CASH,-1); + status_change_end(bl,SC_FOOD_INT_CASH,-1); break; case SC_DEXFOOD: - if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_FOOD_DEX_CASH,-1); + status_change_end(bl,SC_FOOD_DEX_CASH,-1); break; case SC_LUKFOOD: - if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_FOOD_LUK_CASH,-1); + status_change_end(bl,SC_FOOD_LUK_CASH,-1); break; case SC_FOOD_STR_CASH: - if (sc->data[SC_STRFOOD] && sc->data[SC_STRFOOD]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_STRFOOD,-1); + status_change_end(bl,SC_STRFOOD,-1); break; case SC_FOOD_AGI_CASH: - if (sc->data[SC_AGIFOOD] && sc->data[SC_AGIFOOD]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_AGIFOOD,-1); + status_change_end(bl,SC_AGIFOOD,-1); break; case SC_FOOD_VIT_CASH: - if (sc->data[SC_VITFOOD] && sc->data[SC_VITFOOD]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_VITFOOD,-1); + status_change_end(bl,SC_VITFOOD,-1); break; case SC_FOOD_INT_CASH: - if (sc->data[SC_INTFOOD] && sc->data[SC_INTFOOD]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_INTFOOD,-1); + status_change_end(bl,SC_INTFOOD,-1); break; case SC_FOOD_DEX_CASH: - if (sc->data[SC_DEXFOOD] && sc->data[SC_DEXFOOD]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_DEXFOOD,-1); + status_change_end(bl,SC_DEXFOOD,-1); break; case SC_FOOD_LUK_CASH: - if (sc->data[SC_LUKFOOD] && sc->data[SC_LUKFOOD]->val1 <= sc->data[type]->val1) - status_change_end(bl,SC_LUKFOOD,-1); + status_change_end(bl,SC_LUKFOOD,-1); break; } @@ -5258,7 +5256,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_SIGNUMCRUCIS: val2 = 10 + 4*val1; //Def reduction tick = -1; - clif_emotion(bl,4); + clif_emotion(bl,E_SWT); break; case SC_MAXIMIZEPOWER: val2 = tick>0?tick:60000; @@ -5475,7 +5473,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_CONFUSION: - clif_emotion(bl,1); + clif_emotion(bl,E_WHAT); break; case SC_BLEEDING: val4 = tick/10000; @@ -5945,7 +5943,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val int pos = (bl->x&0xFFFF)|(bl->y<<16), //Current Coordinates map = sd->mapindex; //Current Map //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y - pc_setpos(sd,(unsigned short)val2,val3,val4, 3); + pc_setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); //2. Set restore point (val3 -> return map, val4 return coords val3 = map; val4 = pos; @@ -6607,6 +6605,15 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) if(sce->val2) {// erase associated land skill group = skill_id2group(sce->val2); + + if( group == NULL ) + { + ShowDebug("status_change_end: SC_DANCING is missing skill unit group (val1=%d, val2=%d, val3=%d, val4=%d, timer=%d, tid=%d, char_id=%d, map=%s, x=%d, y=%d). Please report this! (#3504)\n", + sce->val1, sce->val2, sce->val3, sce->val4, sce->timer, tid, + sd ? sd->status.char_id : 0, + mapindex_id2name(map_id2index(bl->m)), bl->x, bl->y); + } + sce->val2 = 0; skill_delunitgroup(group); } @@ -6728,7 +6735,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) break; //natural expiration. if(sd && sd->mapindex == sce->val2) - pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, 3); + pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT); break; //guess hes not in jail :P case SC_CHANGE: if (tid == -1) @@ -7668,146 +7675,124 @@ static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr return 0; } -int status_readdb(void) -{ - int i,j,class_; - FILE *fp; - char line[1024], path[1024],*p; - - sprintf(path, "%s/job_db1.txt", db_path); - fp=fopen(path,"r"); // Job-specific values (weight, HP, SP, ASPD) - if(fp==NULL){ - ShowError("can't read %s\n", path); - return 1; +/*========================================== + * DB reading. + * job_db1.txt - weight, hp, sp, aspd + * job_db2.txt - job level stat bonuses + * size_fix.txt - size adjustment table for weapons + * refine_db.txt - refining data table + *------------------------------------------*/ +static bool status_readdb_job1(char* fields[], int columns, int current) +{// Job-specific values (weight, HP, SP, ASPD) + int idx, class_; + unsigned int i; + + class_ = atoi(fields[0]); + + if(!pcdb_checkid(class_)) + { + ShowWarning("status_readdb_job1: Invalid job class %d specified.\n", class_); + return false; } - i = 0; - while(fgets(line, sizeof(line), fp)) + idx = pc_class2idx(class_); + + max_weight_base[idx] = atoi(fields[1]); + hp_coefficient[idx] = atoi(fields[2]); + hp_coefficient2[idx] = atoi(fields[3]); + sp_coefficient[idx] = atoi(fields[4]); + + for(i = 0; i < MAX_WEAPON_TYPE; i++) { - //NOTE: entry MAX_WEAPON_TYPE is not counted - char* split[5 + MAX_WEAPON_TYPE]; - i++; - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line; j < 5 + MAX_WEAPON_TYPE && p; j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(j < 5 + MAX_WEAPON_TYPE) - { //Weapon #.MAX_WEAPON_TYPE is constantly not load. Fix to that: replace < with <= [blackhole89] - ShowDebug("%s: Not enough columns at line %d\n", path, i); - continue; - } - class_ = atoi(split[0]); - if(!pcdb_checkid(class_)) - continue; - class_ = pc_class2idx(class_); - max_weight_base[class_]=atoi(split[1]); - hp_coefficient[class_]=atoi(split[2]); - hp_coefficient2[class_]=atoi(split[3]); - sp_coefficient[class_]=atoi(split[4]); - for(j=0;j<MAX_WEAPON_TYPE;j++) - aspd_base[class_][j]=atoi(split[j+5]); + aspd_base[idx][i] = atoi(fields[i+5]); } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path); + return true; +} - memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus - sprintf(path, "%s/job_db2.txt", db_path); - fp=fopen(path,"r"); - if(fp==NULL){ - ShowError("can't read %s\n", path); - return 1; +static bool status_readdb_job2(char* fields[], int columns, int current) +{ + int idx, class_, i; + + class_ = atoi(fields[0]); + + if(!pcdb_checkid(class_)) + { + ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class_); + return false; } - while(fgets(line, sizeof(line), fp)) + idx = pc_class2idx(class_); + + for(i = 1; i < columns; i++) { - char *split[MAX_LEVEL+1]; //Job Level is limited to MAX_LEVEL, so the bonuses should likewise be limited to it. [Skotlex] - if(line[0]=='/' && line[1]=='/') - continue; - for(j=0,p=line;j<MAX_LEVEL+1 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - class_ = atoi(split[0]); - if(!pcdb_checkid(class_)) - continue; - class_ = pc_class2idx(class_); - for(i=1;i<j && split[i];i++) - job_bonus[class_][i-1]=atoi(split[i]); - } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path); - - // サイズ補正テ?ブル - for(i=0;i<3;i++) - for(j=0;j<MAX_WEAPON_TYPE;j++) - atkmods[i][j]=100; - sprintf(path, "%s/size_fix.txt", db_path); - fp=fopen(path,"r"); - if(fp==NULL){ - ShowError("can't read %s\n", path); - return 1; + job_bonus[idx][i-1] = atoi(fields[i]); } - i=0; - while(fgets(line, sizeof(line), fp)) + return true; +} + +static bool status_readdb_sizefix(char* fields[], int columns, int current) +{ + unsigned int i; + + for(i = 0; i < MAX_WEAPON_TYPE; i++) { - char *split[MAX_WEAPON_TYPE]; - if(line[0]=='/' && line[1]=='/') - continue; - if(atoi(line)<=0) - continue; - memset(split,0,sizeof(split)); - for(j=0,p=line;j<MAX_WEAPON_TYPE && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - atkmods[i][j]=atoi(split[j]); - } - i++; + atkmods[current][i] = atoi(fields[i]); } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path); + return true; +} + +static bool status_readdb_refine(char* fields[], int columns, int current) +{ + int i; + + refinebonus[current][0] = atoi(fields[0]); // stats per safe-upgrade + refinebonus[current][1] = atoi(fields[1]); // stats after safe-limit + refinebonus[current][2] = atoi(fields[2]); // safe limit + + for(i = 0; i < MAX_REFINE; i++) + { + percentrefinery[current][i] = atoi(fields[3+i]); + } + return true; +} - // 精?デ?タテ?ブル - for(i=0;i<5;i++){ +int status_readdb(void) +{ + int i, j; + + // initialize databases to default + // + + // job_db1.txt + memset(max_weight_base, 0, sizeof(max_weight_base)); + memset(hp_coefficient, 0, sizeof(hp_coefficient)); + memset(hp_coefficient2, 0, sizeof(hp_coefficient2)); + memset(sp_coefficient, 0, sizeof(sp_coefficient)); + memset(aspd_base, 0, sizeof(aspd_base)); + + // job_db2.txt + memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus + + // size_fix.txt + for(i=0;i<ARRAYLENGTH(atkmods);i++) + for(j=0;j<MAX_WEAPON_TYPE;j++) + atkmods[i][j]=100; + + // refine_db.txt + for(i=0;i<ARRAYLENGTH(percentrefinery);i++){ for(j=0;j<MAX_REFINE; j++) - percentrefinery[i][j]=100; + percentrefinery[i][j]=100; // success chance percentrefinery[i][j]=0; //Slot MAX+1 always has 0% success chance [Skotlex] - refinebonus[i][0]=0; - refinebonus[i][1]=0; - refinebonus[i][2]=10; + refinebonus[i][0]=0; // stats per safe-upgrade + refinebonus[i][1]=0; // stats after safe-limit + refinebonus[i][2]=10; // safe limit } - sprintf(path, "%s/refine_db.txt", db_path); - fp=fopen(path,"r"); - if(fp==NULL){ - ShowError("can't read %s\n", path); - return 1; - } - i=0; - while(fgets(line, sizeof(line), fp)) - { - char *split[MAX_REFINE+4]; - if(line[0]=='/' && line[1]=='/') - continue; - if(atoi(line)<=0) - continue; - memset(split,0,sizeof(split)); - for(j=0,p=line;j<MAX_REFINE+4 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - refinebonus[i][0]=atoi(split[0]); // 精?ボ?ナス - refinebonus[i][1]=atoi(split[1]); // 過?精?ボ?ナス - refinebonus[i][2]=atoi(split[2]); // 安全精?限界 - for(j=0;j<MAX_REFINE && split[j+3];j++) - percentrefinery[i][j]=atoi(split[j+3]); - i++; - } - fclose(fp); //Lupus. close this file!!! - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path); + // read databases + // + + sv_readdb(db_path, "job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1); + sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); + sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); + sv_readdb(db_path, "refine_db.txt", ',', 3+MAX_REFINE+1, 3+MAX_REFINE+1, ARRAYLENGTH(percentrefinery), &status_readdb_refine); return 0; } |