diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 8 | ||||
-rw-r--r-- | src/map/map.c | 7 | ||||
-rw-r--r-- | src/map/map.h | 1 | ||||
-rw-r--r-- | src/map/mob.c | 4 | ||||
-rw-r--r-- | src/map/pc.c | 50 | ||||
-rw-r--r-- | src/map/skill.c | 95 | ||||
-rw-r--r-- | src/map/status.c | 3 |
7 files changed, 98 insertions, 70 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 929b4494c..e47490ee6 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1437,9 +1437,8 @@ static struct Damage battle_calc_weapon_attack( if (i < 1) i = 1; //Preserve damage ratio when max cart weight is changed. if(sd && sd->cart_weight && sd->cart_max_weight) -// FIXME: Something is wrong with this check! But what...? [Skotlex] -// skillratio += (sd->cart_weight * 80000) / (i * sd->cart_max_weight) - 100; - skillratio += sd->cart_weight/i - 100; + skillratio += sd->cart_weight/i * 80000/sd->cart_max_weight - 100; +// skillratio += sd->cart_weight/i - 100; else if (!sd) skillratio += 80000 / i - 100; flag.cardfix = 0; @@ -2337,7 +2336,8 @@ struct Damage battle_calc_magic_attack( if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS) { //Apply the physical part of the skill's damage. [Skotlex] struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); - ad.damage = (wd.damage + ad.damage) * (100 + 40*skill_lv)/100; + //When mflag, this is a no-splash attack, damage gets a bonus of 100% + ad.damage = (wd.damage + ad.damage) * ((mflag?200:100) + 40*skill_lv)/100; if(src==target) { if (src->type == BL_PC) diff --git a/src/map/map.c b/src/map/map.c index a34805997..e1662fd71 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1846,6 +1846,13 @@ struct map_session_data** map_getallusers(int *users) { return all_sd; } +void map_foreachpc(int (*func)(DBKey,void*,va_list),...) { + va_list ap; + va_start(ap,func); + pc_db->foreach(pc_db,func,ap); + va_end(ap); +} + /*========================================== * id_db?‚Ì‘S‚Ä‚Éfunc‚ð?s *------------------------------------------ diff --git a/src/map/map.h b/src/map/map.h index a82f8bee1..fec279850 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1342,6 +1342,7 @@ int map_eraseallipport(void); void map_addiddb(struct block_list *);
void map_deliddb(struct block_list *bl);
struct map_session_data** map_getallusers(int *users);
+void map_foreachpc(int (*func)(DBKey,void*,va_list),...);
int map_foreachiddb(int (*)(DBKey,void*,va_list),...);
void map_addnickdb(struct map_session_data *);
struct map_session_data * map_nick2sd(char*);
diff --git a/src/map/mob.c b/src/map/mob.c index 3e425f595..72d0a8aaa 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -762,7 +762,6 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) */ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) { - struct map_session_data *sd; struct mob_data *md; struct block_list **target; int dist; @@ -789,9 +788,6 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) if (((TBL_PC*)bl)->state.gangsterparadise && !(status_get_mode(&md->bl)&MD_BOSS)) return 0; //Gangster paradise protection. - sd = (TBL_PC*)bl; //[orn] monster target homunculus while hunting - if (sd->hd && sd->homunculus.alive && (distance_bl(&md->bl, &sd->hd->bl ) < md->db->range2 ) ) // - return 0; //Gangster paradise protection. } case BL_HOMUNCULUS: //[orn] case BL_MOB: diff --git a/src/map/pc.c b/src/map/pc.c index f7c93c94f..3396de798 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -7093,25 +7093,38 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y) * Ž©“®ƒZ?ƒu ŠeƒNƒ‰ƒCƒAƒ“ƒg *------------------------------------------ */ -static int last_save_fd,save_flag; -static int pc_autosave_sub(struct map_session_data *sd,va_list ap) +static int last_save_id=0,save_flag=0; +static int pc_autosave_sub(DBKey key,void * data,va_list app) { - nullpo_retr(0, sd); + struct map_session_data *sd = (TBL_PC*)data; + + if(sd->bl.id == last_save_id) { + save_flag = 1; + return 1; + } - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + if(save_flag != 1) //Not our turn to save yet. + return 0; - if(save_flag==0 && sd->fd>last_save_fd && !sd->state.waitingdisconnect) - { - // pet - if(sd->status.pet_id > 0 && sd->pd) - intif_save_petdata(sd->status.account_id,&sd->pet); + if (sd->state.waitingdisconnect) //Invalid char to save. + return 0; - chrif_save(sd,0); - save_flag=1; - last_save_fd = sd->fd; - } + //Save char. + last_save_id = sd->bl.id; + save_flag=2; - return 0; + // pet + if(sd->status.pet_id > 0 && sd->pd) + intif_save_petdata(sd->status.account_id,&sd->pet); + + if(sd->state.finalsave) + { //Save ack hasn't returned from char-server yet? Retry. + ShowDebug("pc_autosave: Resending to save logging out char %d:%d (save ack from char-server hasn't arrived yet)\n", sd->status.account_id, sd->status.char_id); + sd->state.finalsave = 0; + chrif_save(sd,1); + } else + chrif_save(sd,0); + return 1; } /*========================================== @@ -7122,10 +7135,11 @@ int pc_autosave(int tid,unsigned int tick,int id,int data) { int interval; - save_flag=0; - clif_foreachclient(pc_autosave_sub); - if(save_flag==0) - last_save_fd=0; + if(save_flag == 2) //Someone was saved on last call, normal cycle + save_flag = 0; + else + save_flag = 1; //Noone was saved, so save first found char. + map_foreachpc(pc_autosave_sub); if (autosave_interval < 0) return 0; //Fixed interval for saving. [Skotlex] diff --git a/src/map/skill.c b/src/map/skill.c index b501e9b64..6bf357910 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1068,15 +1068,15 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int // Chance to trigger Taekwon kicks [Dralnu] if(sd->sc.count && sd->sc.data[SC_COMBO].timer == -1) { if(sd->sc.data[SC_READYSTORM].timer != -1 && - sc_start4(src,SC_COMBO, 15, TK_STORMKICK,0,0,0, + sc_start(src,SC_COMBO, 15, TK_STORMKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sd->sc.data[SC_READYDOWN].timer != -1 && - sc_start4(src,SC_COMBO, 15, TK_DOWNKICK,0,0,0, + sc_start(src,SC_COMBO, 15, TK_DOWNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sd->sc.data[SC_READYTURN].timer != -1 && - sc_start4(src,SC_COMBO, 15, TK_TURNKICK,0,0,0, + sc_start(src,SC_COMBO, 15, TK_TURNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sd->sc.data[SC_READYCOUNTER].timer != -1) @@ -1764,7 +1764,7 @@ int skill_blown (struct block_list *src, struct block_list *target, int count) if(!(count&0x20000)) clif_blown(target); - return 0; + return (count&0xFFFF); //Return amount of knocked back cells. } /* @@ -1895,7 +1895,6 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if(src == bl) type = 4; // åå‹•ã¯ãƒ€ãƒ¡ãƒ¼ã‚¸ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ãªã— } -//使用者ãŒPCã®å ´åˆã®å‡¦ç†ã“ã“ã‹ã‚‰ if(sd) { //Sorry for removing the Japanese comments, but they were actually distracting //from the actual code and I couldn't understand a thing anyway >.< [Skotlex] @@ -1910,7 +1909,13 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds sd->skillid_old = skillid; sd->skilllv_old = skilllv; if (pc_famerank(sd->char_id,MAPID_TAEKWON)) - break; //Do not end combo state. + { //Extend combo time. + delete_timer(sc->data[SC_COMBO].timer, status_change_timer); + sd->sc.data[SC_COMBO].timer = add_timer( + tick+sd->sc.data[SC_COMBO].val4, + status_change_timer, src->id, SC_COMBO); + break; + } default: status_change_end(src,SC_COMBO,-1); } @@ -1920,10 +1925,9 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case MO_TRIPLEATTACK: { int delay = 1000 - 4*sstatus->agi - 2*sstatus->dex; - if (damage < (signed int)tstatus->hp && - pc_checkskill(sd, MO_CHAINCOMBO) > 0) + if (pc_checkskill(sd, MO_CHAINCOMBO) > 0) delay += 300 * battle_config.combo_delay_rate / 100; - sc_start4(src,SC_COMBO,100,MO_TRIPLEATTACK,skilllv,0,0,delay); + sc_start(src,SC_COMBO,100,MO_TRIPLEATTACK,delay); clif_combo_delay(src, delay); if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka] @@ -1933,51 +1937,51 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case MO_CHAINCOMBO: { int delay = 1000 - 4*sstatus->agi - 2*sstatus->dex; - if(damage < (signed int)tstatus->hp && - (pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0)) + if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) delay += 300 * battle_config.combo_delay_rate /100; - sc_start4(src,SC_COMBO,100,MO_CHAINCOMBO,skilllv,0,0,delay); + sc_start(src,SC_COMBO,100,MO_CHAINCOMBO,delay); clif_combo_delay(src,delay); break; } case MO_COMBOFINISH: { int delay = 700 - 4*sstatus->agi - 2*sstatus->dex; - if(damage < (signed int)tstatus->hp && - ( + if ( (pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc.data[SC_EXPLOSIONSPIRITS].timer != -1) || (pc_checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0) || (pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1) - )) + ) delay += 300 * battle_config.combo_delay_rate /100; - sc_start4(src,SC_COMBO,100,MO_COMBOFINISH,skilllv,0,0,delay); + sc_start(src,SC_COMBO,100,MO_COMBOFINISH,delay); clif_combo_delay(src,delay); break; } case CH_TIGERFIST: { //Tigerfist is now a combo-only skill. [Skotlex] int delay = 1000 - 4*sstatus->agi - 2*sstatus->dex; - if(damage < (signed int)tstatus->hp && - ( + if( (pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 3 && sd->sc.data[SC_EXPLOSIONSPIRITS].timer != -1) || (pc_checkskill(sd, CH_CHAINCRUSH) > 0) - )) + ) delay += 300 * battle_config.combo_delay_rate /100; - sc_start4(src,SC_COMBO,100,CH_TIGERFIST,skilllv,0,0,delay); + sc_start(src,SC_COMBO,100,CH_TIGERFIST,delay); clif_combo_delay(src,delay); break; } case CH_CHAINCRUSH: { int delay = 1000 - 4*sstatus->agi - 2*sstatus->dex; - if(damage < (signed int)tstatus->hp) + if(pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && + sd->spiritball >= 1 && + sd->sc.data[SC_EXPLOSIONSPIRITS].timer != -1) delay += 300 * battle_config.combo_delay_rate /100; - sc_start4(src,SC_COMBO,100,CH_CHAINCRUSH,skilllv,0,0,delay); + sc_start(src,SC_COMBO,100,CH_CHAINCRUSH,delay); clif_combo_delay(src,delay); break; } case AC_DOUBLE: - if((tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && damage < (signed int)tstatus->hp && pc_checkskill(sd, HT_POWER)) { + if((tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && + pc_checkskill(sd, HT_POWER)) { //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] sc_start4(src,SC_COMBO,100,HT_POWER,bl->id,0,0,2000); clif_combo_delay(src,2000); @@ -2890,34 +2894,39 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int } break; - case KN_BOWLINGBASH: /* ボウリングãƒãƒƒã‚·ãƒ¥ */ + case KN_BOWLINGBASH: if(flag&1){ - /* 個別ã«ãƒ€ãƒ¡ãƒ¼ã‚¸ã‚’与ãˆã‚‹ */ - if(bl->id!=skill_area_temp[1]) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500); + if(bl->id==skill_area_temp[1]) + break; + //Splash damage is always two hits for 500% + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500); } else { - int i,c; /* 他人ã‹ã‚‰èžã„ãŸå‹•ããªã®ã§é–“é•ã£ã¦ã‚‹å¯èƒ½æ€§å¤§ï¼†åŠ¹çŽ‡ãŒæ‚ªã„ã£ã™ï¼žï¼œ */ - /* ã¾ãšã‚¿ãƒ¼ã‚²ãƒƒãƒˆã«æ”»æ’ƒã‚’åŠ ãˆã‚‹ */ - c = skill_get_blewcount(skillid,skilllv); - if(map_flag_gvg(bl->m) || status_get_mexp(bl)) - c = 0; - for(i=0;i<c;i++){ - skill_blown(src,bl,0x20000|1); - skill_area_temp[0]=0; - map_foreachinrange(skill_area_sub,bl, - skill_get_splash(skillid, skilllv),BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY, - skill_area_sub_count); - if(skill_area_temp[0]>1) break; - } - clif_blown(bl); //Update target pos. + int i,c; + c = skill_get_blewcount(skillid,skilllv); + for(i=0;i<c;i++){ + if (!skill_blown(src,bl,0x20000|1)) + break; //Can't knockback + skill_area_temp[0]=0; + map_foreachinrange(skill_area_sub,bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY, + skill_area_sub_count); + if(skill_area_temp[0]>1) break; + } + clif_blown(bl); //Update target pos. + if (i==c) { //No targets found. Single attack for 600% + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,1); + } else { skill_area_temp[1]=bl->id; - /* ãã®å¾Œã‚¿ãƒ¼ã‚²ãƒƒãƒˆä»¥å¤–ã®ç¯„囲内ã®æ•µå…¨ä½“ã«å‡¦ç†ã‚’行ㆠ*/ map_foreachinrange(skill_area_sub,bl, skill_get_splash(skillid, skilllv),BL_CHAR, src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); + //Weirdo dual-hit property, two attacks for 500% + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); + } } break; diff --git a/src/map/status.c b/src/map/status.c index 09aed9ced..613471116 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -5291,6 +5291,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val ud->attackabletime = gettick()+tick; unit_set_walkdelay(bl, gettick(), tick, 1); } + val4 = tick; //Store combo-time in val4. } break; case SC_TKREST: @@ -6347,7 +6348,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_DEVOTION: { //Check range and timeleft to preserve status [Skotlex] - //This implementation won't work for mobs because of map_id2sd, but it's a small cost in exchange of the speed of map_id2sd over map_id2sd + //This implementation won't work for mobs because of map_id2sd, but it's a small cost in exchange of the speed of map_id2sd over map_id2bl struct map_session_data *md = map_id2sd(sc->data[type].val1); if (md && check_distance_bl(bl, &md->bl, sc->data[type].val3) && (sc->data[type].val4-=1000)>0) { |