From e7096ca70629c5fd5f824cec8e2d4307e8578913 Mon Sep 17 00:00:00 2001 From: skotlex Date: Mon, 6 Feb 2006 18:38:51 +0000 Subject: - Added define clif_deadsit to send the dead state into player packets if the player is in trick dead state. - Venom Splasher always hits (but splash damage targets can still avoid it) - Using autoloot with no arguments now toggles it between @autoloot 0 and @autoloot 100% - Falcon Assault now takes Blitz Beat lv5 as base damage. - Fixed pc_makesavestatus not updating status.option correctly. - Corrected Waterball so that higher levels can do insane amount of hits. - Altered slave behaviour. No more random walking, will stay within 2 cells of their master. - Reverted the Summon Slave behaviour to not adjust level based on number of current slaves. - Coma no longer sends SP to 1. - Updated Meteor so that when level 11 or more is casted, the area over which meteors fall is tripled. - Dark elemental characters are now inmune to Curse. - Fixed sc_data saving to sql buffer building method. Thanks to its_sparky. - Changed the map zone reading from using pow to a bit shift. - Experience has now been changed to unsigned int, and is read as such from the dbs. - Increased HT_DETECTING seek range to 7x7 - Added function map_foreachinrange which actually checks distance of nearing objects (unlike for each in area which uses a square area), may come handy for future code. - Corrected Venom Splasher: Being hit does not cancels it, works at 75% or less of target's HP, being hit normally while under the count has a chance of causing poison. Damage is +400% + 50*lv% git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5204 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/char_sql/char.c | 7 ++--- src/common/core.h | 8 ------ src/common/mmo.h | 3 ++- src/map/atcommand.c | 21 +++++++-------- src/map/battle.c | 9 ++++--- src/map/charcommand.c | 4 +-- src/map/charsave.c | 7 ++--- src/map/clif.c | 7 ++--- src/map/irc.c | 4 +-- src/map/irc.h | 4 +-- src/map/map.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/map/map.h | 2 ++ src/map/mob.c | 23 ++++++++++------ src/map/npc.c | 3 ++- src/map/pc.c | 55 +++++++++++++++++++++----------------- src/map/pc.h | 14 +++++----- src/map/skill.c | 47 ++++++++++++++++++++------------- src/map/status.c | 7 ++--- 18 files changed, 197 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/char_sql/char.c b/src/char_sql/char.c index d1a1a6a46..e08e6a07a 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -2901,22 +2901,23 @@ int parse_frommap(int fd) { #ifdef ENABLE_SC_SAVING int count, aid, cid, i; struct status_change_data data; + char *p = tmp_sql; aid = RFIFOL(fd, 4); cid = RFIFOL(fd, 8); count = RFIFOW(fd, 12); - sprintf(tmp_sql, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); + p+ = sprintf(p, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); for (i = 0; i < count; i++) { memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); - sprintf (tmp_sql, "%s ('%d','%d','%hu','%d','%d','%d','%d','%d'),", tmp_sql, aid, cid, + p += sprintf (p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", aid, cid, data.type, data.tick, data.val1, data.val2, data.val3, data.val4); } if (count > 0) { - tmp_sql[strlen(tmp_sql)-1] = '\0'; //Remove final comma. + *--p = '\0'; //Remove final comma. if (mysql_query(&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); diff --git a/src/common/core.h b/src/common/core.h index 22f625a5d..ce57c28a6 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -5,14 +5,6 @@ #define _CORE_H_ //#define SQL_DEBUG //uncomment for debug_mysql_query instead of mysql_real_query - -/* REMOVED because these type of function defines with va_args are a GCC feature and won't compile under Windows [Skotlex] -//Added here, so its avail in 'all' files .. -#define eprintf(mes, args...) \ - fprintf(stderr, "%s:%d: "mes"", __FILE__, __LINE__, args); -#define eprint(mes) \ - fprintf(stderr, "%s:%d: "mes"", __FILE__, __LINE__); -*/ extern int arg_c; extern char **arg_v; diff --git a/src/common/mmo.h b/src/common/mmo.h index d0d4685e2..04ea008bc 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -175,7 +175,8 @@ struct mmo_charstatus { int mother; int child; - int base_exp,job_exp,zeny; + unsigned int base_exp,job_exp; + int zeny; short class_; short status_point,skill_point; diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 445c65a48..fd14b0944 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -2680,7 +2680,7 @@ int atcommand_baselevelup( clif_displaymessage(fd, msg_table[47]); /* Base level can't go any higher. */ return -1; } /* End Addition */ - if (level > pc_maxbaselv(sd) || level > (pc_maxbaselv(sd) - sd->status.base_level)) // fix positiv overflow + if (level > pc_maxbaselv(sd) || level > (pc_maxbaselv(sd) - (int)sd->status.base_level)) // fix positiv overflow level = pc_maxbaselv(sd) - sd->status.base_level; for (i = 1; i <= level; i++) sd->status.status_point += (sd->status.base_level + i + 14) / 5; @@ -2739,7 +2739,7 @@ int atcommand_joblevelup( clif_displaymessage(fd, msg_table[23]); // Job level can't go any higher. return -1; } - if (level > pc_maxjoblv(sd) || level > (pc_maxjoblv(sd) - sd->status.job_level)) // fix positiv overflow + if (level > pc_maxjoblv(sd) || level > (pc_maxjoblv(sd) - (int)sd->status.job_level)) // fix positiv overflow level = pc_maxjoblv(sd) - sd->status.job_level; sd->status.job_level += level; clif_updatestatus(sd, SP_JOBLEVEL); @@ -7633,17 +7633,14 @@ atcommand_autoloot( double drate; nullpo_retr(-1, sd); if (!message || !*message) { - if (sd->state.autoloot) { - sd->state.autoloot = 0; - clif_displaymessage(fd, "Autoloot is now off."); - return 0; - } else { - clif_displaymessage(fd, "Usage: autoloot ."); - return -1; - } + if (sd->state.autoloot) + rate = 0; + else + rate = 10000; + } else { + drate = atof(message); + rate = (int)(drate*100); } - drate = atof(message); - rate = (int)(drate*100); if (rate > 10000) rate = 10000; else if (rate < 0) rate = 0; diff --git a/src/map/battle.c b/src/map/battle.c index d6614a17b..efdb444b8 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1361,6 +1361,9 @@ static struct Damage battle_calc_weapon_attack( if (skill_num && !flag.hit) switch(skill_num) { + case AS_SPLASHER: //Reports say it always hits? + if (wflag) //Only if you were the one exploding. + break; case NPC_GUIDEDATTACK: case RG_BACKSTAP: case AM_ACIDTERROR: @@ -1775,7 +1778,7 @@ static struct Damage battle_calc_weapon_attack( skillratio += 100+100*skill_lv; break; case AS_SPLASHER: - skillratio += 100+20*skill_lv; + skillratio += 400+50*skill_lv; if (sd) skillratio += 20*pc_checkskill(sd,AS_POISONREACT); if(wflag>1) //FIXME: Splash damage... is this the correct method? [Skotlex] @@ -2818,7 +2821,7 @@ struct Damage battle_calc_misc_attack( case SN_FALCONASSAULT: /* ファルコンアサルト */ if( sd==NULL || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0) skill=0; - damage=(dex/10+int_/2+skill*3+40)*2*skill_get_num(HT_BLITZBEAT, skill_lv); //Blitz Beat Damage + damage=(dex/10+int_/2+skill*3+40)*2*skill_get_num(HT_BLITZBEAT, 5); //Blitz Beat lv5 Damage damage=damage*(150+70*skill_lv)/100; //Falcon Assault Modifier if(flag > 1) damage /= flag; @@ -3194,8 +3197,6 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, if (tsc->data[SC_POISONREACT].val2 <= 0) status_change_end(target, SC_POISONREACT, -1); } - if (tsc->data[SC_SPLASHER].timer != -1) //殴ったので対?ロのベナムスプラッシャ?[?態を解? - status_change_end(target, SC_SPLASHER, -1); } //SG_FUSION hp penalty [Komurka] diff --git a/src/map/charcommand.c b/src/map/charcommand.c index e2d4f84c6..33beca832 100644 --- a/src/map/charcommand.c +++ b/src/map/charcommand.c @@ -1262,7 +1262,7 @@ int charcommand_baselevel( clif_displaymessage(fd, msg_table[91]); // Character's base level can't go any higher. return 0; } // End Addition - if (level > pc_maxbaselv(pl_sd) || level > (pc_maxbaselv(pl_sd)- pl_sd->status.base_level)) // fix positiv overflow + if (level > pc_maxbaselv(pl_sd) || level > (pc_maxbaselv(pl_sd)- (int)pl_sd->status.base_level)) // fix positiv overflow level = pc_maxbaselv(pl_sd) - pl_sd->status.base_level; for (i = 1; i <= level; i++) pl_sd->status.status_point += (pl_sd->status.base_level + i + 14) / 5; @@ -1333,7 +1333,7 @@ int charcommand_joblevel( clif_displaymessage(fd, msg_table[67]); // Character's job level can't go any higher. return -1; } - if (pl_sd->status.job_level + level > pc_maxjoblv(pl_sd)) + if ((int)pl_sd->status.job_level + level > pc_maxjoblv(pl_sd)) level = pc_maxjoblv(pl_sd) - pl_sd->status.job_level; pl_sd->status.job_level += level; clif_updatestatus(pl_sd, SP_JOBLEVEL); diff --git a/src/map/charsave.c b/src/map/charsave.c index e9fc888db..c335064c5 100644 --- a/src/map/charsave.c +++ b/src/map/charsave.c @@ -486,8 +486,9 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_ int i,count =0; struct TimerData *timer; unsigned int tick = gettick(); + char *p = tmp_sql; - sprintf(tmp_sql, "INSERT INTO `sc_data` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES "); + p += sprintf(p, "INSERT INTO `sc_data` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES "); for(i = 0; i < max_sc; i++) { @@ -497,14 +498,14 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_ if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) continue; - sprintf (tmp_sql, "%s ('%d','%d','%hu','%d','%d','%d','%d','%d'),", tmp_sql, account_id, char_id, + p += (p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", account_id, char_id, i, DIFF_TICK(timer->tick,tick), sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4); count++; } if (count > 0) { - tmp_sql[strlen(tmp_sql)-1] = '\0'; //Remove the trailing comma. + *--p = '\0'; //Remove the trailing comma. if(mysql_query(&charsql_handle, tmp_sql)){ ShowSQL("DB error - %s\n",mysql_error(&charsql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); diff --git a/src/map/clif.c b/src/map/clif.c index be213f47b..c40a0a037 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -754,6 +754,7 @@ int clif_clearchar_id(int id, int type, int fd) { (sd->inventory_data[sd->equip_index[n]]->view_id > 0)?sd->inventory_data[sd->equip_index[n]]->view_id: \ sd->status.inventory[sd->equip_index[n]].nameid):0) +#define clif_deadsit(sd) (((sd)->sc.count && (sd)->sc.data[SC_TRICKDEAD].timer != -1)?1:sd->state.dead_sit) /*========================================== * *------------------------------------------ @@ -802,7 +803,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) { WBUFB(buf,48)|=sd->dir&0x0f; WBUFB(buf,49)=5; WBUFB(buf,50)=5; - WBUFB(buf,51)=sd->state.dead_sit; + WBUFB(buf,51)=clif_deadsit(sd); WBUFW(buf,52)=clif_setlevel(sd->status.base_level); return packet_len_table[0x78]; @@ -841,7 +842,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) { WBUFB(buf,48)|=sd->dir & 0x0f; WBUFB(buf,49)=5; WBUFB(buf,50)=5; - WBUFB(buf,51)=sd->state.dead_sit; + WBUFB(buf,51)=clif_deadsit(sd); WBUFW(buf,52)=clif_setlevel(sd->status.base_level); return packet_len_table[0x1d8]; @@ -870,7 +871,7 @@ static int clif_dis0078(struct map_session_data *sd, unsigned char *buf) { WBUFB(buf,48)|=sd->dir&0x0f; WBUFB(buf,49)=5; WBUFB(buf,50)=5; - WBUFB(buf,51)=sd->state.dead_sit; + WBUFB(buf,51)=clif_deadsit(sd); WBUFW(buf,52)=0; return packet_len_table[0x78]; diff --git a/src/map/irc.c b/src/map/irc.c index e72af4d0d..5bc0dd633 100644 --- a/src/map/irc.c +++ b/src/map/irc.c @@ -247,12 +247,12 @@ int send_to_parser(int fd, char *input,char key[2]) return total_loops; } -void do_final_irc() +void do_final_irc(void) { } -void do_init_irc() +void do_init_irc(void) { if(!use_irc) return; diff --git a/src/map/irc.h b/src/map/irc.h index 575b93301..fe48c51ff 100644 --- a/src/map/irc.h +++ b/src/map/irc.h @@ -13,8 +13,8 @@ void irc_announce_shop(struct map_session_data *sd,int flag); void irc_announce_mvp(struct map_session_data *sd, struct mob_data *md); int irc_parse(int fd); -void do_final_irc(); -void do_init_irc(); +void do_final_irc(void); +void do_init_irc(void); void irc_send(char *buf); void irc_parse_sub(int fd, char *incoming_string); int send_to_parser(int fd, char *input,char key[2]); diff --git a/src/map/map.c b/src/map/map.c index f69af6d7c..3b0c59e28 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -639,6 +639,79 @@ struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,in return NULL; } +/*========================================== + * Adapted from foreachinarea to use real ranges around a character area. [Skotlex] + *------------------------------------------ + */ + +int map_foreachinrange(int (*func)(struct block_list*,va_list),int m,struct block_list *center, int range,int type,...) { + va_list ap; + int bx,by; + int returnCount =0; //total sum of returned values of func() [Skotlex] + struct block_list *bl=NULL; + int blockcount=bl_list_count,i,c; + int x0,x1,y0,y1; + + if (m < 0) + return 0; + va_start(ap,type); + x0 = center->x-range; + x1 = center->x+range; + y0 = center->y-range; + y1 = center->y+range; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 >= map[m].xs) x1 = map[m].xs-1; + if (y1 >= map[m].ys) y1 = map[m].ys-1; + + if (type&~BL_MOB) + for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { + for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){ + bl = map[m].block[bx+by*map[m].bxs]; + c = map[m].block_count[bx+by*map[m].bxs]; + for(i=0;inext){ + if(bl && bl->type&type + && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 + && check_distance_bl(center, bl, range) + && bl_list_countnext){ + if(bl + && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 + && check_distance_bl(center, bl, range) + && bl_list_count=BL_LIST_MAX) { + if(battle_config.error_log) + ShowWarning("map_foreachinrange: block count too many!\n"); + } + + map_freeblock_lock(); // メモリからの解放を禁止する + + for(i=blockcount;iprev) // 有?かどうかチェック + returnCount += func(bl_list[i],ap); + + map_freeblock_unlock(); // 解放を許可する + + va_end(ap); + bl_list_count = blockcount; + return returnCount; //[Skotlex] +} + /*========================================== * map m (x0,y0)-(x1,y1)?の全objに?して * funcを呼ぶ diff --git a/src/map/map.h b/src/map/map.h index 960e99424..48c2b4093 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1223,6 +1223,8 @@ int map_delblock_sub(struct block_list *, int); #define map_addblock(bl) map_addblock_sub(bl,1) #define map_delblock(bl) map_delblock_sub(bl,1) int map_moveblock(struct block_list *, int, int, unsigned int); + +int map_foreachinrange(int (*)(struct block_list*,va_list),int,struct block_list *,int,int,...); int map_foreachinarea(int (*)(struct block_list*,va_list),int,int,int,int,int,int,...); // -- moonsoul (added map_foreachincell) int map_foreachincell(int (*)(struct block_list*,va_list),int,int,int,int,...); diff --git a/src/map/mob.c b/src/map/mob.c index b40c18495..c0597eff1 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -39,6 +39,7 @@ #define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute) #define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute) +#define MOB_SLAVEDISTANCE 2 //Distance that slaves should keep from their master. //Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex] struct mob_db *mob_db_data[MAX_MOB_DB+1]; struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant one is requested. @@ -1424,18 +1425,23 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) && md->master_distdb->range3 && (md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0)){ int i=0,dx,dy,ret; - if(md->master_dist>AREA_SIZE/2 && DIFF_TICK(md->next_walktime,tick)<3000) { //Allow it to cut down the walk time to chase back. [Skotlex] + if(md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0) + { //Chase back to Master's area also if standing on top of the master. do { if(i<=5){ dx=bl->x - md->bl.x; dy=bl->y - md->bl.y; - if(dx<0) dx+=(rand()%-dx)/2; //On the minimum, half the distance between slave/master. [Skotlex] - else if(dx>0) dx-=(rand()%dx)/2; - if(dy<0) dy+=(rand()%-dy)/2; - else if(dy>0) dy-=(rand()%dy)/2; + + if(dx<0) dx+=rand()%MOB_SLAVEDISTANCE +1; + else if(dx>0) dx-=rand()%MOB_SLAVEDISTANCE +1; + + if(dy<0) dy+=rand()%MOB_SLAVEDISTANCE +1; + else if(dy>0) dy-=rand()%MOB_SLAVEDISTANCE +1; + }else{ - dx=bl->x - md->bl.x + rand()%11- 5; - dy=bl->y - md->bl.y + rand()%11- 5; + ret = MOB_SLAVEDISTANCE*2+1; + dx=bl->x - md->bl.x + rand()%ret - MOB_SLAVEDISTANCE; + dy=bl->y - md->bl.y + rand()%ret - MOB_SLAVEDISTANCE; } ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0); @@ -1854,7 +1860,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) return 0; // Nothing else to do... except random walking. - if (mode&MD_CANMOVE && mob_can_move(md)) + // Slaves do not random walk! [Skotlex] + if (mode&MD_CANMOVE && mob_can_move(md) && !md->master_id) { if (DIFF_TICK(md->next_walktime, tick) > 7000 && (md->walkpath.path_len == 0 || md->walkpath.path_pos >= md->walkpath.path_len)) diff --git a/src/map/npc.c b/src/map/npc.c index cf0632416..e02b31741 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2600,7 +2600,8 @@ static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4) else if (strcmpi(w3,"restricted")==0) { // Komurka map[m].flag.restricted=1; sscanf(w4, "%d", &map[m].zone); - map[m].zone = pow(2,map[m].zone+1); + //map[m].zone = pow(2,map[m].zone+1); + map[m].zone = 1<<(map[m].zone+1); } return 0; diff --git a/src/map/pc.c b/src/map/pc.c index 59843f095..a982bab13 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -41,8 +41,8 @@ #endif #define PVP_CALCRANK_INTERVAL 1000 // PVP順位計算の間隔 -static int exp_table[MAX_PC_CLASS][2][MAX_LEVEL]; -static int max_level[MAX_PC_CLASS][2]; +static unsigned int exp_table[MAX_PC_CLASS][2][MAX_LEVEL]; +static unsigned int max_level[MAX_PC_CLASS][2]; static short statp[MAX_LEVEL]; // h-files are for declarations, not for implementations... [Shinomori] @@ -416,7 +416,7 @@ int pc_makesavestatus(struct map_session_data *sd) // 死亡?態だったのでhpを1、位置をセ?ブ場所に?更 if(!sd->state.waitingdisconnect) { - sd->sc.option = sd->sc.option; + sd->status.option = sd->sc.option; //Since the option saved is in if(pc_isdead(sd)){ pc_setrestartvalue(sd,0); memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); @@ -4687,11 +4687,11 @@ int pc_checkjoblevelup(struct map_session_data *sd) * ??値取得 *------------------------------------------ */ -int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) +int pc_gainexp(struct map_session_data *sd,unsigned int base_exp,unsigned int job_exp) { char output[256]; float nextbp=0, nextjp=0; - int nextb=0, nextj=0; + unsigned int nextb=0, nextj=0; nullpo_retr(0, sd); if(sd->bl.prev == NULL || pc_isdead(sd)) @@ -4702,14 +4702,10 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) if(sd->status.guild_id>0){ // ギルドに上納 base_exp-=guild_payexp(sd,base_exp); - if(base_exp < 0) - base_exp = 0; } if(!battle_config.multi_level_up && pc_nextbaseafter(sd) && sd->status.base_exp+base_exp >= pc_nextbaseafter(sd)) { base_exp = pc_nextbaseafter(sd) - sd->status.base_exp; - if (base_exp < 0) - base_exp = 0; } nextb = pc_nextbaseexp(sd); nextj = pc_nextjobexp(sd); @@ -4719,21 +4715,16 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) nextjp = (float) job_exp / (float) nextj; sd->status.base_exp += base_exp; - if(sd->status.base_exp < 0) - sd->status.base_exp = 0; while(pc_checkbaselevelup(sd)) ; clif_updatestatus(sd,SP_BASEEXP); + if(!battle_config.multi_level_up && pc_nextjobafter(sd) && sd->status.job_exp+job_exp >= pc_nextjobafter(sd)) { job_exp = pc_nextjobafter(sd) - sd->status.job_exp; - if (job_exp < 0) - job_exp = 0; } sd->status.job_exp += job_exp; - if(sd->status.job_exp < 0) - sd->status.job_exp = 0; while(pc_checkjoblevelup(sd)) ; @@ -4741,11 +4732,11 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) if(sd->state.showexp){ sprintf(output, - "Experienced Gained Base:%d (%.2f%%) Job:%d (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100); + "Experience Gained Base:%d (%.2f%%) Job:%d (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100); clif_disp_onlyself(sd,output,strlen(output)); } - return 0; + return 1; } /*========================================== @@ -4753,11 +4744,11 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp) *------------------------------------------ */ -int pc_maxbaselv(struct map_session_data *sd) { +unsigned int pc_maxbaselv(struct map_session_data *sd) { return max_level[sd->status.class_][0]; }; -int pc_maxjoblv(struct map_session_data *sd) { +unsigned int pc_maxjoblv(struct map_session_data *sd) { return max_level[sd->status.class_][1]; }; @@ -4765,7 +4756,7 @@ int pc_maxjoblv(struct map_session_data *sd) { * base level側必要??値計算 *------------------------------------------ */ -int pc_nextbaseexp(struct map_session_data *sd) +unsigned int pc_nextbaseexp(struct map_session_data *sd) { nullpo_retr(0, sd); @@ -4779,7 +4770,7 @@ int pc_nextbaseexp(struct map_session_data *sd) * job level側必要??値計算 *------------------------------------------ */ -int pc_nextjobexp(struct map_session_data *sd) +unsigned int pc_nextjobexp(struct map_session_data *sd) { nullpo_retr(0, sd); @@ -4792,7 +4783,7 @@ int pc_nextjobexp(struct map_session_data *sd) * base level after next [Valaris] *------------------------------------------ */ -int pc_nextbaseafter(struct map_session_data *sd) +unsigned int pc_nextbaseafter(struct map_session_data *sd) { nullpo_retr(0, sd); @@ -4806,7 +4797,7 @@ int pc_nextbaseafter(struct map_session_data *sd) * job level after next [Valaris] *------------------------------------------ */ -int pc_nextjobafter(struct map_session_data *sd) +unsigned int pc_nextjobafter(struct map_session_data *sd) { nullpo_retr(0, sd); @@ -8053,6 +8044,22 @@ int pc_split_atoi(char *str,int *val, char sep, int max) return i; } +int pc_split_atoui(char *str,unsigned int *val, char sep, int max) +{ + int i,j; + for (i=0; idata[SC_EDP].val2 * sc_def_vit / 100) status_change_start(bl,SC_DPOISON,sc->data[SC_EDP].val1,0,0,0,skill_get_time2(ASC_EDP,sc->data[SC_EDP].val1),0); } - if (tsc->count && tsc->data[SC_KAAHI].timer != -1) { - if (dstsd && dstsd->status.sp < 5*tsc->data[SC_KAAHI].val1) - ; //Not enough SP to cast - else { - battle_heal(bl, bl, 200*tsc->data[SC_KAAHI].val1, -5*tsc->data[SC_KAAHI].val1, 1); - if(dstsd && dstsd->fd) - clif_heal(dstsd->fd,SP_HP,200*tsc->data[SC_KAAHI].val1); + if (tsc->count) { + if (tsc->data[SC_SPLASHER].timer != -1 && + tsc->data[SC_POISON].timer == -1 && + rand()%100< (2*tsc->data[SC_SPLASHER].val1+10)*sc_def_vit/100 + ) { + status_change_start(bl,SC_POISON,tsc->data[SC_SPLASHER].val1,0,0,0, + skill_get_time2(tsc->data[SC_SPLASHER].val2,tsc->data[SC_SPLASHER].val1),0); + } + + if(tsc->data[SC_KAAHI].timer != -1) { + if (dstsd && dstsd->status.sp < 5*tsc->data[SC_KAAHI].val1) + ; //Not enough SP to cast + else { + battle_heal(bl, bl, 200*tsc->data[SC_KAAHI].val1, -5*tsc->data[SC_KAAHI].val1, 1); + if(dstsd && dstsd->fd) + clif_heal(dstsd->fd,SP_HP,200*tsc->data[SC_KAAHI].val1); + } } } } @@ -3014,10 +3024,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int s case WZ_WATERBALL: /* ウォ?タ?ボ?ル */ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); if (skilllv>1) { - int range = skilllv > 5 ? 2 : skilllv/2; + int range = skilllv/2; //Rain doesn't affect WATERBALL (Rain has been removed at kRO) [Lupus] //int cnt = (!map[src->m].flag.rain) ? skill_count_water(src,range) - 1 : skill_get_num(skillid,skilllv) - 1; - int cnt = (src->type==BL_PC)?skill_count_water(src,range) - 1:(skilllv>3?24:8); + int cnt = (src->type==BL_PC)?skill_count_water(src,range) - 1:(range*range-1); if (cnt > 0) skill_addtimerskill(src,tick+150,bl->id,0,0, skillid,skilllv,cnt,flag); @@ -5086,8 +5096,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case NPC_SUMMONSLAVE: /* 手下?「喚 */ - if (md) //Only summon remaining slaves - skilllv = skilllv - mob_countslave(&md->bl); case NPC_SUMMONMONSTER: /* MOB?「喚 */ if(md) mob_summonslave(md,md->db->skill[md->skillidx].val,skilllv,skillid); @@ -5425,7 +5433,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case AS_SPLASHER: /* ベナムスプラッシャ? */ - if(status_get_max_hp(bl)*2/3 < status_get_hp(bl)) { //HPが2/3以??っていたら失敗 + if(status_get_max_hp(bl)*3/4 < status_get_hp(bl)) { //HPが2/3以??っていたら失敗 map_freeblock_unlock(); return 1; } @@ -6227,7 +6235,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case HT_DETECTING: /* ディテクティング */ map_foreachinarea( status_change_timer_sub, - src->m, x-1, y-1, x+1,y+1,BL_CHAR, + src->m, x-3, y-3, x+3,y+3,BL_CHAR, src,status_get_sc(src),SC_SIGHT,tick); break; @@ -6279,14 +6287,17 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case WZ_METEOR: //?テオスト?ム { - int flag=0; + int flag=0, area = 7; if (sc && sc->data[SC_MAGICPOWER].timer != -1) flag = flag|2; //Store the magic power flag for future use. [Skotlex] + if (skilllv > skill_get_max(skillid)) + area = area*3; //Double range area for(i=0;i<2+(skilllv>>1);i++) { int j=0; do { - tmpx = x + (rand()%7 - 3); - tmpy = y + (rand()%7 - 3); + + tmpx = x + (rand()%area - area/2); + tmpy = y + (rand()%area - area/2); if(tmpx < 0) tmpx = 0; else if(tmpx >= map[src->m].xs) @@ -6648,11 +6659,11 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, range=2; break; case WZ_METEOR: - if (skilllv > 10) //?L範囲?テオ + if (skilllv > skill_get_max(skillid)) //?L範囲?テオ range = 10; break; case WZ_VERMILION: - if (skilllv > 10) //?L範囲LOV + if (skilllv > skill_get_max(skillid)) //?L範囲LOV range = 25; break; case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] diff --git a/src/map/status.c b/src/map/status.c index 2e2613a8d..1a7dbb3d6 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -3720,7 +3720,9 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val if((type==SC_FREEZE || type==SC_STONE) && undead_flag && !(flag&1)) //I've been informed that undead chars are inmune to stone curse too. [Skotlex] return 0; - + //Dark Elementals are inmune to curse. + if(type==SC_CURSE && elem == 7 && !(flag&1)) + return 0; if (type==SC_BLESSING && (bl->type==BL_PC || (!undead_flag && race!=6))) { if (sc->data[SC_CURSE].timer!=-1) @@ -4451,9 +4453,8 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val break; } - case SC_COMA: //Coma. Sends a char to 1HP/SP + case SC_COMA: //Coma. Sends a char to 1HP battle_damage(NULL, bl, status_get_hp(bl)-1, 0); - if (sd) pc_heal(sd,0,-sd->status.sp+1); return 0; case SC_CARTBOOST: /* カ?トブ?スト */ -- cgit v1.2.3-70-g09d2