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.
// But it will screw 'the game animation display' while players in invisible state.
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.
// This restricts players from changing the langtype and deleting characters.
// For birthdate, the client must be 20100803 or newer.
// Defaults based on client date.
// 1: Email address
// 2: Birthdate (default)
// 2: Birthdate
// 3: Email address or Birthdate
char_del_option: 2

View File

@ -7136,7 +7136,7 @@ Example:
*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,
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.

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_del_level = 0; //From which level u can delete character [Lupus]
charserv_config.char_config.char_del_delay = 86400;
#if PACKETVER >= 20100803
charserv_config.char_config.char_del_option = 2;
#else
charserv_config.char_config.char_del_option = 1;
#endif
// charserv_config.userid[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, },
{ "at_monsterignore", &battle_config.autotrade_monsterignore, 0, 0, 1, },
{ "idletime_option", &battle_config.idletime_option, 0x25, 1, INT_MAX, },
{ "spawn_direction", &battle_config.spawn_direction, 0, 0, 1, },
};
#ifndef STATS_OPT_OUT
/**

View File

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

View File

@ -5726,27 +5726,27 @@ void clif_map_property(struct map_session_data* sd, enum map_property property)
void clif_maptypeproperty2(struct block_list *bl,enum send_target t) {
#if PACKETVER >= 20130000
uint8 buf[8];
#if PACKETVER >= 20121010
unsigned char buf[8];
WBUFW(buf,0)=0x99b; //2
WBUFW(buf,2)=0x28; //2
unsigned int NotifyProperty =
((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)
((map_flag_gvg2(bl->m)?1:0)<<2)| // SIEGE - Show emblem over characters heads when in GvG (WoE castle)
((map[bl->m].flag.nomineeffect || !map_flag_gvg2(bl->m)?0:1)<<3)| // USE_SIMPLE_EFFECT - Automatically enable /mineffect
((map[bl->m].flag.nolockon?1:0)<<4)| // DISABLE_LOCKON - Unknown (By the name it might disable cursor lock-on)
((map[bl->m].flag.pvp?1:0)<<5)| // COUNT_PK - Show the PvP counter
((map[bl->m].flag.partylock?1:0)<<6)| // NO_PARTY_FORMATION - Prevents party creation/modification (Might be used for instance dungeons)
((map[bl->m].flag.battleground?1:0)<<7)| // BATTLEFIELD - Unknown (Does something for battlegrounds areas)
((map[bl->m].flag.noitemconsumption?1:0)<<8)| // DISABLE_COSTUMEITEM - Unknown - (Prevents wearing of costume items?)
((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)
//(1<<11); // Unused bits. 1 - 10 is 0x1 length and 11 is 0x15 length. May be used for future settings.
WBUFB(buf,4) = ((map_flag_vs(bl->m))?0x01:0); //tvt ?
WBUFB(buf,4) |= ((map_flag_gvg(bl->m))?0x02:0); //gvg
WBUFB(buf,4) |= ((map_flag_gvg2(bl->m))?0x04:0); //siege
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
WBUFB(buf,4) |= ((map[bl->m].flag.nolockon)?0x10:0); //nolockon 0x10 @FIXME what this do
WBUFB(buf,4) |= ((map[bl->m].flag.pvp)?0x20:0); //countpk
WBUFB(buf,4) |= 0; //nopartyformation 0x40
WBUFB(buf,4) |= ((map[bl->m].flag.battleground)?0x80:0); //battleground
WBUFB(buf,5) = ((map[bl->m].flag.noitemconsumption)?0x01:0); //noitemconsumption
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,6) = 0; //sparebit [5-15], + extra[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]
clif_send(buf,packet_len(0x99b),bl,t);
#endif
@ -9839,7 +9839,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif_clearunit_area(&sd->bl, CLR_DEAD);
else {
skill_usave_trigger(sd);
clif_changed_dir(&sd->bl, SELF);
if (battle_config.spawn_direction)
clif_changed_dir(&sd->bl, SELF);
}
// Trigger skill effects if you appear standing on them

View File

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

View File

@ -204,8 +204,9 @@ int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
*/
int unit_check_start_teleport_timer(struct block_list *sbl)
{
TBL_PC *msd=NULL;
TBL_PC *msd = NULL;
int max_dist = 0;
switch(sbl->type) {
case BL_HOM:
case BL_ELEM:
@ -216,7 +217,7 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
default:
return 0;
}
switch(sbl->type) {
case BL_HOM: max_dist = AREA_SIZE; break;
case BL_ELEM: max_dist = MAX_ELEDISTANCE; break;
@ -319,17 +320,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
return 0;
} else
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);
}
break;
case BL_MOB: {
case BL_MOB:
if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
if( npc_touch_areanpc2(md) )
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.
clif_move(ud);
}
}
break;
case BL_HOM:
case BL_ELEM:
case BL_PET:
case BL_MER:
unit_check_start_teleport_timer(bl);
break;
}
@ -469,12 +456,16 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
struct unit_data* ud = NULL;
struct status_change* sc = NULL;
struct walkpath_data wpd;
TBL_PC *sd = NULL;
nullpo_ret(bl);
ud = unit_bl2ud(bl);
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
#ifdef OFFICIAL_WALKPATH
@ -519,7 +510,13 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
delete_timer( ud->attacktimer, unit_attack_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);
}
@ -1544,31 +1541,28 @@ 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
// 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);
if( casttime > 0 || combo ) {
if (sd && target->type == BL_MOB) {
TBL_MOB *md = (TBL_MOB*)target;
mobskill_event(md, src, tick, -1); // Cast targetted skill event.
if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) &&
battle_check_target(target, src, BCT_ENEMY) > 0)
{
switch (md->state.skillstate) {
case MSS_RUSH:
case MSS_FOLLOW:
if (!(tstatus->mode&MD_CASTSENSOR_CHASE))
break;
md->target_id = src->id;
md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0;
md->min_chase = md->db->range3;
if (sd && target->type == BL_MOB) {
TBL_MOB *md = (TBL_MOB*)target;
mobskill_event(md, src, tick, -1); // Cast targetted skill event.
if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && battle_check_target(target, src, BCT_ENEMY) > 0) {
switch (md->state.skillstate) {
case MSS_RUSH:
case MSS_FOLLOW:
if (!(tstatus->mode&MD_CASTSENSOR_CHASE))
break;
case MSS_IDLE:
case MSS_WALK:
if (!(tstatus->mode&MD_CASTSENSOR_IDLE))
break;
md->target_id = src->id;
md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0;
md->min_chase = md->db->range3;
md->target_id = src->id;
md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0;
md->min_chase = md->db->range3;
break;
case MSS_IDLE:
case MSS_WALK:
if (!(tstatus->mode&MD_CASTSENSOR_IDLE))
break;
}
md->target_id = src->id;
md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0;
md->min_chase = md->db->range3;
break;
}
}
}