summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c13
-rw-r--r--src/map/mob.c59
-rw-r--r--src/map/mob.h2
-rw-r--r--src/map/party.c69
-rw-r--r--src/map/party.h2
-rw-r--r--src/map/pc.c58
-rw-r--r--src/map/script.c4
-rw-r--r--src/map/skill.c59
-rw-r--r--src/map/status.c5
9 files changed, 154 insertions, 117 deletions
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 <stdarg.h>
+#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);
}
}