summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-02-23 16:31:16 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-02-23 16:31:16 +0000
commit07e03074151d0361be665c05e140eca8e89295ca (patch)
tree27f45515a8e87d04a470ae4773e3d49279e38f5e /src
parentbe36c563041ad7131b1b5dc86771d167b355a619 (diff)
downloadhercules-07e03074151d0361be665c05e140eca8e89295ca.tar.gz
hercules-07e03074151d0361be665c05e140eca8e89295ca.tar.bz2
hercules-07e03074151d0361be665c05e140eca8e89295ca.tar.xz
hercules-07e03074151d0361be665c05e140eca8e89295ca.zip
- 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
Diffstat (limited to 'src')
-rw-r--r--src/char_sql/char.c2
-rw-r--r--src/map/battle.c2
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/clif.c2
-rw-r--r--src/map/map.h4
-rw-r--r--src/map/pc.c84
-rw-r--r--src/map/skill.c3
-rw-r--r--src/map/status.c162
-rw-r--r--src/map/status.h1
9 files changed, 106 insertions, 155 deletions
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index dca9a28a1..0faf23e0a 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -3217,7 +3217,7 @@ int parse_char(int fd) {
WFIFOL(fd,2+28) = char_dat[i].karma;
WFIFOL(fd,2+32) = char_dat[i].manner;
- WFIFOW(fd,2+40) = 0x30;
+ WFIFOW(fd,2+40) = 0x30;
WFIFOW(fd,2+42) = (char_dat[i].hp > 0x7fff) ? 0x7fff : char_dat[i].hp;
WFIFOW(fd,2+44) = (char_dat[i].max_hp > 0x7fff) ? 0x7fff : char_dat[i].max_hp;
WFIFOW(fd,2+46) = (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp;
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]; // 武器ATKサイズ修正(size_fix.txt)
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;j<sd->inventory_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;j<sd->inventory_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;j<sd->inventory_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