From 3ed04f57c71a0b3486bb96b8319f852028dc8c7e Mon Sep 17 00:00:00 2001 From: shennetsind Date: Wed, 30 Jan 2013 19:40:17 -0200 Subject: Fixing skill_trap_type bug, special thanks to exneval Signed-off-by: shennetsind --- src/map/unit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/unit.c b/src/map/unit.c index 148a35782..b7da5629f 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -350,7 +350,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) map_random_dir(bl, &ud->to_x, &ud->to_y); if(ud->walktimer != INVALID_TIMER) { - if( !battle_config.skill_trap_type && sc->data[SC_ANKLE] ) // Ankle disallows you from changing your path + if( !battle_config.skill_trap_type && sc && sc->data[SC_ANKLE] ) // Ankle disallows you from changing your path return 0; // When you come to the center of the grid because the change of destination while you're walking right now // Call a function from a timer unit_walktoxy_sub @@ -427,7 +427,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int map_random_dir(bl, &ud->to_x, &ud->to_y); if(ud->walktimer != INVALID_TIMER) { - if( !battle_config.skill_trap_type && sc->data[SC_ANKLE] ) // Ankle disallows you from changing your path + if( !battle_config.skill_trap_type && sc && sc->data[SC_ANKLE] ) // Ankle disallows you from changing your path return 0; ud->state.change_walk_target = 1; set_mobstate(bl, flag&2); -- cgit v1.2.3-70-g09d2 From 620b36de1890e39ce662245567ac8e60b5cc8990 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Wed, 30 Jan 2013 19:40:36 -0200 Subject: Fixing a typo on skill_trap_type description Signed-off-by: shennetsind --- conf/battle/skill.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/battle/skill.conf b/conf/battle/skill.conf index 03aae2ad1..0dd97610e 100644 --- a/conf/battle/skill.conf +++ b/conf/battle/skill.conf @@ -278,5 +278,5 @@ dancing_weaponswitch_fix: yes // Skill Trap Type // 0: (official) traps only makes player unable to move after its walk path is complete, and it activates other traps on the way. -// 1: trap makes player stops moving right when stepping over it. +// 1: trap makes player stop moving right when stepping over it. skill_trap_type: 0 -- cgit v1.2.3-70-g09d2 From 13317f0e0db8cce32da951c25707840d6357d079 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 31 Jan 2013 11:20:35 -0200 Subject: Fixed Bug #7038 Spider web no longer triggers on players on non-pvp maps http://hercules.ws/board/tracker/issue-7038-spider-web/ (also fixed tab align on switch and a logical thing on skill_additional_effect) Signed-off-by: shennetsind --- src/map/skill.c | 326 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 161 insertions(+), 165 deletions(-) diff --git a/src/map/skill.c b/src/map/skill.c index 752b1ece0..ecd1ff8ac 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1560,7 +1560,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if (skill == AS_SONICBLOW) pc_stop_attack(sd); //Special case, Sonic Blow autospell should stop the player attacking. - if (skill == PF_SPIDERWEB) //Special case, due to its nature of coding. + else if (skill == PF_SPIDERWEB) //Special case, due to its nature of coding. type = CAST_GROUND; sd->state.autocast = 1; @@ -11041,195 +11041,191 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un type = status_skill2sc(sg->skill_id); sce = (sc && type != -1)?sc->data[type]:NULL; skill_id = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still. - switch (sg->unit_id) - { - case UNT_SPIDERWEB: - if( sc && sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1 > 0 ) - { // If you are fiberlocked and can't move, it will only increase your fireweakness level. [Inkfish] - sc->data[SC_SPIDERWEB]->val2++; - break; - } - else if( sc ) - { - int sec = skill_get_time2(sg->skill_id,sg->skill_lv); - if( status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) - { - const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL; - if( td ) - sec = DIFF_TICK(td->tick, tick); - map_moveblock(bl, src->bl.x, src->bl.y, tick); - clif_fixpos(bl); - sg->val2 = bl->id; + switch (sg->unit_id) { + case UNT_SPIDERWEB: + if( sc && sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1 > 0 ) { + // If you are fiberlocked and can't move, it will only increase your fireweakness level. [Inkfish] + sc->data[SC_SPIDERWEB]->val2++; + break; + } else if( sc && battle_check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) { + int sec = skill_get_time2(sg->skill_id,sg->skill_lv); + if( status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) { + const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL; + if( td ) + sec = DIFF_TICK(td->tick, tick); + map_moveblock(bl, src->bl.x, src->bl.y, tick); + clif_fixpos(bl); + sg->val2 = bl->id; + } + else + sec = 3000; //Couldn't trap it? + sg->limit = DIFF_TICK(tick,sg->tick)+sec; } - else - sec = 3000; //Couldn't trap it? - sg->limit = DIFF_TICK(tick,sg->tick)+sec; - } - break; - case UNT_SAFETYWALL: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); - break; + break; + case UNT_SAFETYWALL: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); + break; - case UNT_PNEUMA: - case UNT_CHAOSPANIC: - case UNT_MAELSTROM: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); - break; - case UNT_BLOODYLUST: - if (sg->src_id == bl->id) - break; //Does not affect the caster. - if (!sce) { - TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit - if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1)) - clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, - sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); - else { - if (sd) sd->bloodylust_tick = gettick(); + case UNT_PNEUMA: + case UNT_CHAOSPANIC: + case UNT_MAELSTROM: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + break; + case UNT_BLOODYLUST: + if (sg->src_id == bl->id) + break; //Does not affect the caster. + if (!sce) { + TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit + if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1)) clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, - sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); + sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); + else { + if (sd) sd->bloodylust_tick = gettick(); + clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, + sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); + } } - } - break; + break; - case UNT_WARP_WAITING: { - int working = sg->val1&0xffff; + case UNT_WARP_WAITING: { + int working = sg->val1&0xffff; - if(bl->type==BL_PC && !working){ - struct map_session_data *sd = (struct map_session_data *)bl; - if((!sd->chatID || battle_config.chat_warpportal) - && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) - { - int x = sg->val2>>16; - int y = sg->val2&0xffff; - int count = sg->val1>>16; - unsigned short m = sg->val3; + if(bl->type==BL_PC && !working){ + struct map_session_data *sd = (struct map_session_data *)bl; + if((!sd->chatID || battle_config.chat_warpportal) + && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) + { + int x = sg->val2>>16; + int y = sg->val2&0xffff; + int count = sg->val1>>16; + unsigned short m = sg->val3; - if( --count <= 0 ) - skill_delunitgroup(sg); + if( --count <= 0 ) + skill_delunitgroup(sg); - if ( map_mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y ) - working = 1;/* we break it because officials break it, lovely stuff. */ + if ( map_mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y ) + working = 1;/* we break it because officials break it, lovely stuff. */ - sg->val1 = (count<<16)|working; + sg->val1 = (count<<16)|working; - pc_setpos(sd,m,x,y,CLR_TELEPORT); + pc_setpos(sd,m,x,y,CLR_TELEPORT); + } + } else if(bl->type == BL_MOB && battle_config.mob_warp&2) { + int16 m = map_mapindex2mapid(sg->val3); + if (m < 0) break; //Map not available on this map-server. + unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT); } - } else if(bl->type == BL_MOB && battle_config.mob_warp&2) { - int16 m = map_mapindex2mapid(sg->val3); - if (m < 0) break; //Map not available on this map-server. - unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT); } - } - break; + break; - case UNT_QUAGMIRE: - if( !sce && battle_check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); - break; + case UNT_QUAGMIRE: + if( !sce && battle_check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) + sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + break; - case UNT_VOLCANO: - case UNT_DELUGE: - case UNT_VIOLENTGALE: - if(!sce) - sc_start(bl,type,100,sg->skill_lv,sg->limit); - break; + case UNT_VOLCANO: + case UNT_DELUGE: + case UNT_VIOLENTGALE: + if(!sce) + sc_start(bl,type,100,sg->skill_lv,sg->limit); + break; - case UNT_SUITON: - if(!sce) - sc_start4(bl,type,100,sg->skill_lv, - map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. - 0,0,sg->limit); - break; + case UNT_SUITON: + if(!sce) + sc_start4(bl,type,100,sg->skill_lv, + map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. + 0,0,sg->limit); + break; - case UNT_HERMODE: - if (sg->src_id!=bl->id && battle_check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) - status_change_clear_buffs(bl,1); //Should dispell only allies. - case UNT_RICHMANKIM: - case UNT_ETERNALCHAOS: - case UNT_DRUMBATTLEFIELD: - case UNT_RINGNIBELUNGEN: - case UNT_ROKISWEIL: - case UNT_INTOABYSS: - case UNT_SIEGFRIED: - //Needed to check when a dancer/bard leaves their ensemble area. - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) - return skill_id; - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - break; - case UNT_WHISTLE: - case UNT_ASSASSINCROSS: - case UNT_POEMBRAGI: - case UNT_APPLEIDUN: - case UNT_HUMMING: - case UNT_DONTFORGETME: - case UNT_FORTUNEKISS: - case UNT_SERVICEFORYOU: - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) - return 0; + case UNT_HERMODE: + if (sg->src_id!=bl->id && battle_check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) + status_change_clear_buffs(bl,1); //Should dispell only allies. + case UNT_RICHMANKIM: + case UNT_ETERNALCHAOS: + case UNT_DRUMBATTLEFIELD: + case UNT_RINGNIBELUNGEN: + case UNT_ROKISWEIL: + case UNT_INTOABYSS: + case UNT_SIEGFRIED: + //Needed to check when a dancer/bard leaves their ensemble area. + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + return skill_id; + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + break; + case UNT_WHISTLE: + case UNT_ASSASSINCROSS: + case UNT_POEMBRAGI: + case UNT_APPLEIDUN: + case UNT_HUMMING: + case UNT_DONTFORGETME: + case UNT_FORTUNEKISS: + case UNT_SERVICEFORYOU: + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + return 0; - if (!sc) return 0; - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - else if (sce->val4 == 1) { - //Readjust timers since the effect will not last long. - sce->val4 = 0; - delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); - } - break; + if (!sc) return 0; + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + else if (sce->val4 == 1) { + //Readjust timers since the effect will not last long. + sce->val4 = 0; + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); + } + break; - case UNT_FOGWALL: - if (!sce) - { - sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); - if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) - skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); - } - break; + case UNT_FOGWALL: + if (!sce) + { + sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); + if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) + skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); + } + break; - case UNT_GRAVITATION: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); - break; + case UNT_GRAVITATION: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); + break; -// officially, icewall has no problems existing on occupied cells [ultramage] -// case UNT_ICEWALL: //Destroy the cell. [Skotlex] -// src->val1 = 0; -// if(src->limit + sg->tick > tick + 700) -// src->limit = DIFF_TICK(tick+700,sg->tick); -// break; + // officially, icewall has no problems existing on occupied cells [ultramage] + // case UNT_ICEWALL: //Destroy the cell. [Skotlex] + // src->val1 = 0; + // if(src->limit + sg->tick > tick + 700) + // src->limit = DIFF_TICK(tick+700,sg->tick); + // break; - case UNT_MOONLIT: - //Knockback out of area if affected char isn't in Moonlit effect - if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) - break; - if (ss == bl) //Also needed to prevent infinite loop crash. + case UNT_MOONLIT: + //Knockback out of area if affected char isn't in Moonlit effect + if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) + break; + if (ss == bl) //Also needed to prevent infinite loop crash. + break; + skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); break; - skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); - break; - case UNT_WALLOFTHORN: - if( status_get_mode(bl)&MD_BOSS ) - break; // iRO Wiki says that this skill don't affect to Boss monsters. - if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle_check_target(&src->bl,bl, BCT_ENEMY) == 1 ) - skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - break; + case UNT_WALLOFTHORN: + if( status_get_mode(bl)&MD_BOSS ) + break; // iRO Wiki says that this skill don't affect to Boss monsters. + if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle_check_target(&src->bl,bl, BCT_ENEMY) == 1 ) + skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + break; - case UNT_VOLCANIC_ASH: - if (!sce) - sc_start(bl, SC_ASH, 100, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); - break; + case UNT_VOLCANIC_ASH: + if (!sce) + sc_start(bl, SC_ASH, 100, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); + break; - case UNT_GD_LEADERSHIP: - case UNT_GD_GLORYWOUNDS: - case UNT_GD_SOULCOLD: - case UNT_GD_HAWKEYES: - if ( !sce ) - sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); - break; + case UNT_GD_LEADERSHIP: + case UNT_GD_GLORYWOUNDS: + case UNT_GD_SOULCOLD: + case UNT_GD_HAWKEYES: + if ( !sce ) + sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); + break; } return skill_id; } -- cgit v1.2.3-70-g09d2 From fc2e159d8c3d45ddeae4ce1dcc84312303442745 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 31 Jan 2013 15:51:50 -0200 Subject: Fixed Bug #6918 @follow will not stop immeadily when turned off, instead of waiting for the current walk path to be complete. http://hercules.ws/board/tracker/issue-6918-follow-not-releasing-hold/ Signed-off-by: shennetsind --- src/map/pc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/map/pc.c b/src/map/pc.c index 89925f8f2..abfbbcc12 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5518,6 +5518,8 @@ int pc_stop_following (struct map_session_data *sd) sd->followtarget = -1; sd->ud.target_to = 0; + unit_stop_walking(&sd->bl, 1); + return 0; } -- cgit v1.2.3-70-g09d2 From 638e2b5c985c13a8138d1cb166d5fdb8148b690c Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 31 Jan 2013 16:11:07 -0200 Subject: Fixed Bug #3080 Replaced strncpy with safestrncpy where I found would be beneficial. http://hercules.ws/board/tracker/issue-3080-safestrncpy-instead-of-strncpy-where-applicable/ Also modifying headers accordingly. Signed-off-by: shennetsind --- src/char/int_guild.c | 7 ++++--- src/char/int_pet.c | 7 ++++--- src/common/mapindex.c | 9 +++++---- src/login/login.c | 7 ++++--- src/map/chrif.c | 7 ++++--- src/map/clif.c | 2 +- src/map/elemental.c | 10 ++++++---- src/map/homunculus.c | 11 ++++++----- src/map/map.c | 9 +++++---- src/map/mercenary.c | 9 +++++---- src/map/mob.c | 7 ++++--- src/map/npc.c | 9 +++++---- 12 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/char/int_guild.c b/src/char/int_guild.c index 7090af5ee..9cb17dca8 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/mmo.h" @@ -1815,7 +1816,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le g->member[0].position = 0; //Position 0: guild Master. g->member[0].modified = GS_MEMBER_MODIFIED; - strncpy(g->master, name, len); + safestrncpy(g->master, name, len); if (len < NAME_LENGTH) g->master[len] = '\0'; diff --git a/src/char/int_pet.c b/src/char/int_pet.c index 114398290..d9b0cf5ef 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/mmo.h" #include "../common/malloc.h" @@ -184,7 +185,7 @@ int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name) { memset(pet_pt, 0, sizeof(struct s_pet)); - strncpy(pet_pt->name, pet_name, NAME_LENGTH); + safestrncpy(pet_pt->name, pet_name, NAME_LENGTH); if(incuvate == 1) pet_pt->account_id = pet_pt->char_id = 0; else { diff --git a/src/common/mapindex.c b/src/common/mapindex.c index d46047833..cea945ac0 100644 --- a/src/common/mapindex.c +++ b/src/common/mapindex.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/mmo.h" #include "../common/showmsg.h" @@ -37,7 +38,7 @@ const char* mapindex_getmapname(const char* string, char* output) len -= 4; // strip .gat extension len = min(len, MAP_NAME_LENGTH-1); - strncpy(dest, string, len+1); + safestrncpy(dest, string, len+1); memset(&dest[len], '\0', MAP_NAME_LENGTH-len); return dest; @@ -61,7 +62,7 @@ const char* mapindex_getmapname_ext(const char* string, char* output) ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH, buf); len--; } - strncpy(dest, buf, len+1); + safestrncpy(dest, buf, len+1); if (len < 4 || stricmp(&dest[len-4], ".gat") != 0) { strcpy(&dest[len], ".gat"); diff --git a/src/login/login.c b/src/login/login.c index e079dbaf2..625e0f5c6 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/core.h" #include "../common/db.h" @@ -1596,7 +1597,7 @@ int login_config_read(const char* cfgName) continue; if(!strcmpi(w1,"timestamp_format")) - strncpy(timestamp_format, w2, 20); + safestrncpy(timestamp_format, w2, 20); else if(!strcmpi(w1,"stdout_with_ansisequence")) stdout_with_ansisequence = config_switch(w2); else if(!strcmpi(w1,"console_silent")) { diff --git a/src/map/chrif.c b/src/map/chrif.c index e109f7095..3ad164b89 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -246,7 +247,7 @@ int chrif_setip(const char* ip) { return 0; } - strncpy(char_ip_str, ip, sizeof(char_ip_str)); + safestrncpy(char_ip_str, ip, sizeof(char_ip_str)); ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(char_ip, ip_str)); diff --git a/src/map/clif.c b/src/map/clif.c index 3f4ea8bc2..0e555252b 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -203,7 +203,7 @@ int clif_setip(const char* ip) return 0; } - strncpy(map_ip_str, ip, sizeof(map_ip_str)); + safestrncpy(map_ip_str, ip, sizeof(map_ip_str)); ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(map_ip, ip_str)); return 1; } diff --git a/src/map/elemental.c b/src/map/elemental.c index 90b90c1e3..f6c9eff84 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -10,6 +11,7 @@ #include "../common/showmsg.h" #include "../common/utils.h" #include "../common/random.h" +#include "../common/strlib.h" #include "log.h" #include "clif.h" @@ -795,8 +797,8 @@ int read_elementaldb(void) { db = &elemental_db[j]; db->class_ = atoi(str[0]); - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->name, str[2], NAME_LENGTH); + safestrncpy(db->sprite, str[1], NAME_LENGTH); + safestrncpy(db->name, str[2], NAME_LENGTH); db->lv = atoi(str[3]); status = &db->status; diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 081287d8a..c94a95775 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -709,7 +710,7 @@ int merc_hom_change_name_ack(struct map_session_data *sd, char* name, int flag) clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name return 0; } - strncpy(hd->homunculus.name,name,NAME_LENGTH); + safestrncpy(hd->homunculus.name,name,NAME_LENGTH); clif_charnameack (0,&hd->bl); hd->homunculus.rename_flag = 1; clif_hominfo(sd,hd,0); @@ -887,7 +888,7 @@ int merc_create_homunculus_request(struct map_session_data *sd, int class_) memset(&homun, 0, sizeof(struct s_homunculus)); //Initial data - strncpy(homun.name, homunculus_db[i].name, NAME_LENGTH-1); + safestrncpy(homun.name, homunculus_db[i].name, NAME_LENGTH-1); homun.class_ = class_; homun.level = 1; homun.hunger = 32; //32% @@ -1050,7 +1051,7 @@ static bool read_homunculusdb_sub(char* str[], int columns, int current) } db->evo_class = classid; //Name, Food, Hungry Delay, Base Size, Evo Size, Race, Element, ASPD - strncpy(db->name,str[2],NAME_LENGTH-1); + safestrncpy(db->name,str[2],NAME_LENGTH-1); db->foodID = atoi(str[3]); db->hungryDelay = atoi(str[4]); db->base_size = atoi(str[5]); diff --git a/src/map/map.c b/src/map/map.c index a8521de7d..d2cc9c4a9 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/core.h" @@ -3216,7 +3217,7 @@ int map_config_read(char *cfgName) *ptr = '\0'; if(strcmpi(w1,"timestamp_format")==0) - strncpy(timestamp_format, w2, 20); + safestrncpy(timestamp_format, w2, 20); else if(strcmpi(w1,"stdout_with_ansisequence")==0) stdout_with_ansisequence = config_switch(w2); else if(strcmpi(w1,"console_silent")==0) { @@ -3267,7 +3268,7 @@ int map_config_read(char *cfgName) else if (strcmpi(w1, "charhelp_txt") == 0) strcpy(charhelp_txt, w2); else if(strcmpi(w1,"db_path") == 0) - strncpy(db_path,w2,255); + safestrncpy(db_path,w2,255); else if (strcmpi(w1, "console") == 0) { console = config_switch(w2); if (console) diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 973dac33e..c3fb8e3e2 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -404,8 +405,8 @@ static bool read_mercenarydb_sub(char* str[], int columns, int current) db = &mercenary_db[current]; db->class_ = atoi(str[0]); - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->name, str[2], NAME_LENGTH); + safestrncpy(db->sprite, str[1], NAME_LENGTH); + safestrncpy(db->name, str[2], NAME_LENGTH); db->lv = atoi(str[3]); status = &db->status; diff --git a/src/map/mob.c b/src/map/mob.c index ac3c1dfe3..6550d9b0e 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -4120,7 +4121,7 @@ static bool mob_parse_row_chatdb(char** str, const char* source, int line, int* } msg[len] = 0; // strip previously found EOL - strncpy(ms->msg, str[2], CHAT_SIZE_MAX); + safestrncpy(ms->msg, str[2], CHAT_SIZE_MAX); return true; } diff --git a/src/map/npc.c b/src/map/npc.c index 5d8a0274e..8de53a64e 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -1915,7 +1916,7 @@ void npc_addsrcfile(const char* name) file = (struct npc_src_list*)aMalloc(sizeof(struct npc_src_list) + strlen(name)); file->next = NULL; - strncpy(file->name, name, strlen(name) + 1); + safestrncpy(file->name, name, strlen(name) + 1); if( file_prev == NULL ) npc_src_files = file; else @@ -3606,7 +3607,7 @@ void npc_read_event_script(void) DBData *data; char name[64]="::"; - strncpy(name+2,config[i].event_name,62); + safestrncpy(name+2,config[i].event_name,62); script_event[i].event_count = 0; iter = db_iterator(ev_db); -- cgit v1.2.3-70-g09d2 From 74ed3ed32f33ad4df945718389d7d74ab0a53794 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 31 Jan 2013 16:28:43 -0200 Subject: Fixed Bug #6097 Players in Chatrooms now: - Can Equip/Unequip gear - Can Talk to NPCS - Cant use consumable Items http://hercules.ws/board/tracker/issue-6097-chatroom/ Signed-off-by: shennetsind --- src/map/clif.c | 10 +++++----- src/map/pc.h | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/map/clif.c b/src/map/clif.c index 0e555252b..fba5ffecc 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -10141,7 +10141,7 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) if (pc_isdead(sd)) break; - if (pc_cant_act(sd)) + if ( pc_cant_act2(sd) ) break; if (sd->sc.count && ( @@ -10180,7 +10180,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) if (sd->npc_id != sd->npc_item_flag) return; } - else if (pc_istrading(sd)) + else if ( pc_istrading(sd) || sd->chatID ) return; //Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex] @@ -10213,7 +10213,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) return; } else if (sd->state.storage_flag || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes - else if (pc_cant_act(sd)) + else if ( pc_cant_act2(sd) ) return; if(!sd->status.inventory[index].identify) { @@ -10250,7 +10250,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) if (sd->state.storage_flag || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes - else if (pc_cant_act(sd)) + else if ( pc_cant_act2(sd) ) return; index = RFIFOW(fd,2)-2; @@ -10272,7 +10272,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) return; } - if (pc_cant_act(sd)) + if ( pc_cant_act2(sd) ) return; bl = map_id2bl(RFIFOL(fd,2)); diff --git a/src/map/pc.h b/src/map/pc.h index 3027c5f10..870945d73 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #ifndef _PC_H_ #define _PC_H_ @@ -592,6 +593,10 @@ enum equip_index { #define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share ) #define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading ) #define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag ) + +/* equals pc_cant_act except it doesn't check for chat rooms */ +#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag ) + #define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) ) #define pc_setchatid(sd,n) ( (sd)->chatID = n ) #define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) ) -- cgit v1.2.3-70-g09d2 From 7192b105201499e30a50c061e7ab2005c97d3714 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 1 Feb 2013 12:08:02 -0200 Subject: Fixed Bug #5343 SECURE_NPCTIMEOUT should be fully functional now, fixed remaining known issues. http://hercules.ws/board/tracker/issue-5343-delete-timer-error/ Signed-off-by: shennetsind --- src/map/clif.c | 15 ++++++++++----- src/map/npc.c | 3 +++ src/map/script.c | 34 +++++++++++++++------------------- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/map/clif.c b/src/map/clif.c index fba5ffecc..f8b5119eb 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -11111,11 +11111,16 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) int npc_id = RFIFOL(fd,2); uint8 select = RFIFOB(fd,6); - if( (select > sd->npc_menu && select != 0xff) || select == 0 ) - { - TBL_NPC* nd = map_id2nd(npc_id); - ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); - clif_GM_kick(NULL,sd); + if( (select > sd->npc_menu && select != 0xff) || select == 0 ) { +#ifdef SECURE_NPCTIMEOUT + if( sd->npc_idle_timer != INVALID_TIMER ) { +#endif + TBL_NPC* nd = map_id2nd(npc_id); + ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); + clif_GM_kick(NULL,sd); +#ifdef SECURE_NPCTIMEOUT + } +#endif return; } diff --git a/src/map/npc.c b/src/map/npc.c index 8de53a64e..3aabeaf98 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -232,6 +232,9 @@ int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t dat **/ if( sd->st ) sd->st->state = END; + sd->state.menu_or_input = 0; + sd->npc_menu = 0; + /** * This guy's been idle for longer than allowed, close him. **/ diff --git a/src/map/script.c b/src/map/script.c index 4099820f1..60a61654a 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3590,30 +3590,26 @@ static void script_detach_state(struct script_state* st, bool dequeue_event) { struct map_session_data* sd; - if(st->rid && (sd = map_id2sd(st->rid))!=NULL) - { + if(st->rid && (sd = map_id2sd(st->rid))!=NULL) { sd->st = st->bk_st; sd->npc_id = st->bk_npcid; - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ - #if SECURE_NPCTIMEOUT - /** - * We're done with this NPC session, so we cancel the timer (if existent) and move on - **/ - if( sd->npc_idle_timer != INVALID_TIMER ) { - delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer); - sd->npc_idle_timer = INVALID_TIMER; - } - #endif - if(st->bk_st) - { + if(st->bk_st) { //Remove tag for removal. st->bk_st = NULL; st->bk_npcid = 0; - } - else if(dequeue_event) - { + } else if(dequeue_event) { + /** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ +#if SECURE_NPCTIMEOUT + /** + * We're done with this NPC session, so we cancel the timer (if existent) and move on + **/ + if( sd->npc_idle_timer != INVALID_TIMER ) { + delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer); + sd->npc_idle_timer = INVALID_TIMER; + } +#endif npc_event_dequeue(sd); } } -- cgit v1.2.3-70-g09d2 From 63145d6d4079b692a3cd36eb340b9a0e71b9fbaa Mon Sep 17 00:00:00 2001 From: malufett Date: Fri, 1 Feb 2013 22:14:25 +0800 Subject: Fixed Bug #7037 Where casting MO_EXTREMITY to untargetable targets causes the caster to move in fixed location/coordinate. http://hercules.ws/board/tracker/issue-7037-asura-strike-position/?gopid=16521#entry16521 --- src/map/skill.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/map/skill.c b/src/map/skill.c index ecd1ff8ac..448f54406 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1,4 +1,4 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder #include "../common/cbasetypes.h" @@ -9373,7 +9373,15 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) } if (target && target->m == src->m) { //Move character to target anyway. - if (unit_movepos(src, src->x+3, src->y+3, 1, 1)) + int dir, x, y; + dir = map_calc_dir(src,target->x,target->y); + if( dir > 0 && dir < 4) x = -2; + else if( dir > 4 ) x = 2; + else x = 0; + if( dir > 2 && dir < 6 ) y = -2; + else if( dir == 7 || dir < 2 ) y = 2; + else y = 0; + if (unit_movepos(src, src->x+x, src->y+y, 1, 1)) { //Display movement + animation. clif_slide(src,src->x,src->y); clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skill_id, ud->skill_lv, 5); -- cgit v1.2.3-70-g09d2 From 17f2e6a581ef9e37f01cfd1b98c335a6d5b5ac75 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 1 Feb 2013 23:06:45 -0200 Subject: Fixed clif.c::clif_parse_NpcSelectMenu SECURE_NPCTIMEOUT is always defined; the check is wrong. Signed-off-by: shennetsind --- src/map/clif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/clif.c b/src/map/clif.c index f8b5119eb..3443c1ae3 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -11112,13 +11112,13 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) uint8 select = RFIFOB(fd,6); if( (select > sd->npc_menu && select != 0xff) || select == 0 ) { -#ifdef SECURE_NPCTIMEOUT +#if SECURE_NPCTIMEOUT if( sd->npc_idle_timer != INVALID_TIMER ) { #endif TBL_NPC* nd = map_id2nd(npc_id); ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); clif_GM_kick(NULL,sd); -#ifdef SECURE_NPCTIMEOUT +#if SECURE_NPCTIMEOUT } #endif return; -- cgit v1.2.3-70-g09d2 From 125b75890b29073b0264009e9638e68911a1aa07 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 1 Feb 2013 23:15:49 -0200 Subject: Added New Char-Server Rename Packet Special Thanks to Ancyker http://hercules.ws/board/tracker/issue-7040-missing-char-server-rename-packet/ Signed-off-by: shennetsind --- src/char/char.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/char/char.c b/src/char/char.c index 83b58a0a7..d454e8bd0 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -3991,6 +3991,35 @@ int parse_char(int fd) return 0; RFIFOSKIP(fd,6); break; + // char rename request + // R 08fc .l .24B + case 0x8fc: + FIFOSD_CHECK(30); + { + int i, cid =RFIFOL(fd,2); + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1]; + safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH); + RFIFOSKIP(fd,30); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + break; + + normalize_name(name,TRIM_CHARS); + Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( !check_char_name(name,esc_name) ) { + i = 1; + safestrncpy(sd->new_name, name, NAME_LENGTH); + } else + i = 0; + + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x28e; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } + break; // char rename request // R 028d .l .l .24B -- cgit v1.2.3-70-g09d2 From a4a549da77879c142ed9fe667ed312dfa6e6b70a Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 12:25:53 -0200 Subject: Introducing MySQL Reconnect * mysql_reconnect_type ** 1: when mysql disconnects during runtime, the server tries to reconnect mysql_reconnect_count times and, if unsuccessful, the server is shut down ** 2: when mysql disconnects during runtime it tries to reconnect indefinitely mysql_reconnect_type:2 * mysql_reconnect_count ** number of reconnect attempts the server should do when the database disconnects during runtime ** only used when mysql_reconnect_type is 1 mysql_reconnect_count:1 ~Ind Signed-off-by: shennetsind --- conf/inter-server.conf | 12 ++++++++ src/common/core.c | 2 ++ src/common/sql.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- src/common/sql.h | 1 + 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/conf/inter-server.conf b/conf/inter-server.conf index 70bf80e5c..523437007 100644 --- a/conf/inter-server.conf +++ b/conf/inter-server.conf @@ -56,6 +56,18 @@ log_db_db: ragnarok log_codepage: log_login_db: loginlog +// == MySQL Reconnect Settings +// =========================== +// - mysql_reconnect_type +// - 1: when mysql disconnects during runtime, the server tries to reconnect mysql_reconnect_count times and, +// -- if unsuccessful, the server is shut down +// - 2: when mysql disconnects during runtime it tries to reconnect indefinitely +mysql_reconnect_type:2 +// - mysql_reconnect_count +// - number of reconnect attempts the server should do when the database disconnects during runtime +// - only used when mysql_reconnect_type is 1 +mysql_reconnect_count:1 + // DO NOT CHANGE ANYTHING BEYOND THIS LINE UNLESS YOU KNOW YOUR DATABASE DAMN WELL // this is meant for people who KNOW their stuff, and for some reason want to change their // database layout. [CLOWNISIUS] diff --git a/src/common/core.c b/src/common/core.c index 1e3dbb3d7..bb536a255 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -11,6 +11,7 @@ #include "../common/timer.h" #include "../common/thread.h" #include "../common/mempool.h" +#include "../common/sql.h" #endif #include @@ -319,6 +320,7 @@ int main (int argc, char **argv) display_title(); usercheck(); + Sql_Init(); rathread_init(); mempool_init(); db_init(); diff --git a/src/common/sql.c b/src/common/sql.c index 800aa89b0..96346d68c 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -15,7 +15,10 @@ #include // strlen/strnlen/memcpy/memset #include // strtoul +void hercules_mysql_error_handler(unsigned int ecode); +int mysql_reconnect_type; +int mysql_reconnect_count; /// Sql handle struct Sql @@ -74,7 +77,7 @@ Sql* Sql_Malloc(void) self->lengths = NULL; self->result = NULL; self->keepalive = INVALID_TIMER; - + self->handle.reconnect = 1; return self; } @@ -266,12 +269,14 @@ int Sql_QueryV(Sql* self, const char* query, va_list args) if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } self->result = mysql_store_result(&self->handle); if( mysql_errno(&self->handle) != 0 ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } return SQL_SUCCESS; @@ -291,12 +296,14 @@ int Sql_QueryStr(Sql* self, const char* query) if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } self->result = mysql_store_result(&self->handle); if( mysql_errno(&self->handle) != 0 ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } return SQL_SUCCESS; @@ -639,6 +646,7 @@ int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args) if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } self->bind_params = false; @@ -660,6 +668,7 @@ int SqlStmt_PrepareStr(SqlStmt* self, const char* query) if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } self->bind_params = false; @@ -721,12 +730,14 @@ int SqlStmt_Execute(SqlStmt* self) mysql_stmt_execute(self->stmt) ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } self->bind_columns = false; if( mysql_stmt_store_result(self->stmt) )// store all the data { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } @@ -868,6 +879,7 @@ int SqlStmt_NextRow(SqlStmt* self) if( err ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } @@ -946,3 +958,63 @@ void SqlStmt_Free(SqlStmt* self) aFree(self); } } +/* receives mysql error codes during runtime (not on first-time-connects) */ +void hercules_mysql_error_handler(unsigned int ecode) { + static unsigned int retry = 1; + switch( ecode ) { + case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */ + if( mysql_reconnect_type == 1 ) { + if( ++retry > mysql_reconnect_count ) { + ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry); + exit(EXIT_FAILURE); + } + } + break; + } +} +void Sql_inter_server_read(const char* cfgName, bool first) { + int i; + char line[1024], w1[1024], w2[1024]; + FILE* fp; + + fp = fopen(cfgName, "r"); + if(fp == NULL) { + if( first ) { + ShowFatalError("File not found: %s\n", cfgName); + exit(EXIT_FAILURE); + } else + ShowError("File not found: %s\n", cfgName); + return; + } + + while(fgets(line, sizeof(line), fp)) { + i = sscanf(line, "%[^:]: %[^\r\n]", w1, w2); + if(i != 2) + continue; + + if(!strcmpi(w1,"mysql_reconnect_type")) { + mysql_reconnect_type = atoi(w2); + switch( mysql_reconnect_type ) { + case 1: + case 2: + break; + default: + ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type); + mysql_reconnect_type = 1; + break; + } + } else if(!strcmpi(w1,"mysql_reconnect_count")) { + mysql_reconnect_count = atoi(w2); + if( mysql_reconnect_count < 1 ) + mysql_reconnect_count = 1; + } else if(!strcmpi(w1,"import")) + Sql_inter_server_read(w2,false); + } + fclose(fp); + + return; +} + +void Sql_Init(void) { + Sql_inter_server_read("conf/inter-server.conf",true); +} diff --git a/src/common/sql.h b/src/common/sql.h index 898e2c778..a9d8c6136 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -339,6 +339,7 @@ void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned lo /// Frees a SqlStmt returned by SqlStmt_Malloc. void SqlStmt_Free(SqlStmt* self); +void Sql_Init(void); #endif /* _COMMON_SQL_H_ */ -- cgit v1.2.3-70-g09d2 From d6d49c43b4f742c7aaffd0a102e6019c9adb7438 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 12:49:17 -0200 Subject: Fixed Bug #7046 Updated Safety Wall Renewal behavior, when taking damage higher than the health of the safety wall, excess damage will no longer be passed to the player. http://hercules.ws/board/tracker/issue-7046-safetywall-should-always-block-at-least-one-hit/ Signed-off-by: shennetsind --- src/map/battle.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/map/battle.c b/src/map/battle.c index 2198b25ec..4505b6a63 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -808,13 +808,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag * in RE, SW possesses a lifetime equal to 3 times the caster's health **/ #ifdef RENEWAL + d->dmg_lv = ATK_BLOCK; if ( ( group->val2 - damage) > 0 ) { group->val2 -= damage; - d->dmg_lv = ATK_BLOCK; - return 0; } else - damage -= group->val2; - skill_delunitgroup(group); + skill_delunitgroup(group); + return 0; #else if (--group->val2<=0) skill_delunitgroup(group); -- cgit v1.2.3-70-g09d2 From 5b378058f51019b4b0a07b89d9bf1c16add01281 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 13:10:26 -0200 Subject: Fixed Bug #7048 Items are no longer unequipped when a card within them is blacklisted (e.g. item_unequip.txt), instead the card's effect is nullified. http://hercules.ws/board/tracker/issue-7048-requestreport-regarding/ Signed-off-by: shennetsind --- src/map/clif.c | 1 + src/map/pc.c | 74 +++++++++++++++++++++++++--------------------------------- 2 files changed, 33 insertions(+), 42 deletions(-) diff --git a/src/map/clif.c b/src/map/clif.c index 3443c1ae3..e04941336 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9358,6 +9358,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) } map_iwall_get(sd); // Updates Walls Info on this Map to Client + status_calc_pc(sd, false);/* some conditions are map-dependent so we must recalculate */ sd->state.changemap = false; } diff --git a/src/map/pc.c b/src/map/pc.c index abfbbcc12..e26191717 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -700,24 +700,24 @@ int pc_setequipindex(struct map_session_data *sd) return 0; } +//static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) +//{ +// int i; +// struct item *item = &sd->status.inventory[eqindex]; +// struct item_data *data; +// +// //Crafted/made/hatched items. +// if (itemdb_isspecial(item->card[0])) +// return 1; +// +// /* scan for enchant armor gems */ +// if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 ) +// s = MAX_SLOTS - 1; +// +// ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag ); +// return( i < s ) ? 0 : 1; +//} -static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) -{ - int i; - struct item *item = &sd->status.inventory[eqindex]; - struct item_data *data; - - //Crafted/made/hatched items. - if (itemdb_isspecial(item->card[0])) - return 1; - - /* scan for enchant armor gems */ - if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 ) - s = MAX_SLOTS - 1; - - ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag ); - return( i < s ) ? 0 : 1; -} bool pc_isequipped(struct map_session_data *sd, int nameid) { @@ -860,18 +860,18 @@ int pc_isequip(struct map_session_data *sd,int n) #endif if(item->sex != 2 && sd->status.sex != item->sex) return 0; - if(!map_flag_vs(sd->bl.m) && ((item->flag.no_equip&1) || !pc_isAllowedCardOn(sd,item->slot,n,1))) + if(!map_flag_vs(sd->bl.m) && ((item->flag.no_equip&1))) return 0; - if(map[sd->bl.m].flag.pvp && ((item->flag.no_equip&2) || !pc_isAllowedCardOn(sd,item->slot,n,2))) + if(map[sd->bl.m].flag.pvp && ((item->flag.no_equip&2))) return 0; - if(map_flag_gvg(sd->bl.m) && ((item->flag.no_equip&4) || !pc_isAllowedCardOn(sd,item->slot,n,4))) + if(map_flag_gvg(sd->bl.m) && ((item->flag.no_equip&4))) return 0; - if(map[sd->bl.m].flag.battleground && ((item->flag.no_equip&8) || !pc_isAllowedCardOn(sd,item->slot,n,8))) + if(map[sd->bl.m].flag.battleground && ((item->flag.no_equip&8))) return 0; if(map[sd->bl.m].flag.restricted) { int flag =8*map[sd->bl.m].zone; - if (item->flag.no_equip&flag || !pc_isAllowedCardOn(sd,item->slot,n,flag)) + if (item->flag.no_equip&flag) return 0; } @@ -8618,33 +8618,27 @@ int pc_checkitem(struct map_session_data *sd) if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam) return 0; - if( battle_config.item_check ) - {// check for invalid(ated) items - for( i = 0; i < MAX_INVENTORY; i++ ) - { + if( battle_config.item_check ) { // check for invalid(ated) items + for( i = 0; i < MAX_INVENTORY; i++ ) { id = sd->status.inventory[i].nameid; - if( id && !itemdb_available(id) ) - { + if( id && !itemdb_available(id) ) { ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); } } - for( i = 0; i < MAX_CART; i++ ) - { + for( i = 0; i < MAX_CART; i++ ) { id = sd->status.cart[i].nameid; - if( id && !itemdb_available(id) ) - { + if( id && !itemdb_available(id) ) { ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id); pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); } } } - for( i = 0; i < MAX_INVENTORY; i++) - { + for( i = 0; i < MAX_INVENTORY; i++) { it = sd->inventory_data[i]; if( sd->status.inventory[i].nameid == 0 ) @@ -8653,31 +8647,27 @@ int pc_checkitem(struct map_session_data *sd) if( !sd->status.inventory[i].equip ) continue; - if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) - { + if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) { pc_unequipitem(sd, i, 2); calc_flag = 1; continue; } - if( it ) - { // check for forbiden items. + if( it ) { // check for forbiden items. int flag = (map[sd->bl.m].flag.restricted?(8*map[sd->bl.m].zone):0) | (!map_flag_vs(sd->bl.m)?1:0) | (map[sd->bl.m].flag.pvp?2:0) | (map_flag_gvg(sd->bl.m)?4:0) | (map[sd->bl.m].flag.battleground?8:0); - if( flag && (it->flag.no_equip&flag || !pc_isAllowedCardOn(sd,it->slot,i,flag)) ) - { + if( flag && (it->flag.no_equip&flag) ) { pc_unequipitem(sd, i, 2); calc_flag = 1; } } } - if( calc_flag && sd->state.active ) - { + if( calc_flag && sd->state.active ) { pc_checkallowskill(sd); status_calc_pc(sd,0); } -- cgit v1.2.3-70-g09d2 From 24d6aba263ff25724b8e6c9d6a228bba9fd6e756 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 13:12:57 -0200 Subject: Updating the headers of so-far modified files with outdated headers Signed-off-by: shennetsind --- src/common/core.c | 5 +++-- src/common/sql.c | 5 +++-- src/common/sql.h | 5 +++-- src/map/pc.c | 5 +++-- src/map/skill.c | 5 +++-- src/map/status.c | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/common/core.c b/src/common/core.c index bb536a255..b1714b7a5 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/mmo.h" #include "../common/showmsg.h" diff --git a/src/common/sql.c b/src/common/sql.c index 96346d68c..d00b51694 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/malloc.h" diff --git a/src/common/sql.h b/src/common/sql.h index a9d8c6136..5ac92665e 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #ifndef _COMMON_SQL_H_ #define _COMMON_SQL_H_ diff --git a/src/map/pc.c b/src/map/pc.c index e26191717..49b905c0d 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/core.h" // get_svn_revision() diff --git a/src/map/skill.c b/src/map/skill.c index 448f54406..f806c4ec5 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/timer.h" diff --git a/src/map/status.c b/src/map/status.c index 0379d05d2..8171f20ec 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules dev team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena dev team #include "../common/cbasetypes.h" #include "../common/timer.h" -- cgit v1.2.3-70-g09d2 From 7626b141f8e56b1739abce76f5a99cbbb2b4b159 Mon Sep 17 00:00:00 2001 From: malufett Date: Sun, 3 Feb 2013 23:21:36 +0800 Subject: Fixed Bug #7042 Fixed wrong 'if' condition in checking CELL_CHKNOPASS for the OFFICIAL_WALKPATH where clear path is considered to be limited to 14 cells it should only be with obstacles. --- src/map/unit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/map/unit.c b/src/map/unit.c index b7da5629f..afb7cf19f 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -325,7 +325,8 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) if( ud == NULL) return 0; #ifdef OFFICIAL_WALKPATH - if( path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS) // Check if there is an obstacle between + path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS); // Count walk path cells + if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between && wpd.path_len > 14 ) // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] return 0; #endif -- cgit v1.2.3-70-g09d2 From 0dbbe22a43c72737349b5907088bd5c90d5c3d3a Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 13:36:21 -0200 Subject: Partial Fix to Bug #7039 Fixed magical reflection behavior, user reflecting now visually casts the skill back at the caster, instead of caster casting it on itself. Waiting confirmation on the other part to fix. http://hercules.ws/board/tracker/issue-7039-frost-diver/ Signed-off-by: shennetsind --- src/map/skill.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/map/skill.c b/src/map/skill.c index f806c4ec5..9c07390f3 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2252,6 +2252,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds rmdamage = 1; bl = src; src = tbl; + dsrc = tbl; sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, bl); sc = status_get_sc(bl); -- cgit v1.2.3-70-g09d2 From 4671a3910c923b473d2f4efb50daf0fb343a67a9 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 14:58:02 -0200 Subject: Fixed Bug #7044 Monsters in stone curse pre-stone state no longer are able to attack. http://hercules.ws/board/tracker/issue-7044-stone-curse/ Signed-off-by: shennetsind --- src/map/status.c | 34 +++++++++++++++++----------------- src/map/unit.c | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/map/status.c b/src/map/status.c index 8171f20ec..ce792cd75 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1585,7 +1585,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if( sc && sc->count ) { - if (skill_id != RK_REFRESH && sc->opt1 >0 && (sc->opt1 != OPT1_CRYSTALIZE && src->type != BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc + if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc if (flag != 1) //Can't cast, casted stuff can't damage. return 0; if (!(skill_get_inf(skill_id)&INF_GROUND_SKILL)) @@ -1678,22 +1678,22 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin } } - if (sc && sc->option) - { - if (sc->option&OPTION_HIDE) - switch (skill_id) { //Usable skills while hiding. - case TF_HIDING: - case AS_GRIMTOOTH: - case RG_BACKSTAP: - case RG_RAID: - case NJ_SHADOWJUMP: - case NJ_KIRIKAGE: - case KO_YAMIKUMO: - break; - default: - //Non players can use all skills while hidden. - if (!skill_id || src->type == BL_PC) - return 0; + if (sc && sc->option) { + if (sc->option&OPTION_HIDE) { + switch (skill_id) { //Usable skills while hiding. + case TF_HIDING: + case AS_GRIMTOOTH: + case RG_BACKSTAP: + case RG_RAID: + case NJ_SHADOWJUMP: + case NJ_KIRIKAGE: + case KO_YAMIKUMO: + break; + default: + //Non players can use all skills while hidden. + if (!skill_id || src->type == BL_PC) + return 0; + } } if (sc->option&OPTION_CHASEWALK && skill_id != ST_CHASEWALK) return 0; diff --git a/src/map/unit.c b/src/map/unit.c index afb7cf19f..e901d3138 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -939,7 +939,7 @@ int unit_can_move(struct block_list *bl) { if( sc->data[SC_ANKLE] && ( battle_config.skill_trap_type || !unit_is_walking(bl) ) ) // Ankle only stops you after you're done moving return 0; - if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && (sc->opt1 != OPT1_CRYSTALIZE && bl->type != BL_MOB)) + if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && !(sc->opt1 == OPT1_CRYSTALIZE && bl->type == BL_MOB)) return 0; if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)) -- cgit v1.2.3-70-g09d2 From 453d6cebeb3cde5fc58ed95c574e3a325d59b289 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 17:11:14 -0200 Subject: First attempt at converting our readme to .md markdown format Signed-off-by: shennetsind --- README.md | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d7b996b5..da3077d15 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,161 @@ Hercules -======== \ No newline at end of file +======== +Table of Contents +--------- +* 1 What is Hercules? +* 2 Prerequisites +* 3 Installation +* 4 Troubleshooting +* 5 Helpful Links +* 6 More Documentation + +1. What is Hercules? +--------- +Hercules is a collaborative software development project revolving around the +creation of a robust massively multiplayer online role playing game (MMORPG) +server package. Written in C, the program is very versatile and provides NPCs, +warps and modifications. The project is jointly managed by a group of volunteers +located around the world as well as a tremendous community providing QA and +support. Hercules is a continuation of the original Athena project. + +2. Prerequisites +--------- +Before installing Hercules there are certain tools and applications you will need. +This differs between the varying operating systems available, so the following +is broken down into Windows and Linux prerequisites. + +* Windows + * TortoiseGIT ( http://code.google.com/p/tortoisegit/ ) + * MSysGit ( http://code.google.com/p/msysgit/downloads/list?can=2 ) + * MySQL ( http://www.mysql.com/downloads/mysql/ ) + * MySQL Workbench ( http://www.mysql.com/downloads/workbench/ ) + * MS Visual C++ ( http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express ) + +* Linux (names of packages may require specific version numbers on certain distributions) + * gcc + * make + * mysql + * mysql-devel + * mysql-server + * pcre-devel + * git + * zlib-devel + +3. Installation +--------- +This section is a very brief set of installation instructions. For more concise guides +relevant to your Operation System, please refer to the Wiki (links at the end of this file). + +* Windows + * Install prerequisites + * Create a folder to download Hercules into (e.g. C:\Hercules) + * Right click this folder and select "Git Clone". + * Paste the GIT URL into the box: https://github.com/HerculesWS/Hercules.git + * Open MySQL Workbench and create an instance to connect to your MySQL Server + * Create a database (hercules), a user (hercules), give permissions (GRANT SELECT,INSERT,UPDATE,DELETE) + and then login using the new user + * Use MySQL Workbench to run the .sql files in /sql-files/ on the new Hercules database + +* Linux + * (For CentOS) + * Step 1: yum install gcc make mysql mysql-devel mysql-server pcre-devel zlib-devel + * Step 2: rpm -Uvhhttp://repo.webtatic.com/yum/centos/5/latest.rpm + * Step 3: yum install --enablerepo=webtatic git-all + * Step 4: yum install --enablerepo=webtatic --disableexcludes=main git-all + (For Debian) Type: apt-get install git make gcc libmysqlclient-dev zlib1g-dev libpcre3-dev + * Type: mysql_secure_installation + * Start your MySQL server + * Setup a MySQL user: + + CREATE USER 'hercules'@'localhost' IDENTIFIED BY 'password'; + * Assign permissions: + + GRANT SELECT,INSERT,UPDATE,DELETE ON `hercules\_rag`.* TO 'hercules'@'localhost'; + * Type: git clone https://github.com/HerculesWS/Hercules.git ~/Hercules + * Insert SQL files: mysql --user=root -p hercules_rag < trunk/sql-files/main.sql (and others) + * Type: cd trunk && ./configure && make clean && make sql + * When you're ready, type: ./athena-start start + + + +4. Troubleshooting +--------- +If you're having problems with starting your server, the first thing you should +do is check what's happening on your consoles. More often that not, all support issues +can be solved simply by looking at the error messages given. + +Examples: + +* You get an error on your map-server_sql that looks something like this: + + [Error]: npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in + file 'npc/custom/jobmaster.txt', line '17'. Skipping line... + * w1=prontera,153,193,6 script + * w2=Job Master + * w3=123,{ + * w4= + + If you look at the error, it's telling you that you're missing (or have an extra) TAB. + This is easily fixed by looking at this part of the error: * w1=prontera,153,193,6 script + If there was a TAB where it's supposed to be, that line would have prontera,153,193,6 at w1 + and 'script' at w2. As there's a space instead of a TAB, the two sections are read as a + single parameter. + +* You have a default user/password warning similar to the following: + + [Warning]: Using the default user/password s1/p1 is NOT RECOMMENDED. + [Notice]: Please edit your 'login' table to create a proper inter-server user/pa + ssword (gender 'S') + [Notice]: and then edit your user/password in conf/map_athena.conf (or conf/impo + rt/map_conf.txt) + + Relax. This is just indicating that you're using the default username and password. To + fix this, check over the part in the installation instructions relevant to the `login` table. + +* Your Map Server says the following: + + [Error]: make_connection: connect failed (socket #2, error 10061: No connection + could be made because the target machine actively refused it. + )! + + If this shows up on the map server, it generally means that there is no Char Server available + to accept the connection. + +5. Helpful Links +--------- +The following list of links point to various help files within the GIT, articles or +pages on the Wiki or topics within the Hercules forum. + +* Hercules Forums + http://hercules.ws/board/ + +* GIT Repository URL: + https://github.com/HerculesWS/Hercules + +* Hercules IRC Channel + irc.rizon.net + Channel: #Hercules + + + +6. More Documentation +--------- +Hercules has a large collection of help files and sample NPC scripts located in /doc/ + +* Scripting + It is recommended to look through /doc/script_commands.txt for help, pointers or + even for ideas for your next NPC script. Most script commands have a usage example. + +* @commands + In-game, Game Masters have the ability to use Atcommands (@) to control players, + create items, spawn mobs, reload configuration files and even control the weather. + For an in-depth explanation, please see /doc/atcommands.txt + +* Permissions + The Hercules emulator has a permission system that enables certain groups of players + to perform certain actions, or have access to certain visual enhancements or in-game + activity. To see what permissions are available, they are detailed in /doc/permissions.txt + +There are more files in the /doc/ directory that will help you to create scripts or update the +mapcache, or even explain how the job system and item bonuses work. Before posting a topic asking +for help on the forums, we recommend that all users take the time to look over this directory. \ No newline at end of file -- cgit v1.2.3-70-g09d2 From cc8e005f27f3be0d7bcf8916cb40b2dd0e6a3ae1 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 18:31:21 -0200 Subject: item_noequip overhaul / Fixed Bug #7048 Items are no longer unequipped when disabled by item_noequip.txt, instead their effects are nullified -- however cards in them, unless also disabled, wont have its effect nullified. Consumables will be consumed even while disabled, unless you modify the new config item_restricted_consumption_type http://hercules.ws/board/tracker/issue-7048-requestreport-regarding-to-item-noequiptxt/ Signed-off-by: shennetsind --- conf/battle/items.conf | 5 +++++ src/map/battle.c | 1 + src/map/battle.h | 1 + src/map/pc.c | 55 +++++++++++++++----------------------------------- src/map/status.c | 14 +++++++++++++ 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/conf/battle/items.conf b/conf/battle/items.conf index 9bc2e37cc..343b4212e 100644 --- a/conf/battle/items.conf +++ b/conf/battle/items.conf @@ -75,3 +75,8 @@ gtb_sc_immunity: 50 // NOTE: Different cards that grant the same skill will both // always work independently of each other regardless of setting. autospell_stacking: no + +// Will disabled consumables (disabled by item_noequip.txt) be consumed when trying to use them? +// 1 (official): yes +// 0: no +item_restricted_consumption_type:1 \ No newline at end of file diff --git a/src/map/battle.c b/src/map/battle.c index 4505b6a63..0506f2fe9 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -5867,6 +5867,7 @@ static const struct _battle_data { * Hercules **/ { "skill_trap_type", &battle_config.skill_trap_type, 0, 0, 1, }, + { "item_restricted_consumption_type", &battle_config.item_restricted_consumption_type,1, 0, 1, }, }; #ifndef STATS_OPT_OUT /** diff --git a/src/map/battle.h b/src/map/battle.h index 0943b1aa3..c5ca19b90 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -484,6 +484,7 @@ extern struct Battle_Config int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95] int skill_trap_type; + int item_restricted_consumption_type; } battle_config; void do_init_battle(void); diff --git a/src/map/pc.c b/src/map/pc.c index 49b905c0d..6f608cd49 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -861,20 +861,6 @@ int pc_isequip(struct map_session_data *sd,int n) #endif if(item->sex != 2 && sd->status.sex != item->sex) return 0; - if(!map_flag_vs(sd->bl.m) && ((item->flag.no_equip&1))) - return 0; - if(map[sd->bl.m].flag.pvp && ((item->flag.no_equip&2))) - return 0; - if(map_flag_gvg(sd->bl.m) && ((item->flag.no_equip&4))) - return 0; - if(map[sd->bl.m].flag.battleground && ((item->flag.no_equip&8))) - return 0; - if(map[sd->bl.m].flag.restricted) - { - int flag =8*map[sd->bl.m].zone; - if (item->flag.no_equip&flag) - return 0; - } if (sd->sc.count) { @@ -4134,16 +4120,6 @@ int pc_isUseitem(struct map_session_data *sd,int n) else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS ) return 0; - //added item_noequip.txt items check by Maya&[Lupus] - if ( - (!map_flag_vs(sd->bl.m) && item->flag.no_equip&1) || // Normal - (map[sd->bl.m].flag.pvp && item->flag.no_equip&2) || // PVP - (map_flag_gvg(sd->bl.m) && item->flag.no_equip&4) || // GVG - (map[sd->bl.m].flag.battleground && item->flag.no_equip&8) || // Battleground - (map[sd->bl.m].flag.restricted && item->flag.no_equip&(8*map[sd->bl.m].zone)) // Zone restriction - ) - return 0; - //Gender check if(item->sex != 2 && sd->status.sex != item->sex) return 0; @@ -4222,7 +4198,7 @@ int pc_useitem(struct map_session_data *sd,int n) (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick, tick) > 0) ) return 0; - + /* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */ if( sd->inventory_data[n]->flag.delay_consume ) { if( nameid != ITEMID_REINS_OF_MOUNT && sd->sc.option&OPTION_MOUNTING ) @@ -4273,6 +4249,21 @@ int pc_useitem(struct map_session_data *sd,int n) } } + /* on restricted maps the item is consumed but the effect is not used */ + if ( + (!map_flag_vs(sd->bl.m) && sd->inventory_data[n]->flag.no_equip&1) || // Normal + (map[sd->bl.m].flag.pvp && sd->inventory_data[n]->flag.no_equip&2) || // PVP + (map_flag_gvg(sd->bl.m) && sd->inventory_data[n]->flag.no_equip&4) || // GVG + (map[sd->bl.m].flag.battleground && sd->inventory_data[n]->flag.no_equip&8) || // Battleground + (map[sd->bl.m].flag.restricted && sd->inventory_data[n]->flag.no_equip&(8*map[sd->bl.m].zone)) // Zone restriction + ) { + if( battle_config.item_restricted_consumption_type ) { + clif_useitemack(sd,n,sd->status.inventory[n].amount-1,true); + pc_delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); + } + return 0;/* regardless, effect is not run */ + } + sd->itemid = sd->status.inventory[n].nameid; sd->itemindex = n; if(sd->catch_target_class != -1) //Abort pet catching. @@ -8612,7 +8603,6 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { int pc_checkitem(struct map_session_data *sd) { int i,id,calc_flag = 0; - struct item_data *it=NULL; nullpo_ret(sd); @@ -8640,7 +8630,6 @@ int pc_checkitem(struct map_session_data *sd) } for( i = 0; i < MAX_INVENTORY; i++) { - it = sd->inventory_data[i]; if( sd->status.inventory[i].nameid == 0 ) continue; @@ -8654,18 +8643,6 @@ int pc_checkitem(struct map_session_data *sd) continue; } - if( it ) { // check for forbiden items. - int flag = - (map[sd->bl.m].flag.restricted?(8*map[sd->bl.m].zone):0) - | (!map_flag_vs(sd->bl.m)?1:0) - | (map[sd->bl.m].flag.pvp?2:0) - | (map_flag_gvg(sd->bl.m)?4:0) - | (map[sd->bl.m].flag.battleground?8:0); - if( flag && (it->flag.no_equip&flag) ) { - pc_unequipitem(sd, i, 2); - calc_flag = 1; - } - } } if( calc_flag && sd->state.active ) { diff --git a/src/map/status.c b/src/map/status.c index ce792cd75..7840a7a7f 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2443,6 +2443,20 @@ int status_calc_pc_(struct map_session_data* sd, bool first) if(!sd->inventory_data[index]) continue; + if(sd->inventory_data[index]->flag.no_equip) { // Items may be equipped, their effects however are nullified. + if(map[sd->bl.m].flag.restricted && sd->inventory_data[index]->flag.no_equip&(8*map[sd->bl.m].zone)) + continue; + if(!map_flag_vs(sd->bl.m) && sd->inventory_data[index]->flag.no_equip&1) + continue; + if(map[sd->bl.m].flag.pvp && sd->inventory_data[index]->flag.no_equip&2) + continue; + if(map_flag_gvg(sd->bl.m) && sd->inventory_data[index]->flag.no_equip&4) + continue; + if(map[sd->bl.m].flag.battleground && sd->inventory_data[index]->flag.no_equip&8) + continue; + } + + status->def += sd->inventory_data[index]->def; if(first && sd->inventory_data[index]->equip_script) -- cgit v1.2.3-70-g09d2 From 64d34dc87a5e93d371fc3b1eb5e905e5deb798d7 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 3 Feb 2013 20:03:02 -0200 Subject: Fixed Bug #7051 http://hercules.ws/board/tracker/issue-7051-warning-when-compiling/ Signed-off-by: shennetsind --- src/common/sql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sql.c b/src/common/sql.c index d00b51694..73c4181d9 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -19,7 +19,7 @@ void hercules_mysql_error_handler(unsigned int ecode); int mysql_reconnect_type; -int mysql_reconnect_count; +unsigned int mysql_reconnect_count; /// Sql handle struct Sql -- cgit v1.2.3-70-g09d2