Skip to content

Commit

Permalink
Autobonus in combos and monster target drop
Browse files Browse the repository at this point in the history
- Fixed Autobonus not working in combos (bugreport:8300)
  * Combos will now have a "pos" variable that saves the combination of equipment slots used
  * Autobonus now works with combined positions rather than just a single position
  * Autobonus should now also work with all equipment slots instead of just the first 15
  * This does NOT fix problems with multiple auto-bonuses activating at the same time
- Monsters will now stop instantly if their target is completely non-existent
  * This is mainly for looters that had their loot taken
  * Hide and most other situations still use the configuration setting monster_chase_refresh
  • Loading branch information
Playtester committed Nov 1, 2014
1 parent aab669b commit b6b6b13
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 32 deletions.
2 changes: 1 addition & 1 deletion conf/battle/monster.conf
Expand Up @@ -58,7 +58,7 @@ monster_ai: 0
// x: Every x cells moved
// Regardless of this setting, a monster will always rethink its chase if it has
// reached its target. Increase this value if you want to make monsters continue
// moving after they lost their target (hide, loot picked, etc.).
// moving after they lost their target (hide, no line of sight, etc.).
monster_chase_refresh: 3

// Should mobs be able to be warped (add as needed)?
Expand Down
2 changes: 2 additions & 0 deletions src/map/itemdb.c
Expand Up @@ -1632,8 +1632,10 @@ void itemdb_reload(void) {
if( sd->combos.count ) {
aFree(sd->combos.bonus);
aFree(sd->combos.id);
aFree(sd->combos.pos);
sd->combos.bonus = NULL;
sd->combos.id = NULL;
sd->combos.pos = NULL;
sd->combos.count = 0;
if( pc_load_combo(sd) > 0 )
status_calc_pc(sd, SCO_FORCE);
Expand Down
5 changes: 3 additions & 2 deletions src/map/mob.c
Expand Up @@ -1446,8 +1446,9 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
)) { //No valid target
if (mob_warpchase(md, tbl))
return true; //Chasing this target.
if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh))
return true; //Walk at least "mob_chase_refresh" cells before dropping the target
if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)
&& (tbl || md->ud.walkpath.path_pos == 0))
return true; //Walk at least "mob_chase_refresh" cells before dropping the target unless target is non-existent
mob_unlocktarget(md, tick); //Unlock target
tbl = NULL;
}
Expand Down
37 changes: 29 additions & 8 deletions src/map/pc.c
Expand Up @@ -2113,7 +2113,7 @@ static void pc_bonus_item_drop(struct s_add_drop *drop, const short max, unsigne
drop[i].rate = rate;
}

bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill)
bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned int pos,bool onskill)
{
int i;

Expand Down Expand Up @@ -2159,14 +2159,19 @@ void pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,
{
if( autobonus[i].active != INVALID_TIMER )
{
if( restore && sd->state.autobonus&autobonus[i].pos )
if( restore && (sd->state.autobonus&autobonus[i].pos) == autobonus[i].pos)
{
if( autobonus[i].bonus_script )
{
int j;
ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
if( j < EQI_MAX )
script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]);
unsigned int equip_pos = 0;
//Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester]
for(j = 0; j < EQI_MAX; j++) {
if(sd->equip_index[j] >= 0)
equip_pos |= sd->status.inventory[sd->equip_index[j]].equip;
}
if((equip_pos&autobonus[i].pos) == autobonus[i].pos)
script_run_autobonus(autobonus[i].bonus_script,sd,autobonus[i].pos);
}
continue;
}
Expand All @@ -2193,9 +2198,14 @@ void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
if( autobonus->other_script )
{
int j;
ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
if( j < EQI_MAX )
script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
unsigned int equip_pos = 0;
//Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester]
for(j = 0; j < EQI_MAX; j++) {
if(sd->equip_index[j] >= 0)
equip_pos |= sd->status.inventory[sd->equip_index[j]].equip;
}
if((equip_pos&autobonus->pos) == autobonus->pos)
script_run_autobonus(autobonus->other_script,sd,autobonus->pos);
}

autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus);
Expand Down Expand Up @@ -8923,6 +8933,7 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
} *combo_idx;
int idx, j;
int nb_itemCombo;
unsigned int pos = 0;
/* ensure this isn't a duplicate combo */
if( sd->combos.bonus != NULL ) {
int x;
Expand Down Expand Up @@ -8967,6 +8978,7 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
continue;
}
combo_idx[j].idx = index;
pos |= sd->status.inventory[index].equip;
found = true;
break;
} else { //Cards
Expand Down Expand Up @@ -8994,6 +9006,7 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
continue;
combo_idx[j].idx = index;
combo_idx[j].card[z] = id;
pos |= sd->status.inventory[index].equip;
found = true;
break;
}
Expand All @@ -9011,15 +9024,19 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
if( sd->combos.bonus == NULL ) {
CREATE(sd->combos.bonus, struct script_code *, 1);
CREATE(sd->combos.id, unsigned short, 1);
CREATE(sd->combos.pos, unsigned int, 1);
sd->combos.count = 1;
} else {
RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
RECREATE(sd->combos.id, unsigned short, sd->combos.count);
RECREATE(sd->combos.pos, unsigned int, sd->combos.count);
}
/* we simply copy the pointer */
sd->combos.bonus[idx] = data->combos[i]->script;
/* save this combo's id */
sd->combos.id[idx] = data->combos[i]->id;
/* save pos of combo*/
sd->combos.pos[idx] = pos;
success++;
}
return success;
Expand All @@ -9046,6 +9063,7 @@ static int pc_removecombo(struct map_session_data *sd, struct item_data *data )

sd->combos.bonus[x] = NULL;
sd->combos.id[x] = 0;
sd->combos.pos[x] = 0;
retval++;

/* check if combo requirements still fit */
Expand All @@ -9060,6 +9078,7 @@ static int pc_removecombo(struct map_session_data *sd, struct item_data *data )
if( cursor != j ) {
sd->combos.bonus[cursor] = sd->combos.bonus[j];
sd->combos.id[cursor] = sd->combos.id[j];
sd->combos.pos[cursor] = sd->combos.pos[j];
}
cursor++;
}
Expand All @@ -9068,8 +9087,10 @@ static int pc_removecombo(struct map_session_data *sd, struct item_data *data )
if( (sd->combos.count = cursor) == 0 ) {
aFree(sd->combos.bonus);
aFree(sd->combos.id);
aFree(sd->combos.pos);
sd->combos.bonus = NULL;
sd->combos.id = NULL;
sd->combos.pos = NULL;
return retval; /* we also can return at this point for we have no more combos to check */
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/map/pc.h
Expand Up @@ -129,7 +129,7 @@ struct s_autobonus {
unsigned int duration;
char *bonus_script, *other_script;
int active;
unsigned short pos;
unsigned int pos;
};

struct skill_cooldown_entry {
Expand Down Expand Up @@ -220,7 +220,7 @@ struct map_session_data {
unsigned short autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
unsigned short autoloottype;
unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid
unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
unsigned int autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
unsigned int gmaster_flag : 1;
unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
unsigned int warping : 1;//states whether you're in the middle of a warp processing
Expand Down Expand Up @@ -563,6 +563,7 @@ struct map_session_data {
struct s_combos {
struct script_code **bonus;/* the script */
unsigned short *id;/* array of combo ids */
unsigned int *pos;/* array of positions*/
unsigned char count;
} combos;

Expand Down Expand Up @@ -902,7 +903,7 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd,

void pc_updateweightstatus(struct map_session_data *sd);

bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill);
bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned int pos,bool onskill);
void pc_exeautobonus(struct map_session_data* sd,struct s_autobonus *bonus);
int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data);
void pc_delautobonus(struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore);
Expand Down
57 changes: 42 additions & 15 deletions src/map/script.c
Expand Up @@ -308,6 +308,8 @@ const char* parse_syntax(const char* p);
static int parse_syntax_for_flag = 0;

extern short current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
extern unsigned int current_equip_combo_pos;

int potion_flag=0; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
int potion_target=0;
Expand Down Expand Up @@ -4044,14 +4046,24 @@ static int db_script_free_code_sub(DBKey key, DBData *data, va_list ap)
return 0;
}

void script_run_autobonus(const char *autobonus, int id, int pos)
void script_run_autobonus(const char *autobonus, struct map_session_data *sd, unsigned int pos)
{
struct script_code *script = (struct script_code *)strdb_get(autobonus_db, autobonus);

if( script )
{
current_equip_item_index = pos;
run_script(script,0,id,0);
int j;
ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == pos );
if( j < EQI_MAX ) {
//Single item autobonus
current_equip_item_index = sd->equip_index[j];
current_equip_combo_pos = 0;
} else {
//Combo autobonus
current_equip_item_index = -1;
current_equip_combo_pos = pos;
}
run_script(script,0,sd->bl.id,0);
}
}

Expand Down Expand Up @@ -8455,7 +8467,7 @@ BUILDIN_FUNC(bonus)

BUILDIN_FUNC(autobonus)
{
unsigned int dur;
unsigned int dur, pos;
short rate;
short atk_type = 0;
TBL_PC* sd;
Expand All @@ -8465,13 +8477,18 @@ BUILDIN_FUNC(autobonus)
if( sd == NULL )
return 0; // no player attached

if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip )
if (current_equip_combo_pos)
pos = current_equip_combo_pos;
else
pos = sd->status.inventory[current_equip_item_index].equip;

if((sd->state.autobonus&pos) == pos)
return 0;

rate = script_getnum(st,3);
dur = script_getnum(st,4);
bonus_script = script_getstr(st,2);
if( !rate || !dur || !bonus_script )
if( !rate || !dur || !pos || !bonus_script )
return 0;

if( script_hasdata(st,5) )
Expand All @@ -8480,7 +8497,7 @@ BUILDIN_FUNC(autobonus)
other_script = script_getstr(st,6);

if( pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus),
bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) )
bonus_script,rate,dur,atk_type,other_script,pos,false) )
{
script_add_autobonus(bonus_script);
if( other_script )
Expand All @@ -8492,7 +8509,7 @@ BUILDIN_FUNC(autobonus)

BUILDIN_FUNC(autobonus2)
{
unsigned int dur;
unsigned int dur, pos;
short rate;
short atk_type = 0;
TBL_PC* sd;
Expand All @@ -8502,13 +8519,18 @@ BUILDIN_FUNC(autobonus2)
if( sd == NULL )
return 0; // no player attached

if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip )
if (current_equip_combo_pos)
pos = current_equip_combo_pos;
else
pos = sd->status.inventory[current_equip_item_index].equip;

if((sd->state.autobonus&pos) == pos)
return 0;

rate = script_getnum(st,3);
dur = script_getnum(st,4);
bonus_script = script_getstr(st,2);
if( !rate || !dur || !bonus_script )
if( !rate || !dur || !pos || !bonus_script )
return 0;

if( script_hasdata(st,5) )
Expand All @@ -8517,7 +8539,7 @@ BUILDIN_FUNC(autobonus2)
other_script = script_getstr(st,6);

if( pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2),
bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) )
bonus_script,rate,dur,atk_type,other_script,pos,false) )
{
script_add_autobonus(bonus_script);
if( other_script )
Expand All @@ -8529,7 +8551,7 @@ BUILDIN_FUNC(autobonus2)

BUILDIN_FUNC(autobonus3)
{
unsigned int dur;
unsigned int dur, pos;
short rate,atk_type;
TBL_PC* sd;
const char *bonus_script, *other_script = NULL;
Expand All @@ -8539,7 +8561,12 @@ BUILDIN_FUNC(autobonus3)
if( sd == NULL )
return 0; // no player attached

if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip )
if (current_equip_combo_pos)
pos = current_equip_combo_pos;
else
pos = sd->status.inventory[current_equip_item_index].equip;

if((sd->state.autobonus&pos) == pos)
return 0;

rate = script_getnum(st,3);
Expand All @@ -8548,14 +8575,14 @@ BUILDIN_FUNC(autobonus3)
get_val(st, data); // Convert into value in case of a variable
atk_type = ( data_isstring(data) ? skill_name2id(script_getstr(st,5)) : script_getnum(st,5) );
bonus_script = script_getstr(st,2);
if( !rate || !dur || !atk_type || !bonus_script )
if( !rate || !dur || !pos || !atk_type || !bonus_script )
return 0;

if( script_hasdata(st,6) )
other_script = script_getstr(st,6);

if( pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3),
bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) )
bonus_script,rate,dur,atk_type,other_script,pos,true) )
{
script_add_autobonus(bonus_script);
if( other_script )
Expand Down
2 changes: 1 addition & 1 deletion src/map/script.h
Expand Up @@ -176,7 +176,7 @@ void script_free_state(struct script_state* st);

struct DBMap* script_get_label_db(void);
struct DBMap* script_get_userfunc_db(void);
void script_run_autobonus(const char *autobonus,int id, int pos);
void script_run_autobonus(const char *autobonus, struct map_session_data *sd, unsigned int pos);

bool script_get_constant(const char* name, int* value);
void script_set_constant(const char* name, int value, bool isparameter);
Expand Down
6 changes: 6 additions & 0 deletions src/map/status.c
Expand Up @@ -61,6 +61,7 @@ static struct eri *sc_data_ers; /// For sc_data entries
static struct status_data dummy_status;

short current_equip_item_index; /// Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
unsigned int current_equip_combo_pos; /// For combo items we need to save the position of all involved items here
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

Expand Down Expand Up @@ -2957,6 +2958,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
// Parse equipment
for (i = 0; i < EQI_MAX; i++) {
current_equip_item_index = index = sd->equip_index[i]; // We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
current_equip_combo_pos = 0;
if (index < 0)
continue;
if (i == EQI_AMMO)
Expand Down Expand Up @@ -3065,6 +3067,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
bool no_run = false;
struct item_combo *combo = NULL;

current_equip_item_index = -1;
current_equip_combo_pos = sd->combos.pos[i];

if (!sd->combos.bonus[i] || !(combo = itemdb_combo_exists(sd->combos.id[i])))
continue;
// Check combo items
Expand Down Expand Up @@ -3094,6 +3099,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
// Parse Cards
for (i = 0; i < EQI_MAX; i++) {
current_equip_item_index = index = sd->equip_index[i]; // We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
current_equip_combo_pos = 0;
if (index < 0)
continue;
if (i == EQI_AMMO)
Expand Down
1 change: 1 addition & 0 deletions src/map/status.h
Expand Up @@ -1536,6 +1536,7 @@ enum e_joint_break
};

extern short current_equip_item_index;
extern unsigned int current_equip_combo_pos;
extern int current_equip_card_id;

//Mode definitions to clear up code reading. [Skotlex]
Expand Down

0 comments on commit b6b6b13

Please sign in to comment.