From 7564712d7fc9d13890011fdd22215e9ff912e1a4 Mon Sep 17 00:00:00 2001 From: skotlex Date: Wed, 1 Mar 2006 18:18:32 +0000 Subject: - Turn Undead and Offensive Resurrection should now work on undead players. - Fixed the range checking of Repair weapon - Rude attacked is now also triggered when you hit a target that can't move out of their melee attack range. - Mob ai will attempt to do a long-range attacked condition skill before unlocking a target when it is attacked and said target is out of melee range of a non-walking mob. - Corrected mobskill event to set the target_id before triggering. - Moved MSC_SKILLUSED trigger to mobskill_event which is triggered in battle_calc_damage. It is also triggered on skill_castend_nodamage_id - Added party_share_loot for handling party-share loot. it should now work with autoloot as well. - Fixed skill_break_rate breaking stuff even if the rate is 0. - pc_stopwalking will not send a fixpos packet if you are sitting. - mob_can_reach rude-attacked condition now uses the mob's field of view. - SC_NOCHAT is automatically started on pc_authok if manner is negative. - Map server now refuses to start if you try to define a label with the same name as some const.txt defined character parameter. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5414 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 13 +++++++---- src/map/mob.c | 59 +++++++++++++++++++++++++++++++----------------- src/map/mob.h | 2 +- src/map/party.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/map/party.h | 2 ++ src/map/pc.c | 58 +++++------------------------------------------ src/map/script.c | 4 ++++ src/map/skill.c | 59 ++++++++++++++++++++---------------------------- src/map/status.c | 5 ++-- 9 files changed, 154 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/map/battle.c b/src/map/battle.c index 6913c0294..ee7c4e6a8 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -755,8 +755,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i damage = div_; } - if( md!=NULL && md->hp>0 && damage > 0 ) // 反撃などのMOBスキル判定 - mobskill_event(md,flag); + if( md && !status_isdead(bl) && src != bl) { + if (damage > 0 ) + mobskill_event(md,src,gettick(),flag); + if (skill_num) + mobskill_event(md,src,gettick(),MSC_SKILLUSED|(skill_num<<16)); + } return damage; } @@ -2268,7 +2272,8 @@ static struct Damage battle_calc_weapon_attack( if(sc->data[SC_MAXOVERTHRUST].timer!=-1) breakrate += 10; } - skill_break_equip(src, EQP_WEAPON, breakrate, BCT_SELF); + if (breakrate) + skill_break_equip(src, EQP_WEAPON, breakrate, BCT_SELF); } if (battle_config.equip_skill_break_rate) { // Target equipment breaking @@ -2471,7 +2476,7 @@ struct Damage battle_calc_magic_attack( break; case ALL_RESURRECTION: case PR_TURNUNDEAD: - if(!tsd && battle_check_undead(t_race,t_ele)){ + if(battle_check_undead(t_race,t_ele)){ int hp, mhp, thres; hp = status_get_hp(target); mhp = status_get_max_hp(target); diff --git a/src/map/mob.c b/src/map/mob.c index a4f61b98c..8719b6fa3 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1620,12 +1620,12 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) (dist = distance_bl(&md->bl, abl)) >= 32 || battle_check_target(bl, abl, BCT_ENEMY) <= 0 || (battle_config.mob_ai&2 && !status_check_skilluse(bl, abl, 0, 0)) || - !mob_can_reach(md, abl, dist+2, MSS_RUSH || + !mob_can_reach(md, abl, md->db->range2, MSS_RUSH) || ( //Gangster Paradise check abl->type == BL_PC && !(mode&MD_BOSS) && ((struct map_session_data*)abl)->state.gangsterparadise ) - )) { //Can't attack back + ) { //Can't attack back if (md->attacked_count++ > 3) { if (mobskill_use(md, tick, MSC_RUDEATTACKED) == 0 && mode&MD_CANMOVE && mob_can_move(md)) @@ -1720,8 +1720,11 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) } if (!battle_check_range (&md->bl, tbl, md->db->range)) { //Out of range... - if (!(mode & MD_CANMOVE)) - { //Can't chase. + if (!(mode&MD_CANMOVE)) + { //Can't chase. Attempt to use a ranged skill at least? + if (mobskill_use(md, tick, MSC_LONGRANGEATTACKED) == 0) + md->attacked_count++; //Increase rude-attacked count as it can't attack back. + mob_unlocktarget(md,tick); return 0; } @@ -2074,13 +2077,16 @@ static void mob_item_drop(struct mob_data *md, unsigned int tick, struct delay_i if (ditem->first_sd && ditem->first_sd->state.autoloot && (drop_rate <= ditem->first_sd->state.autoloot || ditem->first_sd->state.autoloot >= 10000) //Fetch 100% drops - && pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount) == 0) - { //Autolooted. - if(log_config.pick > 0) - log_pick(ditem->first_sd, "P", 0, ditem->item_data.nameid, ditem->item_data.amount, &ditem->item_data); - aFree(ditem); - } else - add_timer(tick, mob_delay_item_drop, (int)ditem, 0); + ) { //Autoloot. + if (party_share_loot( + party_search(ditem->first_sd->status.party_id), + ditem->first_sd,&ditem->item_data) + ) { + aFree(ditem); + return; + } + } + add_timer(tick, mob_delay_item_drop, (int)ditem, 0); } /*========================================== @@ -3885,18 +3891,29 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) * Skill use event processing *------------------------------------------ */ -int mobskill_event(struct mob_data *md, int flag) +int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tick, int flag) { - int tick = gettick(); - nullpo_retr(0, md); + int target_id, res = 0; - if (flag == -1 && mobskill_use(md, tick, MSC_CASTTARGETED)) - return 1; - if ((flag & BF_SHORT) && mobskill_use(md, tick, MSC_CLOSEDATTACKED)) - return 1; - if ((flag & BF_LONG) && mobskill_use(md, tick, MSC_LONGRANGEATTACKED)) - return 1; - return 0; + target_id = md->target_id; + if (!target_id || (battle_config.mob_changetarget_byskill && + battle_check_target(&md->bl, src, BCT_ENEMY) > 0)) + md->target_id = src->id; + + if (flag == -1) + res = mobskill_use(md, tick, MSC_CASTTARGETED); + else if ((flag&0xffff) == MSC_SKILLUSED) + res = mobskill_use(md,tick,flag); + else if (flag&BF_SHORT) + res = mobskill_use(md, tick, MSC_CLOSEDATTACKED); + else if (flag&BF_LONG) + res = mobskill_use(md, tick, MSC_LONGRANGEATTACKED); + + if (target_id && !res) + //Restore previous target only if skill condition failed to trigger. [Skotlex] + md->target_id = target_id; + + return res; } /*========================================== diff --git a/src/map/mob.h b/src/map/mob.h index a36aa10a4..c719c721b 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -160,7 +160,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type); int mob_warpslave(struct block_list *bl, int range); int mobskill_use(struct mob_data *md,unsigned int tick,int event); -int mobskill_event(struct mob_data *md,int flag); +int mobskill_event(struct mob_data *md,struct block_list *src,unsigned int tick, int flag); int mobskill_castend_id( int tid, unsigned int tick, int id,int data ); int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ); int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id); diff --git a/src/map/party.c b/src/map/party.c index 65486dcea..98f4b80ca 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -696,13 +696,76 @@ int party_exp_share(struct party *p,int map,unsigned int base_exp,unsigned int j return 0; } -int party_send_dot_remove(struct map_session_data *sd) +int party_share_loot(struct party *p, TBL_PC *sd, struct item *item_data) { - if (sd->status.party_id) - clif_party_xy_remove(sd); + TBL_PC *target=NULL; + int i; + if (p && p->item&2) { + //item distribution to party members. + if (battle_config.party_share_type) { //Round Robin + TBL_PC *psd; + i = p->itemc; + do { + i++; + if (i >= MAX_PARTY) + i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc" + if ((psd=p->member[i].sd)==NULL || sd->bl.m != psd->bl.m) + continue; + + if (pc_additem(psd,item_data,item_data->amount)) + continue; //Chosen char can't pick up loot. + //Successful pick. + p->itemc = i; + target = psd; + break; + } while (i != p->itemc); + } else { //Random pick + TBL_PC *psd[MAX_PARTY]; + int count=0; + //Collect pick candidates + for (i = 0; i < MAX_PARTY; i++) { + if ((psd[count]=p->member[i].sd) && psd[count]->bl.m == sd->bl.m) + count++; + } + if (count > 0) { //Pick a random member. + do { + i = rand()%count; + if (pc_additem(psd[i],item_data,item_data->amount)) + { //Discard this receiver. + psd[i] = psd[count-1]; + count--; + } else { //Successful pick. + target = psd[i]; + break; + } + } while (count > 0); + } + } + } + if (!target) { //Give it to the owner. + target = sd; + if (!(i=pc_additem(sd,item_data,item_data->amount))) + return i; + } + + if(log_config.pick) //Logs items, taken by (P)layers [Lupus] + log_pick(target, "P", 0, item_data->nameid, item_data->amount, item_data); + //Logs + if(battle_config.party_show_share_picker && target != sd){ + char output[80]; + sprintf(output, "%s acquired the item.",target->status.name); + clif_disp_onlyself(sd,output,strlen(output)); + } return 0; } +int party_send_dot_remove(struct map_session_data *sd) +{ +if (sd->status.party_id) + clif_party_xy_remove(sd); +return 0; +} + // To use for Taekwon's "Fighting Chant" // int c = 0; // party_foreachsamemap(party_sub_count, sd, 0, &c); diff --git a/src/map/party.h b/src/map/party.h index f1a3f5fcc..76954a4c5 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -5,6 +5,7 @@ #define _PARTY_H_ #include +#include "map.h" extern int party_share_level; struct party; @@ -39,6 +40,7 @@ int party_check_conflict(struct map_session_data *sd); int party_skill_check(struct map_session_data *sd, int party_id, int skillid, int skilllv); int party_send_xy_clear(struct party *p); int party_exp_share(struct party *p,int map,unsigned int base_exp,unsigned int job_exp,int zeny); +int party_share_loot(struct party *p, TBL_PC *sd, struct item *item_data); int party_send_dot_remove(struct map_session_data *sd); int party_sub_count(struct block_list *bl, va_list ap); int party_foreachsamemap(int (*func)(struct block_list *,va_list),struct map_session_data *sd,int type,...); diff --git a/src/map/pc.c b/src/map/pc.c index c0d8d0aa1..18b943965 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -845,6 +845,8 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); } + if(sd->status.manner < 0) //Needed or manner will always be negative. + status_change_start(&sd->bl,SC_NOCHAT,100,0,0,0,0,0,0); return 0; } @@ -2590,63 +2592,15 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem) } first_sd = NULL; //First_sd will store who picked up the item. if (p && p->item&2) { //item distribution to party members. - first_sd = NULL; - if (battle_config.party_share_type) { //Round Robin - int i; - i = p->itemc; - do { - i++; - if (i >= MAX_PARTY) - i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc" - if ((second_sd=p->member[i].sd)==NULL || sd->bl.m != second_sd->bl.m) - continue; - - if (pc_additem(second_sd,&fitem->item_data,fitem->item_data.amount)) - continue; //Chosen char can't pick up loot. - //Successful pick. - first_sd = second_sd; - break; - } while (i != p->itemc); - // Skip to the current receiver of an item, so the next pick should not go to him again. - p->itemc = i; - } else { //Random pick - struct map_session_data*psd[MAX_PARTY]; - int i, count=0; - //Collect pick candidates - for (i = 0; i < MAX_PARTY; i++) { - if ((psd[count]=p->member[i].sd) && psd[count]->bl.m == sd->bl.m) - count++; - } - if (count > 0) { //Pick a random member. - do { - i = rand()%count; - if (pc_additem(psd[i],&fitem->item_data,fitem->item_data.amount)) - { //Discard this receiver. - psd[i] = psd[count-1]; - count--; - } else { //Successful pick. - first_sd = psd[i]; - break; - } - } while (count > 0); - } - } - } - if (!first_sd) { //Noone has picked it up yet... - if ((flag = pc_additem(sd,&fitem->item_data,fitem->item_data.amount))) { + if ((flag = party_share_loot(p,sd,&fitem->item_data))) { clif_additem(sd,0,0,flag); return 1; } first_sd = sd; - } + } else if(log_config.pick) //Logs items, taken by (P)layers [Lupus] log_pick(first_sd, "P", 0, fitem->item_data.nameid, fitem->item_data.amount, (struct item*)&fitem->item_data); - //Logs - if(battle_config.party_show_share_picker && first_sd != sd){ - char output[80]; - sprintf(output, "%s acquired the item.",first_sd->status.name); - clif_disp_onlyself(sd,output,strlen(output)); - } + //Display pickup animation. if(sd->attacktimer != -1) @@ -3698,7 +3652,7 @@ int pc_stop_walking (struct map_session_data *sd, int type) sd->walkpath.path_len = 0; sd->to_x = sd->bl.x; sd->to_y = sd->bl.y; - if (type & 0x01) + if (type & 0x01 && !pc_issit(sd)) //Trying to fixpos while sitting makes you seem standing. [Skotlex] clif_fixpos(&sd->bl); if (sd->sc.data[SC_RUN].timer != -1) status_change_end(&sd->bl, SC_RUN, -1); diff --git a/src/map/script.c b/src/map/script.c index 2bee93f63..ee1100ac8 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1755,6 +1755,10 @@ unsigned char* parse_syntax(unsigned char *p) { // 関数名のラベルを付ける *p = 0; l=add_str(func_name); + if(str_data[l].type == C_PARAM) { + disp_error_message("invalid label name ",p); + exit(1); + } if(str_data[l].type == C_NOP) { str_data[l].type = C_USERFUNC; } diff --git a/src/map/skill.c b/src/map/skill.c index e29784924..07e6ea73b 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1426,7 +1426,7 @@ int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int if (where&where_list[i]) { if (sc && sc->count && sc->data[scdef[i]].timer != -1) where&=~where_list[i]; - else if (rand()%10000 > rate) + else if (rand()%10000 >= rate) where&=~where_list[i]; else if (!sd) //Cause Strip effect. status_change_start(bl,scatk[i],100,0,0,0,0, @@ -1894,23 +1894,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds if (dmg.dmg_lv == ATK_DEF || damage > 0) //Counter status effects [Skotlex] skill_counter_additional_effect(dsrc,bl,skillid,skilllv,attack_type,tick); - /* ダ??ジがあるなら追加?果判定 */ - if(!status_isdead(bl) && bl->type==BL_MOB && src!=bl) /* スキル使用?件のMOBスキル */ - { - struct mob_data *md=(struct mob_data *)bl; -// nullpo_retr(0, md); //Just so you know.. these are useless. When you cast a pointer, the pointer still is the same, so if bl is not null, the after-casted pointer will never be nulll :/ [Skotlex] - if(battle_config.mob_changetarget_byskill && sd) - { - int target ; - target=md->target_id; - md->target_id=src->id; - mobskill_use(md,tick,MSC_SKILLUSED|(skillid<<16)); - md->target_id=target; - } - else - mobskill_use(md,tick,MSC_SKILLUSED|(skillid<<16)); - } - if(sd && dmg.flag&BF_WEAPON && src != bl && src == dsrc && damage > 0) { int hp = 0,sp = 0; if(sd->right_weapon.hp_drain_rate && sd->right_weapon.hp_drain_per > 0 && dmg.damage > 0 && rand()%1000 < sd->right_weapon.hp_drain_rate) { @@ -5655,6 +5638,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in return 1; } + if (dstmd) //Mob skill event for no damage skills (damage ones are handled in battle_calc_damage) [Skotlex] + mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skillid<<16)); + map_freeblock_unlock(); return 0; } @@ -8640,21 +8626,26 @@ int skill_use_id (struct map_session_data *sd, int target_id, int skill_num, int else clif_skillcasting(&sd->bl,sd->bl.id, target_id, 0,0, skill_num,casttime); /* 詠?・反?モンスタ? */ - if (bl->type == BL_MOB && (mode = status_get_mode(bl))&MD_CASTSENSOR && (md = (struct mob_data *)bl) && - (!md->special_state.ai || skill_get_inf(skill_num) != INF_SUPPORT_SKILL) //Avoid having summons target master from supportive skills. [Skotlex] - ) { - switch (md->state.skillstate) { - case MSS_ANGRY: - case MSS_RUSH: - case MSS_FOLLOW: - if (!(mode&(MD_AGGRESSIVE|MD_ANGRY))) - break; //Only Aggressive mobs change target while chasing. - case MSS_IDLE: - case MSS_WALK: - md->target_id = sd->bl.id; - md->state.targettype = ATTACKABLE; - md->state.aggressive = (mode&MD_ANGRY)?1:0; - md->min_chase = md->db->range3; + if (bl->type == BL_MOB) + { + md = (struct mob_data *)bl; + mobskill_event(md, &sd->bl, tick, -1); //Cast targetted skill event. + if ((mode=status_get_mode(bl))&MD_CASTSENSOR && + battle_check_target(bl, &sd->bl, BCT_ENEMY) > 0) + { + switch (md->state.skillstate) { + case MSS_ANGRY: + case MSS_RUSH: + case MSS_FOLLOW: + if (!(mode&(MD_AGGRESSIVE|MD_ANGRY))) + break; //Only Aggressive mobs change target while chasing. + case MSS_IDLE: + case MSS_WALK: + md->target_id = sd->bl.id; + md->state.targettype = ATTACKABLE; + md->state.aggressive = (mode&MD_ANGRY)?1:0; + md->min_chase = md->db->range3; + } } } } @@ -9038,7 +9029,7 @@ void skill_repairweapon(struct map_session_data *sd, int idx) if(item->nameid <= 0 || item->attribute == 0) return; //Again invalid item.... - if(sd!=target_sd && !battle_check_range(&sd->bl,&target_sd->bl,skill_get_range2(&sd->bl, sd->skillid,sd->skilllv))){ + if(sd!=target_sd && !battle_check_range(&sd->bl,&target_sd->bl,skill_get_range2(&sd->bl, sd->menuskill_id,pc_checkskill(sd, sd->menuskill_id)))){ clif_item_repaireffect(sd,item->nameid,1); return; } diff --git a/src/map/status.c b/src/map/status.c index 91740d663..a39adbc62 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -4848,8 +4848,9 @@ int status_change_end( struct block_list* bl , int type,int tid ) case SC_NOCHAT: //チャット禁止?態 if (sd) { if(battle_config.manner_system){ - if (sd->status.manner >= 0) // weeee ^^ [celest] - sd->status.manner = 0; + //Why set it to 0? Can't we use good manners for something? [Skotlex] +// if (sd->status.manner >= 0) // weeee ^^ [celest] +// sd->status.manner = 0; clif_updatestatus(sd,SP_MANNER); } } -- cgit v1.2.3-70-g09d2