-Update Char_Client packet 2013+, thx (Yommy, Shaktoh)

--change connection sequence for 82d+9a0+20d => 9a1 => 99d
-Merge some Hercules stuffs:
--upd char (default map check, 0x99d HC)
--CreateParty enforced chk
--mapindex_db for name lookup
-Add max packet_len check on chrif init for mmo_charstatus. 
-Upd @mapinfo, add missing mapflag info.
-Expand teleport_timer for pet,homon,ele (Daegaladh)
-Make homon,ele inherit master speed (Daegaladh)
-Fix frostnova status chance and driven fail msg. (Daegaladh)
-Cleanup, replace hardcoded ai value with enum eq, change pet.msd to pet.master to harmonize with other blchar.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17332 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
glighta 2013-05-23 12:44:12 +00:00
parent 54f41e69bc
commit 38f9f0c208
30 changed files with 484 additions and 366 deletions

View File

@ -451,9 +451,29 @@
463: Message configuration has been reloaded.
464: ---- Available languages:
480: ----- Players in Map -----
481: Player '%s' (session #%d) | Location: %d,%d
482: ----- NPCs in Map -----
483: ----- Chats in Map -----
484: Chat: %s | Player: %s | Location: %d %d
485: Users: %d/%d | Password: %s | Public: %s
486: Yes
487: No
488: Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
489: NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
490: NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
491: North
492: North West
493: West
494: South West
495: South
496: South East
497: East
498: North East
499: Unknown
// Messages of others (not for GM commands)
// ----------------------------------------
//500 free
501: Your account time limit is: %d-%m-%Y %H:%M:%S.
502: Day Mode is activated
@ -848,7 +868,7 @@
1042: Town Map
1043: Autotrade Enabled
1044: Autotrade Disabled
1045: Battlegrounds ON
1045: Battlegrounds ON type=%d
1046: PvP Flags:
1047: Pvp ON |
1048: NoGuild |
@ -901,27 +921,15 @@
1095: NoMVPLoot |
1096: PartyLock |
1097: GuildLock |
1098: ----- Players in Map -----
1099: Player '%s' (session #%d) | Location: %d,%d
1100: ----- NPCs in Map -----
1101: North
1102: North West
1103: West
1104: South West
1105: South
1106: South East
1107: East
1108: North East
1109: North
1110: Unknown
1111: NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
1112: NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
1113: ----- Chats in Map -----
1114: Chat: %s | Player: %s | Location: %d %d
1115: Users: %d/%d | Password: %s | Public: %s
1116: Yes
1117: No
1118: Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
1098: Loadevent |
1099: Src4instance |
1100: Chmautojoin |
1101: nousecart |
1102: noitemconsumption |
1103: nosumstarmiracle |
1104: nomineeffect |
1105: nolockon |
1106: Restricted zone=%d
// @mount
1119: You have mounted your Dragon.

View File

@ -1104,7 +1104,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_SHORT, &p.head_top, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p.rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL)
@ -1223,7 +1223,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL)
@ -1242,6 +1242,18 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
p->last_point.map = mapindex_name2id(last_map);
p->save_point.map = mapindex_name2id(save_map);
if( p->last_point.map == 0 ) {
p->last_point.map = mapindex_name2id(MAP_DEFAULT);
p->last_point.x = MAP_DEFAULT_X;
p->last_point.y = MAP_DEFAULT_Y;
}
if( p->save_point.map == 0 ) {
p->save_point.map = mapindex_name2id(MAP_DEFAULT);
p->save_point.x = MAP_DEFAULT_X;
p->save_point.y = MAP_DEFAULT_Y;
}
strcat(t_msg, " status");
if (!load_everything) // For quick selection of data when displaying the char menu
@ -1727,9 +1739,9 @@ int delete_char_sql(int char_id)
if( hom_id )
mapif_homunculus_delete(hom_id);
/* remove elemental */
if (elemental_id)
mapif_elemental_delete(elemental_id);
/* remove elemental */
if (elemental_id)
mapif_elemental_delete(elemental_id);
/* remove mercenary data */
mercenary_owner_delete(char_id);
@ -1907,16 +1919,46 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
return 106+offset;
}
// Tell client how many pages, kRO sends 17 (Yommy)
void char_charlist_notify( int fd, struct char_session_data* sd ){
WFIFOHEAD(fd, 6);
WFIFOW(fd, 0) = 0x9a0;
// pages to req / send them all in 1 until mmo_chars_fromsql can split them up
WFIFOL(fd, 2) = 1; //int TotalCnt
WFIFOSET(fd,6);
}
void char_block_character( int fd, struct char_session_data* sd ){
WFIFOHEAD(fd, 4);
WFIFOW(fd, 0) = 0x20d;
WFIFOW(fd, 2) = 4; //packet len
WFIFOSET(fd,4);
}
/* Made Possible by Yommy~! <3 */
void mmo_char_send099d(int fd, struct char_session_data *sd) {
WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
WFIFOW(fd,0) = 0x99d;
WFIFOW(fd,2) = mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4;
WFIFOSET(fd,WFIFOW(fd,2));
}
//struct PACKET_CH_CHARLIST_REQ { 0x0 short PacketType}
void char_parse_req_charlist(int fd, struct char_session_data* sd){
mmo_char_send099d(fd,sd);
}
//----------------------------------------
// Function to send characters to a player
//----------------------------------------
int mmo_char_send006b(int fd, struct char_session_data* sd)
{
int mmo_char_send006b(int fd, struct char_session_data* sd){
int j, offset = 0;
#if PACKETVER >= 20100413
offset += 3;
#endif
if (save_log)
ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
@ -1942,7 +1984,6 @@ int mmo_char_send006b(int fd, struct char_session_data* sd)
void mmo_char_send082d(int fd, struct char_session_data* sd) {
if (save_log)
ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
WFIFOHEAD(fd,29);
WFIFOW(fd,0) = 0x82d;
WFIFOW(fd,2) = 29;
@ -1953,7 +1994,16 @@ void mmo_char_send082d(int fd, struct char_session_data* sd) {
WFIFOB(fd,8) = sd->char_slots;
memset(WFIFOP(fd,9), 0, 20); // unused bytes
WFIFOSET(fd,29);
}
void mmo_char_send(int fd, struct char_session_data* sd){
#if PACKETVER >= 20130000
mmo_char_send082d(fd,sd);
char_charlist_notify(fd,sd);
char_block_character(fd,sd);
#else
mmo_char_send006b(fd,sd);
#endif
}
int char_married(int pl1, int pl2)
@ -2258,11 +2308,7 @@ int parse_fromlogin(int fd) {
WFIFOSET(i,3);
} else {
// send characters to player
#if PACKETVER >= 20130000
mmo_char_send082d(i, sd);
#else
mmo_char_send006b(i, sd);
#endif
mmo_char_send(i, sd);
#if PACKETVER >= 20110309
if( pincode_enabled ){
// PIN code system enabled
@ -4254,50 +4300,47 @@ int parse_char(int fd)
case 0x2af8:
if (RFIFOREST(fd) < 60)
return 0;
{
char* l_user = (char*)RFIFOP(fd,2);
char* l_pass = (char*)RFIFOP(fd,26);
l_user[23] = '\0';
l_pass[23] = '\0';
ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
if( runflag != CHARSERVER_ST_RUNNING ||
i == ARRAYLENGTH(server) ||
strcmp(l_user, userid) != 0 ||
strcmp(l_pass, passwd) != 0 )
{
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 3;
WFIFOSET(fd,3);
} else {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
else {
char* l_user = (char*)RFIFOP(fd,2);
char* l_pass = (char*)RFIFOP(fd,26);
l_user[23] = '\0';
l_pass[23] = '\0';
ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
if( runflag != CHARSERVER_ST_RUNNING ||
i == ARRAYLENGTH(server) ||
strcmp(l_user, userid) != 0 ||
strcmp(l_pass, passwd) != 0 )
{
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 3;
WFIFOSET(fd,3);
} else {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
server[i].fd = fd;
server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0;
memset(server[i].map, 0, sizeof(server[i].map));
session[fd]->func_parse = parse_frommap;
session[fd]->flag.server = 1;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
char_mapif_init(fd);
server[i].fd = fd;
server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0;
memset(server[i].map, 0, sizeof(server[i].map));
session[fd]->func_parse = parse_frommap;
session[fd]->flag.server = 1;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
char_mapif_init(fd);
}
RFIFOSKIP(fd,60);
}
RFIFOSKIP(fd,60);
}
return 0; // avoid processing of followup packets here
return 0; // avoid processing of followup packets here
// checks the entered pin
case 0x8b8:
if( RFIFOREST(fd) < 10 )
return 0;
if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
pincode_check( fd, sd );
RFIFOSKIP(fd,10);
break;
@ -4305,7 +4348,6 @@ int parse_char(int fd)
case 0x8c5:
if( RFIFOREST(fd) < 6 )
return 0;
if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){
if( strlen( sd->pincode ) <= 0 ){
pincode_sendstate( fd, sd, PINCODE_NEW );
@ -4313,7 +4355,6 @@ int parse_char(int fd)
pincode_sendstate( fd, sd, PINCODE_ASK );
}
}
RFIFOSKIP(fd,6);
break;
@ -4332,10 +4373,8 @@ int parse_char(int fd)
case 0x8ba:
if( RFIFOREST(fd) < 10 )
return 0;
if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
pincode_setnew( fd, sd );
RFIFOSKIP(fd,10);
break;
@ -4345,10 +4384,17 @@ int parse_char(int fd)
return 0;
moveCharSlot( fd, sd, RFIFOW(fd, 2), RFIFOW(fd, 4) );
mmo_char_send(fd, sd);
RFIFOSKIP(fd,8);
break;
case 0x9a1:
if( RFIFOREST(fd) < 2 )
return 0;
char_parse_req_charlist(fd,sd);
RFIFOSKIP(fd,2);
break;
// unknown packet received
default:
ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));
@ -4720,11 +4766,7 @@ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, un
// We successfully moved the char - time to notify the client
moveCharSlotReply( fd, sd, from, 0 );
#if PACKETVER >= 20130000
mmo_char_send082d(fd, sd);
#else
mmo_char_send006b( fd, sd );
#endif
mmo_char_send(fd, sd);
}
// reason

View File

@ -476,6 +476,11 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) == NULL) {
if( name[i] == '"' ) { /* client-special-char */
normalize_name(name,"\"");
mapif_parse_CreateParty(fd,name,item,item2,leader);
return 0;
}
mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}

View File

@ -177,6 +177,7 @@ typedef unsigned long int ppuint32;
// integer with exact processor width (and best speed)
//////////////////////////////
#include <stddef.h> // size_t
//#include <stdbool.h> //boolean
#if defined(WIN32) && !defined(MINGW) // does not have a signed size_t
//////////////////////////////

View File

@ -55,8 +55,7 @@ char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef POSIX
#define compat_signal(signo, func) signal(signo, func)
#else
sigfunc *compat_signal(int signo, sigfunc *func)
{
sigfunc *compat_signal(int signo, sigfunc *func) {
struct sigaction sact, oact;
sact.sa_handler = func;
@ -77,10 +76,8 @@ sigfunc *compat_signal(int signo, sigfunc *func)
* CORE : Console events for Windows
*--------------------------------------*/
#ifdef _WIN32
static BOOL WINAPI console_handler(DWORD c_event)
{
switch(c_event)
{
static BOOL WINAPI console_handler(DWORD c_event) {
switch(c_event) {
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
@ -95,8 +92,7 @@ static BOOL WINAPI console_handler(DWORD c_event)
return TRUE;
}
static void cevents_init()
{
static void cevents_init() {
if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE)
ShowWarning ("Unable to install the console handler!\n");
}
@ -105,8 +101,7 @@ static void cevents_init()
/*======================================
* CORE : Signal Sub Function
*--------------------------------------*/
static void sig_proc(int sn)
{
static void sig_proc(int sn) {
static int is_called = 0;
switch (sn) {
@ -139,8 +134,7 @@ static void sig_proc(int sn)
}
}
void signals_init (void)
{
void signals_init (void) {
compat_signal(SIGTERM, sig_proc);
compat_signal(SIGINT, sig_proc);
#ifndef _DEBUG // need unhandled exceptions to debug on Windows
@ -158,13 +152,11 @@ void signals_init (void)
#endif
#ifdef SVNVERSION
const char *get_svn_revision(void)
{
const char *get_svn_revision(void) {
return EXPAND_AND_QUOTE(SVNVERSION);
}
#else// not SVNVERSION
const char* get_svn_revision(void)
{
const char* get_svn_revision(void) {
static char svn_version_buffer[16] = "";
FILE *fp;
@ -199,12 +191,10 @@ const char* get_svn_revision(void)
fclose(fp);
// parse buffer
for( i = prefix_len + 1; i + postfix_len <= len; ++i )
{
for( i = prefix_len + 1; i + postfix_len <= len; ++i ) {
if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 )
continue; // postfix missmatch
for( j = i; j > 0; --j )
{// skip digits
for( j = i; j > 0; --j ) {// skip digits
if( !ISDIGIT(buffer[j - 1]) )
break;
}

View File

@ -5,12 +5,14 @@
#include "../common/showmsg.h"
#include "../common/malloc.h"
#include "../common/strlib.h"
#include "../common/db.h"
#include "mapindex.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
DBMap *mapindex_db;
struct _indexes {
char name[MAP_NAME_LENGTH]; //Stores map name
} indexes[MAX_MAPINDEX];
@ -23,8 +25,7 @@ char mapindex_cfgfile[80] = "db/map_index.txt";
/// Retrieves the map name from 'string' (removing .gat extension if present).
/// Result gets placed either into 'buf' or in a static local buffer.
const char* mapindex_getmapname(const char* string, char* output)
{
const char* mapindex_getmapname(const char* string, char* output) {
static char buf[MAP_NAME_LENGTH];
char* dest = (output != NULL) ? output : buf;
@ -45,8 +46,7 @@ const char* mapindex_getmapname(const char* string, char* output)
/// Retrieves the map name from 'string' (adding .gat extension if not already present).
/// Result gets placed either into 'buf' or in a static local buffer.
const char* mapindex_getmapname_ext(const char* string, char* output)
{
const char* mapindex_getmapname_ext(const char* string, char* output) {
static char buf[MAP_NAME_LENGTH_EXT];
char* dest = (output != NULL) ? output : buf;
@ -75,13 +75,11 @@ const char* mapindex_getmapname_ext(const char* string, char* output)
/// Adds a map to the specified index
/// Returns 1 if successful, 0 oherwise
int mapindex_addmap(int index, const char* name)
{
int mapindex_addmap(int index, const char* name) {
char map_name[MAP_NAME_LENGTH];
if (index == -1){
for (index = 1; index < max_index; index++)
{
for (index = 1; index < max_index; index++) {
//if (strcmp(indexes[index].name,"#CLEARED#")==0)
if (indexes[index].name[0] == '\0')
break;
@ -105,29 +103,27 @@ int mapindex_addmap(int index, const char* name)
return 0;
}
if (mapindex_exists(index))
if (mapindex_exists(index)) {
ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name);
strdb_remove(mapindex_db, indexes[index].name);
}
safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
strdb_iput(mapindex_db, map_name, index);
if (max_index <= index)
max_index = index+1;
return index;
}
unsigned short mapindex_name2id(const char* name)
{
//TODO: Perhaps use a db to speed this up? [Skotlex]
unsigned short mapindex_name2id(const char* name) {
int i;
char map_name[MAP_NAME_LENGTH];
mapindex_getmapname(name, map_name);
for (i = 1; i < max_index; i++)
{
if (strcmpi(indexes[i].name,map_name)==0)
return i;
}
if( (i = strdb_iget(mapindex_db, map_name)) )
return i;
ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name);
return 0;
}
@ -141,27 +137,24 @@ const char* mapindex_id2name(unsigned short id)
return indexes[id].name;
}
void mapindex_init(void)
{
void mapindex_init(void) {
FILE *fp;
char line[1024];
int last_index = -1;
int index;
char map_name[1024];
char map_name[MAP_NAME_LENGTH];
memset (&indexes, 0, sizeof (indexes));
fp=fopen(mapindex_cfgfile,"r");
if(fp==NULL){
if( ( fp = fopen(mapindex_cfgfile,"r") ) == NULL ){
ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile);
exit(EXIT_FAILURE); //Server can't really run without this file.
}
while(fgets(line, sizeof(line), fp))
{
memset (&indexes, 0, sizeof (indexes));
mapindex_db = strdb_alloc(DB_OPT_DUP_KEY, MAP_NAME_LENGTH);
while(fgets(line, sizeof(line), fp)) {
if(line[0] == '/' && line[1] == '/')
continue;
switch (sscanf(line, "%1023s\t%d", map_name, &index))
{
switch (sscanf(line, "%12s\t%d", map_name, &index)) {
case 1: //Map with no ID given, auto-assign
index = last_index+1;
case 2: //Map with ID given
@ -173,6 +166,10 @@ void mapindex_init(void)
last_index = index;
}
fclose(fp);
if( !strdb_iget(mapindex_db, MAP_DEFAULT) ) {
ShowError("mapindex_init: MAP_DEFAULT '%s' not found in cache! update mapindex.h MAP_DEFAULT var!!!\n",MAP_DEFAULT);
}
}
int mapindex_removemap(int index){
@ -180,6 +177,6 @@ int mapindex_removemap(int index){
return 0;
}
void mapindex_final(void)
{
void mapindex_final(void) {
db_destroy(mapindex_db);
}

View File

@ -47,6 +47,11 @@ extern char mapindex_cfgfile[80];
#define MAP_MALAYA "malaya"
#define MAP_ECLAGE "eclage"
// When a map index search fails, return results from what map? default:prontera
#define MAP_DEFAULT MAP_PRONTERA
#define MAP_DEFAULT_X 150
#define MAP_DEFAULT_Y 150
const char* mapindex_getmapname(const char* string, char* output);
const char* mapindex_getmapname_ext(const char* string, char* output);
unsigned short mapindex_name2id(const char*);

View File

@ -1163,7 +1163,7 @@ void socket_final(void)
if(session[i])
do_close(i);
// session[0] <20>̃_<CC83>~<7E>[<5B>f<EFBFBD>[<5B>^<5E><><EFBFBD>
// session[0]
aFree(session[0]->rdata);
aFree(session[0]->wdata);
aFree(session[0]);

View File

@ -676,7 +676,7 @@ ACMD_FUNC(whogm)
memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
for (j = 0; player_name[j]; j++)
player_name[j] = TOLOWER(player_name[j]);
// search with no case sensitive
// search with no case sensitive
if (strstr(player_name, match_text) == NULL)
continue;
}
@ -2492,8 +2492,7 @@ ACMD_FUNC(stat_all)
/*==========================================
*
*------------------------------------------*/
ACMD_FUNC(guildlevelup)
{
ACMD_FUNC(guildlevelup) {
int level = 0;
short added_level;
struct guild *guild_info;
@ -2533,8 +2532,7 @@ ACMD_FUNC(guildlevelup)
/*==========================================
*
*------------------------------------------*/
ACMD_FUNC(makeegg)
{
ACMD_FUNC(makeegg) {
struct item_data *item_data;
int id, pet_id;
nullpo_retr(-1, sd);
@ -2573,8 +2571,7 @@ ACMD_FUNC(makeegg)
/*==========================================
*
*------------------------------------------*/
ACMD_FUNC(hatch)
{
ACMD_FUNC(hatch) {
nullpo_retr(-1, sd);
if (sd->status.pet_id <= 0)
clif_sendegg(sd);
@ -2589,8 +2586,7 @@ ACMD_FUNC(hatch)
/*==========================================
*
*------------------------------------------*/
ACMD_FUNC(petfriendly)
{
ACMD_FUNC(petfriendly) {
int friendly;
struct pet_data *pd;
nullpo_retr(-1, sd);
@ -3776,15 +3772,20 @@ ACMD_FUNC(mapinfo) {
clif_displaymessage(fd, msg_txt(sd,1041)); // ------ Map Flags ------
if (map[m_id].flag.town)
clif_displaymessage(fd, msg_txt(sd,1042)); // Town Map
if (map[m_id].flag.restricted){
sprintf(atcmd_output, msg_txt(sd,1106),map[m_id].zone);
clif_displaymessage(fd, atcmd_output); //restricted
}
if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade)
clif_displaymessage(fd, msg_txt(sd,1043)); // Autotrade Enabled
else
clif_displaymessage(fd, msg_txt(sd,1044)); // Autotrade Disabled
if (map[m_id].flag.battleground)
clif_displaymessage(fd, msg_txt(sd,1045)); // Battlegrounds ON
if (map[m_id].flag.battleground){
sprintf(atcmd_output, msg_txt(sd,1106),map[m_id].zone);
clif_displaymessage(fd, atcmd_output); // Battlegrounds ON type=%d
}
strcpy(atcmd_output,msg_txt(sd,1046)); // PvP Flags:
if (map[m_id].flag.pvp)
strcat(atcmd_output, msg_txt(sd,1047)); // Pvp ON |
@ -3897,6 +3898,22 @@ ACMD_FUNC(mapinfo) {
strcat(atcmd_output, msg_txt(sd,1096)); // PartyLock |
if (map[m_id].flag.guildlock)
strcat(atcmd_output, msg_txt(sd,1097)); // GuildLock |
if (map[m_id].flag.loadevent)
strcat(atcmd_output, msg_txt(sd,1098)); //Loadevent |
if (map[m_id].flag.src4instance)
strcat(atcmd_output, msg_txt(sd,1099)); // Src4instance |
if (map[m_id].flag.chmautojoin)
strcat(atcmd_output, msg_txt(sd,1100)); // Chmautojoin |
if (map[m_id].flag.nousecart)
strcat(atcmd_output, msg_txt(sd,1101)); // nousecart |
if (map[m_id].flag.noitemconsumption)
strcat(atcmd_output, msg_txt(sd,1102)); // noitemconsumption |
if (map[m_id].flag.nosumstarmiracle)
strcat(atcmd_output, msg_txt(sd,1103)); // nosumstarmiracle |
if (map[m_id].flag.nomineeffect)
strcat(atcmd_output, msg_txt(sd,1104)); // nomineeffect |
if (map[m_id].flag.nolockon)
strcat(atcmd_output, msg_txt(sd,1105)); // nolockon |
clif_displaymessage(fd, atcmd_output);
switch (list) {
@ -3904,12 +3921,12 @@ ACMD_FUNC(mapinfo) {
// Do nothing. It's list 0, no additional display.
break;
case 1:
clif_displaymessage(fd, msg_txt(sd,1098)); // ----- Players in Map -----
clif_displaymessage(fd, msg_txt(sd,480)); // ----- Players in Map -----
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
{
if (pl_sd->mapindex == m_index) {
sprintf(atcmd_output, msg_txt(sd,1099), // Player '%s' (session #%d) | Location: %d,%d
sprintf(atcmd_output, msg_txt(sd,481), // Player '%s' (session #%d) | Location: %d,%d
pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y);
clif_displaymessage(fd, atcmd_output);
}
@ -3917,33 +3934,33 @@ ACMD_FUNC(mapinfo) {
mapit_free(iter);
break;
case 2:
clif_displaymessage(fd, msg_txt(sd,1100)); // ----- NPCs in Map -----
clif_displaymessage(fd, msg_txt(sd,482)); // ----- NPCs in Map -----
for (i = 0; i < map[m_id].npc_num;)
{
nd = map[m_id].npc[i];
switch(nd->ud.dir) {
case 0: strcpy(direction, msg_txt(sd,1101)); break; // North
case 1: strcpy(direction, msg_txt(sd,1102)); break; // North West
case 2: strcpy(direction, msg_txt(sd,1103)); break; // West
case 3: strcpy(direction, msg_txt(sd,1104)); break; // South West
case 4: strcpy(direction, msg_txt(sd,1105)); break; // South
case 5: strcpy(direction, msg_txt(sd,1106)); break; // South East
case 6: strcpy(direction, msg_txt(sd,1107)); break; // East
case 7: strcpy(direction, msg_txt(sd,1108)); break; // North East
case 9: strcpy(direction, msg_txt(sd,1109)); break; // North
default: strcpy(direction, msg_txt(sd,1110)); break; // Unknown
case 0: strcpy(direction, msg_txt(sd,491)); break; // North
case 1: strcpy(direction, msg_txt(sd,492)); break; // North West
case 2: strcpy(direction, msg_txt(sd,493)); break; // West
case 3: strcpy(direction, msg_txt(sd,494)); break; // South West
case 4: strcpy(direction, msg_txt(sd,495)); break; // South
case 5: strcpy(direction, msg_txt(sd,496)); break; // South East
case 6: strcpy(direction, msg_txt(sd,497)); break; // East
case 7: strcpy(direction, msg_txt(sd,498)); break; // North East
case 9: strcpy(direction, msg_txt(sd,491)); break; // North
default: strcpy(direction, msg_txt(sd,499)); break; // Unknown
}
if(strcmp(nd->name,nd->exname) == 0)
sprintf(atcmd_output, msg_txt(sd,1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
sprintf(atcmd_output, msg_txt(sd,490), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y);
else
sprintf(atcmd_output, msg_txt(sd,1112), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y);
sprintf(atcmd_output, msg_txt(sd,489), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y);
clif_displaymessage(fd, atcmd_output);
}
break;
case 3:
clif_displaymessage(fd, msg_txt(sd,1113)); // ----- Chats in Map -----
clif_displaymessage(fd, msg_txt(sd,483)); // ----- Chats in Map -----
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
{
@ -3951,18 +3968,18 @@ ACMD_FUNC(mapinfo) {
pl_sd->mapindex == m_index &&
cd->usersd[0] == pl_sd)
{
sprintf(atcmd_output, msg_txt(sd,1114), // Chat: %s | Player: %s | Location: %d %d
cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
sprintf(atcmd_output, msg_txt(sd,484), // Chat: %s | Player: %s | Location: %d %d
cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, msg_txt(sd,1115), // Users: %d/%d | Password: %s | Public: %s
cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(sd,1116) : msg_txt(sd,1117)); // Yes / No
sprintf(atcmd_output, msg_txt(sd,485), // Users: %d/%d | Password: %s | Public: %s
cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(sd,486) : msg_txt(sd,487)); // Yes / No
clif_displaymessage(fd, atcmd_output);
}
}
mapit_free(iter);
break;
default: // normally impossible to arrive here
clif_displaymessage(fd, msg_txt(sd,1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
clif_displaymessage(fd, msg_txt(sd,488)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
return -1;
break;
}
@ -6320,7 +6337,7 @@ ACMD_FUNC(summon)
return -1;
md->master_id=sd->bl.id;
md->special_state.ai=1;
md->special_state.ai=AI_ATTACK;
md->deletetimer=add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0);
clif_specialeffect(&md->bl,344,AREA);
mob_spawn(md);

View File

@ -5160,8 +5160,8 @@ struct block_list* battle_get_master(struct block_list *src)
prev = src;
switch (src->type) {
case BL_PET:
if (((TBL_PET*)src)->msd)
src = (struct block_list*)((TBL_PET*)src)->msd;
if (((TBL_PET*)src)->master)
src = (struct block_list*)((TBL_PET*)src)->master;
break;
case BL_MOB:
if (((TBL_MOB*)src)->master_id)
@ -5245,9 +5245,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
}
break;
case BL_MOB:
if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
(((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe
if(((((TBL_MOB*)target)->special_state.ai == AI_SPHERE || //Marine Spheres
(((TBL_MOB*)target)->special_state.ai == AI_FLORA && battle_config.summon_flora&1)) && //Floras
s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == AI_ZANZOU && t_bl->id != s_bl->id)) //Zanzoe
{ //Targettable by players
state |= BCT_ENEMY;
strip_enemy = 0;
@ -5412,7 +5412,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( !md->special_state.ai )
{ //Normal mobs
if(
( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != 4 && ((TBL_MOB*)target)->special_state.ai != 1 ) ) ||
( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != AI_ZANZOU && ((TBL_MOB*)target)->special_state.ai != AI_ATTACK ) ) ||
( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai )
)
state |= BCT_PARTY; //Normal mobs with no ai are friends.

View File

@ -179,8 +179,8 @@ int bg_team_get_id(struct block_list *bl)
case BL_PC:
return ((TBL_PC*)bl)->bg_id;
case BL_PET:
if( ((TBL_PET*)bl)->msd )
return ((TBL_PET*)bl)->msd->bg_id;
if( ((TBL_PET*)bl)->master )
return ((TBL_PET*)bl)->master->bg_id;
break;
case BL_MOB:
{

View File

@ -44,10 +44,8 @@ static unsigned int buyingstore_getuid(void)
}
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
{
if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 )
{
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots){
if (!battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0) {
return false;
}

View File

@ -1230,7 +1230,7 @@ int chrif_load_scdata(int fd) {
for (i = 0; i < count; i++) {
data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15);
status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 1|2|4|8);
}
#endif
@ -1600,7 +1600,11 @@ int do_final_chrif(void) {
*
*------------------------------------------*/
int do_init_chrif(void) {
if(sizeof(struct mmo_charstatus) > 0xFFFF){
ShowError("mmo_charstatus size = %d is too big to be transmit\n",
sizeof(struct mmo_charstatus));
exit(EXIT_FAILURE);
}
auth_db = idb_alloc(DB_OPT_BASE);
auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);

View File

@ -2815,10 +2815,10 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOL(fd,4)=sd->battle_status.cri/10;
break;
case SP_MATK1:
WFIFOL(fd,4)=pc_rightside_matk(sd);
WFIFOL(fd,4)=pc_rightside_matk(sd);
break;
case SP_MATK2:
WFIFOL(fd,4)=pc_leftside_matk(sd);
WFIFOL(fd,4)=pc_leftside_matk(sd);
break;
@ -11579,7 +11579,7 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd)
/// 0100
void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
{
if(map[sd->bl.m].flag.partylock) { //Guild locked.
if(map[sd->bl.m].flag.partylock) { //part locked.
clif_displaymessage(fd, msg_txt(sd,227));
return;
}
@ -11591,7 +11591,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
/// 0103 <account id>.L <char name>.24B
void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd)
{
if(map[sd->bl.m].flag.partylock) { //Guild locked.
if(map[sd->bl.m].flag.partylock) { //party locked.
clif_displaymessage(fd, msg_txt(sd,227));
return;
}

View File

@ -783,4 +783,5 @@ void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char
#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
#endif /* _CLIF_H_ */

View File

@ -76,27 +76,27 @@ int elemental_create(struct map_session_data *sd, int class_, unsigned int lifet
ele.mode = EL_MODE_PASSIVE; // Initial mode
i = db->status.size+1; // summon level
//[(Casters Max HP/ 3 ) + (Casters INT x 10 )+ (Casters Job Level x 20 )] x [(Elemental Summon Level + 2) / 3]
//[(Caster<EFBFBD>s Max HP/ 3 ) + (Caster<65>s INT x 10 )+ (Caster<65>s Job Level x 20 )] x [(Elemental Summon Level + 2) / 3]
ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((i + 2) / 3);
//Casters Max SP /4
//Caster<EFBFBD>s Max SP /4
ele.sp = ele.max_sp = sd->battle_status.max_sp/4;
//Casters [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ]
//Caster<EFBFBD>s [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ]
ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100);
//Casters [ Max SP / (18 / Elemental Summon Skill Level) ]
//Caster<EFBFBD>s [ Max SP / (18 / Elemental Summon Skill Level) ]
ele.atk2 = sd->battle_status.max_sp / 18;
//Casters HIT + (Casters Base Level )
//Caster<EFBFBD>s HIT + (Caster<65>s Base Level )
ele.hit = sd->battle_status.hit + sd->status.base_level;
//[Elemental Summon Skill Level x (Casters INT / 2 + Casters DEX / 4)]
//[Elemental Summon Skill Level x (Caster<EFBFBD>s INT / 2 + Caster<65>s DEX / 4)]
ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4);
//150 + [Casters DEX / 10] + [Elemental Summon Skill Level x 3 ]
//150 + [Caster<EFBFBD>s DEX / 10] + [Elemental Summon Skill Level x 3 ]
ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3;
//Casters DEF + (Casters Base Level / (5 Elemental Summon Skill Level)
//Caster<EFBFBD>s DEF + (Caster<65>s Base Level / (5 <20> Elemental Summon Skill Level)
ele.def = sd->battle_status.def + sd->status.base_level / (5-i);
//Casters MDEF + (Casters INT / (5 - Elemental Summon Skill Level)
//Caster<EFBFBD>s MDEF + (Caster<65>s INT / (5 - Elemental Summon Skill Level)
ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i);
//Casters FLEE + (Casters Base Level / (5 Elemental Summon Skill Level)
//Caster<EFBFBD>s FLEE + (Caster<65>s Base Level / (5 <20> Elemental Summon Skill Level)
ele.flee = sd->status.base_level / (5-i);
//Casters HIT + (Casters Base Level )
//Caster<EFBFBD>s HIT + (Caster<65>s Base Level )
ele.hit = sd->battle_status.hit + sd->status.base_level;
//per individual bonuses

View File

@ -47,6 +47,7 @@ struct elemental_data {
struct s_elemental_db *db;
struct s_elemental elemental;
int masterteleport_timer;
struct map_session_data *master;
int summon_timer;
int skill_timer;

View File

@ -49,6 +49,7 @@ struct homun_data {
struct s_homunculus_db *homunculusDB; //[orn]
struct s_homunculus homunculus; //[orn]
int masterteleport_timer;
struct map_session_data *master; //pointer back to its master
int hungry_timer; //[orn]
unsigned int exp_next;

View File

@ -1735,43 +1735,38 @@ int map_quit(struct map_session_data *sd) {
/*==========================================
* Lookup, id to session (player,mob,npc,homon,merc..)
*------------------------------------------*/
struct map_session_data * map_id2sd(int id)
{
struct map_session_data * map_id2sd(int id){
if (id <= 0) return NULL;
return (struct map_session_data*)idb_get(pc_db,id);
}
struct mob_data * map_id2md(int id)
{
struct mob_data * map_id2md(int id){
if (id <= 0) return NULL;
return (struct mob_data*)idb_get(mobid_db,id);
}
struct npc_data * map_id2nd(int id)
{// just a id2bl lookup because there's no npc_db
struct npc_data * map_id2nd(int id){
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_NPC, bl);
}
struct homun_data* map_id2hd(int id)
{
struct homun_data* map_id2hd(int id){
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_HOM, bl);
}
struct mercenary_data* map_id2mc(int id)
{
struct mercenary_data* map_id2mc(int id){
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_MER, bl);
}
struct chat_data* map_id2cd(int id)
{
struct pet_data* map_id2pd(int id){
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_PET, bl);
}
struct chat_data* map_id2cd(int id){
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_CHAT, bl);
}

View File

@ -303,6 +303,16 @@ enum {
ELE_MAX
};
enum mob_ai {
AI_NONE = 0,
AI_ATTACK,
AI_SPHERE,
AI_FLORA,
AI_ZANZOU,
AI_LEGION,
AI_MAX
};
enum auto_trigger_flag {
ATF_SELF=0x01,
ATF_TARGET=0x02,
@ -333,9 +343,7 @@ struct spawn_data {
unsigned int level;
struct {
unsigned int size : 2; //Holds if mob has to be tiny/large
unsigned int ai : 4; //Special ai for summoned monsters.
//0: Normal mob | 1: Standard summon, attacks mobs
//2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou
enum mob_ai ai; //Special ai for summoned monsters.
unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list
unsigned int boss : 1; //0: Non-boss monster | 1: Boss monster
} state;
@ -553,12 +561,12 @@ struct map_data {
unsigned sakura : 1; // [Valaris]
unsigned leaves : 1; // [Valaris]
unsigned nogo : 1; // [Valaris]
unsigned nobaseexp : 1; // [Lorky] added by Lupus
unsigned nojobexp : 1; // [Lorky]
unsigned nomobloot : 1; // [Lorky]
unsigned nomvploot : 1; // [Lorky]
unsigned nobaseexp : 1; // [Lorky] added by Lupus
unsigned nojobexp : 1; // [Lorky]
unsigned nomobloot : 1; // [Lorky]
unsigned nomvploot : 1; // [Lorky]
unsigned nightenabled :1; //For night display. [Skotlex]
unsigned restricted : 1; // [Komurka]
unsigned restricted : 1; // [Komurka]
unsigned nodrop : 1;
unsigned novending : 1;
unsigned loadevent : 1;

View File

@ -1969,11 +1969,11 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
{
struct pet_data *pd = (TBL_PET*)src;
flag = MDLF_PET;
if( pd->msd )
if( pd->master )
{
char_id = pd->msd->status.char_id;
char_id = pd->master->status.char_id;
if( damage ) //Let mobs retaliate against the pet's master [Skotlex]
md->attacked_id = pd->msd->bl.id;
md->attacked_id = pd->master->bl.id;
}
break;
}
@ -2079,7 +2079,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage)
}
#endif
if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex]
if( md->special_state.ai == AI_SPHERE ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex]
md->state.alchemist = 1;
mobskill_use(md, gettick(), MSC_ALCHEMIST);
}
@ -2308,7 +2308,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && (
!md->special_state.ai || //Non special mob
battle_config.alchemist_summon_reward == 2 || //All summoned give drops
(md->special_state.ai==2 && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items.
(md->special_state.ai==AI_SPHERE && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items.
) )
{ // Item Drop
struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list);
@ -2736,7 +2736,7 @@ int mob_class_change (struct mob_data *md, int class_)
if( mob_is_treasure(md) )
return 0; //Treasure Boxes
if( md->special_state.ai > 1 )
if( md->special_state.ai > AI_ATTACK )
return 0; //Marine Spheres and Floras.
if( mob_is_clone(md->class_) )

View File

@ -69,14 +69,6 @@ enum size {
SZ_BIG,
};
enum ai {
AI_NONE = 0,
AI_ATTACK,
AI_SPHERE,
AI_FLORA,
AI_ZANZOU,
};
struct mob_skill {
enum MobSkillState state;
uint16 skill_id,skill_lv;
@ -129,13 +121,7 @@ struct mob_data {
char name[NAME_LENGTH];
struct {
unsigned int size : 2; //Small/Big monsters.
unsigned int ai : 4; //Special ai for summoned monsters.
//0: Normal mob.
//1: Standard summon, attacks mobs.
//2: Alchemist Marine Sphere
//3: Alchemist Summon Flora
//4: Summon Zanzou
//5: Summon Legion
enum mob_ai ai; //Special ai for summoned monsters.
unsigned int clone : 1;/* is clone? 1:0 */
} special_state; //Special mob information that does not needs to be zero'ed on mob respawn.
struct {

View File

@ -3063,7 +3063,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
return strchr(start, '\n');
}
if( (mob.state.ai < 0 || mob.state.ai > 4) && ai != -1 )
if( (mob.state.ai < AI_NONE || mob.state.ai >= AI_MAX) && ai != -1 )
{
ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mob.state.ai, class_, filepath, strline(buffer, start - buffer));
return strchr(start, '\n');
@ -3086,7 +3086,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
mob.level = mob_lv;
if (size > 0 && size <= 2)
mob.state.size = size;
if (ai > 0 && ai <= 4)
if (ai > AI_NONE && ai <= AI_MAX)
mob.state.ai = ai;
if (mob.num > 1 && battle_config.mob_count_rate != 100) {

View File

@ -519,7 +519,7 @@ int pc_makesavestatus(struct map_session_data *sd)
if(!battle_config.save_clothcolor)
sd->status.clothes_color=0;
//Only copy the Cart/Peco/Falcon options, the rest are handled via
//Only copy the Cart/Peco/Falcon options, the rest are handled via
//status change load/saving. [Skotlex]
#ifdef NEW_CARTS
sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING);
@ -4044,7 +4044,7 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
}
else
if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id)
{
{
second_sd = map_charid2sd(fitem->second_get_charid);
if(DIFF_TICK(tick, fitem->second_get_tick) < 0) {
if(!(p && p->party.item&1 &&
@ -4837,8 +4837,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
if(sd->bl.prev != NULL){
unit_remove_map_pc(sd,clrtype);
clif_changemap(sd,map[m].index,x,y); // [MouseJstr]
} else if(sd->state.active)
//Tag player for rewarping after map-loading is done. [Skotlex]
} else if(sd->state.active) //Tag player for rewarping after map-loading is done. [Skotlex]
sd->state.rewarp = 1;
sd->mapindex = mapindex;
@ -6573,10 +6572,8 @@ static int pc_close_npc_timer(int tid, unsigned int tick, int id, intptr_t data)
{
TBL_PC *sd = map_id2sd(id);
if(sd) pc_close_npc(sd,data);
return 0;
}
/*
* Method to properly close npc for player and clear anything related
* @flag == 1 : produce close button
@ -7815,7 +7812,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
clif_cartlist(sd);
clif_updatestatus(sd, SP_CARTINFO);
sc_start(&sd->bl,&sd->bl, SC_PUSH_CART, 100, type, 0);
clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0);
clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0);
if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
sd->sc.data[SC_PUSH_CART]->val1 = type;
break;
@ -9231,7 +9228,7 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
{
if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled)
{ //Night/day state does not match.
{ //Night/day state does not match.
clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex]
sd->state.night = night_flag;
return 1;

View File

@ -64,7 +64,7 @@ void pet_set_intimate(struct pet_data *pd, int value)
nullpo_retv(pd);
intimate = pd->pet.intimate;
sd = pd->msd;
sd = pd->master;
pd->pet.intimate = value;
if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
@ -135,7 +135,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
pd = sd->pd;
Assert((pd->msd == 0) || (pd->msd->pd == pd));
Assert((pd->master == 0) || (pd->master->pd == pd));
if(bl == NULL || bl->type != BL_MOB || bl->prev == NULL ||
pd->pet.intimate < battle_config.pet_support_min_friendly ||
@ -323,7 +323,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
nullpo_retr(1, sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd);
if(sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) {
sd->status.pet_id = 0;
@ -350,7 +350,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
pd->bl.type = BL_PET;
pd->bl.id = npc_get_new_npc_id();
pd->msd = sd;
pd->master = sd;
pd->petDB = &pet_db[i];
pd->db = mob_db(pet->class_);
memcpy(&pd->pet, pet, sizeof(struct s_pet));
@ -389,7 +389,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet)
{
nullpo_retr(1, sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd);
if(sd->status.pet_id && pet->incuvate == 1) {
sd->status.pet_id = 0;
@ -417,7 +417,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet)
clif_pet_equip_area(sd->pd);
clif_send_petstatus(sd);
}
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd);
return 0;
}
@ -791,7 +791,7 @@ static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
{
nullpo_ret(pd);
Assert((pd->msd == 0) || (pd->msd->pd == pd));
Assert((pd->master == 0) || (pd->master->pd == pd));
if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) {
const int retrycount=20;
@ -968,7 +968,7 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
sd_charid = fitem->first_get_charid;
if(sd_charid && sd_charid != pd->msd->status.char_id)
if(sd_charid && sd_charid != pd->master->status.char_id)
return 0;
if(unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) &&

View File

@ -95,7 +95,8 @@ struct pet_data {
struct pet_skill_support* s_skill;
struct pet_loot* loot;
struct map_session_data *msd;
int masterteleport_timer;
struct map_session_data *master;
};

View File

@ -12083,7 +12083,7 @@ BUILDIN_FUNC(petloot)
pd = sd->pd;
if (pd->loot != NULL)
{ //Release whatever was there already and reallocate memory
pet_lootitem_drop(pd, pd->msd);
pet_lootitem_drop(pd, pd->master);
aFree(pd->loot->item);
}
else

View File

@ -919,17 +919,13 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case MG_FROSTDIVER:
#ifndef RENEWAL
case WZ_FROSTNOVA:
#endif
sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv));
if(!sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv)))
clif_skill_fail(sd,skill_id,0,0);
break;
#ifdef RENEWAL
case WZ_FROSTNOVA:
sc_start(src,bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill_get_time2(skill_id,skill_lv));
break;
#endif
case WZ_STORMGUST:
/**
@ -5140,7 +5136,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!ud) break;
if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
if (src->type == BL_PET)
bl = (struct block_list*)((TBL_PET*)src)->msd;
bl = (struct block_list*)((TBL_PET*)src)->master;
if (!bl) bl = src;
unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv);
} else { //Assume offensive skills
@ -5846,7 +5842,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_SELFDESTRUCTION:
//Self Destruction hits everyone in range (allies+enemies)
//Except for Summoned Marine spheres on non-versus maps, where it's just enemy.
i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))?
i = ((!md || md->special_state.ai == AI_SPHERE) && !map_flag_vs(src->m))?
BCT_ENEMY:BCT_ALL;
clif_skill_nodamage(src, src, skill_id, -1, 1);
map_delblock(src); //Required to prevent chain-self-destructions hitting back.
@ -8734,7 +8730,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!ud) break;
if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
if (src->type == BL_PET)
bl = (struct block_list*)((TBL_PET*)src)->msd;
bl = (struct block_list*)((TBL_PET*)src)->master;
if (!bl) bl = src;
unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv);
} else {
@ -9266,7 +9262,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sum_md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
if (sum_md) {
sum_md->master_id = src->id;
sum_md->special_state.ai = 5;
sum_md->special_state.ai = AI_LEGION;
if (sum_md->deletetimer != INVALID_TIMER)
delete_timer(sum_md->deletetimer, mob_timer_delete);
sum_md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, sum_md->bl.id, 0);
@ -9496,7 +9492,16 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
}
break;
}
#ifdef OFFICIAL_WALKPATH
if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) )
{
if (sd) {
clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,3); //Consume items anyway.
}
break;
}
#endif
if( sd )
{
if( !skill_check_condition_castend(sd, ud->skill_id, ud->skill_lv) )
@ -9504,18 +9509,14 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
else
skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,1);
}
#ifdef OFFICIAL_WALKPATH
if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) )
break;
#endif
if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) )
break;
if (ud->state.running && ud->skill_id == TK_JUMPKICK)
{
ud->state.running = 0;
status_change_end(src, SC_RUN, INVALID_TIMER);
flag = 1;
if (ud->state.running && ud->skill_id == TK_JUMPKICK){
ud->state.running = 0;
status_change_end(src, SC_RUN, INVALID_TIMER);
flag = 1;
}
if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH)
@ -9579,7 +9580,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
if(sc->data[SC_SPIRIT] &&
sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
sc->data[SC_SPIRIT]->val3 == ud->skill_id &&
ud->skill_id != WZ_WATERBALL)
ud->skill_id != WZ_WATERBALL)
sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check.
if( sc->data[SC_DANCING] && skill_get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd )
@ -9600,7 +9601,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
//Skill failed.
if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL]))
{ //When Asura fails... (except when it fails from Fog of Wall)
{ //When Asura fails... (except when it fails from Fog of Wall)
//Consume SP/spheres
skill_consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
status_set_sp(src, 0, 0);

View File

@ -2014,7 +2014,7 @@ int status_calc_mob_(struct mob_data* md, bool first)
if (battle_config.slaves_inherit_speed && md->master_id)
flag|=8;
if (md->master_id && md->special_state.ai>1)
if (md->master_id && md->special_state.ai>AI_ATTACK)
flag|=16;
if (!flag)
@ -2050,28 +2050,28 @@ int status_calc_mob_(struct mob_data* md, bool first)
struct unit_data *ud = unit_bl2ud(mbl);
//Remove special AI when this is used by regular mobs.
if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai)
md->special_state.ai = 0;
md->special_state.ai = AI_NONE;
if (ud)
{ // different levels of HP according to skill level
switch(ud->skill_id){
case AM_SPHEREMINE:
status->max_hp = 2000 + 400*ud->skill_lv;
break;
status->max_hp = 2000 + 400*ud->skill_lv;
break;
case KO_ZANZOU:
status->max_hp = 3000 + 3000 * ud->skill_lv;
break;
status->max_hp = 3000 + 3000 * ud->skill_lv;
break;
case AM_CANNIBALIZE:
status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
break;
status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
break;
case MH_SUMMON_LEGION:{
int homblvl = status_get_lv(mbl);
status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl);
status->batk = 100 * (ud->skill_lv+5) / 2;
status->def = 10 * (100 * (ud->skill_lv+2) + homblvl);
// status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10);
// status->aspd_rate = max(100,status->aspd_rate);
break;
int homblvl = status_get_lv(mbl);
status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl);
status->batk = 100 * (ud->skill_lv+5) / 2;
status->def = 10 * (100 * (ud->skill_lv+2) + homblvl);
// status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10);
// status->aspd_rate = max(100,status->aspd_rate);
break;
}
}
status->hp = status->max_hp;
@ -2182,9 +2182,9 @@ int status_calc_pet_(struct pet_data *pd, bool first)
}
}
if (battle_config.pet_lv_rate && pd->msd)
if (battle_config.pet_lv_rate && pd->master)
{
struct map_session_data *sd = pd->msd;
struct map_session_data *sd = pd->master;
int lv;
lv =sd->status.base_level*battle_config.pet_lv_rate/100;
@ -3157,6 +3157,8 @@ int status_calc_mercenary_(struct mercenary_data *md, bool first)
status->sp = status->max_sp;
md->battle_status.hp = merc->hp;
md->battle_status.sp = merc->sp;
if (md->master)
status->speed = status_get_speed(&md->master->bl);
}
status_calc_misc(&md->bl, status, md->db->lv);
@ -3287,6 +3289,9 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) {
status->flee = ele->flee;
status->hit = ele->hit;
if (ed->master)
status->speed = status_get_speed(&ed->master->bl);
memcpy(&ed->battle_status,status,sizeof(struct status_data));
} else {
status_calc_misc(&ed->bl, status, 0);
@ -3807,7 +3812,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
//Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
//because if you step on something while walking, the moment this
//piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex]
if (ud)
if (ud)
ud->state.change_walk_target = ud->state.speed_changed = 1;
if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed )
@ -3815,6 +3820,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master)
status->speed = status_get_speed(&((TBL_HOM*)bl)->master->bl);
if( bl->type&BL_MER && ((TBL_MER*)bl)->master)
status->speed = status_get_speed(&((TBL_MER*)bl)->master->bl);
if( bl->type&BL_ELEM && ((TBL_ELEM*)bl)->master)
status->speed = status_get_speed(&((TBL_ELEM*)bl)->master->bl);
}
@ -5905,8 +5914,8 @@ int status_get_party_id(struct block_list *bl) {
case BL_PC:
return ((TBL_PC*)bl)->status.party_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.party_id;
if (((TBL_PET*)bl)->master)
return ((TBL_PET*)bl)->master->status.party_id;
break;
case BL_MOB: {
struct mob_data *md=(TBL_MOB*)bl;
@ -5942,8 +5951,8 @@ int status_get_guild_id(struct block_list *bl) {
case BL_PC:
return ((TBL_PC*)bl)->status.guild_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.guild_id;
if (((TBL_PET*)bl)->master)
return ((TBL_PET*)bl)->master->status.guild_id;
break;
case BL_MOB: {
struct map_session_data *msd;
@ -5982,8 +5991,8 @@ int status_get_emblem_id(struct block_list *bl) {
case BL_PC:
return ((TBL_PC*)bl)->guild_emblem_id;
case BL_PET:
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->guild_emblem_id;
if (((TBL_PET*)bl)->master)
return ((TBL_PET*)bl)->master->guild_emblem_id;
break;
case BL_MOB: {
struct map_session_data *msd;

View File

@ -112,16 +112,92 @@ int unit_walktoxy_sub(struct block_list *bl)
return 1;
}
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
TBL_PC* unit_get_master(struct block_list *bl){
if(bl)
switch(bl->type){
case BL_HOM : return (((TBL_HOM *)bl)->master);
case BL_ELEM : return (((TBL_ELEM *)bl)->master);
case BL_PET : return (((TBL_PET *)bl)->master);
case BL_MER : return (((TBL_MER *)bl)->master);
}
return NULL;
}
int* unit_get_masterteleport_timer(struct block_list *bl){
if(bl)
switch(bl->type){
case BL_HOM: return &(((TBL_HOM *)bl)->masterteleport_timer);
case BL_ELEM: return &(((TBL_ELEM *)bl)->masterteleport_timer);
case BL_PET: return &(((TBL_PET *)bl)->masterteleport_timer);
case BL_MER: return &(((TBL_MER *)bl)->masterteleport_timer);
}
return NULL;
}
int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data){
if(tid == INVALID_TIMER)
return 0;
else {
struct block_list *bl = map_id2bl(id);
int *mast_tid = unit_get_masterteleport_timer(bl);
TBL_PC *msd = unit_get_master(bl);
switch(data){
case BL_HOM:
case BL_ELEM:
case BL_PET :
case BL_MER :
if(msd && *mast_tid != INVALID_TIMER && !check_distance_bl(&msd->bl, bl, MAX_MER_DISTANCE)){
*mast_tid = INVALID_TIMER;
unit_warp(bl, msd->bl.id, msd->bl.x, msd->bl.y, CLR_TELEPORT );
}
break;
}
}
return 0;
}
int unit_check_start_teleport_timer(struct block_list *sbl){
TBL_PC *msd = unit_get_master(sbl);
int max_dist=AREA_SIZE;
switch(sbl->type){
//case BL_HOM: max_dist = MAX_HOM_DISTANCE; break;
case BL_ELEM: max_dist = MAX_ELEDISTANCE; break;
//case BL_PET : max_dist = MAX_PET_DISTANCE; break;
case BL_MER : max_dist = MAX_MER_DISTANCE; break;
}
if(msd){ //if there is a master
int *msd_tid = unit_get_masterteleport_timer(sbl);
if(msd_tid == NULL) return 0;
if (!check_distance_bl(&msd->bl, sbl, MAX_MER_DISTANCE)) {
if(*msd_tid == INVALID_TIMER)
*msd_tid = add_timer(gettick()+3000,unit_teleport_timer,sbl->id,BL_MER);
}
else {
if(*msd_tid != INVALID_TIMER)
delete_timer(*msd_tid,unit_teleport_timer);
*msd_tid = INVALID_TIMER; //cancel recall
}
}
return 0;
}
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data){
int i;
int x,y,dx,dy;
uint8 dir;
struct block_list *bl;
struct map_session_data *sd;
struct mob_data *md;
struct unit_data *ud;
struct mercenary_data *mrd;
TBL_PC *sd;
TBL_MOB *md;
TBL_MER *mrd;
TBL_ELEM *ed;
TBL_PET *pd;
TBL_HOM *hd;
bl = map_id2bl(id);
if(bl == NULL)
@ -129,6 +205,9 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
sd = BL_CAST(BL_PC, bl);
md = BL_CAST(BL_MOB, bl);
mrd = BL_CAST(BL_MER, bl);
ed = BL_CAST(BL_ELEM, bl);
pd = BL_CAST(BL_PET, bl);
hd = BL_CAST(BL_HOM, bl);
ud = unit_bl2ud(bl);
if(ud == NULL) return 0;
@ -174,6 +253,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
ud->walktimer = INVALID_TIMER;
if(sd) {
struct block_list *sbl; //slave bl
if( sd->touching_id )
npc_touchnext_areanpc(sd,false);
if(map_getcell(bl->m,x,y,CELL_CHKNPC)) {
@ -183,24 +263,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
} else
sd->areanpc_id=0;
if( sd->md && !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) )
{
// mercenary should be warped after being 3 seconds too far from the master [greenbox]
if (sd->md->masterteleport_timer == 0)
{
sd->md->masterteleport_timer = gettick();
}
else if (DIFF_TICK(gettick(), sd->md->masterteleport_timer) > 3000)
{
sd->md->masterteleport_timer = 0;
unit_warp( &sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
}
}
else if( sd->md )
{
// reset the tick, he is not far anymore
sd->md->masterteleport_timer = 0;
}
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);
} else if (md) {
if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
if( npc_touch_areanpc2(md) ) return 0; // Warped
@ -212,7 +278,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
if(tid != INVALID_TIMER &&
!(ud->walk_count%WALK_SKILL_INTERVAL) &&
mobskill_use(md, tick, -1))
{
{
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
{ //Skill used, abort walking
clif_fixpos(bl); //Fix position as walk has been cancelled.
@ -222,26 +288,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
clif_move(ud);
}
}
else if( mrd && mrd->master )
{
if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE))
{
// mercenary should be warped after being 3 seconds too far from the master [greenbox]
if (mrd->masterteleport_timer == 0)
{
mrd->masterteleport_timer = gettick();
}
else if (DIFF_TICK(gettick(), mrd->masterteleport_timer) > 3000)
{
mrd->masterteleport_timer = 0;
unit_warp( bl, mrd->master->bl.id, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT );
}
}
else
{
mrd->masterteleport_timer = 0;
}
}
else if( hd) unit_check_start_teleport_timer(&hd->bl);
else if( ed) unit_check_start_teleport_timer(&ed->bl);
else if( pd) unit_check_start_teleport_timer(&pd->bl);
else if( mrd) unit_check_start_teleport_timer(&mrd->bl);
if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
return 0;
@ -798,7 +848,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
}
if (x<0 || y<0)
{ //Random map position.
{ //Random map position.
if (!map_search_freecell(NULL, m, &x, &y, -1, -1, 1)) {
ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y);
return 2;
@ -809,7 +859,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map[m].name, x,y);
if (!map_search_freecell(NULL, m, &x, &y, 4, 4, 1))
{ //Can't find a nearby cell
{ //Can't find a nearby cell
ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y);
return 2;
}
@ -2187,7 +2237,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
}
case BL_PET: {
struct pet_data *pd = (struct pet_data*)bl;
if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) )
if( pd->pet.intimate <= 0 && !(pd->master && !pd->master->state.active) )
{ //If logging out, this is deleted on unit_free
clif_clearunit_area(bl,clrtype);
map_delblock(bl);
@ -2350,7 +2400,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
case BL_PET:
{
struct pet_data *pd = (struct pet_data*)bl;
struct map_session_data *sd = pd->msd;
struct map_session_data *sd = pd->master;
pet_hungry_timer_delete(pd);
if( pd->a_skill )
{
@ -2528,6 +2578,7 @@ int do_init_unit(void)
add_timer_func_list(unit_walktobl_sub, "unit_walktobl_sub");
add_timer_func_list(unit_delay_walktoxy_timer,"unit_delay_walktoxy_timer");
add_timer_func_list(unit_delay_walktobl_timer,"unit_delay_walktobl_timer");
add_timer_func_list(unit_teleport_timer,"unit_teleport_timer");
return 0;
}