From c8758478b4469f42dc26cfd629ee01b490fadc5e Mon Sep 17 00:00:00 2001 From: aleos89 Date: Thu, 24 Jul 2014 11:45:57 -0400 Subject: [PATCH] Bug Fixes * Fixed the stun effect from Berkana Rune. (bugreport:9057) * Adjusted Thorn Wall to be a placeable skill and to ignore caster's % damage cards. * Field Manuals (SC_EXPBOOST and SC_JEXPBOOST) now increase EXP gained from NPC quests (through the getexp script command). (bugreport:9091) * Lif's Mental Change no longer fully restores her HP and SP upon activation. * Fixed fakename atcommand not working while disguised. (bugreport:8896) (Hercules 1e492e3) * Fixed speed atcommand resetting when swapping equipment/changing maps. (bugreport:8915) (Hercules 37fdcba) * Cleaned up some compile warnings. --- conf/msg_conf/map_msg.conf | 2 +- db/pre-re/skill_db.txt | 2 +- db/re/skill_db.txt | 2 +- src/common/mmo.h | 2 +- src/map/atcommand.c | 20 +++++++++--- src/map/battle.c | 20 ++++++------ src/map/clif.c | 6 ++-- src/map/clif.h | 2 +- src/map/pc.c | 64 ++++++++++++++++++++------------------ src/map/skill.c | 4 +-- src/map/status.c | 35 ++++++++++----------- 11 files changed, 85 insertions(+), 74 deletions(-) diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index cb21ea2836..06fcbdd7fb 100644 --- a/conf/msg_conf/map_msg.conf +++ b/conf/msg_conf/map_msg.conf @@ -404,7 +404,7 @@ 387: The chosen emblem was detected invalid as it contain too much transparency (limit=%d) //etc 388: You cannot use this item while storage is open. -//389 free +389: Speed returned to normal. //NoAsk 390: Autorejecting is activated. 391: Autorejecting is deactivated. diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 6899fb3ef1..3624257c30 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -1194,7 +1194,7 @@ 2479,9,6,2,0,0,0,5,1,yes,0,0x80,3,misc,0,0x0, GN_THORNS_TRAP,Thorn Trap 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0, GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm.... 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0, GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm. -2482,11,6,16,0,0,0,5,1,yes,0,0,1,weapon,2,0x0, GN_WALLOFTHORN,Wall of Thorns +2482,11,6,2,0,0x8,0,5,1,yes,0,0,1,weapon,2,0x0, GN_WALLOFTHORN,Wall of Thorns 2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1, GN_CRAZYWEED,Crazy Weed 2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1, GN_CRAZYWEED_ATK,Crazy Weed Attack 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0, GN_DEMONIC_FIRE,Demonic Fire diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index d0c9a017a5..5820bf5ff1 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -1194,7 +1194,7 @@ 2479,9,6,2,0,0,0,5,1,yes,0,0x80,3,misc,0,0x0, GN_THORNS_TRAP,Thorn Trap 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0, GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm.... 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0, GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm. -2482,11,6,16,0,0,0,5,1,yes,0,0,1,weapon,2,0x0, GN_WALLOFTHORN,Wall of Thorns +2482,11,6,2,0,0x8,0,5,1,yes,0,0,1,weapon,2,0x0, GN_WALLOFTHORN,Wall of Thorns 2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1, GN_CRAZYWEED,Crazy Weed 2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1, GN_CRAZYWEED_ATK,Crazy Weed Attack 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0, GN_DEMONIC_FIRE,Demonic Fire diff --git a/src/common/mmo.h b/src/common/mmo.h index 15f53c3dd1..646ee617cf 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -60,7 +60,7 @@ #define ACCOUNT_REG2_NUM 16 ///Max permanent global account variables per account #define MAX_REG_NUM 256 ///Should hold the max of GLOBAL/ACCOUNT/ACCOUNT2 (needed for some arrays that hold all three) #define DEFAULT_WALK_SPEED 150 ///Default walk speed -#define MIN_WALK_SPEED 0 ///Min walk speed +#define MIN_WALK_SPEED 20 ///Min walk speed #define MAX_WALK_SPEED 1000 ///Max walk speed #define MAX_STORAGE 600 ///Max number of storage slots a player can have, (up to ~850 tested) #define MAX_GUILD_STORAGE 600 ///Max number of storage slots a guild diff --git a/src/map/atcommand.c b/src/map/atcommand.c index bcae44b5c4..15edb0507e 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -862,15 +862,21 @@ ACMD_FUNC(speed) return -1; } - if (speed < 0) { + sd->state.permanent_speed = 0; // Remove lock when set back to default speed. + + if (speed < 0) sd->base_status.speed = DEFAULT_WALK_SPEED; - sd->state.permanent_speed = 0; // Remove lock when set back to default speed. - } else { + else sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); + + if (sd->base_status.speed != DEFAULT_WALK_SPEED) { sd->state.permanent_speed = 1; // Set lock when set to non-default speed. - } + clif_displaymessage(fd, msg_txt(sd,8)); // Speed changed. + } else + clif_displaymessage(fd, msg_txt(sd,389)); // Speed returned to normal. + status_calc_bl(&sd->bl, SCB_SPEED); - clif_displaymessage(fd, msg_txt(sd,8)); // Speed changed. + return 0; } @@ -7849,6 +7855,8 @@ ACMD_FUNC(fakename) { sd->fakename[0] = '\0'; clif_charnameack(0, &sd->bl); + if (sd->disguise) + clif_charnameack(sd->fd, &sd->bl); clif_displaymessage(sd->fd, msg_txt(sd,1307)); // Returned to real name. return 0; } @@ -7865,6 +7873,8 @@ ACMD_FUNC(fakename) safestrncpy(sd->fakename, message, sizeof(sd->fakename)); clif_charnameack(0, &sd->bl); + if (sd->disguise) // Another packet should be sent so the client updates the name for sd + clif_charnameack(sd->fd, &sd->bl); clif_displaymessage(sd->fd, msg_txt(sd,1310)); // Fake name enabled. return 0; diff --git a/src/map/battle.c b/src/map/battle.c index c74830fb10..37a7a0b9c1 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -795,11 +795,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) { struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3); - uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; + uint16 skill_id_val = sc->data[SC_SAFETYWALL]->val2; if (group) { d->dmg_lv = ATK_BLOCK; - if (skill_id == MH_STEINWAND) { + if (skill_id_val == MH_STEINWAND) { if (--group->val2 <= 0) skill_delunitgroup(group); if( (group->val3 - damage) > 0 ) @@ -863,18 +863,18 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam } if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) { - clif_skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); sce->val3 -= (int)cap_value(damage,INT_MIN,INT_MAX); // absorb damage d->dmg_lv = ATK_BLOCK; - sc_start(src,bl,SC_STUN,15,0,skill_get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stunned when one shield is broken. if( sce->val3 <= 0 ) { // Shield Down sce->val2--; - if( sce->val2 > 0 ) { - if( sd ) - clif_millenniumshield(sd,sce->val2); - sce->val3 = 1000; // Next Shield - } else - status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down + if( sce->val2 >= 0 ) { + clif_millenniumshield(bl,sce->val2); + if( !sce->val2 ) + status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down + else + sce->val3 = 1000; // Next shield + } + status_change_start(src,bl,SC_STUN,10000,0,0,0,0,1000,2); } return 0; } diff --git a/src/map/clif.c b/src/map/clif.c index 1ab19c6633..9eafe83c3a 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16677,15 +16677,15 @@ int clif_elementalconverter_list(struct map_session_data *sd) { /** * Rune Knight **/ -void clif_millenniumshield(struct map_session_data *sd, short shields ) { +void clif_millenniumshield(struct block_list *bl, short shields) { #if PACKETVER >= 20081217 unsigned char buf[10]; WBUFW(buf,0) = 0x440; - WBUFL(buf,2) = sd->bl.id; + WBUFL(buf,2) = bl->id; WBUFW(buf,6) = shields; WBUFW(buf,8) = 0; - clif_send(buf,packet_len(0x440),&sd->bl,AREA); + clif_send(buf,packet_len(0x440),bl,AREA); #endif } /** diff --git a/src/map/clif.h b/src/map/clif.h index e010659d65..1664193a64 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -844,7 +844,7 @@ void clif_msgtable_num(int fd, int line, int num); int clif_elementalconverter_list(struct map_session_data *sd); -void clif_millenniumshield(struct map_session_data *sd, short shields ); +void clif_millenniumshield(struct block_list *bl, short shields); int clif_spellbook_list(struct map_session_data *sd); diff --git a/src/map/pc.c b/src/map/pc.c index 5d5becd2a8..896d3f1d2c 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -231,7 +231,7 @@ void pc_addspiritball(struct map_session_data *sd,int interval,int max) sd->spirit_timer[i] = tid; sd->spiritball++; if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) - clif_millenniumshield(sd,sd->spiritball); + clif_millenniumshield(&sd->bl,sd->spiritball); else clif_spiritball(&sd->bl); } @@ -274,7 +274,7 @@ void pc_delspiritball(struct map_session_data *sd,int count,int type) if(!type) { if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) - clif_millenniumshield(sd,sd->spiritball); + clif_millenniumshield(&sd->bl,sd->spiritball); else clif_spiritball(&sd->bl); } @@ -6217,38 +6217,41 @@ int pc_checkjoblevelup(struct map_session_data *sd) static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) { int bonus = 0, vip_bonus_base = 0, vip_bonus_job = 0; - struct status_data *status = status_get_status_data(src); - if( sd->expaddrace[status->race] ) - bonus += sd->expaddrace[status->race]; - if( sd->expaddrace[RC_ALL] ) - bonus += sd->expaddrace[RC_ALL]; - if( sd->expaddclass[status->class_] ) - bonus += sd->expaddclass[status->class_]; - if( sd->expaddclass[CLASS_ALL] ) - bonus += sd->expaddclass[CLASS_ALL]; + if (src) { + struct status_data *status = status_get_status_data(src); - if (battle_config.pk_mode && - (int)(status_get_lv(src) - sd->status.base_level) >= 20) - bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris] + if( sd->expaddrace[status->race] ) + bonus += sd->expaddrace[status->race]; + if( sd->expaddrace[RC_ALL] ) + bonus += sd->expaddrace[RC_ALL]; + if( sd->expaddclass[status->class_] ) + bonus += sd->expaddclass[status->class_]; + if( sd->expaddclass[CLASS_ALL] ) + bonus += sd->expaddclass[CLASS_ALL]; - if (sd->sc.data[SC_EXPBOOST]) { - bonus += sd->sc.data[SC_EXPBOOST]->val1; + if (battle_config.pk_mode && + (int)(status_get_lv(src) - sd->status.base_level) >= 20) + bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris] + +#ifdef VIP_ENABLE + //EXP bonus for VIP player + if (src && src->type == BL_MOB && pc_isvip(sd)) { + vip_bonus_base = battle_config.vip_base_exp_increase; + vip_bonus_job = battle_config.vip_job_exp_increase; + } +#endif + } + + if (&sd->sc && sd->sc.data[SC_EXPBOOST]) { + bonus += sd->sc.data[SC_EXPBOOST]->val1; if( battle_config.vip_bm_increase && pc_isvip(sd) ) // Increase Battle Manual EXP rate for VIP. bonus += ( sd->sc.data[SC_EXPBOOST]->val1 / battle_config.vip_bm_increase ); } -#ifdef VIP_ENABLE - //EXP bonus for VIP player - if (src && src->type == BL_MOB && pc_isvip(sd)) { - vip_bonus_base = battle_config.vip_base_exp_increase; - vip_bonus_job = battle_config.vip_job_exp_increase; - } -#endif - *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100., 1, UINT_MAX); - - if (sd->sc.data[SC_JEXPBOOST]) + + if (&sd->sc && sd->sc.data[SC_JEXPBOOST]) bonus += sd->sc.data[SC_JEXPBOOST]->val1; *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * (bonus + vip_bonus_job)/100., 1, UINT_MAX); @@ -6258,10 +6261,11 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi /*========================================== * Give x exp at sd player and calculate remaining exp for next lvl *------------------------------------------*/ -int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool quest) +int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool quest) { - float nextbp=0, nextjp=0; - unsigned int nextb=0, nextj=0; + float nextbp = 0, nextjp = 0; + unsigned int nextb = 0, nextj = 0; + nullpo_ret(sd); if(sd->bl.prev == NULL || pc_isdead(sd)) @@ -6273,7 +6277,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int if(sd->status.guild_id>0) base_exp-=guild_payexp(sd,base_exp); - if(src) pc_calcexp(sd, &base_exp, &job_exp, src); + pc_calcexp(sd, &base_exp, &job_exp, src); // Give (J)EXPBOOST for quests even if src is NULL. nextb = pc_nextbaseexp(sd); nextj = pc_nextjobexp(sd); diff --git a/src/map/skill.c b/src/map/skill.c index c0b2c87812..80102b673b 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -8378,7 +8378,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui int8 rate = rnd()%100; int16 shields = ((rate < 20) ? 4 : (rate < 50) ? 3 : 2); sc_start4(src,bl,type,100,skill_lv,shields,1000,0,skill_get_time(skill_id,skill_lv)); - clif_millenniumshield(sd,shields); + clif_millenniumshield(bl,shields); clif_skill_nodamage(src,bl,skill_id,1,1); } break; @@ -8427,7 +8427,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui if( skill_area_temp[5]&0x10 ) { if( dstsd ) { i = (rnd()%100 < 50) ? 4 : ((rnd()%100 < 80) ? 3 : 2); - clif_millenniumshield(dstsd,i); + clif_millenniumshield(bl,i); skill_area_temp[5] &= ~0x10; type = SC_MILLENNIUMSHIELD; } diff --git a/src/map/status.c b/src/map/status.c index 9034c8d5fd..52bb8366eb 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -726,7 +726,6 @@ void initChangeTables(void) set_sc( GN_CARTBOOST , SC_GN_CARTBOOST , SI_GN_CARTBOOST , SCB_SPEED ); set_sc( GN_THORNS_TRAP , SC_THORNSTRAP , SI_THORNTRAP , SCB_NONE ); set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOODSUCKER , SI_BLOODSUCKER , SCB_NONE ); - add_sc( GN_WALLOFTHORN , SC_STOP ); set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER , SC_SMOKEPOWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_FLEE ); set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_TEARGAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_HIT|SCB_FLEE ); set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT ); @@ -2849,11 +2848,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) clif_status_load(&sd->bl, SI_INTRAVISION, 0); memset(&sd->special_state,0,sizeof(sd->special_state)); - memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); + + if (!sd->state.permanent_speed) { + memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); + status->speed = DEFAULT_WALK_SPEED; + } else { + int pSpeed = status->speed; + + memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); + status->speed = pSpeed; + } // !FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] - if (!sd->state.permanent_speed) - status->speed = DEFAULT_WALK_SPEED; // Give them all modes except these (useful for clones) status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); @@ -4247,6 +4253,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(flag&SCB_SPEED) { struct unit_data *ud = unit_bl2ud(bl); + status->speed = status_calc_speed(bl, sc, b_status->speed); /** [Skotlex] @@ -4257,7 +4264,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if (ud) ud->state.change_walk_target = ud->state.speed_changed = 1; - if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed ) + if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && status->speed < battle_config.max_walk_speed ) status->speed = battle_config.max_walk_speed; if( bl->type&BL_HOM && battle_config.hom_setting&HOMSET_COPY_SPEED && ((TBL_HOM*)bl)->master) @@ -4266,8 +4273,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) status->speed = status_get_speed(&((TBL_MER*)bl)->master->bl); if( bl->type&BL_ELEM && ((TBL_ELEM*)bl)->master) status->speed = status_get_speed(&((TBL_ELEM*)bl)->master->bl); - - } if(flag&SCB_CRI && b_status->cri) { @@ -4279,7 +4284,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) /// After status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240 if( bl->type == BL_PC && ((TBL_PC*)bl)->status.weapon == W_KATAR ) status->cri <<= 1; - } if(flag&SCB_FLEE2 && b_status->flee2) { @@ -5826,11 +5830,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha TBL_PC* sd = BL_CAST(BL_PC, bl); int speed_rate = 100; - if( sc == NULL ) - return cap_value(speed,10,USHRT_MAX); - - if (sd && sd->state.permanent_speed) - return (short)cap_value(speed,10,USHRT_MAX); + if (sc == NULL || (sd && sd->state.permanent_speed)) + return (unsigned short)cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) ) { if( sd->ud.skill_id == LG_EXEEDBREAK ) @@ -5992,7 +5993,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha if( sc->data[SC_REBOUND] ) speed += max(speed, 100); - return (short)cap_value(speed,10,USHRT_MAX); + return (unsigned short)cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); } #ifdef RENEWAL_ASPD @@ -8195,7 +8196,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty case SC_MARIONETTE: case SC_MARIONETTE2: case SC_NOCHAT: - case SC_CHANGE: // Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. case SC_ABUNDANCE: case SC_FEAR: case SC_TOXIN: @@ -10212,9 +10212,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty } sce->val2 = 5 * status->max_hp / 100; break; - case SC_CHANGE: - status_percent_heal(bl, 100, 100); - break; case SC_RUN: { struct unit_data *ud = unit_bl2ud(bl); @@ -10762,7 +10759,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const /* 3rd Stuff */ case SC_MILLENNIUMSHIELD: - clif_millenniumshield(sd,0); + clif_millenniumshield(bl, 0); break; case SC_HALLUCINATIONWALK: sc_start(bl,bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill_get_time2(GC_HALLUCINATIONWALK,sce->val1));