Bug Fixes

* Fixed mouse cursor displaying incorrectly for PvP scenarios. Thanks to Napster. (bugreport:8605)
* Fixed summons getting stuck when master gets too far off screen or changes maps. (bugreport:9152)
* Added a battle_config 'spawn_direction' for keeping a  character's face direction when teleporting/changing maps/logging in. Default is always North (official). (bugreport:8754)
* Cast sensor mobs should always target the caster whenever any skill is used. (bugreport:8555)
* Added a packet version check to char_del_option based on client date. (bugreport:8521)
* Script command query_sql will now return -1 on an empty result or failed result. (bugreport:5937)
This commit is contained in:
aleos89 2014-08-16 16:15:50 -04:00
parent adabedba23
commit 60b0ed9c8b
9 changed files with 72 additions and 66 deletions

View File

@ -170,3 +170,7 @@ emblem_transparency_limit: 80
// So that will help client handling WPE - Maya Purple Hack stuff. // So that will help client handling WPE - Maya Purple Hack stuff.
// But it will screw 'the game animation display' while players in invisible state. // But it will screw 'the game animation display' while players in invisible state.
update_enemy_position: yes update_enemy_position: yes
// When a player teleports, changes maps, or logs in, will they face the direction they were facing before warped?
// Official: Disabled, players always face North.
spawn_direction: no

View File

@ -155,8 +155,9 @@ char_del_delay: 86400
// Restrict character deletion by email address or birthdate. // Restrict character deletion by email address or birthdate.
// This restricts players from changing the langtype and deleting characters. // This restricts players from changing the langtype and deleting characters.
// For birthdate, the client must be 20100803 or newer. // For birthdate, the client must be 20100803 or newer.
// Defaults based on client date.
// 1: Email address // 1: Email address
// 2: Birthdate (default) // 2: Birthdate
// 3: Email address or Birthdate // 3: Email address or Birthdate
char_del_option: 2 char_del_option: 2

View File

@ -7136,7 +7136,7 @@ Example:
*query_logsql("your MySQL query"{, <array variable>{, <array variable>{, ...}}}); *query_logsql("your MySQL query"{, <array variable>{, <array variable>{, ...}}});
Executes an SQL query. A 'select' query can fill array variables with up to 128 rows of values, Executes an SQL query. A 'select' query can fill array variables with up to 128 rows of values,
and will return the number of rows (i.e. array size). and will return the number of rows (i.e. array size) or -1 on failure/empty array.
Note that 'query_sql' runs on the main database while 'query_logsql' runs on the log database. Note that 'query_sql' runs on the main database while 'query_logsql' runs on the log database.

View File

@ -2488,7 +2488,11 @@ void char_set_defaults(){
charserv_config.char_config.char_per_account = 0; //Maximum chars per account (default unlimited) [Sirius] charserv_config.char_config.char_per_account = 0; //Maximum chars per account (default unlimited) [Sirius]
charserv_config.char_config.char_del_level = 0; //From which level u can delete character [Lupus] charserv_config.char_config.char_del_level = 0; //From which level u can delete character [Lupus]
charserv_config.char_config.char_del_delay = 86400; charserv_config.char_config.char_del_delay = 86400;
#if PACKETVER >= 20100803
charserv_config.char_config.char_del_option = 2; charserv_config.char_config.char_del_option = 2;
#else
charserv_config.char_config.char_del_option = 1;
#endif
// charserv_config.userid[24]; // charserv_config.userid[24];
// charserv_config.passwd[24]; // charserv_config.passwd[24];

View File

@ -7798,6 +7798,7 @@ static const struct _battle_data {
{ "mail_delay", &battle_config.mail_delay, 1000, 1000, INT_MAX, }, { "mail_delay", &battle_config.mail_delay, 1000, 1000, INT_MAX, },
{ "at_monsterignore", &battle_config.autotrade_monsterignore, 0, 0, 1, }, { "at_monsterignore", &battle_config.autotrade_monsterignore, 0, 0, 1, },
{ "idletime_option", &battle_config.idletime_option, 0x25, 1, INT_MAX, }, { "idletime_option", &battle_config.idletime_option, 0x25, 1, INT_MAX, },
{ "spawn_direction", &battle_config.spawn_direction, 0, 0, 1, },
}; };
#ifndef STATS_OPT_OUT #ifndef STATS_OPT_OUT
/** /**

View File

@ -566,6 +566,7 @@ extern struct Battle_Config
int mail_delay; int mail_delay;
int autotrade_monsterignore; int autotrade_monsterignore;
int idletime_option; int idletime_option;
int spawn_direction;
} battle_config; } battle_config;
void do_init_battle(void); void do_init_battle(void);

View File

@ -5726,26 +5726,26 @@ void clif_map_property(struct map_session_data* sd, enum map_property property)
void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { void clif_maptypeproperty2(struct block_list *bl,enum send_target t) {
#if PACKETVER >= 20130000 #if PACKETVER >= 20121010
uint8 buf[8]; unsigned char buf[8];
WBUFW(buf,0)=0x99b; //2 unsigned int NotifyProperty =
WBUFW(buf,2)=0x28; //2 ((map[bl->m].flag.pvp?1:0)<<0)| // PARTY - Show attack cursor on non-party members (PvP)
((map_flag_gvg(bl->m)?1:0)<<1)| // GUILD - Show attack cursor on non-guild members (GvG)
WBUFB(buf,4) = ((map_flag_vs(bl->m))?0x01:0); //tvt ? ((map_flag_gvg2(bl->m)?1:0)<<2)| // SIEGE - Show emblem over characters heads when in GvG (WoE castle)
WBUFB(buf,4) |= ((map_flag_gvg(bl->m))?0x02:0); //gvg ((map[bl->m].flag.nomineeffect || !map_flag_gvg2(bl->m)?0:1)<<3)| // USE_SIMPLE_EFFECT - Automatically enable /mineffect
WBUFB(buf,4) |= ((map_flag_gvg2(bl->m))?0x04:0); //siege ((map[bl->m].flag.nolockon?1:0)<<4)| // DISABLE_LOCKON - Unknown (By the name it might disable cursor lock-on)
WBUFB(buf,4) |= (map[bl->m].flag.nomineeffect || !map_flag_gvg2(bl->m))?0:0x08; //disable mine effect on nomineeffect map and enable it on gvgmap by default ((map[bl->m].flag.pvp?1:0)<<5)| // COUNT_PK - Show the PvP counter
WBUFB(buf,4) |= ((map[bl->m].flag.nolockon)?0x10:0); //nolockon 0x10 @FIXME what this do ((map[bl->m].flag.partylock?1:0)<<6)| // NO_PARTY_FORMATION - Prevents party creation/modification (Might be used for instance dungeons)
WBUFB(buf,4) |= ((map[bl->m].flag.pvp)?0x20:0); //countpk ((map[bl->m].flag.battleground?1:0)<<7)| // BATTLEFIELD - Unknown (Does something for battlegrounds areas)
WBUFB(buf,4) |= 0; //nopartyformation 0x40 ((map[bl->m].flag.noitemconsumption?1:0)<<8)| // DISABLE_COSTUMEITEM - Unknown - (Prevents wearing of costume items?)
WBUFB(buf,4) |= ((map[bl->m].flag.battleground)?0x80:0); //battleground ((map[bl->m].flag.nousecart?0:1)<<9)| // USECART - Allow opening cart inventory (Well force it to always allow it)
((map[bl->m].flag.nosumstarmiracle?0:1)<<10); // SUNMOONSTAR_MIRACLE - Unknown - (Guessing it blocks Star Gladiator's Miracle from activating)
WBUFB(buf,5) = ((map[bl->m].flag.noitemconsumption)?0x01:0); //noitemconsumption //(1<<11); // Unused bits. 1 - 10 is 0x1 length and 11 is 0x15 length. May be used for future settings.
WBUFB(buf,5) |= ((map[bl->m].flag.nousecart)?0:0x02); // usecart
WBUFB(buf,5) |= ((map[bl->m].flag.nosumstarmiracle)?0:0x04); //summonstarmiracle
// WBUFB(buf,5) |= RBUFB(buf,5)&0xf8; //sparebit[0-4]
WBUFW(buf,0)=0x99b;
WBUFW(buf,2)=0x28; // Type - What is it asking for? MAPPROPERTY? MAPTYPE? I don't know. Do we even need it? [Rytech]
WBUFL(buf,4)=NotifyProperty;
WBUFW(buf,6) = 0; // sparebit [5-15], + extra[4] WBUFW(buf,6) = 0; // sparebit [5-15], + extra[4]
clif_send(buf,packet_len(0x99b),bl,t); clif_send(buf,packet_len(0x99b),bl,t);
@ -9839,6 +9839,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif_clearunit_area(&sd->bl, CLR_DEAD); clif_clearunit_area(&sd->bl, CLR_DEAD);
else { else {
skill_usave_trigger(sd); skill_usave_trigger(sd);
if (battle_config.spawn_direction)
clif_changed_dir(&sd->bl, SELF); clif_changed_dir(&sd->bl, SELF);
} }

View File

@ -15344,13 +15344,13 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle)
if( SQL_ERROR == Sql_QueryStr(handle, query) ) { if( SQL_ERROR == Sql_QueryStr(handle, query) ) {
Sql_ShowDebug(handle); Sql_ShowDebug(handle);
script_pushint(st, 0); script_pushint(st, -1);
return 1; return 1;
} }
if( Sql_NumRows(handle) == 0 ) { // No data received if( Sql_NumRows(handle) == 0 ) { // No data received
Sql_FreeResult(handle); Sql_FreeResult(handle);
script_pushint(st, 0); script_pushint(st, -1);
return 0; return 0;
} }

View File

@ -206,6 +206,7 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
{ {
TBL_PC *msd = NULL; TBL_PC *msd = NULL;
int max_dist = 0; int max_dist = 0;
switch(sbl->type) { switch(sbl->type) {
case BL_HOM: case BL_HOM:
case BL_ELEM: case BL_ELEM:
@ -319,17 +320,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
return 0; return 0;
} else } else
sd->areanpc_id=0; sd->areanpc_id=0;
/* WIP disable [Lighta], currently unsuported
* this was meant to start the timer if the player move but not his slave...
if(sd->md) unit_check_start_teleport_timer(&sd->md->bl);
if(sd->ed) unit_check_start_teleport_timer(&sd->ed->bl);
if(sd->hd) unit_check_start_teleport_timer(&sd->hd->bl);
if(sd->pd) unit_check_start_teleport_timer(&sd->pd->bl);
*/
pc_cell_basilica(sd); pc_cell_basilica(sd);
} }
break; break;
case BL_MOB: { case BL_MOB:
if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) { if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
if( npc_touch_areanpc2(md) ) if( npc_touch_areanpc2(md) )
return 0; // Warped return 0; // Warped
@ -349,13 +343,6 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
// Resend walk packet for proper Self Destruction display. // Resend walk packet for proper Self Destruction display.
clif_move(ud); clif_move(ud);
} }
}
break;
case BL_HOM:
case BL_ELEM:
case BL_PET:
case BL_MER:
unit_check_start_teleport_timer(bl);
break; break;
} }
@ -469,6 +456,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
struct unit_data* ud = NULL; struct unit_data* ud = NULL;
struct status_change* sc = NULL; struct status_change* sc = NULL;
struct walkpath_data wpd; struct walkpath_data wpd;
TBL_PC *sd = NULL;
nullpo_ret(bl); nullpo_ret(bl);
@ -476,6 +464,9 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
if (ud == NULL) return 0; if (ud == NULL) return 0;
if (bl->type == BL_PC)
sd = BL_CAST(BL_PC, bl);
path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS); // Count walk path cells path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS); // Count walk path cells
#ifdef OFFICIAL_WALKPATH #ifdef OFFICIAL_WALKPATH
if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between
@ -520,6 +511,12 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
ud->attacktimer = INVALID_TIMER; ud->attacktimer = INVALID_TIMER;
} }
// Start timer to recall summon
if (sd && sd->md) unit_check_start_teleport_timer(&sd->md->bl);
if (sd && sd->ed) unit_check_start_teleport_timer(&sd->ed->bl);
if (sd && sd->hd) unit_check_start_teleport_timer(&sd->hd->bl);
if (sd && sd->pd) unit_check_start_teleport_timer(&sd->pd->bl);
return unit_walktoxy_sub(bl); return unit_walktoxy_sub(bl);
} }
@ -1544,13 +1541,11 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
unit_stop_walking(src,1);// Even though this is not how official works but this will do the trick. bugreport:6829 unit_stop_walking(src,1);// Even though this is not how official works but this will do the trick. bugreport:6829
// In official this is triggered even if no cast time. // In official this is triggered even if no cast time.
clif_skillcasting(src, src->id, target_id, 0,0, skill_id, skill_get_ele(skill_id, skill_lv), casttime); clif_skillcasting(src, src->id, target_id, 0,0, skill_id, skill_get_ele(skill_id, skill_lv), casttime);
if( casttime > 0 || combo ) {
if (sd && target->type == BL_MOB) { if (sd && target->type == BL_MOB) {
TBL_MOB *md = (TBL_MOB*)target; TBL_MOB *md = (TBL_MOB*)target;
mobskill_event(md, src, tick, -1); // Cast targetted skill event. mobskill_event(md, src, tick, -1); // Cast targetted skill event.
if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && battle_check_target(target, src, BCT_ENEMY) > 0) {
battle_check_target(target, src, BCT_ENEMY) > 0)
{
switch (md->state.skillstate) { switch (md->state.skillstate) {
case MSS_RUSH: case MSS_RUSH:
case MSS_FOLLOW: case MSS_FOLLOW:
@ -1571,7 +1566,6 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
} }
} }
} }
}
if( casttime <= 0 ) if( casttime <= 0 )
ud->state.skillcastcancel = 0; ud->state.skillcastcancel = 0;