From 173c3195ade5a6cdfe20c49e7f184a6b1336ca19 Mon Sep 17 00:00:00 2001 From: skotlex Date: Thu, 9 Feb 2006 14:21:41 +0000 Subject: - Code rewrites in mob_damage and party_exp_even_share for correctly handling overflow issues. Now uses UINT_MAX for range comparisons, as it should be. - Also modified the mob_db reading to use UINT_MAX for exp limits, changed their exp/job exp fields to unsigned int as well. - Modified multi_level_up behaviour to work as specified by Kyoki. - removed functions pc_next[base/job]after as they are no longer needed. - Modified the skill attack display of Meteor Assault and the Warm Skills (I think the caster should no longer do fancy animations now on each hit) - Added back water elemental targets being inmune to SC_FREEZE - Fixed the status_change_start line in charsave.c (I knew I was forgetting something) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5235 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/charsave.c | 4 +-- src/map/clif.c | 13 +++++---- src/map/mob.c | 83 ++++++++++++++++++++++++++++++++-------------------- src/map/mob.h | 2 +- src/map/party.c | 25 ++++++++++------ src/map/party.h | 2 +- src/map/pc.c | 85 +++++++++++++++++++++++------------------------------- src/map/pc.h | 2 -- src/map/skill.c | 4 +++ src/map/status.c | 6 ++-- 10 files changed, 122 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/map/charsave.c b/src/map/charsave.c index 1d163612c..fde1f66ed 100644 --- a/src/map/charsave.c +++ b/src/map/charsave.c @@ -467,8 +467,8 @@ int charsave_load_scdata(int account_id, int char_id) continue; } - status_change_start(&sd->bl, atoi(sql_row[0]), 10000, atoi(sql_row[2]), atoi(sql_row[3]), - atoi(sql_row[4]), atoi(sql_row[5]), atoi(sql_row[1]), 7); + status_change_start(&sd->bl, atoi(sql_row[0]), 100, atoi(sql_row[2]), atoi(sql_row[3]), + atoi(sql_row[4]), atoi(sql_row[5]), atoi(sql_row[1]), 15); } } diff --git a/src/map/clif.c b/src/map/clif.c index 1ba814652..a97f27941 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -365,7 +365,7 @@ int clif_send (unsigned char *buf, int len, struct block_list *bl, int type) { for (i = 0; i < fd_max; i++) { if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL && sd->state.auth) { if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - WFIFOHEAD(i, len); + WFIFOHEAD(i, len); memcpy(WFIFOP(i,0), buf, len); WFIFOSET(i,len); } @@ -412,7 +412,7 @@ int clif_send (unsigned char *buf, int len, struct block_list *bl, int type) { if (packet_db[cd->usersd[i]->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version if (cd->usersd[i]->fd >0 && session[cd->usersd[i]->fd]) // Added check to see if session exists [PoW] { - WFIFOHEAD(cd->usersd[i]->fd,len); + WFIFOHEAD(cd->usersd[i]->fd,len); memcpy(WFIFOP(cd->usersd[i]->fd,0), buf, len); WFIFOSET(cd->usersd[i]->fd,len); } @@ -424,6 +424,7 @@ int clif_send (unsigned char *buf, int len, struct block_list *bl, int type) { for(i=1; isession_data) != NULL && sd->state.mainchat && sd->fd) { + WFIFOHEAD(sd->fd, len); memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd, len); } @@ -472,7 +473,7 @@ int clif_send (unsigned char *buf, int len, struct block_list *bl, int type) { if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth && sd->fd && sd->partyspy) { if (sd->partyspy == p->party_id) { if (sd->fd && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - WFIFOHEAD(sd->fd,len); + WFIFOHEAD(sd->fd,len); memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -483,7 +484,7 @@ int clif_send (unsigned char *buf, int len, struct block_list *bl, int type) { break; case SELF: if (sd && sd->fd && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - WFIFOHEAD(sd->fd,len); + WFIFOHEAD(sd->fd,len); memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -533,7 +534,7 @@ int clif_send (unsigned char *buf, int len, struct block_list *bl, int type) { if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth && sd->fd && sd->guildspy) { if (sd->guildspy == g->guild_id) { if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - WFIFOHEAD(sd->fd,len); + WFIFOHEAD(sd->fd,len); memcpy(WFIFOP(sd->fd,0), buf, len); WFIFOSET(sd->fd,len); } @@ -8809,7 +8810,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) pc_checkskill(sd,SG_STAR_COMFORT)) status_calc_pc(sd,0); - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobafter(sd)) + if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) clif_status_load(&sd->bl, SI_DEVIL, 1); //blindness [Komurka] map_foreachinarea(clif_getareachar,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,BL_ALL,sd); diff --git a/src/map/mob.c b/src/map/mob.c index 0ce92e813..4f70ef349 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "timer.h" #include "socket.h" @@ -2176,7 +2177,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) struct map_session_data *sd = NULL,*tmpsd[DAMAGELOG_SIZE]; struct { struct party *p; - int id,base_exp,job_exp,zeny; + int id,zeny; + unsigned int base_exp,job_exp; } pt[DAMAGELOG_SIZE]; int pnum=0; int mvp_damage,max_hp; @@ -2422,7 +2424,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) // 経験値の分配 for(i=0;ibl.m != md->bl.m || pc_isdead(tmpsd[i])) @@ -2436,8 +2438,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) if (count>1) per *= (9.+(double)((count > 6)? 6:count))/10.; //attackers count bonus. - base_exp = (unsigned long)md->db->base_exp; - job_exp = (unsigned long)md->db->job_exp; + base_exp = md->db->base_exp; + job_exp = md->db->job_exp; if (ret) per += per*ret/100.; //SC_RICHMANKIM bonus. [Skotlex] @@ -2477,21 +2479,24 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) else if(md->special_state.size==2 && zeny >1) zeny*=2; } - if(battle_config.mobs_level_up && md->level > md->db->lv) { // [Valaris] - base_exp+=(unsigned long) (((md->level-md->db->lv)*((md->db->base_exp))*(battle_config.mobs_level_up_exp_rate/100))); - job_exp+=(unsigned long) (((md->level-md->db->lv)*((md->db->job_exp))*(battle_config.mobs_level_up_exp_rate/100))); - } + if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris] + per+= per*(md->level-md->db->lv)*battle_config.mobs_level_up_exp_rate/100; } if (per > 4) per = 4; //Limit gained exp to quadro the mob's exp. [3->4 Komurka] - base_exp = (unsigned long)(base_exp*per); - job_exp = (unsigned long)(job_exp*per); - - if (base_exp > 0x7fffffff) base_exp = 0x7fffffff; - else if (base_exp < 1) base_exp = 1; - if (job_exp > 0x7fffffff) job_exp = 0x7fffffff; - else if (job_exp < 1) job_exp = 1; + if (base_exp*per > UINT_MAX) + base_exp = UINT_MAX; + else + base_exp = (unsigned int)(base_exp*per); + + if (job_exp*per > UINT_MAX) + job_exp = UINT_MAX; + else + job_exp = (unsigned int)(job_exp*per); + + if (base_exp < 1) base_exp = 1; + if (job_exp < 1) job_exp = 1; //mapflags: noexp check [Lorky] if (map[md->bl.m].flag.nobaseexp == 1) base_exp=0; @@ -2514,14 +2519,16 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type) flag=0; } }else{ // いるときは公平 - if (pt[j].base_exp +base_exp < 0x7fffffff) + if (pt[j].base_exp > UINT_MAX - base_exp) + pt[j].base_exp=UINT_MAX; + else pt[j].base_exp+=base_exp; + + if (pt[j].job_exp > UINT_MAX - job_exp) + pt[j].job_exp=UINT_MAX; else - pt[j].base_exp = 0x7fffffff; - if (pt[j].job_exp +job_exp < 0x7fffffff) pt[j].job_exp+=job_exp; - else - pt[j].job_exp = 0x7fffffff; + if(battle_config.zeny_from_mobs) pt[j].zeny+=zeny; // zeny share [Valaris] flag=0; @@ -4241,14 +4248,20 @@ static int mob_readdb(void) mob_db_data[class_]->max_sp = atoi(str[5]); exp = (double)atoi(str[6]) * (double)battle_config.base_exp_rate / 100.; - if (exp < 0) exp = 0; - else if (exp > 0x7fffffff) exp = 0x7fffffff; - mob_db_data[class_]->base_exp = (int)exp; + if (exp < 0) + mob_db_data[class_]->base_exp = 0; + if (exp > UINT_MAX) + mob_db_data[class_]->base_exp = UINT_MAX; + else + mob_db_data[class_]->base_exp = (unsigned int)exp; exp = (double)atoi(str[7]) * (double)battle_config.job_exp_rate / 100.; - if (exp < 0) exp = 0; - else if (exp > 0x7fffffff) exp = 0x7fffffff; - mob_db_data[class_]->job_exp = (int)exp; + if (exp < 0) + mob_db_data[class_]->job_exp = 0; + else if (exp > UINT_MAX) + mob_db_data[class_]->job_exp = UINT_MAX; + else + mob_db_data[class_]->job_exp = (unsigned int)exp; mob_db_data[class_]->range=atoi(str[8]); mob_db_data[class_]->atk1=atoi(str[9]); @@ -4811,14 +4824,20 @@ static int mob_read_sqldb(void) mob_db_data[class_]->max_sp = TO_INT(5); exp = (double)TO_INT(6) * (double)battle_config.base_exp_rate / 100.; - if (exp < 0) exp = 0; - else if (exp > 0x7fffffff) exp = 0x7fffffff; - mob_db_data[class_]->base_exp = (int)exp; + if (exp < 0) + mob_db_data[class_]->base_exp = 0; + else if (exp > UINT_MAX) + mob_db_data[class_]->base_exp = UINT_MAX; + else + mob_db_data[class_]->base_exp = (unsigned int)exp; exp = (double)TO_INT(7) * (double)battle_config.job_exp_rate / 100.; - if (exp < 0) exp = 0; - else if (exp > 0x7fffffff) exp = 0x7fffffff; - mob_db_data[class_]->job_exp = (int)exp; + if (exp < 0) + mob_db_data[class_]->job_exp = 0; + else if (exp > UINT_MAX) + mob_db_data[class_]->job_exp = UINT_MAX; + else + mob_db_data[class_]->job_exp = (unsigned int)exp; mob_db_data[class_]->range = TO_INT(8); mob_db_data[class_]->atk1 = TO_INT(9); diff --git a/src/map/mob.h b/src/map/mob.h index bbdd66105..2a084f082 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -31,7 +31,7 @@ struct mob_db { char name[NAME_LENGTH],jname[NAME_LENGTH]; short lv; int max_hp,max_sp; - int base_exp,job_exp; + unsigned int base_exp,job_exp; int atk1,atk2; int def,mdef; int str,agi,vit,int_,dex,luk; diff --git a/src/map/party.c b/src/map/party.c index d5c6b800b..be8520d8f 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../common/timer.h" #include "../common/socket.h" @@ -639,12 +640,11 @@ int party_send_xy_clear(struct party *p) } // exp share and added zeny share [Valaris] -int party_exp_share(struct party *p,int map,int base_exp,int job_exp,int zeny) +int party_exp_share(struct party *p,int map,unsigned int base_exp,unsigned int job_exp,int zeny) { struct map_session_data* sd[MAX_PARTY]; int i; short c, bonus =100; // modified [Valaris] - unsigned long base, job; nullpo_retr(0, p); @@ -660,15 +660,22 @@ int party_exp_share(struct party *p,int map,int base_exp,int job_exp,int zeny) bonus += (battle_config.party_even_share_bonus*c*(c-1)/10); //Changed Valaris's bonus switch to an equation [Skotlex] else //Official kRO/iRO sites state that the even share bonus is 10% per additional party member. bonus += (c-1)*10; - base = (unsigned long)(base_exp/c)*bonus/100; - job = (unsigned long)(job_exp/c)*bonus/100; - if (base > 0x7fffffff) - base = 0x7fffffff; - if (job > 0x7fffffff) - job = 0x7fffffff; + + base_exp/=c; + job_exp/=c; + if (base_exp/100 > UINT_MAX/bonus) + base_exp= UINT_MAX; //Exp overflow + else + base_exp = base_exp*bonus/100; + + if (job_exp/100 > UINT_MAX/bonus) + job_exp = UINT_MAX; + else + job_exp = job_exp*bonus/100; + for (i = 0; i < c; i++) { - pc_gainexp(sd[i], base, job); + pc_gainexp(sd[i], base_exp, job_exp); if (battle_config.zeny_from_mobs) // zeny from mobs [Valaris] pc_getzeny(sd[i],bonus*zeny/(c*100)); } diff --git a/src/map/party.h b/src/map/party.h index 4e9601d68..b98731c18 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -38,7 +38,7 @@ int party_recv_message(int party_id,int account_id,char *mes,int len); 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,int base_exp,int job_exp,int zeny); +int party_exp_share(struct party *p,int map,unsigned int base_exp,unsigned int job_exp,int zeny); int party_send_dot_remove(struct map_session_data *sd); int party_sub_count(struct block_list *bl, va_list ap); void 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 09ed0d7f7..46fe462d8 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "socket.h" // [Valaris] #include "timer.h" @@ -4597,11 +4598,13 @@ int pc_checkbaselevelup(struct map_session_data *sd) nullpo_retr(0, sd); if(sd->status.base_exp >= next && next > 0){ - - // base側レベルアップ?理 sd->status.base_exp -= next; + //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex] + if(!battle_config.multi_level_up && sd->status.base_exp > next-1) + sd->status.base_exp = next-1; sd->status.base_level ++; + if (battle_config.pet_lv_rate && sd->pd) // update pet's level status_calc_pet(sd,0); if (battle_config.use_statpoint_table) @@ -4653,9 +4656,13 @@ int pc_checkjoblevelup(struct map_session_data *sd) nullpo_retr(0, sd); if(sd->status.job_exp >= next && next > 0){ - // job側レベルアップ?理 sd->status.job_exp -= next; + //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex] + if(!battle_config.multi_level_up && sd->status.job_exp > next-1) + sd->status.job_exp = next-1; + sd->status.job_level ++; + clif_updatestatus(sd,SP_JOBLEVEL); clif_updatestatus(sd,SP_NEXTJOBEXP); sd->status.skill_point ++; @@ -4663,7 +4670,7 @@ int pc_checkjoblevelup(struct map_session_data *sd) status_calc_pc(sd,0); clif_misceffect(&sd->bl,1); - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobafter(sd)) + if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) clif_status_change(&sd->bl,SI_DEVIL, 1); //Permanent blind effect from SG_DEVIL. if (script_config.event_script_type == 0) { @@ -4697,34 +4704,41 @@ int pc_gainexp(struct map_session_data *sd,unsigned int base_exp,unsigned int jo if(sd->bl.prev == NULL || pc_isdead(sd)) return 0; - if((battle_config.pvp_exp == 0) && map[sd->bl.m].flag.pvp) // [MouseJstr] + if(!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr] return 0; // no exp on pvp maps if(sd->status.guild_id>0){ // ギルドに上納 base_exp-=guild_payexp(sd,base_exp); } - 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(sd->state.showexp){ + nextb = pc_nextbaseexp(sd); + nextj = pc_nextjobexp(sd); + if (nextb > 0) + nextbp = (float) base_exp / (float) nextb; + if (nextj > 0) + nextjp = (float) job_exp / (float) nextj; } - nextb = pc_nextbaseexp(sd); - nextj = pc_nextjobexp(sd); - if (nextb > 0) - nextbp = (float) base_exp / (float) nextb; - if (nextj > 0) - nextjp = (float) job_exp / (float) nextj; - - sd->status.base_exp += base_exp; - + + //Overflow checks... think we'll ever really need'em? [Skotlex] + if (base_exp > 0 && sd->status.base_exp > UINT_MAX - base_exp) + sd->status.base_exp = UINT_MAX; + else if (base_exp < 0 && sd->status.base_exp > base_exp) + sd->status.base_exp = 0; + else + sd->status.base_exp += base_exp; + 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; - } - - sd->status.job_exp += job_exp; + //Overflow checks... think we'll ever really need'em? [Skotlex] + if (job_exp > 0 && sd->status.job_exp > UINT_MAX - job_exp) + sd->status.job_exp = UINT_MAX; + else if (job_exp < 0 && sd->status.job_exp > job_exp) + sd->status.job_exp = 0; + else + sd->status.job_exp += job_exp; while(pc_checkjoblevelup(sd)) ; @@ -4779,33 +4793,6 @@ unsigned int pc_nextjobexp(struct map_session_data *sd) return exp_table[sd->status.class_][1][sd->status.job_level-1]; } -/*========================================== - * base level after next [Valaris] - *------------------------------------------ - */ -unsigned int pc_nextbaseafter(struct map_session_data *sd) -{ - nullpo_retr(0, sd); - - if(sd->status.base_level>=pc_maxbaselv(sd) || sd->status.base_level<=0) - return 0; - - return exp_table[sd->status.class_][0][sd->status.base_level]; -} - -/*========================================== - * job level after next [Valaris] - *------------------------------------------ - */ -unsigned int pc_nextjobafter(struct map_session_data *sd) -{ - nullpo_retr(0, sd); - - if(sd->status.job_level>=pc_maxjoblv(sd) || sd->status.job_level<=0) - return 0; - - return exp_table[sd->status.class_][1][sd->status.job_level]; -} /*========================================== * 必要ステ?タスポイント計算 @@ -5208,7 +5195,7 @@ int pc_resetskill(struct map_session_data* sd) int i, skill, inf2; nullpo_retr(0, sd); - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobafter(sd)) + if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) clif_status_load(&sd->bl, SI_DEVIL, 0); //Remove perma blindness due to skill-reset. [Skotlex] for (i = 1; i < MAX_SKILL; i++) { diff --git a/src/map/pc.h b/src/map/pc.h index 11e7539f8..f184f3f5d 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -123,9 +123,7 @@ int pc_checkbaselevelup(struct map_session_data *sd); int pc_checkjoblevelup(struct map_session_data *sd); int pc_gainexp(struct map_session_data*,unsigned int,unsigned int); unsigned int pc_nextbaseexp(struct map_session_data *); -unsigned int pc_nextbaseafter(struct map_session_data *); // [Valaris] unsigned int pc_nextjobexp(struct map_session_data *); -unsigned int pc_nextjobafter(struct map_session_data *); // [Valaris] int pc_need_status_point(struct map_session_data *,int); int pc_statusup(struct map_session_data*,int); int pc_statusup2(struct map_session_data*,int,int); diff --git a/src/map/skill.c b/src/map/skill.c index 6822c8327..44e78e51f 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1766,6 +1766,10 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //武器スキル?ここまで switch(skillid){ case AS_SPLASHER: + case ASC_METEORASSAULT: + case SG_SUN_WARM: + case SG_MOON_WARM: + case SG_STAR_WARM: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5); break; case ASC_BREAKER: // [celest] diff --git a/src/map/status.c b/src/map/status.c index f9c79cc8c..c2ed134e1 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1618,7 +1618,7 @@ int status_calc_pc(struct map_session_data* sd,int first) // Relative modifiers from passive skills if((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0) sd->aspd_rate -= (skill/2); - if((skill = pc_checkskill(sd,SG_DEVIL)) > 0 && !pc_nextjobafter(sd)) + if((skill = pc_checkskill(sd,SG_DEVIL)) > 0 && !pc_nextjobexp(sd)) sd->aspd_rate -= (skill*3); if(pc_isriding(sd)) @@ -3740,8 +3740,10 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val //Check for inmunities / sc fails switch (type) { - case SC_STONE: case SC_FREEZE: + if (elem == 1 && !(flag&1)) + return 0; //Can't freeze water elementals. + case SC_STONE: //I've been informed that undead chars are inmune to stone curse too. [Skotlex] if (undead_flag && !(flag&1)) return 0; -- cgit v1.2.3-70-g09d2