Autobonus in combos and monster target drop
- 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
This commit is contained in:
parent
aab669b685
commit
b6b6b1366a
@ -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)?
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
37
src/map/pc.c
37
src/map/pc.c
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
@ -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 */
|
||||
@ -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++;
|
||||
}
|
||||
@ -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 */
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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) )
|
||||
@ -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 )
|
||||
@ -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;
|
||||
@ -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) )
|
||||
@ -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 )
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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 )
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
@ -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)
|
||||
@ -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
|
||||
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -1067,7 +1067,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
|
||||
* @param flag
|
||||
* 0x1 - Offensive (not set: self skill, e.g. Backslide)
|
||||
* 0x2 - Knockback type (not set: Stop type, e.g. Ankle Snare)
|
||||
* 0x4 - Boss attack
|
||||
* 0x4 - Boss attack
|
||||
* @return reason for immunity
|
||||
* 0 - can be knocked back / stopped
|
||||
* 1 - at WOE/BG map;
|
||||
@ -1075,7 +1075,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
|
||||
* 3 - target is MD_KNOCKBACK_IMMUNE|MD_BOSS;
|
||||
* 4 - target is in Basilica area;
|
||||
* 5 - target has 'special_state.no_knockback';
|
||||
* 6 - target is trap that cannot be knocked back
|
||||
* 6 - target is trap that cannot be knocked back
|
||||
*/
|
||||
int unit_blown_immune(struct block_list* bl, int flag)
|
||||
{
|
||||
@ -3131,6 +3131,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
if( sd->combos.count ) {
|
||||
aFree(sd->combos.bonus);
|
||||
aFree(sd->combos.id);
|
||||
aFree(sd->combos.pos);
|
||||
sd->combos.count = 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user