From 07e03074151d0361be665c05e140eca8e89295ca Mon Sep 17 00:00:00 2001 From: skotlex Date: Thu, 23 Feb 2006 16:31:16 +0000 Subject: - Modified the way autospells stack to mimic official servers. Cards of the same ID cannot stack, but different cards with the same skill can each trigger indepedently of each other. - Added battle_config autospell_stacking to enable stacking of cards of same ID. - Moved card-specific battle options to items.conf - Autospells triggered when hit will check the range to the target. - Some cleaning up of status_calc_pc - In status_change_start capped the passed success chance to 100% git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5377 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 2 + src/map/battle.h | 1 + src/map/clif.c | 2 +- src/map/map.h | 4 +- src/map/pc.c | 84 +++++++++++------------------ src/map/skill.c | 3 ++ src/map/status.c | 162 ++++++++++++++++++++++--------------------------------- src/map/status.h | 1 + 8 files changed, 105 insertions(+), 154 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index c578167d7..6913c0294 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -3821,6 +3821,7 @@ static const struct battle_data_short { { "pc_max_status_def", &battle_config.pc_max_sc_def }, { "mob_max_status_def", &battle_config.mob_max_sc_def }, { "sg_miracle_skill_ratio", &battle_config.sg_miracle_skill_ratio }, + { "autospell_stacking", &battle_config.autospell_stacking }, }; static const struct battle_data_int { @@ -4220,6 +4221,7 @@ void battle_set_defaults() { battle_config.mob_max_sc_def = 5000; battle_config.sg_miracle_skill_ratio=1; battle_config.sg_miracle_skill_duration=600000; + battle_config.autospell_stacking = 0; } void battle_validate_conf() { diff --git a/src/map/battle.h b/src/map/battle.h index 09eddf294..512179482 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -429,6 +429,7 @@ extern struct Battle_Config { unsigned short sg_miracle_skill_ratio; int sg_miracle_skill_duration; + unsigned short autospell_stacking; //Enables autospell cards to stack. [Skotlex] } battle_config; diff --git a/src/map/clif.c b/src/map/clif.c index 88150576b..9ccb2b2c8 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -3033,7 +3033,7 @@ int clif_updatestatus(struct map_session_data *sd,int type) if ( !session_isActive(fd) ) // Invalid pointer fix, by sasuke [Kevin] return 0; - WFIFOHEAD(fd, 14); + WFIFOHEAD(fd, 14); WFIFOW(fd,0)=0xb0; WFIFOW(fd,2)=type; switch(type){ diff --git a/src/map/map.h b/src/map/map.h index 9ae1d3d2a..ddbb776ee 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -578,8 +578,8 @@ struct map_session_data { short unequip_losesp[11]; // zeroed arrays end here. // zeroed structures start here - struct { - short id, lv, rate; + struct s_autospell{ + short id, lv, rate, card_id; } autospell[MAX_PC_BONUS], autospell2[MAX_PC_BONUS]; struct { //skillatk raises bonus dmg% of skills, skillblown increases bonus blewcount for some skills. short id, val; diff --git a/src/map/pc.c b/src/map/pc.c index b89639ebc..fd52944be 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1126,6 +1126,29 @@ int pc_checkweighticon(struct map_session_data *sd) return 0; } +static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short card_id) { + int i; + for (i = 0; i < max && spell[i].id; i++) { + if (spell[i].card_id == card_id && + spell[i].id == id && spell[i].lv == lv) + { + if (!battle_config.autospell_stacking) + return 0; + rate += spell[i].rate; + break; + } + } + if (i == max) { + if (battle_config.error_log) + ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max); + return 0; + } + spell[i].id = id; + spell[i].lv = lv; + spell[i].rate = rate; + spell[i].card_id = card_id; + return 1; +} /*========================================== * ? 備品による能力等のボ?ナス設定 *------------------------------------------ @@ -2044,34 +2067,12 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) } break; case SP_AUTOSPELL: - if(sd->state.lr_flag != 2) { - for (i = 0; i < MAX_PC_BONUS; i++) { - if (sd->autospell[i].id == 0 || - (sd->autospell[i].id == type2 && sd->autospell[i].lv < type3) || - (sd->autospell[i].id == type2 && sd->autospell[i].lv == type3 && sd->autospell[i].rate < val)) - { - sd->autospell[i].id = type2; - sd->autospell[i].lv = type3; - sd->autospell[i].rate = val; - break; - } - } - } + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell, MAX_PC_BONUS, type2, type3, val, current_equip_card_id); break; case SP_AUTOSPELL_WHENHIT: - if(sd->state.lr_flag != 2) { - for (i = 0; i < MAX_PC_BONUS; i++) { - if (sd->autospell2[i].id == 0 || - (sd->autospell2[i].id == type2 && sd->autospell2[i].lv < type3) || - (sd->autospell2[i].id == type2 && sd->autospell2[i].lv == type3 && sd->autospell2[i].rate < val)) - { - sd->autospell2[i].id = type2; - sd->autospell2[i].lv = type3; - sd->autospell2[i].rate = val; - break; - } - } - } + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell2, MAX_PC_BONUS, type2, type3, val, current_equip_card_id); break; case SP_HP_LOSS_RATE: if(sd->state.lr_flag != 2) { @@ -2124,39 +2125,16 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) { - int i; nullpo_retr(0, sd); switch(type){ case SP_AUTOSPELL: - if(sd->state.lr_flag != 2) { - for (i = 0; i < MAX_PC_BONUS; i++) { - if (sd->autospell[i].id == 0 || - (sd->autospell[i].id == type2 && sd->autospell[i].lv < type3) || - (sd->autospell[i].id == type2 && sd->autospell[i].lv == type3 && sd->autospell[i].rate < type4)) - { - sd->autospell[i].id = (val) ? type2 : -type2; // val = 0: self, 1: enemy - sd->autospell[i].lv = type3; - sd->autospell[i].rate = type4; - break; - } - } - } + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell, MAX_PC_BONUS, val?type2:-type2, type3, type4, current_equip_card_id); break; case SP_AUTOSPELL_WHENHIT: - if(sd->state.lr_flag != 2) { - for (i = 0; i < MAX_PC_BONUS; i++) { - if (sd->autospell2[i].id == 0 || - (sd->autospell2[i].id == type2 && sd->autospell2[i].lv < type3) || - (sd->autospell2[i].id == type2 && sd->autospell2[i].lv == type3 && sd->autospell2[i].rate < type4)) - { - sd->autospell2[i].id = (val) ? type2 : -type2; // val = 0: self, 1: enemy - sd->autospell2[i].lv = type3; - sd->autospell2[i].rate = type4; - break; - } - } - } + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell2, MAX_PC_BONUS, val?type2:-type2, type3, type4, current_equip_card_id); break; default: if(battle_config.error_log) diff --git a/src/map/skill.c b/src/map/skill.c index a36f17368..faedbd39a 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1373,6 +1373,9 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * else tbl = src; + if (tbl != src && !battle_check_range(src, tbl, skill_get_range2(src, skillid, skilllv))) + continue; //Autoskills DO check for target-src range. [Skotlex] + switch (skill_get_casttype(skillid)) { case CAST_GROUND: skill_castend_pos2(bl, tbl->x, tbl->y, skillid, skilllv, tick, 0); diff --git a/src/map/status.c b/src/map/status.c index a6ba3bf28..bf2f6024e 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -42,6 +42,7 @@ static int atkmods[3][20]; // static char job_bonus[MAX_PC_CLASS][MAX_LEVEL]; int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus] +int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex] //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only //to avoid cards exploits @@ -557,8 +558,7 @@ int status_calc_pc(struct map_session_data* sd,int first) int b_base_atk; struct skill b_skill[MAX_SKILL]; int i,bl,index; - int skill,wele,wele_,def_ele,refinedef=0; - int pele=0,pdef_ele=0; + int skill,refinedef=0; int str,dstr,dex; nullpo_retr(0, sd); @@ -782,51 +782,35 @@ int status_calc_pc(struct map_session_data* sd,int first) continue; if(sd->inventory_data[index]) { - if(sd->inventory_data[index]->type == 4) { // Weapon cards - if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) { - int j; - for(j=0;jinventory_data[index]->slot;j++){ // カ?ド - int c=sd->status.inventory[index].card[j]; - if(c>0){ - if(i == 8 && sd->status.inventory[index].equip == 0x20) - sd->state.lr_flag = 1; - run_script(itemdb_equipscript(c),0,sd->bl.id,0); - sd->state.lr_flag = 0; - if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] - return 1; - } - } - } - } - else if(sd->inventory_data[index]->type==5){ // Non-weapon equipment cards - if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) { - int j; - for(j=0;jinventory_data[index]->slot;j++){ // カ?ド - int c=sd->status.inventory[index].card[j]; - if(c>0) { - run_script(itemdb_equipscript(c),0,sd->bl.id,0); - if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] - return 1; - } - } + int j,c; + //Card script execution. + if(sd->status.inventory[index].card[0]==0x00ff || + sd->status.inventory[index].card[0]==0x00fe || + sd->status.inventory[index].card[0]==(short)0xff00) + continue; + for(j=0;jinventory_data[index]->slot;j++){ // カ?ド + current_equip_card_id= c= sd->status.inventory[index].card[j]; + if(c>0){ + if(i == 8 && sd->status.inventory[index].equip == 0x20) + { //Left hand status. + sd->state.lr_flag = 1; + run_script(itemdb_equipscript(c),0,sd->bl.id,0); + sd->state.lr_flag = 0; + } else + run_script(itemdb_equipscript(c),0,sd->bl.id,0); + if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] + return 1; } } } } - wele = sd->right_weapon.atk_ele; - wele_ = sd->left_weapon.atk_ele; - def_ele = sd->def_ele; - - if(sd->status.pet_id > 0) { // Pet + + if(sd->status.pet_id > 0 && battle_config.pet_status_support && sd->pet.intimate > 0) + { // Pet struct pet_data *pd=sd->pd; - if((pd && battle_config.pet_status_support) && (!battle_config.pet_equip_required || pd->equip > 0)) { - if(sd->pet.intimate > 0 && pd->state.skillbonus == 1 && pd->bonus) { //Skotlex: Readjusted for pets - pc_bonus(sd,pd->bonus->type, pd->bonus->val); - } - pele = sd->right_weapon.atk_ele; - pdef_ele = sd->def_ele; - sd->right_weapon.atk_ele = sd->def_ele = 0; - } + if(pd && (!battle_config.pet_equip_required || pd->equip > 0) && + pd->state.skillbonus == 1 && pd->bonus) //Skotlex: Readjusted for pets + pc_bonus(sd,pd->bonus->type, pd->bonus->val); } memcpy(sd->paramcard,sd->parame,sizeof(sd->paramcard)); @@ -841,61 +825,53 @@ int status_calc_pc(struct map_session_data* sd,int first) continue; if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) continue; - if(sd->inventory_data[index]) { - sd->def += sd->inventory_data[index]->def; - if(sd->inventory_data[index]->type == 4) { - int r,wlv = sd->inventory_data[index]->wlv; - if (wlv >= MAX_REFINE_BONUS) - wlv = MAX_REFINE_BONUS - 1; - if(i == 8 && sd->status.inventory[index].equip == 0x20) { // Left-hand weapon - sd->left_weapon.watk += sd->inventory_data[index]->atk; - sd->left_weapon.watk2 = (r=sd->status.inventory[index].refine)* // 精?攻?力 - refinebonus[wlv][0]; - if( (r-=refinebonus[wlv][2])>0 ) // 過?精?ボ?ナス - sd->left_weapon.overrefine = r*refinebonus[wlv][1]; - - if(sd->status.inventory[index].card[0]==0x00ff){ // Forged weapon - sd->left_weapon.star = (sd->status.inventory[index].card[1]>>8); // 星のかけら - if(sd->left_weapon.star >= 15) sd->left_weapon.star = 40; // 3 Star Crumbs now give +40 dmg - if (pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) - sd->left_weapon.star += 10; - wele_= (sd->status.inventory[index].card[1]&0x0f); // ? 性 - } + if(!sd->inventory_data[index]) + continue; + + sd->def += sd->inventory_data[index]->def; + if(sd->inventory_data[index]->type == 4) { + int r,wlv = sd->inventory_data[index]->wlv; + struct weapon_data *wd; + if (wlv >= MAX_REFINE_BONUS) + wlv = MAX_REFINE_BONUS - 1; + if(i == 8 && sd->status.inventory[index].equip == 0x20) + wd = &sd->left_weapon; // Left-hand weapon + else + wd = &sd->right_weapon; + wd->watk += sd->inventory_data[index]->atk; + wd->watk2 = (r=sd->status.inventory[index].refine)*refinebonus[wlv][0]; + if((r-=refinebonus[wlv][2])>0) //Overrefine bonus. + wd->overrefine = r*refinebonus[wlv][1]; + + if(sd->status.inventory[index].card[0]==0x00ff) + { // Forged weapon + wd->star += (sd->status.inventory[index].card[1]>>8); + if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg + if(pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) + wd->star += 10; + + if (!wd->atk_ele) //Do not overwrite element from previous bonuses. + wd->atk_ele = (sd->status.inventory[index].card[1]&0x0f); + + if (wd == &sd->left_weapon) { sd->attackrange_ += sd->inventory_data[index]->range; sd->state.lr_flag = 1; run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); sd->state.lr_flag = 0; - if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] - return 1; - } - else { // Right-hand weapon - sd->right_weapon.watk += sd->inventory_data[index]->atk; - sd->right_weapon.watk2 += (r=sd->status.inventory[index].refine)* // 精?攻?力 - refinebonus[wlv][0]; - if( (r-=refinebonus[wlv][2])>0 ) // 過?精?ボ?ナス - sd->right_weapon.overrefine += r*refinebonus[wlv][1]; - - if(sd->status.inventory[index].card[0]==0x00ff){ // Forged weapon - sd->right_weapon.star += (sd->status.inventory[index].card[1]>>8); // 星のかけら - if(sd->right_weapon.star >= 15) sd->right_weapon.star = 40; // 3 Star Crumbs now give +40 dmg - if (pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) - sd->right_weapon.star += 10; - wele = (sd->status.inventory[index].card[1]&0x0f); // ? 性 - } + } else { sd->attackrange += sd->inventory_data[index]->range; run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); - if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] - return 1; } - } - else if(sd->inventory_data[index]->type == 5) { - sd->right_weapon.watk += sd->inventory_data[index]->atk; - refinedef += sd->status.inventory[index].refine*refinebonus[0][0]; - run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] return 1; } } + else if(sd->inventory_data[index]->type == 5) { + refinedef += sd->status.inventory[index].refine*refinebonus[0][0]; + run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); + if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] + return 1; + } } if(sd->equip_index[10] >= 0){ // 矢 @@ -915,18 +891,6 @@ int status_calc_pc(struct map_session_data* sd,int first) sd->attackrange = sd->attackrange_; if(sd->status.weapon == 11) sd->attackrange += sd->arrow_range; - if(wele > 0) - sd->right_weapon.atk_ele = wele; - if(wele_ > 0) - sd->left_weapon.atk_ele = wele_; - if(def_ele > 0) - sd->def_ele = def_ele; - if(battle_config.pet_status_support) { - if(pele > 0 && !sd->right_weapon.atk_ele) - sd->right_weapon.atk_ele = pele; - if(pdef_ele > 0 && !sd->def_ele) - sd->def_ele = pdef_ele; - } sd->double_rate += sd->double_add_rate; sd->perfect_hit += sd->perfect_hit_add; sd->splash_range += sd->splash_add_range; @@ -3493,6 +3457,8 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val //Check rate if (!(flag&(4|1))) { rate*=100; //Pass to 10000 = 100% + if (rate > 10000) //Shouldn't let this go above 100% + rate = 10000; race = flag&8?0:status_get_sc_def(bl, type); //recycling race to store the sc_def value. //sd resistance applies even if the flag is &8 if(sd && SC_COMMON_MIN<=type && type<=SC_COMMON_MAX && sd->reseff[type-SC_COMMON_MIN] > 0) diff --git a/src/map/status.h b/src/map/status.h index 13989080f..a104b5a9d 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -365,6 +365,7 @@ enum { extern int StatusIconChangeTable[]; extern int current_equip_item_index; +extern int current_equip_card_id; //Mode definitions to clear up code reading. [Skotlex] #define MD_CANMOVE 0x001 -- cgit v1.2.3-60-g2f50