Index: conf/commands.conf =================================================================== --- conf/commands.conf (revision 3520) +++ conf/commands.conf (working copy) @@ -69,4 +69,9 @@ commands_ini[55] = { ["name"] = "completequest", ["path"] = "scripts/commands", ["parameters"] = "iis" }; commands_ini[56] = { ["name"] = "mobsub", ["path"] = "scripts/commands", ["parameters"] = "ii" }; commands_ini[57] = { ["name"] = "logoff", ["path"] = "scripts/commands", ["parameters"] = "s" }; -commands_ini[58] = { ["name"] = "animatenpc", ["path"] = "scripts/commands", ["parameters"] = "ii" }; \ No newline at end of file +commands_ini[58] = { ["name"] = "givespell", ["path"] = "scripts/commands", ["parameters"] = "si" }; +commands_ini[59] = { ["name"] = "capplayerskill", ["path"] = "scripts/commands", ["parameters"] = "ss" }; +commands_ini[60] = { ["name"] = "teleplayer", ["path"] = "scripts/commands", ["parameters"] = "siiii" }; +commands_ini[61] = { ["name"] = "op", ["path"] = "scripts/commands", ["parameters"] = "ss" }; +commands_ini[62] = { ["name"] = "delspell", ["path"] = "scripts/commands", ["parameters"] = "i" }; +commands_ini[63] = { ["name"] = "animatenpc", ["path"] = "scripts/commands", ["parameters"] = "ii" }; \ No newline at end of file Index: conf/login_darkstar.conf =================================================================== --- conf/login_darkstar.conf (revision 3520) +++ conf/login_darkstar.conf (working copy) @@ -58,8 +58,11 @@ #01000000 Bit6 - Not Used - Future expansion #10000000 Bit7 - Not Used - Future expansion -expansions: 30 +expansions: 4094 #Server name (not longer than 15 characters) servername: DarkStar +# LAN IP Mask +lan_ipmask: 10.1.10.* + Index: conf/map_darkstar.conf =================================================================== --- conf/map_darkstar.conf (revision 3520) +++ conf/map_darkstar.conf (working copy) @@ -91,7 +91,57 @@ # 0111 7 Parry, Block, & Guard newstyle_skillups: 7 +#Multiplies the distance that you can engage target. Change to 2 for double the distance. Default is 1. +engage_dist_mod: 2 +#Multiplies the distance that you can cast magic on a target. Change to 2 for double the distance. Default is 1. +magic_dist_mod: 2 + +#Multiplies the distance that you can used ranged attack on a target. Change to 2 for double the distance. Default is 1. +ranged_dist_mod: 2 + +#Set to 1 to disable the delay that happens just after killing a target, or after equipping a weapon. +remove_engage_delay: 1 + +#Set to 1 to allow movement while casting magic. +magic_movement: 1 + +#Increases chance of exp mobs dropping seals or crests. Set from 0 - 60. Default is 0. +seal_crest_bonus: 5 + +#Allows non exp beastman mobs to drop seals and crests. Set to 1 for non exp beastman mobs to drop seals and crests. Default is 0. +always_seal_crest: 0 + +#Adds to the drop rate percentage. Set to 20 to add additional %20 drop rate on items. Default 0. +drop_rate_bonus: 10 + +#Set to 1 to allow all mobs to drop gil. Currently does not display in-game messages for these gil drops. Default is 0. +all_mobs_drop_gil: 0 + +#Multiplies the amount of gil dropped. Default is 1. +gil_bonus: 1 + +#Allows exp chain on any exp mob. Default is 0. +chain_on_easy: 1 + +#Increases the time frame allowed to get an exp chain. Default is 1. +chain_bonus: 3 + +#Allows same skill-up on chance for failures as crafting successes have. Default is 0. +craft_skill_onfail: 1 + +#Increases the chance of getting larger skill-ups while crafting. Set 0 to 100. Default 0. +craft_skillamt: 10 + +#Increases the chance of succeeding at crafting. Set 0 to 100. Default 0. +craft_success: 10 + +#Multiplies the amount of conquest points earned on an exp mob kill. Default is 1. +conquest_bonus: 1 + +notorious_hp_mod: 4.5 +notorious_mp_mod: 4.5 + #Max allowed merits points players can hold # 10 classic # 30 abyssea Index: sql/DSP_import.bat =================================================================== --- sql/DSP_import.bat (revision 0) +++ sql/DSP_import.bat (working copy) @@ -0,0 +1,43 @@ +@ECHO OFF +REM ============================================================================= +REM ============================================================================= +REM ====== ========= +REM ====== THis script will drop the DB specificed, then create the DB ========= +REM ====== specified, and then load all .sql tables from its run dir to ========= +REM ====== the the DB. ========= +REM ====== ========= +REM ====== File needs to be run from within the \dsp\sql folder (same ========= +REM ====== folder with all the .sql files. Please edit as needed. By ========= +REM ====== default it WILL DROP the standard dspdb DB, loosing all ========= +REM ====== accounts and characters. If this is not desired, then update ========= +REM ====== the file to load the new DB into a new DB name. ========= +REM ====== ========= +REM ====== Update -p with MySQL password. If you password is 'foo', ========= +REM ====== then change '-pMYSQLPASS' to '-pfoo' (3 places). ========= +REM ====== ========= +REM ====== If you want to use a different database name, change 'dspdb' ========= +REM ====== with a database name of your choosing. ========= +REM ====== ========= +REM ============================================================================= +REM ============================================================================= +REM ====== ========= +REM ====== by Thrydwolf 9/8/2012 ========= +REM ====== Updated with status by bluekirby0 3/30/2012 ========= +REM ====== Updated by Thrydwolf 9/18/2012 ========= +REM ====== ========= +REM ============================================================================= +REM ============================================================================= + +ECHO Creating Database dspdb +mysqladmin -h localhost -u root -priotz123 DROP dspdb + +ECHO Creating Database dspdb +mysqladmin -h localhost -u root -priotz123 CREATE dspdb + +ECHO Loading dspdb with tables +REM FOR %%X IN (*.sql) DO mysql dspdb -h localhost -u root -priotz123 < %%X +FOR %%X IN (*.sql) DO ECHO Importing %%X & mysql dspdb -h localhost -u root -priotz123 < %%X + +ECHO Finished! + +pause \ No newline at end of file Index: src/common/mmo.h =================================================================== --- src/common/mmo.h (revision 3520) +++ src/common/mmo.h (working copy) @@ -74,8 +74,8 @@ typedef std::string string_t; -// для персонажей в size хранится рост, -// для npc и монстров что-то вроде типа используемой модели +// Size of the characters in the store growth +// Npc and monsters for a bit of product model struct look_t { @@ -112,23 +112,23 @@ // index SkillID 0-63 uint16 skill[64]; }; - // ранг используется только в ремеслах. размер 64 необходим для совместимости ID + // Rank is used only in the arts. size of 64 is required for compatibility ID uint8 rank[64]; }; struct keyitems_t { - uint8 keysList[320]; // таблица ключевых предметов - uint8 seenList[320]; // таблица ключевых предметов, отмеченных как "увиденные" + uint8 keysList[320]; // table of key items + uint8 seenList[320]; // table of key items that are marked as "seen" }; struct position_t { - uint8 rotation; // угол поворота сущности относительно своей позиции (используется 255 система, место 360°) + uint8 rotation; // angle of rotation of the essence with respect to its position (using 255 systems, the 360 °) float x; - float y; // высота расположения сущности относительно "уровня моря" + float y; // height the location of essence relatively "sea level" float z; - uint16 moving; // что-то вроде расстояния перемещения, необходимое для правильной отрисовки в клиенте количества шагов сущности + uint16 moving; // sort of distance traveled, necessary for the proper rendering of the number of steps in the client entity }; struct stats_t @@ -176,10 +176,10 @@ // информация для окна поиска struct search_t { - uint8 language; // предпочтительный язык общения - uint8 messagetype; // тип комментария + uint8 language; // the preferred language of communication + uint8 messagetype; // type of comment - string_t message; // комментарий поиска + string_t message; // comment search }; struct bazaar_t @@ -187,12 +187,12 @@ string_t message; }; -// небольшой комментарий к пакетам ниже, определенным в виде констант -// 1-й байт - размер пакета -// через 4-ре байта начинается заголовк 0x49, 0x58, 0x46, 0x46 - IXFF -// после заголовка идет предположительно тип сообщения: -// 0x03 - положительный результат -// 0x04 - ошибка (в случае ошибки начиная с 33 байта идет код ошибки uint16) +// A comment on the packages below, defined as constants +// 1 byte - packet size +// A 4-D bytes File Title starts 0x49, 0x58, 0x46, 0x46 - IXFF +// After the title is presumably the type of message: +// 0x03 - positive +// 0x04 - error (in the case of error ranging from 33 bytes is an error code uint16) #define LOBBY_A1_RESERVEPACKET(a)\ unsigned char a[] = { \ Index: src/common/utils.cpp =================================================================== --- src/common/utils.cpp (revision 3520) +++ src/common/utils.cpp (working copy) @@ -425,6 +425,39 @@ return retVal; } +int wildcmp(const char *wild, const char *string) { + const char *cp = NULL, *mp = NULL; + + while ((*string) && (*wild != '*')) { + if ((*wild != *string) && (*wild != '?')) { + return 0; + } + wild++; + string++; + } + + while (*string) { + if (*wild == '*') { + if (!*++wild) { + return 1; + } + mp = wild; + cp = string+1; + } else if ((*wild == *string) || (*wild == '?')) { + wild++; + string++; + } else { + wild = mp; + string = cp++; + } + } + + while (*wild == '*') { + wild++; + } + return !*wild; +} + int8* EncodeStringLinkshell(int8* signature, int8* target) { uint8 encodedSignature[16]; Index: src/common/utils.h =================================================================== --- src/common/utils.h (revision 3520) +++ src/common/utils.h (working copy) @@ -62,5 +62,6 @@ int8* EncodeStringSignature(int8* signature, int8* target); int8* DecodeStringSignature(int8* signature, int8* target); +int wildcmp(const char *wild, const char *string); #endif Index: src/login/lobby.cpp =================================================================== --- src/login/lobby.cpp (revision 3520) +++ src/login/lobby.cpp (working copy) @@ -128,11 +128,11 @@ unsigned char CharList[2500]; memset(CharList,0,sizeof(CharList)); - //запись зарезервированных чисел + //Record numbers of reserved CharList[0] = 0xE0;CharList[1] = 0x08; CharList[4] = 0x49;CharList[5] = 0x58;CharList[6] = 0x46;CharList[7] = 0x46;CharList[8] = 0x20; - CharList[28] = 16; // количество ячеек, доступных для создания персонажей (0-16) + CharList[28] = 16; // the number of cells available for creating characters (0-16) const char *pfmtQuery = "SELECT charid, charname, pos_zone, pos_prevzone, mjob,\ race, face, head, body, hands, legs, feet, main, sub,\ @@ -157,7 +157,7 @@ //server's name that shows in lobby menu memcpy(ReservePacket+60, login_config.servername, dsp_cap(strlen(login_config.servername), 0, 15)); - //Подготовка пространства в пакете для информации о 16 игровых персонажах + //Preparing the space in the packet for information about the 16 game characters for(int j = 0; j<16; ++j) { memcpy(CharList+32+140*j, ReservePacket+32, 140); @@ -173,8 +173,8 @@ int i = 0; - //Считывание информации о конкректном персонаже - //Загрузка всей необходимой информации о персонаже из базы + //Reading information about a specific character + //Download all the information about a character from the database while(Sql_NextRow(SqlHandle) != SQL_NO_DATA) { char* strCharName = NULL; @@ -209,7 +209,7 @@ WBUFW(CharList,68+32+i*140) = (uint16)Sql_GetIntData(SqlHandle,12); // main; WBUFW(CharList,70+32+i*140) = (uint16)Sql_GetIntData(SqlHandle,13); // sub; - WBUFB(CharList,72+32+i*140) = (zone == 0 ? prevzone : zone); // если персонаж в MogHouse + WBUFB(CharList,72+32+i*140) = (zone == 0 ? prevzone : zone); // if a character in MogHouse /////////////////////////////////////////////////// ++i; } @@ -262,37 +262,58 @@ uint32 charid = RBUFL(session[sd->login_lobbyview_fd]->rdata,32); - const char *fmtQuery = "SELECT zoneip, zoneport, zoneid, pos_prevzone \ + const char *fmtQuery = "SELECT lanip, wanip, zoneport, zoneid, pos_prevzone \ FROM zone_settings, chars \ WHERE zoneid = pos_zone AND charid = %u;"; - uint32 ZoneIP = sd->servip; - uint16 ZonePort = 54230; + uint32 ZoneLANIP = 0; + uint32 ZoneWANIP = 0; + uint16 ZonePort = 54230; if( Sql_Query(SqlHandle,fmtQuery,charid) != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 ) { Sql_NextRow(SqlHandle); - if (Sql_GetIntData(SqlHandle,3) == 0) key3[16] += 6; + if (Sql_GetIntData(SqlHandle,4) == 0) key3[16] += 6; - ZoneIP = Sql_GetUIntData(SqlHandle,0); - ZonePort = (uint16)Sql_GetUIntData(SqlHandle,1); - uint8 ZoneID = (uint8)Sql_GetUIntData(SqlHandle,2); - WBUFL(ReservePacket,(0x38)) = ZoneIP; - WBUFW(ReservePacket,(0x3C)) = ZonePort; - ShowInfo("lobbydata_parse: zoneid:(%u),zoneip:(%s),zoneport:(%u) for char:(%u)\n",ZoneID,ip2str(ntohl(ZoneIP),NULL),ZonePort,charid); - }else{ + ZoneLANIP = Sql_GetUIntData(SqlHandle,0); + ZoneWANIP = Sql_GetUIntData(SqlHandle,1); + ZonePort = (uint16)Sql_GetUIntData(SqlHandle,2); + uint8 ZoneID = (uint8)Sql_GetUIntData(SqlHandle,3); + + if(wildcmp(login_config.lan_ipmask,ip2str(sd->client_addr,NULL))) + { + ShowInfo("lobbydata_parse: Using LAN IP Settings \n"); + WBUFL(ReservePacket,(0x38)) = ZoneLANIP; // map-server ip + WBUFW(ReservePacket,(0x3C)) = ZonePort; // map-server port + WBUFL(ReservePacket,(0x40)) = sd->servip; // search-server ip + //WBUFW(ReservePacket,(0x44)) = SearchPort; // search-server port + } + else + { + ShowInfo("lobbydata_parse: Using WAN IP Settings \n"); + WBUFL(ReservePacket,(0x38)) = ZoneWANIP; // map-server ip + WBUFW(ReservePacket,(0x3C)) = ZonePort; // map-server port + WBUFL(ReservePacket,(0x40)) = sd->servip; // search-server ip + //WBUFW(ReservePacket,(0x44)) = SearchPort; // search-server port + } + ShowInfo("lobbydata_parse: zoneid:(%u),zoneport:(%u) for char:(%u)\n",ZoneID,ZonePort,charid); + ShowInfo("lobbydata_parse: WAN IP:(%s)\n",ip2str(ntohl(ZoneWANIP),NULL)); + ShowInfo("lobbydata_parse: LAN IP:(%s)\n",ip2str(ntohl(ZoneLANIP),NULL)); + } + else + { ShowWarning("lobbydata_parse: zoneip:(%s) for char:(%u) is standard\n",ip2str(sd->servip,NULL),charid); WBUFL(ReservePacket,(0x38)) = sd->servip; // map-server ip - //WBUFW(ReservePacket,(0x3C)) = port; // map-server port + WBUFW(ReservePacket,(0x3C)) = ZonePort; // map-server port + WBUFL(ReservePacket,(0x40)) = sd->servip; // search-server ip + //WBUFW(ReservePacket,(0x44)) = SearchPort; // search-server port } - WBUFL(ReservePacket,(0x40)) = sd->servip; // search-server ip - //WBUFW(ReservePacket,(0x44)) = port; // search-server port memcpy(MainReservePacket,ReservePacket,RBUFB(ReservePacket,0)); - // необходиму одалять сессию, необработанную игровым сервером + // necessary to remove the session, the raw game server Sql_Query(SqlHandle,"DELETE FROM accounts_sessions WHERE accid = %u and client_port = 0", sd->accid); int8 session_key[sizeof(key3)*2+1]; @@ -300,14 +321,29 @@ fmtQuery = "INSERT INTO accounts_sessions(accid,charid,session_key,server_addr,server_port,client_addr) VALUES(%u,%u,x'%s',%u,%u,%u)"; - if( Sql_Query(SqlHandle, fmtQuery, sd->accid, charid, session_key, ZoneIP, ZonePort, sd->client_addr) == SQL_ERROR ) + if(wildcmp(login_config.lan_ipmask,ip2str(sd->client_addr,NULL))) { - //отправляем клиенту сообщение об ошибке - LOBBBY_ERROR_MESSAGE(ReservePacket); - // устанавливаем код ошибки - // Unable to connect to world server. Specified operation failed - WBUFW(ReservePacket,32) = 305; - memcpy(MainReservePacket,ReservePacket,RBUFB(ReservePacket,0)); + if( Sql_Query(SqlHandle, fmtQuery, sd->accid, charid, session_key, ZoneLANIP, ZonePort, sd->client_addr) == SQL_ERROR ) + { + //send an error message to the client + LOBBBY_ERROR_MESSAGE(ReservePacket); + // set the error code + // Unable to connect to world server. Specified operation failed + WBUFW(ReservePacket,32) = 305; + memcpy(MainReservePacket,ReservePacket,RBUFB(ReservePacket,0)); + } + } + else + { + if( Sql_Query(SqlHandle, fmtQuery, sd->accid, charid, session_key, ZoneWANIP, ZonePort, sd->client_addr) == SQL_ERROR ) + { + //send an error message to the client + LOBBBY_ERROR_MESSAGE(ReservePacket); + // set the error code + // Unable to connect to world server. Specified operation failed + WBUFW(ReservePacket,32) = 305; + memcpy(MainReservePacket,ReservePacket,RBUFB(ReservePacket,0)); + } } unsigned char Hash[16]; @@ -324,12 +360,12 @@ RFIFOFLUSH(sd->login_lobbyview_fd); if (SendBuffSize == 0x24){ - // выходим в случае ошибки без разрыва соединения + // leave in case of an error without disconnection return -1; } do_close_tcp(sd->login_lobbyview_fd); - ShowStatus("lobbydata_parse: client %s finished work with " CL_GREEN"lobbyview" CL_RESET"\n",ip2str(sd->client_addr,NULL)); + ShowStatus("lobbydata_parse: client %s finished work with "CL_GREEN"lobbyview" CL_RESET"\n",ip2str(sd->client_addr,NULL)); break; } default: @@ -431,11 +467,11 @@ LOBBY_026_RESERVEPACKET(ReservPacket); WBUFW(ReservPacket,32) = login_config.expansions; // BitMask for expansions; - //Хеширование пакета, и запись значения Хеш функции в пакет + //Hashing package, and write the value hash functions in a package unsigned char Hash[16]; md5(ReservPacket, Hash, SendBuffSize); memcpy(ReservPacket+12,Hash,16); - //Запись итогового пакета + //Record the final package memcpy(session[fd]->wdata,ReservPacket,SendBuffSize); RFIFOSKIP(fd,session[fd]->rdata_size); @@ -468,8 +504,8 @@ RFIFOSKIP(fd,session[fd]->rdata_size); RFIFOFLUSH(fd); - //Выполнение удаления персонажа из основных таблиц - //Достаточно удалить значение из таблицы chars, все остальное сделает mysql-сервер + // Execute the removal of the character of the main table + // Just remove the value from the table chars, everything else will make mysql-server const char *pfmtQuery = "DELETE FROM chars WHERE charid = %i"; Sql_Query(SqlHandle,pfmtQuery,CharID); @@ -587,10 +623,10 @@ { ShowWarning(CL_WHITE"lobbyview_parse:" CL_RESET" character name " CL_WHITE"<%s>" CL_RESET"already taken\n",CharName); LOBBBY_ERROR_MESSAGE(ReservePacket); - // устанавливаем код ошибки + //set the error code // The character name you entered is unavailable. Please choose another name. - // сообщение отображается на японском + // message is displayed in Japanese WBUFW(ReservePacket,32) = 313; memcpy(MainReservePacket,ReservePacket,sendsize); }else{ @@ -639,7 +675,7 @@ int32 lobby_createchar(login_session_data_t *loginsd, char *buf) { - // инициализируем генератор случайных чисел + // initialize the random number generator srand(clock()); char_mini createchar; @@ -680,7 +716,22 @@ { Sql_NextRow(SqlHandle); - CharID = (uint32)Sql_GetUIntData(SqlHandle,0) + 1; + if(wildcmp(login_config.lan_ipmask,ip2str(loginsd->client_addr,NULL))) + { + if((uint32)Sql_GetUIntData(SqlHandle,0) > 40000) + { + CharID = (uint32)Sql_GetUIntData(SqlHandle,0) - 20000 + 1; + } + else + { + CharID = (uint32)Sql_GetUIntData(SqlHandle,0) + 1; + } + } + else + { + CharID = (uint32)Sql_GetUIntData(SqlHandle,0) + 20001; + } + } CharID = (CharID < 21828 ? 21828 : CharID); Index: src/login/login.cpp =================================================================== --- src/login/login.cpp (revision 3520) +++ src/login/login.cpp (working copy) @@ -322,6 +322,10 @@ { login_config_read(w2); } + else if (strcmp(w1, "lan_ipmask" ) == 0) + { + login_config.lan_ipmask = aStrdup(w2); + } else { ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); Index: src/login/login.h =================================================================== --- src/login/login.h (revision 3520) +++ src/login/login.h (working copy) @@ -57,6 +57,8 @@ const char* mysql_login; // mysql login -> default root const char* mysql_password; // mysql pass -> default NULL const char* mysql_database; // mysql database -> default dspdb + + const char* lan_ipmask; }; extern login_config_t login_config; Index: src/map/ability.cpp =================================================================== --- src/map/ability.cpp (revision 3520) +++ src/map/ability.cpp (working copy) @@ -193,7 +193,7 @@ /************************************************************************ * * -* Получаем/Устанавливаем сообщение способности * +* Set / get message capacity * * * ************************************************************************/ @@ -261,7 +261,7 @@ /************************************************************************ * * -* Реализация namespase для работы со способностями * +* Implementing namespase ability to work with * * * ************************************************************************/ @@ -269,7 +269,7 @@ { CAbility* PAbilityList[MAX_ABILITY_ID]; // Complete Abilities List std::vector PAbilitiesList[MAX_JOBTYPE]; // Abilities List By Job Type - std::vector PChargesList; // Abilities with charges + std::vector PChargesList; // Abilities with charges /************************************************************************ * * @@ -279,7 +279,7 @@ void LoadAbilitiesList() { - // TODO: добавить поле message в таблицу + // TODO: add the message field to the table memset(PAbilityList,0,sizeof(PAbilityList)); @@ -373,7 +373,7 @@ /************************************************************************ * * - * Получаем основную способность профессии * + * The ability to obtain the main occupation * * * ************************************************************************/ Index: src/map/ability.h =================================================================== --- src/map/ability.h (revision 3520) +++ src/map/ability.h (working copy) @@ -43,7 +43,7 @@ enum ABILITY { ABILITY_MIGHTY_STRIKES = 0, - ABILITY_HUNDRED_FISTS = 1, + ABILITY_HUNDRED_FISTS = 1, ABILITY_BENEDICTION = 2, ABILITY_MANAFONT = 3, ABILITY_CHAINSPELL = 4, @@ -107,6 +107,7 @@ ABILITY_REWARD = 62, ABILITY_COVER = 63, ABILITY_SPIRIT_LINK = 64, + ABILITY_ENRAGE = 65, ABILITY_CHI_BLAST = 66, ABILITY_CONVERT = 67, ABILITY_ACCOMPLICE = 68, @@ -143,6 +144,11 @@ ABILITY_PUPPET_ROLL = 99, ABILITY_DANCERS_ROLL = 100, ABILITY_SCHOLARS_ROLL = 101, + ABILITY_BOLTERS_ROLL = 102, + ABILITY_CASTERS_ROLL = 103, + ABILITY_COURSERS_ROLL = 104, + ABILITY_BLITZERS_ROLL = 105, + ABILITY_TACTICIANS_ROLL = 106, ABILITY_DOUBLE_UP = 107, ABILITY_QUICK_DRAW = 108, ABILITY_FIRE_SHOT = 109, @@ -154,6 +160,7 @@ ABILITY_LIGHT_SHOT = 115, ABILITY_DARK_SHOT = 116, ABILITY_RANDOM_DEAL = 117, + // . = 118, ABILITY_OVERDRIVE = 119, ABILITY_ACTIVATE = 120, ABILITY_REPAIR = 121, @@ -247,8 +254,10 @@ ABILITY_SNARL = 209, ABILITY_RETALIATION = 210, ABILITY_FOOTWORK = 211, + ABILITY_DESPOIL = 212, ABILITY_PIANISSIMO = 213, ABILITY_SEKKANOKI = 214, + // . = 215, ABILITY_ELEMENTAL_SIPHON = 216, ABILITY_SUBLIMATION = 217, ABILITY_ADDENDUM_WHITE = 218, @@ -267,90 +276,101 @@ ABILITY_COMPOSURE = 231, ABILITY_YONIN = 232, ABILITY_INNIN = 233, - ABILITY_AVATARS_FAVOR = 234, - ABILITY_READY = 235, - ABILITY_RESTRAINT = 236, - ABILITY_PERFECT_COUNTER = 237, - ABILITY_MANA_WALL = 238, - ABILITY_DIVINE_EMBLEM = 239, - ABILITY_NETHER_VOID = 240, - ABILITY_DOUBLE_SHOT = 241, - ABILITY_SENGIKORI = 242, - ABILITY_FUTAE = 243, - ABILITY_SPIRIT_JUMP = 244, - ABILITY_PRESTO = 245, - ABILITY_DIVINE_WALTZ_II = 246, - ABILITY_FLOURISHES_III = 247, - ABILITY_CLIMACTIC_FLOURISH = 248, - ABILITY_LIBRA = 249, - ABILITY_TACTICAL_SWITCH = 250, - ABILITY_BLOOD_RAGE = 251, - ABILITY_IMPETUS = 253, - ABILITY_DIVINE_CARESS = 254, - ABILITY_SANCROSANCTITY = 255, - ABILITY_ENMITY_DOUSE = 256, - ABILITY_MANAWELL = 257, - ABILITY_SABOTEUR = 258, - ABILITY_SPONTANEITY = 259, - ABILITY_CONSPIRATOR = 260, - ABILITY_SEPULCHER = 261, - ABILITY_PALISADE = 262, - ABILITY_ARCANE_CREST = 263, - ABILITY_SCARLET_DELIRIUM = 264, - ABILITY_SPUR = 265, - ABILITY_RUN_WILD = 266, - ABILITY_TENUTO = 267, - ABILITY_MARCATO = 268, - ABILITY_BOUNTY_SHOT = 269, - ABILITY_DECOY_SHOT = 270, - ABILITY_HAMANOHA = 271, - ABILITY_HAGAKURE = 272, - ABILITY_ISSEKIGAN = 275, - ABILITY_DRAGON_BREAKER = 276, - ABILITY_SOUL_JUMP = 277, - ABILITY_STEADY_WING = 279, - ABILITY_MANA_CEDE = 280, - ABILITY_EFFLUX = 281, - ABILITY_UNBRIDLED_LEARNING = 282, - ABILITY_TRIPLE_SHOT = 285, - ABILITY_ALLIES_ROLL = 286, - ABILITY_MISER_S_ROLL = 287, - ABILITY_COMPANION_S_ROLL = 288, - ABILITY_AVENGER_S_ROLL = 289, - ABILITY_COOLDOWN = 293, - ABILITY_DEUX_EX_AUTOMATA = 294, - ABILITY_CURING_WALTZ_V = 295, - ABILITY_FEATHER_STEP = 296, - ABILITY_STRIKING_FLOURISH = 297, - ABILITY_TERNARY_FLOURISH = 298, - ABILITY_PERPETUANCE = 300, - ABILITY_IMMANENCE = 301, - ABILITY_SMITING_BREATH = 302, - ABILITY_RESTORING_BREATH = 303, - ABILITY_KONZEN_ITTAI = 304, - ABILITY_BULLY = 305, - ABILITY_MAINTENANCE = 306, - //ABILITY_WAR_SP2 = 307, - //ABILITY_MNK_SP2 = 308, - //ABILITY_ASYLUM = 309, - //ABILITY_SUBLTE_SORCERY = 310, //yes, subtle is misspelled - //ABILITY_RDM_SP2 = 311, - //ABILITY_THF_SP2 = 312, - //ABILITY_PLD_SP2 = 313, - //ABILITY_SOUL_ENSLAVEMENT = 314, - //ABILITY_BST_SP2 = 315, - //ABILITY_BRD_SP2 = 316, - //ABILITY_RNG_SP2 = 317, - //ABILITY_YAEGASUMI = 318, - //ABILITY_NIN_SP2 = 319, - //ABILITY_DSG_SP2 = 320, - //ABILITY_ASTRAL_CONDUIT = 321, - //ABILITY_UNBRIDLED_WISDOM = 322, - //ABILITY_COR_SP2 = 323, - //ABILITY_HEADY_ARTIFICE = 324, - //ABILITY_GRAND_PAS = 325, - //ABILITY_CAPER_EMISSARIUS = 326, + ABILITY_AVATARS_FAVOR = 234, + ABILITY_READY = 235, + ABILITY_RESTRAINT = 236, + ABILITY_PERFECT_COUNTER = 237, + ABILITY_MANA_WALL = 238, + ABILITY_DIVINE_EMBLEM = 239, + ABILITY_NETHER_VOID = 240, + ABILITY_DOUBLE_SHOT = 241, + ABILITY_SENGIKORI = 242, + ABILITY_FUTAE = 243, + ABILITY_SPIRIT_JUMP = 244, + ABILITY_PRESTO = 245, + ABILITY_DIVINE_WALTZ_II = 246, + ABILITY_FLOURISHES_III = 247, + ABILITY_CLIMACTIC_FLOURISH = 248, + ABILITY_LIBRA = 249, + ABILITY_TACTICAL_SWITCH = 250, + ABILITY_BLOOD_RAGE = 251, + // . = 252, + ABILITY_IMPETUS = 253, + ABILITY_DIVINE_CARESS = 254, + ABILITY_SANCROSANCTITY = 255, + ABILITY_ENMITY_DOUSE = 256, + ABILITY_MANAWELL = 257, + ABILITY_SABOTEUR = 258, + ABILITY_SPONTANEITY = 259, + ABILITY_CONSPIRATOR = 260, + ABILITY_SEPULCHER = 261, + ABILITY_PALISADE = 262, + ABILITY_ARCANE_CREST = 263, + ABILITY_SCARLET_DELIRIUM = 264, + ABILITY_SPUR = 265, + ABILITY_RUN_WILD = 266, + ABILITY_TENUTO = 267, + ABILITY_MARCATO = 268, + ABILITY_BOUNTY_SHOT = 269, + ABILITY_DECOY_SHOT = 270, + ABILITY_HAMANOHA = 271, + ABILITY_HAGAKURE = 272, + // . = 273, + // . = 274, + ABILITY_ISSEKIGAN = 275, + ABILITY_DRAGON_BREAKER = 276, + ABILITY_SOUL_JUMP = 277, + // . = 278, + ABILITY_STEADY_WING = 279, + ABILITY_MANA_CEDE = 280, + ABILITY_EFFLUX = 281, + ABILITY_UNBRIDLED_LEARNING = 282, + // . = 283, + // . = 284, + ABILITY_TRIPLE_SHOT = 285, + ABILITY_ALLIES_ROLL = 286, + ABILITY_MISERS_ROLL = 287, + ABILITY_COMPANIONS_ROLL = 288, + ABILITY_AVENGERS_ROLL = 289, + // . = 290, + // . = 291, + // . = 292, + ABILITY_COOLDOWN = 293, + ABILITY_DEUX_EX_AUTOMATA = 294, + ABILITY_CURING_WALTZ_V = 295, + ABILITY_FEATHER_STEP = 296, + ABILITY_STRIKING_FLOURISH = 297, + ABILITY_TERNARY_FLOURISH = 298, + // . = 299, + ABILITY_PERPETUANCE = 300, + ABILITY_IMMANENCE = 301, + ABILITY_SMITING_BREATH = 302, + ABILITY_RESTORING_BREATH = 303, + ABILITY_KONZEN_ITTAI = 304, + ABILITY_BULLY = 305, + ABILITY_MAINTENANCE = 306, + //ABILITY_WAR_SP2 = 307, + //ABILITY_MNK_SP2 = 308, + //ABILITY_ASYLUM = 309, + //ABILITY_SUBLTE_SORCERY = 310, //yes, subtle is misspelled + //ABILITY_RDM_SP2 = 311, + //ABILITY_THF_SP2 = 312, + //ABILITY_PLD_SP2 = 313, + //ABILITY_SOUL_ENSLAVEMENT = 314, + //ABILITY_BST_SP2 = 315, + //ABILITY_BRD_SP2 = 316, + //ABILITY_RNG_SP2 = 317, + //ABILITY_YAEGASUMI = 318, + //ABILITY_NIN_SP2 = 319, + //ABILITY_DSG_SP2 = 320, + //ABILITY_ASTRAL_CONDUIT = 321, + //ABILITY_UNBRIDLED_WISDOM = 322, + //ABILITY_COR_SP2 = 323, + //ABILITY_HEADY_ARTIFICE = 324, + //ABILITY_GRAND_PAS = 325, + //ABILITY_CAPER_EMISSARIUS = 326, ABILITY_BOLSTER = 327, + // . = 328, ABILITY_FULL_CIRCLE = 329, ABILITY_LASTING_EMANATION = 330, ABILITY_ECLIPTIC_ATTRITION = 331, @@ -360,6 +380,8 @@ ABILITY_DEMATERIALIZE = 335, ABILITY_THEURGIC_FOCUS = 336, ABILITY_CONCENTRIC_PULSE = 337, + // . = 338, + // . = 339, ABILITY_ELEMENTAL_SFORZO = 340, ABILITY_RUNE_ENCHANTMENT = 341, ABILITY_IGNIS = 342, @@ -379,8 +401,14 @@ ABILITY_GAMBIT = 356, ABILITY_LIEMENT = 357, ABILITY_ONE_FOR_ALL = 358, + // . = 359, + // . = 360, + // . = 361, + // . = 362, ABILITY_WARD = 363, ABILITY_EFFUSION = 364, + ABILITY_CHOCOBO_JIG_II = 365, + ABILITY_HEALING_RUBY = 496, ABILITY_POISON_NAILS = 497, ABILITY_SHINING_RUBY = 498, @@ -388,6 +416,9 @@ ABILITY_METEORITE = 500, ABILITY_HEALING_RUBY_II = 501, ABILITY_SEARING_LIGHT = 502, + ABILITY_HOLY_MIST = 503, + ABILITY_SOOTHING_RUBY = 504, + ABILITY_MOONLIT_CHARGE = 512, ABILITY_CRESCENT_FANG = 513, ABILITY_LUNAR_CRY = 514, @@ -395,7 +426,11 @@ ABILITY_ECLIPTIC_GROWL = 516, ABILITY_ECLIPTIC_HOWL = 517, ABILITY_ECLIPSE_BITE = 518, + ABILITY_HOWLING_MOON = 520, + ABILITY_LUNAR_BAY = 521, + ABILITY_HEAVENWARD_HOWL = 522, + ABILITY_PUNCH = 528, ABILITY_FIRE_II = 529, ABILITY_BURNING_STRIKE = 530, @@ -405,6 +440,8 @@ ABILITY_FLAMING_CRUSH = 534, ABILITY_METEOR_STRIKE = 535, ABILITY_INFERNO = 536, + ABILITY_INFERNO_HOWL = 537, + ABILITY_ROCK_THROW = 544, ABILITY_STONE_II = 545, ABILITY_ROCK_BUSTER = 546, @@ -414,6 +451,8 @@ ABILITY_MOUNTAIN_BUSTER = 550, ABILITY_GEOCRUSH = 551, ABILITY_EARTHEN_FURY = 552, + ABILITY_EARTHEN_ARMOR = 553, + ABILITY_BARRACUDA_DIVE = 560, ABILITY_WATER_II = 561, ABILITY_TAIL_WHIP = 562, @@ -423,6 +462,8 @@ ABILITY_SPINNING_DIVE = 566, ABILITY_GRAND_FALL = 567, ABILITY_TIDAL_WAVE = 568, + ABILITY_TIDAL_ROAR = 569, + ABILITY_CLAW = 576, ABILITY_AERO_II = 577, ABILITY_WHISPERING_WIND = 578, @@ -432,6 +473,8 @@ ABILITY_PREDATOR_CLAWS = 582, ABILITY_WIND_BLADE = 583, ABILITY_AERIAL_BLAST = 584, + ABILITY_FLEET_WIND = 585, + ABILITY_AXE_KICK = 592, ABILITY_BLIZZARD_II = 593, ABILITY_FROST_ARMOR = 594, @@ -441,18 +484,36 @@ ABILITY_RUSH = 598, ABILITY_HEAVENLY_STRIKE = 599, ABILITY_DIAMOND_DUST = 600, + ABILITY_DIAMOND_STORM = 601, + ABILITY_SHOCK_STRIKE = 608, ABILITY_THUNDER_II = 609, + ABILITY_ROLLING_THUNDER = 610, ABILITY_THUNDERSPARK = 611, - ABILITY_ROLLING_THUNDER = 610, ABILITY_LIGHTNING_ARMOR = 612, ABILITY_THUNDER_IV = 613, ABILITY_CHAOTIC_STRIKE = 614, ABILITY_THUNDERSTORM = 615, - ABILITY_JUDGMENT_BOLT = 616 + ABILITY_JUDGMENT_BOLT = 616, + ABILITY_SHOCK_SQUALL = 617, + + ABILITY_CAMISADO = 640, + ABILITY_SOMNOLENCE = 641, + ABILITY_NIGHTMARE = 642, + ABILITY_ULTIMATE_TERROR = 643, + ABILITY_NOCTOSHIELD = 644, + ABILITY_DREAM_SHROUD = 645, + ABILITY_NETHER_BLAST = 646, + ABILITY_CACODEMONIA = 647, + ABILITY_RUINOUS_OMEN = 648, + ABILITY_NIGHT_TERROR = 649, + ABILITY_PAVOR_NOCTURNUS = 650, + + ABILITY_ZANTETSUKEN = 654, + ABILITY_PERFECT_DEFENSE = 655 }; -#define MAX_ABILITY_ID 617 +#define MAX_ABILITY_ID 656 struct Charge_t { @@ -539,7 +600,7 @@ /************************************************************************ * * -* namespase для работы со способностями * +* namespase to work with the abilities * * * ************************************************************************/ Index: src/map/ai/ai_char_normal.cpp =================================================================== --- src/map/ai/ai_char_normal.cpp (revision 3520) +++ src/map/ai/ai_char_normal.cpp (working copy) @@ -60,8 +60,8 @@ /************************************************************************ * * -* Инициализируем владельца интеллекта (может добавить проверку на * -* пустой указатель с выводом FatalError ?) * +* Initialize the owner of the intellectual (can add a check on the * +* null pointer with output FatalError ?) * * * ************************************************************************/ @@ -75,7 +75,7 @@ /************************************************************************ * * -* Основная часть интеллекта - главный цикл * +* The bulk of intelligence - the main loop * * * ************************************************************************/ @@ -232,7 +232,7 @@ /************************************************************************ * * -* Персонаж переходит в боевую стойку, включается прежим атаки * +* The character goes into a fighting stance, included attack mode * * * ************************************************************************/ @@ -245,7 +245,7 @@ { if(IsMobOwner(m_PBattleTarget)) { - if (distance(m_PChar->loc.p, m_PBattleTarget->loc.p) <= 30) + if (distance(m_PChar->loc.p, m_PBattleTarget->loc.p) <= 30*map_config.engage_dist_mod) { if ((m_Tick - m_LastMeleeTime) > m_PChar->m_Weapons[SLOT_MAIN]->getDelay()) { @@ -293,7 +293,7 @@ /************************************************************************ * * -* Персонаж меняет основную цель атаки * +* The main character is changing their target of attack * * * ************************************************************************/ @@ -310,7 +310,7 @@ { if (IsMobOwner(PBattleTarget)) { - if (distance(m_PChar->loc.p, PBattleTarget->loc.p) <= 30) + if (distance(m_PChar->loc.p, PBattleTarget->loc.p) <= 30*map_config.engage_dist_mod) { m_LastActionTime = m_Tick; m_PBattleTarget = PBattleTarget; @@ -334,7 +334,7 @@ /************************************************************************ * * -* Персонаж выходит из режима атаки по каким-либо причинам * +* Character exits attack for some reason * * * ************************************************************************/ @@ -352,7 +352,7 @@ /************************************************************************ * * -* Смерть персонажа * +* character death * * * ************************************************************************/ @@ -387,13 +387,13 @@ /************************************************************************ * * -* Удаляем соответствующие эффекты с ожиданием в одну секунду * +* Remove the corresponding effects with the expectation of one second * * * ************************************************************************/ void CAICharNormal::ActionDeath() { - // без задержки удаление эффектов не всегда правильно обрабатывается клиентом + // Immediately remove the effects are not always properly handled by the client if ((m_Tick - m_LastActionTime) >= 1000) { m_PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DEATH); @@ -422,7 +422,7 @@ * * ************************************************************************/ -// TODO: нет проверки на наличие зарядов у предмета (в случае использования экипировки) +// TODO: there is no check for the charges of the object (in the case of equipment) void CAICharNormal::ActionItemStart() { @@ -495,7 +495,7 @@ /************************************************************************ * * -* Процесс использовани предмета * +* The process of using the item * * * ************************************************************************/ @@ -516,7 +516,7 @@ if ((m_Tick - m_LastActionTime) >= m_PItemUsable->getActivationTime()) { - // обновление времени необходимо для правильной работы задержки анимации + // update the time required for proper operation of the delay animation m_LastMeleeTime += (m_Tick - m_LastActionTime); m_LastActionTime = m_Tick; m_ActionType = ACTION_ITEM_FINISH; @@ -550,7 +550,7 @@ } m_PItemUsable = new CItemUsable(*m_PItemUsable); } - else // разблокируем все предметы, кроме экипирвоки + else // unlock all items, except for equipment { m_PItemUsable->setSubType(ITEM_UNLOCKED); m_PItemUsable = new CItemUsable(*m_PItemUsable); @@ -580,8 +580,8 @@ /************************************************************************ * * -* Окончание использования предмета. * -* Сюда попадает копия предмета, которую нужно удалить. * +* Ending the use of the object. * +* Here gets a copy of the object to be deleted. * * * ************************************************************************/ @@ -592,7 +592,7 @@ if ((m_Tick - m_LastActionTime) >= m_PItemUsable->getAnimationTime()) { - if(battleutils::IsParalised(m_PChar)){ + if(battleutils::IsParalyzed(m_PChar)){ m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar,m_PBattleSubTarget,0,0,MSGBASIC_IS_PARALYZED)); } else { @@ -665,13 +665,14 @@ /************************************************************************ * * -* Начало дальней атаки. Логика: * -* - если цель мертва, то атака не начинается. никаких сообщений * -* - проверяем видимость цели (если не видим, то не можем определить * -* дистанцию до цели или узнать, в бою ли цель) * -* - определяем в бою ли цель (нет смысла определять дистанцию, если * -* цель атакует другой персонаж) * -* - и наконец определяем дистанцию до цели * +* Start a ranged attack. Logic: * +* - If the target is dead, the attack begins. no reports * +* - Check the visibility of the target (if you do not see, we can not * +* determine distance to the target or to find out whether the * +* purpose in battle) * +* - In a battle to determine the target (not relevant to determine * +* the distance, if purpose of attacking another character) * +* - And finally determine the distance to the target * * * ************************************************************************/ @@ -800,7 +801,7 @@ m_PBattleSubTarget = NULL; return; } - if (distance(m_PChar->loc.p, m_PBattleSubTarget->loc.p) > 25) + if (distance(m_PChar->loc.p, m_PBattleSubTarget->loc.p) > 25*map_config.ranged_dist_mod) { m_PChar->pushPacket(new CMessageBasicPacket(m_PChar,m_PBattleSubTarget,0,0,MSGBASIC_TOO_FAR_AWAY)); @@ -816,7 +817,7 @@ return; } - // TODO: скорее всего m_LastActionTime нужно выставлять лишь при ANIMATION_ATTACK, иначе использовать LastRangedTime для + // TODO: m_LastActionTime likely to exhibit only at ANIMATION_ATTACK, otherwise use for LastRangedTime m_LastActionTime = m_Tick; m_PChar->m_StartActionPos = m_PChar->loc.p; @@ -841,7 +842,7 @@ /************************************************************************ * * -* Окончание дальней атаки * +* Closing ranged attack * * * ************************************************************************/ @@ -944,6 +945,11 @@ if(rand()%100 < battleutils::GetCritHitRate(m_PChar,m_PBattleSubTarget, true)) { pdif *= 1.25; //uncapped + if(m_PChar->getMod(MOD_DEAD_AIM) > 0) + { + pdif *= (float)(1.0f + m_PChar->getMod(MOD_DEAD_AIM)/100.0f); + // ShowDebug(CL_CYAN"Dead Aim Proc PDIF: %g \n", pdif); + } Action.speceffect = SPECEFFECT_CRITICAL_HIT; Action.messageID = 353; } @@ -961,7 +967,7 @@ if(slot == SLOT_RANGED) { - damage = battleutils::CheckForDamageMultiplier(PItem,damage, 0); + damage = battleutils::CheckForDamageMultiplier(PItem,damage, 0,m_PChar); if(PItem != NULL) { @@ -1066,8 +1072,8 @@ m_ActionType = (m_PChar->animation == ANIMATION_ATTACK ? ACTION_ATTACK : ACTION_NONE); - // TODO: что это ? .... - // если не ошибаюсь, то TREASURE_HUNTER работает лишь при последнем ударе + // TODO: what is this? .... + // If I am not mistaken, the TREASURE_HUNTER works only when the last stroke CMobEntity* Monster = (CMobEntity*)m_PBattleSubTarget; @@ -1218,7 +1224,7 @@ { if (m_PBattleSubTarget->isDead() && !(m_PSpell->getValidTarget() & TARGET_PLAYER_DEAD)) { - MagicStartError(0); // TODO: узнать сообщение + MagicStartError(0); // TODO: find a message return; } if (m_PBattleSubTarget->objtype == TYPE_MOB && !IsMobOwner(m_PBattleSubTarget)) @@ -1233,14 +1239,24 @@ MagicStartError(35); return; } + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_FUTAE)) + { + CItemWeapon* PAmmo = (CItemWeapon*)m_PChar->getStorage(LOC_INVENTORY)->GetItem(m_PChar->equip[SLOT_AMMO]); + if( (PAmmo->getQuantity()-2) < 1) + MagicStartError(35); + return; + } } else { uint16 cost = charutils::CalculateManaCost(m_PChar, m_PSpell); if (cost > m_PChar->health.mp && !m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAFONT)) { - MagicStartError(34); - return; + if (cost > m_PChar->health.mp && !m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAWELL)) + { + MagicStartError(34); + return; + } } } } @@ -1259,12 +1275,12 @@ { float Distance = distance(m_PChar->loc.p, m_PBattleSubTarget->loc.p); - if (Distance > 25) + if (Distance > 25*map_config.magic_dist_mod) { MagicStartError(78); return; } - if (Distance > 21.5) + if (Distance > 21.5*map_config.magic_dist_mod) { MagicStartError(313); return; @@ -1302,7 +1318,7 @@ /************************************************************************ * * -* Невозможно начать читать заклинание * +* Can not start to cast * * * ************************************************************************/ @@ -1351,7 +1367,7 @@ uint32 totalCastTime = charutils::CalculateSpellcastTime(m_PChar, m_PSpell); if (m_Tick - m_LastActionTime >= totalCastTime || - m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_CHAINSPELL)) + m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_CHAINSPELL) || m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SPONTANEITY)) { if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SILENCE) || m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MUTE)) @@ -1361,7 +1377,7 @@ ActionMagicInterrupt(); return; } - else if (battleutils::IsParalised(m_PChar)) + else if (battleutils::IsParalyzed(m_PChar)) { m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar,m_PBattleSubTarget,0,0,MSGBASIC_IS_PARALYZED)); m_ActionType = ACTION_MAGIC_INTERRUPT; @@ -1387,9 +1403,9 @@ } //the check for player position only occurs AFTER the cast time is up, you can move so long as x/z is the same on finish. //furthermore, it's actually quite lenient, hence the rounding to 1 dp - if (floorf(m_PChar->m_StartActionPos.x * 10 + 0.5) / 10 != floorf(m_PChar->loc.p.x * 10 + 0.5) / 10 || + if (map_config.magic_movement == 0 && (floorf(m_PChar->m_StartActionPos.x * 10 + 0.5) / 10 != floorf(m_PChar->loc.p.x * 10 + 0.5) / 10 || floorf(m_PChar->m_StartActionPos.z * 10 + 0.5) / 10 != floorf(m_PChar->loc.p.z * 10 + 0.5) / 10 || - m_PChar->StatusEffectContainer->HasPreventActionEffect()) + m_PChar->StatusEffectContainer->HasPreventActionEffect())) { m_PChar->pushPacket(new CMessageBasicPacket(m_PChar, m_PChar, 0, 0, MSGBASIC_IS_INTERRUPTED)); @@ -1398,7 +1414,7 @@ return; } if ((m_PBattleSubTarget != m_PChar) && - (distance(m_PChar->loc.p,m_PBattleSubTarget->loc.p) > 21.5)) + (distance(m_PChar->loc.p,m_PBattleSubTarget->loc.p) > 21.5*map_config.magic_dist_mod)) { m_PChar->pushPacket(new CMessageBasicPacket(m_PChar,m_PBattleSubTarget,0,0,MSGBASIC_TOO_FAR_AWAY)); @@ -1423,21 +1439,36 @@ uint16 cost = charutils::CalculateManaCost(m_PChar, m_PSpell); if (cost > m_PChar->health.mp && !m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAFONT)) { - m_PChar->pushPacket(new CMessageBasicPacket(m_PChar,m_PChar,m_PSpell->getID(),0,MSGBASIC_NOT_ENOUGH_MP)); + if (cost > m_PChar->health.mp && !m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAWELL)) + { + m_PChar->pushPacket(new CMessageBasicPacket(m_PChar,m_PChar,m_PSpell->getID(),0,MSGBASIC_NOT_ENOUGH_MP)); - m_ActionType = ACTION_MAGIC_INTERRUPT; - ActionMagicInterrupt(); - return; + m_ActionType = ACTION_MAGIC_INTERRUPT; + ActionMagicInterrupt(); + return; + } } else { - if (!m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAFONT)) + if (!m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAFONT) || !m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAWELL)) { - m_PChar->addMP(-(int16)cost); + if(rand()%100 <= m_PChar->getMod(MOD_CONSERVE_MP)) + { + // MP Cost = floor(Old MP Cost * N / 16) N random 8-15 + m_PChar->addMP(-(floor((float)(((int16)cost * (float)(rand()%8 + 8)) / 16.0f)))); + // ShowDebug(CL_CYAN"Conserve MP Proc \n"); + } + else + { + m_PChar->addMP(-(int16)cost); + } } } } - + if (m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANAWELL)) + { + m_PChar->StatusEffectContainer->DelStatusEffect(EFFECT_MANAWELL); + } m_ActionType = ACTION_MAGIC_FINISH; ActionMagicFinish(); } @@ -1455,16 +1486,16 @@ m_PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_MAGIC_BEGIN); - if (!m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_CHAINSPELL)) + if (!m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_CHAINSPELL) || !m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SPONTANEITY)) { uint32 RecastTime = charutils::CalculateSpellRecastTime(m_PChar, m_PSpell); - + //needed so the client knows of the reduced recast time! m_PSpell->setModifiedRecast(RecastTime); m_PChar->PRecastContainer->Add(RECAST_MAGIC, m_PSpell->getID(), RecastTime); } - else //chainspell does have a small delay between casts sadly! + else //chainspell and spontaneity does have a small delay between casts sadly! { m_PSpell->setModifiedRecast(2000); m_PChar->PRecastContainer->Add(RECAST_MAGIC, m_PSpell->getID(), 2000); @@ -1522,6 +1553,17 @@ ce = m_PSpell->getCE(); ve = m_PSpell->getVE(); + + if ((m_PSpell->getID() >= 14 && m_PSpell->getID() <= 20) || m_PSpell->getID() == 94 || m_PSpell->getID() == 95 || m_PSpell->getID() == 143) // Status Ailment Recovery Spells (Divine Benison) + { + int16 DivineBenisonEnmityMod = m_PChar->getMod(MOD_DIVINE_BENISON_ENMITY); + if(DivineBenisonEnmityMod > 0) + { + ce = ce * ((float)(100+DivineBenisonEnmityMod)/100); + ve = ve * ((float)(100+DivineBenisonEnmityMod)/100); + // ShowDebug(CL_CYAN"Divine Benison Proc \n"); + } + } // take all shadows if(m_PSpell->canTargetEnemy() && aoeType > 0) @@ -1616,9 +1658,12 @@ m_PChar->m_ActionList.push_back(Action); } charutils::RemoveStratagems(m_PChar, m_PSpell); - // если заклинание атакующее, то дополнительно удаляем эффекты с флагом атаки + // If an attacking spell, then remove the additional effects to the flag attack m_PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_MAGIC_END | ((m_PSpell->getValidTarget() & TARGET_ENEMY) ? EFFECTFLAG_DETECTABLE : EFFECTFLAG_NONE)); - + if (m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SPONTANEITY)) + { + m_PChar->StatusEffectContainer->DelStatusEffect(EFFECT_SPONTANEITY); + } charutils::UpdateHealth(m_PChar); // only skill up if the effect landed @@ -1875,7 +1920,7 @@ } // check paralysis - if(battleutils::IsParalised(m_PChar)){ + if(battleutils::IsParalyzed(m_PChar)){ // display paralyzed m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar,m_PBattleSubTarget,0,0,MSGBASIC_IS_PARALYZED)); } else { @@ -1889,14 +1934,23 @@ m_PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_INVISIBLE); } - if(m_PJobAbility->getID() == ABILITY_REWARD){ - CItem* PItem = m_PChar->getStorage(LOC_INVENTORY)->GetItem(m_PChar->equip[SLOT_HEAD]); - if(PItem->getID() == 15157 || PItem->getID() == 16104){ - //TODO: Transform this into an item MOD_REWARD_RECAST perhaps ? - //The Bison Warbonnet & Khimaira Bonnet reduces recast time by 10 seconds. - RecastTime -= (10 *1000); // remove 10 seconds - } + if(m_PJobAbility->getID() == ABILITY_REWARD) + { + int16 RewardRecastMod = m_PChar->getMod(MOD_REWARD_RECAST); + RecastTime -= (RewardRecastMod *1000); // remove x seconds } + + if(m_PJobAbility->getID() == ABILITY_LIGHT_ARTS || m_PJobAbility->getID() == ABILITY_DARK_ARTS) + { + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_TABULA_RASA)) + { + RecastTime = 0; + } + else + { + RecastTime -= (m_PChar->PMeritPoints->GetMeritValue(MERIT_GRIMOIRE_RECAST,m_PChar) *1000); // remove x seconds + } + } apAction_t Action; m_PChar->m_ActionList.clear(); @@ -2068,7 +2122,7 @@ } } - // TODO: бардак. тоже выкинуть отсюда + // TODO: mess. also throw away else if (m_PJobAbility->isAvatarAbility()) { if (m_PChar->PPet != NULL) //is a bp - dont display msg and notify pet @@ -2081,17 +2135,39 @@ Action.flag = 0; Action.messageID = 0; - if(m_PJobAbility->getID() == ABILITY_SEARING_LIGHT || m_PJobAbility->getID() == ABILITY_AERIAL_BLAST || m_PJobAbility->getID() == ABILITY_EARTHEN_FURY){ - if(m_PChar->health.mp >= m_PChar->GetMLevel() * 2){ - m_PChar->addMP(-m_PChar->GetMLevel() * 2); + if(m_PJobAbility->getID() == ABILITY_SEARING_LIGHT || m_PJobAbility->getID() == ABILITY_AERIAL_BLAST || m_PJobAbility->getID() == ABILITY_EARTHEN_FURY) + { + if(m_PChar->health.mp >= m_PChar->GetMLevel() * 2) + { + if(rand()%100 <= m_PChar->getMod(MOD_BLOOD_BOON)) // Proc Check + { + // MP Cost = floor(Old MP Cost * N / 16) N random 8-15 max 50% decrease + m_PChar->addMP(-(floor((float)(((m_PChar->GetMLevel() * 2) * (rand()%8 + 8)) / 16.0f)))); + // ShowDebug(CL_CYAN"Blood Boon Proc \n"); + } + else + { + m_PChar->addMP(-m_PChar->GetMLevel() * 2); + } } - } else { - m_PChar->addMP(-m_PJobAbility->getAnimationID()); // TODO: ... + } + else + { + if(rand()%100 <= m_PChar->getMod(MOD_BLOOD_BOON)) + { + m_PChar->addMP(-(floor((float)((m_PJobAbility->getAnimationID() * (rand()%8 + 8)) / 16.0f)))); + // ShowDebug(CL_CYAN"Blood Boon Proc \n"); + } + else + { + m_PChar->addMP(-m_PJobAbility->getAnimationID()); // TODO: ... + } } + m_PChar->m_ActionList.push_back(Action); m_PChar->PPet->PBattleAI->SetBattleSubTarget(m_PBattleSubTarget); - ((CAIPetDummy*)m_PChar->PPet->PBattleAI)->m_MasterCommand = m_PJobAbility->getID(); // TODO: не допустимый подход + ((CAIPetDummy*)m_PChar->PPet->PBattleAI)->m_MasterCommand = m_PJobAbility->getID(); // TODO: not a valid approach m_PChar->PPet->PBattleAI->SetCurrentAction(ACTION_MOBABILITY_START); charutils::UpdateHealth(m_PChar); @@ -2185,7 +2261,7 @@ hitOccured = true; damage = (damage + m_PChar->GetRangedWeaponDmg() + battleutils::GetFSTR(m_PChar,m_PBattleSubTarget,SLOT_RANGED)) * pdif * 5; - damage = battleutils::CheckForDamageMultiplier(PItem,damage, 0); + damage = battleutils::CheckForDamageMultiplier(PItem,damage,0,m_PChar); damage = battleutils::RangedDmgTaken(m_PBattleSubTarget, damage); } @@ -2250,16 +2326,58 @@ Action.flag = 0; if( m_PJobAbility->getID() == ABILITY_SHADOWBIND ) - { - //Action.flag = 3; - } + { + uint16 damage = 0; + Action.ActionTarget = m_PBattleSubTarget; + Action.reaction = REACTION_HIT; + Action.speceffect = SPECEFFECT_HIT; //0x60 (SPECEFFECT_HIT + SPECEFFECT_RECOIL) + Action.animation = m_PJobAbility->getAnimationID();; + Action.messageID = MSGBASIC_USES_JA; + Action.flag = 3; + if(m_PBattleSubTarget->objtype == TYPE_MOB && ((CMobEntity*)m_PBattleSubTarget)->m_Type != MOBTYPE_NOTORIOUS) + { + uint8 shadowbindDur = 30; + if(m_PChar->getMod(MOD_SHADOWBIND) >= 1) + { + shadowbindDur = 45; + } + m_PBattleSubTarget->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_BIND,EFFECT_BIND,1,0,10)); + } + CItemWeapon* PAmmo = (CItemWeapon*)m_PChar->getStorage(LOC_INVENTORY)->GetItem(m_PChar->equip[SLOT_AMMO]); + uint8 recycleChance = m_PChar->getMod(MOD_RECYCLE); + if (charutils::hasTrait(m_PChar,TRAIT_RECYCLE)) + recycleChance += m_PChar->PMeritPoints->GetMeritValue(MERIT_RECYCLE,m_PChar); + + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_UNLIMITED_SHOT)) + { + m_PChar->StatusEffectContainer->DelStatusEffect(EFFECT_UNLIMITED_SHOT); + recycleChance = 100; + } + + if(PAmmo != NULL && rand()%100 > recycleChance) + { + if ( (PAmmo->getQuantity()-1) < 1) // ammo will run out after this shot, make sure we remove it from equip + { + uint8 slot = m_PChar->equip[SLOT_AMMO]; + charutils::UnequipItem(m_PChar,SLOT_AMMO); + charutils::UpdateItem(m_PChar, LOC_INVENTORY, slot, -1); + } + else + { + charutils::UpdateItem(m_PChar, LOC_INVENTORY, m_PChar->equip[SLOT_AMMO], -1); + } + } + m_PChar->pushPacket(new CInventoryFinishPacket()); + + } + /* TODO: Handle post-Lv. 75 genkai job abilities from support jobs that * deal damage points and defeats a monster while Blade of Darkness and/or * Blade of Death quests are active. */ - // handle jump abilities--- + // handle jump abilities--- // Jump if(m_PJobAbility->getID() == ABILITY_JUMP) @@ -2273,8 +2391,8 @@ else if (Action.param >= m_PBattleSubTarget->health.hp) { m_PChar->setWeaponSkillKill(true); - } } + } // High Jump else if(m_PJobAbility->getID() == ABILITY_HIGH_JUMP) { @@ -2287,8 +2405,8 @@ else if (Action.param >= m_PBattleSubTarget->health.hp) { m_PChar->setWeaponSkillKill(true); - } } + } // Super Jump else if(m_PJobAbility->getID() == ABILITY_SUPER_JUMP) { @@ -2296,6 +2414,26 @@ Action.messageID = 0; m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar, m_PBattleSubTarget, m_PJobAbility->getID()+16, 0, MSGBASIC_USES_JA)); } + // Spirit Jump + else if(m_PJobAbility->getID() == ABILITY_SPIRIT_JUMP) + { + Action.param = battleutils::jumpAbility(m_PChar, m_PBattleSubTarget, 4); + if (Action.param == 0) + { + Action.messageID = 0; + m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar, m_PBattleSubTarget, m_PJobAbility->getID()+16, 0, MSGBASIC_USES_BUT_MISSES)); + } + } + // Soul Jump + else if(m_PJobAbility->getID() == ABILITY_SOUL_JUMP) + { + Action.param = battleutils::jumpAbility(m_PChar, m_PBattleSubTarget, 5); + if (Action.param == 0) + { + Action.messageID = 0; + m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar, m_PBattleSubTarget, m_PJobAbility->getID()+16, 0, MSGBASIC_USES_BUT_MISSES)); + } + } // handle enmity transfer abilities if (m_PJobAbility->getID() == ABILITY_ACCOMPLICE) @@ -2373,7 +2511,7 @@ if (m_PJobAbility->getValidTarget() & TARGET_ENEMY) { - // во время pvp целью могут быт персонажи, монстры и их питомцы + // during pvp to life are the characters, monsters and their pets if (m_PBattleSubTarget->objtype == TYPE_MOB && m_PJobAbility->getID() != ABILITY_ASSAULT && m_PJobAbility->getID() != ABILITY_FIGHT && @@ -2388,7 +2526,7 @@ } } - // TODO: все перенести в скрипты, т.к. система позволяет получать указатель на питомца + // TODO: all moved to the script, as system allows you to get a pointer to the pet if(m_PJobAbility->getID() == ABILITY_CALL_BEAST || m_PJobAbility->getID() == ABILITY_REWARD){ charutils::UpdateItem(m_PChar, LOC_INVENTORY, m_PChar->equip[SLOT_AMMO], -1); @@ -2412,6 +2550,8 @@ m_PJobAbility->getID() != ABILITY_JUMP && m_PJobAbility->getID() != ABILITY_HIGH_JUMP && m_PJobAbility->getID() != ABILITY_SUPER_JUMP && + m_PJobAbility->getID() != ABILITY_SPIRIT_JUMP && + m_PJobAbility->getID() != ABILITY_SOUL_JUMP && m_PJobAbility->getID() != ABILITY_REWARD && m_PJobAbility->getID() != ABILITY_SNARL && m_PJobAbility->getID() != ABILITY_GAUGE) @@ -2522,7 +2662,7 @@ /************************************************************************ * * -* Невозможно начать weapon skill * +* Can not start weapon skill * * * ************************************************************************/ @@ -2671,6 +2811,14 @@ m_PChar->health.tp = 0; } + if(m_PChar->getMod(MOD_CONSERVE_TP) > 0) // Proc Rate + { + if(rand()%100 <= m_PChar->getMod(MOD_CONSERVE_TP)) + { + m_PChar->health.tp += rand()%20; // Gives back random 1-20 TP + // ShowDebug(CL_CYAN"Conserve TP Proc \n"); + } + } //incase a TA party member is available CBattleEntity* taChar = NULL; @@ -2881,7 +3029,7 @@ if(PTarget->objtype == TYPE_MOB){ CMobEntity* mob = (CMobEntity*)PTarget; - mob->PEnmityContainer->UpdateEnmityFromDamage(m_PChar, Action.param); + mob->PEnmityContainer->UpdateEnmityFromDamage(m_PChar, Action.param, false); } m_PChar->m_ActionList.push_back(Action); @@ -3042,7 +3190,7 @@ float Distance = distance(m_PChar->loc.p,m_PBattleTarget->loc.p); - if (Distance > 30) + if (Distance > 30*map_config.engage_dist_mod) { m_PChar->pushPacket(new CMessageBasicPacket(m_PChar,m_PBattleTarget,0,0,MSGBASIC_LOSE_SIGHT)); @@ -3075,7 +3223,7 @@ return; } m_LastMeleeTime = m_Tick; - if (battleutils::IsParalised(m_PChar)) + if (battleutils::IsParalyzed(m_PChar)) { m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar,m_PBattleTarget,0,0,MSGBASIC_IS_PARALYZED)); } @@ -3192,8 +3340,8 @@ { hitRate = battleutils::GetHitRate(m_PChar,m_PBattleTarget,2); } - // сначала вычисляем вероятность попадания по монстру - // затем нужно вычислить вероятность нанесения критического удара + // First compute the probability of hitting the monster + // Then need to calculate the critical strike chance if (m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_PERFECT_DODGE,0)) { Action.messageID = 32; @@ -3239,6 +3387,11 @@ abs(m_PBattleTarget->loc.p.rotation - m_PChar->loc.p.rotation) < 23) { bonusDMG = m_PChar->DEX(); + if(m_PChar->getMod(MOD_SNEAK_ATK_MOD) > 0) + { + bonusDMG = bonusDMG + (bonusDMG * (m_PChar->getMod(MOD_SNEAK_ATK_MOD)/10)); + } + damage = damage + (damage * (m_PChar->getMod(MOD_SATA_DMG)/100)); if(rand()%100 < 4) Monster->m_THLvl +=1; } @@ -3247,6 +3400,11 @@ if(m_PChar->GetMJob() == JOB_THF && (!ignoreSneakTrickAttack) && taChar != NULL) { bonusDMG += m_PChar->AGI(); + if(m_PChar->getMod(MOD_TRICK_ATK_MOD) > 0) + { + bonusDMG = bonusDMG + (bonusDMG * (m_PChar->getMod(MOD_TRICK_ATK_MOD)/100)); + } + damage = damage + (damage * (m_PChar->getMod(MOD_SATA_DMG)/100)); } if (isHTH) @@ -3316,7 +3474,8 @@ if (Action.reaction == REACTION_HIT) { - damage = battleutils::CheckForDamageMultiplier(PWeapon,damage,i); + CItemWeapon* PAmmo = (CItemWeapon*)m_PChar->getStorage(LOC_INVENTORY)->GetItem(m_PChar->equip[SLOT_AMMO]); + damage = battleutils::CheckForDamageMultiplier(PWeapon,damage,i,m_PChar); Action.param = battleutils::TakePhysicalDamage(m_PChar, m_PBattleTarget, damage, isBlocked, fstrslot, 1, taChar, true); } else @@ -3360,7 +3519,7 @@ void CAICharNormal::ActionRaiseMenuSelection() { // TODO: Moghancement Experience needs to be factored in here somewhere. - DSP_DEBUG_BREAK_IF(m_PChar->m_hasRaise == 0 || m_PChar->m_hasRaise > 3); + DSP_DEBUG_BREAK_IF(m_PChar->m_hasRaise == 0 || m_PChar->m_hasRaise > 4); m_PChar->animation = ANIMATION_NONE; @@ -3389,6 +3548,12 @@ hpReturned = m_PChar->GetMaxHP()*0.5; ratioReturned = ((m_PChar->GetMLevel() <= 50) ? 0.50f : 0.90f) * (1 - map_config.exp_retain); } + else if(m_PChar->m_hasRaise == 4) + { + Action.animation = 496; + hpReturned = m_PChar->GetMaxHP(); + ratioReturned = ((m_PChar->GetMLevel() <= 50) ? 0.50f : 0.90f) * (1 - map_config.exp_retain); + } m_PChar->addHP(((hpReturned < 1) ? 1 : hpReturned)); Action.reaction = REACTION_NONE; Action.speceffect = SPECEFFECT_RAISE; @@ -3399,14 +3564,28 @@ m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CActionPacket(m_PChar)); uint8 weaknessLvl = 1; - if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_WEAKNESS)) - { - //double weakness! Calculate stuff here - weaknessLvl = 2; - } - //add weakness effect (75% reduction in HP/MP) - CStatusEffect* PWeaknessEffect = new CStatusEffect(EFFECT_WEAKNESS,EFFECT_WEAKNESS,weaknessLvl,0,300); - m_PChar->StatusEffectContainer->AddStatusEffect(PWeaknessEffect); + uint8 weaknessEffect = 1; + CItemWeapon* PWeapon = (CItemWeapon*)m_PChar->getStorage(LOC_INVENTORY)->GetItem(m_PChar->equip[SLOT_MAIN]); + + if(PWeapon->getID() == 18525 && (rand()%100 < 10)) // Himthige + { + weaknessEffect = 0; + } + if(m_PChar->m_hasRaise == 4) + { + weaknessEffect = 0; + } + if(weaknessEffect == 1) + { + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_WEAKNESS)) + { + //double weakness! Calculate stuff here + weaknessLvl = 2; + } + //add weakness effect (75% reduction in HP/MP) + CStatusEffect* PWeaknessEffect = new CStatusEffect(EFFECT_WEAKNESS,EFFECT_WEAKNESS,weaknessLvl,0,300); + m_PChar->StatusEffectContainer->AddStatusEffect(PWeaknessEffect); + } charutils::UpdateHealth(m_PChar); m_PChar->pushPacket(new CCharUpdatePacket(m_PChar)); Index: src/map/ai/ai_mob_dummy.cpp =================================================================== --- src/map/ai/ai_mob_dummy.cpp (revision 3520) +++ src/map/ai/ai_mob_dummy.cpp (working copy) @@ -24,8 +24,10 @@ #include "../../common/showmsg.h" #include "../../common/utils.h" +#include "../battleentity.h" #include "../battleutils.h" #include "../blueutils.h" +#include "../charentity.h" #include "../charutils.h" #include "../itemutils.h" #include "../mobskill.h" @@ -51,8 +53,8 @@ /************************************************************************ * * -* Инициализируем владельца интеллекта (может добавить проверку на * -* пустой указатель с выводом FatalError ?) * +* Initialize the owner intelligence (can add a check to * +* Null pointer with output FatalError?) * * * ************************************************************************/ @@ -71,7 +73,7 @@ /************************************************************************ * * -* Основная часть интеллекта - главный цикл * +* The bulk of intelligence - the main loop * * * ************************************************************************/ @@ -108,8 +110,9 @@ /************************************************************************ * * -* Здесь должен быть алгоритм путешествия по зоне, а также переход в * -* режим боевой стойки, если его обладатель (атакующий) не равен нулю. * +* There must be an algorithm travel zone, and the transition to * +* mode of fighting stance, if the holder (the attacker) is not equal * +* to zero. * * * ************************************************************************/ @@ -129,7 +132,7 @@ // try to resolve the person who owns us m_PBattleTarget = (CBattleEntity*)m_PMob->loc.zone->GetEntity(m_PMob->m_OwnerID.targid, TYPE_PC | TYPE_MOB | TYPE_PET); - // TODO: возможно необходимо добавлять цели базовое количество ненависти + // TODO: may be added to basic amount of hate m_ActionType = ACTION_ENGAGE; ActionEngage(); @@ -210,7 +213,7 @@ /************************************************************************ * * -* Монстр переходит в боевую стойку, включается режим атаки * +* Monster goes into a fighting stance, the movie Attack * * * ************************************************************************/ @@ -255,8 +258,8 @@ /************************************************************************ * * -* Монстр выходит из режима атаки по каким-либо причинам. Если при этом * -* он слишком далеко от точки появления, то запускается перерождение. * +* Monster exits attack for some reason. If this it is too far from the * +* point of introduction, is started degeneration. * * * ************************************************************************/ @@ -302,7 +305,7 @@ /************************************************************************ * * -* Монстр падает на землю после получения смертельного удара. * +* Monster falls to the ground after the fatal blow. * * * ************************************************************************/ @@ -326,8 +329,8 @@ /************************************************************************ * * -* Здесь выполняется скрипт после смерти монстра, распределяется опыт * -* и определяются выпавшие предметы * +* This script is executed after the death of the monster, the * +* experience is distributed and are determined by fallen objects * * * ************************************************************************/ @@ -361,16 +364,16 @@ uint8 tries = 0; while(tries < 1+highestTH) { - if(rand()%100 < DropList->at(i).DropRate) + if(rand()%100 < (DropList->at(i).DropRate + map_config.drop_rate_bonus)) { - PChar->PTreasurePool->AddItem(DropList->at(i).ItemID, m_PMob); + PChar->PTreasurePool->AddItem(DropList->at(i).ItemID, m_PMob); break; } tries++; - } + } } //check for gil (beastmen drop gil, some NMs drop gil) - if(m_PMob->m_EcoSystem == SYSTEM_BEASTMEN || m_PMob->m_Type & MOBTYPE_NOTORIOUS) + if(m_PMob->m_EcoSystem == SYSTEM_BEASTMEN || m_PMob->m_Type & MOBTYPE_NOTORIOUS || map_config.all_mobs_drop_gil == 1) { charutils::DistributeGil(PChar, m_PMob); // TODO: REALISATION MUST BE IN TREASUREPOOL } @@ -381,8 +384,8 @@ >= 90 = High Kindred Crests ID=2956 */ uint8 Pzone = PChar->getZone(); - if(charutils::GetRealExp(PChar->GetMLevel(),m_PMob->GetMLevel())>0 && - rand()%100 < 40 && m_PMob->m_Type == MOBTYPE_NORMAL && ((Pzone > 0 && + if((charutils::GetRealExp(PChar->GetMLevel(),m_PMob->GetMLevel())>0 || map_config.always_seal_crest == 1) && + rand()%100 < (40 + map_config.seal_crest_bonus) && m_PMob->m_Type == MOBTYPE_NORMAL && ((Pzone > 0 && Pzone < 39) || (Pzone > 42 && Pzone < 134) || (Pzone > 135 && Pzone < 185) || (Pzone > 188 && Pzone < 255))){ //exp-yielding monster and drop is successful //TODO: The drop is actually based on a 5 minute timer, and not a probability of dropping! @@ -439,7 +442,7 @@ /************************************************************************ * * -* Время ожидания до исчезновения (монстр не обязательно мертв) * +* Waiting time until extinction (the monster does not necessarily dead)* * * ************************************************************************/ @@ -467,10 +470,10 @@ /************************************************************************ * * -* Здесь модель пропадает после постепенного ичезновения, так же * -* решается вопрос, а нужно ли включать процесс возрождения монстра. * -* Если его тип возрождения равен нулю, значит он был вызван и в * -* возрождении не нуждается, иначе запускаем процесс * +* Here, the model after gradually disappears icheznoveniya as well * +* Solved the problem, and whether to include the revival of the monster.* +* If the type of revival is zero, then it is called in * +* Does not need revival, or run processesс * * * ************************************************************************/ @@ -495,11 +498,11 @@ /************************************************************************ * * -* Возрождение монстра * +* revival monster * * * ************************************************************************/ -// TODO: ночные монстры должны появляться только ночью +// TODO: nocturnal monsters appear only at night void CAIMobDummy::ActionSpawn() { @@ -569,7 +572,7 @@ /************************************************************************ * * -* Начало специальной атаки монстра (эффект начала) * +* Start special attack monster (the effect of start) * * * ************************************************************************/ @@ -579,7 +582,7 @@ std::vector MobSkills = battleutils::GetMobSkillsByFamily(m_PMob->m_Family); - // не у всех монстов прописаны способности, так что выходим из процедуры, если способность не найдена + // Not all registered Monster ability, so get out of the procedure, if the ability is not found // We don't have any skills we can use, so let's go back to attacking if (MobSkills.size() == 0) { @@ -688,8 +691,8 @@ Action.messageID = 43; //readies message Action.flag = 0; - m_PMob->m_ActionList.push_back(Action); - m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CActionPacket(m_PMob)); + m_PMob->m_ActionList.push_back(Action); + m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CActionPacket(m_PMob)); m_ActionType = ACTION_MOBABILITY_USING; } @@ -737,9 +740,9 @@ /************************************************************************ * * -* Окончание специальной атаки монстра (анимация эффекта). * -* После выполения специальной атаки не обнуляем m_PMobSkill, позднее * -* по этому значению blu будет учить заклинания. * +* Closing special attack monster (animation effect). * +* If this is done the special attack is not zero out m_PMobSkill, later * +* This value blu will teach spells. * * * ************************************************************************/ @@ -862,7 +865,7 @@ /************************************************************************ * * -* Прерывание специальной атаки монстра * +* Interrupting a special monster attacks * * * ************************************************************************/ @@ -1033,7 +1036,7 @@ ActionMagicInterrupt(); return; } - else if (battleutils::IsParalised(m_PMob)) + else if (battleutils::IsParalyzed(m_PMob)) { m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CMessageBasicPacket(m_PMob,m_PBattleSubTarget,0,0,MSGBASIC_IS_PARALYZED)); m_ActionType = ACTION_MAGIC_INTERRUPT; @@ -1220,7 +1223,7 @@ /************************************************************************ * * -* Обычная физическая атака без нанесения какого-либо урона * +* Normal physical attack without causing any damage * * * ************************************************************************/ @@ -1320,7 +1323,7 @@ if ((m_Tick - m_LastActionTime) > WeaponDelay) { - if (battleutils::IsParalised(m_PMob) && m_AutoAttackEnabled) + if (battleutils::IsParalyzed(m_PMob) && m_AutoAttackEnabled) { m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CMessageBasicPacket(m_PMob,m_PBattleTarget,0,0, MSGBASIC_IS_PARALYZED)); } @@ -1339,198 +1342,255 @@ } if (m_AutoAttackEnabled) { - apAction_t Action; - m_PMob->m_ActionList.clear(); + apAction_t Action; + m_PMob->m_ActionList.clear(); - Action.ActionTarget = m_PBattleTarget; + Action.ActionTarget = m_PBattleTarget; - uint8 numAttacks = battleutils::CheckMultiHits(m_PMob, m_PMob->m_Weapons[SLOT_MAIN]); + uint8 numAttacks = battleutils::CheckMultiHits(m_PMob, m_PMob->m_Weapons[SLOT_MAIN]); - for(uint8 i=0; iisDead()){ - break; - } + for(uint8 i=0; iisDead()){ + break; + } - uint16 damage = 0; - bool isCountered = false; - bool isParried = false; - bool isGuarded = false; - if (m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_PERFECT_DODGE)) + uint16 damage = 0; + bool isCountered = false; + bool isParried = false; + bool isGuarded = false; + if (m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_PERFECT_DODGE)) + { + Action.messageID = 32; + } + else if ( rand()%100 < battleutils::GetHitRate(m_PMob, m_PBattleTarget) ) + { + if (battleutils::IsParried(m_PMob, m_PBattleTarget)) { - Action.messageID = 32; + isParried = true; + Action.messageID = 70; + Action.reaction = REACTION_PARRY; + Action.speceffect = SPECEFFECT_NONE; } - else if ( rand()%100 < battleutils::GetHitRate(m_PMob, m_PBattleTarget) ) + else if (battleutils::IsAbsorbByShadow(m_PBattleTarget)) { - if (battleutils::IsParried(m_PMob, m_PBattleTarget)) + Action.messageID = 0; + m_PBattleTarget->loc.zone->PushPacket(m_PBattleTarget,CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PBattleTarget,m_PBattleTarget,0,1, MSGBASIC_SHADOW_ABSORB)); + } + else if (battleutils::IsAnticipated(m_PBattleTarget,false,false)) + { + Action.messageID = 30; + } + else + { + Action.reaction = REACTION_HIT; + Action.speceffect = SPECEFFECT_HIT; + Action.messageID = 1; + + // if victim is a player, get the players counter merits + uint8 meritCounter = 0; + if (m_PBattleTarget->objtype == TYPE_PC && charutils::hasTrait((CCharEntity*)m_PBattleTarget,TRAIT_COUNTER)) { - isParried = true; - Action.messageID = 70; - Action.reaction = REACTION_PARRY; - Action.speceffect = SPECEFFECT_NONE; + if (m_PBattleTarget->GetMJob() == JOB_MNK || m_PBattleTarget->GetMJob() == JOB_PUP) + meritCounter = ((CCharEntity*)m_PBattleTarget)->PMeritPoints->GetMeritValue(MERIT_COUNTER_RATE,(CCharEntity*)m_PBattleTarget); } - else if (battleutils::IsAbsorbByShadow(m_PBattleTarget)) - { - Action.messageID = 0; - m_PBattleTarget->loc.zone->PushPacket(m_PBattleTarget,CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PBattleTarget,m_PBattleTarget,0,1, MSGBASIC_SHADOW_ABSORB)); - } - else if (battleutils::IsAnticipated(m_PBattleTarget,false,false)) - { - Action.messageID = 30; - } - else - { - Action.reaction = REACTION_HIT; - Action.speceffect = SPECEFFECT_HIT; - Action.messageID = 1; - // if victim is a player, get the players counter merits - uint8 meritCounter = 0; - if (m_PBattleTarget->objtype == TYPE_PC && charutils::hasTrait((CCharEntity*)m_PBattleTarget,TRAIT_COUNTER)) - { - if (m_PBattleTarget->GetMJob() == JOB_MNK || m_PBattleTarget->GetMJob() == JOB_PUP) - meritCounter = ((CCharEntity*)m_PBattleTarget)->PMeritPoints->GetMeritValue(MERIT_COUNTER_RATE,(CCharEntity*)m_PBattleTarget); - } - - - //counter check (rate AND your hit rate makes it land, else its just a regular hit) - if (rand()%100 < (m_PBattleTarget->getMod(MOD_COUNTER) + meritCounter) && - rand()%100 < battleutils::GetHitRate(m_PBattleTarget,m_PMob) && + int16 naturalh2hDMG = 0; + + //counter check (rate AND your hit rate makes it land, else its just a regular hit) + if (rand()%100 < (m_PBattleTarget->getMod(MOD_COUNTER) + meritCounter) && + rand()%100 < battleutils::GetHitRate(m_PBattleTarget,m_PMob) && (charutils::hasTrait((CCharEntity*)m_PBattleTarget,TRAIT_COUNTER) || m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_SEIGAN))) - { - isCountered = true; - Action.messageID = 33; //counter msg 32 - Action.reaction = REACTION_HIT; - Action.speceffect = SPECEFFECT_NONE; + { + isCountered = true; + Action.messageID = 33; //counter msg 32 + Action.reaction = REACTION_HIT; + Action.speceffect = SPECEFFECT_NONE; - bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PBattleTarget, m_PMob,false) ); + bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PBattleTarget, m_PMob,false) ); bool isHTH = m_PBattleTarget->m_Weapons[SLOT_MAIN]->getDmgType() == DAMAGE_HTH; if (!isHTH && m_PBattleTarget->objtype == TYPE_MOB && m_PBattleTarget->GetMJob() == JOB_MNK) { isHTH = true; } - int16 naturalh2hDMG = 0; if (isHTH) { naturalh2hDMG = (float)(m_PBattleTarget->GetSkill(SKILL_H2H) * 0.11f)+3; } - float DamageRatio = battleutils::GetDamageRatio(m_PBattleTarget, m_PMob,isCritical, 0); - damage = (uint16)((m_PBattleTarget->GetMainWeaponDmg() + naturalh2hDMG + battleutils::GetFSTR(m_PBattleTarget, m_PMob,SLOT_MAIN)) * DamageRatio); + float DamageRatio = battleutils::GetDamageRatio(m_PBattleTarget, m_PMob,isCritical, 0); + damage = (uint16)(((m_PBattleTarget->GetMainWeaponDmg() + naturalh2hDMG + m_PBattleTarget->getMod(MOD_COUNTER_BASE_DMG))+ battleutils::GetFSTR(m_PBattleTarget, m_PMob,SLOT_MAIN)) * DamageRatio); - Action.subparam = (damage * 2); - Action.flag = 2; - } - else if (m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_PERFECT_COUNTER)) - { //Perfect Counter only counters hits that normal counter misses - isCountered = true; + Action.subparam = (damage * 2); + Action.flag = 2; + } + else if (m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_PERFECT_COUNTER)) + { + isCountered = true; + Action.messageID = 33; //counter msg 32 + Action.reaction = REACTION_HIT; + Action.speceffect = SPECEFFECT_NONE; + float DamageRatio = battleutils::GetDamageRatio(m_PBattleTarget, m_PMob,true, 0); + damage = (uint16)(((m_PBattleTarget->GetMainWeaponDmg() + naturalh2hDMG + m_PBattleTarget->getMod(MOD_COUNTER_BASE_DMG) + + m_PBattleTarget->getMod(MOD_PFT_COUNTER_DMG))+ battleutils::GetFSTR(m_PBattleTarget, m_PMob,SLOT_MAIN)) * DamageRatio); + + Action.subparam = (damage * 2); + Action.flag = 2; + m_PBattleTarget->StatusEffectContainer->DelStatusEffect(EFFECT_PERFECT_COUNTER); + } + else + { + bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PMob, m_PBattleTarget,false) ); + + if(m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_MIGHTY_STRIKES,0)) + { + isCritical=true; } - else - { - bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PMob, m_PBattleTarget,false) ); - if(m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_MIGHTY_STRIKES,0)) - { - isCritical=true; - } + float DamageRatio = battleutils::GetDamageRatio(m_PMob, m_PBattleTarget,isCritical, 0); - float DamageRatio = battleutils::GetDamageRatio(m_PMob, m_PBattleTarget,isCritical, 0); + if(isCritical) + { + Action.speceffect = SPECEFFECT_CRITICAL_HIT; + Action.messageID = 67; + } - if(isCritical) - { - Action.speceffect = SPECEFFECT_CRITICAL_HIT; - Action.messageID = 67; - } + // Guard + if(battleutils::IsGuarded(m_PMob, m_PBattleTarget)) + { + isGuarded = true; + //Action.messageID = 0; + Action.reaction = REACTION_GUARD; + Action.speceffect = SPECEFFECT_NONE; + DamageRatio -= 1.0f; // Guard lowers pDif by 1.0 + } - // Guard - if(battleutils::IsGuarded(m_PMob, m_PBattleTarget)) - { - isGuarded = true; - //Action.messageID = 0; - Action.reaction = REACTION_GUARD; - Action.speceffect = SPECEFFECT_NONE; - DamageRatio -= 1.0f; // Guard lowers pDif by 1.0 - } + damage = (uint16)((m_PMob->m_Weapons[SLOT_MAIN]->getDamage() + battleutils::GetFSTR(m_PMob, m_PBattleTarget,SLOT_MAIN)) * DamageRatio); - damage = (uint16)((m_PMob->m_Weapons[SLOT_MAIN]->getDamage() + battleutils::GetFSTR(m_PMob, m_PBattleTarget,SLOT_MAIN)) * DamageRatio); - - // Guard skill up - if(m_PBattleTarget->objtype == TYPE_PC && isGuarded || ((map_config.newstyle_skillups & NEWSTYLE_GUARD) > 0)) - { - if(battleutils::GetGuardRate(m_PMob, m_PBattleTarget) > 0) - { - charutils::TrySkillUP((CCharEntity*)m_PBattleTarget,SKILL_GRD, m_PBattleTarget->GetMLevel()); - } - } // Guard skill up - } + // Guard skill up + if(m_PBattleTarget->objtype == TYPE_PC && isGuarded || ((map_config.newstyle_skillups & NEWSTYLE_GUARD) > 0)) + { + m_PBattleTarget->addTP(m_PBattleTarget->getMod(MOD_TACTICAL_GUARD)); + if(battleutils::GetGuardRate(m_PMob, m_PBattleTarget) > 0) + { + charutils::TrySkillUP((CCharEntity*)m_PBattleTarget,SKILL_GRD, m_PBattleTarget->GetMLevel()); + } + } // Guard skill up } + } - // Parry skill up - if(m_PBattleTarget->objtype == TYPE_PC && isParried || ((map_config.newstyle_skillups & NEWSTYLE_PARRY) > 0)) + // Parry skill up + if(m_PBattleTarget->objtype == TYPE_PC && isParried || ((map_config.newstyle_skillups & NEWSTYLE_PARRY) > 0)) + { + m_PBattleTarget->addTP(m_PBattleTarget->getMod(MOD_TACTICAL_PARRY)); + if(m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_ISSEKIGAN)) { - if(battleutils::GetParryRate(m_PMob, m_PBattleTarget) > 0) - { - charutils::TrySkillUP((CCharEntity*)m_PBattleTarget,SKILL_PAR,m_PBattleTarget->GetMLevel()); - } - } // Parry skill up - } - if (m_PBattleTarget->objtype == TYPE_PC && !isCountered && !isParried) - { - charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, SKILL_EVA, m_PMob->GetMLevel()); - } + m_PMob->PEnmityContainer->UpdateEnmity(m_PBattleTarget, 300, 10); + } + if(battleutils::GetParryRate(m_PMob, m_PBattleTarget) > 0) + { + charutils::TrySkillUP((CCharEntity*)m_PBattleTarget,SKILL_PAR,m_PBattleTarget->GetMLevel()); + } + } // Parry skill up + } + if (m_PBattleTarget->objtype == TYPE_PC && !isCountered && !isParried) + { + charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, SKILL_EVA, m_PMob->GetMLevel()); + } - bool isBlocked = battleutils::IsBlocked(m_PMob, m_PBattleTarget); - if(isBlocked){ Action.reaction = REACTION_BLOCK; } + bool isBlocked = battleutils::IsBlocked(m_PMob, m_PBattleTarget); + if(isBlocked){ Action.reaction = REACTION_BLOCK; } - if(!isCountered) + if(!isCountered) + { + if (m_PBattleTarget->objtype == TYPE_PC) { - if (m_PBattleTarget->objtype == TYPE_PC) + damage = battleutils::HandleSpecialPhysicalDamageReduction((CCharEntity*)m_PBattleTarget,damage,&Action); + uint16 recoverMP = battleutils::HandleDamageToMP((CCharEntity*)m_PBattleTarget,damage,&Action); + if (recoverMP > 0) { - damage = battleutils::HandleSpecialPhysicalDamageReduction((CCharEntity*)m_PBattleTarget,damage,&Action); + // ShowDebug(CL_CYAN"Damage to MP %d", recoverMP); + m_PBattleTarget->addMP(recoverMP); + m_PBattleTarget->loc.zone->PushPacket(m_PBattleTarget,CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PBattleTarget,m_PBattleTarget,0,recoverMP, 276)); + charutils::UpdateHealth((CCharEntity*)m_PBattleTarget); } + uint16 recoverTP = battleutils::HandleDamageToTP((CCharEntity*)m_PBattleTarget,damage,&Action); + if (recoverTP > 0) + { + // ShowDebug(CL_CYAN"Damage to TP %d", recoverTP); + m_PBattleTarget->addTP(recoverTP); + charutils::UpdateHealth((CCharEntity*)m_PBattleTarget); + } + + } - Action.param = battleutils::TakePhysicalDamage(m_PMob, m_PBattleTarget, damage, isBlocked ,SLOT_MAIN, 1, NULL, true); - m_PMob->PEnmityContainer->UpdateEnmityFromAttack(m_PBattleTarget, Action.param); - - // Block skill up - if(m_PBattleTarget->objtype == TYPE_PC && isBlocked || ((map_config.newstyle_skillups & NEWSTYLE_BLOCK) > 0)) + Action.param = battleutils::TakePhysicalDamage(m_PMob, m_PBattleTarget, damage, isBlocked ,SLOT_MAIN, 1, NULL, true); + m_PMob->PEnmityContainer->UpdateEnmityFromAttack(m_PBattleTarget, Action.param); + + if(m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_SCARLET_DELIRIUM_I) && (damage > 0)) + { + m_PBattleTarget->StatusEffectContainer->DelStatusEffect(EFFECT_SCARLET_DELIRIUM_I); + uint16 scarletDeliriumBonus = ceil((float)(((float)damage / (float)m_PBattleTarget->GetMaxHP()) / 2.0f) * 100); + // ShowDebug(CL_CYAN"Scarlet Delirium Bonus %d", scarletDeliriumBonus); + m_PBattleTarget->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SCARLET_DELIRIUM_II,EFFECT_SCARLET_DELIRIUM_II,scarletDeliriumBonus,0,60)); + } + + // Block skill up + if(m_PBattleTarget->objtype == TYPE_PC && isBlocked || ((map_config.newstyle_skillups & NEWSTYLE_BLOCK) > 0)) + { + m_PBattleTarget->addTP(m_PBattleTarget->getMod(MOD_SHIELD_MASTERY)); + uint16 blockMP = battleutils::HandleBlockToMP((CCharEntity*)m_PBattleTarget,damage,&Action); + if (blockMP > 0) { - if(battleutils::GetBlockRate(m_PMob, m_PBattleTarget) > 0) - { - charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, SKILL_SHL, m_PMob->GetMLevel()); - } - } // Block skill up + // ShowDebug(CL_CYAN"Damage to MP %d", blockMP); + m_PBattleTarget->addMP(blockMP); + m_PBattleTarget->loc.zone->PushPacket(m_PBattleTarget,CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PBattleTarget,m_PBattleTarget,0,blockMP, 276)); + charutils::UpdateHealth((CCharEntity*)m_PBattleTarget); + } + if(battleutils::GetBlockRate(m_PMob, m_PBattleTarget) > 0) + { + charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, SKILL_SHL, m_PMob->GetMLevel()); + } + } // Block skill up - // spike effect - if (Action.reaction != REACTION_EVADE && Action.reaction != REACTION_PARRY) - { - // spikes take priority - if(!battleutils::HandleSpikesDamage(m_PMob, m_PBattleTarget, &Action, damage)){ - // no spikes, handle enspell - // TODO: enspell method needs to be refactored to accept just battleentity - // battleutils::HandleEnspell(m_PMob, m_PBattleTarget, &Action, i, WeaponDelay, damage); - } + // spike effect + if (Action.reaction != REACTION_EVADE && Action.reaction != REACTION_PARRY) + { + // spikes take priority + if(!battleutils::HandleSpikesDamage(m_PMob, m_PBattleTarget, &Action, damage)){ + // no spikes, handle enspell + // TODO: enspell method needs to be refactored to accept just battleentity + // battleutils::HandleEnspell(m_PMob, m_PBattleTarget, &Action, i, WeaponDelay, damage); } + battleutils::HandleRetaliation(m_PMob, m_PBattleTarget, &Action, damage); } - else + } + else + { + Action.param = battleutils::TakePhysicalDamage(m_PBattleTarget, m_PMob, damage, false, SLOT_MAIN, 1, NULL, true); + if(m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_SCARLET_DELIRIUM_I) && (damage > 0)) { - Action.param = battleutils::TakePhysicalDamage(m_PBattleTarget, m_PMob, damage, false, SLOT_MAIN, 1, NULL, true); - if(m_PBattleTarget->objtype == TYPE_PC) - { - uint8 skilltype = (m_PBattleTarget->m_Weapons[SLOT_MAIN] == NULL ? SKILL_H2H : m_PBattleTarget->m_Weapons[SLOT_MAIN]->getSkillType()); - charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, (SKILLTYPE)skilltype, m_PMob->GetMLevel()); - } + m_PBattleTarget->StatusEffectContainer->DelStatusEffect(EFFECT_SCARLET_DELIRIUM_I); + uint16 scarletDeliriumBonus = ceil((float)(((float)damage / (float)m_PBattleTarget->GetMaxHP()) / 2.0f) * 100); + // ShowDebug(CL_CYAN"Scarlet Delirium Bonus %d", scarletDeliriumBonus); + m_PBattleTarget->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SCARLET_DELIRIUM_II,EFFECT_SCARLET_DELIRIUM_II,scarletDeliriumBonus,0,60)); } + if(m_PBattleTarget->objtype == TYPE_PC) + { + uint8 skilltype = (m_PBattleTarget->m_Weapons[SLOT_MAIN] == NULL ? SKILL_H2H : m_PBattleTarget->m_Weapons[SLOT_MAIN]->getSkillType()); + charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, (SKILLTYPE)skilltype, m_PMob->GetMLevel()); + } + } - m_PMob->m_ActionList.push_back(Action); + m_PMob->m_ActionList.push_back(Action); } // battleutils::MoveIntoRange(m_PMob,m_PBattleTarget,25); m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CActionPacket(m_PMob)); Index: src/map/ai/ai_mob_dummy.h =================================================================== --- src/map/ai/ai_mob_dummy.h (revision 3520) +++ src/map/ai/ai_mob_dummy.h (working copy) @@ -43,9 +43,9 @@ enum AOERANGE { - AOE_PARTY = 0x01, + AOE_PARTY = 0x01, AOE_ALLIANCE = 0x02, - AOE_ZONE = 0x04 + AOE_ZONE = 0x04 }; class CMobEntity; Index: src/map/ai/ai_pet_dummy.cpp =================================================================== --- src/map/ai/ai_pet_dummy.cpp (revision 3520) +++ src/map/ai/ai_pet_dummy.cpp (working copy) @@ -648,7 +648,7 @@ else{ //try to attack if((m_Tick - m_LastActionTime) > m_PPet->m_Weapons[SLOT_MAIN]->getDelay()){ - if (battleutils::IsParalised(m_PPet)) + if (battleutils::IsParalyzed(m_PPet)) { m_PPet->loc.zone->PushPacket(m_PPet, CHAR_INRANGE, new CMessageBasicPacket(m_PPet,m_PBattleTarget,0,0,29)); } Index: src/map/baseentity.cpp =================================================================== --- src/map/baseentity.cpp (revision 3520) +++ src/map/baseentity.cpp (working copy) @@ -51,6 +51,18 @@ return name.c_str(); } +const int8* CBaseEntity::GetSayName() +{ + //Strip out the _ in names + npcSayName = name; + size_t start_pos = npcSayName.find("_"); + if (start_pos < name.size()) + { + npcSayName.replace(start_pos,1," "); + } + return npcSayName.c_str(); +} + uint16 CBaseEntity::getZone() { return loc.zone != NULL ? loc.zone->GetID() : loc.destination; Index: src/map/baseentity.h =================================================================== --- src/map/baseentity.h (revision 3520) +++ src/map/baseentity.h (working copy) @@ -73,7 +73,7 @@ ANIMATION_FISHING_START = 50 }; -// TODO: возможо стоит сделать эту структуру частью класса, взамен нынешних id и targid, но уже без метода clean +// TODO: is possible to make the structure of the class, instead of the current id and targid, but without a clean method struct EntityID_t { @@ -91,17 +91,17 @@ struct location_t { - position_t p; // позиция сущности - uint16 destination; // текущая зона - CZone* zone; // текущая зона - uint16 prevzone; // предыдущая зона (для монстров и npc не используется) - bool zoning; // флаг сбрасывается при каждом входе в новую зону. необходим для реализации логики игровых задач ("quests") - uint16 boundary; // определенная область в зоне, в которой находится сущность (используется персонажами и транспортом) + position_t p; // position essentially + uint16 destination; // current zone + CZone* zone; // current zone + uint16 prevzone; // previous zone (for monsters and npc not used) + bool zoning; // flag is reset every time you access a new area. needed to implement the logic of the game problems ("quests") + uint16 boundary; // specific area in the zone in which the entity (using the characters and vehicles) }; /************************************************************************ * * -* Базовый класс для всех сущностей в игре * +* The base class for all entities in the game * * * ************************************************************************/ @@ -109,28 +109,30 @@ { public: - uint32 id; // глобальный идентификатор, уникальный на сервере - uint16 targid; // локалный идентификатор, уникальный в зоне - ENTITYTYPE objtype; // тип сущности - STATUSTYPE status; // статус сущности (разные сущности - разные статусы) - uint16 m_TargID; // targid объекта, на который смотрит сущность - string_t name; // имя сущности - look_t look; // внешний вид всех сущностей + uint32 id; // global identifier that is unique to the server + uint16 targid; // lokalny identifier that is unique in the area + ENTITYTYPE objtype; // entity Type + STATUSTYPE status; // status of the entity (separate entities - different statuses) + uint16 m_TargID; // targid object that looks the essence + string_t name; // the entity name + string_t npcSayName; // NPC Say name + look_t look; // appearance of all the entities look_t mainlook; // only used if mob use changeSkin() - location_t loc; // местоположение сущности - uint8 animation; // анимация - uint8 animationsub; // дополнительный параметры анимации - uint8 speed; // скорость передвижения - uint8 speedsub; // подолнительный параметр скорости передвижения + location_t loc; // location entities + uint8 animation; // animation + uint8 animationsub; // additional animation options + uint8 speed; // speed + uint8 speedsub; // podolnitelny setting the speed of movement - virtual const int8* GetName(); // имя сущности - uint16 getZone(); // текущая зона - float GetXPos(); // позиция по координате X - float GetYPos(); // позиция по координате Y - float GetZPos(); // позиция по координате Z + virtual const int8* GetName(); // the entity name + virtual const int8* GetSayName(); // the entity name + uint16 getZone(); // current zone + float GetXPos(); // position coordinate X + float GetYPos(); // position coordinate Y + float GetZPos(); // position coordinate Z - CBaseEntity(); // конструктор - virtual ~CBaseEntity(); // деструктор + CBaseEntity(); // designer + virtual ~CBaseEntity(); // destructor private: }; Index: src/map/battleentity.cpp =================================================================== --- src/map/battleentity.cpp (revision 3520) +++ src/map/battleentity.cpp (working copy) @@ -30,7 +30,7 @@ CBattleEntity::CBattleEntity() { m_OwnerID.clean(); - m_ModelSize = 3; // неправильная инициализация, она приведет к тому, что заклинания станут читаться на 3 дальше + m_ModelSize = 3; // this happened, it would lead to the fact that the spell will be read on three further m_mlvl = 0; m_slvl = 0; @@ -108,7 +108,7 @@ /************************************************************************ * * -* Пересчитываем максимальные значения hp и mp с учетом модификаторов * +* Recalculated maximum hp and mp with the modifier * * * ************************************************************************/ @@ -131,7 +131,7 @@ /************************************************************************ * * -* Получаем текущее количество очков жизней * +* Get the current number of hit points * * * ************************************************************************/ @@ -147,7 +147,7 @@ /************************************************************************ * * -* Получаем текущее количество очков маны * +* Get the current amount of mana * * * ************************************************************************/ @@ -342,7 +342,7 @@ /************************************************************************ * * -* Изменяем количество TP сущности * +* Change the nature of TP * * * ************************************************************************/ @@ -371,7 +371,7 @@ /************************************************************************ * * -* Изменяем количество жизней сущности * +* Change the number of lives the essence * * * ************************************************************************/ @@ -387,7 +387,7 @@ hp = health.hp - cap; health.hp = cap; - // если количество жизней достигает нуля, то сущность умирает + // If the number of lives reaches zero, the entity dies if(hp > 0) { @@ -415,7 +415,7 @@ /************************************************************************ * * -* Полные значения характеристик боевой сущности * +* The full value of the characteristics of combat entity * * * ************************************************************************/ @@ -566,14 +566,14 @@ void CBattleEntity::SetMJob(uint8 mjob) { - DSP_DEBUG_BREAK_IF(mjob == 0 || mjob >= MAX_JOBTYPE); // выход за пределы доступных профессий + DSP_DEBUG_BREAK_IF(mjob == 0 || mjob >= MAX_JOBTYPE); // going beyond the available jobs m_mjob = (JOBTYPE)mjob; } void CBattleEntity::SetSJob(uint8 sjob) { - DSP_DEBUG_BREAK_IF(sjob >= MAX_JOBTYPE); // выход за пределы доступных профессий + DSP_DEBUG_BREAK_IF(sjob >= MAX_JOBTYPE); // going beyond the available jobs m_sjob = (JOBTYPE)sjob; } @@ -592,7 +592,7 @@ /************************************************************************ * * -* Добавляем модификатор * +* Add modifier * * * ************************************************************************/ @@ -603,7 +603,7 @@ /************************************************************************ * * -* Добавляем модификаторы * +* Add modifier * * * ************************************************************************/ @@ -617,7 +617,7 @@ /************************************************************************ * * -* Устанавливаем модификатор * +* Set the modifier * * * ************************************************************************/ @@ -628,7 +628,7 @@ /************************************************************************ * * -* Устанавливаем модификаторы * +* Set modifier * * * ************************************************************************/ @@ -642,7 +642,7 @@ /************************************************************************ * * -* Удаляем модификатор * +* Remove the modifier * * * ************************************************************************/ @@ -653,7 +653,7 @@ /************************************************************************ * * -* Удаляем модификаторы * +* Remove the modifier * * * ************************************************************************/ @@ -667,7 +667,7 @@ /************************************************************************ * * -* Получаем текущее значение указанного модификатора * +* Get the current value of the specified modifier * * * ************************************************************************/ @@ -682,7 +682,7 @@ /************************************************************************ * * -* Текущая величина умения (не максимальная, а ограниченная уровнем) * +* The current value of skills (not the maximum, and a limited level) * * * ************************************************************************/ Index: src/map/battleentity.h =================================================================== --- src/map/battleentity.h (revision 3520) +++ src/map/battleentity.h (working copy) @@ -132,6 +132,8 @@ SKILL_STR = 41, SKILL_WND = 42, SKILL_BLU = 43, + SKILL_GEO = 44, + SKILL_HBL = 45, SKILL_FSH = 48, SKILL_WDW = 49, @@ -203,7 +205,7 @@ SUBSKILL_TOLOI = 68 }; -// ячейки экипировки. монстры используют лишь первые четыре, персонаж использует все +// cell equipment. Monsters use only the first four, the character uses all enum SLOTTYPE { @@ -226,9 +228,9 @@ SLOT_LINK = 0x10 }; -// CROSSBOW и GUN - это Piercing, разделение сделано из-за одинакового skilltype -// для возможности различить эти орудия при экипировке и избавиться от ошибки -// использования пуль с арбалетом и арбалетных стрел с огнестрельным оружием (только персонажи) +// CROSSBOW and GUN - it Piercing, the division made ​​by the same skilltype +// to be able to distinguish these weapons when equipped and get rid of the error +// use bullets with a crossbow and crossbow bolts with a firearm (only characters) enum DAMAGETYPE { @@ -243,12 +245,12 @@ enum REACTION { - REACTION_NONE = 0x00, // отсутствие реакции - REACTION_MISS = 0x01, // промах - REACTION_PARRY = 0x03, // блокирование оружием (MISS + PARRY) - REACTION_BLOCK = 0x04, // блокирование щитом - REACTION_HIT = 0x08, // попадание - REACTION_EVADE = 0x09, // уклонение (MISS + HIT) + REACTION_NONE = 0x00, // lack of response + REACTION_MISS = 0x01, // slip + REACTION_PARRY = 0x03, // locking arms (MISS + PARRY) + REACTION_BLOCK = 0x04, // block with + REACTION_HIT = 0x08, // hit + REACTION_EVADE = 0x09, // evasion (MISS + HIT) REACTION_GUARD = 0x14, // mnk guard (20 dec) }; @@ -300,6 +302,7 @@ // 9 weight? or evasion down? SUBEFFECT_HP_DRAIN = 10, // 110101 43 SUBEFFECT_TP_DRAIN = 11, + SUBEFFECT_WEAKENS_ATTACKS = 12, //SKILLCHAINS @@ -339,7 +342,7 @@ TARGET_PLAYER_ALLIANCE = 0x08, TARGET_PLAYER = 0x10, TARGET_PLAYER_DEAD = 0x20, - TARGET_NPC = 0x40 // скорее всего подразумевается mob, выглядящий как npc и воюющий на стороне персонажа + TARGET_NPC = 0x40 // likely mean mob, looking like npc and fighting on the side of the character }; enum SKILLCHAIN_ELEMENT @@ -401,16 +404,16 @@ /************************************************************************ * * -* TP хранится то пому же принципу, что и skill, т.е. 6,4% = 64 * +* TP then stored pomu same principle as the skill, ie 6,4% = 64 * * * ************************************************************************/ struct health_t { - float tp; // текущее значение - int32 hp, mp; // текущие значения - int32 maxhp, maxmp; // максимальные значения - int32 modhp, modmp; // модифицированные максимальные значения + float tp; // present value + int32 hp, mp; // current values + int32 maxhp, maxmp; // maximum + int32 modhp, modmp; // modified maximum }; typedef std::vector ActionList_t; @@ -420,8 +423,8 @@ public: health_t health; // hp,mp,tp - stats_t stats; // атрибуты STR,DEX,VIT,AGI,INT,MND,CHR - skills_t WorkingSkills; // структура всех доступных сущности умений, ограниченных уровнем + stats_t stats; // attributes STR,DEX,VIT,AGI,INT,MND,CHR + skills_t WorkingSkills; // structure essentially all available skills, the limited level of IMMUNITY m_Immunity; // Mob immunity uint16 m_magicEvasion; // store this so it can be removed easily @@ -441,27 +444,27 @@ uint32 charmTime; // to hold the time entity is charmed bool isCharmed; // is the battle entity charmed? - bool isDead(); // проверяем, мертва ли сущность + bool isDead(); // check whether the entity is dead bool isInDynamis(); bool hasImmunity(uint32 imID); bool isAsleep(); - JOBTYPE GetMJob(); // главная профессия - JOBTYPE GetSJob(); // дополнительная профессия - uint8 GetMLevel(); // уровень главной профессии - uint8 GetSLevel(); // уровень дополнительной профессии + JOBTYPE GetMJob(); // home Occupation + JOBTYPE GetSJob(); // secondary skill + uint8 GetMLevel(); // level of the main occupations + uint8 GetSLevel(); // additional level of profession - void SetMJob(uint8 mjob); // главная профессия - void SetSJob(uint8 sjob); // дополнительная профессия - void SetMLevel(uint8 mlvl); // уровень главной профессии - void SetSLevel(uint8 slvl); // уровень дополнительной профессии + void SetMJob(uint8 mjob); // home Occupation + void SetSJob(uint8 sjob); // secondary skill + void SetMLevel(uint8 mlvl); // level of the main occupations + void SetSLevel(uint8 slvl); // additional level of profession - uint8 GetHPP(); // количество hp в процентах - int32 GetMaxHP(); // максимальное количество hp - uint8 GetMPP(); // количество mp в процентах - int32 GetMaxMP(); // максимальное количество mp - void UpdateHealth(); // пересчет максимального количества hp и mp, а так же корректировка их текущих значений + uint8 GetHPP(); // Percentage of hp + int32 GetMaxHP(); // the maximum amount of hp + uint8 GetMPP(); // Percentage of mp + int32 GetMaxMP(); // the maximum number of mp + void UpdateHealth(); // counting the maximum number of hp and mp, as well as the adjustment of their current values int16 GetWeaponDelay(bool tp); //returns delay of combined weapons int16 GetRangedWeaponDelay(bool tp); //returns delay of ranged weapon + ammo where applicable @@ -473,13 +476,13 @@ uint16 GetSubWeaponRank(); //returns total sub weapon DMG Rank uint16 GetRangedWeaponRank(); //returns total ranged weapon DMG Rank - uint16 GetSkill(uint16 SkillID); // текущая величина умения (не максимальная, а ограниченная уровнем) + uint16 GetSkill(uint16 SkillID); // current value of skills (not the maximum, and the limited level) - virtual uint16 addTP(float tp); // увеличиваем/уменьшаем количество tp - virtual int32 addHP(int32 hp); // увеличиваем/уменьшаем количество hp - virtual int32 addMP(int32 mp); // увеличиваем/уменьшаем количество mp + virtual uint16 addTP(float tp); // increase / decrease the number of tp + virtual int32 addHP(int32 hp); // increase / decrease the number of hp + virtual int32 addMP(int32 mp); // increase / decrease the number of mp - int16 getMod(uint16 modID); // величина модификатора + int16 getMod(uint16 modID); // value modifier bool Rest(float rate); // heal an amount of hp / mp @@ -490,34 +493,34 @@ void setModifiers(std::vector *modList); void delModifiers(std::vector *modList); - uint8 m_ModelSize; // размер модели сущности, для расчета дальности физической атаки - ECOSYSTEM m_EcoSystem; // эко-система сущности - CItemWeapon* m_Weapons[4]; // четыре основных ячейки, используемыж для хранения оружия (только оружия) + uint8 m_ModelSize; // size model of the entity for the calculation range of physical attack + ECOSYSTEM m_EcoSystem; // eco-system of nature + CItemWeapon* m_Weapons[4]; // four major cell ispolzuemyzh for weapons (only weapon) - TraitList_t TraitList; // список постянно активных способностей в виде указателей + TraitList_t TraitList; // Fasting list active abilities as pointers - EntityID_t m_OwnerID; // ID атакующей сущности (после смерти будет хранить ID сущности, нанесщей последний удар) + EntityID_t m_OwnerID; // ID attacking entity (after death will store ID essentially nanesschey last hit) - ActionList_t m_ActionList; // список совершенных действий за одну атаку (нужно будет написать структуру, включающую ActionList в которой будут категории анимации и т.д.) + ActionList_t m_ActionList; // list of acts committed in one attack (you need to write a framework that includes ActionList category in which to animate and etc.) - CAIGeneral* PBattleAI; // интеллект боевой сущности - CParty* PParty; // описание группы, в которой состоит сущность - CBattleEntity* PPet; // питомец сущности - CBattleEntity* PMaster; // владелец/хозяин сущности (распространяется на все боевые сущности) + CAIGeneral* PBattleAI; // military intelligence entities + CParty* PParty; // description of the group, which is the essence + CBattleEntity* PPet; // pet essence + CBattleEntity* PMaster; // owner / host entity (applies to all military entity) CStatusEffectContainer* StatusEffectContainer; - CBattleEntity(); // конструктор - virtual ~CBattleEntity(); // деструктор + CBattleEntity(); // designer + virtual ~CBattleEntity(); // destructor private: - JOBTYPE m_mjob; // главная профессия - JOBTYPE m_sjob; // дополнительная профессия - uint8 m_mlvl; // ТЕКУЩИЙ уровень главной профессии - uint8 m_slvl; // ТЕКУЩИЙ уровень дополнительной профессии + JOBTYPE m_mjob; // home Occupation + JOBTYPE m_sjob; // secondary skill + uint8 m_mlvl; // The current level of the main occupations + uint8 m_slvl; // The current level of the profession more - int16 m_modStat[MAX_MODIFIER]; // массив модификаторов + int16 m_modStat[MAX_MODIFIER]; // array modifiers }; #endif \ No newline at end of file Index: src/map/battleutils.cpp =================================================================== --- src/map/battleutils.cpp (revision 3520) +++ src/map/battleutils.cpp (working copy) @@ -46,6 +46,7 @@ #include "spell.h" #include "trait.h" #include "weapon_skill.h" +#include "vana_time.h" #include "mobskill.h" #include "mobentity.h" #include "petentity.h" @@ -407,64 +408,359 @@ * * ************************************************************************/ -uint32 CheckForDamageMultiplier(CItemWeapon* PWeapon, uint32 damage, uint8 hitNumber) +uint32 CheckForDamageMultiplier(CItemWeapon* PWeapon, uint32 damage, uint8 hitNumber, CCharEntity* m_PChar) { if (PWeapon==NULL) return damage; uint32 originalDamage = damage; + CItemWeapon* PAmmo = (CItemWeapon*)m_PChar->getStorage(LOC_INVENTORY)->GetItem(m_PChar->equip[SLOT_AMMO]); switch (PWeapon->getID()) { //relic weapons have 16% (ffxiclopedia) chance to do x times damage, cannot proc with weapon skills // Relic: 2.5 times damage - case 18264: // Spharai, h2h - case 18276: // Excalibur, sword - case 18282: // Ragnarok, great sword - case 18288: // Guttler, axe - case 18300: // Gungnir, polearm - case 18318: // Amanomurakumo, great katana - case 18330: // Claustrum, staff - if (rand()%100 > 16) return originalDamage; - return (damage = (damage * (float)2.5)); + case 18264: // Spharai 75 + case 18265: // Spharai 80 + case 18637: // Spharai 85 + case 18651: // Spharai 90 + case 18665: // Spharai 95 + case 19746: // Spharai 99 + case 19839: // Spharai 99-2 + + case 18276: // Excalibur 75 + case 18277: // Excalibur 80 + case 18639: // Excalibur 85 + case 18653: // Excalibur 90 + case 18667: // Excalibur 95 + case 19748: // Excalibur 99 + case 19841: // Excalibur 99-2 + + case 18282: // Ragnarok 75 + case 18283: // Ragnarok 80 + case 18640: // Ragnarok 85 + case 18654: // Ragnarok 90 + case 18668: // Ragnarok 95 + case 19749: // Ragnarok 99 + case 19842: // Ragnarok 99-2 + + case 18288: // Guttler 75 + case 18289: // Guttler 80 + case 18641: // Guttler 85 + case 18655: // Guttler 90 + case 18669: // Guttler 95 + case 19750: // Guttler 99 + case 19843: // Guttler 99-2 + + case 18300: // Gungnir 75 + case 18301: // Gungnir 80 + case 18643: // Gungnir 85 + case 18657: // Gungnir 90 + case 18671: // Gungnir 95 + case 19752: // Gungnir 99 + case 19845: // Gungnir 99-2 + + case 18318: // Amanomurakumo 75 + case 18319: // Amanomurakumo 80 + case 18646: // Amanomurakumo 85 + case 18660: // Amanomurakumo 90 + case 18674: // Amanomurakumo 95 + case 19755: // Amanomurakumo 99 + case 19848: // Amanomurakumo 99-2 + + case 18330: // Claustrum 75 + case 18331: // Claustrum 80 + case 18648: // Claustrum 85 + case 18662: // Claustrum 90 + case 18676: // Claustrum 95 + case 19757: // Claustrum 99 + case 19850: // Claustrum 99-2 + if (rand()%100 <= 16) + { + originalDamage = (damage * (float)2.5); + } break; // Relic: 3 times damage - case 18270: // Mandau, dagger - case 18312: // Kikoku, katana - case 18324: // Mjollnir, club - case 18336: // Annihilator, marksmanship - case 18348: // Yoichinoyumi, archery - if (rand()%100 >= 16) return originalDamage; - return (damage = (damage * 3)); + case 18270: // Mandau 75 + case 18271: // Mandau 80 + case 18638: // Mandau 85 + case 18652: // Mandau 90 + case 18666: // Mandau 95 + case 19747: // Mandau 99 + case 19840: // Mandau 99-2 + + case 18312: // Kikoku 75 + case 18313: // Kikoku 80 + case 18645: // Kikoku 85 + case 18659: // Kikoku 90 + case 18673: // Kikoku 95 + case 19754: // Kikoku 99 + case 19847: // Kikoku 99-2 + + case 18324: // Mjollnir 75 + case 18325: // Mjollnir 80 + case 18647: // Mjollnir 85 + case 18661: // Mjollnir 90 + case 18675: // Mjollnir 95 + case 19756: // Mjollnir 99 + case 19849: // Mjollnir 99-2 + + case 18336: // Annihilator 75 + case 18337: // Annihilator 80 + case 18649: // Annihilator 85 + case 18663: // Annihilator 90 + case 18677: // Annihilator 95 + case 19758: // Annihilator 99 + case 19851: // Annihilator 99-2 + + case 18348: // Yoichinoyumi 75 + case 18349: // Yoichinoyumi 80 + case 18650: // Yoichinoyumi 85 + case 18664: // Yoichinoyumi 90 + case 18678: // Yoichinoyumi 95 + case 19759: // Yoichinoyumi 99 + case 19852: // Yoichinoyumi 99-2 + if (rand()%100 <= 16) + { + originalDamage = (damage * 3); + } break; // Relic: 2 times damage - case 18294: // Bravura, great axe - case 18306: // Apocalypse, scythe - if (rand()%100 >= 16) return originalDamage; - return (damage = (damage * 2)); + case 18294: // Bravura 75 + case 18295: // Bravura 80 + case 18642: // Bravura 85 + case 18656: // Bravura 90 + case 18670: // Bravura 95 + case 19751: // Bravura 99 + case 19844: // Bravura 99-2 + + case 18306: // Apocalypse 75 + case 18307: // Apocalypse 80 + case 18644: // Apocalypse 85 + case 18658: // Apocalypse 90 + case 18672: // Apocalypse 95 + case 19753: // Apocalypse 99 + case 19846: // Apocalypse 99-2 + + if (rand()%100 <= 16) + { + originalDamage = (damage * 2); + } break; + + // Aftermath Empyrean Weapons 2x Dmg + case 19460: // Farsha 85 + case 19538: // Farsha 90 + case 19636: // Farsha 95 + case 19809: // Farsha 99 + case 19857: // Farsha 99-2 + + case 19461: // Ukonvasara 85 + case 19539: // Ukonvasara 90 + case 19637: // Ukonvasara 95 + case 19810: // Ukonvasara 99 + case 19858: // Ukonvasara 99-2 + + case 19466: // Gambanteinn 85 + case 19544: // Gambanteinn 90 + case 19642: // Gambanteinn 95 + case 19815: // Gambanteinn 99 + case 19863: // Gambanteinn 99-2 + + case 19457: // Twashtar 85 + case 19535: // Twashtar 90 + case 19633: // Twashtar 95 + case 19806: // Twashtar 99 + case 19854: // Twashtar 99-2 + + case 19456: // Verethragna 85 + case 19534: // Verethragna 90 + case 19632: // Verethragna 95 + case 19805: // Verethragna 99 + case 19853: // Verethragna 99-2 + + case 19464: // Kannagi 85 + case 19542: // Kannagi 90 + case 19640: // Kannagi 95 + case 19813: // Kannagi 99 + case 19861: // Kannagi 99-2 + + case 19465: // Masamune 85 + case 19543: // Masamune 90 + case 19641: // Masamune 95 + case 19814: // Masamune 99 + case 19862: // Masamune 99-2 + + case 19463: // Rhongomiant 85 + case 19541: // Rhongomiant 90 + case 19639: // Rhongomiant 95 + case 19812: // Rhongomiant 99 + case 19860: // Rhongomiant 99-2 + + case 19462: // Redemption 85 + case 19540: // Redemption 90 + case 19638: // Redemption 95 + case 19811: // Redemption 99 + case 19859: // Redemption 99-2 + + case 19467: // Hvergelmir 85 + case 19545: // Hvergelmir 90 + case 19643: // Hvergelmir 95 + case 19816: // Hvergelmir 99 + case 19864: // Hvergelmir 99-2 + + case 19458: // Almace 85 + case 19536: // Almace 90 + case 19634: // Almace 95 + case 19807: // Almace 99 + case 19855: // Almace 99-2 + + case 19459: // Caladbolg 85 + case 19537: // Caladbolg 90 + case 19635: // Caladbolg 95 + case 19808: // Caladbolg 99 + case 19856: // Caladbolg 99-2 + + case 19468: // Gandiva 85 + case 19546: // Gandiva 90 + case 19644: // Gandiva 95 + case 19817: // Gandiva 99 + case 19865: // Gandiva 99-2 + + case 19469: // Armageddon 85 + case 19547: // Armageddon 90 + case 19645: // Armageddon 95 + case 19818: // Armageddon 99 + case 19866: // Armageddon 99-2 + + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AFTERMATH_LV1) == true) + { + if (rand()%100 <= 30) + { + // ShowDebug(CL_CYAN"Aftermath Lvl 1 Proc \n"); + originalDamage = (damage * 2); + } + } + else if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AFTERMATH_LV2) == true) + { + if (rand()%100 <= 40) + { + // ShowDebug(CL_CYAN"Aftermath Lvl 2 Proc \n"); + originalDamage = (damage * 2); + } + } + else if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AFTERMATH_LV3) == true) + { + if (rand()%100 <= 50) + { + // ShowDebug(CL_CYAN"Aftermath Lvl 3 Proc \n"); + originalDamage = (damage * 2); + } + } + break; + + // Aftermath Lvl 3 Mythic Weapons: 2x Dmg + case 19001: // Gastraphetes 75 + + case 19007: // Death Penalty 75 + + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AFTERMATH_LV3) == true) + { + if (rand()%100 <= 40) + { + // ShowDebug(CL_CYAN"Aftermath Lvl 3 2x Proc 40 Percent \n"); + originalDamage = (damage * 2); + } + } + break; + + case 19070: // Gastraphetes 80 + case 19090: // Gastraphetes 85 + case 19622: // Gastraphetes 90 + + case 19076: // Death Penalty 80 + case 19096: // Death Penalty 85 + case 19628: // Death Penalty 90 + + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AFTERMATH_LV3) == true) + { + if (rand()%100 <= 60) + { + // ShowDebug(CL_CYAN"Aftermath Lvl 3 2x Proc 60 Percent \n"); + originalDamage = (damage * 2); + } + } + break; + + // Aftermath Lvl 3 Mythic Weapons: 2x-3x Dmg + case 19720: // Gastraphetes 95 + case 19829: // Gastraphetes 99 + case 19958: // Gastraphetes 99-2 + + case 19726: // Death Penalty 95 + case 19835: // Death Penalty 99 + case 19964: // Death Penalty 99-2 + if(m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AFTERMATH_LV3) == true) + { + if (rand()%100 <= 60) + { + // ShowDebug(CL_CYAN"Aftermath Lvl 3 2x-3x Proc 60 Percent \n"); + if (rand()%100 < 50) + { + originalDamage = (damage * 2); + } + else + { + originalDamage = (damage * 3); + } + } + } + break; - //mythic weapons, same distribution as multi attacking weapons - - // Mythic: 2 time damage - case 19001: // Gastraphetes(lvl75), marksmanship - case 19007: // Death Penalty(lvl75), marksmanship - if (rand()%100 < 55) return originalDamage; - return (damage = (damage * 2)); + // Magnus Stone Weapons + case 18533: // Magnus Axe + case 19168: // Magnus Claymore + case 19131: // Magnus Dagger + case 17047: // Magnus Hammer + case 19313: // Magnus Lance + case 18620: // Magnus Pole + case 18777: // Magnus Sainti + case 18967: // Magnus Scythe + case 18893: // Magnus Sword + case 18514: // Magnus Toporok + case 19289: // Toki + case 18456: // Yoshihiro + if(PAmmo->getID() == 19262) + { + if (rand()%100 > 50) + { + // ShowDebug(CL_CYAN"Magnus Weapon Proc \n"); + if ( (PAmmo->getQuantity()-1) < 1) // ammo will run out after this attack, make sure we remove it from equip + { + uint8 slot = m_PChar->equip[SLOT_AMMO]; + charutils::UnequipItem(m_PChar,SLOT_AMMO); + charutils::UpdateItem(m_PChar, LOC_INVENTORY, slot, -1); + } + else + { + charutils::UpdateItem(m_PChar, LOC_INVENTORY, m_PChar->equip[SLOT_AMMO], -1); + } + m_PChar->pushPacket(new CInventoryFinishPacket()); + originalDamage = (damage * 2); + } + } break; - default: - return originalDamage; // just to be sure break; } + + return originalDamage; - - } @@ -478,27 +774,284 @@ { // check for special damage reducing gear CItemArmor* PArmor = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_BACK]); - + CItemArmor* PHead = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_HEAD]); + CItemArmor* PBack = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_BACK]); + uint32 originalDamage = damage; if(PArmor != NULL) { switch(PArmor->getID()) { - //shadow mantle 10% chance to annual damage + // Shadow Mantle 10% chance to annual damage case 13658: - if (rand()%100 > 10) return originalDamage; - damage = 0; + if (rand()%100 > 10) + { + damage = 0; + } break; default: - return originalDamage; + break; } } + if(PHead != NULL) + { + switch(PHead->getID()) + { + // Nocturnus Helm 5% chance to absorb damage + case 11501: + if (rand()%100 <= 5) + { + PChar->addHP(damage); + charutils::UpdateHealth((CCharEntity*)PChar); + PChar->loc.zone->PushPacket(PChar,CHAR_INRANGE_SELF, new CMessageBasicPacket(PChar,PChar,0,damage, 263)); + damage = 0; + } + break; + + + default: + break; + } + } + if(PBack != NULL) + { + switch(PBack->getID()) + { + // Archon Cape 5% chance to annul "severe" physical damage + case 10975: + if ((ceil((float)(((float)damage / (float)PChar->GetMaxHP())) * 100)) > 50) + { + if (rand()%100 <= 5) + { + damage = 0; + } + } + break; + + + default: + break; + } + } return damage; } +uint32 HandleDamageToMP(CCharEntity* PChar, uint32 damage, apAction_t* Action) +{ + // check for gear + CItemArmor* PEarring1 = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_EAR1]); + CItemArmor* PEarring2 = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_EAR2]); + CItemArmor* PWaist = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_WAIST]); + CItemArmor* PHead = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_HEAD]); + CItemArmor* PBody = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_BODY]); + + uint32 damageToMP = 0; + if(PEarring1 != NULL) + { + switch(PEarring1->getID()) + { + //Ethereal Earring + case 15965: + damageToMP = damage * .03; + break; + + + default: + break; + } + } + if(PEarring2 != NULL) + { + switch(PEarring2->getID()) + { + //Ethereal Earring + case 15965: + damageToMP = damage * .03; + break; + + + default: + break; + } + } + if(PBody != NULL) + { + switch(PBody->getID()) + { + //Valor Surcoat + case 15093: + //Valor Surcoat +1 + case 14506: + if(PChar->StatusEffectContainer->HasStatusEffect(EFFECT_COVER)) + { + damageToMP = damage * .2; + break; + } + + //Valor Surcoat +2 + case 10676: + if(PChar->StatusEffectContainer->HasStatusEffect(EFFECT_COVER)) + { + damageToMP = damage * .3; + break; + } + + default: + break; + } + } + if(PWaist != NULL) + { + switch(PWaist->getID()) + { + //Flume Belt + case 10819: + damageToMP = damage * .02; + break; + + + default: + break; + } + } + if(PHead != NULL) + { + switch(PHead->getID()) + { + //Creed Armet +1 + case 11170: + damageToMP = damage * .03; + break; + + //Creed Armet +1 + case 11070: + damageToMP = damage * .05; + break; + + default: + break; + } + } + + return damageToMP; + +} + +uint32 HandleDamageToTP(CCharEntity* PChar, uint32 damage, apAction_t* Action) +{ + // check for gear + CItemArmor* PShield = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_EAR1]); + CItemArmor* PArmor = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_BODY]); + + uint32 damageToTP = 0; + if(PShield != NULL) + { + switch(PShield->getID()) + { + //Butznar Shield + case 28671: + damageToTP = damage * .005; + break; + + //Butznar Shield +1 + case 28669: + damageToTP = damage * .005; + break; + + + default: + break; + } + } + if(PArmor != NULL) + { + switch(PArmor->getID()) + { + //Mekira Toshugai + case 11865: + damageToTP = damage * .01; + break; + + //Mekira Toshugai +1 + case 11871: + damageToTP = damage * .012; + break; + + //Mekira Meikogai + case 11868: + damageToTP = damage * .014; + break; + + //Myochin Domaru + case 13781: + if(rand()%100 <= 10) + { + damageToTP = damage * .01; + } + break; + + //Myochin Domaru +1 + case 14484: + if(rand()%100 <= 15) + { + damageToTP = damage * .012; + } + break; + + + default: + break; + } + } + + return damageToTP; + +} + +uint32 HandleBlockToMP(CCharEntity* PChar, uint32 damage, apAction_t* Action) +{ + if(PChar->objtype == TYPE_PC) + { + // check for gear + CItemArmor* PShield = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_SUB]); + + uint32 blockToMP = 0; + if(PShield != NULL) + { + switch(PShield->getID()) + { + //Ochain - 90 + case 16193: + blockToMP = damage * .25; + break; + + //Ochain - 95 + case 16194: + blockToMP = damage * .30; + break; + + //Ochain - 99 + case 16199: + //Ochain - 99 - 2 + case 11926: + blockToMP = damage * .35; + break; + + default: + break; + } + } + return blockToMP; + } + else + { + return 0; + } +} + uint16 CalculateSpikeDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, uint8 spikesType, uint16 damageTaken) { uint16 damage = PDefender->getMod(MOD_SPIKES_DMG); @@ -509,16 +1062,16 @@ case SPIKE_DREAD: // drain same as damage taken damage = damageTaken; - break; + break; case SPIKE_REPRISAL: damage += (float)damageTaken*0.3; if(PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_SENTINEL)){ // bonus damage *= rand()%2+1; } - break; + break; default: - break; + break; } return damage; @@ -696,6 +1249,16 @@ spikesEffect = (SUBEFFECT)0; switch(PItem->getID()) { + case 11962: // Galvanic Slops + spikesEffect = SUBEFFECT_ICE_SPIKES; + damage = 25; + chance = 25; + break; + case 11948: // Staunch Cuisses + spikesEffect = SUBEFFECT_ICE_SPIKES; + damage = 20; + chance = 25; + break; case 12880: // ogre trousers spikesEffect = SUBEFFECT_ICE_SPIKES; damage = 15; @@ -799,6 +1362,12 @@ spikesEffect = (SUBEFFECT)0; switch(PItem->getID()) { + case 15018: // Ritterhentzes + case 11921: // Magma Gauntlets + spikesEffect = SUBEFFECT_BLAZE_SPIKES; + damage = 20; + chance = 20; + break; case 15042: // gothic gauntlets case 14952: // ice gauntlets spikesEffect = SUBEFFECT_ICE_SPIKES; @@ -844,6 +1413,11 @@ damage = 0; chance = 20; break; + case 11433: // Dornen Schuhs + spikesEffect = SUBEFFECT_SHOCK_SPIKES; + damage = 20; + chance = 25; + break; } if(spikesEffect && HandleSpikesEquip(PAttacker, PDefender, Action, damage, spikesEffect, chance)){ @@ -1046,20 +1620,20 @@ !PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_DRAIN_DAZE) && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_DRAIN_SAMBA)) { - PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_ASPIR_DAZE); - PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_HASTE_DAZE); + PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_ASPIR_DAZE); + PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_HASTE_DAZE); PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_DRAIN_DAZE,EFFECT_DRAIN_DAZE,10,0,10)); - } + } break; case ENSPELL_ASPIR_SAMBA: if (hitNumber <= 2 && PDefender->m_EcoSystem != SYSTEM_UNDEAD && !PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_ASPIR_DAZE) && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_ASPIR_SAMBA)) { - PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_DRAIN_DAZE); - PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_HASTE_DAZE); + PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_DRAIN_DAZE); + PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_HASTE_DAZE); PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_ASPIR_DAZE,EFFECT_ASPIR_DAZE,10,0,10)); - } + } case ENSPELL_HASTE_SAMBA: if (hitNumber <= 2 && !PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_HASTE_DAZE) && @@ -1093,7 +1667,7 @@ Samba -= lvlDiff; if (Samba > (finaldamage / 2)){ - Samba = finaldamage / 2; + Samba = finaldamage / 2; } if(finaldamage <= 2){ @@ -1138,33 +1712,1010 @@ // no enspells active, check weapon additional effects CItemWeapon* PWeapon = (CItemWeapon*)PAttacker->getStorage(LOC_INVENTORY)->GetItem(PAttacker->equip[SLOT_MAIN]); - + CItemWeapon* PAmmo = (CItemWeapon*)PAttacker->getStorage(LOC_INVENTORY)->GetItem(PAttacker->equip[SLOT_AMMO]); + int ammoUse = 0; + int tizonaChance = 0; + int tizonaPercent = 0; + if (Action->animation == 1) PWeapon = (CItemWeapon*)PAttacker->getStorage(LOC_INVENTORY)->GetItem(PAttacker->equip[SLOT_SUB]); if(PWeapon != NULL) { EFFECT dispelled; + uint8 chance = 0; + uint8 effect = 0; switch(PWeapon->getID()) { - //Additional Effect: HP drain Weapons - case 16827: - case 16528: - case 16824: - case 17651: - case 16556: - case 16609: - case 16580: - case 17646: - case 16777: - case 16791: - case 16846: - case 16881: - case 17561: - case 17562: - case 17778: - case 17779: - case 17576: - case 17510: + // Additional Effect vs. Vermin: HP Drain + case 18428: // Kogitsunemaru + if(PDefender->m_EcoSystem == SYSTEM_VERMIN) + { + effect = 1; + } + return; + //Additional Effect: HP Drain Weapons + case 16827: // Carnage Blade + case 16528: // Bloody Rapier + case 16824: // Carnage Rapier + case 17651: // Dainslaif + case 16556: // Bloody Blade + case 16609: // Bloody Sword + case 16580: // Bloodsword + case 17646: // Carnage Sword + case 16777: // Death Scythe + case 16791: // Death Scythe +1 + case 16846: // Bloody Lance + case 16881: // Carnage Lance + case 17561: // Revenging Staff + case 17562: // Revenging Staff +1 + case 17778: // Muketsu + case 17779: // Muketsu +1 + case 17576: // Grim Staff + case 17510: // Vampiric Claws + case 18810: // Cadushi Grip + case 16582: // Vetala Sword + case 18859: // Kerykeion + case 18785: // Grotesque Cesti + case 18908: // Dhampyr Sword + case 18856: // Deae Gratia + { + effect = 1; + } + break; + + //Additional Effect: MP Recover + case 18324: // Mjollnir Lvl 75 + case 18325: // Mjollnir Lvl 80 + case 18647: // Mjollnir Lvl 85 + case 18661: // Mjollnir Lvl 90 + case 18675: // Mjollnir Lvl 95 + case 19756: // Mjollnir Lvl 99 + case 19849: // Mjollnir Lvl 99 - 2 + { + effect = 2; + } + break; + + //Additional Effect: TP drain Weapons + case 18904: // Ephemeron + case 19795: // Ereptor Lance + case 19160: // Estramacon + case 18437: // Namikirimaru + case 17823: // Shinsoku + { + effect = 3; + } + break; + + //Additional Effect: MP drain Weapons + case 17574: // Archalaus's Pole + case 16509: // Aspir Knife + case 18948: // Enforcer + case 17430: // Fey Wand + case 18047: // Havoc Scythe + case 17718: // Leech Scimitar + case 18941: // Naigama + case 18942: // Naigama +1 + case 18599: // Pestle + { + chance = 10; + effect = 4; + } + break; + case 17072: // Lilith's Rod + { + chance = 20; + chance += rand()%11; + effect = 4; + } + break; + + //Additional Effect: HP or MP drain Weapons + case 17745: // Hofud + { + effect = 5; + } + break; + + //Additional Effect: HP, MP, or TP drain Weapons + case 19132: // Twilight Knife + { + if (rand()%100 <= 30) + { + int randomEffect = rand()%3; + if (randomEffect == 0) + { + effect =1; + } + else if (randomEffect == 1) + { + chance = 100; + effect = 4; + } + else + { + effect = 3; + } + } + } + break; + // Additional Effect vs. Vermin: Stun + case 18040: // Webcutter + if(PDefender->m_EcoSystem == SYSTEM_VERMIN) + { + effect = 6; + } + break; + //Additional Effect: Stun Weapons (5% chance guestimate) + case 19177: // Etourdissante + case 19178: // Etourdissante +1 + case 16910: // Mamushito + case 17770: // Mamushito +1 + case 19019: // Platinum Grip + case 19020: // Platinum Grip +1 + case 17464: // Purgatory Mace + case 16431: // Stun Claws + case 17486: // Stun Claws +1 + case 16432: // Stun Jamadhars + case 17484: // Stun Jamadhars +1 + case 16503: // Stun Knife + case 17600: // Stun Knife +1 + case 16506: // Stun Kukri + case 17614: // Stun Kukri +1 + { + effect = 6; + } + break; + + // Additional Effect vs. Tigers: Paralysis + case 16672: // Tigerhunter + if(((CMobEntity*)PDefender)->m_Family == 242) + { + effect = 7; + } + break; + //Additional Effect: Paralysis Weapons (5% chance guestimate) + case 17737: // Corsair's Scimitar + case 18762: // Custodes + case 17648: // Dragvandil + case 18211: // Gawain's Axe + case 18312: // Kikoku Lvl 75 + case 18313: // Kikoku Lvl 80 + case 18645: // Kikoku Lvl 85 + case 18659: // Kikoku Lvl 90 + case 18673: // Kikoku Lvl 95 + case 19754: // Kikoku Lvl 99 + case 19847: // Kikoku Lvl 99 - 2 + case 19796: // Rosschinder + case 19797: // Rosschinder +1 + case 17492: // Shiva's Claws + { + effect = 7; + } + break; + + // Additional Effect: Petrify (5% chance guestimate) + case 18454: // Ishikirimaru + { + effect = 8; + } + break; + + // Additional Effect: Terror (5% chance guestimate) + case 19163: // Nightfall + { + effect = 9; + } + break; + + // Additional Effect: Addle (5% chance guestimate) + case 19316: // Fetter Lance + { + effect = 10; + } + break; + + // Additional Effect: Choke (5% chance guestimate) + case 18288: // Guttler Lvl 75 + case 18289: // Guttler Lvl 80 + case 18641: // Guttler Lvl 85 + case 18655: // Guttler Lvl 90 + case 18669: // Guttler Lvl 95 + case 19750: // Guttler Lvl 99 + case 19843: // Guttler Lvl 99 - 2 + { + effect = 11; + } + break; + + // Additional Effect vs. Plantoids: Weight + case 16785: // Harvester + if(PDefender->m_EcoSystem == SYSTEM_PLANTOID) + { + effect = 12; + } + break; + // Additional Effect: Weight (5% chance guestimate) + case 18096: // Heavy Lance + case 18026: // Magnet Knife + case 19140: // Mantodea Harpe + { + effect = 12; + } + break; + + // Additional Effect: Amnesia (5% chance guestimate) + case 18510: // Vermeil Bhuj + { + effect = 13; + } + break; + + // Additional Effect vs. Plantoids: Bind + case 16783: // Plantreaper + if(PDefender->m_EcoSystem == SYSTEM_PLANTOID) + { + effect = 14; + } + break; + // Additional Effect vs. Birds: Bind + case 18044: // Scarecrow Scythe + if(PDefender->m_EcoSystem == SYSTEM_BIRD) + { + effect = 14; + } + break; + // Additional Effect vs. Arcana: Bind + case 17058: // Caduceus + if(PDefender->m_EcoSystem == SYSTEM_ARCANA) + { + effect = 14; + } + break; + // Additional Effect: Bind (5% chance guestimate) + case 16897: // Kageboshi + { + effect = 14; + } + break; + + // Additional Effect: Slow (5% chance guestimate) + case 17083: // Time Hammer + { + effect = 15; + } + break; + + // Additional Effect: Flash (5% chance guestimate) + case 17069: // Moepapa Mace + { + effect = 16; + } + break; + + // Additional Effect: Reduce Enemy TP (2% chance guestimate) + case 19298: // Ikarigiri + { + effect = 17; + } + break; + + // Additional Effect: STR Boost 10% ?? + case 17563: // Power Staff + { + effect = 18; + } + break; + + // Additional Effect: Haste (7% chance guestimate) + case 16504: // Oynos Knife + { + effect = 19; + } + break; + + // Additional Effect: Blink (15% chance guestimate) + case 18830: // Gusterion + { + effect = 20; + } + break; + + //Additional Effect: Poison Weapons (5% chance guestimate) + case 16907: // Busuto + case 16927: // Busuto +1 + case 16525: // Hornet Fleuret + case 16909: // Kororito + case 17769: // Kororito +1 + case 17937: // Leopard Axe + case 18270: // Mandau Lvl 75 + case 18271: // Mandau Lvl 80 + case 18638: // Mandau Lvl 85 + case 18652: // Mandau Lvl 90 + case 18666: // Mandau Lvl 95 + case 19747: // Mandau Lvl 99 + case 19840: // Mandau Lvl 99 - 2 + case 17650: // Nadrs + case 16458: // Poison Baselard + case 16387: // Poison Cesti + case 16700: // Poison Cesti +1 + case 16417: // Poison Claws + case 16439: // Poison Claws +1 + case 16496: // Poison Dagger + case 16741: // Poison Dagger +1 + case 16403: // Poison Katars + case 16693: // Poison Katars +1 + case 16472: // Poison Knife + case 16742: // Poison Knife +1 + case 16478: // Poison Kukri + case 16488: // Poison Kukri +1 + case 16410: // Poison Baghnakhs + case 16692: // Poison Baghnakhs +1 + case 16743: // Python Baselard + case 16507: // Venom Baselard + case 16510: // Venom Baselard +1 + case 16418: // Venom Claws + case 16425: // Venom Claws +1 + case 16404: // Venom Katars + case 17483: // Venom Katars +1 + case 16502: // Venom Knife + case 16762: // Venom Knife +1 + case 16499: // Venom Kris + case 16761: // Venom Kris +1 + case 16505: // Venom Kukri + case 17604: // Venom Kukri +1 + case 17959: // Viperine Pick + case 17634: // Wasp Fleuret + { + effect = 21; + } + break; + + // Additional Effect: Poisone, Paralysis, or Bind (5% chance guestimate) + case 18784: // Metasoma Katars + if (rand()%100 <= 5) + { + int metasomaEffect = rand()%3; + if (metasomaEffect == 0) + { + effect = 21; + } + else if (metasomaEffect == 1) + { + effect = 7; + } + else + { + effect = 14; + } + } + break; + + // Additional Effect: Blind (5% chance guestimate) + case 18306: // Apocalypse Lvl 75 + case 18307: // Apocalypse Lvl 80 + case 18644: // Apocalypse Lvl 85 + case 18658: // Apocalypse Lvl 90 + case 18672: // Apocalypse Lvl 95 + case 19753: // Apocalypse Lvl 99 - 1 + case 19846: // Apocalypse Lvl 99 - 2 + case 16454: // Blind Dagger + case 16493: // Blind Dagger +1 + case 16471: // Blind Knife + case 16490: // Blind Knife +1 + case 16905: // Bokuto + case 16926: // Bokuto +1 + { + effect = 22; + } + break; + + // Additional Effect: Silence (5% chance guestimate) + case 17627: // Garuda's Dagger + case 18355: // Hushed Baghnakhs + case 18008: // Hushed Dagger + case 16906: // Mokuto + case 16925: // Mokuto +1 + case 17797: // Seito + case 16495: // Silence Dagger + case 16508: // Silence Dagger +1 + case 16429: // Silence Baghnakhs + case 16438: // Silence Baghnakhs +1 + { + effect = 23; + } + break; + + // Additional Effect: Curse (5% chance guestimate) + case 16533: // Ancient Sword + case 17116: // Misery Staff + case 18813: // Ultio Grip + { + effect = 24; + } + break; + + // Additional Effect: Death (2% chance guestimate) + case 18916: // Heimdall's Doom + case 18551: // Twilight Scythe + { + effect = 25; + } + break; + + // Additional Effect: Sleep (5% chance guestimate) + case 17117: // Hypno Staff + case 16497: // Sleep Dagger + case 17575: // Somnus Signa + { + effect = 26; + } + break; + + + // Additional Effect: Impairs Evasion (5% chance guestimate) + case 18032: // Adder Jambiya + case 18033: // Adder Jambiya +1 + case 17695: // Bayard's Sword + case 18294: // Bravura Lvl 75 + case 18295: // Bravura Lvl 80 + case 18642: // Bravura Lvl 85 + case 18656: // Bravura Lvl 90 + case 18670: // Bravura Lvl 95 + case 19751: // Bravura Lvl 99 + case 19844: // Bravura Lvl 99 - 2 + case 16773: // Cruel Scythe + case 16863: // Cruel Spear + case 18118: // Dark Mezraq + case 18119: // Dark Mezraq +1 + case 16974: // Dotanuki + case 18110: // Mezraq + case 18111: // Mezraq +1 + case 18123: // Thalassocrat + case 18124: // Thalassocrat +1 + { + effect = 27; + } + break; + + // Additional Effect vs. Dolls: Weakens Defense + case 16674: // Emeth Pick + if((((CMobEntity*)PDefender)->m_Family == 83) || ((CMobEntity*)PDefender)->m_Family == 84 + || ((CMobEntity*)PDefender)->m_Family == 85) + { + effect = 28; + } + break; + + // Additional Effect vs. Arcana Weakens Defense + case 17416: // Arcana Breaker + if(PDefender->m_EcoSystem == SYSTEM_ARCANA) + { + effect = 28; + } + break; + + // Additional Effect Weakens Defense + case 16430: // Acid Claws + case 16459: // Acid Baselard + case 17605: // Acid Dagger + case 16501: // Acid Knife + case 16479: // Acid Kukri + case 18794: // Blutklauen + case 18793: // Blutkrallen + case 17487: // Corrosive Claws + case 17607: // Corrosive Baselard + case 17606: // Corrosive Dagger + case 17608: // Corrosive Knife + case 16494: // Corrosive Kukri + case 17694: // Guespiere + case 18300: // Gungnir Lvl 75 + case 18301: // Gungnir Lvl 80 + case 18643: // Gungnir Lvl 85 + case 18657: // Gungnir Lvl 90 + case 18671: // Gungnir Lvl 95 + case 19752: // Gungnir Lvl 99 + case 19845: // Gungnir Lvl 99 - 2 + case 18357: // Melt Claws + case 18012: // Melt Baselard + case 18010: // Melt Dagger + case 18011: // Melt Knife + case 18013: // Melt Kukri + case 18410: // Melt Katana + case 20639: // Oxidant Baselard + case 20640: // Nitric Baselard + case 21009: // Nakajimarai + case 21010: // Nakajimarai +1 + case 17106: // Rockmasher + case 16908: // Yoto + case 17768: // Yoto +1 + { + effect = 28; + } + break; + + // Additional Effect: Weakens Attacks 5% ?? + case 18318: // Amanomurakumo Lvl 75 + case 18319: // Amanomurakumo Lvl 80 + case 18646: // Amanomurakumo Lvl 85 + case 18660: // Amanomurakumo Lvl 90 + case 18674: // Amanomurakumo Lvl 95 + case 19775: // Amanomurakumo Lvl 99 + case 19848: // Amanomurakumo Lvl 99 - 2 + case 18088: // Dreizack + { + effect = 29; + } + break; + + // Additional Effect vs. Beasts: Darkness Damage + case 18041: // A L'Outrance + if(PDefender->m_EcoSystem == SYSTEM_BEAST) + { + chance = 100; + effect = 30; + } + break; + // Additional Effect: Darkness Damage (5% chance guestimate) + case 18961: // Plaga Scythe + case 16515: // Colichemarde + case 17632: // Colichemarde +1 + case 16787: // Demon Slicer + case 17559: // Dark Staff + case 17560: // Pluto's Staff + case 16936: // Demonic Sword + { + chance = 5; + effect = 30; + } + break; + + // Additional Effect: Earth Damage (5% chance guestimate) + case 17552: // Terra Staff + case 18501: // Seismic Axe + case 17807: // Gold Musketeers Uchigatana + case 19114: // Galkan Dagger + case 17076: // Earth Wand + case 17551: // Earth Staff + case 17438: // Titan's Cudgel + { + effect = 31; + } + break; + + // Additional Effect vs. Undead: Fire Damage + case 18042: // Ascention + if(PDefender->m_EcoSystem == SYSTEM_UNDEAD) + { + effect = 32; + } + break; + // Additional Effect vs. Plantoids: Fire Damage + case 16720: // Plantbane + if(PDefender->m_EcoSystem == SYSTEM_PLANTOID) + { + effect = 32; + } + break; + // Additional Effect: Fire Damage (5% chance guestimate) + case 18385: // Agol + case 19151: // Bahdur + case 19152: // Bahdur +1 + case 19296: // Ban + case 16398: // Burning Cesti + case 16929: // Burning Claymore + case 16416: // Dragon Claws + case 17485: // Dragon Claws +1 + case 17545: // Fire Staff + case 16543: // Fire Sword + case 16564: // Flame Blade + case 16804: // Flame Blade +1 + case 16588: // Flame Claymore + case 16522: // Flame Degen + case 16823: // Flame Degen +1 + case 16621: // Flame Sword + case 18625: // Gerra's Staff + case 16713: // Hellfire Axe + case 16928: // Hellfire Sword + case 16973: // Homura + case 16986: // Homura +1 + case 17665: // Ifrit's Blade + case 16709: // Inferno Axe + case 16594: // Inferno Sword + case 17828: // Koen + case 18220: // Prominence Axe + case 18381: // Prominence Sword + case 18043: // Suzaku's Scythe + case 17706: // Vulcan Blade + case 18379: // Vulcan Claymore + case 17705: // Vulcan Degen + case 17704: // Vulcan Sword + case 17546: // Vulcan's Staff + { + effect = 32; + } + break; + + // Additional Effect vs. Slimes: Light Damage + case 17981: // Ban Del Sol + if((((CMobEntity*)PDefender)->m_Family == 228) || ((CMobEntity*)PDefender)->m_Family == 229 + || ((CMobEntity*)PDefender)->m_Family == 230) + { + effect = 33; + } + break; + // Additional Effect vs. Orcs: Light Damage + case 16867: // Orc Piercer + if((((CMobEntity*)PDefender)->m_Family == 189) || ((CMobEntity*)PDefender)->m_Family == 190 + || ((CMobEntity*)PDefender)->m_Family == 248 || ((CMobEntity*)PDefender)->m_Family == 334) + { + effect = 33; + } + break; + // Additional Effect vs. Gigas: Light Damage + case 16956: // Skofnung + if(((((CMobEntity*)PDefender)->m_Family >= 126) && (((CMobEntity*)PDefender)->m_Family <= 130)) + || ((CMobEntity*)PDefender)->m_Family == 328) + { + chance = 100; + effect = 33; + } + break; + // Additional Effect vs. Dragons: Light Damage + case 16943: // Ascalon + if(PDefender->m_EcoSystem == SYSTEM_DRAGON) + { + chance = 100; + effect = 33; + } + break; + // Additional Effect Night Time: Light Damage + case 17774: // Shiranui + if(CVanaTime::getInstance()->GetCurrentTOTD() == TIME_NIGHT) + { + chance = 20; + effect = 33; + } + break; + // Additional Effect: Light Damage (5% chance guestimate) + case 17558: // Apollo's Staff + case 18882: // Beaivi's Scepter + case 16549: // Divine Sword + case 16826: // Divine Sword +1 + case 16938: // Glorious Sword + case 16550: // Hallowed Sword + case 17738: // Hauteclaire + case 16523: // Holy Degen + case 16817: // Holy Degen +1 + case 16860: // Holy Lance + case 16880: // Holy Lance +1 + case 17041: // Holy Mace + case 17411: // Holy Mace +1 + case 17080: // Holy Maul + case 17114: // Holy Maul +1 + case 16581: // Holy Sword + case 16816: // Holy Sword +1 + case 17085: // Holy Wand + case 17434: // Holy Wand +1 + case 17557: // Light Staff + case 17414: // Pixie Mace + case 17683: // Sacred Degen + case 16858: // Sacred Lance + case 18391: // Sacred Mace + case 18392: // Sacred Maul + case 17682: // Sacred Sword + case 18393: // Sacred Wand + case 18853: // Spirit Maul + case 16613: // Spirit Sword + { + chance = 5; + effect = 33; + } + break; + + // Additional Effect vs. Undead: Water Damage + case 16884: // Narval + if(PDefender->m_EcoSystem == SYSTEM_UNDEAD) + { + effect = 34; + } + break; + // Additional Effect: Water Damage with Pump + case 17512: // Hydro Baghnakhs + case 17513: // Hydro Baghnakhs +1 + case 18200: // Hydro Axe + case 18201: // Hydro Baghnakhs +1 + case 18204: // Hydro Chopper + case 18205: // Hydro Chopper +1 + case 17514: // Hydro Claws + case 17515: // Hydro Claws +1 + case 18202: // Hydro Cutter + case 18203: // Hydro Cutter +1 + case 17516: // Hydro Patas + case 17517: // Hydro Patas +1 + if (PAmmo->getID() == 18232 || PAmmo->getID() == 18233 || PAmmo->getID() == 18234) + { + chance = 10; + chance += rand()%6; + ammoUse = 1; + effect = 36; + } + break; + + // Additional Effect: Water Damage (5% chance guestimate) + case 17750: // Anthos Xiphos + case 16945: // Arondight + case 18953: // Beluga + case 17623: // Bmt. Knife + case 16548: // Coral Sword + case 17134: // Dolphin Staff + case 18109: // Leviathan's Couse + case 17439: // Leviathan's Rod + case 16620: // Merman's Sword + case 16961: // Murasame + case 17556: // Neptune's Staff + case 17659: // Seiryu's Sword + case 17555: // Water Staff + case 17533: // Whale Staff + case 17534: // Whale Staff +1 + { + chance = 5; + effect = 34; + } + break; + + // Additional Effect vs. Lizards: Ice Damage + case 16853: // Lizard Piercer + if(PDefender->m_EcoSystem == SYSTEM_LIZARD) + { + effect = 35; + } + break; + // Additional Effect vs. Hounds + case 18199: // Ulfhedinn Axe + if(((CMobEntity*)PDefender)->m_Family == 142 || ((CMobEntity*)PDefender)->m_Family == 143) + { + effect = 35; + } + break; + // Additional Effect: Ice Damage (5% chance guestimate) + case 17548: // Aquilo's Staff + case 16702: // Cougar Baghnakhs + case 16784: // Frostreaper + case 16937: // Ice Brand + case 16861: // Ice Lance + case 16895: // Ice Lance +1 + case 17547: // Ice Staff + case 18503: // Mammut + case 17711: // Shiva's Shotel + case 17135: // Walrus Staff + { + effect = 35; + } + break; + + // Additional Effect: Lightning Damage with Battery + case 17986: // Spark Baselard + case 17987: // Spark Baselard +1 + case 17686: // Spark Bilbo + case 17687: // Spark Bilbo +1 + case 17984: // Spark Dagger + case 17985: // Spark Dagger +1 + case 17688: // Spark Degen + case 17689: // Spark Degen +1 + case 18080: // Spark Fork + case 18081: // Spark Fork +1 + case 17988: // Spark Kris + case 17989: // Spark Kris +1 + case 18078: // Spark Lance + case 18079: // Spark Lance +1 + case 17690: // Spark Rapier + case 17691: // Spark Rapier +1 + case 18076: // Spark Spear + case 18077: // Spark Spear +1 + if (PAmmo->getID() == 18228 || PAmmo->getID() == 18229 || PAmmo->getID() == 18230) + { + chance = 10; + chance += rand()%6; + ammoUse = 1; + effect = 36; + } + break; + + // Additional Effect vs. Quadav: Lightning Damage + case 17415: // Shellbuster + if((((CMobEntity*)PDefender)->m_Family == 200) || ((CMobEntity*)PDefender)->m_Family == 201 + || ((CMobEntity*)PDefender)->m_Family == 202 || ((CMobEntity*)PDefender)->m_Family == 249 + || ((CMobEntity*)PDefender)->m_Family == 337) + { + chance = 10; + effect = 36; + } + break; + // Additional Effect: Lightning Damage (5% chance guestimate) + case 16888: // Battle Fork + case 16889: // Battle Fork +1 + case 18129: // Dabo + case 18130: // Dabo +1 + case 18104: // Fuscina + case 17071: // Heat Rod + case 17511: // Indra Katars + case 17554: // Jupiter's Staff + case 18210: // Raifu + case 18404: // Ramuh's Mace + case 17531: // Ramuh's Staff + case 17553: // Thunder Staff + case 16869: // Thundercloud + case 16837: // Trident + { + chance = 5; + effect = 36; + } + break; + + // Additional Effect: Wind Damage with Fan + case 18366: // Gust Claymore + case 18367: // Gust Claymore +1 + case 18368: // Gust Sword + case 18369: // Gust Sword +1 + case 18370: // Gust Tongue + case 18371: // Gust Tongue +1 + case 17784: // Keppu + case 17785: // Keppu +1 + case 17780: // Kyofu + case 17781: // Kyofu +1 + case 17782: // Reppu + case 17783: // Reppu +1 + if (PAmmo->getID() == 18236 || PAmmo->getID() == 18238 || PAmmo->getID() == 18237) + { + chance = 10; + chance += rand()%6; + ammoUse = 1; + effect = 37; + } + break; + // Additional Effect: Wind Damage (5% chance guestimate) + case 17550: // Auster's Staff + case 18198: // Byakko's Axe + case 16726: // Forseti's Axe + case 18451: // Mokusa + case 18027: // Palladium Dagger + case 18598: // Prester + case 17965: // Sirocco Axe + case 16434: // Sonic Knuckles + case 16675: // Storm Axe + case 16857: // Wind Spear + case 17549: // Wind Staff + case 16542: // Wing Sword + case 17637: // Wing Sword +1 + { + chance = 5; + effect = 37; + } + break; + case 18359: // Boreas Cesti + case 18018: // Sirocco Kukri + { + chance = 100; + effect = 37; + } + break; + + // Additional Effect: Flee (0-75% chance guestimate) + case 17615: // Chicken Knife + { + effect = 38; + } + break; + + //Additional Effect: Dispel Weapons (10% chance needs verifying) + case 16942: // Balmung + case 16944: // Lockheart + case 16950: // Mithril Heart + case 16951: // Mithril Heart +1 + case 18330: // Claustrum - 75 + case 18331: // Claustrum - 80 + case 18648: // Claustrum - 85 + case 18662: // Claustrum - 90 + case 18676: // Claustrum - 95 + case 19757: // Claustrum - 99 + case 19850: // Claustrum - 99 - 2 + { + effect = 39; + } + break; + + // Additional Effect Regen (7% Guestimate) + case 18887: // Dukkha + case 18525: // Himthige + { + effect = 40; + } + break; + + // Additional Effect: Ice Spikes (7% chance guestimate) + case 17564: // Cocytus Pole + { + effect = 41; + } + break; + // Additional Effect: Convert Damage to MP - Tizona + case 19006: // Tizona 75 + { + tizonaChance = rand()%2 + 10; + tizonaPercent = rand()%25 + 10; + effect = 42; + } + break; + case 19075: // Tizona 80 + { + tizonaChance = 15; + tizonaPercent = rand()%10 + 10; + effect = 42; + } + break; + case 19095: // Tizona 85 + { + tizonaChance = 20; + tizonaPercent = rand()%10 + 10; + effect = 42; + } + break; + case 19627: // Tizona 90 + case 19725: // Tizona 95 + { + tizonaChance = 25; + tizonaPercent = rand()%10 + 10; + effect = 42; + } + break; + case 19834: // Tizona 99 + case 19963: // Tizona 99-2 + { + tizonaChance = 30; + tizonaPercent = rand()%10 + 10; + effect = 42; + } + break; + // Additional Effect: Slashing Dmg based on HP Excaliburs + case 18276: // Excalibur 75 + case 18277: // Excalibur 80 + case 18639: // Excalibur 85 + case 18653: // Excalibur 90 + case 18667: // Excalibur 95 + case 19748: // Excalibur 99 + case 19841: // Excalibur 99-2 + { + effect = 43; + } + break; + // Additional Effect: Damage varies with MP + case 16540: // Tyrfing + { + effect = 44; + } + break; + // Additional Effect: Damage varies with TP + case 19315: // Erebus's Lance + if(PDefender->m_EcoSystem == SYSTEM_EMPTY) + { + effect = 45; + } + return; + + // Additional Effect: HP Recover + case 17429: // Dominion Mace + { + effect = 46; + } + return; + + default: + break; + } + switch(effect) + { + case 1: // HP Drain //30 % chance to drain, will heal 30% of damage done if (rand()%100 >= 30 || PWeapon==NULL) return; @@ -1174,18 +2725,762 @@ Action->subparam = (float)(Action->param * 0.3f); PAttacker->addHP(Action->subparam); + if(PAttacker->objtype == TYPE_PC) + { + charutils::UpdateHealth(PAttacker); + } + return; + case 2: // MP Recover + //30 % chance to Recover MP, 4-16 MP + if (rand()%100 <= 30) + { + Action->submessageID = 152; + Action->flag = 3; + int mpRecover = 4; + mpRecover = dsp_cap(mpRecover,4,16); + mpRecover += rand()%13; //4~16 randomised + Action->subparam = mpRecover; + PAttacker->addMP(Action->subparam); + + if(PAttacker->objtype == TYPE_PC){ + charutils::UpdateHealth(PAttacker); + } + } + return; + case 3: // TP Drain + //10 % chance to drain, will restore TP 10% of damage done + if (rand()%100 <= 10 || PWeapon==NULL) return; + + Action->subeffect = SUBEFFECT_TP_DRAIN; + Action->submessageID = 165; + Action->flag = 3; + Action->subparam = (float)(Action->param * 0.1f); + PAttacker->addTP(Action->subparam); + if(PAttacker->objtype == TYPE_PC){ charutils::UpdateHealth(PAttacker); } return; + case 4: // MP Drain + //10 % chance to drain, will restore MP 10% of damage done + if (rand()%100 <= chance || PWeapon==NULL) return; + Action->subeffect = SUBEFFECT_MP_DRAIN; + Action->submessageID = 162; + Action->flag = 3; + Action->subparam = (float)(Action->param * 0.1f); + PAttacker->addMP(Action->subparam); - //Additional Effect: Dispel Weapons (10% chance needs verifying) - case 16942: - case 16944: - case 16950: - case 16951: - case 18330: + if(PAttacker->objtype == TYPE_PC){ + charutils::UpdateHealth(PAttacker); + } + return; + case 5: // HP or MP Drain + //15 % chance to drain, will heal 7.5% of dmg done or restore mp 7.5% of dmg done + if (rand()%100 <= 15 || PWeapon==NULL) return; + if (rand()%2 == 1) + Action->subeffect = SUBEFFECT_HP_DRAIN; + Action->submessageID = 161; + Action->flag = 3; + Action->subparam = (float)(Action->param * 0.075f); + PAttacker->addHP(Action->subparam); + + + if(PAttacker->objtype == TYPE_PC){ + charutils::UpdateHealth(PAttacker); + } + else + Action->subeffect = SUBEFFECT_MP_DRAIN; + Action->submessageID = 162; + Action->flag = 3; + Action->subparam = (float)(Action->param * 0.075f); + PAttacker->addMP(Action->subparam); + + if(PAttacker->objtype == TYPE_PC){ + charutils::UpdateHealth(PAttacker); + } + return; + case 6: // Stun + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_STUNRES)) + { + if(PDefender->hasImmunity(8) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_STUN,EFFECT_STUN,1,0,4))) + { + Action->subeffect = SUBEFFECT_STUN; + Action->subparam = EFFECT_STUN; + Action->submessageID = 160; + Action->flag = 3; + } + } + } + } + return; + case 7: // Paralyze + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_PARALYZERES)) + { + if(PDefender->hasImmunity(32) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_PARALYSIS,EFFECT_PARALYSIS,20,0,10))) + { + Action->subeffect = SUBEFFECT_PARALYSIS; + Action->subparam = EFFECT_PARALYSIS; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 8: // Petrify + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_PETRIFYRES)) + { + // if(PDefender->hasImmunity(?) == false) // Petrify immunity unknown + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_PETRIFICATION,EFFECT_PETRIFICATION,1,0,30))) + { + Action->subeffect = SUBEFFECT_PETRIFY; + Action->subparam = EFFECT_PETRIFICATION; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + return; + case 9: // Terror + if (rand()%100 <= 5) + { + // if(PDefender->hasImmunity(?) == false) // Terror immunity unknown + if(rand()%100 >= PDefender->getMod(MOD_TERRORRES)) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_TERROR,EFFECT_TERROR,1,0,10))) + { + Action->subparam = EFFECT_TERROR; + Action->submessageID = 160; + Action->flag = 3; + } + } + + } + return; + case 10: // Addle + if (rand()%100 <= 5) + { + // if(PDefender->hasImmunity(?) == false) // Addle immunity unknown + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_ADDLE,EFFECT_ADDLE,1,0,10))) + { + Action->subparam = EFFECT_ADDLE; + Action->submessageID = 160; + Action->flag = 1; + } + } + return; + case 11: // Choke + if (rand()%100 <= 5) + { + // if(PDefender->hasImmunity(?) == false) // Choke immunity unknown + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_CHOKE,EFFECT_CHOKE,5,3,10))) + { + Action->subparam = EFFECT_ADDLE; + Action->submessageID = 160; + Action->flag = 1; + } + } + return; + case 12: // Weight + if (rand()%100 <= 5) + { + if(PDefender->hasImmunity(2) == false) + { + if(rand()%100 >= PDefender->getMod(MOD_GRAVITYRES)) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_WEIGHT,EFFECT_WEIGHT,50,0,30))) + { + Action->subeffect = SUBEFFECT_WEIGHT; + Action->subparam = EFFECT_WEIGHT; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 13: // Amnesia + if (rand()%100 <= 5) + { + // if(PDefender->hasImmunity(?) == false) // Amnesia immunity unknown + if(rand()%100 >= PDefender->getMod(MOD_AMNESIARES)) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_AMNESIA,EFFECT_AMNESIA,1,0,10))) + { + Action->subparam = EFFECT_AMNESIA; + Action->submessageID = 160; + Action->flag = 1; + } + } + + } + return; + case 14: // Bind + if (rand()%100 <= 5) + { + if(PDefender->hasImmunity(4) == false) + { + if(rand()%100 >= PDefender->getMod(MOD_BINDRES)) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_BIND,EFFECT_BIND,1,0,10))) + { + Action->subeffect = SUBEFFECT_BIND; + Action->subparam = EFFECT_BIND; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 15: // Slow + if (rand()%100 <= 5) + { + if(PDefender->hasImmunity(128) == false) + { + if(rand()%100 >= PDefender->getMod(MOD_SLOWRES)) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_HASTE,EFFECT_HASTE,-51,0,30))) + { + Action->subparam = EFFECT_HASTE; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 16: // Flash + if (rand()%100 <= 5) + { + if(PDefender->hasImmunity(64) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_FLASH,EFFECT_FLASH,100,0,30))) + { + Action->subeffect = SUBEFFECT_BLIND; + Action->subparam = EFFECT_FLASH; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + return; + case 17: // TP Removal + if (rand()%100 <= 2) + { + Action->submessageID = 363; + Action->flag = 3; + int tpRemove = 5; + tpRemove = dsp_cap(tpRemove,5,50); + tpRemove += rand()%46; //Random 5-50 + PDefender->addTP(-tpRemove); + + } + return; + case 18: // STR Boost + if (rand()%100 <= 10) + { + int strBoost = 5; + strBoost = dsp_cap(strBoost,5,7); + strBoost += rand()%3; //5~7 randomised + if(PAttacker->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_STR_BOOST,EFFECT_STR_BOOST,strBoost,0,30))) + { + Action->subparam = EFFECT_STR_BOOST; + Action->submessageID = 166; + Action->flag = 1; + } + } + return; + case 19: // Haste + if (rand()%100 <= 7) + { + if(PAttacker->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_HASTE,EFFECT_HASTE,307,0,30))) + { + Action->subparam = EFFECT_HASTE; + Action->submessageID = 166; + Action->flag = 1; + } + } + return; + case 20: // Blink + if (rand()%100 <= 15) + { + if(PAttacker->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_BLINK,EFFECT_BLINK,1,0,5))) + { + Action->subparam = EFFECT_BLINK; + Action->submessageID = 166; + Action->flag = 1; + } + } + return; + case 21: // Poison + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_POISONRES)) + { + if(PDefender->hasImmunity(256) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_POISON,EFFECT_POISON,1,3,30))) + { + Action->subeffect = SUBEFFECT_POISON; + Action->subparam = EFFECT_POISON; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 22: // Blind + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_BLINDRES)) + { + if(PDefender->hasImmunity(64) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_BLINDNESS,EFFECT_BLINDNESS,10,0,10))) + { + Action->subeffect = SUBEFFECT_BLIND; + Action->subparam = EFFECT_BLINDNESS; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 23: // Silence + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_SILENCERES)) + { + if(PDefender->hasImmunity(16) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_SILENCE,EFFECT_SILENCE,1,0,10))) + { + Action->subeffect = SUBEFFECT_SILENCE; + Action->subparam = EFFECT_SILENCE; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + return; + case 24: // Curse + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_CURSERES)) + { + // if(PDefender->hasImmunity(?) == false) // Curse immunity unknown + + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_CURSE,EFFECT_CURSE,1,0,10))) + { + Action->subeffect = SUBEFFECT_CURSE; + Action->subparam = EFFECT_CURSE; + Action->submessageID = 160; + Action->flag = 3; + } + + } + } + return; + case 25: // Death + if (rand()%100 <= 2) + { + if(rand()%100 >= PDefender->getMod(MOD_DEATHRES)) + { + // if(PDefender->hasImmunity(?) == false) // Death immunity unknown + + Action->subparam = SUBEFFECT_NONE; + Action->submessageID = 160; + Action->flag = 3; + PDefender->addHP(-999999); + } + } + return; + case 26: // Sleep + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_SLEEPRES)) + { + if(!PDefender->isDead() && PDefender->hasImmunity(1) == false) + { + int duration = 25 - (PDefender->GetMLevel() - PAttacker->GetMLevel())*5 - ((float)PDefender->getMod(MOD_SLEEPRES)/5); + + if(duration <= 1) + { + duration = 1; + } + else + { + //randomize sleep duration + duration -= rand()%(duration/2); + } + + duration = dsp_cap(duration,1,25); + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_SLEEP,EFFECT_SLEEP,1,0,duration))) + { + Action->subeffect = SUBEFFECT_SLEEP; + Action->subparam = EFFECT_SLEEP; + Action->submessageID = 160; + Action->flag = 3; + } + } + } + } + return; + case 27: // Evasion Down + if (rand()%100 <= 5) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_EVASION_DOWN,EFFECT_EVASION_DOWN,10,0,10))) + { + Action->subeffect = SUBEFFECT_IMPAIRS_EVASION; + Action->subparam = EFFECT_EVASION_DOWN; + Action->submessageID = 160; + Action->flag = 3; + } + } + return; + case 28: // Defense Down + if (rand()%100 <= 5) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_DEFENSE_DOWN,EFFECT_DEFENSE_DOWN,50,0,10))) + { + Action->subeffect = SUBEFFECT_DEFENSE_DOWN; + Action->subparam = EFFECT_DEFENSE_DOWN; + Action->submessageID = 160; + Action->flag = 1; + } + } + return; + case 29: // Weaken Attack + if (rand()%100 <= 5) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_ATTACK_DOWN,EFFECT_ATTACK_DOWN,50,0,10))) + { + Action->subeffect = SUBEFFECT_WEAKENS_ATTACKS; + Action->subparam = EFFECT_ATTACK_DOWN; + Action->submessageID = 160; + Action->flag = 1; + } + } + return; + case 30: // Darkness Dmg + if(rand()%100 <= chance) + { + if(rand()%100 >= PDefender->getMod(MOD_DARKRES)) + { + Action->subeffect = SUBEFFECT_DARKNESS_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + int damage = (PAttacker->INT() - PDefender->INT())/2; + damage += (PAttacker->GetMLevel() - PDefender->GetMLevel()); + damage = dsp_cap(damage,0,50); + damage += PAttacker->GetMLevel()/2; + damage += rand()%20; //At 75 -> 37~56 low or 87~106 high + + damage += (float)damage * ((float)PDefender->getMod(MOD_DARKRES)/-100); + + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 31: // Earth Dmg + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_EARTHRES)) + { + Action->subeffect = SUBEFFECT_EARTH_DAMAGE; + Action->submessageID = 163; + Action->flag = 1; + //calculate damage + uint8 damage = (PAttacker->VIT() - PDefender->VIT())/2; + damage = dsp_cap(damage,0,50); + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + + damage += (float)damage * ((float)PDefender->getMod(MOD_EARTHRES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 32: // Fire Dmg + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_FIRERES)) + { + Action->subeffect = SUBEFFECT_FIRE_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + //calculate damage + uint8 damage = (PAttacker->INT() - PDefender->INT())/2; + damage = dsp_cap(damage,0,50); + + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_FIRERES)/-100); + + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 33: // Light Dmg + if (rand()%100 <= chance) + { + if(rand()%100 >= PDefender->getMod(MOD_LIGHTRES)) + { + Action->subeffect = SUBEFFECT_LIGHT_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + //calculate damage + uint8 damage = (PAttacker->MND() - PDefender->MND())/2; + damage = dsp_cap(damage,0,50); + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_LIGHTRES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 34: // Water Dmg + if (rand()%100 <= chance) + { + if(rand()%100 >= PDefender->getMod(MOD_WATERRES)) + { + Action->subeffect = SUBEFFECT_WATER_DAMAGE; + Action->submessageID = 163; + Action->flag = 1; + //calculate damage + uint8 damage = (PAttacker->MND() - PDefender->MND())/2; + damage = dsp_cap(damage,0,50); + if(ammoUse == 1) + { + if (PAmmo->getID() == 18232) // Hydro Pump + { + damage += 10; //10~60 + damage += rand()%6; //10~65 randomised + } + else if (PAmmo->getID() == 18233) // Kilo Pump + { + damage += 20; //20~70 + damage += rand()%6; //20~75 randomised + } + else if (PAmmo->getID() == 18234) // Mega Pump + { + damage += 30; //30~80 + damage += rand()%6; //30~85 randomised + } + // ShowDebug(CL_CYAN"Water Pump Removal \n"); + if ( (PAmmo->getQuantity()-1) < 1) // ammo will run out after this attack, make sure we remove it from equip + { + uint8 slot = PAttacker->equip[SLOT_AMMO]; + charutils::UnequipItem(PAttacker,SLOT_AMMO); + charutils::UpdateItem(PAttacker, LOC_INVENTORY, slot, -1); + } + else + { + charutils::UpdateItem(PAttacker, LOC_INVENTORY, PAttacker->equip[SLOT_AMMO], -1); + } + PAttacker->pushPacket(new CInventoryFinishPacket()); + } + else + { + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + } + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_WATERRES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 35: // Ice Dmg + if (rand()%100 <= 5) + { + if(rand()%100 >= PDefender->getMod(MOD_ICERES)) + { + Action->subeffect = SUBEFFECT_ICE_DAMAGE; + Action->submessageID = 163; + Action->flag = 1; + //calculate damage + uint8 damage = (PAttacker->INT() - PDefender->INT())/2; + damage = dsp_cap(damage,0,50); + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_ICERES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 36: // Lightning Dmg + if (rand()%100 <= chance) + { + if(rand()%100 >= PDefender->getMod(MOD_THUNDERRES)) + { + Action->subeffect = SUBEFFECT_LIGHTNING_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + //calculate damage + uint8 damage = (PAttacker->DEX() - PDefender->DEX())/2; + damage = dsp_cap(damage,0,50); + if(ammoUse == 1) + { + if (PAmmo->getID() == 18228) // Battery + { + damage += 10; //10~60 + damage += rand()%6; //10~65 randomised + } + else if (PAmmo->getID() == 18229) // Kilo Battery + { + damage += 20; //20~70 + damage += rand()%6; //20~75 randomised + } + else if (PAmmo->getID() == 18230) // Mega Battery + { + damage += 30; //30~80 + damage += rand()%6; //30~85 randomised + } + // ShowDebug(CL_CYAN"Battery Removal \n"); + if ( (PAmmo->getQuantity()-1) < 1) // ammo will run out after this attack, make sure we remove it from equip + { + uint8 slot = PAttacker->equip[SLOT_AMMO]; + charutils::UnequipItem(PAttacker,SLOT_AMMO); + charutils::UpdateItem(PAttacker, LOC_INVENTORY, slot, -1); + } + else + { + charutils::UpdateItem(PAttacker, LOC_INVENTORY, PAttacker->equip[SLOT_AMMO], -1); + } + PAttacker->pushPacket(new CInventoryFinishPacket()); + } + else + { + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + } + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_THUNDERRES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 37: // Wind Dmg + if (rand()%100 <= chance) + { + if(rand()%100 >= PDefender->getMod(MOD_WINDRES)) + { + Action->subeffect = SUBEFFECT_WIND_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + //calculate damage + uint8 damage = (PAttacker->AGI() - PDefender->AGI())/2; + damage = dsp_cap(damage,0,50); + if(ammoUse == 1) + { + if (PAmmo->getID() == 18236) // Wind Fan + { + damage += 10; //10~60 + damage += rand()%6; //10~65 randomised + } + else if (PAmmo->getID() == 18237) // Kilo Fan + { + damage += 20; //20~70 + damage += rand()%6; //20~75 randomised + } + else if (PAmmo->getID() == 18238) // Mega Fan + { + damage += 30; //30~80 + damage += rand()%6; //30~85 randomised + } + // ShowDebug(CL_CYAN"Wind Fan Removal \n"); + if ( (PAmmo->getQuantity()-1) < 1) // ammo will run out after this attack, make sure we remove it from equip + { + uint8 slot = PAttacker->equip[SLOT_AMMO]; + charutils::UnequipItem(PAttacker,SLOT_AMMO); + charutils::UpdateItem(PAttacker, LOC_INVENTORY, slot, -1); + } + else + { + charutils::UpdateItem(PAttacker, LOC_INVENTORY, PAttacker->equip[SLOT_AMMO], -1); + } + PAttacker->pushPacket(new CInventoryFinishPacket()); + } + else + { + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + } + damage += (float)damage * ((float)PDefender->getMod(MOD_WINDRES)/-100); + //set damage TODO: handle resi st/staff/day + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + return; + case 38: // Flee + chance = 0; + if(PDefender->GetMLevel() > PAttacker->GetMLevel()) + { + chance += 5*(PDefender->GetMLevel() - PAttacker->GetMLevel()); + chance = dsp_cap(chance,0,75); + } + if(rand()%100 <= chance) + { + if(PAttacker->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_FLEE,EFFECT_FLEE,100,0,30))) + { + Action->subparam = EFFECT_FLEE; + Action->submessageID = 160; + Action->flag = 3; + } + } + return; + case 39: // Dispel if (rand()%100 > 10) return; dispelled = PDefender->StatusEffectContainer->DispelStatusEffect(); // if(dispelled > 0){ @@ -1195,6 +3490,99 @@ // Action->subparam = dispelled; // } return; + case 40: // Regen + if (rand()%100 <= 7) + { + if(PAttacker->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_REGEN,EFFECT_REGEN,30,3,180))) + { + Action->subparam = EFFECT_REGEN; + Action->submessageID = 166; + Action->flag = 1; + } + } + return; + case 41: // Ice Spikes + if (rand()%100 <= 7) + { + if(PAttacker->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_ICE_SPIKES,EFFECT_ICE_SPIKES,20,0,90))) + { + Action->subparam = EFFECT_ICE_SPIKES; + Action->submessageID = 166; + Action->flag = 1; + } + } + return; + case 42: // Damage to MP - Tizona + //12-20 % chance to Recover MP + if (rand()%100 <= tizonaChance) + { + Action->submessageID = 152; + Action->flag = 3; + int mpRecover = ceil((float)(finaldamage * (tizonaPercent / 100.0f))); + // ShowDebug(CL_CYAN"Tizona MP Recovery %d \n", mpRecover); + Action->subparam = mpRecover; + PAttacker->addMP(Action->subparam); + + if(PAttacker->objtype == TYPE_PC){ + charutils::UpdateHealth(PAttacker); + } + } + return; + case 43: // Slashing Dmg -- Excalibur + { + Action->submessageID = 163; + Action->flag = 3; + uint8 damage = ceil((float)PAttacker->health.hp * .25f); + // ShowDebug(CL_CYAN"Excalibur Damage %d \n", damage); + damage += ceil((float)damage * ((float)PDefender->getMod(MOD_SLASHRES)/1000.0f)); + // ShowDebug(CL_CYAN"Excalibur After Resistance Damage %d \n", damage); + Action->subparam = damage; + PDefender->addHP(-damage); + } + return; + case 44: // Dmg varies with MP -- Tyrfing + if (rand()%100 <= 10) + { + Action->submessageID = 163; + Action->flag = 3; + uint8 damage = ceil((float)PAttacker->health.mp / 5.24f); + Action->subparam = damage; + PDefender->addHP(-damage); + } + return; + case 45: // Dmg varies with TP -- Erebus's Lance + if (rand()%100 <= 5) + { + Action->subeffect = SUBEFFECT_LIGHT_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + uint8 damage = 40; + damage += ceil((float)PAttacker->health.tp / 2.0f); + + Action->subparam = damage; + PDefender->addHP(-damage); + } + return; + case 46: // HP Recover + //15 % chance to Recover HP, 4-16 MP + if (rand()%100 <= 15) + { + Action->submessageID = 167; + Action->flag = 3; + int hpRecover = 4; + hpRecover = dsp_cap(hpRecover,4,16); + hpRecover += rand()%13; //4~16 randomised + Action->subparam = hpRecover; + PAttacker->addHP(Action->subparam); + + if(PAttacker->objtype == TYPE_PC){ + charutils::UpdateHealth(PAttacker); + } + } + return; + default: return; } @@ -1210,6 +3598,7 @@ void HandleRangedAdditionalEffect(CCharEntity* PAttacker, CBattleEntity* PDefender,apAction_t* Action){ CItemWeapon* PAmmo = (CItemWeapon*)PAttacker->getStorage(LOC_INVENTORY)->GetItem(PAttacker->equip[SLOT_AMMO]); + CItemWeapon* PRanged = (CItemWeapon*)PAttacker->getStorage(LOC_INVENTORY)->GetItem(PAttacker->equip[SLOT_RANGED]); //add effects dont have 100% proc, presume level dependant. 95% chance but -5% for each level diff. //capped at 5% proc when mob is 18 (!!!) levels higher than you. uint8 chance = 95; @@ -1217,9 +3606,113 @@ chance -= 5*(PDefender->GetMLevel() - PAttacker->GetMLevel()); chance = dsp_cap(chance,5,95); } - if(rand()%100 >= chance || PAmmo==NULL){return;} + + if(rand()%100 >= chance) + { + if(PAmmo->getID() == 18168 || PAmmo->getID() == 18168) + { + } + else + { + return; + } + } + if(PRanged==NULL && PAmmo==NULL){return;} + + switch(PRanged->getID()){ + case 19261:{ // Jinx Discus + + //check curse resistance + if(rand()%100 >= PDefender->getMod(MOD_CURSERES)){return;} + { + // if(PDefender->hasImmunity(?) == false) // Curse immunity unknown + + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_CURSE,EFFECT_CURSE,1,0,20))) + { + Action->subeffect = SUBEFFECT_CURSE; + Action->subparam = EFFECT_CURSE; + Action->submessageID = 160; + Action->flag = 3; + } + + } + } + break; + case 18708: // Snakeeye + case 18709: // Snakeeye +1 + { + if(PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_POISON)) + { + if(rand()%100 >= PDefender->getMod(MOD_POISONRES)) + { + if(PDefender->hasImmunity(256) == false) + { + if(PDefender->StatusEffectContainer->AddStatusEffect( + new CStatusEffect(EFFECT_POISON,EFFECT_POISON,1,3,30))) + { + Action->subeffect = SUBEFFECT_POISON; + Action->subparam = EFFECT_POISON; + Action->submessageID = 160; + Action->flag = 1; + } + } + } + } + } + break; + case 17293:{ // Yagudo Freezer + + if((((CMobEntity*)PDefender)->m_Family == 250) || ((CMobEntity*)PDefender)->m_Family == 270) + { + //check ice resistance + Action->subeffect = SUBEFFECT_ICE_DAMAGE; + Action->submessageID = 163; + Action->flag = 1; + //calculate damage + uint8 damage = (PAttacker->INT() - PDefender->INT())/2; + damage = dsp_cap(damage,0,50); + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_ICERES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + } + break; + case 17291:{ // Flame Boomberang + + //check Fire resistance + Action->subeffect = SUBEFFECT_FIRE_DAMAGE; + Action->submessageID = 163; + Action->flag = 3; + //calculate damage + uint8 damage = (PAttacker->INT() - PDefender->INT())/2; + damage = dsp_cap(damage,0,50); + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_FIRERES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + break; + } + + if(PAmmo==NULL){return;} + switch(PAmmo->getID()){ + case 18168: // Imperial Egg + case 18169:{ // Tzar's Egg + ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmity(PAttacker, 1800, 1); + Action->subeffect = SUBEFFECT_NONE; + Action->subparam = EFFECT_PROVOKE; + Action->submessageID = 164; + Action->flag = 3; + } + break; case 17325:{ // kabura_arrow //check wind resistance @@ -1262,7 +3755,8 @@ } } break; - case 17329: // patriarch_protectors_arrow + case 18740: // Combat Caster Arrow + case 17329: // Patriarch Protectors Arrow case 18696:{ // Paralysis Arrow //check ice resistance if(rand()%100 <= PDefender->getMod(MOD_ICERES)){return;} @@ -1321,6 +3815,26 @@ PDefender->addHP(-damage); } break; + case 18729: // Djinn Arm + case 19196:{ //Darkling Bolt + //damage doesn't exceed ~67 unless wearing light staff/iceday/weather + //there isn't a formula, but INT affects damage, so this is guesstimated. It seems to be level + //invarient since its used on harder monsters for damage occasionally. Assuming the modifier + //is simply INT with a degree of randomisation + Action->subeffect = SUBEFFECT_DARKNESS_DAMAGE; + Action->submessageID = 163; + Action->flag = 1; + //calculate damage + uint8 damage = (PAttacker->INT() - PDefender->INT())/2; + damage = dsp_cap(damage,0,50); + damage += 10; //10~60 + damage += rand()%8; //10~67 randomised + //set damage TODO: handle resist/staff/day + damage += (float)damage * ((float)PDefender->getMod(MOD_DARKRES)/-100); + Action->subparam = damage; + PDefender->addHP(-damage); + } + break; case 18698:{ //Water Arrow //damage doesn't exceed ~67 unless wearing light staff/iceday/weather //there isn't a formula, but INT affects damage, so this is guesstimated. It seems to be level @@ -1423,6 +3937,27 @@ charutils::UpdateHealth(PAttacker); } break; + case 18140:{ // Phantom Tathlum + //10 % chance to drain, will restore MP 10% of damage done + if (rand()%100 <= PDefender->getMod(MOD_DARKRES)){return;} + + Action->subeffect = SUBEFFECT_MP_DRAIN; + Action->submessageID = 162; + Action->flag = 3; + int damage = (PAttacker->INT() - PDefender->INT())/2; + damage += (PAttacker->GetMLevel() - PDefender->GetMLevel()); + damage = dsp_cap(damage,0,50); + damage += PAttacker->GetMLevel()/2; + damage += rand()%20; //At 75 -> 37~56 low or 87~106 high + + damage += (float)damage * ((float)PDefender->getMod(MOD_DARKRES)/-100); + + Action->subparam = damage; + PDefender->addMP(-damage); + PAttacker->addMP(damage); + charutils::UpdateHealth(PAttacker); + } + break; case 18152:{ //Venom Bolt if(PDefender->hasImmunity(256) == false){ //check water resistance @@ -1479,6 +4014,7 @@ } } break; + case 21323: // Oxidant Bolt case 18148:{ //Acid Bolt //check wind resistance @@ -1494,6 +4030,7 @@ } break; + case 17315: // Riot Grenade case 17324:{ //Lightning Arrow //damage doesn't exceed ~67 //there isn't a formula. It seems to be level @@ -1513,6 +4050,7 @@ PDefender->addHP(-damage); } break; + case 17306: // Snoll Arm case 17323:{ //Ice Arrow //damage doesn't exceed ~67 unless wearing ice staff/iceday/weather //there isn't a formula, but INT affects damage, so this is guesstimated. It seems to be level @@ -1532,6 +4070,11 @@ PDefender->addHP(-damage); } break; + case 19202: // Smart Grenade + case 17314: // Quake Grenade + case 17313: // Grenade + case 17305: // Cluster Arm + case 17316: // Bomb Arm case 17327: // Grand knights Arrow case 17322:{ //Fire Arrow //damage doesn't exceed ~67 unless wearing ice staff/iceday/weather @@ -1561,6 +4104,36 @@ } } +void HandleRetaliation(CBattleEntity* PAttacker, CBattleEntity* PDefender,apAction_t* Action, uint16 damage) +{ + //retaliation check (rate AND your hit rate makes it land, else its just a regular hit) + if (rand()%100 < battleutils::GetRetaliationRate(PAttacker, PDefender) && + rand()%100 < battleutils::GetHitRate(PDefender,PAttacker) && + PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_RETALIATION)) + { + Action->subeffect = SUBEFFECT_NONE; + Action->submessageID = 536; + Action->flag = 3; + bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(PDefender, PAttacker,false) ); + float DamageRatio = battleutils::GetDamageRatio(PDefender, PAttacker,isCritical, 0); + damage = (uint16)((PDefender->GetMainWeaponDmg() + battleutils::GetFSTR(PDefender, PAttacker,SLOT_MAIN)) * DamageRatio); + + damage = damage + (damage * (PDefender->getMod(MOD_RETALIATION_DMG)/100)); + Action->subparam = damage; + if (battleutils::IsAbsorbByShadow(PAttacker)) + { + Action->submessageID = 535; + Action->subparam = 1; + } + else + { + Action->reaction = REACTION_HIT; + // ShowDebug(CL_CYAN"Retaliation Damage %d \n", damage); + PAttacker->addHP(-damage); + } + } +} + uint8 GetRangedHitRate(CBattleEntity* PAttacker, CBattleEntity* PDefender){ int acc = 0; int hitrate = 75; @@ -1708,6 +4281,16 @@ return false; } +bool IsRetaliated(CBattleEntity* PAttacker, CBattleEntity* PDefender) +{ + if(isFaceing(PDefender->loc.p, PAttacker->loc.p, 40) && !PDefender->isAsleep()) + { + return(rand() % 100 < battleutils::GetRetaliationRate(PAttacker, PDefender)); + } + + return false; +} + bool TryInterruptSpell(CBattleEntity* PAttacker, CBattleEntity* PDefender){ //Reasonable assumption for the time being. @@ -1793,11 +4376,12 @@ if(PItem!=NULL && PItem->getID()!=65535 && PItem->getShieldSize()>0 && PItem->getShieldSize()<=5) { float chance = ((5-PItem->getShieldSize())*10.0f)+ //base - dsp_max(((float)(PChar->GetSkill(SKILL_SHL)+PChar->getMod(MOD_SHIELD)-GetMaxSkill(SKILL_SHL,JOB_PLD,PAttacker->GetMLevel()))/4.6f),-10); + dsp_max(((float)(PChar->GetSkill(SKILL_SHL)+PChar->getMod(MOD_SHIELD)-GetMaxSkill(SKILL_SHL,JOB_PLD, + PAttacker->GetMLevel()))/4.6f),-10) + PChar->getMod(MOD_BLOCK_RATE); //TODO: HANDLE OCHAIN - if(PItem->getShieldSize()==5){return 65;}//aegis, presume capped? need info. - //65% cap - return dsp_cap(chance,5,65); + if(PItem->getShieldSize()==5){return (65 + PChar->getMod(MOD_BLOCK_RATE));}//aegis, presume capped? need info. + //65% cap + Block Rate Mod + return dsp_cap(chance,5,(65 + PChar->getMod(MOD_BLOCK_RATE))); } } @@ -1814,12 +4398,15 @@ if( PDefender->GetMJob() == JOB_NIN || PDefender->GetMJob() == JOB_SAM || PDefender->GetMJob() == JOB_THF || PDefender->GetMJob() == JOB_BST || PDefender->GetMJob() == JOB_DRG || PDefender->GetMJob() == JOB_PLD || PDefender->GetMJob() == JOB_WAR || PDefender->GetMJob() == JOB_BRD || - PDefender->GetMJob() == JOB_DRK || PDefender->GetMJob() == JOB_RDM || PDefender->GetMJob() == JOB_COR) + PDefender->GetMJob() == JOB_DRK || PDefender->GetMJob() == JOB_RDM || PDefender->GetMJob() == JOB_COR || + PDefender->GetMJob() == JOB_GEO || PDefender->GetMJob() == JOB_RUN || PDefender->GetMJob() == JOB_DNC || + PDefender->GetMJob() == JOB_BLU || PDefender->GetMJob() == JOB_SCH || PDefender->GetMJob() == JOB_PUP) { - int skill = PDefender->GetSkill(SKILL_PAR) + PDefender->getMod(MOD_PARRY); //max A-, so need gear+ for 20% parry + int skill = PDefender->GetSkill(SKILL_PAR) + PDefender->getMod(MOD_PARRY) + + (PDefender->GetSkill(SKILL_PAR) * (PDefender->getMod(MOD_PARRYP) / 100)); //max A-, so need gear+ for 20% parry int max = GetMaxSkill(SKILL_SHL, JOB_PLD, PDefender->GetMLevel()); //A+ skill - int chance = 20 * ((double)skill / (double)max); - return dsp_cap(chance, 1, 20);//20% max parry rate + int chance = (20 * ((double)skill / (double)max)) + PDefender->getMod(MOD_PARRY_RATE); + return dsp_cap(chance, 1, (20 + PDefender->getMod(MOD_PARRY_RATE)));//20% max parry rate + Bonus } } @@ -1843,6 +4430,22 @@ return 0; } +uint8 GetRetaliationRate(CBattleEntity* PAttacker, CBattleEntity* PDefender) +{ + CItemWeapon* PWeapon = GetEntityWeapon(PDefender, SLOT_MAIN); + + if(PWeapon != NULL && battleutils::IsEngauged(PDefender)) + { + if( PDefender->GetMJob() == JOB_WAR || PDefender->GetSJob() == JOB_WAR) + { + int chance = 20 + rand()%31; + return dsp_cap(chance, 20, 50);//50% max retaliation rate + } + } + + return 0; +} + /************************************************************************ * * * Calculates damage based on damage and resistance to damage type * @@ -1853,6 +4456,10 @@ { bool isRanged = (slot == SLOT_AMMO || slot == SLOT_RANGED); + if(PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SCARLET_DELIRIUM_II)) + { + damage = damage + (damage * PAttacker->getMod(MOD_SCARLET_DMG)/100); + } if(PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_FORMLESS_STRIKES)) { uint8 formlessMod = 70; @@ -1865,7 +4472,6 @@ else { - damage = DmgTaken(PDefender, damage); if(isRanged) { @@ -1887,6 +4493,7 @@ if (isBlocked && PDefender->m_Weapons[SLOT_SUB]->IsShield()) { damage = (damage * PDefender->m_Weapons[SLOT_SUB]->getShieldAbsorption()) / 100; + damage = damage - (damage * (PDefender->getMod(MOD_SHIELD_DEF)/100)); } } damage = dsp_max(damage - PDefender->getMod(MOD_PHALANX),0); @@ -1903,9 +4510,16 @@ } damage -= absorb; } + + if(PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_MANA_WALL)) + { + damage = ManaWallDmgTaken(PDefender, damage); + } + + damage = DmgTaken(PDefender, damage); PDefender->addHP(-damage); - + if (PAttacker->PMaster != NULL) { PDefender->m_OwnerID.id = PAttacker->PMaster->id; @@ -1942,9 +4556,9 @@ PDefender->addTP(TP); } if(taChar == NULL){ - ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmityFromDamage(PAttacker, damage); + ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmityFromDamage(PAttacker, damage, false); }else{ - ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmityFromDamage(taChar, damage); + ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmityFromDamage(taChar, damage, false); } //if the mob is charmed by player @@ -2215,8 +4829,8 @@ cRatioMin = (cRatioMin < 0 ? 0 : cRatioMin); if(isCritical){ - cRatioMin += 1; - cRatioMax += 1; + cRatioMin += 1 + (PAttacker->getMod(MOD_CRIT_DMG)/100); + cRatioMax += 1 + (PAttacker->getMod(MOD_CRIT_DMG)/100); } cRatioMax = (cRatioMax > 3 ? 3 : cRatioMax); @@ -2294,11 +4908,13 @@ uint8 CheckMultiHits(CBattleEntity* PEntity, CItemWeapon* PWeapon) { + //checking players weapon hit count uint8 num = PWeapon->getHitCount(NULL); int8 tripleAttack = PEntity->getMod(MOD_TRIPLE_ATTACK); int8 doubleAttack = PEntity->getMod(MOD_DOUBLE_ATTACK); + int8 quadrupleAttack = PEntity->getMod(MOD_QUADRUPLE_ATTACK); //check for merit upgrades if (PEntity->objtype == TYPE_PC) @@ -2334,9 +4950,55 @@ doubleAttack = dsp_cap(doubleAttack,0,100); tripleAttack = dsp_cap(tripleAttack,0,100); + quadrupleAttack = dsp_cap(quadrupleAttack,0,100); + if (PEntity->objtype == TYPE_PC) + { + CCharEntity* PChar = (CCharEntity*)PEntity; + CItemWeapon* PAmmo = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_AMMO]); + switch (PWeapon->getID()) + { + // Virtue Stone Weapons - if (rand()%100 < tripleAttack) + case 18360: // Faith Baghnakhs, h2h + case 17710: // Justice Sword, sword + case 18222: // Fortitude Axe, great axe + case 18282: // Hope Staff, staff + case 17948: // Temperance Axe, axe + case 18100: // Love Halberd, polearm + case 18379: // Prudence Rod, club + case 17595: // Hope Staff, staff + if(PAmmo->getID() == 18244) + { + if (rand()%100 > 50) + { + // ShowDebug(CL_CYAN"Virtue Weapon Proc \n"); + num +=1; + if ( (PAmmo->getQuantity()-1) < 1) // ammo will run out after this attack, make sure we remove it from equip + { + uint8 slot = PChar->equip[SLOT_AMMO]; + charutils::UnequipItem(PChar,SLOT_AMMO); + charutils::UpdateItem(PChar, LOC_INVENTORY, slot, -1); + } + else + { + charutils::UpdateItem(PChar, LOC_INVENTORY, PChar->equip[SLOT_AMMO], -1); + } + PChar->pushPacket(new CInventoryFinishPacket()); + } + } + break; + + default: + break; + } + } + + if (rand()%100 < quadrupleAttack) { + num +=3; + } + else if (rand()%100 < tripleAttack) + { num +=2; } else if (rand()%100 < doubleAttack) @@ -2370,51 +5032,177 @@ luautils to check if it needs to load a spell script or not. ******************************************************************************/ uint16 SingSong(CBattleEntity* PCaster,CBattleEntity* PTarget,CSpell* PSpell){ - uint8 tier = 1; + uint8 tier = 1; // power EFFECT effect = EFFECT_NONE; uint8 tick = 0; + uint8 subPower = 0; + uint8 extraVar = 0; + uint8 modifier = 0; + uint16 songDuration = 120; + songDuration = songDuration * (PCaster->getMod(MOD_SONG_DURATION) / 100); + //calculate strengths. Need to know TIER and EFFECTTYPE (Minuet, Paeon, etc) for icon if(PSpell->getID() >= 394 && PSpell->getID() <= 398){ + if(PTarget->objtype==TYPE_PC) + { + CItem* PItemEar1 = ((CCharEntity*)PTarget)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PTarget)->equip[SLOT_EAR1]); + CItem* PItemEar2 = ((CCharEntity*)PTarget)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PTarget)->equip[SLOT_EAR2]); + if(PItemEar1->getID() == 14764 || PItemEar2->getID() == 14764) + { + extraVar = 3; + } + modifier = PCaster->getMod(MOD_MINUET) + PCaster->getMod(MOD_ALL_SONGS); + switch (modifier) + { + case 1: + subPower = 1; + + case 2: + subPower = 5; + + case 3: + subPower = 9; + + case 4: + subPower = 13; + + case 5: + subPower = 17; + + default: + break; + } + if(PCaster->objtype==TYPE_PC) + { + subPower += ((CCharEntity*)PCaster)->PMeritPoints->GetMeritValue(MERIT_MINUET_EFFECT,(CCharEntity*)PCaster); + } + } effect = EFFECT_MINUET; tier = PSpell->getID()-393; + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_MINUET) * 10) / 100)); } else if(PSpell->getID() >= 389 && PSpell->getID() <= 393){ + if(PTarget->objtype==TYPE_PC) + { + CItem* PItemEar1 = ((CCharEntity*)PTarget)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PTarget)->equip[SLOT_EAR1]); + CItem* PItemEar2 = ((CCharEntity*)PTarget)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PTarget)->equip[SLOT_EAR2]); + if(PItemEar1->getID() == 14765 || PItemEar2->getID() == 14765) + { + extraVar = 4; + } + modifier = PCaster->getMod(MOD_MINNE) + PCaster->getMod(MOD_ALL_SONGS); + switch (modifier) + { + case 1: + subPower = 1; + + case 2: + subPower = 5; + + case 3: + subPower = 9; + + case 4: + subPower = 13; + + case 5: + subPower = 17; + + default: + break; + } + if(PCaster->objtype==TYPE_PC) + { + subPower += ((CCharEntity*)PCaster)->PMeritPoints->GetMeritValue(MERIT_MINNE_EFFECT,(CCharEntity*)PCaster); + } + } effect = EFFECT_MINNE; tier = PSpell->getID()-388; + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_MINNE) * 10) / 100)); } else if(PSpell->getID() >= 399 && PSpell->getID() <= 400){ + if(PTarget->objtype==TYPE_PC) + { + CItem* PAmmo = ((CCharEntity*)PTarget)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PTarget)->equip[SLOT_AMMO]); + if(PAmmo->getID() == 19762) + { + extraVar = 6; + } + modifier = PCaster->getMod(MOD_MADRIGAL) + PCaster->getMod(MOD_ALL_SONGS); + switch (modifier) + { + case 1: + subPower = 1; + + case 2: + subPower = 4; + + case 3: + subPower = 7; + + case 4: + subPower = 10; + + case 5: + subPower = 13; + + default: + break; + } + if(PCaster->objtype==TYPE_PC) + { + subPower += ((CCharEntity*)PCaster)->PMeritPoints->GetMeritValue(MERIT_MADRIGAL_EFFECT,(CCharEntity*)PCaster); + } + } effect = EFFECT_MADRIGAL; tier = PSpell->getID()-398; + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_MADRIGAL) * 10) / 100)); } else if(PSpell->getID() >= 403 && PSpell->getID() <= 404){ effect = EFFECT_MAMBO; - tier = PSpell->getID()-382; + tier = PSpell->getID()-402; + subPower = PCaster->getMod(MOD_MAMBO) + PCaster->getMod(MOD_ALL_SONGS); + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_MAMBO) * 10) / 100)); } else if(PSpell->getID() >= 386 && PSpell->getID() <= 388){ effect = EFFECT_BALLAD; tier = PSpell->getID()-385; + subPower = PCaster->getMod(MOD_BALLAD) + PCaster->getMod(MOD_ALL_SONGS); tick = 3; + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_BALLAD) * 10) / 100)); } else if(PSpell->getID() >= 419 && PSpell->getID() <= 420){ effect = EFFECT_MARCH; tier = PSpell->getID()-418; + subPower = PCaster->getMod(MOD_MARCH) + PCaster->getMod(MOD_ALL_SONGS); + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_MARCH) * 10) / 100)); } else if(PSpell->getID() >= 378 && PSpell->getID() <= 385){ effect = EFFECT_PAEON; tier = PSpell->getID()-377; + subPower = PCaster->getMod(MOD_PAEON) + PCaster->getMod(MOD_ALL_SONGS); tick = 3; } + else if(PSpell->getID() >= 409 && PSpell->getID() <= 411){ + effect = EFFECT_OPERETTA; + tier = PSpell->getID()-408; + subPower = PCaster->getMod(MOD_ALL_SONGS); + songDuration = songDuration + (songDuration * ((PCaster->getMod(MOD_ALL_SONGS) * 10) / 100)); + } if(effect==EFFECT_NONE){ return effect; } - //TODO: Handle instruments! - - CStatusEffect* PStatus = new CStatusEffect(effect,effect,tier,tick,120,PCaster->targid); + + + + + CStatusEffect* PStatus = new CStatusEffect(effect,effect,tier,tick,songDuration,PCaster->targid,subPower,extraVar); PStatus->SetFlag(EFFECTFLAG_ON_ZONE);//wears on zone uint8 maxSongs = 2; + maxSongs = maxSongs + PCaster->getMod(MOD_SONG_EFFECTS); if(PCaster->objtype==TYPE_PC){ CCharEntity* PChar = (CCharEntity*)PCaster; CItemWeapon* PItem = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_RANGED]); @@ -2447,7 +5235,7 @@ * * ************************************************************************/ -bool IsParalised(CBattleEntity* PAttacker) +bool IsParalyzed(CBattleEntity* PAttacker) { return (rand()%100 < dsp_cap(PAttacker->getMod(MOD_PARALYZE) - PAttacker->getMod(MOD_PARALYZERES), 0, 100)); } @@ -2995,7 +5783,7 @@ case TYPE_MOB: { - ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmityFromDamage(PAttacker, damage); + ((CMobEntity*)PDefender)->PEnmityContainer->UpdateEnmityFromDamage(PAttacker, damage, false); } break; } @@ -3061,7 +5849,7 @@ /************************************************************************ * * -* Для всех сущностей, за исключением персонажей, по умолчанию true * +* For all entities, except the characters, the default is true * * * ************************************************************************/ @@ -3133,6 +5921,10 @@ if(ConsumeTool && rand() % 100 > chance) { + if(PChar->StatusEffectContainer->HasStatusEffect(EFFECT_FUTAE)) + { + charutils::UpdateItem(PChar, LOC_INVENTORY, SlotID, -1); + } charutils::UpdateItem(PChar, LOC_INVENTORY, SlotID, -1); PChar->pushPacket(new CInventoryFinishPacket()); } @@ -3353,16 +6145,27 @@ CItem* PItemHead = ((CCharEntity*)m_PChar)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)m_PChar)->equip[SLOT_HEAD]); CItem* PItemBody = ((CCharEntity*)m_PChar)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)m_PChar)->equip[SLOT_BODY]); CItem* PItemLegs = ((CCharEntity*)m_PChar)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)m_PChar)->equip[SLOT_LEGS]); - if(PItemHead->getID() == 12516 || PItemHead->getID() == 15232 || PItemBody->getID() == 14409 || PItemLegs->getID() == 15370){ - drainPercent = 0.12; - } + CItem* PItemRing1 = ((CCharEntity*)m_PChar)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)m_PChar)->equip[SLOT_RING1]); + CItem* PItemRing2 = ((CCharEntity*)m_PChar)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)m_PChar)->equip[SLOT_RING2]); + CItem* PItemMain = ((CCharEntity*)m_PChar)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)m_PChar)->equip[SLOT_MAIN]); + if(PItemHead->getID() == 12516 || PItemHead->getID() == 15232 || PItemBody->getID() == 14409 || PItemLegs->getID() == 15370) + { + drainPercent = 0.12; + } + if((PItemRing1->getID() == 15818 && PItemMain->getID() == 18947) || (PItemRing2->getID() == 15818 && PItemMain->getID() == 18947)) + { + drainPercent = 0.12; + } damage = damage + m_PChar->health.hp*drainPercent; m_PChar->addHP(-drainPercent*m_PChar->health.hp); } - else if(m_PChar->GetSJob()==JOB_DRK &&m_PChar->health.hp>=10 && m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SOULEATER)){ + else if(m_PChar->GetSJob()==JOB_DRK &&m_PChar->health.hp>=10 && m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SOULEATER)) + { //lose 10% Current HP, only HALF (5%) converted to damage damage = damage + m_PChar->health.hp*0.05; - m_PChar->addHP(-0.1*m_PChar->health.hp); + float stalwartSoulHP = 0.1; + stalwartSoulHP = stalwartSoulHP - (m_PChar->getMod(MOD_STALWART_SOUL)/1000); + m_PChar->addHP((-1 * stalwartSoulHP) * m_PChar->health.hp); } return damage; } @@ -3461,9 +6264,9 @@ if (lvl < 30) return 0; else if (lvl < 50) shotCount += 3; else if (lvl < 75) shotCount += 4; - else if (lvl < 90) shotCount += 5; - else if (lvl < 99) shotCount += 6; - else if (lvl >= 99) shotCount += 7; + else if (lvl < 90) shotCount += (5 + PChar->getMod(MOD_BARRAGE)); + else if (lvl < 99) shotCount += (6 + PChar->getMod(MOD_BARRAGE)); + else if (lvl >= 99) shotCount += (7 + PChar->getMod(MOD_BARRAGE)); // make sure we have enough ammo for all these shots @@ -3489,6 +6292,8 @@ uint16 jumpAbility(CBattleEntity* PAttacker, CBattleEntity* PVictim, uint8 tier) { + CBattleEntity* PPet = PAttacker->PPet; + // super jump - remove 99% of enmity if (tier == 3 && PVictim->objtype == TYPE_MOB) { @@ -3522,12 +6327,24 @@ uint8 hitrate = battleutils::GetHitRate(PAttacker, PVictim); uint8 realHits = 0; // to store the real number of hit for tp multipler + uint8 hitAcc = 0; + uint8 hitDbl = 0; uint16 totalDamage = 0; uint16 damageForRound = 0; bool hitTarget = false; + CItem* PItemFeet = ((CCharEntity*)PAttacker)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PAttacker)->equip[SLOT_FEET]); + CItem* PItemMain = ((CCharEntity*)PAttacker)->getStorage(LOC_INVENTORY)->GetItem(((CCharEntity*)PAttacker)->equip[SLOT_MAIN]); + if (PItemMain->getID() == 16854) + { + if(rand()%100 < 5) + { + hitDbl = 1; + } + } + // Loop number of hits - for (uint8 i = 0; i < (numattacksLeftHand + numattacksRightHand); ++i) + for (uint8 i = 0; i < (numattacksLeftHand + numattacksRightHand + hitDbl); ++i) { if (i != 0) { @@ -3540,8 +6357,13 @@ fstrslot = SLOT_SUB; } } + + if (PItemFeet->getID() == 15347) + { + hitAcc = 4; + } - if(rand()%100 < hitrate) + if(rand()%100 < (hitrate + hitAcc)) { // attack hit, try to be absorbed by shadow @@ -3553,22 +6375,73 @@ // get jump attack bonus from gear if (PAttacker->objtype == TYPE_PC) AttMultiplerPercent = PAttacker->getMod(MOD_JUMP_ATT_BONUS); + + // get spirit jump attack bonus from gear + if (PAttacker->objtype == TYPE_PC && tier == 4) + AttMultiplerPercent += PAttacker->getMod(MOD_SPIRIT_JUMP_ATT); + + // get spirit jump attack bonus from wyvern + if(PAttacker->PPet != NULL && ((CPetEntity*)PPet)->getPetType() == PETTYPE_WYVERN && tier == 4) + AttMultiplerPercent += 25; + + // get soul jump attack bonus from wyvern + if(PAttacker->PPet != NULL && ((CPetEntity*)PPet)->getPetType() == PETTYPE_WYVERN && tier == 5) + AttMultiplerPercent += 50; + + // bonus for Ryunohige Weapons + if ((PItemMain->getID() == 19004 || PItemMain->getID() == 19073 || PItemMain->getID() == 19093 + || PItemMain->getID() == 19625 || PItemMain->getID() == 19723 || PItemMain->getID() == 19823 + || PItemMain->getID() == 19961) && (tier == 1 || tier == 2)) + { + float DamageRatio = battleutils::GetDamageRatio(PAttacker, PVictim, true, AttMultiplerPercent); + damageForRound = (uint16)((PAttacker->GetMainWeaponDmg() + battleutils::GetFSTR(PAttacker,PVictim,SLOT_MAIN)) * DamageRatio); + } + // spirit jump and soul jump bonus for wyvern + else if(PAttacker->PPet != NULL && ((CPetEntity*)PPet)->getPetType() == PETTYPE_WYVERN && (tier == 4 || tier == 5)) + { + float DamageRatio = battleutils::GetDamageRatio(PAttacker, PVictim, true, AttMultiplerPercent); + damageForRound = (uint16)((PAttacker->GetMainWeaponDmg() + battleutils::GetFSTR(PAttacker,PVictim,SLOT_MAIN)) * DamageRatio); + } + else + { + float DamageRatio = battleutils::GetDamageRatio(PAttacker, PVictim, false, AttMultiplerPercent); + damageForRound = (uint16)((PAttacker->GetMainWeaponDmg() + battleutils::GetFSTR(PAttacker,PVictim,SLOT_MAIN)) * DamageRatio); + } - float DamageRatio = battleutils::GetDamageRatio(PAttacker, PVictim, false, AttMultiplerPercent); - damageForRound = (uint16)((PAttacker->GetMainWeaponDmg() + battleutils::GetFSTR(PAttacker,PVictim,SLOT_MAIN)) * DamageRatio); - // bonus applies to jump only, not high jump if (tier == 1) { float jumpBonus = ( (PAttacker->VIT() / (float)256)+1 ); damageForRound = damageForRound * jumpBonus; } + + // bonus for Ryunohige Weapons + if (PItemMain->getID() == 19004 && tier == 1) + { + damageForRound += (damageForRound * .05); + } + else if (PItemMain->getID() == 19073 && tier == 1) + { + damageForRound += (damageForRound * .10); + } + else if (PItemMain->getID() == 19093 && tier == 1) + { + damageForRound += (damageForRound * .15); + } + else if ((PItemMain->getID() == 19625 || PItemMain->getID() == 19723) && tier == 1) + { + damageForRound += (damageForRound * .25); + } + else if ((PItemMain->getID() == 19832 || PItemMain->getID() == 19961) && tier == 1) + { + damageForRound += (damageForRound * .35); + } hitTarget = true; realHits++; // incase player has gungnir^^ (or any other damage increases weapons) - damageForRound = battleutils::CheckForDamageMultiplier(PWeapon,damageForRound,i); + damageForRound = battleutils::CheckForDamageMultiplier(PWeapon,damageForRound,i,((CCharEntity*)PAttacker)); totalDamage += damageForRound; @@ -3583,16 +6456,29 @@ totalDamage = battleutils::doSoulEaterEffect((CCharEntity*)PAttacker, totalDamage); // bonus jump tp is added even if damage is 0, will not add if jump misses - if (PAttacker->objtype == TYPE_PC && hitTarget) + if (PAttacker->objtype == TYPE_PC && hitTarget && (tier == 1 || tier == 2)) { int mod = PAttacker->getMod(MOD_JUMP_TP_BONUS); PAttacker->addTP( ((float)(mod)/(float)10)); } + if (PAttacker->objtype == TYPE_PC && hitTarget && tier == 4) + { + int mod = PAttacker->getMod(MOD_SPIRIT_JUMP_TP); + PAttacker->addTP( ((float)(mod)/(float)10)); + } // if damage is 0 then jump missed if (totalDamage == 0) return 0; + // If Attacker has Delphinius equipped Additional Effect Stun + if (tier == 1 && PWeapon->getID() == 19794) + { + if(PVictim->hasImmunity(8) == false) + { + PVictim->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_STUN,EFFECT_STUN,1,0,10)); + } + } // high jump removes %50 emnity + more from any gear mods if (tier == 2 && PVictim->objtype == TYPE_MOB) @@ -3605,13 +6491,36 @@ ((CMobEntity*)PVictim)->PEnmityContainer->LowerEnmityByPercent(PAttacker , enmityReduction, NULL); } + // Under Spirit Surge, High Jump lowers the target's TP proportionately to the amount of damage dealt (TP is reduced by damage * 2) + if (tier == 2 && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SPIRIT_SURGE)) + { + PVictim->addTP(-(totalDamage * 2)); + } + + // Under Spirit Surge, Jump also decreases target defense by 20% for 60 seconds + if (tier == 1 && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SPIRIT_SURGE)) + { + PVictim->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_DEFENSE_DOWN,EFFECT_DEFENSE_DOWN,20,0,60)); + } + // try skill up (CharEntity only) if (PAttacker->objtype == TYPE_PC) charutils::TrySkillUP((CCharEntity*)PAttacker, (SKILLTYPE)PWeapon->getSkillType(), PVictim->GetMLevel()); // jump + high jump doesn't give any tp to victim - battleutils::TakePhysicalDamage(PAttacker, PVictim, totalDamage, false, fstrslot, realHits, NULL, false); - + // spirit jump and soul jump bonus for wyvern + if(PAttacker->PPet != NULL && ((CPetEntity*)PPet)->getPetType() == PETTYPE_WYVERN && tier == 4) + { + battleutils::TakePhysicalDamage(PAttacker, PVictim, totalDamage, false, fstrslot, (realHits * 2), NULL, false); + } + else if(PAttacker->PPet != NULL && ((CPetEntity*)PPet)->getPetType() == PETTYPE_WYVERN && tier == 5) + { + battleutils::TakePhysicalDamage(PAttacker, PVictim, totalDamage, false, fstrslot, (realHits * 3), NULL, false); + } + else + { + battleutils::TakePhysicalDamage(PAttacker, PVictim, totalDamage, false, fstrslot, realHits, NULL, false); + } return totalDamage; } @@ -3657,11 +6566,11 @@ return; } - // cannot charm NM - if (((CMobEntity*)PVictim)->m_Type & MOBTYPE_NOTORIOUS){ - ((CMobEntity*)PVictim)->PEnmityContainer->UpdateEnmity(PCharmer, 0, 0); - return; - } + // cannot charm NM unless they are Taifun or Trombe + if (((CMobEntity*)PVictim)->m_Type & MOBTYPE_NOTORIOUS & PVictim->m_OwnerID.id != 17576269 & PVictim->m_OwnerID.id != 17576270){ + ((CMobEntity*)PVictim)->PEnmityContainer->UpdateEnmity(PCharmer, 0, 0); + return; + } else { // mob is charmable @@ -3809,7 +6718,7 @@ } if(check < rand()%100) { return true; - } + } return false; } @@ -3862,7 +6771,32 @@ } } +int32 ManaWallDmgTaken(CBattleEntity* PDefender, int32 damage) +{ + if(PDefender->health.mp > 0) + { + uint8 dmgDivisor = 2; + if(PDefender->StatusEffectContainer->HasStatusEffect(EFFECT_MANAFONT)) + { + dmgDivisor = 4; + } + if(PDefender->health.mp > ((damage / dmgDivisor) - (damage * (PDefender->getMod(MOD_MANA_WALL_DMG) / 100)))) + { + PDefender->addMP(-(damage / dmgDivisor)); + return 0; + } + else + { + damage = ((damage / dmgDivisor) - (damage * (PDefender->getMod(MOD_MANA_WALL_DMG) / 100))) - PDefender->health.mp; + PDefender->addMP(-(PDefender->health.mp)); + PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_MANA_WALL); + return damage; + } + } + return damage; +} + int32 DmgTaken(CBattleEntity* PDefender, int32 damage) { @@ -4004,12 +6938,12 @@ { if (PSpell->getAOE() == SPELLAOE_RADIAL_ACCE) if (PCaster->StatusEffectContainer->HasStatusEffect(EFFECT_ACCESSION)) - return SPELLAOE_RADIAL; + return SPELLAOE_RADIAL; else return SPELLAOE_NONE; if (PSpell->getAOE() == SPELLAOE_RADIAL_MANI) if (PCaster->StatusEffectContainer->HasStatusEffect(EFFECT_MANIFESTATION)) - return SPELLAOE_RADIAL; + return SPELLAOE_RADIAL; else return SPELLAOE_NONE; return PSpell->getAOE(); Index: src/map/battleutils.h =================================================================== --- src/map/battleutils.h (revision 3520) +++ src/map/battleutils.h (working copy) @@ -102,10 +102,10 @@ uint8 GetSkillchainSubeffect(SKILLCHAIN_ELEMENT skillchain); uint16 GetSkillchainMinimumResistance(SKILLCHAIN_ELEMENT element, CBattleEntity* PDefender); - bool IsParalised(CBattleEntity* PAttacker); - bool IsAbsorbByShadow(CBattleEntity* PDefender); - bool IsIntimidated(CBattleEntity* PAttacker, CBattleEntity* PDefender); - bool IsAnticipated(CBattleEntity* PDefender, bool forceRemove, bool ignore); + bool IsParalyzed(CBattleEntity* PAttacker); + bool IsAbsorbByShadow(CBattleEntity* PDefender); + bool IsIntimidated(CBattleEntity* PAttacker, CBattleEntity* PDefender); + bool IsAnticipated(CBattleEntity* PDefender, bool forceRemove, bool ignore); int32 GetFSTR(CBattleEntity* PAttacker, CBattleEntity* PDefender, uint8 SlotID); uint8 GetHitRateEx(CBattleEntity* PAttacker, CBattleEntity* PDefender, uint8 attackNumber, uint8 offsetAccuracy); @@ -117,6 +117,7 @@ uint8 GetBlockRate(CBattleEntity* PAttacker, CBattleEntity* PDefender); uint8 GetParryRate(CBattleEntity* PAttacker, CBattleEntity* PDefender); uint8 GetGuardRate(CBattleEntity* PAttacker, CBattleEntity* PDefender); + uint8 GetRetaliationRate(CBattleEntity* PAttacker, CBattleEntity* PDefender); float GetDamageRatio(CBattleEntity* PAttacker, CBattleEntity* PDefender, bool isCritical, uint16 bonusAttPercent); uint16 TakePhysicalDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, int16 damage, bool isBlocked, uint8 slot, uint16 tpMultiplier, CBattleEntity* taChar, bool giveTPtoVictim); @@ -127,9 +128,11 @@ bool IsParried(CBattleEntity* PAttacker, CBattleEntity* PDefender); bool IsGuarded(CBattleEntity* PAttacker, CBattleEntity* PDefender); bool IsBlocked(CBattleEntity* PAttacker, CBattleEntity* PDefender); + bool IsRetaliated(CBattleEntity* PAttacker, CBattleEntity* PDefender); float GetRangedPDIF(CBattleEntity* PAttacker, CBattleEntity* PDefender); void HandleRangedAdditionalEffect(CCharEntity* PAttacker, CBattleEntity* PDefender,apAction_t* Action); + void HandleRetaliation(CBattleEntity* PAttacker, CBattleEntity* PDefender,apAction_t* Action, uint16 damage); uint16 CalculateSpikeDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender, uint8 spikesType); bool HandleSpikesDamage(CBattleEntity* PAttacker, CBattleEntity* PDefender,apAction_t* Action, uint16 damage); bool HandleSpikesEquip(CBattleEntity* PAttacker, CBattleEntity* PDefender, apAction_t* Action, uint8 damage, SUBEFFECT spikesType, uint8 chance); @@ -151,10 +154,13 @@ CItemArmor* GetEntityArmor(CBattleEntity* PEntity, SLOTTYPE Slot); uint32 HandleSpecialPhysicalDamageReduction(CCharEntity* PAttacker, uint32 damage, apAction_t* Action); + uint32 HandleDamageToMP(CCharEntity* PAttacker, uint32 damage, apAction_t* Action); + uint32 HandleDamageToTP(CCharEntity* PAttacker, uint32 damage, apAction_t* Action); + uint32 HandleBlockToMP(CCharEntity* PAttacker, uint32 damage, apAction_t* Action); void MakeEntityStandUp(CBattleEntity* PEntity); bool IsEngauged(CBattleEntity* PEntity); CBattleEntity* getAvailableTrickAttackChar(CBattleEntity* taUser, CBattleEntity* PMob); - uint32 CheckForDamageMultiplier(CItemWeapon* PWeapon, uint32 damage, uint8 hitNumber); + uint32 CheckForDamageMultiplier(CItemWeapon* PWeapon, uint32 damage, uint8 hitNumber, CCharEntity* m_PChar); bool HasNinjaTool(CBattleEntity* PEntity, CSpell* PSpell, bool ConsumeTool); bool TryCharm(CBattleEntity* PCharmer, CBattleEntity* PVictim, uint32 base); @@ -171,6 +177,7 @@ EFFECT getCorsairRollEffect(uint16 id); void ClaimMob(CBattleEntity* PDefender, CBattleEntity* PAttacker); + int32 ManaWallDmgTaken(CBattleEntity* PDefender, int32 damage); int32 DmgTaken(CBattleEntity* PDefender, int32 damage); int32 BreathDmgTaken(CBattleEntity* PDefender, int32 damage); int32 MagicDmgTaken(CBattleEntity* PDefender, int32 damage); Index: src/map/charentity.cpp =================================================================== --- src/map/charentity.cpp (revision 3520) +++ src/map/charentity.cpp (working copy) @@ -101,6 +101,8 @@ m_lastBcnmTimePrompt = 0; m_AHHistoryTimestamp = 0; m_DeathTimestamp = 0; + m_PlayTime = 0; + m_ZoneTimer = 0; m_EquipFlag = 0; m_EquipBlock = 0; @@ -237,11 +239,10 @@ /************************************************************************ * * -* Возвращаем контейнер с указанным ID. Если ID выходит за рамки, то * -* защищаем сервер от падения использованием контейнера временных * -* предметов в качестве заглушки (из этого контейнера предметы нельзя * -* перемещать, надевать, передавать, продавать и т.д.). Отображаем * -* сообщение о фатальной ошибке. * +* Return the container with the specified ID. If the ID is out of * +* range, then Protects the server from falling container using the * +* time- Items as caps (of the container objects can not Move, put, * +* transfer, sell, etc.). Display a fatal error. * * * ************************************************************************/ @@ -258,7 +259,7 @@ case LOC_MOGSACK: return m_Mogsack; } - DSP_DEBUG_BREAK_IF(LocationID >= MAX_CONTAINER_ID); // неразрешенный ID хранилища + DSP_DEBUG_BREAK_IF(LocationID >= MAX_CONTAINER_ID); // unresolved ID vault return 0; } @@ -317,4 +318,18 @@ void CCharEntity::setWeaponSkillKill(bool isWeaponSkillKill) { m_isWeaponSkillKill = isWeaponSkillKill; -} \ No newline at end of file +} + + + +void CCharEntity::SetPlayTime(uint32 setTime) +{ + m_PlayTime = setTime; +} + +void CCharEntity::AddPlayTime() +{ + m_ZoneTimer++; + if((m_ZoneTimer % 2) == 0) + m_PlayTime++; +} Index: src/map/charentity.h =================================================================== --- src/map/charentity.h (revision 3520) +++ src/map/charentity.h (working copy) @@ -68,22 +68,22 @@ struct jobs_t { - uint32 unlocked; // битовая маска профессий, доступных персонажу (первый бит - дополнительная профессия) - uint8 job[MAX_JOBTYPE]; // текущий уровень для каждой из профессий - uint16 exp[MAX_JOBTYPE]; // текущее количество опыта для каждой из профессий - uint8 genkai; // максимальный уровень профессий персонажа + uint32 unlocked; // bitmask of professions available characters (the first bit - additional job) + uint8 job[MAX_JOBTYPE]; // current level for each of the professions + uint16 exp[MAX_JOBTYPE]; // current amount of experience for each profession + uint8 genkai; // maximum character professions }; struct event_t { - int32 EventID; // номер события - int32 Option; // фиктивный возвращаемый результат + int32 EventID; // number of event + int32 Option; // dummy return value - CBaseEntity* Target; // инициатор события + CBaseEntity* Target; // initiator of the event - string_t Script; // путь к файлу, отвечающему за обработку события - string_t Function; // не используется + string_t Script; // path to the file is responsible for handling events + string_t Function; // not used void reset() { @@ -97,13 +97,13 @@ struct profile_t { - uint8 nation; // принадлежность к государству - uint8 mhflag; // флаг выхода из MogHouse - uint16 title; // звание - uint16 fame[4]; // известность - uint8 rank[3]; // рагн в трех государствах - uint32 rankpoints; // очки ранга в трех государствах - location_t home_point; // точка возрождения персонажа + uint8 nation; // belongs to the state + uint8 mhflag; // flag out of MogHouse + uint16 title; // title + uint16 fame[4]; // fame + uint8 rank[3]; // Rank in three states + uint32 rankpoints; // rank points in three states + location_t home_point; // dot character revival }; @@ -159,32 +159,32 @@ { public: - jobs_t jobs; // доступрые профессии персонажа - keyitems_t keys; // таблица ключевых предметов - event_t m_event; // структура для запуска событый - skills_t RealSkills; // структура всех реальных умений персонажа, с точностью до 0.1 и не ограниченных уровнем - nameflags_t nameflags; // флаги перед именем персонажа - profile_t profile; // профиль персонажа (все, что связывает города и персонажа) + jobs_t jobs; // occupation character + keyitems_t keys; // table of key items + event_t m_event; // structure to trigger events + skills_t RealSkills; // structure of the real skills of the character, up to 0.1, and not limited to the level of + nameflags_t nameflags; // flags in front of the name of the character + profile_t profile; // character profile (everything that connects the city and the character) expChain_t expChain; // Exp Chains - search_t search; // данные и комментарий, отображаемые в окне поиска - bazaar_t bazaar; // все данные, необходимые для таботы bazaar - uint16 m_EquipFlag; // текущие события, обрабатываемые экипировкой (потом упакую в структуру, вместе с equip[]) - uint16 m_EquipBlock; // заблокированные ячейки экипировки + search_t search; // data and comments are displayed in the search box + bazaar_t bazaar; // all the data necessary for bazaar + uint16 m_EquipFlag; // current events that are handled gear (then pack them in a structure with equip []) + uint16 m_EquipBlock; // locked cells outfit bool m_EquipSwap; // true if equipment was recently changed - uint8 equip[17]; // экипировка персонажа + uint8 equip[17]; // character equipment - uint8 m_ZonesList[36]; // список посещенных персонажем зон - uint8 m_SpellList[128]; // список изученных заклинаний - uint8 m_TitleList[94]; // список заслуженных завний - uint8 m_Abilities[46]; // список текущих способностей + uint8 m_ZonesList[36]; // list of visited character zones + uint8 m_SpellList[128]; // list studied spells + uint8 m_TitleList[94]; // list of honored titles + uint8 m_Abilities[46]; // list of current abilities uint8 m_LearnedAbilities[46]; // learnable abilities (corsair rolls) - uint8 m_TraitList[16]; // список постянно активных способностей в виде битовой маски - uint8 m_PetCommands[32]; // список доступных команд питомцу + uint8 m_TraitList[16]; // list Fasting active abilities in the form of a bit mask + uint8 m_PetCommands[32]; // list of available commands pet uint8 m_WeaponSkills[32]; - questlog_t m_questLog[MAX_QUESTAREA]; // список всех квестов - missionlog_t m_missionLog[MAX_MISSIONAREA];// список миссий - assaultlog_t m_assaultLog; // список assault миссий - campaignlog_t m_campaignLog; // список campaing миссий + questlog_t m_questLog[MAX_QUESTAREA]; // list of all quests + missionlog_t m_missionLog[MAX_MISSIONAREA];// mission list + assaultlog_t m_assaultLog; // list of assault missions + campaignlog_t m_campaignLog; // list of campaign missions uint32 m_rangedDelay; // ranged attack delay (with timestamp for repeat attacks, hence 32bit)for items, abilities and magic bool m_insideBCNM; // true if user is inside a bcnm uint32 m_lastBcnmTimePrompt; // the last message prompt in seconds @@ -192,67 +192,68 @@ void resetPetZoningInfo(); // reset pet zoning info (when changing job ect) uint8 m_SetBlueSpells[20]; // The 0x200 offsetted blue magic spell IDs which the user has set. (1 byte per spell) - // Эти миссии не нуждаются в списке пройденных, т.к. клиент автоматически - // отображает более ранние миссии выплненными + // These missions do not need a list passed as client automatically + // Displays the earlier mission - uint16 m_copCurrent; // текущая миссия Chains of Promathia - uint16 m_acpCurrent; // текущая миссия A Crystalline Prophecy - uint16 m_mkeCurrent; // текущая миссия A Moogle Kupo d'Etat - uint16 m_asaCurrent; // текущая миссия A Shantotto Ascension + uint16 m_copCurrent; // current mission Chains of Promathia + uint16 m_acpCurrent; // current mission A Crystalline Prophecy + uint16 m_mkeCurrent; // current mission A Moogle Kupo d'Etat + uint16 m_asaCurrent; // current mission A Shantotto Ascension - // TODO: половина этого массива должна храниться в char_vars, а не здесь, т.к. эта информация не отображается в интерфейсе клиента и сервер не проводит с ними никаких операций + // TODO: half of the array should be stored in char_vars, and not here, because This information is not displayed in the interface of the client and the server does not perform any operations with them uint32 RegionPoints[15]; // conquest points, imperial standing points etc NationTP_t nationtp; // supply tp, runic portal, campaign tp,... - uint8 GetGender(); // узнаем пол персонажа + uint8 GetGender(); // find out the sex of the character - int32 firstPacketSize(); // размер первого пакета в PacketList - void clearPacketList(); // отчистка PacketList - void pushPacket(CBasicPacket*); // добавление копии пакета в PacketList - bool isPacketListEmpty(); // проверка размера PacketList - CBasicPacket* popPacket(); // получение первого пакета из PacketList + int32 firstPacketSize(); // size of the first packet in PacketList + void clearPacketList(); // cleanup PacketList + void pushPacket(CBasicPacket*); // add up package PacketList + bool isPacketListEmpty(); // size check PacketList + CBasicPacket* popPacket(); // get the first package of PacketList - CLinkshell* PLinkshell; // linkshell, в которой общается персонаж - CTreasurePool* PTreasurePool; // сокровища, добытые с монстров + + CLinkshell* PLinkshell; // linkshell, in which a character talks + CTreasurePool* PTreasurePool; // treasure, obtained from monsters CMeritPoints* PMeritPoints; // - bool MeritMode; //If true then player is meriting + bool MeritMode; // If true then player is meriting CRecastContainer* PRecastContainer; // CLatentEffectContainer* PLatentEffectContainer; - CItemContainer* PGuildShop; // текущий магазин гильдии, в котором персонаж производит закупки - CItemContainer* getStorage(uint8 LocationID); // получение указателя на соответствующее хранилище + CItemContainer* PGuildShop; // Store the current guilds, in which the characters make purchases + CItemContainer* getStorage(uint8 LocationID); // Get a pointer to the appropriate storage - CTradeContainer* Container; // универсальный контейнер для обмена, синтеза, магазина и т.д. - CUContainer* UContainer; // новый универсальный контейнер для обмена, синтеза, магазина и т.д. + CTradeContainer* Container; // universal container for the exchange, synthesis, shop etc. + CUContainer* UContainer; // new universal container for the exchange, synthesis, shop etc. - CBaseEntity* PWideScanTarget; // wide scane цель + CBaseEntity* PWideScanTarget; // wide scane goal - SpawnIDList_t SpawnPCList; // список видимых персонажей - SpawnIDList_t SpawnMOBList; // список видимых монстров - SpawnIDList_t SpawnPETList; // список видимых питомцев - SpawnIDList_t SpawnNPCList; // список видимых npc + SpawnIDList_t SpawnPCList; // list of visible characters + SpawnIDList_t SpawnMOBList; // list of visible MOBs + SpawnIDList_t SpawnPETList; // list of visible PETs + SpawnIDList_t SpawnNPCList; // list of visible NPCs - void SetName(int8* name); // устанавливаем имя персонажа (имя ограничивается 15-ю символами) + void SetName(int8* name); // set the character's name (the name is limited to 15-th character) - EntityID_t TradePending; // ID персонажа, предлагающего обмен - EntityID_t InvitePending; // ID персонажа, отправившего приглашение в группу + EntityID_t TradePending; // ID character's Swap + EntityID_t InvitePending; // ID of the character who sent the invitation to the group EntityID_t BazaarID; // Pointer to the bazaar we are browsing. BazaarList_t BazaarCustomers; // Array holding the IDs of the current customers - uint32 m_InsideRegionID; // номер региона, в котором сейчас находится персонаж (??? может засунуть в m_event ???) - uint8 m_LevelRestriction; // ограничение уровня персонажа - uint16 m_Costum; // карнавальный костюм персонажа (модель) + uint32 m_InsideRegionID; // number of the region, which now houses the character (? can shove m_event???) + uint8 m_LevelRestriction; // limit the level of character + uint16 m_Costum; // carnival costume character (model) uint32 m_AHHistoryTimestamp; // Timestamp when last asked to view history uint32 m_DeathTimestamp; // Timestamp when you last died. This is set when you first login. uint8 m_PVPFlag; // pvp uint8 m_hasTractor; // checks if player has tractor already uint8 m_hasRaise; // checks if player has raise already - uint8 m_hasAutoTarget; // возможность использования AutoTarget функции - position_t m_StartActionPos; // позиция начала действия (использование предмета, начало стрельбы, позиция tractor) + uint8 m_hasAutoTarget; // the use of the function AutoTarget + position_t m_StartActionPos; // start position of the (use of the subject, the shooting started, the position of tractor) int8 getShieldSize(); @@ -267,11 +268,15 @@ int32 addHP(int32 hp); int32 addMP(int32 mp); - std::vector m_ah_history; // AH history list (в будущем нужно использовать UContainer) + std::vector m_ah_history; // AH history list (in the future to use UContainer) - CCharEntity(); // конструктор - ~CCharEntity(); // деструктор + void SetPlayTime(uint32); // Set playtime from database + void AddPlayTime(); // Add playtime every second + uint32 __inline const& GetPlayTime() { return m_PlayTime; }; + CCharEntity(); // Designer + ~CCharEntity(); // Destructor + private: CItemContainer* m_Inventory; @@ -284,7 +289,10 @@ bool m_isWeaponSkillKill; - PacketList_t PacketList; // в этом списке хранятся все пакеты, предназначенные для отправки персонажу + PacketList_t PacketList; // This list contains all of the packages to be sent character + + uint32 m_ZoneTimer; + uint32 m_PlayTime; }; #endif Index: src/map/charutils.cpp =================================================================== --- src/map/charutils.cpp (revision 3520) +++ src/map/charutils.cpp (working copy) @@ -78,7 +78,7 @@ /************************************************************************ * * -* Таблицы получаемого опыта * +* Experience Gain Table * * * ************************************************************************/ @@ -96,26 +96,26 @@ /************************************************************************ * * -* Расчет характеристик персонажей * +* Calculation of characters * * * ************************************************************************/ void CalculateStats(CCharEntity* PChar) { - // Объявление переменных, нужных для рассчета. + // Declare variables needed for the calculation. - float raceStat = 0; // конечное число HP для уровня на основе расы. - float jobStat = 0; // конечное число HP для уровня на основе первичной профессии. - float sJobStat = 0; // коенчное число HP для уровня на основе вторичной профессии. - int32 bonusStat = 0; // бонусное число HP которое добавляется при соблюдении некоторых условий. + float raceStat = 0; // Finite number of HP for the level on the basis of race. + float jobStat = 0; // Finite number of HP for a level based on primary occupation. + float sJobStat = 0; // Number of HP for a level based on secondary profession. + int32 bonusStat = 0; // HP bonus number is added under certain conditions. - int32 baseValueColumn = 0; // номер колонки с базовым количеством HP - int32 scaleTo60Column = 1; // номер колонки с модификатором до 60 уровня - int32 scaleOver30Column = 2; // номер колонки с модификатором после 30 уровня - int32 scaleOver60Column = 3; // номер колонки с модификатором после 60 уровня - int32 scaleOver75Column = 4; // номер колонки с модификатором после 75 уровня - int32 scaleOver60 = 2; // номер колонки с модификатором для расчета MP после 60 уровня - int32 scaleOver75 = 3; // номер колонки с модификатором для расчета Статов после 75-го уровня + int32 baseValueColumn = 0; // Column number to the base of HP + int32 scaleTo60Column = 1; // Column number with the modifier level 60 + int32 scaleOver30Column = 2; // Column number modifier after level 30 + int32 scaleOver60Column = 3; // Column number modifier after level 60 + int32 scaleOver75Column = 4; // Column number modifier after level 75 + int32 scaleOver60 = 2; // Column number modifier to calculate the MP after level 60 + int32 scaleOver75 = 3; // Column number modifier to calculate the article after level 75 uint8 grade; @@ -136,23 +136,23 @@ case 8: race = 4; break; //Galka } - // Расчет прироста HP от main job + // The calculation of the gain HP main job - int32 mainLevelOver30 = dsp_cap(mlvl - 30, 0, 30); // Расчет условия +1HP каждый лвл после 30 уровня - int32 mainLevelUpTo60 = (mlvl < 60 ? mlvl - 1 : 59 ); // Первый режим рассчета до 60 уровня (Используется так же и для MP) - int32 mainLevelOver60To75 = dsp_cap(mlvl - 60, 0, 15); // Второй режим расчета после 60 уровня - int32 mainLevelOver75 = (mlvl < 75 ? 0 : mlvl - 75); // Третий режим расчета после 75 уровня + int32 mainLevelOver30 = dsp_cap(mlvl - 30, 0, 30); // Calculation conditions +1 HP each lvl after level 30 + int32 mainLevelUpTo60 = (mlvl < 60 ? mlvl - 1 : 59 ); // The first mode calculation level 60 (used also for MP) + int32 mainLevelOver60To75 = dsp_cap(mlvl - 60, 0, 15); // The second mode of calculation after level 60 + int32 mainLevelOver75 = (mlvl < 75 ? 0 : mlvl - 75); // The third mode of calculation after level 75 - //Расчет бонусного количества HP + //Calculation of bonus HP - int32 mainLevelOver10 = (mlvl < 10 ? 0 : mlvl - 10); // +2HP на каждом уровне после 10 - int32 mainLevelOver50andUnder60 = dsp_cap(mlvl - 50, 0, 10); // +2HP на каждом уровне в промежутке от 50 до 60 уровня + int32 mainLevelOver10 = (mlvl < 10 ? 0 : mlvl - 10); // +2HP at every level after 10 + int32 mainLevelOver50andUnder60 = dsp_cap(mlvl - 50, 0, 10); // +2HP at every level in the range from 50 to 60 levels int32 mainLevelOver60 = (mlvl < 60 ? 0 : mlvl - 60); - // Расчет прироста HP от дополнительной профессии + // The calculation of the additional HP gain profession - int32 subLevelOver10 = dsp_cap(slvl - 10, 0, 20); // +1HP на каждый уровень после 10 (/2) - int32 subLevelOver30 = (slvl < 30 ? 0 : slvl - 30); // +1HP на каждый уровень после 30 + int32 subLevelOver10 = dsp_cap(slvl - 10, 0, 20); // +1HP for each level after 10 (/2) + int32 subLevelOver30 = (slvl < 30 ? 0 : slvl - 30); // +1HP for each level after 30 // Расчет raceStat jobStat bonusStat sJobStat // Расчет по расе @@ -167,7 +167,7 @@ // raceStat = (int32)(statScale[grade][baseValueColumn] + statScale[grade][scaleTo60Column] * (mlvl - 1)); - // Расчет по main job + // Раcket main job grade = grade::GetJobGrade(mjob,0); jobStat = grade::GetHPScale(grade,baseValueColumn) + @@ -176,10 +176,10 @@ (grade::GetHPScale(grade,scaleOver60Column) * mainLevelOver60To75) + (grade::GetHPScale(grade,scaleOver75Column) * mainLevelOver75); - // Расчет бонусных HP + // Расket bonus HP bonusStat = (mainLevelOver10 + mainLevelOver50andUnder60) * 2; - // Расчет по support job + // Раcket support job if (slvl > 0) { grade = grade::GetJobGrade(sjob,0); @@ -195,30 +195,30 @@ uint16 MeritBonus = PChar->PMeritPoints->GetMeritValue(MERIT_MAX_HP, PChar); PChar->health.maxhp = (int16)(raceStat + jobStat + bonusStat + sJobStat + MeritBonus); - //Начало расчера MP + //Home raschera MP raceStat = 0; jobStat = 0; sJobStat = 0; - // Расчет MP расе. + // Раcket MP расе. grade = grade::GetRaceGrades(race,1); - //Если у main job нет МП рейтинга, расчитиваем расовый бонус на основе уровня subjob уровня(при условии, что у него есть МП рейтинг) + // If there is no main job megapixel rating raschitivaem racial bonus based on the level subjob level (provided that it has a megapixel rating) if (grade::GetJobGrade(mjob,1) == 0) { - if (grade::GetJobGrade(sjob,1) != 0 && slvl > 0) // В этом выражении ошибка + if (grade::GetJobGrade(sjob,1) != 0 && slvl > 0) // In this expression, the error { raceStat = (grade::GetMPScale(grade,0) + grade::GetMPScale(grade,scaleTo60Column) * (slvl - 1)) / 2; // Вот здесь ошибка } }else{ - //Расчет нормального расового бонуса + //Calculation of normal racial bonus raceStat = grade::GetMPScale(grade,0) + grade::GetMPScale(grade,scaleTo60Column) * mainLevelUpTo60 + grade::GetMPScale(grade,scaleOver60) * mainLevelOver60; } - //Для главной профессии + //For the main occupation grade = grade::GetJobGrade(mjob,1); if (grade > 0) { @@ -227,7 +227,7 @@ grade::GetMPScale(grade,scaleOver60) * mainLevelOver60; } - //Для дополнительной профессии + //For more professions if (slvl > 0) { grade = grade::GetJobGrade(sjob,1); @@ -235,7 +235,7 @@ } MeritBonus = PChar->PMeritPoints->GetMeritValue(MERIT_MAX_MP, PChar); - PChar->health.maxmp = (int16)(raceStat + jobStat + sJobStat + MeritBonus); // результат расчета MP + PChar->health.maxmp = (int16)(raceStat + jobStat + sJobStat + MeritBonus); // result of the calculation MP //add in evasion from skill @@ -248,13 +248,13 @@ PChar->setModifier(MOD_EVA,eva); - //Начало расчета характеристик + //Start calculating the characteristics uint8 counter = 0; for (uint8 StatIndex = 2; StatIndex <=8; ++StatIndex) { - // расчет по расе + // Calculated by reference to race grade = grade::GetRaceGrades(race,StatIndex); raceStat = grade::GetStatScale(grade,0) + grade::GetStatScale(grade,scaleTo60Column) * mainLevelUpTo60; @@ -268,7 +268,7 @@ } } - // расчет по профессии + // Calculation of the profession grade = grade::GetJobGrade(mjob,StatIndex); jobStat = grade::GetStatScale(grade,0) + grade::GetStatScale(grade,scaleTo60Column) * mainLevelUpTo60; @@ -282,7 +282,7 @@ } } - // расчет по дополнительной профессии + // Payment on the additional trade if (slvl > 0) { grade = grade::GetJobGrade(sjob,StatIndex); @@ -294,7 +294,7 @@ // get each merit bonus stat, str,dex,vit and so on... MeritBonus = PChar->PMeritPoints->GetMeritValue((Merit_t*)PChar->PMeritPoints->GetMeritByIndex(StatIndex), PChar); - // Вывод значения + // Printing a WBUFW(&PChar->stats,counter) = (uint16)(raceStat + jobStat + sJobStat + MeritBonus); counter += 2; } @@ -302,8 +302,8 @@ /************************************************************************ * * -* Предварительная версия загрузки персонажа. Функция будет * -* оптимизирована после определения всех необходимых данных и таблиц * +* Pre-download version of the character. The function will be * +* optimized after determining all the necessary data and tables * * * ************************************************************************/ @@ -366,6 +366,8 @@ PChar->profile.nation = (uint8)Sql_GetIntData(SqlHandle,13); + PChar->SetPlayTime(Sql_GetUIntData(SqlHandle, 21)); + size_t length = 0; int8* quests = NULL; Sql_GetData(SqlHandle,14,&quests,&length); @@ -679,7 +681,7 @@ /************************************************************************ * * -* Загружаем инвентарь персонажа * +* Load the character's inventory * * * ************************************************************************/ @@ -775,7 +777,7 @@ } if (PItem->getType() & ITEM_FURNISHING && PItem->getLocationID() == LOC_MOGSAFE) { - if (Sql_GetIntData(SqlHandle,10) != 0) // способ узнать, что предмет действительно установлен + if (Sql_GetIntData(SqlHandle,10) != 0) // Way to know that the object is indeed installed { ((CItemFurnishing*)PItem)->setSubType(ITEM_LOCKED); @@ -844,21 +846,21 @@ /************************************************************************ * * -* Отправляем список текущих/завершенных квестов и миссий * +* Send the list of current / completed quests and mission * * * ************************************************************************/ void SendQuestMissionLog(CCharEntity* PChar) { - // в нижележащем цикле загружаются все квесты, текущие и выполненные - // в одном пакете с текущими квестами Aht Urhgan отправляется информация о текущих миссиях + // In the underlying cycle is loaded all the quests, current and completed + // In the same package with the current quest Aht Urhgan will receive information about the current missions // Treasures of Aht Urhgan // Wings of the Goddess Missions // Assault Missions // Campaign Operations - // пакет с завершенными квестами Aht Urhgan содержит завершенные миссии Assault Missions + // Package to complete the quest has completed Aht Urhgan Mission Assault Missions - for (uint8 status = 0x01; status <= 0x02; ++status) + for (uint8 status = 0x01; status <= 0x02; ++status) { for (uint8 areaID = 0; areaID <= QUESTS_CRYSTALWAR ; ++areaID) { @@ -883,12 +885,12 @@ } } - // обновляем статус миссий + // Update the status of the mission // National Missions // Rise of the Zilart and Chains of Promathia Missions // Add-on Scenarios - // так как все эти миссии обновляются вместе, - // то достаточно выполнить обновление для MISSION_ZILART + // For all these missions are updated together + // It is sufficient to perform the updates MISSION_ZILART PChar->pushPacket(new CQuestMissionLogPacket(PChar, MISSION_ZILART, 0x01)); @@ -897,7 +899,7 @@ /************************************************************************ * * -* Отправляем списки ключевых предметов персонажа * +* Send the list of key items of the character * * * ************************************************************************/ @@ -911,7 +913,7 @@ /************************************************************************ * * -* Отправляем персонажу весь его инвентарь * +* Send a character all its inventory * * * ************************************************************************/ @@ -960,11 +962,11 @@ /************************************************************************ * * -* Добавляем новый предмет персонажу в выбранный контейнер * +* Add a new item to the character selected container * * * ************************************************************************/ -// TODO: мне не нравится параметр silens, нужно придумать что-нибудь более элегантное +// TODO: I do not like setting silens, to come up with something more elegant uint8 AddItem(CCharEntity* PChar, uint8 LocationID, uint16 ItemID, uint32 quantity, bool silence) { @@ -986,7 +988,7 @@ /************************************************************************ * * -* Добавляем новый предмет персонажу в выбранный контейнер * +* Add a new item to the character selected container * * * ************************************************************************/ @@ -1048,7 +1050,7 @@ /************************************************************************ * * -* Проверяем наличие предмета у персонажа * +* Check the presence of the subject of the character * * * ************************************************************************/ @@ -1094,7 +1096,7 @@ /************************************************************************ * * -* Перемещаем предмет в указанную ячейки или первую пустую * +* Move the objects in the specified cell or the first empty * * * ************************************************************************/ @@ -1128,7 +1130,7 @@ PChar->pushPacket(new CInventoryItemPacket(PItemContainer->GetItem(NewSlotID), LocationID, NewSlotID)); return NewSlotID; } - PItemContainer->InsertItem(NULL, NewSlotID); // отменяем все изменения контейнера + PItemContainer->InsertItem(NULL, NewSlotID); // container, the changes } } ShowError(CL_RED"charutils::MoveItem: item can't be moved\n" CL_RESET); @@ -1137,7 +1139,7 @@ /************************************************************************ * * -* Обновляем количество предметов в указанных контейнере и ячейке * +* Update the number of items in the specified container and cell * * * ************************************************************************/ @@ -1191,7 +1193,7 @@ /************************************************************************ * * -* Проверяем возможность обмена между персонажами * +* Check the possibility of exchange between the characters * * * ************************************************************************/ @@ -1218,7 +1220,7 @@ /************************************************************************ * * -* Совершаем обмен между персонажами * +* Make an exchange between characters * * * ************************************************************************/ @@ -1243,8 +1245,8 @@ /************************************************************************ * * -* Снимаем с персонажа экипированный предмет без обновления внешного * -* вида. Используется как вспомогательная функция в связке с другими * +* Removes Equipped object without updating the External * +* species. Used as an auxiliary function in conjunction with other * * * ************************************************************************/ @@ -1344,6 +1346,9 @@ } PChar->PBattleAI->SetCurrentAction(ACTION_RANGED_INTERRUPT); PChar->health.tp = 0; + PChar->StatusEffectContainer->DelStatusEffect(EFFECT_AFTERMATH_LV1); + PChar->StatusEffectContainer->DelStatusEffect(EFFECT_AFTERMATH_LV2); + PChar->StatusEffectContainer->DelStatusEffect(EFFECT_AFTERMATH_LV3); BuildingCharWeaponSkills(PChar); } break; @@ -1376,6 +1381,9 @@ } PChar->health.tp = 0; + PChar->StatusEffectContainer->DelStatusEffect(EFFECT_AFTERMATH_LV1); + PChar->StatusEffectContainer->DelStatusEffect(EFFECT_AFTERMATH_LV2); + PChar->StatusEffectContainer->DelStatusEffect(EFFECT_AFTERMATH_LV3); BuildingCharWeaponSkills(PChar); } break; @@ -1386,7 +1394,7 @@ /************************************************************************ * * -* Пытаемся экипировать предмет с соблюдением всех условий * +* We are trying to equip the item in compliance with all conditions * * * ************************************************************************/ @@ -1422,9 +1430,18 @@ { if (PItem->getType() & ITEM_WEAPON) { - switch (((CItemWeapon*)PItem)->getSkillType()) + switch (((CItemWeapon*)PItem)->getSkillType()) { case SKILL_H2H: + { + CItemArmor* armor = (CItemArmor*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_SUB]); + if ((armor != NULL) && (armor->getType() & ITEM_ARMOR)) + { + UnequipItem(PChar,SLOT_SUB); + } + PChar->look.sub = PItem->getModelId() + 0x1000; + } + break; case SKILL_GSD: case SKILL_GAX: case SKILL_SYH: @@ -1435,11 +1452,24 @@ CItemArmor* armor = (CItemArmor*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_SUB]); if ((armor != NULL) && (armor->getType() & ITEM_ARMOR)) { - UnequipItem(PChar,SLOT_SUB); + // Only one hand weapons, shields and grips can be offhanded. Grips should not be unequipped. + if (armor->IsShield()) + { + UnequipItem(PChar,SLOT_SUB); + } } - if (((CItemWeapon*)PItem)->getSkillType() == SKILL_H2H) + } + break; + default: + { + CItemArmor* armor = (CItemArmor*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_SUB]); + if ((armor != NULL) && (armor->getType() & ITEM_ARMOR)) { - PChar->look.sub = PItem->getModelId() + 0x1000; + // One-handed weapons can use shields but cannot use grips, take them off. + if (!armor->IsShield()) + { + UnequipItem(PChar,SLOT_SUB); + } } } break; @@ -1651,7 +1681,7 @@ PItem->setAssignTime(CVanaTime::getInstance()->getVanaTime()); PChar->PRecastContainer->Add(RECAST_ITEM, slotID, PItem->getReuseTime()); - // не забываем обновить таймер при экипировке предмета + // Do not forget to update the timer object when equipped PChar->pushPacket(new CInventoryItemPacket(PItem, LOC_INVENTORY, slotID)); PChar->pushPacket(new CInventoryFinishPacket()); @@ -1700,7 +1730,7 @@ if (!(PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_MAIN])->getType() & ITEM_ARMOR) || PChar->m_Weapons[SLOT_MAIN] == itemutils::GetUnarmedH2HItem()) { CheckUnarmedWeapon(PChar); - } + } BuildingCharWeaponSkills(PChar); } @@ -1710,7 +1740,7 @@ /************************************************************************ * * -* Проверяем возможность персонажа носить экипированные на нем предметы * +* Check the possibility of the character wearing equipped gear * * * ************************************************************************/ @@ -1769,13 +1799,13 @@ /************************************************************************ * * -* Проверяем логику всей экипировки персонажа * +* Check the logic of the entire equipment of the character * * * ************************************************************************/ -// позднее нужно будет сделать экипировку в структуре, -// куда добавить битовое поле, указывающее, в какой ячейке находится экипировка с условием -// для начала это поле избавит нас от проверки ячеек у персонажей без экипировки с условием +// Later need to make equipment in the structure, +// To add a bit field indicating which cell is equipment with a condition +// To the beginning of this field will save us from checking the cells in the characters without equipment with the condition void CheckEquipLogic(CCharEntity* PChar, SCRIPTTYPE ScriptType, uint32 param) { @@ -1848,9 +1878,9 @@ || PSkill->getID() == wsIDs[SLOT_MAIN] || PSkill->getID() == wsIDs[SLOT_SUB] || isInDynamis && (PSkill->getID() == wsDynIDs[SLOT_MAIN] || PSkill->getID() == wsDynIDs[SLOT_SUB])) { - addWeaponSkill(PChar, PSkill->getID()); - } - } + addWeaponSkill(PChar, PSkill->getID()); + } + } //add in ranged ws PItem = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_RANGED]); @@ -1865,10 +1895,10 @@ || PSkill->getID() == wsIDs[SLOT_RANGED] || isInDynamis && (PSkill->getID() == wsDynIDs[SLOT_RANGED])) { - addWeaponSkill(PChar, PSkill->getID()); - } - } - } + addWeaponSkill(PChar, PSkill->getID()); + } + } + } PChar->pushPacket(new CCharAbilitiesPacket(PChar)); } @@ -1890,7 +1920,7 @@ { CAbility* PAbility = AbilitiesList.at(i); - if (PPet->GetMLevel() >= PAbility->getLevel() && PetID>=8 && PetID<=15 && PAbility->getAddType() == ADDTYPE_NORMAL) //carby/fen/ele avatars NOT diabolos + if (PPet->GetMLevel() >= PAbility->getLevel() && PetID>=8 && PetID<=16 && PAbility->getAddType() == ADDTYPE_NORMAL) //carby/fen/ele avatars { //16 IDs per avatar starting from 496 if(PAbility->getID()>= (496+((PetID-8)*16)) && PAbility->getID() < (496+((PetID-7)*16))){ //pet ability @@ -1904,8 +1934,8 @@ /************************************************************************ * * -* Собираем рабочую таблицу способностей персонажа. С нулевым уровнем * -* должны быть 2h способности. По этому условию отсеиваем их для sjob * +* Collect worksheet Abilities. With zero- * +* should be 2h abilities. Under this condition sift them for sjob * * * ************************************************************************/ @@ -1935,6 +1965,12 @@ break; } } + + // Temp Solution until I figure why they don't load into the list + if(PChar->GetMJob() == JOB_SMN && PChar->GetMLevel() >= 87) + { + addAbility(PChar, 280); // Mana Cede + } //To stop a character with no SJob to receive the traits with job = 0 in the DB. if (PChar->GetSJob() == JOB_NON){ @@ -1968,8 +2004,8 @@ /************************************************************************ * * -* Собираем рабочую таблицу умений персонажа на основе реальной. * -* Добавляем ограничения, отмечаем умения основной профессии (rank != 0)* +* Collect worksheet skills of the character based on the real. * +* Add restrictions to note basic trade skills (rank != 0) * * * ************************************************************************/ @@ -2074,13 +2110,13 @@ /************************************************************************ * * -* Пытаемся увеличить значение умения * +* We are trying to increase the skills * * * ************************************************************************/ void TrySkillUP(CCharEntity* PChar, SKILLTYPE SkillID, uint8 lvl) { - DSP_DEBUG_BREAK_IF(SkillID >= MAX_SKILLTYPE); // выход за пределы допустимых умений + DSP_DEBUG_BREAK_IF(SkillID >= MAX_SKILLTYPE); // out of range of skills if ((PChar->WorkingSkills.rank[SkillID] != 0) && !(PChar->WorkingSkills.skill[SkillID] & 0x8000)) { @@ -2098,7 +2134,7 @@ uint8 SkillAmount = 1; uint8 tier = dsp_min(1 + (Diff/5), 5); - for(uint8 i = 0; i < 4; ++i) // 1 + 4 возможных дополнительных (максимум 5) + for(uint8 i = 0; i < 4; ++i) // 1 + 4 possible additional (maximum of 5) { random = rand() / ((double)RAND_MAX); @@ -2181,7 +2217,7 @@ /************************************************************************ * * -* Методы для работы с ключевыми предметами * +* Methods for working with key items * * * ************************************************************************/ @@ -2212,7 +2248,7 @@ /************************************************************************ * * -* Методы для работы с заклинаниями * +* Methods for working with spells * * * ************************************************************************/ @@ -2254,7 +2290,7 @@ /************************************************************************ * * -* Методы для работы со званиями * +* Methods for working with ranks * * * ************************************************************************/ @@ -2275,7 +2311,7 @@ /************************************************************************ * * -* Методы для работы с основными способностями * +* Methods for basic skills * * * ************************************************************************/ @@ -2358,7 +2394,7 @@ /************************************************************************ * * -* Обновляем MP, HP и TP персонажа * +* Update the MP, HP and TP character * * * ************************************************************************/ @@ -2388,7 +2424,7 @@ /************************************************************************ * * -* Инициализируем таблицу опыта * +* Initialize the table experience * * * ************************************************************************/ @@ -2431,15 +2467,15 @@ } } -/************************************************************************ -* * -* Узнаем реальное количество опыта, который персонаж получит с цели * -* * -************************************************************************/ +/******************************************************************************************** +* * +* Find out the real number of experiences that the character will receive from the target * +* * +********************************************************************************************/ uint32 GetRealExp(uint8 charlvl, uint8 moblvl) { - int32 levelDif = moblvl - charlvl + 34; + int32 levelDif = moblvl - charlvl + 34; if ((charlvl > 0) && (charlvl < 100)) { @@ -2450,7 +2486,7 @@ /************************************************************************ * * -* Узнаем количество опыта, необходимое для получения следующего уровня * +* Know the amount of experience needed to get the next level * * * ************************************************************************/ @@ -2475,12 +2511,14 @@ { //work out the amount of gil to give (guessed; replace with testing) uint32 gil = PMob->GetRandomGil(); + + gil = gil + (gil * (.5 * PChar->getMod(MOD_GILFINDER))); //distribute to said members (perhaps store pointers to each member in first loop?) if (PChar->PParty != NULL) { - // TODO: плохая реализация - два раза проверяем дистанцию, два раза проверяем один и тот же массив + // TODO: poor implementation - double check the distance, double check the same array uint8 count = 0; //work out how many pt members should get the gil @@ -2595,6 +2633,7 @@ else if (PMob->m_Family == 266 && PMob->getZone() == 174) monsterbonus = 1.23f; else if (PMob->m_Family == 206 && PMob->getZone() == 5) monsterbonus = 1.10f; else if (PMob->m_Family == 208 && PMob->getZone() == 24) monsterbonus = 1.23f; + else if (PMob->m_Type & MOBTYPE_NOTORIOUS && PMob->GetMLevel() > 75) monsterbonus = 5.00f; if (monsterbonus > 1.00f) exp *= monsterbonus; permonstercap = ((PMember->PParty != NULL && pcinzone > 1) ? 1.35f : 1.15f); if (PMember->GetMLevel() <= 50) @@ -2604,8 +2643,8 @@ else if (PMember->GetMLevel() <= 60) { if (exp > (250*permonstercap)) exp = 250*permonstercap; - } - else if (exp > (300*permonstercap)) + } + else if (exp > (300*permonstercap) && PMob->m_Type != MOBTYPE_NOTORIOUS && PMob->GetMLevel() <= 75) { exp = 300*permonstercap; } @@ -2625,13 +2664,13 @@ } else { - if (PMember->GetMLevel() <=10) PMember->expChain.chainTime = gettick()+50000; - else if (PMember->GetMLevel() <=20) PMember->expChain.chainTime = gettick()+100000; - else if (PMember->GetMLevel() <=30) PMember->expChain.chainTime = gettick()+150000; - else if (PMember->GetMLevel() <=40) PMember->expChain.chainTime = gettick()+200000; - else if (PMember->GetMLevel() <=50) PMember->expChain.chainTime = gettick()+250000; - else if (PMember->GetMLevel() <=60) PMember->expChain.chainTime = gettick()+300000; - else PMember->expChain.chainTime = gettick()+360000; + if (PMember->GetMLevel() <=10) PMember->expChain.chainTime = gettick()+50000*map_config.chain_bonus; + else if (PMember->GetMLevel() <=20) PMember->expChain.chainTime = gettick()+100000*map_config.chain_bonus; + else if (PMember->GetMLevel() <=30) PMember->expChain.chainTime = gettick()+150000*map_config.chain_bonus; + else if (PMember->GetMLevel() <=40) PMember->expChain.chainTime = gettick()+200000*map_config.chain_bonus; + else if (PMember->GetMLevel() <=50) PMember->expChain.chainTime = gettick()+250000*map_config.chain_bonus; + else if (PMember->GetMLevel() <=60) PMember->expChain.chainTime = gettick()+300000*map_config.chain_bonus; + else PMember->expChain.chainTime = gettick()+360000*map_config.chain_bonus; chainactive = false; PMember->expChain.chainNumber = 1; } @@ -2639,85 +2678,85 @@ { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+50000; break; - case 1: PMember->expChain.chainTime = gettick()+40000; break; - case 2: PMember->expChain.chainTime = gettick()+30000; break; - case 3: PMember->expChain.chainTime = gettick()+20000; break; - case 4: PMember->expChain.chainTime = gettick()+10000; break; - case 5: PMember->expChain.chainTime = gettick()+6000; break; - default: PMember->expChain.chainTime = gettick()+2000; break; + case 0: PMember->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+30000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+20000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+10000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+6000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+2000*map_config.chain_bonus; break; } } else if(chainactive && PMember->GetMLevel() <= 20) { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+100000; break; - case 1: PMember->expChain.chainTime = gettick()+80000; break; - case 2: PMember->expChain.chainTime = gettick()+60000; break; - case 3: PMember->expChain.chainTime = gettick()+40000; break; - case 4: PMember->expChain.chainTime = gettick()+20000; break; - case 5: PMember->expChain.chainTime = gettick()+8000; break; - default: PMember->expChain.chainTime = gettick()+4000; break; + case 0: PMember->expChain.chainTime = gettick()+100000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+80000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+20000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+8000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+4000*map_config.chain_bonus; break; } } else if(chainactive && PMember->GetMLevel() <= 30) { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+150000; break; - case 1: PMember->expChain.chainTime = gettick()+120000; break; - case 2: PMember->expChain.chainTime = gettick()+90000; break; - case 3: PMember->expChain.chainTime = gettick()+60000; break; - case 4: PMember->expChain.chainTime = gettick()+30000; break; - case 5: PMember->expChain.chainTime = gettick()+10000; break; - default: PMember->expChain.chainTime = gettick()+5000; break; + case 0: PMember->expChain.chainTime = gettick()+150000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+120000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+90000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+30000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+10000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+5000*map_config.chain_bonus; break; } } else if(chainactive && PMember->GetMLevel() <= 40) { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+200000; break; - case 1: PMember->expChain.chainTime = gettick()+160000; break; - case 2: PMember->expChain.chainTime = gettick()+120000; break; - case 3: PMember->expChain.chainTime = gettick()+80000; break; - case 4: PMember->expChain.chainTime = gettick()+40000; break; - case 5: PMember->expChain.chainTime = gettick()+40000; break; - default: PMember->expChain.chainTime = gettick()+30000; break; + case 0: PMember->expChain.chainTime = gettick()+200000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+160000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+120000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+80000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+30000*map_config.chain_bonus; break; } } else if(chainactive && PMember->GetMLevel() <= 50) { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+250000; break; - case 1: PMember->expChain.chainTime = gettick()+200000; break; - case 2: PMember->expChain.chainTime = gettick()+150000; break; - case 3: PMember->expChain.chainTime = gettick()+100000; break; - case 4: PMember->expChain.chainTime = gettick()+50000; break; - case 5: PMember->expChain.chainTime = gettick()+50000; break; - default: PMember->expChain.chainTime = gettick()+50000; break; + case 0: PMember->expChain.chainTime = gettick()+250000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+200000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+150000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+100000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; } } else if(chainactive && PMember->GetMLevel() <= 60) { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+300000; break; - case 1: PMember->expChain.chainTime = gettick()+240000; break; - case 2: PMember->expChain.chainTime = gettick()+180000; break; - case 3: PMember->expChain.chainTime = gettick()+120000; break; - case 4: PMember->expChain.chainTime = gettick()+90000; break; - case 5: PMember->expChain.chainTime = gettick()+60000; break; - default: PMember->expChain.chainTime = gettick()+60000; break; + case 0: PMember->expChain.chainTime = gettick()+300000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+240000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+180000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+120000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+90000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; } } else if (chainactive) { switch(PMember->expChain.chainNumber) { - case 0: PMember->expChain.chainTime = gettick()+360000; break; - case 1: PMember->expChain.chainTime = gettick()+300000; break; - case 2: PMember->expChain.chainTime = gettick()+240000; break; - case 3: PMember->expChain.chainTime = gettick()+165000; break; - case 4: PMember->expChain.chainTime = gettick()+105000; break; - case 5: PMember->expChain.chainTime = gettick()+60000; break; - default: PMember->expChain.chainTime = gettick()+60000; break; + case 0: PMember->expChain.chainTime = gettick()+360000*map_config.chain_bonus; break; + case 1: PMember->expChain.chainTime = gettick()+300000*map_config.chain_bonus; break; + case 2: PMember->expChain.chainTime = gettick()+240000*map_config.chain_bonus; break; + case 3: PMember->expChain.chainTime = gettick()+165000*map_config.chain_bonus; break; + case 4: PMember->expChain.chainTime = gettick()+105000*map_config.chain_bonus; break; + case 5: PMember->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + default: PMember->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; } } exp = charutils::AddExpBonus(PMember, exp); @@ -2732,8 +2771,8 @@ uint8 Pzone = PMember->getZone(); if (PMob->m_Type == MOBTYPE_NORMAL && ((Pzone > 0 && Pzone < 39) || (Pzone > 42 && Pzone < 134) || (Pzone > 135 && Pzone < 185) || (Pzone > 188 && Pzone < 255))) { - if (PMember->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET) && PMob->m_Element > 0 && rand()%100 < 20 && - PMember->loc.zone == PMob->loc.zone) // Need to move to SIGNET_CHANCE constant + if ((PMember->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET) || PMember->StatusEffectContainer->HasStatusEffect(EFFECT_SANCTION)) && PMob->m_Element > 0 && + rand()%100 < (20 - PMember->getMod(MOD_CRYSTAL_DROP)) && PMember->loc.zone == PMob->loc.zone) // Need to move to SIGNET_CHANCE constant { PMember->PTreasurePool->AddItem(4095 + PMob->m_Element, PMob); } @@ -2761,6 +2800,7 @@ else if (PMob->m_Family == 266 && PMob->getZone() == 174) monsterbonus = 1.23f; else if (PMob->m_Family == 206 && PMob->getZone() == 5) monsterbonus = 1.10f; else if (PMob->m_Family == 208 && PMob->getZone() == 24) monsterbonus = 1.23f; + else if (PMob->m_Type & MOBTYPE_NOTORIOUS && PMob->GetMLevel() > 75) monsterbonus = 5.00f; if (monsterbonus > 1.00f) exp *= monsterbonus; if (PChar->GetMLevel() <= 50) { @@ -2769,8 +2809,8 @@ else if (PChar->GetMLevel() <= 60) { if (exp > (250*permonstercap)) exp = 250*permonstercap; - } - else if (exp > (300*permonstercap)) + } + else if (exp > (300*permonstercap) && PMob->m_Type != MOBTYPE_NOTORIOUS && PMob->GetMLevel() <= 75) { exp = 300*permonstercap; } @@ -2790,13 +2830,13 @@ } else { - if (PChar->GetMLevel() <=10) PChar->expChain.chainTime = gettick()+50000; - else if (PChar->GetMLevel() <=20) PChar->expChain.chainTime = gettick()+100000; - else if (PChar->GetMLevel() <=30) PChar->expChain.chainTime = gettick()+150000; - else if (PChar->GetMLevel() <=40) PChar->expChain.chainTime = gettick()+200000; - else if (PChar->GetMLevel() <=50) PChar->expChain.chainTime = gettick()+250000; - else if (PChar->GetMLevel() <=60) PChar->expChain.chainTime = gettick()+300000; - else PChar->expChain.chainTime = gettick()+360000; + if (PChar->GetMLevel() <=10) PChar->expChain.chainTime = gettick()+50000*map_config.chain_bonus; + else if (PChar->GetMLevel() <=20) PChar->expChain.chainTime = gettick()+100000*map_config.chain_bonus; + else if (PChar->GetMLevel() <=30) PChar->expChain.chainTime = gettick()+150000*map_config.chain_bonus; + else if (PChar->GetMLevel() <=40) PChar->expChain.chainTime = gettick()+200000*map_config.chain_bonus; + else if (PChar->GetMLevel() <=50) PChar->expChain.chainTime = gettick()+250000*map_config.chain_bonus; + else if (PChar->GetMLevel() <=60) PChar->expChain.chainTime = gettick()+300000*map_config.chain_bonus; + else PChar->expChain.chainTime = gettick()+360000*map_config.chain_bonus; chainactive = false; PChar->expChain.chainNumber = 1; } @@ -2804,85 +2844,85 @@ { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+50000; break; - case 1: PChar->expChain.chainTime = gettick()+40000; break; - case 2: PChar->expChain.chainTime = gettick()+30000; break; - case 3: PChar->expChain.chainTime = gettick()+20000; break; - case 4: PChar->expChain.chainTime = gettick()+10000; break; - case 5: PChar->expChain.chainTime = gettick()+6000; break; - default: PChar->expChain.chainTime = gettick()+2000; break; + case 0: PChar->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+30000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+20000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+10000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+6000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+2000*map_config.chain_bonus; break; } } else if(chainactive && PChar->GetMLevel() <= 20) { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+100000; break; - case 1: PChar->expChain.chainTime = gettick()+80000; break; - case 2: PChar->expChain.chainTime = gettick()+60000; break; - case 3: PChar->expChain.chainTime = gettick()+40000; break; - case 4: PChar->expChain.chainTime = gettick()+20000; break; - case 5: PChar->expChain.chainTime = gettick()+8000; break; - default: PChar->expChain.chainTime = gettick()+4000; break; + case 0: PChar->expChain.chainTime = gettick()+100000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+80000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+20000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+8000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+4000*map_config.chain_bonus; break; } } else if(chainactive && PChar->GetMLevel() <= 30) { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+150000; break; - case 1: PChar->expChain.chainTime = gettick()+120000; break; - case 2: PChar->expChain.chainTime = gettick()+90000; break; - case 3: PChar->expChain.chainTime = gettick()+60000; break; - case 4: PChar->expChain.chainTime = gettick()+30000; break; - case 5: PChar->expChain.chainTime = gettick()+10000; break; - default: PChar->expChain.chainTime = gettick()+5000; break; + case 0: PChar->expChain.chainTime = gettick()+150000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+120000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+90000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+30000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+10000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+5000*map_config.chain_bonus; break; } } else if(chainactive && PChar->GetMLevel() <= 40) { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+200000; break; - case 1: PChar->expChain.chainTime = gettick()+160000; break; - case 2: PChar->expChain.chainTime = gettick()+120000; break; - case 3: PChar->expChain.chainTime = gettick()+80000; break; - case 4: PChar->expChain.chainTime = gettick()+40000; break; - case 5: PChar->expChain.chainTime = gettick()+40000; break; - default: PChar->expChain.chainTime = gettick()+30000; break; + case 0: PChar->expChain.chainTime = gettick()+200000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+160000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+120000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+80000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+40000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+30000*map_config.chain_bonus; break; } } else if(chainactive && PChar->GetMLevel() <= 50) { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+250000; break; - case 1: PChar->expChain.chainTime = gettick()+200000; break; - case 2: PChar->expChain.chainTime = gettick()+150000; break; - case 3: PChar->expChain.chainTime = gettick()+100000; break; - case 4: PChar->expChain.chainTime = gettick()+50000; break; - case 5: PChar->expChain.chainTime = gettick()+50000; break; - default: PChar->expChain.chainTime = gettick()+50000; break; + case 0: PChar->expChain.chainTime = gettick()+250000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+200000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+150000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+100000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+50000*map_config.chain_bonus; break; } } else if(chainactive && PChar->GetMLevel() <= 60) { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+300000; break; - case 1: PChar->expChain.chainTime = gettick()+240000; break; - case 2: PChar->expChain.chainTime = gettick()+180000; break; - case 3: PChar->expChain.chainTime = gettick()+120000; break; - case 4: PChar->expChain.chainTime = gettick()+90000; break; - case 5: PChar->expChain.chainTime = gettick()+60000; break; - default: PChar->expChain.chainTime = gettick()+60000; break; + case 0: PChar->expChain.chainTime = gettick()+300000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+240000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+180000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+120000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+90000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; } } else if (chainactive) { switch(PChar->expChain.chainNumber) { - case 0: PChar->expChain.chainTime = gettick()+360000; break; - case 1: PChar->expChain.chainTime = gettick()+300000; break; - case 2: PChar->expChain.chainTime = gettick()+240000; break; - case 3: PChar->expChain.chainTime = gettick()+165000; break; - case 4: PChar->expChain.chainTime = gettick()+105000; break; - case 5: PChar->expChain.chainTime = gettick()+60000; break; - default: PChar->expChain.chainTime = gettick()+60000; break; + case 0: PChar->expChain.chainTime = gettick()+360000*map_config.chain_bonus; break; + case 1: PChar->expChain.chainTime = gettick()+300000*map_config.chain_bonus; break; + case 2: PChar->expChain.chainTime = gettick()+240000*map_config.chain_bonus; break; + case 3: PChar->expChain.chainTime = gettick()+165000*map_config.chain_bonus; break; + case 4: PChar->expChain.chainTime = gettick()+105000*map_config.chain_bonus; break; + case 5: PChar->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; + default: PChar->expChain.chainTime = gettick()+60000*map_config.chain_bonus; break; } } exp = charutils::AddExpBonus(PChar, exp); @@ -2895,9 +2935,10 @@ return; } uint8 Pzone = PChar->getZone(); - if (PMob->m_Type == MOBTYPE_NORMAL && ((Pzone > 0 && Pzone < 39) || (Pzone > 42 && Pzone < 134) || (Pzone > 135 && Pzone < 185) || (Pzone > 188 && Pzone < 255))) + if (PMob->m_Type & MOBTYPE_NORMAL && ((Pzone > 0 && Pzone < 39) || (Pzone > 42 && Pzone < 134) || (Pzone > 135 && Pzone < 185) || (Pzone > 188 && Pzone < 255))) { - if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET) && PMob->m_Element > 0 && rand()%100 < 20) // Need to move to SIGNET_CHANCE constant + if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET) && PMob->m_Element > 0 && + rand()%100 < (20 - PChar->getMod(MOD_CRYSTAL_DROP))) // Need to move to SIGNET_CHANCE constant { PChar->PTreasurePool->AddItem(4095 + PMob->m_Element, PMob); } @@ -2942,8 +2983,8 @@ if (PChar->m_LevelRestriction == 0 || PChar->jobs.job[PChar->GetMJob()] < PChar->m_LevelRestriction) { - PChar->SetMLevel(PChar->jobs.job[PChar->GetMJob()]); - PChar->SetSLevel(PChar->jobs.job[PChar->GetSJob()]); + PChar->SetMLevel(PChar->jobs.job[PChar->GetMJob()]); + PChar->SetSLevel(PChar->jobs.job[PChar->GetSJob()]); } BuildingCharSkillsTable(PChar); @@ -3024,7 +3065,7 @@ /************************************************************************ * * -* Добавляем очки опытка указанному персонажу * +* Adding Points opytka chosen character * * * ************************************************************************/ @@ -3094,13 +3135,13 @@ //TODO: Only add IS if player has Saction //TODO: Killing mobs != gaining Zeni - if(PChar->getZone() >= 48 && PChar->getZone() <= 79) - { + if(PChar->getZone() >= 48 && PChar->getZone() <= 79) + { PChar->RegionPoints[3] += (exp*0.1f); // 10% // PChar->RegionPoints[10] += (exp*0.1f); // 10% - PChar->pushPacket(new CConquestPacket(PChar)); - } + PChar->pushPacket(new CConquestPacket(PChar)); } + } //player levels up @@ -3166,7 +3207,7 @@ /************************************************************************ * * -* Устанавливаем ограничение уровня персонажа * +* Set the level of the character limit * * * ************************************************************************/ @@ -3235,7 +3276,7 @@ /************************************************************************ * * -* Сохраняем позицию * +* Reserve position * * * ************************************************************************/ @@ -3266,7 +3307,7 @@ /************************************************************************ * * -* Сохраняем список квестов * +* Save the list of quests * * * ************************************************************************/ @@ -3288,7 +3329,7 @@ /************************************************************************ * * -* Сохраняем список квестов * +* Save the amount of fame * * * ************************************************************************/ @@ -3345,7 +3386,7 @@ /************************************************************************ * * -* Cохраняем список колючевых предметов * +* Maintains a list of items kolyuchevyh * * * ************************************************************************/ @@ -3372,7 +3413,7 @@ /************************************************************************ * * -* Cохраняем список колючевых предметов * +* Maintains a list of items kolyuchevyh * * * ************************************************************************/ @@ -3388,7 +3429,7 @@ /************************************************************************ * * -* Сохраняем список выученных заклинаний * +* Store a list of memorized spells * * * ************************************************************************/ @@ -3410,7 +3451,7 @@ /************************************************************************ * * -* Сохраняем список выученных заклинаний * +* Store a list of memorized abilities * * * ************************************************************************/ @@ -3431,7 +3472,7 @@ /************************************************************************ * * -* Сохраняем список званий * +* Store a list of titles * * * ************************************************************************/ @@ -3456,7 +3497,7 @@ /************************************************************************ * * -* Сохраняем список посещенных зон * +* Save the list of visited zones * * * ************************************************************************/ @@ -3472,7 +3513,7 @@ /************************************************************************ * * -* Сохраняем экипировку и внешний вид персонажа. * +* Store equipment and appearance of the character. * * * ************************************************************************/ @@ -3524,7 +3565,7 @@ /************************************************************************ * * -* Сохраняем часть текущих характеристик персонажа * +* Save the part of the current characteristics of the character * * * ************************************************************************/ @@ -3566,7 +3607,7 @@ /************************************************************************ * * -* Сохраняем текущие уровни профессий персонажа * +* Retain the current levels of occupational character * * * ************************************************************************/ @@ -3606,7 +3647,7 @@ /************************************************************************ * * -* Сохраняем текущий опыт персонажа * +* Save the current experience of the character * * * ************************************************************************/ @@ -3650,7 +3691,7 @@ /************************************************************************ * * -* Сохраняем значение выбранного умения персонажа * +* Save the value of the selected character's abilities * * * ************************************************************************/ @@ -3896,6 +3937,11 @@ Sql_Query(SqlHandle, fmtQuery, (uint32)time(NULL), PChar->id); } +void SavePlayTime(CCharEntity* PChar) +{ + Sql_Query(SqlHandle, "UPDATE chars SET playtime = '%u' WHERE charid = '%u' LIMIT 1;", PChar->GetPlayTime(), PChar->id); +} + /************************************************************************ * * * Checks which UnarmedItem to grant when SLOT_MAIN is empty. * @@ -4097,13 +4143,15 @@ return dsp_cap(cost, 0, 9999); } +int8 QuickMagicChance = 0; + uint32 CalculateSpellcastTime(CCharEntity* PChar, CSpell* PSpell) { bool applyArts = true; uint32 base = PSpell->getCastTime(); uint32 cast = base; - if (PSpell->getSpellGroup() == SPELLGROUP_BLACK) + if (PSpell->getSpellGroup() == SPELLGROUP_BLACK) // Black Magic Cast Modifiers { if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_ALACRITY)) { @@ -4115,8 +4163,17 @@ { cast = cast * (1.0f + PChar->getMod(MOD_BLACK_MAGIC_CAST)/100.0f); } + else + { + int16 BlackCastMod = PChar->getMod(MOD_BLACK_CAST); + cast = cast * ((float)(100-BlackCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } } - else if (PSpell->getSpellGroup() == SPELLGROUP_WHITE) + else if (PSpell->getSpellGroup() == SPELLGROUP_WHITE) // White Magic Cast Modifiers { if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_CELERITY)) { @@ -4128,8 +4185,177 @@ { cast = cast * (1.0f + PChar->getMod(MOD_WHITE_MAGIC_CAST)/100.0f); } + if ((PSpell->getID() >= 1 && PSpell->getID() <= 11) || (PSpell->getID() == 93 || PSpell->getID() == 474 || PSpell->getID() == 475)) + { + int16 CureCastMod = PChar->getMod(MOD_CURE_CAST); + if (PSpell->getID() >= 1 && PSpell->getID() <= 11) // Cure - Curaga Magic Cast Modifier + { + cast = cast * ((float)(100-CureCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getID() == 93 || PSpell->getID() == 474 || PSpell->getID() == 475) // Cura Magic Cast Modifier + { + cast = cast * ((float)(100-CureCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + } + else if ((PSpell->getID() >= 14 && PSpell->getID() <= 20) || PSpell->getID() == 94 || PSpell->getID() == 95 || PSpell->getID() == 143) // Status Ailment Recovery Spells (Divine Benison) + { + int16 DivineBenisonCastMod = PChar->getMod(MOD_DIVINE_BENISON_FASTCAST); + cast = cast * ((float)(100-DivineBenisonCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getID() == 54) // Stoneskin Cast Modifier + { + int16 StoneskinCastMod = PChar->getMod(MOD_STONESKIN_CAST); + cast = cast * ((float)(100-StoneskinCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } } - return cast * ((100.0f-(float)dsp_cap(PChar->getMod(MOD_FASTCAST),-100,50))/100.0f); + else if (PSpell->getSpellGroup() == SPELLGROUP_SUMMONING) // Summoning Magic Cast Modifiers + { + int16 SummoningCastMod = PChar->getMod(MOD_SUMMON_CAST); + cast = cast * ((float)(100-SummoningCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getSpellGroup() == SPELLGROUP_BLUE) // Blue Magic Cast Modifiers + { + int16 BlueCastMod = PChar->getMod(MOD_BLUE_CAST); + cast = cast * ((float)(100-BlueCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getSpellGroup() == SPELLGROUP_NINJUTSU) // Ninjutsu Cast Modifiers + { + if (PSpell->getID() >= 338 && PSpell->getID() <= 340) // Utsusemi Cast Modifier + { + int16 UtsusemiCastMod = PChar->getMod(MOD_UTSUSEMI_CAST); + cast = cast * ((float)(100-UtsusemiCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + } + else if (PSpell->getSpellGroup() == SPELLGROUP_SONG) // Song Cast Modifiers + { + int16 SongCastMod = PChar->getMod(MOD_SONG_CAST); + cast = cast * ((float)(100-SongCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_TROUBADOUR) && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_NIGHTINGALE)) + { + cast = cast * .75; + } + else if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_NIGHTINGALE)) + { + cast = cast * .5; + int16 NightingaleMerit = (PChar->PMeritPoints->GetMeritValue(MERIT_NIGHTINGALE,PChar)) - 25; + int8 NightingaleChance = (rand() % 99) + 1; + if (NightingaleChance <= NightingaleMerit) + { + cast = 0; + } + } + else if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_TROUBADOUR)) + { + cast = cast * 1.5; + } + + } + + // Grimoire Cast Modifier + if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_LIGHT_ARTS) || PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DARK_ARTS)) + { + if (!PChar->StatusEffectContainer->HasStatusEffect(EFFECT_ALACRITY) || !PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANIFESTATION)) + { + int16 GrimoireCastMod = PChar->getMod(MOD_GRIMOIRE_CAST); + cast = cast * ((float)(100-GrimoireCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + } + + // Magic Skill Type Casting Modifiers + if (PSpell->getSkillType() == 34) // Enhancing Magic Cast Modifier + { + int16 EnhancingCastMod = PChar->getMod(MOD_ENHANCING_CAST); + cast = cast * ((float)(100-EnhancingCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getSkillType() == 37) // Dark Magic Cast Modifier + { + int16 DarkCastMod = PChar->getMod(MOD_DARK_MAG_CAST); + cast = cast * ((float)(100-DarkCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getSkillType() == 33) // Healing Magic Cast Modifier + { + int16 HealingCastMod = PChar->getMod(MOD_HEALING_CAST); + cast = cast * ((float)(100-HealingCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getSkillType() == 36) // Elemental Magic Cast Modifier + { + int16 ElementalCastMod = PChar->getMod(MOD_ELEMENTAL_CAST); + cast = cast * ((float)(100-ElementalCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + else if (PSpell->getSkillType() == 35) // Enfeebling Magic Cast Modifier + { + int16 EnfeeblingCastMod = PChar->getMod(MOD_ENFEEBLING_CAST); + cast = cast * ((float)(100-EnfeeblingCastMod)/100); + if (cast < 1000) + { + cast = 1000; + } + } + + // Quick Magic + if (PChar->getMod(MOD_QUICK_MAGIC) > 0) + { + QuickMagicChance = (rand() % 99) + 1; + if (QuickMagicChance < PChar->getMod(MOD_QUICK_MAGIC)) + { + cast = 0; + return cast; + } + } + return cast * ((100.0f-(float)dsp_cap(PChar->getMod(MOD_FASTCAST),-100,50))/100.0f); + } uint32 CalculateSpellRecastTime(CCharEntity* PChar, CSpell* PSpell) @@ -4199,14 +4425,104 @@ { recast = recast * (1.0f + PChar->getMod(MOD_WHITE_MAGIC_RECAST)/100.0f); } + if ((PSpell->getID() >= 14 && PSpell->getID() <= 20) || PSpell->getID() == 94 || PSpell->getID() == 95 || PSpell->getID() == 143) // Status Ailment Recovery Spells (Divine Benison) + { + int16 DivineBenisonCastMod = PChar->getMod(MOD_DIVINE_BENISON_FASTCAST); + recast = recast * ((float)(100-DivineBenisonCastMod)/100); + if (recast < 2000) + { + recast = 2000; + } + } } - int16 haste = PChar->getMod(MOD_HASTE_MAGIC) + PChar->getMod(MOD_HASTE_GEAR); + else if (PSpell->getSpellGroup() == SPELLGROUP_BLUE) // Blue Magic Recast Modifier + { + int16 BlueRecastMod = PChar->getMod(MOD_BLUE_RECAST); + recast = recast * ((float)(100-BlueRecastMod)/100); + if (recast < 2000) + { + recast = 2000; + } + } + else if (PSpell->getSpellGroup() == SPELLGROUP_SUMMONING) // Summoning Magic Recast Modifier + { + if (PSpell->getID() >= 288 && PSpell->getID() <= 295) // Elemental Avatar Recast Modifier + { + int16 EleAvatarRecastMod = PChar->getMod(MOD_ELE_AVATAR_RECAST); + recast = recast * ((float)(100-EleAvatarRecastMod)/100); + if (recast < 2000) + { + recast = 2000; + } + } + } + else if (PSpell->getSpellGroup() == SPELLGROUP_NINJUTSU) // Ninjutsu Recast Modifier + { + int16 NinjutsuRecastMod = PChar->getMod(MOD_NINJUTSU_RECAST); + recast = recast * ((float)(100-NinjutsuRecastMod)/100); + if (recast < 2000) + { + recast = 2000; + } + } + else if (PSpell->getSpellGroup() == SPELLGROUP_SONG) // Bard Song Recast Modifier + { + int16 SongRecastMod = PChar->getMod(MOD_SONG_RECAST); + recast = recast * ((float)(100-SongRecastMod)/100); + if (PSpell->getID() == 376 || PSpell->getID() == 377 || PSpell->getID() == 463 || PSpell->getID() == 471) + { + recast -= (PChar->PMeritPoints->GetMeritValue(MERIT_LULLABY_RECAST,PChar) *1000); // remove x seconds + } + if (PSpell->getID() == 462) + { + recast -= (PChar->PMeritPoints->GetMeritValue(MERIT_FINALE_RECAST,PChar) *1000); // remove x seconds + } + if (recast < 100) // Pretty much instacast + { + recast = 100; + } + } + + // Grimoire Recast Modifier + if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_LIGHT_ARTS) || PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DARK_ARTS)) + { + if (!PChar->StatusEffectContainer->HasStatusEffect(EFFECT_ALACRITY) || !PChar->StatusEffectContainer->HasStatusEffect(EFFECT_MANIFESTATION)) + { + int16 GrimoireRecastMod = PChar->getMod(MOD_GRIMOIRE_RECAST); + recast = recast * ((float)(100-GrimoireRecastMod)/100); + if (recast < 2000) + { + recast = 2000; + } + } + } + + // Recast Modifiers by Skilltype + if (PSpell->getSkillType() == 36) // Elemental Magic Recast Modifier + { + int16 ElementalRecastMod = PChar->getMod(MOD_ELEMENTAL_RECAST); + recast = recast * ((float)(100-ElementalRecastMod)/100); + if (recast < 2000) + { + recast = 2000; + } + } + + if (PChar->getMod(MOD_QUICK_MAGIC) > 0) + { + if (QuickMagicChance < PChar->getMod(MOD_QUICK_MAGIC)) + { + recast = 0; + return recast; + } + } - if ( haste < 0 || applyHaste == 0 || applyHaste == 2) - { - recast = recast * ((float)(1024-dsp_cap(haste,-1024,256))/1024); - } - return recast * ((100.0f-dsp_cap((float)PChar->getMod(MOD_FASTCAST)/2.0f,0.0f,25.0f))/100.0f); + int16 haste = PChar->getMod(MOD_HASTE_MAGIC) + PChar->getMod(MOD_HASTE_GEAR); + if ( haste < 0 || applyHaste == 0 || applyHaste == 2) + { + recast = recast * ((float)(1024-dsp_cap(haste,-1024,256))/1024); + } + return recast * ((100.0f-dsp_cap((float)PChar->getMod(MOD_FASTCAST)/2.0f,0.0f,25.0f))/100.0f); } void RemoveStratagems(CCharEntity* PChar, CSpell* PSpell) @@ -4239,4 +4555,23 @@ } } +uint32 GetClientIP(CCharEntity* PChar) +{ + const int8* Query = "SELECT client_addr FROM accounts_sessions WHERE charid = %u LIMIT 1;"; + + int32 ret = Sql_Query(SqlHandle,Query,PChar->id); + + if (ret == SQL_ERROR || + Sql_NumRows(SqlHandle) == 0 || + Sql_NextRow(SqlHandle) != SQL_SUCCESS) + { + ShowError(CL_RED"Cannot load client_addr for charid %u. Unable to pull Client IP!" CL_RESET, PChar->id); + return 0; + } + else + { + return Sql_GetIntData(SqlHandle,0); + } +} + } // namespace charutils Index: src/map/charutils.h =================================================================== --- src/map/charutils.h (revision 3520) +++ src/map/charutils.h (working copy) @@ -83,29 +83,29 @@ void UpdateHealth(CCharEntity* PChar); - int32 hasKeyItem(CCharEntity* PChar, uint16 KeyItemID); // проверяем наличие ключевого предмета - int32 seenKeyItem(CCharEntity* PChar, uint16 KeyItemID); // проверяем, было ли описание ключевого предмета прочитано + int32 hasKeyItem(CCharEntity* PChar, uint16 KeyItemID); // check for a key item + int32 seenKeyItem(CCharEntity* PChar, uint16 KeyItemID); // check to see if there was a description of the key subject read int32 unseenKeyItem(CCharEntity* PChar, uint16 KeyItemID); // Attempt to remove keyitem from seen list - int32 addKeyItem(CCharEntity* PChar, uint16 KeyItemID); // добавляем ключевой предмет - int32 delKeyItem(CCharEntity* PChar, uint16 KeyItemID); // улаляем ключевой предмет + int32 addKeyItem(CCharEntity* PChar, uint16 KeyItemID); // add key item + int32 delKeyItem(CCharEntity* PChar, uint16 KeyItemID); // delete key item - int32 hasSpell(CCharEntity* PChar, uint16 SpellID); // проверяем наличие заклинания - int32 addSpell(CCharEntity* PChar, uint16 SpellID); // добавляем заклинание - int32 delSpell(CCharEntity* PChar, uint16 SpellID); // улаляем заклинание + int32 hasSpell(CCharEntity* PChar, uint16 SpellID); // check for spell + int32 addSpell(CCharEntity* PChar, uint16 SpellID); // add spell + int32 delSpell(CCharEntity* PChar, uint16 SpellID); // delete spell - int32 hasLearnedAbility(CCharEntity* PChar, uint16 AbilityID); // проверяем наличие заклинания - int32 addLearnedAbility(CCharEntity* PChar, uint16 AbilityID); // добавляем заклинание - int32 delLearnedAbility(CCharEntity* PChar, uint16 AbilityID); // улаляем заклинание + int32 hasLearnedAbility(CCharEntity* PChar, uint16 AbilityID); // check for an ability + int32 addLearnedAbility(CCharEntity* PChar, uint16 AbilityID); // add ability + int32 delLearnedAbility(CCharEntity* PChar, uint16 AbilityID); // delete ability - int32 hasAbility(CCharEntity* PChar, uint16 AbilityID); // проверяем наличие ключевого предмета - int32 addAbility(CCharEntity* PChar, uint16 AbilityID); // добавляем ключевой предмет - int32 delAbility(CCharEntity* PChar, uint16 AbilityID); // улаляем ключевой предмет + int32 hasAbility(CCharEntity* PChar, uint16 AbilityID); // check for an ability + int32 addAbility(CCharEntity* PChar, uint16 AbilityID); // add ability + int32 delAbility(CCharEntity* PChar, uint16 AbilityID); // delete ability int32 hasTitle(CCharEntity* PChar, uint16 Title); int32 addTitle(CCharEntity* PChar, uint16 Title); int32 delTitle(CCharEntity* PChar, uint16 Title); - int32 hasPetAbility(CCharEntity* PChar, uint16 AbilityID); //same as Ability but for pet commands (e.g. Healing Ruby) + int32 hasPetAbility(CCharEntity* PChar, uint16 AbilityID); // same as Ability but for pet commands (e.g. Healing Ruby) int32 addPetAbility(CCharEntity* PChar, uint16 AbilityID); int32 delPetAbility(CCharEntity* PChar, uint16 AbilityID); @@ -117,28 +117,31 @@ int32 hasWeaponSkill(CCharEntity* PChar, uint16 WeaponSkillID); // declaration of function to check for weapon skill int32 delWeaponSkill(CCharEntity* PChar, uint16 WeaponSkillID); // declaration of function to delete weapon skill - void SaveCharJob(CCharEntity* PChar, JOBTYPE job); // сохраняем уровень для выбранной профессий персонажа - void SaveCharExp(CCharEntity* PChar, JOBTYPE job); // сохраняем опыт для выбранной профессии персонажа - void SaveCharEquip(CCharEntity* PChar); // сохраняем экипировку и внешний вид персонажа - void SaveCharPosition(CCharEntity* PChar); // сохраняем позицию персонажа + void SaveCharJob(CCharEntity* PChar, JOBTYPE job); // Holds the level of the selected character's profession + void SaveCharExp(CCharEntity* PChar, JOBTYPE job); // store experience for their chosen profession character + void SaveCharEquip(CCharEntity* PChar); // store the equipment and the appearance of the character + void SaveCharPosition(CCharEntity* PChar); // save the position of the character void SaveMissionsList(CCharEntity* PChar); // Save the missions list - void SaveQuestsList(CCharEntity* PChar); // сохраняем список ксевтов - void SaveFame(CCharEntity* PChar); // Save area fame / reputation - void SaveZonesVisited(CCharEntity* PChar); // сохраняем посещенные зоны - void SaveKeyItems(CCharEntity* PChar); // сохраняем ключевые предметы + void SaveQuestsList(CCharEntity* PChar); // save the quest list + void SaveFame(CCharEntity* PChar); // Save area fame / reputation + void SaveZonesVisited(CCharEntity* PChar); // save the visited area + void SaveKeyItems(CCharEntity* PChar); // save the key items void SaveCharInventoryCapacity(CCharEntity* PChar); // Save Character inventory capacity - void SaveSpells(CCharEntity* PChar); // сохраняем выученные заклинания + void SaveSpells(CCharEntity* PChar); // store memorized spells void SaveLearnedAbilities(CCharEntity* PChar); // saved learned abilities (corsair rolls) - void SaveTitles(CCharEntity* PChar); // сохраняем заслуженные звания - void SaveCharStats(CCharEntity* PChar); // сохраняем флаги, текущие значения жихней, маны и профессий - void SaveCharNation(CCharEntity* PChar); // Sace the character's nation of allegiance. - void SaveCharSkills(CCharEntity* PChar, uint8 skillID); // сохраняем указанный skill персонажа + void SaveTitles(CCharEntity* PChar); // save the honored title + void SaveCharStats(CCharEntity* PChar); // store the flags, the current values ​​zhihney, mana and professions + void SaveCharNation(CCharEntity* PChar); // Save the character's nation of allegiance. + void SaveCharSkills(CCharEntity* PChar, uint8 skillID); // Saves the character's skill void SaveCharPoints(CCharEntity* PChar); // Conquest point, Nation TP void SaveDeathTime(CCharEntity* PChar); // Saves when this character last died. + void SavePlayTime(CCharEntity* PChar); // Saves this characters total play time. bool hasMogLockerAccess(CCharEntity* PChar); // true if have access, false otherwise. uint32 AddExpBonus(CCharEntity* PChar, uint32 exp); void ResetAllTwoHours(); + + uint32 GetClientIP(CCharEntity* PChar); void RemoveAllEquipment(CCharEntity* PChar); Index: src/map/commandhandler.cpp =================================================================== --- src/map/commandhandler.cpp (revision 3520) +++ src/map/commandhandler.cpp (working copy) @@ -156,7 +156,7 @@ return -1; } - //Загрузка файла команды. + // Load the file command. if( luaL_loadfile(m_LState,std::string(CmdHandler->CmdPath+"/"+CmdHandler->CmdName+".lua").c_str()) || lua_pcall(m_LState,0,0,0) ) { @@ -165,7 +165,7 @@ return -1; } - //Загрузка адреса функции в стек. + // Load the address of the function to the stack. lua_pushstring(m_LState, "onTrigger"); lua_gettable(m_LState,LUA_GLOBALSINDEX); @@ -176,7 +176,7 @@ return -1; } - //Добавление самого первого параметра + // Add the first parameter of the CLuaBaseEntity LuaCmdCaller(PChar); int32 cntparam = 0; if( PChar != NULL ) @@ -185,7 +185,7 @@ cntparam += 1; } - /* цикл просмотра строки передаваемых значений*/ + /* Loop transmission line view of values */ std::string::const_iterator param_iter = CmdHandler->CmdParameters.begin(); std::string param; @@ -221,7 +221,7 @@ ++param_iter; } - //Вызов функции. + // Call the function. int32 status = lua_pcall(m_LState,cntparam,0,0); if( status ) { Index: src/map/commandhandler.h =================================================================== --- src/map/commandhandler.h (revision 3520) +++ src/map/commandhandler.h (working copy) @@ -40,8 +40,8 @@ /************************************************************************ * * -* Структура инициализирующего файла CmdHandler, представлена * -* записями следующего типа. * +* The structure of the initialization file CmdHandler, presented * +* Records the following type. * * * ************************************************************************/ @@ -85,10 +85,10 @@ //m_CmdInIPath += InitCmdInIPath; }; - bool init(const int8* InitCmdInIPath, lua_State* InitLState); // Инициализация списка команд. - bool free(); // Освобождение занятых заранее ресурсов + bool init(const int8* InitCmdInIPath, lua_State* InitLState); // Initialize the list of commands. + bool free(); // pre-release employment resources - int32 call(CCharEntity* PChar, const int8* commandline); // Вызов сценария. + int32 call(CCharEntity* PChar, const int8* commandline); // Call the script. ~CCommandHandler() {} }; Index: src/map/conquest_system.cpp =================================================================== --- src/map/conquest_system.cpp (revision 3520) +++ src/map/conquest_system.cpp (working copy) @@ -31,7 +31,7 @@ /************************************************************************ * * -* Реализация namespace conquest * +* Implementation namespace conquest * * * ************************************************************************/ @@ -345,7 +345,7 @@ /************************************************************************ * * - * Оставшееся количество дней до подсчета conquest * + * Remaining number of days to count conquest * * * ************************************************************************/ @@ -357,7 +357,7 @@ /************************************************************************ * * - * Узнаем страну, владеющую данной зоной * + * Know the country that owns this area * * * ************************************************************************/ @@ -390,16 +390,16 @@ /************************************************************************ * * - * Добавляем персонажу conquest points, основываясь на полученном опыте * + * Add the character conquest points, based on experience * * * ************************************************************************/ - // TODO: необходимо учитывать добавленные очки для еженедельного подсчета conquest + // TODO: need to consider the added points for the weekly count conquest uint32 AddConquestPoints(CCharEntity* PChar, uint32 exp) { - // ВНИМЕНИЕ: не нужно отправлять персонажу CConquestPacket, - // т.к. клиент сам запрашивает этот пакет через фиксированный промежуток времени + // ATTENTION: no need to send a character CConquestPacket, + // As the client requests this package after a fixed period REGIONTYPE region = PChar->loc.zone->GetRegionID(); @@ -408,9 +408,9 @@ // 10% if region control is player's nation // 15% otherwise - PChar->RegionPoints[PChar->profile.nation] += exp * (PChar->profile.nation == GetRegionOwner(region) ? 0.1 : 0.15); + PChar->RegionPoints[PChar->profile.nation] += exp * map_config.conquest_bonus * (PChar->profile.nation == GetRegionOwner(region) ? 0.1 : 0.15); } - return 0; // added conquest points (пока не вижу в этом определенного смысла) + return 0; // added conquest points (do not see in this a sense) } Index: src/map/enmity_container.cpp =================================================================== --- src/map/enmity_container.cpp (revision 3520) +++ src/map/enmity_container.cpp (working copy) @@ -80,7 +80,7 @@ /************************************************************************ * * -* Минимальное (базовое) значение ненависти * +* Minimum (base) value hate * * * ************************************************************************/ @@ -169,7 +169,7 @@ void CEnmityContainer::AddPartyEnmity(CCharEntity* PChar) { - // TODO: добавляемые персонажи уже могут быть в списке enmity, я не уверен, что добавление базового значения здесь актуально + // TODO: add characters may already be in the list of enmity, I'm not sure that adding a base value is true if (PChar->PParty != NULL) { @@ -224,16 +224,49 @@ void CEnmityContainer::UpdateEnmityFromCure(CBattleEntity* PEntity, uint16 level, uint16 CureAmount, bool isCureV) { - if(isCureV){ - UpdateEnmity(PEntity, 400, 700); + uint16 CE = 0; + uint16 VE = 0; + float tranquilHeart = 0; + tranquilHeart = (float)(PEntity->GetSkill(SKILL_HEA) / 10.0f) * 0.5f; // 0.5% per 10 Healing Skill reduction + if(tranquilHeart > .25) + { + tranquilHeart = .25; // Caps at -25% Enmity } + + if(isCureV) + { + CE = 400; + VE = 700; + if(PEntity->getMod(MOD_TRANQUIL_HEART) > 0) + { + // ShowDebug(CL_CYAN"Tranquil Heart Proc\n"); + // ShowDebug(CL_CYAN"Original CE: %u\n", CE); + // ShowDebug(CL_CYAN"Original VE: %u\n", VE); + CE = floor((float)CE * (1.0f - tranquilHeart)); + VE = floor((float)VE * (1.0f - tranquilHeart)); + // ShowDebug(CL_CYAN"Modded CE: %u\n", CE); + // ShowDebug(CL_CYAN"Modded VE: %u\n", VE); + } + UpdateEnmity(PEntity, CE, VE); + } else{ CureAmount = (CureAmount < 1 ? 1 : CureAmount); uint16 mod = battleutils::GetEnmityMod(level, 0); - uint16 CE = 40 / mod * CureAmount; - uint16 VE = 240 / mod * CureAmount; + CE = 40 / mod * CureAmount; + VE = 240 / mod * CureAmount; + + if(PEntity->getMod(MOD_TRANQUIL_HEART) > 0) + { + // ShowDebug(CL_CYAN"Tranquil Heart Proc\n"); + // ShowDebug(CL_CYAN"Original CE: %u\n", CE); + // ShowDebug(CL_CYAN"Original VE: %u\n", VE); + CE = floor((float)CE * (1.0f - tranquilHeart)); + VE = floor((float)VE * (1.0f - tranquilHeart)); + // ShowDebug(CL_CYAN"Modded CE: %u\n", CE); + // ShowDebug(CL_CYAN"Modded VE: %u\n", VE); + } UpdateEnmity(PEntity, CE, VE); } @@ -293,8 +326,9 @@ * * ************************************************************************/ -void CEnmityContainer::UpdateEnmityFromDamage(CBattleEntity* PEntity, uint16 Damage) +void CEnmityContainer::UpdateEnmityFromDamage(CBattleEntity* PEntity, uint16 Damage, bool isCure) { + float tranquilHeart = 0; // Crash fix, PEntity was in ACTION_FALL if (PEntity->PBattleAI->GetCurrentAction() == ACTION_FALL) return; @@ -311,6 +345,25 @@ uint16 CE = (80.0f / mod) * Damage; uint16 VE = (240.0f / mod) * Damage; + if(isCure) + { + if(PEntity->getMod(MOD_TRANQUIL_HEART) > 0) + { + // ShowDebug(CL_CYAN"Tranquil Heart Proc\n"); + // ShowDebug(CL_CYAN"Original CE: %u\n", CE); + // ShowDebug(CL_CYAN"Original VE: %u\n", VE); + tranquilHeart = (float)(PEntity->GetSkill(SKILL_HEA) / 10.0f) * 0.5f; // 0.5% per 10 Healing Skill reduction + if(tranquilHeart > .25) + { + tranquilHeart = .25; + } + CE = floor((float)CE * (1.0f - tranquilHeart)); + VE = floor((float)VE * (1.0f - tranquilHeart)); + // ShowDebug(CL_CYAN"Modded CE: %u\n", CE); + // ShowDebug(CL_CYAN"Modded VE: %u\n", VE); + } + } + UpdateEnmity(PEntity, CE, VE); } Index: src/map/enmity_container.h =================================================================== --- src/map/enmity_container.h (revision 3520) +++ src/map/enmity_container.h (working copy) @@ -52,7 +52,7 @@ void Clear(uint32 EntityID = 0); // Removes Entries from list void AddBaseEnmity(CBattleEntity* PEntity); void UpdateEnmity(CBattleEntity* PEntity, int16 CE, int16 VE); - void UpdateEnmityFromDamage(CBattleEntity* PEntity, uint16 Damage); + void UpdateEnmityFromDamage(CBattleEntity* PEntity, uint16 Damage,bool isCure); void UpdateEnmityFromCure(CBattleEntity* PEntity, uint16 level, uint16 CureAmount, bool isCureV); void UpdateEnmityFromAttack(CBattleEntity* PEntity,uint16 Damage); void AddPartyEnmity(CCharEntity* PChar); Index: src/map/fishingutils.cpp =================================================================== --- src/map/fishingutils.cpp (revision 3520) +++ src/map/fishingutils.cpp (working copy) @@ -49,7 +49,7 @@ /************************************************************************ * * -* Массив смещений для сообщений рыбалки * +* An array of offsets for fishing reports * * * ************************************************************************/ @@ -65,7 +65,7 @@ /************************************************************************ * * -* Получение смещения для сообщений рыбалки * +* Get the offset for the posts of fishing * * * ************************************************************************/ @@ -76,7 +76,7 @@ /************************************************************************ * * -* Проверяем наличие удочки, наживки и возможности ловли * +* Check if the rods, bait and fishing opportunities * * * ************************************************************************/ @@ -106,7 +106,7 @@ !(WeaponItem->getType() & ITEM_WEAPON) || (WeaponItem->getSkillType() != SKILL_FSH)) { - // сообщение: "You can't fish without a rod in your hands" + // The message: "You can't fish without a rod in your hands" PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x01)); PChar->pushPacket(new CReleasePacket(PChar,RELEASE_FISHING)); @@ -119,7 +119,7 @@ !(WeaponItem->getType() & ITEM_WEAPON) || (WeaponItem->getSkillType() != SKILL_FSH)) { - // сообщение: "You can't fish without bait on the hook" + // The message: "You can't fish without bait on the hook" PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x02)); PChar->pushPacket(new CReleasePacket(PChar,RELEASE_FISHING)); @@ -135,7 +135,7 @@ /************************************************************************ * * -* Персонаж ломает удочку * +* Character breaks bait * * * ************************************************************************/ @@ -192,7 +192,7 @@ { while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { - // ловля предметов, необходимых для поисков + // Fishing items needed for searches uint8 logid = (uint8)Sql_GetIntData(SqlHandle,5); uint8 quest = (uint8)Sql_GetIntData(SqlHandle,6); @@ -211,7 +211,7 @@ break; } } - // TODO: ловля простых предметов + // TODO: Fishing simple objects } } } @@ -262,7 +262,7 @@ /************************************************************************ * * -* Персонаж теряет наживку (теряет блесну лишь при условии RemoveFly) * +* A character loses bait (minnow loses only if RemoveFly) * * * ************************************************************************/ @@ -291,7 +291,7 @@ /************************************************************************ * * -* Персонаж ломает удочку * +* Character breaks bait * * * ************************************************************************/ @@ -345,7 +345,7 @@ { if (CheckFisherLuck(PChar)) { - // сообщение: "Something caught the hook!" + // The message: "Something caught the hook!" PChar->animation = ANIMATION_FISHING_FISH; PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x08)); @@ -353,7 +353,7 @@ } else { - // сообщение: "You didn't catch anything." + // The message: "You didn't catch anything." PChar->animation = ANIMATION_FISHING_STOP; PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x04)); @@ -364,7 +364,7 @@ { if (stamina == 0) { - // сообщение: "You caught fish!" + // The message: "You caught fish!" DSP_DEBUG_BREAK_IF(PChar->UContainer->GetType() != UCONTAINER_FISHING); DSP_DEBUG_BREAK_IF(PChar->UContainer->GetItem(0) == NULL); @@ -373,7 +373,7 @@ CItem* PFish = PChar->UContainer->GetItem(0); - // TODO: анализируем RodFlag + // TODO: analyze RodFlag charutils::AddItem(PChar, LOC_INVENTORY, PFish->getID(), 1); PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, new CCaughtFishPacket(PChar, PFish->getID(), MessageOffset + 0x27)); @@ -386,7 +386,7 @@ } else if (stamina <= 0x64) { - // сообщение: "Your line breaks!" + // The message: "Your line breaks!" PChar->animation = ANIMATION_FISHING_LINE_BREAK; LureLoss(PChar, true); @@ -394,7 +394,7 @@ } else if (stamina <= 0x100) { - // сообщение: "You give up!" + // The message: "You give up!" PChar->animation = ANIMATION_FISHING_STOP; @@ -408,7 +408,7 @@ } else { - // сообщение: "You lost your catch!" + // The message: "You lost your catch!" PChar->animation = ANIMATION_FISHING_STOP; LureLoss(PChar, false); @@ -419,7 +419,7 @@ break; case FISHACTION_WARNING: { - // сообщение: "You don't know how much longer you can keep this one on the line..." + // The message: "You don't know how much longer you can keep this one on the line..." PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x28)); return; Index: src/map/fishingutils.h =================================================================== --- src/map/fishingutils.h (revision 3520) +++ src/map/fishingutils.h (working copy) @@ -36,7 +36,7 @@ /************************************************************************ * * -* Все методы, необходимые для реализации рыбалки * +* All of the techniques required to implement fishing * * * ************************************************************************/ Index: src/map/grades.cpp =================================================================== --- src/map/grades.cpp (revision 3520) +++ src/map/grades.cpp (working copy) @@ -25,13 +25,13 @@ /************************************************************************ * * -* Таблицы расчета характеристик сушностей * +* Tables for calculating the characteristics sushnostey * * * ************************************************************************/ /************************************************************************ * * -* Массив с уровнями характеристик по профессиям * +* An array of performance levels by occupation * * * ************************************************************************/ @@ -151,7 +151,7 @@ uint8 GetJobGrade(JOBTYPE job, uint8 stat) { - //DSP_DEBUG_BREAK_IF(job >= MAX_JOBTYPE || stat > 8); // выход за пределы массива + //DSP_DEBUG_BREAK_IF(job >= MAX_JOBTYPE || stat > 8); // Out of bounds return JobGrades[job][stat]; } @@ -164,7 +164,7 @@ uint8 GetRaceGrades(uint8 race, uint8 stat) { - //DSP_DEBUG_BREAK_IF(race > 4 || stat > 8); // выход за пределы массива + //DSP_DEBUG_BREAK_IF(race > 4 || stat > 8); // Out of bounds return RaceGrades[race][stat]; } @@ -177,7 +177,7 @@ float GetHPScale(uint8 rank, uint8 scale) { - //DSP_DEBUG_BREAK_IF(rank > 7 || scale > 4); // выход за пределы массива + //DSP_DEBUG_BREAK_IF(rank > 7 || scale > 4); // Out of bounds return HPScale[rank][scale]; } @@ -190,7 +190,7 @@ float GetMPScale(uint8 rank, uint8 scale) { - //DSP_DEBUG_BREAK_IF(rank > 7 || scale > 3); // выход за пределы массива + //DSP_DEBUG_BREAK_IF(rank > 7 || scale > 3); // Out of bounds return MPScale[rank][scale]; } @@ -203,7 +203,7 @@ float GetStatScale(uint8 rank, uint8 scale) { - //DSP_DEBUG_BREAK_IF(rank > 7 || scale > 3); // выход за пределы массива + //DSP_DEBUG_BREAK_IF(rank > 7 || scale > 3); // Out of bounds return StatScale[rank][scale]; } Index: src/map/guildutils.cpp =================================================================== --- src/map/guildutils.cpp (revision 3520) +++ src/map/guildutils.cpp (working copy) @@ -29,13 +29,13 @@ #include "item_container.h" #include "map.h" -// TODO: во время закрытия гильдии всем просматривающим список товаров отправляется пакет 0x86 с информацией о закрытии гильдии +// TODO: when you close the guild all watched items list goes 0x86 package with information about the closing of the guild -//#define количество обновляемых предметов при restock (в процентах от максимального количества) +//#Define the number of items updated by restock (as a percentage of the maximum amount) /************************************************************************ * * -* Список гильдий * +* A list of guilds * * * ************************************************************************/ @@ -52,7 +52,7 @@ /************************************************************************ * * -* Инициализация гильдий * +* Initialize the guild * * * ************************************************************************/ @@ -110,7 +110,7 @@ /************************************************************************ * * -* Обновляем запас гильдий * +* Update reserve guilds * * * ************************************************************************/ @@ -123,7 +123,7 @@ { CItemShop* PItem = (CItemShop*)PGuild->GetItem(slotid); - // TODO: сначала, анализируя текущее количество предметов, обновляем их стоимость + // TODO: first, by analyzing the current number of items, update the cost if (PItem->IsDailyIncrease()) { @@ -140,12 +140,12 @@ PItem->setBasePrice(PItem->getMinPrice()); } } - ShowDebug(CL_CYAN"UpdateGuildsStock is finished\n" CL_RESET); + // ShowDebug(CL_CYAN"UpdateGuildsStock is finished\n" CL_RESET); } /************************************************************************ * * -* Получаем указатель на магазин гильдии с указанным ID * +* Get a pointer to store the guild with the specified ID * * * ************************************************************************/ Index: src/map/item_container.cpp =================================================================== --- src/map/item_container.cpp (revision 3520) +++ src/map/item_container.cpp (working copy) @@ -69,7 +69,7 @@ /************************************************************************ * * -* Установка размера контейнера * +* Set the size of the container * * * ************************************************************************/ @@ -81,16 +81,16 @@ uint8 CItemContainer::AddBuff(int8 buff) { m_buff += buff; - return SetSize(dsp_min(m_buff, 80)); // ограничение в 80 ячеек для персонажа + return SetSize(dsp_min(m_buff, 80)); // limit of 80 cells for a character } /************************************************************************ * * -* Установка размера контейнера * +* Set the size of the container * * * ************************************************************************/ -// контейнер не несет ответственности за то, что предметы могут остаться за пределами размера +// Container is not responsible for the fact that things may go beyond the size of uint8 CItemContainer::SetSize(uint8 size) { @@ -108,11 +108,11 @@ /************************************************************************ * * -* Увеличиваем/уменьшаем размер контейнера * +* Increase / decrease the size of the container * * * ************************************************************************/ -// контейнер не несет ответственности за то, что предметы могут остаться за пределами размера +// Container is not responsible for the fact that things may go beyond the size of uint8 CItemContainer::AddSize(int8 size) { @@ -161,7 +161,7 @@ /************************************************************************ * * -* Добавляем предмет в указанную ячейку. NULL удаляет предмет * +* Add the item to the specified cell. NULL removes the item * * * ************************************************************************/ Index: src/map/item_container.h =================================================================== --- src/map/item_container.h (revision 3520) +++ src/map/item_container.h (working copy) @@ -57,22 +57,22 @@ ~CItemContainer(); uint16 GetID(); - uint16 GetBuff(); // планируемый размер хранилища (размер без ограничений) + uint16 GetBuff(); // the planned amount of storage (unlimited size) uint8 GetSize(); - uint8 GetFreeSlotsCount(); // количество свободных ячеек в хранилище - uint8 AddBuff(int8 buff); // планируемый размер хранилища (размер без ограничений) - uint8 AddSize(int8 size); // увеличиваем/уменьшаем размер контейнера + uint8 GetFreeSlotsCount(); // amount of free space in storage + uint8 AddBuff(int8 buff); // the planned amount of storage (unlimited size) + uint8 AddSize(int8 size); // increase / decrease the size of the container uint8 SetSize(uint8 size); - uint8 SearchItem(uint16 ItemID); // поиск предмета в хранилище + uint8 SearchItem(uint16 ItemID); // Find the items in the store uint8 SearchItemWithSpace(uint16 ItemID, uint32 quantity); //search for item that has space to accomodate x items added - uint8 InsertItem(CItem* PItem); // добавляем заранее созданный предмет в свободную ячейку - uint8 InsertItem(CItem* PItem, uint8 slotID); // добавляем заранее созданный предмет в выбранную ячейку + uint8 InsertItem(CItem* PItem); // add a previously created object in free cell + uint8 InsertItem(CItem* PItem, uint8 slotID); // add a previously created object to the selected cell - uint32 SortingPacket; // количество запросов на сортировку за такт - uint32 LastSortingTime; // время последней сортировки контейнера + uint32 SortingPacket; // number of requests for sorting per cycle + uint32 LastSortingTime; // the last sorting container - CItem* GetItem(uint8 slotID); // получаем указатель на предмет, находящийся в указанной ячейка. + CItem* GetItem(uint8 slotID); // get a pointer to the object at the specified cell. private: Index: src/map/items/item.cpp =================================================================== --- src/map/items/item.cpp (revision 3520) +++ src/map/items/item.cpp (working copy) @@ -69,7 +69,7 @@ /************************************************************************ * * -* Уникальный номер предмета * +* Unique Item Number * * * ************************************************************************/ @@ -101,7 +101,7 @@ /************************************************************************ * * -* Параметр, определяющий характеристики предмета * +* The parameter that determines the characteristics of the subject * * * ************************************************************************/ @@ -117,8 +117,8 @@ /************************************************************************ * * +* Auction House Catagory * * * -* * ************************************************************************/ void CItem::setAHCat(uint8 ahCat) @@ -165,7 +165,7 @@ /************************************************************************ * * -* Зарезервированное количество предметов в пачке * +* The reserved amount of items in a pack * * * ************************************************************************/ @@ -181,7 +181,7 @@ /************************************************************************ * * -* Текущее количество предметов в пачке * +* Current number of items in a pack * * * ************************************************************************/ @@ -197,7 +197,7 @@ /************************************************************************ * * -* Максимальное количество предметов в пачке * +* Maximum number of items in a pack * * * ************************************************************************/ @@ -213,8 +213,8 @@ /************************************************************************ * * +* Item Base Price * * * -* * ************************************************************************/ void CItem::setBasePrice(uint32 BasePrice) @@ -245,7 +245,7 @@ /************************************************************************ * * -* Название предмета * +* Item name * * * ************************************************************************/ @@ -296,8 +296,8 @@ /************************************************************************ * * +* Item Signature * * * -* * ************************************************************************/ const int8* CItem::getSignature() @@ -313,8 +313,8 @@ /************************************************************************ * * +* Item Storage Location * * * -* * ************************************************************************/ uint8 CItem::getLocationID() @@ -329,8 +329,8 @@ /************************************************************************ * * +* Item Slot Location * * * -* * ************************************************************************/ uint8 CItem::getSlotID() Index: src/map/items/item.h =================================================================== --- src/map/items/item.h (revision 3520) +++ src/map/items/item.h (working copy) @@ -27,7 +27,7 @@ #include "../../common/cbasetypes.h" #include "../../common/mmo.h" -// основной тип предмета m_type +// basic type of object m_type enum ITEM_TYPE { @@ -42,7 +42,7 @@ ITEM_LINKSHELL = 0x80 }; -// дополнительный тип предмета m_subtype +// additional type of object m_subtype enum ITEM_SUBTYPE { @@ -53,7 +53,7 @@ ITEM_UNLOCKED = 0xFE }; -// флаги предметов +// items flags enum ITEM_FLAG { @@ -136,17 +136,17 @@ uint16 m_subid; uint8 m_type; uint8 m_subtype; - uint32 m_quantity; // текущее количество предметов - uint32 m_reserve; // зарезервированное количество предметов - uint32 m_stackSize; // максимальное количество предметов + uint32 m_quantity; // the current number of items + uint32 m_reserve; // the number of reserved items + uint32 m_stackSize; // the maximum number of items uint32 m_BasePrice; - uint32 m_CharPrice; // стоимость предмета в bazaar - uint8 m_ahCat; // категоряи предмета на укционе + uint32 m_CharPrice; // value of the object in bazaar + uint8 m_ahCat; // Subject category at auction uint16 m_flag; uint8 m_wornItem; // worn item (BCNM item, maat testimony) - uint8 m_slotID; // ячейка предмета в хранилище - uint8 m_locationID; // номер хранилища предмета + uint8 m_slotID; // Box object in the repository + uint8 m_locationID; // object storage room uint16 m_augments[4]; // augment types uint8 m_augmentvalues[4]; //augment values Index: src/map/itemutils.cpp =================================================================== --- src/map/itemutils.cpp (revision 3520) +++ src/map/itemutils.cpp (working copy) @@ -36,7 +36,7 @@ /************************************************************************ * * -* Собственно методы работы с глобальной коллекцией предметов * +* Own work from a global collection of objects * * * ************************************************************************/ @@ -45,7 +45,7 @@ /************************************************************************ * * - * Создаем пустой экземпляр предмета по ID (private метод) * + * Creates an empty instance of the object by ID (private method) * * * ************************************************************************/ @@ -94,7 +94,7 @@ /************************************************************************ * * - * Создаем новый экземпляр предмета по ID * + * Create a new instance of the object by ID * * * ************************************************************************/ @@ -148,7 +148,7 @@ /************************************************************************ * * - * Создаем копию предмета * + * Make a copy of the subject * * * ************************************************************************/ @@ -193,7 +193,7 @@ /************************************************************************ * * - * Получаем указатель на предмет из коллекции (только для чтения) * + * Get a pointer to the object from the collection (read-only) * * * ************************************************************************/ @@ -225,7 +225,7 @@ /************************************************************************ * * - * Список выпадаемых из монстров предметов * + * The list of objects to fall out of the monsters * * * ************************************************************************/ @@ -257,7 +257,7 @@ /************************************************************************ * * - * Загружаем базу предметов * + * Load the base objects * * * ************************************************************************/ @@ -425,7 +425,7 @@ /************************************************************************ * * - * Загружаем списки предметов, выпадающих из монстров * + * Load the list of items that pop out of monsters * * * ************************************************************************/ @@ -491,7 +491,7 @@ /************************************************************************ * * - * Инициализация системы игровых предметов * + * System Initialization game items * * * ************************************************************************/ @@ -514,7 +514,7 @@ /************************************************************************ * * - * Освобождаем базу предметов (метод только для "галочки") * + * Free the database objects (method only for "show") * * * ************************************************************************/ Index: src/map/itemutils.h =================================================================== --- src/map/itemutils.h (revision 3520) +++ src/map/itemutils.h (working copy) @@ -81,7 +81,7 @@ /************************************************************************ * * -* Пространстов имен дла работы с глобальными списками предметов * +* Space names to Fight with a global list of items * * * ************************************************************************/ Index: src/map/latent_effect.h =================================================================== --- src/map/latent_effect.h (revision 3520) +++ src/map/latent_effect.h (working copy) @@ -35,8 +35,10 @@ LATENT_HP_OVER_TP_UNDER_100 = 3, //hp more than %, tp over 100 - PARAM: HP PERCENT LATENT_HP_OVER_VISIBLE_GEAR = 46, //hp more than or equal to %, calculated using HP bonuses from visible gear only LATENT_MP_UNDER_PERCENT = 4, //mp less than or equal to % - PARAM: MP PERCENT + LATENT_MP_OVER_PERCENT = 12, //mp more than % - PARAM: MP PERCENT LATENT_MP_UNDER = 5, //mp less than # - PARAM: MP # LATENT_MP_UNDER_VISIBLE_GEAR = 45, //mp less than or equal to %, calculated using MP bonuses from visible gear only + LATENT_MP_OVER = 15, //mp greater than # - PARAM: MP # LATENT_TP_UNDER_100 = 6, //tp under 100 and during WS - PARAM: NONE LATENT_TP_OVER_100 = 7, //tp over 100 - PARAM: NONE LATENT_SUBJOB = 8, //subjob - PARAM: JOBTYPE @@ -59,6 +61,7 @@ LATENT_ICEDAY = 34, LATENT_LIGHTNINGSDAY = 35, LATENT_LIGHTSDAY = 36, + LATENT_DARKSDAY = 15, LATENT_MOON_FIRST_QUARTER = 37, LATENT_JOB_MULTIPLE_5 = 38, LATENT_JOB_MULTIPLE_10 = 39, @@ -74,10 +77,10 @@ /************************************************************************ * * -* Нерешенные задачи: * +* Pending problem: * * * -* - сохранение ID сущности, добавившей эффект * -* - обновление эффекта (например перезапись protect 1 на protect 2) * +* - Save ID essence, add effects * +* - Update effect (eg overwrite protect 1 to protect 2) * * * ************************************************************************/ Index: src/map/latent_effect_container.cpp =================================================================== --- src/map/latent_effect_container.cpp (revision 3520) +++ src/map/latent_effect_container.cpp (working copy) @@ -254,6 +254,16 @@ { switch(m_LatentEffectList.at(i)->GetConditionsID()) { + case LATENT_MP_OVER_PERCENT: + if (((float)mp / m_POwner->health.maxmp ) >= m_LatentEffectList.at(i)->GetConditionsValue()) + { + m_LatentEffectList.at(i)->Activate(); + } + else + { + m_LatentEffectList.at(i)->Deactivate(); + } + break; case LATENT_MP_UNDER_PERCENT: if ((float)(mp / m_POwner->health.maxmp ) <= m_LatentEffectList.at(i)->GetConditionsValue()) { @@ -274,6 +284,16 @@ m_LatentEffectList.at(i)->Deactivate(); } break; + case LATENT_MP_OVER: + if (mp >= m_LatentEffectList.at(i)->GetConditionsValue()) + { + m_LatentEffectList.at(i)->Activate(); + } + else + { + m_LatentEffectList.at(i)->Deactivate(); + } + break; //case LATENT_MP_UNDER_VISIBLE_GEAR: // { // //TODO: figure out if this is actually right Index: src/map/linkshell.cpp =================================================================== --- src/map/linkshell.cpp (revision 3520) +++ src/map/linkshell.cpp (working copy) @@ -42,7 +42,7 @@ /************************************************************************ * * -* Реализация класса CLinkshell * +* Implementation class CLinkshell * * * ************************************************************************/ @@ -111,7 +111,7 @@ /************************************************************************ * * -* Добавляем персонажа в список активных участников Linkshells * +* Add the character to the list of active participants Linkshells * * * ************************************************************************/ @@ -124,7 +124,7 @@ /************************************************************************ * * -* Удаляем персонажа из списка активных участников Linkshells * +* Delete a character from a list of active participants Linkshells * * * ************************************************************************/ @@ -202,7 +202,7 @@ /************************************************************************ * * -* Удаление персонажа из Linkshell по имени (ломаем все его Linkshells) * +* Removing a character from Linkshell by name (break his Linkshells) * * * ************************************************************************/ @@ -262,7 +262,7 @@ /************************************************************************ * * -* Отправляем пакет всем членам Linkshells, за исключением PChar * +* Send the package to all members Linkshells, except PChar * * * ************************************************************************/ @@ -282,7 +282,7 @@ /************************************************************************ * * -* Реализация namespase для работы с Linkshells * +* Implementing namespase to work with Linkshells * * * ************************************************************************/ @@ -294,7 +294,7 @@ /************************************************************************ * * - * Загружаем список зарегистрированных Linkshells * + * Load the list of registered Linkshells * * * ************************************************************************/ @@ -323,7 +323,7 @@ /************************************************************************ * * - * Добавляем персонажа в список Linkshell * + * Add character to your Linkshell * * * ************************************************************************/ @@ -344,7 +344,7 @@ /************************************************************************ * * - * Удаляем персонажа из списка Lilkshell * + * Remove the character from the list Lilkshell * * * ************************************************************************/ @@ -366,7 +366,7 @@ /************************************************************************ * * - * Проверяем строку на возможность использования в качестве имени LS * + * Check string could be used as the name of LS * * * ************************************************************************/ @@ -381,7 +381,7 @@ /************************************************************************ * * - * Регистрируем новую linkshell * + * Register a new linkshell * * * ************************************************************************/ Index: src/map/linkshell.h =================================================================== --- src/map/linkshell.h (revision 3520) +++ src/map/linkshell.h (working copy) @@ -67,7 +67,7 @@ void PushPacket(CCharEntity* PChar, CBasicPacket* packet); - std::vector members; // список участников linkshell + std::vector members; // list of participants linkshell private: @@ -82,7 +82,7 @@ /************************************************************************ * * -* namespase для работы с Linkshells * +* Namespase to work with Linkshells * * * ************************************************************************/ Index: src/map/lua/lua_baseentity.cpp =================================================================== --- src/map/lua/lua_baseentity.cpp (revision 3520) +++ src/map/lua/lua_baseentity.cpp (working copy) @@ -45,6 +45,7 @@ #include "../packets/char_stats.h" #include "../packets/char_sync.h" #include "../packets/char_update.h" +#include "../packets/chat_message.h" #include "../packets/send_box.h" #include "../packets/entity_update.h" #include "../packets/event.h" @@ -453,6 +454,20 @@ //======================================================// +inline int32 CLuaBaseEntity::updateHealth(lua_State *L) +{ + DSP_DEBUG_BREAK_IF(m_PBaseEntity == NULL); + DSP_DEBUG_BREAK_IF(m_PBaseEntity->objtype == TYPE_NPC); + + if(m_PBaseEntity->objtype == TYPE_PC && m_PBaseEntity->status != STATUS_DISAPPEAR) + { + charutils::UpdateHealth((CCharEntity*)m_PBaseEntity); + } + return 0; +} + + +//======================================================// inline int32 CLuaBaseEntity::getMaxHP(lua_State *L) { DSP_DEBUG_BREAK_IF(m_PBaseEntity == NULL); @@ -516,7 +531,7 @@ /************************************************************************ * * -* Мгновенное перемещение сущности * +* Essentially instantaneous movement * * * ************************************************************************/ @@ -803,9 +818,11 @@ } /************************************************************************ +* * * player:hasWornItem(item) * * return true if player has this worn item * * For BCNM Item and Testimony (Maat battle) * +* * ************************************************************************/ inline int32 CLuaBaseEntity::hasWornItem(lua_State *L) @@ -841,7 +858,7 @@ /************************************************************************ * * -* Получаем имя зоны, в которой находится персонаж * +* Get the name of the area in which the character is * * * ************************************************************************/ @@ -876,7 +893,7 @@ /************************************************************************ * * -* Узнаем континент, на котором находится сущность * +* Know the continent on which the entity * * * ************************************************************************/ @@ -890,7 +907,7 @@ /************************************************************************ * * -* Проверяем, посещалась ли указанная зона персонажем ранее * +* Check whether a specific area visited earlier character * * * ************************************************************************/ @@ -1059,9 +1076,9 @@ CCharEntity * PChar = (CCharEntity*)m_PBaseEntity; uint16 rank = 1; - rank = PChar->profile.rank[PChar->profile.nation]; - lua_pushinteger( L, rank); - return 1; + rank = PChar->profile.rank[PChar->profile.nation]; + lua_pushinteger( L, rank); + return 1; } } lua_pushnil(L); @@ -1229,7 +1246,7 @@ /************************************************************************ * * -* Проверяем, завершил ли персонаж задачу (quest) * +* Check whether the person has completed the task (quest) * * * ************************************************************************/ @@ -1258,7 +1275,7 @@ /************************************************************************ * * -* Добавляем выбранную миссию * +* Adds the selected mission * * * ************************************************************************/ @@ -1296,7 +1313,7 @@ /************************************************************************ * * -* Удаляем выбранную миссию * +* Removes the selected mission * * * ************************************************************************/ @@ -1339,7 +1356,7 @@ /************************************************************************ * * -* Проверяем, завершил ли персонаж выбранную миссию * +* Check whether the person has completed the selected mission * * * ************************************************************************/ @@ -1370,7 +1387,7 @@ /************************************************************************ * * -* Узнаем текущую миссию * +* View the current mission * * * ************************************************************************/ @@ -1398,7 +1415,7 @@ /************************************************************************ * * -* Завершаем выбранную миссию * +* Finish the selected mission * * * ************************************************************************/ @@ -1506,7 +1523,7 @@ /************************************************************************ * * -* Проверяем, было ли описание ключевого предмета прочитано * +* Test whether a key item description was read * * * ************************************************************************/ @@ -1553,7 +1570,7 @@ /************************************************************************ * * -* получить текущий уровень мастерства * +* Get the current level of skill * * * ************************************************************************/ @@ -1569,8 +1586,8 @@ /************************************************************************ * * -* * * * +* * ************************************************************************/ inline int32 CLuaBaseEntity::getMaxSkillLevel(lua_State *L) @@ -1622,7 +1639,7 @@ /************************************************************************ * * -* Добавляем персонажу заклинание с отображением сообщения * +* Add character to a spell with a displayed message * * * ************************************************************************/ @@ -1682,7 +1699,7 @@ /************************************************************************ * * -* Проверяем у персонажа наличие заклинания в списке заклинаний * +* Check the availability of a character spells in the spellbook * * * ************************************************************************/ @@ -1905,7 +1922,7 @@ /************************************************************************ * * -* Делаем доступной персонажу указанную профессию. 0 - subjob * +* Make available characters specified profession. 0 - subjob * * * ************************************************************************/ @@ -1935,7 +1952,7 @@ /************************************************************************ * * -* Изменяем ограничение максимального уровня персонажа (genkai) * +* Change the limit on the maximum level of character (genkai) * * * ************************************************************************/ @@ -1964,11 +1981,11 @@ /************************************************************************ * * -* Устанавливаем/узнаем временное ограничение уровня. Параметр функции * -* является новый ограничением уровня, 0 - отмена ограничения уровня. * -* Функция всегда возвращается значение текущего/нового ограниченя. * +* Set / learn time limit level. function parameter * +* is a new restriction level, 0 - cancellation level constraints. * +* The function always returns the current / new constraint. * * * -* Нужно будет вынести код установки уровня в отдельную функцию * +* It will be necessary to make the install code level in a function * * * ************************************************************************/ @@ -2095,7 +2112,7 @@ /************************************************************************ * * -* Запускаем событие с указанными параметрами * +* Start the event with the specified parameters * * * ************************************************************************/ @@ -2236,7 +2253,7 @@ /************************************************************************ * * -* Получаем указатель на персонажа, начавшего событие * +* Get a pointer to the character that started the event * * * ************************************************************************/ @@ -2278,7 +2295,7 @@ /************************************************************************ * * -* Отображаем статичный текст от лица NPC * +* Display static text on behalf of the NPC * * * ************************************************************************/ @@ -2371,7 +2388,7 @@ /************************************************************************ * * -* Отправляем персонажу меню магазина гильдии * +* Send the character to store menu Guild * * * ************************************************************************/ @@ -2418,7 +2435,7 @@ /************************************************************************ * * -* Получаем временные переменные, необходимые для логики поисков * +* Obtain temporary variables needed to search logic * * * ************************************************************************/ @@ -2449,7 +2466,7 @@ /************************************************************************ * * -* Сохраняем временные переменные, необходимые для логики поисков * +* Save the temporary variables needed to search logic * * * ************************************************************************/ @@ -2480,7 +2497,7 @@ /************************************************************************ * * -* Увеличиваем/уменьшаем значение временной переменной * +* Increase / decrease the value of the time variable * * * ************************************************************************/ @@ -2786,7 +2803,7 @@ /************************************************************************ * * -* Добавляем персонажу новое звание * +* Add character to a new rank * * * ************************************************************************/ @@ -2811,7 +2828,7 @@ /************************************************************************ * * -* Удаляем у персонажа звание (DEBUG ONLY) * +* Delete the character title (DEBUG ONLY) * * * ************************************************************************/ @@ -3016,7 +3033,7 @@ /************************************************************************ * * -* Отправляем базовое сообщение персонажу * +* Send a basic message character * * * ************************************************************************/ @@ -3256,7 +3273,7 @@ /************************************************************************ * * -* Узнаем текущее значение известности персонажа * +* Find out the current value of the known character * * * ************************************************************************/ @@ -3295,7 +3312,7 @@ /************************************************************************ * * -* Узнаем текущий уровень известности персонажа * +* Know the current level of well-known characters * * * ************************************************************************/ @@ -3332,7 +3349,7 @@ /************************************************************************ * * -* Устанавливаем известность персонажу * +* Known character set * * * ************************************************************************/ @@ -3373,7 +3390,7 @@ /************************************************************************ * * -* Добавляем известность персонажу * +* Add the well-known character * * * ************************************************************************/ @@ -3452,7 +3469,7 @@ /************************************************************************ * * -* Получаем/устанавливаем скорость передвижения сущности * +* Set / get the essence of speed * * * ************************************************************************/ @@ -3483,7 +3500,7 @@ /************************************************************************ * * -* Получаем/устанавливаем значение дополнительной анимации * +* Set / get the value of additional animation * * * ************************************************************************/ @@ -3514,7 +3531,7 @@ /************************************************************************ * * -* Получаем/устанавливаем костюм персонажу * +* Set / get character costumes * * * ************************************************************************/ @@ -3545,7 +3562,7 @@ /************************************************************************ * * -* Проверяем, может ли персонаж использовать костюм * +* Check whether a character costume to use * * * ************************************************************************/ @@ -3565,7 +3582,7 @@ /************************************************************************ * * -* Проверяем, может ли персонаж использовать chocobo * +* Check whether a character use chocobo * * * ************************************************************************/ @@ -3602,7 +3619,7 @@ /************************************************************************ * * -* Разрещение атаковать этого персонажа другим персонажам * +* Permission to attack the character to other characters * * * ************************************************************************/ @@ -3615,6 +3632,7 @@ return 0; } + //==========================================================// inline int32 CLuaBaseEntity::sendTractor(lua_State *L) @@ -3652,7 +3670,7 @@ /************************************************************************ * * -* Отправляем персонажу Raise меню * +* Send the character menu Raise * * * ************************************************************************/ inline int32 CLuaBaseEntity::sendReraise(lua_State *L) @@ -3688,7 +3706,7 @@ uint8 RaiseLevel = (uint8)lua_tonumber(L,1); - if (RaiseLevel == 0 || RaiseLevel > 3) + if (RaiseLevel == 0 || RaiseLevel > 4) { ShowDebug(CL_CYAN"lua::sendRaise raise value is not valide!\n" CL_RESET); } @@ -3702,7 +3720,7 @@ /************************************************************************ * * -* Добавляем боевой сущности StatusEffect * +* Add the essence of combat StatusEffect * * * ************************************************************************/ @@ -3735,7 +3753,7 @@ /************************************************************************ * * -* Добавляем боевой сущности StatusEffect * +* Add the essence of combat StatusEffect * * * ************************************************************************/ @@ -3899,7 +3917,7 @@ /************************************************************************ * * -* Получаем указатель на эффект по имени * +* Get a pointer to the effect named * * * ************************************************************************/ @@ -3940,7 +3958,7 @@ /************************************************************************ * * -* Проверяем наличие статус-эффекта в контейнере * +* Check the presence of the status effect in the container * * * ************************************************************************/ @@ -4001,8 +4019,8 @@ /************************************************************************ * * -* Удаляем статус-эффект по его основному и дополнительному типам. * -* Возвращаем результат выполнения операции. * +* Remove the status effect on its main and additional types. * +* Return the result of the operation. * * * ************************************************************************/ @@ -4171,7 +4189,7 @@ /************************************************************************ * * -* Удаляем первый отрицательный эффект * +* Remove the first negative effect * * * ************************************************************************/ @@ -4263,7 +4281,7 @@ /************************************************************************ * * -* Удаляем первый положительный эффект * +* Remove the first positive effect * * * ************************************************************************/ @@ -4339,7 +4357,7 @@ /************************************************************************ * * -* Добавляем очки опыта персонажу * +* Add experience points the character * * * ************************************************************************/ @@ -4588,7 +4606,7 @@ /************************************************************************ * * -* Устанавливаем персонажу указанный флаг * +* Character set specified flag * * * ************************************************************************/ @@ -4606,7 +4624,7 @@ /************************************************************************ * * -* Устанавливаем/запрашиваем флаг выхода из MogHouse * +* Set / Query the flag out of the MogHouse * * * ************************************************************************/ @@ -4742,7 +4760,7 @@ /************************************************************************ * * -* блокируем ячейку экипировки * +* block cell equipment * * * ************************************************************************/ @@ -4772,7 +4790,7 @@ /************************************************************************ * * -* Cнимаем блокировку с ячейки экипировки * +* Unlocks the cell equipment * * * ************************************************************************/ @@ -4880,7 +4898,7 @@ /************************************************************************ * * -* Сущность призывает питомца * +* Essence encourages pet * * * ************************************************************************/ @@ -4893,6 +4911,24 @@ if( !lua_isnil(L,1) && lua_isstring(L,1) ) { petutils::SpawnPet((CBattleEntity*)m_PBaseEntity, lua_tointeger(L,1), false); + CCharEntity* PChar = (CCharEntity*)m_PBaseEntity; + if(lua_tointeger(L,1) >= 0 && lua_tointeger(L,1) <= 7) + { + if((PChar->GetMJob() == JOB_SMN && PChar->GetMLevel() >= 50) || + (PChar->GetSJob() == JOB_SMN && PChar->GetSLevel() == 50)) + { + charutils::addAbility(PChar, 216); // Elemental Siphon + PChar->pushPacket(new CCharAbilitiesPacket(PChar)); + } + } + else if(lua_tointeger(L,1) >= 8 && lua_tointeger(L,1) <= 16) + { + if(PChar->GetMJob() == JOB_SMN && PChar->GetMLevel() >= 55) + { + charutils::addAbility(PChar, 234); // Avatars Favor + PChar->pushPacket(new CCharAbilitiesPacket(PChar)); + } + } } else { @@ -4970,7 +5006,7 @@ /************************************************************************ * * -* Сущность освобождает питомца * +* The essence of free pet * * * ************************************************************************/ @@ -4982,6 +5018,24 @@ { if(((CBattleEntity*)m_PBaseEntity)->PPet!=NULL){ petutils::DespawnPet((CBattleEntity*)m_PBaseEntity); + CCharEntity* PChar = (CCharEntity*)m_PBaseEntity; + if(lua_tointeger(L,1) >= 0 && lua_tointeger(L,1) <= 7) + { + if((PChar->GetMJob() == JOB_SMN && PChar->GetMLevel() >= 50) || + (PChar->GetSJob() == JOB_SMN && PChar->GetSLevel() == 50)) + { + charutils::delAbility(PChar, 216); // Elemental Siphon + PChar->pushPacket(new CCharAbilitiesPacket(PChar)); + } + } + else if(lua_tointeger(L,1) >= 8 && lua_tointeger(L,1) <= 16) + { + if(PChar->GetMJob() == JOB_SMN && PChar->GetMLevel() >= 55) + { + charutils::delAbility(PChar, 234); // Avatars Favor + PChar->pushPacket(new CCharAbilitiesPacket(PChar)); + } + } } } } @@ -4990,7 +5044,7 @@ /************************************************************************ * * -* Обновляем ненависть монстров к указанной цели * +* Updating hate monsters to that purpose * * * ************************************************************************/ @@ -5102,6 +5156,12 @@ return 1; } +/************************************************************************ +* * +* Return mob ecosystem * +* * +************************************************************************/ + inline int32 CLuaBaseEntity::getSystem(lua_State* L) { DSP_DEBUG_BREAK_IF(m_PBaseEntity == NULL); @@ -5234,11 +5294,17 @@ CLuaBaseEntity* PEntity = Lunar::check(L,1); uint32 damage = lua_tointeger(L,2); + bool isCure = false; + if(!lua_isnil(L,3) && lua_isboolean(L,3)) + { + isCure = true; + } + if (PEntity != NULL && PEntity->GetBaseEntity()->objtype != TYPE_NPC) { - ((CMobEntity*)m_PBaseEntity)->PEnmityContainer->UpdateEnmityFromDamage((CBattleEntity*)PEntity->GetBaseEntity(),damage); + ((CMobEntity*)m_PBaseEntity)->PEnmityContainer->UpdateEnmityFromDamage((CBattleEntity*)PEntity->GetBaseEntity(),damage, isCure); } return 0; @@ -5246,9 +5312,9 @@ /************************************************************************ * * -* Проверяем, покидал ли персонаж зону после поднятия флага * -* необходимости ее покинуть. С параметром устанавливаем флаг, без * -* параметра узнаем результат. * +* Check if the character left the area after the flag-raising * +* The need to leave. With a parameter set the flag without * +* Parameter to know the results. * * * ************************************************************************/ @@ -5674,6 +5740,28 @@ } /*************************************************************** + Resets the caller's ability recast time for the specified RecastID + INPUT: + The RecastID of the ability to make available +****************************************************************/ +inline int32 CLuaBaseEntity::resetAbilityRecast(lua_State *L) +{ + DSP_DEBUG_BREAK_IF(m_PBaseEntity == NULL); + DSP_DEBUG_BREAK_IF(lua_isnil(L,-1) || !lua_isnumber(L,-1)); + + // Only reset for players + if(m_PBaseEntity->objtype == TYPE_PC){ + CCharEntity* PChar = (CCharEntity*)m_PBaseEntity; + + PChar->PRecastContainer->Del(RECAST_ABILITY, lua_tointeger(L,-1)); + + PChar->pushPacket(new CCharSkillsPacket(PChar)); + } + return 0; +} + + +/*************************************************************** Attempts to register a BCNM or Dynamis instance. INPUT: The BCNM ID to register. OUTPUT: The instance number assigned, or -1 if it's all full. @@ -5945,7 +6033,7 @@ /************************************************************************ * * -* Открываем дверь и автоматически закрываем через 7 секунд * +* Open the door and close automatically after 7 seconds * * * ************************************************************************/ @@ -6881,6 +6969,83 @@ return 1; } +inline int32 CLuaBaseEntity::GotoMob(lua_State* L) +{ + CCharEntity* PChar = (CCharEntity*)m_PBaseEntity; + if(m_PBaseEntity == NULL) + { + + ShowNotice(CL_RED"TRACER:COMMAND: spawnmob Error\n" CL_RESET); + return false; + } + if(m_PBaseEntity->objtype != TYPE_PC) + { + + ShowNotice(CL_RED"TRACER:COMMAND: spawnmob Error1\n" CL_RESET); + return false; + } + if(lua_isnil(L,-1) || !lua_isnumber(L,-1)) + { + PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "Command Error1")); + PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "Command Example: .spawnmob 1")); + ShowNotice(CL_RED"TRACER:COMMAND: spawnmob Error2\n" CL_RESET); + return false; + } + uint32 mobid = (uint32)lua_tointeger(L,1); + uint32 groupid =0; + float pos_x =0; + float pos_y =0; + float pos_z =0; + uint32 pos_rot =0; + uint32 zoneid = 0; + CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB); + if (PMob != NULL) + { + //BE FUN TO ADD A APPEAR TO MOB AT LOCATION ALSO + const int8* Query = "SELECT groupid,pos_x,pos_y,pos_z,pos_rot FROM mob_spawn_points WHERE mobid = '%u';"; + int32 ret = Sql_Query(SqlHandle,Query,mobid); + if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS) + { + PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN); + ShowNotice(CL_RED"TRACER:COMMAND: Player %s Is Appearing To Mob ID %u\n" CL_RESET ,PChar->GetName(),mobid); + groupid = Sql_GetUIntData(SqlHandle,0); + ShowNotice(CL_RED"TRACER:COMMAND: GET GROUP ID %u\n" CL_RESET ,groupid); + pos_x = Sql_GetFloatData(SqlHandle,1); + ShowNotice(CL_RED"TRACER:COMMAND: GET POS_X ID %f\n" CL_RESET ,pos_x); + pos_y = Sql_GetFloatData(SqlHandle,2); + ShowNotice(CL_RED"TRACER:COMMAND: GET POS_Y ID %f\n" CL_RESET ,pos_y); + pos_z = Sql_GetFloatData(SqlHandle,3); + ShowNotice(CL_RED"TRACER:COMMAND: GET POS_Z ID %f\n" CL_RESET ,pos_z); + pos_rot = Sql_GetUIntData(SqlHandle,4); + ShowNotice(CL_RED"TRACER:COMMAND: GET POS_ROT ID %u\n" CL_RESET ,pos_rot); + PChar->status = STATUS_DISAPPEAR; + PChar->loc.p.x=pos_x; + PChar->loc.p.y=pos_y; + PChar->loc.p.z=pos_z; + PChar->loc.p.rotation=pos_rot; + PChar->loc.boundary = 0; + const int8* Query = "SELECT zoneid FROM mob_groups WHERE groupid = '%u';"; + int32 ret = Sql_Query(SqlHandle,Query,groupid); + if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS) + { + zoneid = Sql_GetUIntData(SqlHandle,0); + ShowNotice(CL_RED"TRACER:COMMAND: GET ZONE ID %u\n" CL_RESET ,zoneid); + PChar->loc.destination=zoneid ; + PChar->clearPacketList(); + PChar->pushPacket(new CServerIPPacket(PChar,2)); + PChar->pushPacket(new CCharUpdatePacket(PChar)); + PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE, new CEntityUpdatePacket(PChar, ENTITY_SPAWN)); + return false; + } + lua_pushnil(L); + return false; + } + lua_pushnil(L); + return false; + } + lua_pushnil(L); + return false; +} inline int32 CLuaBaseEntity::getBaseHP(lua_State* L) { DSP_DEBUG_BREAK_IF(m_PBaseEntity == NULL); @@ -6903,6 +7068,54 @@ return 1; } +inline int32 CLuaBaseEntity::Kill_Target(lua_State *L) +{ + CCharEntity* PChar = (CCharEntity*)m_PBaseEntity; + if(m_PBaseEntity == NULL) + { + //PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "setPos Error")); + ShowNotice(CL_RED"TRACER:COMMAND: killtarget Error\n" CL_RESET); + return false; + } + + if(m_PBaseEntity->objtype != TYPE_PC) + { + //PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "getRace Error1")); + ShowNotice(CL_RED"TRACER:COMMAND: killtarget Error1\n" CL_RESET); + return false; + } + + if(PChar->loc.zone->GetEntity(PChar->m_TargID, TYPE_PC)) + { + CCharEntity* PCharTarget = (CCharEntity*)PChar->loc.zone->GetEntity(PChar->m_TargID, TYPE_PC); + PCharTarget->PBattleAI->SetCurrentAction(ACTION_FALL); + PCharTarget->nameflags.flags = 0; + PCharTarget->health.hp=0; + charutils::UpdateHealth(PCharTarget); + PCharTarget->animation = ANIMATION_DEATH; + PCharTarget->isDead(); + PCharTarget->pushPacket(new CCharUpdatePacket(PCharTarget)); + return false; + } + if(PChar->loc.zone->GetEntity(PChar->m_TargID, TYPE_MOB)) + { + CMobEntity * PMob = (CMobEntity*)PChar->loc.zone->GetEntity(PChar->m_TargID, TYPE_MOB); + PMob->health.hp=0; + PMob->PBattleAI->SetCurrentAction(ACTION_FALL); + PMob->animation = ANIMATION_DEATH; + PMob->isDead(); + PMob->loc.zone->PushPacket(PMob, CHAR_INRANGE, new CEntityUpdatePacket(PMob,ENTITY_UPDATE)); + PChar->pushPacket(new CCharUpdatePacket(PChar)); + return false; + } + + PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "kill Error1")); + PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "Command Example .kill")); + PChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, "Note: Mob Or Player Target Must Be Selected")); + ShowNotice(CL_RED"TRACER:COMMAND: killtarget\n" CL_RESET); + return false; +} + //==========================================================// const int8 CLuaBaseEntity::className[] = "CBaseEntity"; @@ -6928,6 +7141,7 @@ LUNAR_DECLARE_METHOD(CLuaBaseEntity,addTP), LUNAR_DECLARE_METHOD(CLuaBaseEntity,delTP), LUNAR_DECLARE_METHOD(CLuaBaseEntity,setTP), + LUNAR_DECLARE_METHOD(CLuaBaseEntity,updateHealth), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getStat), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getMaxHP), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getMaxMP), @@ -7121,6 +7335,7 @@ LUNAR_DECLARE_METHOD(CLuaBaseEntity,addAllSpells), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getMeleeHitDamage), LUNAR_DECLARE_METHOD(CLuaBaseEntity,resetRecasts), + LUNAR_DECLARE_METHOD(CLuaBaseEntity,resetAbilityRecast), LUNAR_DECLARE_METHOD(CLuaBaseEntity,bcnmRegister), LUNAR_DECLARE_METHOD(CLuaBaseEntity,bcnmEnter), LUNAR_DECLARE_METHOD(CLuaBaseEntity,bcnmLeave), @@ -7153,7 +7368,7 @@ LUNAR_DECLARE_METHOD(CLuaBaseEntity,hasImmunity), LUNAR_DECLARE_METHOD(CLuaBaseEntity,rageMode), LUNAR_DECLARE_METHOD(CLuaBaseEntity,isUndead), - LUNAR_DECLARE_METHOD(CLuaBaseEntity,isMobType), + LUNAR_DECLARE_METHOD(CLuaBaseEntity,isMobType), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getBattleTime), LUNAR_DECLARE_METHOD(CLuaBaseEntity,changeSkin), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getSkinID), @@ -7190,5 +7405,7 @@ LUNAR_DECLARE_METHOD(CLuaBaseEntity,isSpellAoE), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getBaseHP), LUNAR_DECLARE_METHOD(CLuaBaseEntity,getBaseMP), + LUNAR_DECLARE_METHOD(CLuaBaseEntity,GotoMob), + LUNAR_DECLARE_METHOD(CLuaBaseEntity,Kill_Target), {NULL,NULL} }; \ No newline at end of file Index: src/map/lua/lua_baseentity.h =================================================================== --- src/map/lua/lua_baseentity.h (revision 3520) +++ src/map/lua/lua_baseentity.h (working copy) @@ -46,22 +46,30 @@ static uint16 ValidSpells[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45, - 46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,86,87,88,89, - 90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123, - 124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155, - 156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, - 188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219, - 220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,245,246,247,248,249,250,251,252,253, - 254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285, - 287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,312,318,320,321,322,323,324,325,326,327,328,329,330,331, - 332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363, - 364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395, - 396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427, - 428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459, - 460,461,462,463,464,465,466,467,468,469,477,478,504,513,515,517,519,521,522,524,527,529,530,531,532,533,534,535,536,537,538,539, - 540,541,542,543,544,545,547,548,549,551,554,555,557,560,561,563,564,565,567,569,570,572,573,574,575,576,577,578,579,581,582,584, - 585,587,588,589,591,592,593,594,595,596,597,598,599,603,604,605,606,608,610,611,612,613,614,615,616,617,618,620,621,622,623,626, - 628,629,631,632,633,634,636,637,638,640,641,642,643,644,645,646,647,648,650,651,652,653 + 46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87, + 88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122, + 123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154, + 155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186, + 187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, + 219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250, + 251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282, + 283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,311,312,313,314,315, + 316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347, + 348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379, + 380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411, + 412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443, + 444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475, + 477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,507,508,509,510, + 513,515,517,519,521,522,524,527,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,547,548,549,551,554,555,557, + 560,561,563,564,565,567,569,570,572,573,574,575,576,577,578,579,581,582,584,585,587,588,589,591,592,593,594,595,596,597,598,599, + 603,604,605,606,608,610,611,612,613,614,615,616,617,618,620,621,622,623,626,628,629,631,632,633,634,636,637,638,640,641,642,643, + 644,645,646,647,648,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676, + 677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708, + 709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740, + 741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,772,773, + 774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,802,803,804,805,806, + 807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838, + 839,840 }; @@ -111,9 +119,10 @@ int32 addTP(lua_State*); // Modify tp of Entity +/- int32 delTP(lua_State*); // Subtract tp of Entity int32 setTP(lua_State*); // Set tp of Entity to value - int32 getRangedDmg(lua_State*); // Get ranged weapon DMG rating - int32 getRangedDmgForRank(lua_State*); // Get ranged weapond DMG rating used for calculating rank - int32 getAmmoDmg(lua_State*); // Get ammo DMG rating + int32 updateHealth(lua_State*); // Used to ensure the player stats are updated in real time + int32 getRangedDmg(lua_State*); // Get ranged weapon DMG rating + int32 getRangedDmgForRank(lua_State*); // Get ranged weapond DMG rating used for calculating rank + int32 getAmmoDmg(lua_State*); // Get ammo DMG rating int32 getRATT(lua_State*); // Get total r.attack int32 getRACC(lua_State*); // Get total r.acc int32 getACC(lua_State*); // Get total ACC @@ -189,10 +198,10 @@ int32 canLearnSpell(lua_State*); // Check to see if character can learn spell, 0 if so int32 delSpell(lua_State*); // Remove spell from Entity spell list - int32 addLearnedAbility(lua_State*); // Add spell to Entity spell list - int32 hasLearnedAbility(lua_State*); // Check to see if character has item in spell list + int32 addLearnedAbility(lua_State*); // Add spell to Entity spell list + int32 hasLearnedAbility(lua_State*); // Check to see if character has item in spell list int32 canLearnAbility(lua_State*); // Check to see if character can learn spell, 0 if so - int32 delLearnedAbility(lua_State*); // Remove spell from Entity spell list + int32 delLearnedAbility(lua_State*); // Remove spell from Entity spell list int32 addWeaponSkill(lua_State*); // int32 delWeaponSkill(lua_State*); // @@ -294,7 +303,7 @@ int32 isMobType(lua_State*); // True if mob is of type passed to function int32 changeSkin(lua_State*); // Change mob skin int32 getSkinID(lua_State*); // Get Skin ID (0 for base skin) - int32 getSystem(lua_State*); + int32 getSystem(lua_State*); // Returns the value of the mobs Ecosystem int32 getFamily(lua_State*); int32 addStatusEffect(lua_State*); // Adds status effect to character @@ -358,7 +367,7 @@ int32 setsLevel(lua_State*); // sets the character's level int32 changeJob(lua_State*); // changes the job of a char (testing only!) int32 setMerits(lua_State*); // set merits (testing only!) - int32 getMerit(lua_State*); + int32 getMerit(lua_State*); // get merits int32 changesJob(lua_State*); // changes the sub job of a char (testing only!) int32 getWeaponDmg(lua_State*); // gets the current equipped weapons' DMG rating int32 getOffhandDmg(lua_State*); // gets the current equipped offhand's DMG rating (used in WS calcs) @@ -376,6 +385,7 @@ int32 openDoor(lua_State*); // открываем дверь int32 hideNPC(lua_State*); // hide an NPC int32 resetRecasts(lua_State*); // Reset recasts for the caller + int32 resetAbilityRecast(lua_State*); // Resets the caller's ability recast time for the specified RecastID int32 addCP(lua_State*); // Add CP int32 getCP(lua_State*); // Get CP @@ -426,6 +436,9 @@ int32 recalculateAbilitiesTable(lua_State*); int32 isSpellAoE(lua_State* L); + int32 GotoMob(lua_State*); + int32 Kill_Target(lua_State*); + }; #endif Index: src/map/lua/lua_spell.cpp =================================================================== --- src/map/lua/lua_spell.cpp (revision 3520) +++ src/map/lua/lua_spell.cpp (working copy) @@ -29,7 +29,7 @@ /************************************************************************ * * -* Конструктор * +* Designer * * * ************************************************************************/ @@ -46,7 +46,7 @@ /************************************************************************ * * -* Конструктор * +* Designer * * * ************************************************************************/ @@ -57,7 +57,7 @@ /************************************************************************ * * -* Устанавливаем сообщение заклинания * +* Set the message spells * * * ************************************************************************/ @@ -126,9 +126,37 @@ return 1; } +inline int32 CLuaSpell::getSkillType(lua_State *L) +{ + DSP_DEBUG_BREAK_IF(m_PLuaSpell == NULL); + lua_pushinteger(L,m_PLuaSpell->getSkillType()); + return 1; +} + +inline int32 CLuaSpell::getMPCost(lua_State *L) +{ + DSP_DEBUG_BREAK_IF(m_PLuaSpell == NULL); + lua_pushinteger(L,m_PLuaSpell->getMPCost()); + return 1; +} + +inline int32 CLuaSpell::getCE(lua_State *L) +{ + DSP_DEBUG_BREAK_IF(m_PLuaSpell == NULL); + lua_pushinteger(L,m_PLuaSpell->getCE()); + return 1; +} + +inline int32 CLuaSpell::getVE(lua_State *L) +{ + DSP_DEBUG_BREAK_IF(m_PLuaSpell == NULL); + lua_pushinteger(L,m_PLuaSpell->getVE()); + return 1; +} + /************************************************************************ * * -* Инициализация методов в lua * +* Initialization methods in lua * * * ************************************************************************/ @@ -139,9 +167,13 @@ LUNAR_DECLARE_METHOD(CLuaSpell,isAoE), LUNAR_DECLARE_METHOD(CLuaSpell,getDefaultMessage), LUNAR_DECLARE_METHOD(CLuaSpell,getMagicBurstMessage), - LUNAR_DECLARE_METHOD(CLuaSpell,getElement), + LUNAR_DECLARE_METHOD(CLuaSpell,getElement), LUNAR_DECLARE_METHOD(CLuaSpell,getTotalTargets), LUNAR_DECLARE_METHOD(CLuaSpell, getID), LUNAR_DECLARE_METHOD(CLuaSpell, getSpellGroup), + LUNAR_DECLARE_METHOD(CLuaSpell, getSkillType), + LUNAR_DECLARE_METHOD(CLuaSpell, getMPCost), + LUNAR_DECLARE_METHOD(CLuaSpell, getCE), + LUNAR_DECLARE_METHOD(CLuaSpell, getVE), {NULL,NULL} }; \ No newline at end of file Index: src/map/lua/lua_spell.h =================================================================== --- src/map/lua/lua_spell.h (revision 3520) +++ src/map/lua/lua_spell.h (working copy) @@ -55,6 +55,10 @@ int32 getElement(lua_State*); int32 getID(lua_State*); int32 getSpellGroup(lua_State*); + int32 getSkillType(lua_State*); + int32 getMPCost(lua_State*); + int32 getCE(lua_State*); + int32 getVE(lua_State*); }; #endif \ No newline at end of file Index: src/map/lua/luautils.cpp =================================================================== --- src/map/lua/luautils.cpp (revision 3520) +++ src/map/lua/luautils.cpp (working copy) @@ -56,9 +56,10 @@ #include "../packets/char_sync.h" #include "../packets/char_update.h" #include "../packets/char.h" +#include "../packets/chat_message.h" #include "../packets/menu_raisetractor.h" #include "../packets/message_basic.h" -#include "../packets/uncnown_39.h" +#include "../packets/unknown_39.h" namespace luautils { @@ -66,7 +67,7 @@ /************************************************************************ * * -* Инициализация lua, пользовательских классов и глобальных функций * +* Initialization lua, custom classes and global functions * * * ************************************************************************/ @@ -85,6 +86,7 @@ lua_register(LuaHandle,"setMobPos",luautils::setMobPos); lua_register(LuaHandle,"SpawnMob",luautils::SpawnMob); lua_register(LuaHandle,"DespawnMob",luautils::DespawnMob); + lua_register(LuaHandle,"SpawnNPC",luautils::SpawnNPC); lua_register(LuaHandle,"GetPlayerByName",luautils::GetPlayerByName); lua_register(LuaHandle,"GetMobAction",luautils::GetMobAction); lua_register(LuaHandle,"VanadielTOTD",luautils::VanadielTOTD); @@ -98,11 +100,12 @@ lua_register(LuaHandle,"VanadielMoonPhase",luautils::VanadielMoonPhase); lua_register(LuaHandle,"VanadielMoonDirection", luautils::VanadielMoonDirection); lua_register(LuaHandle,"SetVanadielTimeOffset",luautils::SetVanadielTimeOffset); + lua_register(LuaHandle,"IsMoonNew",luautils::IsMoonNew); lua_register(LuaHandle,"IsMoonFull",luautils::IsMoonFull); lua_register(LuaHandle,"RunElevator",luautils::StartElevator); lua_register(LuaHandle,"GetServerVariable",luautils::GetServerVariable); lua_register(LuaHandle,"SetServerVariable",luautils::SetServerVariable); - lua_register(LuaHandle,"SendUncnown0x39Packet",luautils::SendUncnown0x39Packet); + lua_register(LuaHandle,"SendUnknown0x39Packet",luautils::SendUnknown0x39Packet); lua_register(LuaHandle,"GetMobRespawnTime",luautils::GetMobRespawnTime); lua_register(LuaHandle,"DeterMob",luautils::DeterMob); @@ -110,6 +113,7 @@ lua_register(LuaHandle,"getCorsairRollEffect",luautils::getCorsairRollEffect); lua_register(LuaHandle,"getSpell",luautils::getSpell); + lua_register(LuaHandle,"SendMobMessage",luautils::SendMobMessage); Lunar::Register(LuaHandle); Lunar::Register(LuaHandle); @@ -127,7 +131,7 @@ /************************************************************************ * * -* Освобождение lua * +* Release lua * * * ************************************************************************/ @@ -141,7 +145,7 @@ /************************************************************************ * * -* Переопределение официальной lua функции print * +* Overriding the official lua function print * * * ************************************************************************/ @@ -160,7 +164,7 @@ * * ************************************************************************/ -int32 SendUncnown0x39Packet(lua_State* L) +int32 SendUnknown0x39Packet(lua_State* L) { if((!lua_isnil(L,1) && lua_isnumber(L,1)) && (!lua_isnil(L,2) && lua_isnumber(L,2)) ) @@ -172,7 +176,7 @@ if (PNpc != NULL) { - PNpc->loc.zone->PushPacket(PNpc, CHAR_INRANGE, new CUncnown0x39Packet(PNpc, param)); + PNpc->loc.zone->PushPacket(PNpc, CHAR_INRANGE, new CUnknown0x39Packet(PNpc, param)); } return 0; } @@ -277,7 +281,7 @@ /************************************************************************ * * -* Узнаем страну, владеющую текущим регионом * +* Know the country that owns the current region * * * ************************************************************************/ @@ -331,7 +335,7 @@ /************************************************************************ * * -* Получаем текущее время суток Vana'diel * +* Get the current time of day Vana'diel * * * ************************************************************************/ @@ -432,8 +436,44 @@ return 1; } + /************************************************************************ * * +* Is new moon? * +* * +************************************************************************/ + +int32 IsMoonNew(lua_State* L) +{ + // New moon occurs when: + // Waning (decreasing) from 10% to 0%, + // Waxing (increasing) from 0% to 5%. + + uint8 phase = CVanaTime::getInstance()->getMoonPhase(); + + switch (CVanaTime::getInstance()->getMoonDirection()) + { + case 0: // None + lua_pushboolean(L, false); + return 0; + + case 1: // Waning (decending) + if (phase <= 10 && phase >= 0) { + lua_pushboolean(L, true); + return 1; + } + + case 2: // Waxing (increasing) + if (phase >= 0 && phase <= 5) { + lua_pushboolean(L, true); + return 1; + } + } + lua_pushboolean(L, false); + return 0; +} +/************************************************************************ +* * * Return Moon Phase * * * ************************************************************************/ @@ -585,6 +625,7 @@ if(!lua_isnil(L,2) && lua_isnumber(L,2)) { PMob->SetDespawnTimer((uint32)lua_tointeger(L,2)); + PMob->m_ForceDespawn = false; } else { @@ -601,6 +642,40 @@ /************************************************************************ * * +* Spawn a NPC using mob ID. * +* * +************************************************************************/ + +int32 SpawnNPC(lua_State* L) +{ + if( !lua_isnil(L,1) && lua_isnumber(L,1) ) + { + uint32 npcid = (uint32)lua_tointeger(L,1); + + zoneutils::LoadNPC(npcid); + + CNpcEntity* PNpc = (CNpcEntity*)zoneutils::GetEntity(npcid, TYPE_NPC); + if (PNpc != NULL) + { + lua_pushstring(L,CLuaBaseEntity::className); + lua_gettable(L,LUA_GLOBALSINDEX); + lua_pushstring(L,"new"); + lua_gettable(L,-2); + lua_insert(L,-2); + lua_pushlightuserdata(L,(void*)PNpc); + lua_pcall(L,2,1,0); + return 1; + } else { + ShowDebug(CL_RED"SpawnNPC: npc <%u> not found\n" CL_RESET, npcid); + } + return 0; + } + lua_pushnil(L); + return 1; +} + +/************************************************************************ +* * * set a mobs position * * * ************************************************************************/ @@ -633,8 +708,8 @@ { ShowDebug(CL_CYAN"setMobPos: <%s> is currently in battle, will not warp it!\n" CL_RESET, PMob->GetName()); return 1; - } } + } lua_pushnil(L); return 0; } @@ -698,9 +773,34 @@ return 1; } +int32 SendMobMessage(lua_State* L) +{ + uint32 mobid = (uint32)lua_tointeger(L,1); + uint32 CharID = (uint32)lua_tointeger(L,2); + CBaseEntity* PNPC = (CBaseEntity*)zoneutils::GetEntity(mobid, TYPE_MOB | TYPE_NPC); + if (PNPC != NULL) + { + const int8* Query = "SELECT targid, pos_zone FROM chars INNER JOIN accounts_sessions USING(charid) WHERE charid = %u LIMIT 1"; + int32 ret = Sql_Query(SqlHandle, Query, CharID); + if (ret != SQL_ERROR && + Sql_NumRows(SqlHandle) != 0 && + Sql_NextRow(SqlHandle) == SQL_SUCCESS) + { + uint16 TargID = (uint16)Sql_GetUIntData(SqlHandle,0); + uint8 ZoneID = (uint8) Sql_GetUIntData(SqlHandle,1); + CCharEntity* PTellRecipient = (CCharEntity*)zoneutils::GetZone(ZoneID)->GetEntity(TargID, TYPE_PC); + int8* data = (int8*)lua_tolstring(L,3,NULL); + int8* name = (int8*)PNPC->GetSayName(); + uint8 size = (uint8)PNPC->name.size(); + PTellRecipient->pushPacket(new CNPCMessagePacket(name,ZoneID,data,size)); + } + } + return 1; +} + /************************************************************************ * * -* Загружаем значение переменной TextID указанной зоны * +* Load the value of the specified zone TextID * * * ************************************************************************/ @@ -734,7 +834,8 @@ /************************************************************************ * * -* Выполняем скрипт при старте сервера (все монстры, npc уже загружены) * +* Execute the script when the server starts (all monsters, npc already * +* been downloaded) * * * ************************************************************************/ @@ -773,13 +874,12 @@ /************************************************************************ * * -* Запускаем скрипт инициализации зоны. * -* Выполняется во время старта сервера при загрузке зон. * -* При разделенных lua стеках необходимо создавать их здесь * +* Run the script file for the zone. Performed at startup time when * +* loading zones. When separated lua stacks create them here. * * * ************************************************************************/ -int32 OnZoneInitialise(uint16 ZoneID) +int32 OnZoneInitialize(uint16 ZoneID) { CZone* PZone = zoneutils::GetZone(ZoneID); @@ -793,7 +893,7 @@ if( luaL_loadfile(LuaHandle,File) || lua_pcall(LuaHandle,0,0,0) ) { - //ShowError("luautils::OnZoneInitialise: %s\n",lua_tostring(LuaHandle,-1)); + //ShowError("luautils::OnZoneInitialize: %s\n",lua_tostring(LuaHandle,-1)); lua_pop(LuaHandle, 1); return -1; } @@ -801,7 +901,7 @@ lua_getfield(LuaHandle, LUA_GLOBALSINDEX, "onInitialize"); if( lua_isnil(LuaHandle,-1) ) { - ShowError("luautils::OnZoneInitialise: undefined procedure onInitialize\n"); + ShowError("luautils::OnZoneInitialize: undefined procedure onInitialize\n"); return -1; } @@ -820,7 +920,7 @@ /************************************************************************ * * -* Выполняем скрипт при входе персонажа в зону * +* Execute the script by entering the character in the game * * * ************************************************************************/ @@ -865,7 +965,7 @@ /************************************************************************ * * -* Выполняем скрипт при входе персонажа в зону * +* Execute the script by entering the character in the zone * * * ************************************************************************/ @@ -912,7 +1012,7 @@ /************************************************************************ * * -* Персонаж входит в активный регион * +* Character enters the active region * * * ************************************************************************/ @@ -959,7 +1059,7 @@ /************************************************************************ * * -* Персонаж покидает активный регион * +* Character leaves the active region * * * ************************************************************************/ @@ -1006,8 +1106,7 @@ /************************************************************************ * * -* Персонаж обращается к какому-либо npc. Пытаемся отреагировать на * -* его действие * +* The character refers to any npc. We try to respond to its action. * * * * ************************************************************************/ @@ -1057,7 +1156,7 @@ /************************************************************************ * * -* Запущенное событие нуждается в дополнительных параметрах * +* Running event in need of additional options * * * ************************************************************************/ @@ -1095,17 +1194,24 @@ lua_pushinteger(LuaHandle,result); if( lua_pcall(LuaHandle,3,LUA_MULTRET,0) ) - { - ShowError("luautils::OnEventUpdate: %s\n", lua_tostring(LuaHandle, -1)); + { + int8 File[255]; + memset(File,0,sizeof(File)); + snprintf(File, sizeof(File), "scripts/zones/%s/Zone.lua", PChar->loc.zone->GetName()); + + if( luaL_loadfile(LuaHandle,File) || lua_pcall(LuaHandle,0,0,0) ) + { + ShowError("luautils::OnEventUpdate %s\n", lua_tostring(LuaHandle, -1)); lua_pop(LuaHandle, 1); - return -1; + return -1; + } } return (!lua_isnil(LuaHandle,-1) && lua_isnumber(LuaHandle,-1) ? (int32)lua_tonumber(LuaHandle,-1) : 0); } /************************************************************************ * * -* Событие завершилось, результат события хранится в result * +* The event ended with the result of the event is stored in the result * * * ************************************************************************/ @@ -1121,12 +1227,19 @@ snprintf(File, sizeof(File), "scripts/zones/%s/Zone.lua", PChar->loc.zone->GetName()); if( luaL_loadfile(LuaHandle,File) || lua_pcall(LuaHandle,0,0,0) ) - { - ShowError("luautils::OnEventFinish %s\n", lua_tostring(LuaHandle, -1)); - lua_pop(LuaHandle, 1); - return -1; + { + int8 File[255]; + memset(File,0,sizeof(File)); + snprintf(File, sizeof(File), "scripts/zones/%s/Zone.lua", PChar->loc.zone->GetName()); + + if( luaL_loadfile(LuaHandle,File) || lua_pcall(LuaHandle,0,0,0) ) + { + ShowError("luautils::OnEventFinish %s\n", lua_tostring(LuaHandle, -1)); + lua_pop(LuaHandle, 1); + return -1; } } + } lua_getfield(LuaHandle, LUA_GLOBALSINDEX, "onEventFinish"); if( lua_isnil(LuaHandle,-1) ) @@ -1154,13 +1267,21 @@ PChar->pushPacket(new CRaiseTractorMenuPacket(PChar,TYPE_HOMEPOINT)); PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE, new CCharPacket(PChar,ENTITY_UPDATE)); } + + + if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_CHOCOBO)) + { + PChar->animation = ANIMATION_CHOCOBO; + PChar->pushPacket(new CCharUpdatePacket(PChar)); + } + return (!lua_isnil(LuaHandle,-1) && lua_isnumber(LuaHandle,-1) ? (int32)lua_tonumber(LuaHandle,-1) : 0); } /************************************************************************ * * -* Персонаж пытается передать предмет npc * +* The character is trying to convey the subject npc * * * ************************************************************************/ @@ -1212,8 +1333,7 @@ /************************************************************************ * * -* Начало работы статус-эффекта. Возвращаемое значение 0 или номер * -* сообщения * +* Starting the status effect. The return value is 0 or number posts * * * * ************************************************************************/ @@ -1258,7 +1378,7 @@ /************************************************************************ * * -* Повторяемое действие в процессе работы статус-оффекта * +* Repeated action in the course of work status effect * * * ************************************************************************/ @@ -1303,8 +1423,7 @@ /************************************************************************ * * -* Завершение работы статус-эффекта. Возвращаемое значение -1 или * -* номер сообщения * +* Completing the status effect. The return value is -1 or Message # * * * * ************************************************************************/ @@ -1349,8 +1468,8 @@ /************************************************************************ * * -* Проверяем возможность использования предмета. Если все хорошо, то * -* возвращаемое значение - 0, в случае отказа - номер сообщения ошибки * +* Check the possibility of using the object. If all is well, then * +* Return value - 0, in case of failure - the number of error messages * * * ************************************************************************/ @@ -1395,9 +1514,9 @@ /************************************************************************ * * -* Используем предмет. Возврадаемое значение - номер сообщения или 0. * -* Так же необходимо как-то передавать параметр сообщения (например, * -* количество восстановленных MP) * +* Use the subject. Vozvradaemoe value - the number of messages, or 0. * +* You need to somehow convey the message parameter (such as number of * +* recovered MP) * * * ************************************************************************/ @@ -1486,7 +1605,7 @@ /************************************************************************ * * -* Чтение заклинаний * +* Spellcasting * * * ************************************************************************/ @@ -1496,7 +1615,7 @@ EFFECT effectId = (EFFECT)battleutils::SingSong(PCaster,PTarget,PCaster->PBattleAI->GetCurrentSpell()); if(effectId != EFFECT_NONE){ return effectId; - } + } } int8 File[255]; memset(File,0,sizeof(File)); @@ -1583,6 +1702,7 @@ } /************************************************************************ +* * * OnMobInitialise * * Used for passive trait * * * @@ -1629,6 +1749,7 @@ * * * Сalled when a monster engages a target for the first time * * Added by request (for doing stuff when mobs first engage) * +* * ************************************************************************/ int32 OnMobEngaged(CBaseEntity* PMob, CBaseEntity* PTarget) @@ -1815,7 +1936,7 @@ /************************************************************************ * * -* Скрипт выполняется после смерти любого монстра в игре * +* The script is executed after the death of any monster in the game * * * ************************************************************************/ @@ -2082,6 +2203,7 @@ } /************************************************************************ +* * * OnGameDayAutomatisation() * * used for creating action of npc every game day * * * @@ -2121,6 +2243,7 @@ } /************************************************************************ +* * * OnGameHourAutomatisation() * * used for creating action of npc every game hour * * * @@ -2159,6 +2282,14 @@ return (!lua_isnil(LuaHandle,-1) && lua_isnumber(LuaHandle,-1) ? (int32)lua_tonumber(LuaHandle,-1) : 0); } +/************************************************************************ +* * +* OnZoneWeatherChange * +* used to allow scripted Npcs and mobs to spawn under specific * +* weather conditions * +* * +************************************************************************/ + int32 OnZoneWeatherChange(uint16 ZoneID, uint8 weather) { int8 File[255]; @@ -2656,8 +2787,8 @@ /************************************************************************ * * -* Получаем значение глобальной переменной сервера. * -* Переменная действительна лишь в пределах зоны, в которой установлена * +* Get the value of a global variable server. The variable is only * +* valid within the zone in which the set * * * ************************************************************************/ @@ -2681,7 +2812,7 @@ /************************************************************************ * * -* Устанавливаем значение глобальной переменной сервера. * +* Set the value of the global server variable. * * * ************************************************************************/ @@ -2752,7 +2883,10 @@ } /******************************************************************** - onBcnmEnter - callback when you enter a BCNM via a lua call to bcnmEnter(bcnmid) +* * +* onBcnmEnter - callback when you enter a BCNM via a lua call to * +* bcnmEnter(bcnmid) * +* * *********************************************************************/ int32 OnBcnmEnter(CCharEntity* PChar, CInstance* PInstance){ int8 File[255]; @@ -2792,16 +2926,18 @@ return (!lua_isnil(LuaHandle,-1) && lua_isnumber(LuaHandle,-1) ? (int32)lua_tonumber(LuaHandle,-1) : 0); } -/******************************************************************** - onBcnmLeave - callback when you leave a BCNM via multiple means. - The method of leaving is given by the LeaveCode as follows: - 1 - Leaving via burning circle e.g. "run away" - 2 - Leaving via warp or d/c - 3 - Leaving via win - 4 - Leaving via lose - This callback is executed for everyone in the BCNM when they leave - so if they leave via win, this will be called for each char. -*********************************************************************/ +/************************************************************************ +* * +* onBcnmLeave - callback when you leave a BCNM via multiple means. * +* The method of leaving is given by the LeaveCode as follows: * +* 1 - Leaving via burning circle e.g. "run away" * +* 2 - Leaving via warp or d/c * +* 3 - Leaving via win * +* 4 - Leaving via lose * +* This callback is executed for everyone in the BCNM when they leave * +* so if they leave via win, this will be called for each char. * +* * +************************************************************************/ int32 OnBcnmLeave(CCharEntity* PChar, CInstance* PInstance, uint8 LeaveCode){ int8 File[255]; memset(File,0,sizeof(File)); @@ -2847,11 +2983,13 @@ } /******************************************************************** - onBcnmRegister - callback when you successfully register a BCNM. - For example, trading an orb, selecting the battle. - Called AFTER assigning BCNM status to all valid characters. - This callback is called only for the character initiating the - registration, and after CInstance:init() procedure. +* * +* onBcnmRegister - callback when you successfully register a BCNM.* +* For example, trading an orb, selecting the battle. * +* Called AFTER assigning BCNM status to all valid characters. * +* This callback is called only for the character initiating the * +* registration, and after CInstance:init() procedure. * +* * *********************************************************************/ int32 OnBcnmRegister(CCharEntity* PChar, CInstance* PInstance){ int8 File[255]; Index: src/map/lua/luautils.h =================================================================== --- src/map/lua/luautils.h (revision 3520) +++ src/map/lua/luautils.h (working copy) @@ -51,13 +51,13 @@ int32 free(); int32 print(lua_State*); - int32 SendUncnown0x39Packet(lua_State*); // временное решение для работы гейзеров в Dangruf_Wadi + int32 SendUnknown0x39Packet(lua_State*); // Temporary solution for geysers in Dangruf Wadi int32 GetNPCByID(lua_State*); // Returns NPC By Id int32 GetMobByID(lua_State*); // Returns Mob By Id int32 GetMobIDByJob(lua_State*); // Return mobid by job int32 WeekUpdateConquest(lua_State*); - int32 GetRegionOwner(lua_State*); // узнаем страну, владеющую текущим регионом + int32 GetRegionOwner(lua_State*); // Know the country that owns the current region int32 SetRegionalConquestOverseers(); // Update NPC Conquest Guard int32 setMobPos(lua_State*); // set a mobs position (only if mob is not in combat) @@ -66,11 +66,12 @@ int32 SpawnMob(lua_State*); // Spawn Mob By Mob Id - NMs, BCNM... int32 DespawnMob(lua_State*); // Despawn (Fade Out) Mob By Id + int32 SpawnNPC(lua_State*); // Spawn Mob By NPC Id - NMs, BCNM... int32 GetPlayerByName(lua_State*); // Gets Player ref from a name supplied int32 GetMobAction(lua_State*); // Get Mobs current action - int32 VanadielTOTD(lua_State*); // текущее игровое время суток - int32 VanadielHour(lua_State*); // текущие Vanadiel часы - int32 VanadielMinute(lua_State*); // текущие Vanadiel минуты + int32 VanadielTOTD(lua_State*); // Current playing time of day + int32 VanadielHour(lua_State*); // Current Vanadiel hour + int32 VanadielMinute(lua_State*); // Current Vanadiel minute int32 VanadielDayOfTheYear(lua_State*); // Gets Integer Value for Day of the Year (Jan 01 = Day 1) int32 VanadielDayOfTheMonth(lua_State*); // Gets day of the month (Feb 6 = Day 6) int32 VanadielYear(lua_State*); // Gets the current Vanadiel Year @@ -79,12 +80,13 @@ int32 VanadielMoonPhase(lua_State*); // Gets the current Vanadiel Moon Phase int32 VanadielMoonDirection(lua_State* L); // Gets the current Vanadiel Moon Phasing direction (waxing, waning, neither) int32 SetVanadielTimeOffset(lua_State* L); + int32 IsMoonNew(lua_State* L); // Returns true if the moon is new int32 IsMoonFull(lua_State* L); // Returns true if the moon is full int32 StartElevator(lua_State*); int32 GetServerVariable(lua_State*); int32 SetServerVariable(lua_State *); - int32 GetTextIDVariable(uint16 ZoneID, const char* variable); // загружаем значение переменной TextID указанной зоны + int32 GetTextIDVariable(uint16 ZoneID, const char* variable); // load the value of the specified zone TextID int32 OnServerStart(); // triggers when game server starts up @@ -95,7 +97,7 @@ int32 OnGameIn(CCharEntity* PChar); // int32 OnZoneIn(CCharEntity* PChar); // triggers when a player zones into a zone - int32 OnZoneInitialise(uint16 ZoneID); // triggers when zone is loaded + int32 OnZoneInitialize(uint16 ZoneID); // triggers when zone is loaded int32 OnRegionEnter(CCharEntity* PChar, CRegion* PRegion); // when player enters a region of a zone int32 OnRegionLeave(CCharEntity* PChar, CRegion* Pregion); // when player leaves a region of a zone int32 OnTransportEvent(CCharEntity* PChar, uint32 TransportID); @@ -143,6 +145,7 @@ int32 GetMobRespawnTime(lua_State* L); // get the respawn time of a mob int32 DeterMob(lua_State* L); // Allow or prevent a mob from spawning int32 UpdateNMSpawnPoint(lua_State* L); // Update the spawn point of an NM + int32 SendMobMessage(lua_State* L); }; #endif //- _LUAUTILS_H - Index: src/map/Makefile.in =================================================================== --- src/map/Makefile.in (revision 3520) +++ src/map/Makefile.in (working copy) @@ -44,7 +44,7 @@ obj_map/packets/fishing.o obj_map/packets/guild_menu.o obj_map/packets/guild_menu_buy.o obj_map/packets/guild_menu_sell.o \ obj_map/packets/merit_points_categories.o obj_map/packets/party_define.o obj_map/packets/party_invite.o obj_map/packets/party_map.o \ obj_map/packets/party_member_update.o obj_map/packets/party_search.o obj_map/packets/pet_sync.o obj_map/packets/treasure_find_item.o \ - obj_map/packets/treasure_lot_item.o obj_map/packets/uncnown_39.o obj_map/packets/world_pass.o obj_map/packets/linkshell_equip.o \ + obj_map/packets/treasure_lot_item.o obj_map/packets/unknown_39.o obj_map/packets/world_pass.o obj_map/packets/linkshell_equip.o \ obj_map/packets/linkshell_message.o obj_map/packets/bazaar_confirmation.o obj_map/packets/bazaar_purchase.o \ obj_map/items/item.o obj_map/items/item_armor.o obj_map/items/item_furnishing.o obj_map/items/item_general.o \ obj_map/items/item_linkshell.o obj_map/items/item_currency.o \ @@ -83,7 +83,7 @@ packets/char_spells.h packets/delivery_box.h packets/fishing.h packets/guild_menu.h packets/guild_menu_buy.h \ packets/guild_menu_sell.h packets/merit_points_categories.h packets/party_define.h packets/party_invite.h \ packets/party_map.h packets/party_member_update.h packets/party_search.h packets/pet_sync.h packets/treasure_find_item.h \ - packets/treasure_lot_item.h packets/uncnown_39.h packets/world_pass.h packets/bazaar_confirmation.h packets/bazaar_purchase.h \ + packets/treasure_lot_item.h packets/unknown_39.h packets/world_pass.h packets/bazaar_confirmation.h packets/bazaar_purchase.h \ packets/trade_action.h packets/trade_item.h packets/trade_request.h packets/trade_update.h \ items/item.h items/item_armor.h items/item_furnishing.h items/item_general.h \ items/item_linkshell.h items/item_puppet.h items/item_usable.h items/item_weapon.h \ Index: src/map/map.cpp =================================================================== --- src/map/map.cpp (revision 3520) +++ src/map/map.cpp (working copy) @@ -66,8 +66,8 @@ const int8* MAP_CONF_FILENAME = NULL; -int8* g_PBuff = NULL; // глобальный буфер обмена пакетами -int8* PTempBuff = NULL; // временный буфер обмена пакетами +int8* g_PBuff = NULL; // global buffer packet exchange +int8* PTempBuff = NULL; // temporary buffer packet exchange Sql_t* SqlHandle = NULL; // SQL descriptor int32 map_fd = 0; // main socket @@ -154,7 +154,7 @@ } Sql_Keepalive(SqlHandle); - // отчищаем таблицу сессий при старте сервера (временное решение, т.к. в кластере это не будет работать) + // Cleans the session table when the server starts (a temporary solution, because in the cluster, this will not work) Sql_Query(SqlHandle, "TRUNCATE TABLE accounts_sessions"); ShowMessage("\t\t - " CL_GREEN"[OK]" CL_RESET"\n"); @@ -166,8 +166,8 @@ itemutils::Initialize(); ShowMessage("\t\t\t - " CL_GREEN"[OK]" CL_RESET"\n"); - // нужно будет написать один метод для инициализации всех данных в battleutils - // и один метод для освобождения этих данных + // Need to write a single method to initialize all data battleutils + // And a method to release the data ShowStatus("do_init: loading spells"); spell::LoadSpellList(); @@ -206,6 +206,7 @@ CTaskMgr::getInstance()->AddTask("time_server", gettick(), NULL, CTaskMgr::TASK_INTERVAL, time_server, 2400); CTaskMgr::getInstance()->AddTask("map_cleanup", gettick(), NULL, CTaskMgr::TASK_INTERVAL, map_cleanup, 5000); + CTaskMgr::getInstance()->AddTask("save_playtime", gettick(), NULL, CTaskMgr::TASK_INTERVAL, save_playtime, 600000); // Update this every 10 minutes. CREATE(g_PBuff, int8, map_config.buffer_size + 20); CREATE(PTempBuff, int8, map_config.buffer_size + 20); @@ -333,8 +334,8 @@ if( recv_parse(g_PBuff,&size,&from,map_session_data) != -1 ) { - // если предыдущий пакет был потерян, то мы не собираем новый, - // а отправляем предыдущий пакет повторно + // If the previous packet was lost, we do not collect new + // And re-send the previous package if (!parse(g_PBuff,&size,&from,map_session_data)) { send_parse(g_PBuff,&size,&from,map_session_data); @@ -438,7 +439,7 @@ memcpy(map_session_data->blowfish.key,strSessionKey,20); } - // наверное создание персонажа лучше вынести в метод charutils::LoadChar() и загрузку инвентаря туда же сунуть + // Create a character must make a better method charutils :: LoadChar () and loading equipment to the same stick CCharEntity* PChar = new CCharEntity(); @@ -497,7 +498,7 @@ int32 parse(int8* buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data) { - // начало обработки входящего пакета + // Start processing the incoming packet int8* PacketData_Begin = &buff[FFXI_HEADER_SIZE]; int8* PacketData_End = &buff[*buffsize]; @@ -517,8 +518,8 @@ if(PacketSize[SmallPD_Type] == SmallPD_Size || PacketSize[SmallPD_Type] == 0) // Tests incoming packets for the correct size prior to processing { - // если код текущего пакета меньше либо равен последнему полученному - // или больше глобального то игнорируем пакет + // If the code of the current package is less than or equal to the last received + // Or more global then ignore package if ((RBUFW(SmallPD_ptr,2) <= map_session_data->client_packet_id) || (RBUFW(SmallPD_ptr,2) > SmallPD_Code)) @@ -545,8 +546,8 @@ } map_session_data->client_packet_id = SmallPD_Code; - // здесь мы проверяем, получил ли клиент предыдущий пакет - // если не получил, то мы не создаем новый, а отправляем предыдущий + // Here we check to see whether the client the previous package + // If not, then we do not create a new one and send the previous if (RBUFW(buff,2) != map_session_data->server_packet_id) { @@ -560,11 +561,11 @@ return -1; } - // увеличиваем номер отправленного пакета только в случае отправки новых данных + //Increase the number of sent packet only when sending new data map_session_data->server_packet_id += 1; - // собираем большой пакет, состоящий из нескольких маленьких + // Collect a large package, consisting of a few small CBasicPacket* PSmallPacket; @@ -592,26 +593,26 @@ int32 send_parse(int8 *buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data) { - // Модификация заголовка исходящего пакета - // Суть преобразований: - // - отправить клиенту номер последнего полученного от него пакета - // - присвоить исходящему пакету номер последнего отправленного клиенту пакета +1 - // - записать текущее время отправки пакета + // Modification of the outgoing packet header + // The point transformations: + // - Send to the client number of the last packet received from him + // - Set the number of the last outgoing packet is sent to the client package +1 + // - Write the current time a packet is sent WBUFW(buff,0) = map_session_data->server_packet_id; WBUFW(buff,2) = map_session_data->client_packet_id; - // сохранение текущего времени (32 BIT!) + // Save the current time (32 BIT!) WBUFL(buff,8) = (uint32)time(NULL); - //Сжимаем данные без учета заголовка - //Возвращаемый размер в 8 раз больше реальных данных + // Compress data without header + // Return the size is 8 times the actual data uint32 PacketSize = zlib_compress(buff+FFXI_HEADER_SIZE, *buffsize-FFXI_HEADER_SIZE, PTempBuff, *buffsize, zlib_compress_table); - //Запись размера данных без учета заголовка + // Write data size without header WBUFL(PTempBuff,(PacketSize+7)/8) = PacketSize; - //Расчет hash'a также без учета заголовка, но с учетом записанного выше размера данных + // Calculate the hash'a also without title, but with the size of the data recorded above PacketSize = (PacketSize+7)/8+4; uint8 hash[16]; md5((uint8*)PTempBuff, hash, PacketSize); @@ -623,7 +624,7 @@ ShowFatalError(CL_RED"%Memory manager: PTempBuff is overflowed (%u)\n" CL_RESET, PacketSize); } - //making total packet + // making total packet memcpy(buff+FFXI_HEADER_SIZE, PTempBuff, PacketSize); uint32 CypherSize = (PacketSize/4)&-2; @@ -635,12 +636,12 @@ blowfish_encipher((uint32*)(buff)+j+7, (uint32*)(buff)+j+8, pbfkey->P, pbfkey->S[0]); } - // контролируем размер отправляемого пакета. в случае, - // если его размер превышает 1400 байт (размер данных + 42 байта IP заголовок), - // то клиент игнорирует пакет и возвращает сообщение о его потере + // Control the size of the packet sent. in case + // If it exceeds 1400 bytes (the size of data + 42 bytes of IP header) + // The client ignores the packet and returns a message about his loss - // в случае возникновения подобной ситуации выводим предупреждующее сообщение и - // уменьшаем размер BuffMaxSize с шагом в 4 байта до ее устранения (вручную) + // In case of a situation like this we deduce ADVISED message and + // Decrease the size BuffMaxSize increments of 4 bytes to fix it (by hand) *buffsize = PacketSize+FFXI_HEADER_SIZE; @@ -653,8 +654,8 @@ /************************************************************************ * * -* Таймер для завершения сессии (без таймера мы этого сделать не можем, * -* т.к. сессия продолжает использоваться в do_sockets) * +* Timer to end the session (without the timer, we can not do that, * +* As session continues to be used do_sockets) * * * ************************************************************************/ @@ -668,6 +669,8 @@ { Sql_Query(SqlHandle,"DELETE FROM accounts_sessions WHERE charid = %u",map_session_data->PChar->id); + charutils::SavePlayTime(map_session_data->PChar); + uint64 port64 = map_session_data->client_port; uint64 ipp = map_session_data->client_addr; ipp |= port64<<32; @@ -824,6 +827,7 @@ map_config.server_message = ""; map_config.buffer_size = 1800; map_config.exp_rate = 1.0f; + map_config.exp_loss_rate = 1.0f; map_config.exp_retain = 0.0f; map_config.exp_loss_level = 4; map_config.speed_mod = 0; @@ -835,6 +839,24 @@ map_config.lightluggage_block = 4; map_config.max_time_lastupdate = 60000; map_config.newstyle_skillups = 7; + map_config.engage_dist_mod = 1.0f; + map_config.magic_dist_mod = 1.0f; + map_config.ranged_dist_mod = 1.0f; + map_config.remove_engage_delay = 0; + map_config.magic_movement = 0; + map_config.seal_crest_bonus = 0; + map_config.always_seal_crest = 0; + map_config.drop_rate_bonus = 0; + map_config.all_mobs_drop_gil = 0; + map_config.gil_bonus = 1; + map_config.chain_on_easy = 0; + map_config.chain_bonus = 1; + map_config.craft_skill_onfail = 0; + map_config.craft_skillamt = 0; + map_config.conquest_bonus = 1; + map_config.craft_success = 1; + map_config.notorious_hp_mod = 2.5f; + map_config.notorious_hp_mod = 2.5f; map_config.max_merit_points = 30; return 0; } @@ -893,6 +915,78 @@ { map_config.buffer_size = atoi(w2); } + else if (strcmp(w1,"engage_dist_mod") == 0) + { + map_config.engage_dist_mod = atoi(w2); + } + else if (strcmp(w1,"magic_dist_mod") == 0) + { + map_config.magic_dist_mod = atoi(w2); + } + else if (strcmp(w1,"ranged_dist_mod") == 0) + { + map_config.ranged_dist_mod = atoi(w2); + } + else if (strcmp(w1,"remove_engage_delay") == 0) + { + map_config.remove_engage_delay = atoi(w2); + } + else if (strcmp(w1,"magic_movement") == 0) + { + map_config.magic_movement = atoi(w2); + } + else if (strcmp(w1,"seal_crest_bonus") == 0) + { + map_config.seal_crest_bonus = atoi(w2); + } + else if (strcmp(w1,"always_seal_crest") == 0) + { + map_config.always_seal_crest = atoi(w2); + } + else if (strcmp(w1,"drop_rate_bonus") == 0) + { + map_config.drop_rate_bonus = atoi(w2); + } + else if (strcmp(w1,"all_mobs_drop_gil") == 0) + { + map_config.all_mobs_drop_gil = atoi(w2); + } + else if (strcmp(w1,"gil_bonus") == 0) + { + map_config.gil_bonus = atoi(w2); + } + else if (strcmp(w1,"chain_on_easy") == 0) + { + map_config.chain_on_easy = atoi(w2); + } + else if (strcmp(w1,"chain_bonus") == 0) + { + map_config.chain_bonus = atoi(w2); + } + else if (strcmp(w1,"craft_skill_onfail") == 0) + { + map_config.craft_skill_onfail = atoi(w2); + } + else if (strcmp(w1,"craft_skillamt") == 0) + { + map_config.craft_skillamt = atoi(w2); + } + else if (strcmp(w1,"conquest_bonus") == 0) + { + map_config.conquest_bonus = atoi(w2); + } + else if (strcmp(w1,"craft_success") == 0) + { + map_config.craft_success = atoi(w2); + } + else if (strcmp(w1,"notorious_hp_mod") == 0) + { + map_config.notorious_hp_mod = atoi(w2); + } + else if (strcmp(w1,"notorious_mp_mod") == 0) + { + map_config.notorious_mp_mod = atoi(w2); + } else if (strcmp(w1,"max_time_lastupdate") == 0) { map_config.max_time_lastupdate = atoi(w2); Index: src/map/map.h =================================================================== --- src/map/map.h (revision 3520) +++ src/map/map.h (working copy) @@ -87,6 +87,24 @@ float mob_tp_multiplier; // Multiplies the amount of TP mobs gain on any effect that would grant TP float player_tp_multiplier; // Multiplies the amount of TP players gain on any effect that would grant TP uint8 newstyle_skillups; // Allows failed parries and blocks to trigger skill up chance. + float engage_dist_mod; // Default is 1. Multiplies the distance that you can engage a target. Change to 3 for 3x the distance. + float magic_dist_mod; // Default is 1. Multiplies the distance that you can cast magic on a target. Change to 3 for 3x the distance. + float ranged_dist_mod; // Default is 1. Multiplies the distance that you can used ranged attack on a target. Change to 3 for 3x the distance. + int8 remove_engage_delay; // Default is 0. This removes the engegement delay that happens just after killing a target, or after equipping a weapon. + float magic_movement; // Default is 0. Allows movement while magic casting. + int16 seal_crest_bonus; // Increases chance of exp mobs dropping seals or crests. Set from 0 - 60. + int8 always_seal_crest; // Allows non exp beastman mobs to drop seals and crests. Default is 0. Set to 1 for non exp beastman mobs to drop seals and crests. + int8 drop_rate_bonus; // Adds to the drop rate percentate. Set to 20 to add additional %20 drop rate on all drops. + int8 all_mobs_drop_gil; // Set to 1 to allow all mobs to drop gil. Currently does not display ingame messages for these gil drops. Default is 0. + int16 gil_bonus; // Multiplies the amount of gil dropped + int8 chain_on_easy; // Allows exp chain on any exp mob + int8 chain_bonus; // Increases the time frame allowed to get an exp chain. Default is 1. + int8 craft_skill_onfail; // Allows same skillup on chance for failures as crafting successes have. Default is 0. + int8 craft_skillamt; // Increases the chance of getting larger skillups while crafting. Set 0 to 100. Default 0. + int8 conquest_bonus; // Multiplies the amount of conquest points earned on an exp mob kill. Default is 1 + int16 craft_success; // Increases the chance of succeding at crafting. Default 1. + float notorious_hp_mod; // Multiplier to NM HP. + float notorious_mp_mod; // Multiplier to NM HP. uint8 max_merit_points; // global variable, amount of merit points players are allowed }; @@ -100,10 +118,10 @@ { uint32 client_addr; uint16 client_port; - uint16 client_packet_id; // id последнего пакета, пришедшего от клиента - uint16 server_packet_id; // id последнего пакета, отправленного сервером - int8* server_packet_data; // указатель на собранный пакет, который был ранее отправлен клиенту - size_t server_packet_size; // размер пакета, который был ранее отправлен клиенту + uint16 client_packet_id; // id of the last packet passed to the client + uint16 server_packet_id; // id of the last packet sent by the server + int8* server_packet_data; // pointer to the assembled package that was previously sent to the client + size_t server_packet_size; // size of the package that was previously sent to the client time_t last_update; // time of last packet recv blowfish_t blowfish; // unique decypher keys CCharEntity *PChar; // game char @@ -134,7 +152,7 @@ int32 map_config_default(); int32 map_cleanup(uint32 tick,CTaskMgr::CTask *PTask); // Clean up timed out players -int32 map_close_session(uint32 tick,CTaskMgr::CTask *PTask); // завершение сессии +int32 map_close_session(uint32 tick,CTaskMgr::CTask *PTask); // End of session #endif //_MAP_H Index: src/map/merit.cpp =================================================================== --- src/map/merit.cpp (revision 3520) +++ src/map/merit.cpp (working copy) @@ -31,11 +31,11 @@ /************************************************************************ * * -* Две версии значений - до abyssea и после * +* Two versions of the values - up to and after abyssea * * * ************************************************************************/ -// массив больше на одно значение, заполняемое нулем +// greater array to the same value, filled zero #ifdef ABYSSEA_EXPANSION static uint8 upgrade[9][16] = @@ -43,58 +43,58 @@ {1,2,3,4,5,5,5,5,5,7,7,7,9,9,9}, // HP-MP {3,6,9,9,9,12,12,12,12,15,15,15}, // Attributes {1,2,3,3,3,3,3,3}, // Combat Skills - {1,2,3,3}, // Defensive Skills + {1,2,3,3}, // Defensive Skills {1,2,3,3,3,3,3,3}, // Magic Skills {1,2,3,4,5}, // Others {1,2,3,4,5}, // Job Group 1 {3,4,5,5,5}, // Job Group 2 {10,15,20,25,30}, // Weapon Skills }; -#define MAX_LIMIT_POINTS 10000 // количество опыта для получения одного merit -//#define MAX_MERIT_POINTS 30 // максимальное количество неиспользованных merit +#define MAX_LIMIT_POINTS 10000 // amount of experience to get one merit +//#define MAX_MERIT_POINTS 30 // the maximum number of unused merits // option to change max points, kept the original above -#define MAX_MERIT_POINTS map_config.max_merit_points +#define MAX_MERIT_POINTS map_config.max_merit_points #else static uint8 upgrade[9][9] = { {1,2,3,4,5,5,5,5}, //0 HP-MP {3,6,9,9,9}, //1 Attributes - {1,2,3,3,3,3,3,3}, //2 Combat Skills - {1,2,3,3}, //3 Defensive Skills - {1,2,3,3,3,3,3,3}, //4 Magic Skills + {1,2,3,3,3,3,3,3}, //2 Combat Skills + {1,2,3,3}, //3 Defensive Skills + {1,2,3,3,3,3,3,3}, //4 Magic Skills {1,2,3,4,5}, //5 Others {1,2,3,4,5}, //6 Job Group 1 {3,4,5,5,5}, //7 Job Group 2 {0}, //8 Weapon Skills }; -#define MAX_LIMIT_POINTS 10000 // количество опыта для получения одного merit -//#define MAX_MERIT_POINTS 100 // максимальное количество неиспользованных merit +#define MAX_LIMIT_POINTS 10000 // amount of experience to get a merit +//#define MAX_MERIT_POINTS 100 // the maximum number of unused merits // option to change max points, kept the original above -#define MAX_MERIT_POINTS map_config.max_merit_points +#define MAX_MERIT_POINTS map_config.max_merit_points -#endif +#endif -// TODO: скорее всего придется все это перенести в базу +// TODO: most likely will have to move it to the database /************************************************************************ * * -* Ограничение количества усилений metir * +* Limit the number of maximum merit * * * ************************************************************************/ static uint8 cap[100] = -{ - 0,0,0,0,0,0,0,0,0,0, // 0-9 0 - 1,1,1,1,1,1,1,1,1,1, // 10-19 1 - 2,2,2,2,2,2,2,2,2,2, // 20-29 2 - 3,3,3,3,3,3,3,3,3,3, // 30-39 3 - 4,4,4,4,4,4,4,4,4,4, // 40-49 4 - 5,5,5,5,5, // 50-54 5 - 6,6,6,6,6, // 55-59 6 - 7,7,7,7,7, // 60-64 7 +{ + 0,0,0,0,0,0,0,0,0,0, // 0-9 0 + 1,1,1,1,1,1,1,1,1,1, // 10-19 1 + 2,2,2,2,2,2,2,2,2,2, // 20-29 2 + 3,3,3,3,3,3,3,3,3,3, // 30-39 3 + 4,4,4,4,4,4,4,4,4,4, // 40-49 4 + 5,5,5,5,5, // 50-54 5 + 6,6,6,6,6, // 55-59 6 + 7,7,7,7,7, // 60-64 7 8,8,8,8,8, // 65-69 8 8,8,8,8,8,8,8,8,8,8, // 70-79 8 8,8,8,8,8,8,8,8,8,8, // 80-89 8 @@ -103,78 +103,78 @@ /************************************************************************ * * -* Количество элементов в каждой из категорий * +* The number of items in each category * * * ************************************************************************/ struct MeritCategoryInfo_t { - int8 MeritsInCat; // количество элементов в группе - uint8 MaxPoints; // максимальное количество points, которые можно вложить в группу - uint8 UpgradeID; // индекс группы в массиве upgrade + int8 MeritsInCat; // the number of elements in the group + uint8 MaxPoints; // the maximum number of points, which can be embedded in a group + uint8 UpgradeID; // group index in the array of upgrade }; static const MeritCategoryInfo_t meritCatInfo[] = { - {2,15,0}, //MCATEGORY_HP_MP - {7,12,1}, //MCATEGORY_ATTRIBUTES - {19,32,2}, //MCATEGORY_COMBAT - {12,24,4}, //MCATEGORY_MAGIC - {5,10,5}, //MCATEGORY_OTHERS + {2,15,0}, //MCATEGORY_HP_MP + {7,12,1}, //MCATEGORY_ATTRIBUTES + {19,32,2}, //MCATEGORY_COMBAT + {12,24,4}, //MCATEGORY_MAGIC + {5,10,5}, //MCATEGORY_OTHERS - {5,10,6}, //MCATEGORY_WAR_1 - {5,10,6}, //MCATEGORY_MNK_1 - {5,10,6}, //MCATEGORY_WHM_1 - {7,10,6}, //MCATEGORY_BLM_1 - {7,10,6}, //MCATEGORY_RDM_1 - {5,10,6}, //MCATEGORY_THF_1 - {5,10,6}, //MCATEGORY_PLD_1 - {5,10,6}, //MCATEGORY_DRK_1 - {5,10,6}, //MCATEGORY_BST_1 - {5,10,6}, //MCATEGORY_BRD_1 - {5,10,6}, //MCATEGORY_RNG_1 - {5,10,6}, //MCATEGORY_SAM_1 - {7,10,6}, //MCATEGORY_NIN_1 - {5,10,6}, //MCATEGORY_DRG_1 - {5,10,6}, //MCATEGORY_SMN_1 - {5,10,6}, //MCATEGORY_BLU_1 - {5,10,6}, //MCATEGORY_COR_1 - {5,10,6}, //MCATEGORY_PUP_1 - {4,10,6}, //MCATEGORY_DNC_1 - {4,10,6}, //MCATEGORY_SCH_1 + {5,10,6}, //MCATEGORY_WAR_1 + {5,10,6}, //MCATEGORY_MNK_1 + {5,10,6}, //MCATEGORY_WHM_1 + {7,10,6}, //MCATEGORY_BLM_1 + {7,10,6}, //MCATEGORY_RDM_1 + {5,10,6}, //MCATEGORY_THF_1 + {5,10,6}, //MCATEGORY_PLD_1 + {5,10,6}, //MCATEGORY_DRK_1 + {5,10,6}, //MCATEGORY_BST_1 + {5,10,6}, //MCATEGORY_BRD_1 + {5,10,6}, //MCATEGORY_RNG_1 + {5,10,6}, //MCATEGORY_SAM_1 + {7,10,6}, //MCATEGORY_NIN_1 + {5,10,6}, //MCATEGORY_DRG_1 + {5,10,6}, //MCATEGORY_SMN_1 + {5,10,6}, //MCATEGORY_BLU_1 + {5,10,6}, //MCATEGORY_COR_1 + {5,10,6}, //MCATEGORY_PUP_1 + {4,10,6}, //MCATEGORY_DNC_1 + {4,10,6}, //MCATEGORY_SCH_1 {14,15,8}, //MCATEGORY_WS {0,0,8}, //MCATEGORY_UNK_0 26 - {0,0,8}, //MCATEGORY_UNK_1 - {0,0,8}, //MCATEGORY_UNK_2 - {0,0,8}, //MCATEGORY_UNK_3 + {0,0,8}, //MCATEGORY_UNK_1 + {0,0,8}, //MCATEGORY_UNK_2 + {0,0,8}, //MCATEGORY_UNK_3 {0,0,8}, //MCATEGORY_UNK_4 30 - {4,10,7}, //MCATEGORY_WAR_2 - {4,10,7}, //MCATEGORY_MNK_2 - {4,10,7}, //MCATEGORY_WHM_2 - {6,10,7}, //MCATEGORY_BLM_2 - {6,10,7}, //MCATEGORY_RDM_2 - {4,10,7}, //MCATEGORY_THF_2 - {4,10,7}, //MCATEGORY_PLD_2 - {4,10,7}, //MCATEGORY_DRK_2 - {4,10,7}, //MCATEGORY_BST_2 - {4,10,7}, //MCATEGORY_BRD_2 - {4,10,7}, //MCATEGORY_RNG_2 - {4,10,7}, //MCATEGORY_SAM_2 - {8,10,7}, //MCATEGORY_NIN_2 - {4,10,7}, //MCATEGORY_DRG_2 - {6,10,7}, //MCATEGORY_SMN_2 - {4,10,7}, //MCATEGORY_BLU_2 - {4,10,7}, //MCATEGORY_COR_2 - {4,10,7}, //MCATEGORY_PUP_2 - {4,10,7}, //MCATEGORY_DNC_2 - {6,10,7}, //MCATEGORY_SHC_2 + {4,10,7}, //MCATEGORY_WAR_2 + {4,10,7}, //MCATEGORY_MNK_2 + {4,10,7}, //MCATEGORY_WHM_2 + {6,10,7}, //MCATEGORY_BLM_2 + {6,10,7}, //MCATEGORY_RDM_2 + {4,10,7}, //MCATEGORY_THF_2 + {4,10,7}, //MCATEGORY_PLD_2 + {4,10,7}, //MCATEGORY_DRK_2 + {4,10,7}, //MCATEGORY_BST_2 + {4,10,7}, //MCATEGORY_BRD_2 + {4,10,7}, //MCATEGORY_RNG_2 + {4,10,7}, //MCATEGORY_SAM_2 + {8,10,7}, //MCATEGORY_NIN_2 + {4,10,7}, //MCATEGORY_DRG_2 + {6,10,7}, //MCATEGORY_SMN_2 + {4,10,7}, //MCATEGORY_BLU_2 + {4,10,7}, //MCATEGORY_COR_2 + {4,10,7}, //MCATEGORY_PUP_2 + {4,10,7}, //MCATEGORY_DNC_2 + {6,10,7}, //MCATEGORY_SHC_2 }; -#define GetMeritCategory(merit) ((merit >> 6) - 1) // получаем категорию из merit -#define GetMeritID(merit) ((merit & 0x3F) >> 1) // получаем смещение в категории из merit +#define GetMeritCategory(merit) ((merit >> 6) - 1) // obtain the category of merit +#define GetMeritID(merit) ((merit & 0x3F) >> 1) // get the offset in the category of merit /************************************************************************ * * @@ -188,7 +188,7 @@ DSP_DEBUG_BREAK_IF(sizeof(merits) != sizeof(merits::GMeritsTemplate)); memcpy(merits, merits::GMeritsTemplate, sizeof(merits)); - + for (uint8 m = 0, i = 0; i < sizeof(Categories)/sizeof(Merit_t*); ++i) { Categories[i] = &merits[m]; @@ -241,11 +241,11 @@ { if (catNumber > 25 && catNumber < 31) // point these to valid merits to prevent crash - Categories[catNumber] = &merits[163]; + Categories[catNumber] = &merits[163]; else Categories[catNumber] = &merits[i]; - - catNumber++; + + catNumber++; } merits[i].count = points[i]; @@ -299,7 +299,7 @@ /************************************************************************ * * -* Получаем текущие limit points * +* Get the current limit points * * * ************************************************************************/ @@ -310,7 +310,7 @@ /************************************************************************ * * -* Получаем текущие merit points * +* Get the current merit points * * * ************************************************************************/ @@ -322,7 +322,7 @@ /************************************************************************ * * -* Получаем указател на массив merits * +* Gets a pointer to an array of merits * * * ************************************************************************/ @@ -334,11 +334,11 @@ /************************************************************************ * * -* Добавляем персонажу limit points * +* add character limit points * * * ************************************************************************/ -// true - если merit был добавлен +// true - if merit was added bool CMeritPoints::AddLimitPoints(uint16 points) { @@ -390,8 +390,8 @@ /************************************************************************ * * -* Проверяем наличие merit. Необходимо использовать лишь в случае * -* получения meritid от персонажа * +* Check the presence of merit. Should be used only in the case * +* receipt of a character meritid * * * ************************************************************************/ @@ -407,7 +407,7 @@ /************************************************************************ * * -* Получаем указатель на искомый const merit * +* Get a pointer of the desired const merit * * * ************************************************************************/ @@ -418,7 +418,7 @@ /************************************************************************ * * -* Получаем указатель на искомый const merit по индексу * +* Get a pointer of the desired const merit index * * * ************************************************************************/ @@ -432,7 +432,7 @@ /************************************************************************ * * -* Получаем указатель на искомый merit * +* Get a pointer of the desired merit * * * ************************************************************************/ @@ -507,7 +507,7 @@ /************************************************************************ * * -* Получаем текущее значение указанного merit * +* Get the current value of the specified merit * * * ************************************************************************/ @@ -537,21 +537,21 @@ /************************************************************************ * * -* Реализация namespase для работы с Linkshells * +* Implementing namespase to work with Linkshells * * * ************************************************************************/ namespace meritNameSpace { - Merit_t GMeritsTemplate[MERITS_COUNT] = {0}; // global list of merits and their properties + Merit_t GMeritsTemplate[MERITS_COUNT] = {0}; // global list of merits and their properties int16 groupOffset[MCATEGORY_COUNT/64-1] = {0}; // the first merit offset of each catagory - /************************************************************************ - * * - * Загружаем шаблон массива merits / Load pattern array merits * - * * - ************************************************************************/ + /*********************************** + * * + * Load pattern array merits * + * * + ************************************/ void LoadMeritsList() { @@ -570,7 +570,7 @@ int8 catMeritIndex = 0; // counts number of merits in a catagory - while( Sql_NextRow(SqlHandle) == SQL_SUCCESS ) + while( Sql_NextRow(SqlHandle) == SQL_SUCCESS ) { Merit_t Merit = {0}; // creat a new merit template. Index: src/map/merit.h =================================================================== --- src/map/merit.h (revision 3520) +++ src/map/merit.h (working copy) @@ -460,7 +460,7 @@ MERIT_STORMSURGE = MCATEGORY_SCH_2 + 0x0A, }; -#define MERITS_COUNT 305 // 5 полных пакетов по 61 элементу +#define MERITS_COUNT 305 // 5 complete package for 61 elements @@ -478,16 +478,16 @@ { struct { - uint16 id; // id мерита - uint8 next; // необходимое количество меритов для следующего усиления - uint8 count; // текущее количество усилений + uint16 id; // id Merit + uint8 next; // required number of Merits for the next increase + uint8 count; // the current number of exacerbations }; - uint32 data; // информация для отправки персонажу + uint32 data; // information to send to character }; - uint32 value; // коэффициент изменения параметра, привязанного к merit - uint8 upgrade; // максимальное количество усилений для данного merit - uint32 jobs; // маска профессий, для которых merit работает + uint32 value; // coefficient of variation of the parameter that is bound to merit + uint8 upgrade; // the maximum amount of gain for the merit + uint32 jobs; // Mask jobs for which the merit works uint8 upgradeid; // which set of upgrade values the merit will use uint8 catid; // cat which merit belongs to uint16 spellid; // associated spell ID to learn/unlearn @@ -512,7 +512,7 @@ int32 GetMeritValue(Merit_t* merit, CCharEntity* PChar); bool AddLimitPoints(uint16 points); // automatically adds merit points > 10000 - bool IsMeritExist(MERIT_TYPE merit); // проверяем существование merit + bool IsMeritExist(MERIT_TYPE merit); // check the existence of merit void RaiseMerit(MERIT_TYPE merit); // add upgrade void LowerMerit(MERIT_TYPE merit); // del upgrade Index: src/map/mob_spell_list.cpp =================================================================== --- src/map/mob_spell_list.cpp (revision 3520) +++ src/map/mob_spell_list.cpp (working copy) @@ -41,7 +41,7 @@ /************************************************************************ * * -* Реализация namespase для работы с заклинаниями * +* Implementing namespase to work with spells * * * ************************************************************************/ @@ -51,7 +51,7 @@ /************************************************************************ * * - * Загружаем список заклинаний * + * Load a list of spells * * * ************************************************************************/ Index: src/map/mob_spell_list.h =================================================================== --- src/map/mob_spell_list.h (revision 3520) +++ src/map/mob_spell_list.h (working copy) @@ -31,7 +31,7 @@ #include "spell.h" -#define MAX_MOBSPELLLIST_ID 42 +#define MAX_MOBSPELLLIST_ID 43 typedef struct { @@ -57,7 +57,7 @@ /************************************************************************ * * -* namespase для работы с заклинаниями * +* Namespase to work with spells * * * ************************************************************************/ Index: src/map/mobentity.cpp =================================================================== --- src/map/mobentity.cpp (revision 3520) +++ src/map/mobentity.cpp (working copy) @@ -41,6 +41,7 @@ MPscale = 1.0; m_AllowRespawn = 0; + m_ForceDespawn = false; m_CallForHelp = 0; m_DespawnTimer = 0; m_DropItemTime = 0; @@ -86,7 +87,7 @@ /************************************************************************ * * -* Время исчезновения монстра в секундах * +* Fade time monster in seconds * * * ************************************************************************/ Index: src/map/mobentity.h =================================================================== --- src/map/mobentity.h (revision 3520) +++ src/map/mobentity.h (working copy) @@ -43,7 +43,7 @@ SPAWNTYPE_FOG = 0x08, // 02:00-07:00 SPAWNTYPE_MOONPHASE = 0x10, SPAWNTYPE_LOTTERY = 0x20, - SPAWNTYPE_WINDOWED = 0x40, // понятия не имею, что это ^^ + SPAWNTYPE_WINDOWED = 0x40, // ​​I have no idea what it is ^ ^ SPAWNTYPE_SCRIPTED = 0x80 }; @@ -93,23 +93,24 @@ { public: - bool m_AllowRespawn; // монстру разрешено возрождаться - uint32 m_RespawnTime; // отрезок времени, через который монстр возрождается после смерти - uint32 m_DropItemTime; // время анимации смерти монстра + bool m_AllowRespawn; // monster is allowed to revive + bool m_ForceDespawn; + uint32 m_RespawnTime; // length of time over which the monster reborn after death + uint32 m_DropItemTime; // animation time of death monster uint32 m_MagicRecastTime; // Amount of time between casts. uint32 m_SpecialCoolDown; // Cool down time between uses. - uint16 m_SpecialSkill; // mobskill id to use + uint16 m_SpecialSkill; // mobskill id to use - uint32 m_DropID; // номер группы оставляемых монстром предметов после смерти + uint32 m_DropID; // number of items left by the death of a monster - uint8 m_minLevel; // минимально-возможный уровень монстра - uint8 m_maxLevel; // максимально-возможный уровень монстра + uint8 m_minLevel; // lowest possible level monster + uint8 m_maxLevel; // maximum possible level monster uint32 HPmodifier; // HP in Database (mob_groups) uint32 MPmodifier; // MP in Database (mob_groups) - float HPscale; // HP boost percentage - float MPscale; // MP boost percentage + float HPscale; // HP boost percentage + float MPscale; // MP boost percentage uint8 linkRadius; // mobs have different link radiuses // stat ranks @@ -127,28 +128,28 @@ // not used uint8 evaRank; - uint8 m_Type; // тип монстра - uint8 m_Link; // взаимопомощь монстрам своего семейства - uint16 m_Behaviour; // поведение монстра в различных ситуациях - SPAWNTYPE m_SpawnType; // условие появления монстра + uint8 m_Type; // type of monster + uint8 m_Link; // mutual monsters of his family + uint16 m_Behaviour; // monster behavior in different situations + SPAWNTYPE m_SpawnType; // condition for the appearance of a monster uint32 m_extraVar; // extra variable to store combat related variables from scripts - uint8 m_CallForHelp; // в перспективе желательно объединить эту переменную с CNpc->unknown + uint8 m_CallForHelp; // in the long term it is desirable to combine this variable CNpc-> unknown - position_t m_SpawnPoint; // точка возрождения монстра + position_t m_SpawnPoint; // point of the revival of the monster uint8 m_Element; uint8 m_HiPCLvl; // Highest Level of Player Character that hit the Monster uint8 m_THLvl; // Highest Level of Treasure Hunter that apply to drops uint32 m_THPCID; // ID of last PC that hit the NPC and apply TH onto the NPC uint16 m_Family; uint8 m_SkillStatus; // status of skills (used 2h/used epic tp move/etc) - CMobSpellList* m_SpellListContainer; // The spells list container for this mob + CMobSpellList* m_SpellListContainer; // The spells list container for this mob std::map m_UsedSkillIds; // mob skill ids used (key) along with mob level (value) uint32 m_unknown; // includes the CFH flag and whether the HP bar should be shown or not (e.g. Yilgeban doesnt) uint8 m_name_prefix; // The ding bats VS Ding bats - CEnmityContainer* PEnmityContainer; // система ненависти монстров + CEnmityContainer* PEnmityContainer; // system hate monsters bool hasRageMode(); // If the mob has the rage mode: true void addRageMode(); // Rage mode ON: stat x10 Index: src/map/mobskill.h =================================================================== --- src/map/mobskill.h (revision 3520) +++ src/map/mobskill.h (working copy) @@ -86,23 +86,23 @@ const int8* getName(); void setName(int8* name); - uint16 m_SkillCondition; //the condition of the skill, used for special tp moves, e.g. used sub 50% HP - uint16 m_SkillConditionValue; //the condition value, e.g. SkillCondition=BELOW_PCT SkillConditionValue=50 - // so TP move can only be used below 50% HP + uint16 m_SkillCondition; // the condition of the skill, used for special tp moves, e.g. used sub 50% HP + uint16 m_SkillConditionValue; // the condition value, e.g. SkillCondition=BELOW_PCT SkillConditionValue=50 + // so TP move can only be used below 50% HP private: uint16 m_ID; uint16 m_TotalTargets; uint16 m_FamilyID; - uint16 m_AnimID; //animation id - uint8 m_Aoe; // не используется - float m_Distance; // не используется - uint8 m_Flag; // не используется - uint8 m_ValidTarget; //same as - uint16 m_AnimationTime; //how long the tp animation lasts for in ms - uint16 m_ActivationTime; //how long the mob prepares the tp move for - uint16 m_Message; //message param, scripters can edit this depending on self/resist/etc. - float m_TP; //the tp at the time of finish readying (for scripts) + uint16 m_AnimID; // animation id + uint8 m_Aoe; // not used + float m_Distance; // not used + uint8 m_Flag; // not used + uint8 m_ValidTarget; // same as + uint16 m_AnimationTime; // how long the tp animation lasts for in ms + uint16 m_ActivationTime; // how long the mob prepares the tp move for + uint16 m_Message; // message param, scripters can edit this depending on self/resist/etc. + float m_TP; // the tp at the time of finish readying (for scripts) string_t m_name; }; Index: src/map/mobutils.cpp =================================================================== --- src/map/mobutils.cpp (revision 3520) +++ src/map/mobutils.cpp (working copy) @@ -37,7 +37,7 @@ /************************************************************************ * * -* Расчет базовой величины оружия монстров * +* The calculation of basic quantities of monsters weapons * * * ************************************************************************/ @@ -49,8 +49,8 @@ /************************************************************************ * * -* Базовое значение для расчера характеристик * -* (на название не хватило фантазии) * +* The base value for raschera characteristics * +* (the name did not have the imagination) * * * ************************************************************************/ @@ -71,8 +71,8 @@ /************************************************************************ * * -* Базовое значение для расчерта защиты и уклонения * -* (на название не хватило фантазии) * +* The base value for rascherta Def * +* (the name did not have the imagination) * * * ************************************************************************/ @@ -119,7 +119,7 @@ /************************************************************************ * * -* Расчет атрибутов (характеристик) монстра * +* The calculation of the attributes (characteristics) of a monster * * * ************************************************************************/ @@ -161,9 +161,9 @@ if(isNM) { - PMob->health.maxhp *= 2.0; + PMob->health.maxhp *= 5.0; if(PMob->GetMLevel() > 75){ - PMob->health.maxhp *= 2.5; + PMob->health.maxhp *= 7.5; } } @@ -184,9 +184,9 @@ if(PMob->MPmodifier == 0){ PMob->health.maxmp = (int16)(18.2 * pow(PMob->GetMLevel(),1.1075) * PMob->MPscale); if(isNM){ - PMob->health.maxmp *= 2.5; + PMob->health.maxmp *= 5.0; if(PMob->GetMLevel()>75){ - PMob->health.maxmp *= 2.5; + PMob->health.maxmp *= 7.5; } } } else { Index: src/map/modifier.h =================================================================== --- src/map/modifier.h (revision 3520) +++ src/map/modifier.h (working copy) @@ -64,11 +64,16 @@ MOD_RACC = 0x1A, // Ranged Accuracy MOD_ENMITY = 0x1B, // Enmity + MOD_TRANQUIL_HEART = 0x233, // Reduces enmity bases on healing skill (only checks if > 0) MOD_MATT = 0x1C, // Magic Attack MOD_MDEF = 0x1D, // Magic Defense MOD_MACC = 0x1E, // Magic Accuracy MOD_MEVA = 0x1F, // Magic Evasion + MOD_MAG_BURST_DMG = 0x19E, // Magic Burst Dmg % Bonus + MOD_ELEM_MAG_DMG = 0x1A2, // Elemental Magic Dmg % Bonus + MOD_ENFB_MAG_DMG = 0x1A3, // Enfeebling Magic Dmg % Bonus + MOD_NIN_MAG_DMG = 0x1A4, // Ninjutsu Magic Dmg % Bonus // Magic Accuracy and Elemental Attacks @@ -90,6 +95,7 @@ MOD_DARKACC = 0x2F, // Dark Accuracy MOD_WSACC = 0x30, // Weaponskill Accuracy + MOD_WS_DMG = 0x1C9, // Weaponskill Damage % // Resistance to damage type // Value is stored as a percentage of damage reduction (to within 1000) @@ -120,6 +126,7 @@ MOD_EVAP = 0x41, // % Evasion MOD_RATTP = 0x42, // % Ranged Attack MOD_RACCP = 0x43, // % Ranged Attack Accuracy + MOD_PARRYP = 0x232, // % Parry MOD_EVA = 0x44, // Evasion MOD_RDEF = 0x45, // Ranged Defense @@ -178,6 +185,8 @@ MOD_COOK = 0x87, MOD_SYNERGY = 0x88, MOD_RIDING = 0x89, + + MOD_GOLDFISHING = 0x1D1, // Chance you will not make an hq synth (Impossibility of HQ synth) @@ -198,13 +207,18 @@ MOD_DMGMAGIC = 0xA3, // Magic Damage Multiplier - 256 base! (value of -24 means -24/256 magic damage taken) MOD_DMGRANGE = 0xA4, // Range Damage Multiplier - MOD_UDMGPHYS = 0x183, // Uncapped Damage Multipliers + MOD_UDMGPHYS = 0x183, // Uncapped Damage Multipliers MOD_UDMGBREATH = 0x184, // Used in sentinal, invincible, physical shield etc MOD_UDMGMAGIC = 0x185, MOD_UDMGRANGE = 0x186, MOD_CRITHITRATE = 0xA5, // Raises chance to crit MOD_ENEMYCRITRATE = 0xA6, // Raises chance enemy will crit + MOD_CRIT_DMG = 0x1CB, // Raises Crit Hit Dmg % divided by 100 + MOD_MAGIC_CRIT_RATE = 0x22F, // Raises chance to Magic Crit + MOD_MAG_CRIT_DMG = 0x230, // Raises Magic Crit Dmg (MAB) + + MOD_SHIELD_DEF = 0x1CC, // Shield Dmg Reduction % Bonus MOD_HASTE_MAGIC = 0xA7, // Haste (and Slow) from magic - 1024 base! (448 cap) MOD_HASTE_ABILITY = 0x17F, // Haste (and Slow) from abilities - 1024 base! (256 cap?) @@ -268,86 +282,152 @@ MOD_SLOWRES = 0xFA, MOD_STUNRES = 0xFB, MOD_CHARMRES = 0xFC, + MOD_DEATHRES = 0xFD, // Not sure if I can just fill in a blank + MOD_TERRORRES = 0xFE, // empty inbetween on POL Utils + MOD_AMNESIARES = 0xFF, + MOD_DOOMRES = 0x19C, - MOD_UNKNOWN = 0xFF, - MOD_PARALYZE = 0x101, // Paralyze -- percent chance to proc MOD_MIJIN_GAKURE = 0x102, // Tracks whether or not you used this ability to die. MOD_DUAL_WIELD = 0x103, // Percent reduction in dual wield delay. + MOD_SHIELD_MASTERY = 0x1CD, // Extra TP Gained from a Block + MOD_TACTICAL_GUARD = 0x1CE, // Extra TP Gained from a Guard + MOD_TACTICAL_PARRY = 0x1CF, // Extra TP Gained from a Parry + MOD_OCCULT_ACCUMEN = 0x1D0, // TP Gained from Elemental or Dark Magic Casts divided by 1000 // Warrior MOD_DOUBLE_ATTACK = 0x120, // Percent chance to proc + MOD_RETALIATION_DMG = 0x1DB, // % increase to Retaliation Dmg + MOD_BLOOD_RAGE = 0x228, // Blood Rage duration // Monk MOD_SUBTLE_BLOW = 0x121, // How much TP to reduce. MOD_COUNTER = 0x123, // Percent chance to counter MOD_KICK_ATTACK = 0x124, // Percent chance to kick + MOD_KICK_DMG = 0x182, // increases kick attack damage + MOD_COUNTER_BASE_DMG = 0x1D9, // Increase Weapon Base DMG on Counters + MOD_PFT_COUNTER_DMG = 0x21A, // Increase Weapon Base DMG on Perfect Counter // White Mage MOD_AFFLATUS_SOLACE = 0x125, // Pool of HP accumulated during Afflatus Solace MOD_AFFLATUS_MISERY = 0x126, // Pool of HP accumulated during Afflatus Misery + MOD_DIVINE_BENISON_FASTCAST = 0x234, // Divine Benison Fastcast Mod + MOD_DIVINE_BENISON_ENMITY = 0x235, // Divine Benison Enmity Mod // Black Mage MOD_CLEAR_MIND = 0x127, // Used in conjunction with MOD_HEALMP to increase amount between tics MOD_CONSERVE_MP = 0x128, // Percent chance + MOD_MANA_WALL_DMG = 0x21B, // Percent additional Dmg Reduction to Mana Wall // Red Mage MOD_BLINK = 0x12B, // Tracks blink shadows MOD_STONESKIN = 0x12C, // Tracks stoneskin HP pool MOD_PHALANX = 0x12D, // Tracks direct damage reduction + MOD_SABOTEUR = 0x220, // Increase Potency and Duration durring Saboteur // Thief MOD_STEAL = 0x12A, // Increase/Decrease THF Steal chance MOD_TRIPLE_ATTACK = 0x12E, // Percent chance MOD_TREASURE_HUNTER = 0x12F, // Percent chance + MOD_SNEAK_ATK_MOD = 0x1CA, // Modifier for DEX Divided by 10 (1 = .01) + MOD_TRICK_ATK_MOD = 0x1D6, // Modifier for AGI % + MOD_SATA_DMG = 0x1D7, // SA TA Dmg Modifier % + MOD_GILFINDER = 0x1D4, // Gil dropped from mob +50% per mod + MOD_DESPOIL = 0x1DC, // Increase/Decrease THF Despoil chance // Paladin + MOD_SHIELD_BASH = 0x181, // Shield Bash Dmg Increase + MOD_DIVINE_EMBLEM = 0x21C, // Divine Emblem enmity modifier + MOD_BLOCK_RATE = 0x21D, // Increase chance to block with shield (Reprisal/Palisade) + // Dark Knight + MOD_WEAPON_BASH = 0x1B1, // Increase Weapon Bash Damage + MOD_STALWART_SOUL = 0x1D5, // HP reduction from Souleater divided by 1000 + MOD_DARK_MAG_CAST = 0x1DA, // % Reduction to Dark Magic Cast Time + MOD_ABSORB_POTENCY = 0x21E, // % increase to Absorb potency + MOD_ABSORB_DURATION = 0x21F, // Increase to Absorb duration seconds + MOD_SCARLET_DMG = 0x229, // Percent Bonus to Dmg during Scarlet Delirium + MOD_SCARLET_MDMG = 0x22A, // Percent Bonus to Magic Dmg during Scarlet Delirium + // Beastmaster MOD_TAME = 0x130, // Additional percent chance to charm MOD_CHARM_TIME = 0x168, // extends the charm time only, no effect of charm chance MOD_REWARD_HP_BONUS = 0x16C, // Percent to add to reward HP healed. (364) - MOD_CHARM_CHANCE = 0x187, // extra chance to charm (light+apollo staff ect) + MOD_CHARM_CHANCE = 0x19B, // extra chance to charm (light&apollo staff etc) + MOD_REWARD_RECAST = 0x18C, // Time reduction to Reward recast // Bard + MOD_SONG_RECAST = 0x187, // Percent decrease to Bard Song Recast + MOD_SONG_CAST = 0x18F, // Percent decrease to Song Cast Time + MOD_SONG_DURATION = 0x1B3, // Song Duration % Modifier + MOD_SONG_EFFECTS = 0x1C8, // Additional # of Song Effects (Daurdabla) + MOD_ALL_SONGS = 0x1B4, // Increase to all songs + MOD_ETUDE = 0x1B5, + MOD_REQUIEM = 0x1B6, + MOD_VIRELAI = 0x1B7, + MOD_MARCH = 0x1B8, + MOD_HYMNUS = 0x1B9, + MOD_MADRIGAL = 0x1BA, + MOD_MINUET = 0x1BB, + MOD_CAROL = 0x1BC, + MOD_PAEON = 0x1BD, + MOD_MAMBO = 0x1BE, + MOD_LULLABY = 0x1BF, + MOD_BALLAD = 0x1C0, + MOD_MAZURKA = 0x1C1, + MOD_THRENODY = 0x1C2, + MOD_FINALE = 0x1C3, + MOD_MINNE = 0x1C4, + MOD_SCHERZO = 0x1C5, + MOD_ELEGY = 0x1C6, + MOD_PRELUDE = 0x1C7, // Ranger MOD_RECYCLE = 0x131, // Percent chance to recycle MOD_SNAP_SHOT = 0x16D, // Percent reduction to range attack delay MOD_RAPID_SHOT = 0x167, // Percent chance to proc rapid shot MOD_WIDESCAN = 0x154, + MOD_SHADOWBIND = 0x1D2, // Enables Shadowbind on next RA + MOD_BARRAGE = 0x1D3, // Barrage Shot Count Increase + MOD_DEAD_AIM = 0x237, // Critical Ranged Hit Dmg % Increase // Samurai MOD_ZANSHIN = 0x132, // Percent chance to counter + MOD_MEDITATE_DUR = 0x1B0, // Extends Meditate duration in secs // Ninja MOD_UTSUSEMI = 0x133, // Everyone's favorite --tracks shadows. MOD_NINJA_TOOL = 0x134, // Percent chance to not use a tool. - + MOD_STEALTH = 0x166, // Chance to remain undetected ?? + MOD_UTSUSEMI_CAST = 0x195, // Percent decrease to Utsusemi Cast Time + MOD_NINJUTSU_RECAST = 0x18A, // Percent decrease to Ninjutsu Spell Recast + MOD_PARRY_RATE = 0x22D, // Percent increase to parry rate. + // Dragoon MOD_JUMP_TP_BONUS = 0x169, // bonus tp player receives when using jump (must be divided by 10) MOD_JUMP_ATT_BONUS = 0x16A, // ATT% bonus for jump + high jump MOD_HIGH_JUMP_ENMITY_REDUCTION = 0x16B, // for gear that reduces more enmity from high jump + MOD_SPIRIT_JUMP_TP = 0x214, // bonus tp player receives when using spirit jump (must be divided by 10) + MOD_SPIRIT_JUMP_ATT = 0x215, // ATT% bonus for spirit jump + MOD_CONSERVE_TP = 0x236, // Proc rate for Conserve TP // Summoner MOD_AVATAR_PERPETUATION = 0x173, //stores base cost of current avatar MOD_WEATHER_REDUCTION = 0x174, //stores perpetuation reduction depending on weather - MOD_DAY_REDUCTION = 0x175, //stores perpetuation reduction depending on day + MOD_DAY_REDUCTION = 0x175, //stores perpetuation reduction depending on day MOD_PERPETUATION_REDUCTION = 0x15A, //stores the MP/tick reduction from gear - MOD_BP_DELAY = 0x165, //stores blood pact delay reduction + MOD_BP_DELAY = 0x165, //stores blood pact delay reduction + MOD_SUMMON_CAST = 0x192, // Percent decrease to Summoning Magic Cast Time + MOD_ELE_AVATAR_RECAST = 0x18B, // Percent decrease to Elemental Avatar Recast + MOD_BLOOD_BOON = 0x238, // Proc chance for Blood Boon // Blue Mage MOD_BLUE_POINTS = 0x135, // Tracks extra blue points + MOD_BLUE_RECAST = 0x189, // Percent decrease to Blue Spell Recast + MOD_BLUE_CAST = 0x196, // Percent decrease to Blue Magic Cast Time + MOD_BLUE_LEARN = 0x231, // Percent chance increase to learn Blue Magics // Corsair - MOD_DEDICATION = 0x136, // % exp gain - MOD_DEDICATION_CAP = 0x137, // Cap of dedicaiton effect - MOD_EXP_BONUS = 0x17E, - - MOD_PET_MABB = 0x138, // Tracks totals - MOD_PET_MACC = 0x139, // Tracks totals - MOD_PET_ATTP = 0x13A, // Tracks totals - MOD_PET_ACC = 0x13B, // Tracks totals MOD_DMG_REFLECT = 0x13C, // Tracks totals MOD_ROLL_ROGUES = 0x13D, // Tracks totals MOD_ROLL_GALLANTS = 0x13E, // Tracks totals @@ -367,15 +447,119 @@ MOD_BUST = 0x14C, // # of busts // Puppetmaster + // Dancer MOD_FINISHING_MOVES = 0x14D, // Tracks # of finishing moves + MOD_JIG_TIME = 0x1A6, // Additional duration of Jigs in secs + MOD_WALTZ_POTENCY = 0x1DD, // Additional potency of Waltzs + MOD_WALTZ_RCVD = 0x1DE, // Additional potency of Waltzs Recieved +// Scholar + MOD_SUBLIMATION_BONUS = 0x14E, // MP drain Mod for Sublimation charge. + MOD_LIGHT_ARTS_EFFECT = 0x1B2, + MOD_DARK_ARTS_EFFECT = 0x14F, + MOD_LIGHT_ARTS_SKILL = 0x150, + MOD_DARK_ARTS_SKILL = 0x151, + MOD_REGEN_EFFECT = 0x152, + MOD_REGEN_DURATION = 0x153, + MOD_HELIX_EFFECT = 0x22B, + MOD_HELIX_DURATION = 0x22C, + MOD_STORMSURGE_EFFECT = 0x22E, + MOD_BLACK_MAGIC_COST = 0x221, // MP cost for black magic (light/dark arts) + MOD_WHITE_MAGIC_COST = 0x222, // MP cost for white magic (light/dark arts) + MOD_BLACK_MAGIC_CAST = 0x223, // Cast time for black magic (light/dark arts) + MOD_WHITE_MAGIC_CAST = 0x224, // Cast time for black magic (light/dark arts) + MOD_BLACK_MAGIC_RECAST = 0x225, // Recast time for black magic (light/dark arts) + MOD_WHITE_MAGIC_RECAST = 0x226, // Recast time for white magic (light/dark arts) + MOD_ALACRITY_CELERITY_EFFECT = 0x227, // Bonus for celerity/alacrity effect + MOD_GRIMOIRE_RECAST = 0x19A, // Percent decrease to Spell Recasts under Light Arts and Dark Arts + MOD_GRIMOIRE_CAST = 0x190, // Percent decrease to Grimoire Cast Time + +// Pets / Avatars / Automatons / Wyverns + MOD_PET_MABB = 0x138, // Tracks totals + MOD_PET_MACC = 0x139, // Tracks totals + MOD_PET_MDEF = 0x1E8, + + MOD_PET_ATTP = 0x13A, // Tracks totals + MOD_PET_DEFP = 0x1E9, + MOD_PET_ACC = 0x13B, // Tracks totals + MOD_PET_RACC = 0x1EA, + MOD_PET_ATT = 0x1EB, + MOD_PET_RATT = 0x1EC, + MOD_PET_DEF = 0x1ED, + MOD_PET_EVA = 0x1EE, + + MOD_PET_HP = 0x1EF, + MOD_PET_HPP = 0x1F0, + MOD_PET_MP = 0x1F1, + + MOD_PET_HPHEAL = 0x1F2, + MOD_PET_MPHEAL = 0x1F3, + + MOD_PET_ENMITY = 0x1F4, + MOD_PET_BLD_PACT_DMG = 0x1F5, + MOD_PET_REGAIN = 0x1F6, + MOD_PET_REGEN = 0x1F7, + MOD_PET_REFRESH = 0x1F8, + MOD_PET_HASTE = 0x1F9, + MOD_PET_STORETP = 0x1FA, + MOD_PET_TPBONUS = 0x1FB, + + MOD_PET_DMG = 0x1FC, + MOD_PET_PPHYS_DMG = 0x1FD, + MOD_PET_MAG_DMG = 0x1FE, + MOD_PET_CRITRATE = 0x1FF, + + MOD_PET_BREATH_ACC = 0x200, + MOD_WYVERN_BREATH = 0x201, + MOD_PET_BREATH_DMG = 0x202, + MOD_WYVERN_SUBJOB = 0x216, + + MOD_PET_BMAG_SKL = 0x203, + MOD_PET_COMBAT_SKL = 0x204, + MOD_PET_MELEE_SKL = 0x205, + MOD_PET_WMAG_SKL = 0x206, + + MOD_PET_DBL_ATK = 0x207, + MOD_PET_COUNTER = 0x208, + MOD_PET_SPELL_TIME = 0x209, + MOD_PET_CONSERVE_MP = 0x20A, + MOD_PET_MP_COST = 0x20B, + MOD_PET_CURE_PTNCY = 0x20C, + MOD_PET_SUBTLE_BLOW = 0x217, + MOD_PET_FASTCAST = 0x218, + MOD_PET_SPELL_INT = 0x219, + + MOD_PET_STR = 0x20D, + MOD_PET_DEX = 0x20E, + MOD_PET_VIT = 0x20F, + MOD_PET_AGI = 0x210, + MOD_PET_INT = 0x211, + MOD_PET_MND = 0x212, + MOD_PET_CHR = 0x213, + +// Fellow + MOD_FELLOW_HP = 0x1DF, + MOD_FELLOW_MP = 0x1E0, + MOD_FELLOW_STR = 0x1E1, + MOD_FELLOW_DEX = 0x1E2, + MOD_FELLOW_VIT = 0x1E3, + MOD_FELLOW_AGI = 0x1E4, + MOD_FELLOW_INT = 0x1E5, + MOD_FELLOW_MND = 0x1E6, + MOD_FELLOW_CHR = 0x1E7, + + MOD_ENSPELL = 0x155, //stores the type of enspell active (0 if nothing) MOD_SPIKES = 0x156, //store the type of spike spell active (0 if nothing) MOD_ENSPELL_DMG = 0x157, //stores the base damage of the enspell before reductions MOD_SPIKES_DMG = 0x158, //stores the base damage of the spikes before reductions + MOD_ENSPELL_DURATION = 0x19D, //stores the additional duration time for enspell MOD_TP_BONUS = 0x159, + MOD_DEDICATION = 0x136, // % exp gain + MOD_DEDICATION_CAP = 0x137, // Cap of dedicaiton effect + MOD_EXP_BONUS = 0x17E, MOD_FIRE_AFFINITY = 0x15B, //stores the amount of elemental affinity (elemental staves mostly) @@ -392,8 +576,8 @@ MOD_ADDS_WEAPONSKILL = 0x163, MOD_ADDS_WEAPONSKILL_DYN = 0x164, - MOD_STEALTH = 0x166, - + MOD_CRYSTAL_DROP = 0x1D8, // Increase drop rate of Crystals (20 Max) + MOD_MAIN_DMG_RATING = 0x16E, //adds damage rating to main hand weapon (maneater/blau dolch etc hidden effects) MOD_SUB_DMG_RATING = 0x16F, //adds damage rating to off hand weapon MOD_REGAIN = 0x170, //auto regain TP (from items) | this is multiplied by 10 e.g. 20 is 2% TP @@ -408,31 +592,53 @@ MOD_DELAYP = 0x17C, //delay addition percent (does not affect tp gain) MOD_RANGED_DELAYP = 0x17D, //ranged delay addition percent (does not affect tp gain) - MOD_SHIELD_BASH = 0x181, - MOD_KICK_DMG = 0x182, // increases kick attack damage - MOD_WEAPON_BASH = 0x188, + MOD_ELEMENTAL_RECAST = 0x188, // Percent decrease to Elemental Spell Recast + + MOD_BLACK_CAST = 0x18D, // Percent decrease to Black Magic Cast Time + MOD_CURE_CAST = 0x18E, // Percent decrease to Cure Magic Cast Time + MOD_STONESKIN_CAST = 0x191, // Percent decrease to Stoneskin Cast Time + MOD_ELEMENTAL_CAST = 0x193, // Percent decrease to Elemental Magic Cast Time + MOD_HEALING_CAST = 0x194, // Percent decrease to Healing Magic Cast Time + MOD_ENHANCING_CAST = 0x197, // Percent decrease to Enhancing Magic Cast Time + MOD_ENFEEBLING_CAST = 0x198, // Percent decrease to Enfeebling Magic Cast Time + MOD_QUICK_MAGIC = 0x199, // Occasionally causes spells to cast instantly and 0 recast + + MOD_CHOCOBO_TIME = 0x19F, // Chocobo Riding Time Increase in Mins + + MOD_EAT_RAW_FISH = 0x1A0, // Allows the User to eat Raw Fish like a Mithra + MOD_EAT_RAW_MEAT = 0x1A1, // Allows the User to eat Raw Meat like a Galka + + MOD_QUADRUPLE_ATTACK = 0x1A5, // Percent chance + + MOD_SNEAK_DUR = 0x1A7, // Percent Increase + MOD_INVIS_DUR = 0x1A8, // Percent Increase + MOD_ENHANCING_DUR = 0x1A9, // Percent Increase + MOD_BARSPELL_DUR = 0x1AB, // Percent Increase duration Elemental Resistance Spells + MOD_BARSPELL_PWR = 0x1AC, // Power Increase Elemental Resistance Spells + MOD_DRAIN_ASPIR = 0x1AD, // Percent Increase + MOD_CURSNA_EFFECT = 0x1AE, // Percent Increase chance to remove DooM + MOD_CURSNA_RCVD = 0x1AF, // Percent Increase chance to remove DooM + + MOD_STONESKIN_HP = 0x1AA // Stoneskin + + + - MOD_BLACK_MAGIC_COST = 0x189, // MP cost for black magic (light/dark arts) - MOD_WHITE_MAGIC_COST = 0x18A, // MP cost for white magic (light/dark arts) - MOD_BLACK_MAGIC_CAST = 0x18B, // Cast time for black magic (light/dark arts) - MOD_WHITE_MAGIC_CAST = 0x18C, // Cast time for black magic (light/dark arts) - MOD_BLACK_MAGIC_RECAST = 0x18D, // Recast time for black magic (light/dark arts) - MOD_WHITE_MAGIC_RECAST = 0x18E, // Recast time for white magic (light/dark arts) - MOD_ALACRITY_CELERITY_EFFECT = 0x18F, // Bonus for celerity/alacrity effect - MOD_LIGHT_ARTS_EFFECT = 0x14E, - MOD_DARK_ARTS_EFFECT = 0x14F, - MOD_LIGHT_ARTS_SKILL = 0x150, - MOD_DARK_ARTS_SKILL = 0x151, - MOD_REGEN_EFFECT = 0x152, - MOD_REGEN_DURATION = 0x153, - MOD_HELIX_EFFECT = 0x154, - MOD_HELIX_DURATION = 0x155, - MOD_STORMSURGE_EFFECT = 0x190, - MOD_SUBLIMATION_BONUS = 0x191, - MOD_WYVERN_BREATH = 0x192 + // To save time finding the next mod to use.. + + //MOD_SPARE = 0x239; + //MOD_SPARE = 0x23A; + //MOD_SPARE = 0x23B; + //MOD_SPARE = 0x23C; + //MOD_SPARE = 0x23D; + //MOD_SPARE = 0x23E; + //MOD_SPARE = 0x23F; + //MOD_SPARE = 0x240; + + }; -#define MAX_MODIFIER 0x193 +#define MAX_MODIFIER 0x239 Index: src/map/npcentity.cpp =================================================================== --- src/map/npcentity.cpp (revision 3520) +++ src/map/npcentity.cpp (working copy) @@ -31,10 +31,10 @@ /************************************************************************ * * -* Таймер для закрывания дверей. * +* Timer to close the doors. * * * -* Вообще можно подумать о реализации универсального таймера для * -* изменения анимации NPC, а не только закрытия дверей. * +* In general, you can think about the implementation of the universal * +* timer changes animation NPC, and not just close the door. * * * ************************************************************************/ Index: src/map/npcentity.h =================================================================== --- src/map/npcentity.h (revision 3520) +++ src/map/npcentity.h (working copy) @@ -28,7 +28,7 @@ #include "../common/taskmgr.h" #include "baseentity.h" -int32 close_door(uint32 tick,CTaskMgr::CTask *PTask); // закрываем дверь +int32 close_door(uint32 tick,CTaskMgr::CTask *PTask); // close the door int32 reappear_npc(uint32 tick,CTaskMgr::CTask *PTask); // used for hideNPC lua function class CNpcEntity : public CBaseEntity @@ -39,8 +39,8 @@ uint32 unknown; uint8 name_prefix; - CNpcEntity(); // конструктор - ~CNpcEntity(); // деструктор + CNpcEntity(); // Designer + ~CNpcEntity(); // Destructor private: }; Index: src/map/packet_system.cpp =================================================================== --- src/map/packet_system.cpp (revision 3520) +++ src/map/packet_system.cpp (working copy) @@ -134,7 +134,7 @@ /************************************************************************ * * -* Отображения содержимого входящего пакета в консоли * +* Display the contents of the incoming packet to the console * * * ************************************************************************/ @@ -162,7 +162,7 @@ /************************************************************************ * * -* Неизвестный пакет * +* Unknown package * * * ************************************************************************/ @@ -174,7 +174,7 @@ /************************************************************************ * * -* Нереализованный пакет * +* unrealized package * * * ************************************************************************/ @@ -186,10 +186,10 @@ /************************************************************************ * * -* Вход в зону * +* Log into the zone * * * -* Обновляем sessionkey и порт клиента при каждом переходе между зонами * -* Мы должны оставлять правильный ключ при переходе с сервера на сервер * +* Update sessionkey and client port at each transition between zones * +* We need to keep the correct key when moving from server to server * * * ************************************************************************/ @@ -197,7 +197,7 @@ { WBUFL(data,(0x5C)) = 0; - bool firstlogin = false; // временное решение, до появления PlayTime + bool firstlogin = false; // temporary solution until PlayTime PChar->clearPacketList(); @@ -251,13 +251,23 @@ PChar->m_ZonesList[PChar->getZone() >> 3] |= (1 << (PChar->getZone()%8)); const int8* fmtQuery = "UPDATE accounts_sessions SET targid = %u, session_key = x'%s', server_addr = %u, client_port = %u WHERE charid = %u"; - + + if(PChar->id > 40000) // External Accounts are assigned much higher IDs. + { Sql_Query(SqlHandle,fmtQuery, PChar->targid, session_key, - PChar->loc.zone->GetIP(), + PChar->loc.zone->GetWANIP(), session->client_port, PChar->id); + } else { + Sql_Query(SqlHandle,fmtQuery, + PChar->targid, + session_key, + PChar->loc.zone->GetLANIP(), + session->client_port, + PChar->id); + } const int8* deathTsQuery = "SELECT death FROM char_stats where charid = %u;"; int32 ret = Sql_Query(SqlHandle,deathTsQuery, PChar->id); @@ -290,6 +300,8 @@ charutils::SaveCharPosition(PChar); charutils::SaveZonesVisited(PChar); + charutils::SavePlayTime(PChar); + PChar->pushPacket(new CDownloadingDataPacket()); PChar->pushPacket(new CZoneInPacket(PChar,EventID)); PChar->pushPacket(new CZoneVisitedPacket(PChar)); @@ -299,12 +311,12 @@ return; }; -/************************************************************************ -* * -* Пакет-запрос информации о персонаже. Приходит только во время * -* перехода между зонами / входа в игру (что почти одно и то же) * -* * -************************************************************************/ +/**************************************************************************** +* * +* Package request for information about a character. Comes only when * +* transition between zones / entry into the game (which is almost the same)* +* * +****************************************************************************/ void SmallPacket0x00C(map_session_data_t* session, CCharEntity* PChar, int8* data) { @@ -356,10 +368,10 @@ /************************************************************************ * * -* Персонаж покидает зону каким-либо из возможных способов. В случае * -* выхода из игры, текущая зона находится в переменной zone, во всех * -* остальных случаех в prevzone. Делаем соответствующую проверку для * -* правильного удаления персонажа их списка зоны. * +* Character leaves the area in any way possible. In the case of * +* exit the game, the current zone is in your zone, in all * +* in other sluchaeh prevzone. Making the appropriate test for * +* proper disposal of the character of the zone list. * * * ************************************************************************/ @@ -421,17 +433,17 @@ } if (PChar->PLinkshell != NULL) { - // удаляем персонажа из linkshell + // remove the character from the linkshell PChar->PLinkshell->DelMember(PChar); } CTaskMgr::getInstance()->AddTask(new CTaskMgr::CTask("close_session", gettick()+2500, session, CTaskMgr::TASK_ONCE, map_close_session)); } - else // проверка именно при покидании зоны, чтобы не делать двойную проверку при входе в игру + else // check it when leaving the area to do a double check at the entrance to the game { charutils::CheckEquipLogic(PChar, SCRIPT_CHANGEZONE, PChar->getZone()); } - // персонаж может отвалиться во время перехода между зонами, - // map_cleanup вызовет этот метод и zone персонажа будет NULL + // character can fall off during the transition between zones, + // map_cleanup calls this method and zone character will NULL if (PChar->loc.zone != NULL) { PChar->loc.zone->DecreaseZoneCounter(PChar); @@ -444,7 +456,7 @@ /************************************************************************ * * -* Запрос на список квестов и миссий, предметов и ключевых предметов * +* Request for a list of quests and missions, items and key items * * * ************************************************************************/ @@ -466,9 +478,9 @@ /************************************************************************ * * -* Первый пакет после входа в игру / перехода между зонами, является * -* подтверждением завершения перехода персонажа. * -* Привязываем экипированные предметы * +* The first packet after entering the game / transition between zones * +* is proof of completion of the transition of the character. * +* Tie items equipped, * * * ************************************************************************/ @@ -490,10 +502,10 @@ /************************************************************************ * * -* Перемещение персонажа (обновление позиции в зоне) * -* Обновление цели, выбранной персонажем, для правильного отображения * -* поворота головы. Из-за блуждания монстров необходимо проверять их * -* видимость постоянно, так же как и видимость питомцев * +* Move character (updated position in the area) * +* Update, in choosing a character to display correctly * +* head rotation. Because of the wandering monsters to check their * +* visibility of the time, as well as the appearance of pets * * * ************************************************************************/ @@ -539,11 +551,11 @@ return; } -/************************************************************************ -* * -* Клиент запрашивает информацию об NPC, для отображения их в событиях * -* * -************************************************************************/ +/**************************************************************************** +* * +* The client requests information about NPC, to display them in the events * +* * +****************************************************************************/ void SmallPacket0x016(map_session_data_t* session, CCharEntity* PChar, int8* data) { @@ -567,7 +579,7 @@ /************************************************************************ * * -* Kлиент сообщает серверу об ошибочном типе npc * +* Clients tells the server to the wrong type of npc * * * ************************************************************************/ @@ -583,8 +595,8 @@ /************************************************************************ * * -* Различные действия персонажа в игре: рыбалка, команды боя, общение * -* с npc и подобные * +* The various actions of the character in the game fishing, team * +* battle, communication and similar to the npc * * * ************************************************************************/ @@ -718,18 +730,18 @@ PChar->m_hasRaise = 0; } break; - case 0x0E: // рыбалка + case 0x0E: // fishing { fishingutils::StartFishing(PChar); } break; - case 0x0F: // смена цели во время боя + case 0x0F: // change targets in combat { PChar->PBattleAI->SetCurrentAction(ACTION_CHANGE_TARGET, TargID); PChar->PBattleAI->CheckCurrentAction(gettick()); } break; - case 0x10: // rangedattack + case 0x10: // ranged attack { PChar->PBattleAI->SetCurrentAction(ACTION_RANGED_START, TargID); PChar->PBattleAI->CheckCurrentAction(gettick()); @@ -762,7 +774,7 @@ break; case 0x13: // tractor menu { - // по любому, это работает неправильно. проблемный код в комментарии + // for anyone, it is not working properly. problem code in a comment //PChar->PBattleAI->SetCurrentAction(ACTION_RAISE_MENU_SELECTION); //PChar->PBattleAI->CheckCurrentAction(gettick()); @@ -782,7 +794,7 @@ */ } break; - case 0x14: // окончание обновления данных персонажа + case 0x14: // end update character { if (PChar->getZone() == 0) { @@ -815,7 +827,7 @@ /************************************************************************ * * -* Генерация World Pass * +* Generation World Pass * * * ************************************************************************/ @@ -829,9 +841,9 @@ /************************************************************************ * * -* Назначение пакета неизвестно, но начинает появляться при * -* использовании способностей, если у персонажа есть питомец. Возможно * -* клиент требует недостающие пакеты. * +* Purpose of the package is not known, but it is beginning to appear * +* in using the abilities, if a character has a pet. perhaps * +* client requires the missing packages. * * * ************************************************************************/ @@ -843,7 +855,7 @@ /************************************************************************ * * -* Удаление предметов из хранилищ * +* Removing items from storage * * * ************************************************************************/ @@ -873,7 +885,7 @@ /************************************************************************ * * -* Перемещение предметов между хранилищами * +* Moving objects between repositories * * * ************************************************************************/ @@ -921,18 +933,18 @@ uint32 NewQuantity = PItem->getQuantity() - quantity; - if(NewQuantity != 0) // делим пачку + if(NewQuantity != 0) // divide the pack { if (charutils::AddItem(PChar, ToLocationID, PItem->getID(), quantity) != ERROR_SLOTID) { charutils::UpdateItem(PChar, FromLocationID, FromSlotID, -(int32)quantity); } } - else // переносим всю пачку, или пытаемся объединить одинаковые предметы + else // transfer the entire stack, or trying to combine the same subjects { if (ToSlotID < 82) // 80 + 1 { - // объединение еще не реализовано + // the guild is not yet implemented ShowDebug("SmallPacket0x29: Trying to unite items\n", FromLocationID, FromSlotID); return; } @@ -950,19 +962,19 @@ { PChar->getStorage(FromLocationID)->InsertItem(NULL, FromSlotID); - PChar->pushPacket(new CInventoryItemPacket(NULL, FromLocationID, FromSlotID)); // убираем предмет из FormLocationID - PChar->pushPacket(new CInventoryItemPacket(PItem, ToLocationID, NewSlotID)); // добавляем предмет в ToLocationID + PChar->pushPacket(new CInventoryItemPacket(NULL, FromLocationID, FromSlotID)); // remove the item from the FormLocationID + PChar->pushPacket(new CInventoryItemPacket(PItem, ToLocationID, NewSlotID)); // add the item to the ToLocationID } - else // в случае ошибки отменяем перемещение предмета + else // in case of error cancel moving object { - PChar->getStorage(ToLocationID)->InsertItem(NULL, NewSlotID); // убираем предмет - PChar->getStorage(FromLocationID)->InsertItem(PItem, FromSlotID); // возвращаем предмет (для обновления Location и Slot предмета) + PChar->getStorage(ToLocationID)->InsertItem(NULL, NewSlotID); // remove item + PChar->getStorage(FromLocationID)->InsertItem(PItem, FromSlotID); // Returned items (to update the Location and Slot item) } } else { - // клиент не позволяет перемещать предмет в полный контейнер. - // если мы видим это сообщение, значит данные клиента и сервера различаются + // the client does not allow you to move the object in a full container. + // If we see this message, it means the data server and client are different // Client thinks that ToLocationID is NOT full, so lets send those packets again and tell them it is! uint8 size = PChar->getStorage(ToLocationID)->GetSize(); for(uint8 slotID = 0; slotID <= size; ++slotID) @@ -985,7 +997,7 @@ /************************************************************************ * * -* Запрос начала обмена между персонажами (trade) * +* Request early exchange between characters (trade) * * * ************************************************************************/ @@ -1027,7 +1039,7 @@ /************************************************************************ * * -* Запрос начала обмена между персонажами (trade) * +* Request early exchange between characters (trade) * * * ************************************************************************/ @@ -1043,13 +1055,13 @@ { case 0x00: // request accepted { - // цели обмена у персонажей соответствующие + // purpose of exchange of the characters corresponding if (PChar->TradePending.id == PTarget->id && PTarget->TradePending.id == PChar->id) { - // контейнеры у персонажей свободны + // containers of the characters are free if (PChar->UContainer->IsContainerEmpty() && PTarget->UContainer->IsContainerEmpty()) { - // между персонажами соответствующая дистанция + // corresponding to the distance between the characters if (distance(PChar->loc.p, PTarget->loc.p) < 6) { PChar->UContainer->SetType(UCONTAINER_TRADE); @@ -1069,10 +1081,10 @@ break; case 0x01: // trade cancelled { - // цели обмена у персонажей соответствующие + // purpose of exchange of the characters corresponding if (PChar->TradePending.id == PTarget->id && PTarget->TradePending.id == PChar->id) { - // контейнер у цели зарезервирован для обмена + // the target container is reserved for exchange if (PTarget->UContainer->GetType() == UCONTAINER_TRADE) { PTarget->TradePending.clean(); @@ -1090,13 +1102,13 @@ break; case 0x02: // trade accepted { - // цели обмена у персонажей соответствующие + // purpose of exchange of the characters corresponding if (PChar->TradePending.id == PTarget->id && PTarget->TradePending.id == PChar->id) { PChar->UContainer->SetLock(); PTarget->pushPacket(new CTradeActionPacket(PChar, action)); - // совершаем обмен предметами в контейнерах персонажей + // make an exchange items in containers characters if (PTarget->UContainer->IsLocked()) { if (charutils::CanTrade(PChar, PTarget) && charutils::CanTrade(PTarget, PChar)) @@ -1109,8 +1121,8 @@ } else { - // обмен не состоялся: - // недостаточно места в контейнере одного или обоих персонажей + // exchange did not take place: + // not enough space in the container of one or both characters // or // rare item in the exchange is owned by the recipient @@ -1133,7 +1145,7 @@ /************************************************************************ * * -* Заполняем ячейки окошка trade (обмен между персонажами) * +* Fill the cell window trade (the exchange between the characters) * * * ************************************************************************/ @@ -1153,7 +1165,7 @@ // We used to disable Rare/Ex items being added to the container, but that is handled properly else where now if (PItem != NULL && PItem->getID() == itemID) { - // если количество предметов равно нулю, то удаляем предмет из контейнера + // if the number of items is equal to zero, then remove the object from the container PItem->setReserve(quantity); PChar->UContainer->SetItem(tradeSlotID, quantity > 0 ? PItem : NULL); @@ -1166,7 +1178,7 @@ /************************************************************************ * * -* Передача предметов NPC (команда обмен - "trade") * +* Item History NPC (team sharing - "trade") * * * ************************************************************************/ @@ -1216,7 +1228,7 @@ /************************************************************************ * * -* Использование предметов * +* use of items * * * ************************************************************************/ @@ -1232,7 +1244,7 @@ { if (PItem->getType() & ITEM_ARMOR) { - //TODO: если ITEM_LOCKED, то должна быть проверка на то, что предмет экипирован + //TODO: if ITEM_LOCKED, it should be to check that the item equipped } else if (PItem->getSubType() & ITEM_LOCKED) { @@ -1258,9 +1270,9 @@ /************************************************************************ * * -* Сортировка инвентаря * -* Жестокий алгоритм, но лучшего для неупорядоченного массива не найдем * -* 80 - ячеек. Минимальное количество проверок - 80, максимальное 3240 * +* sorting equipment * +* Brutal algorithm, but better for the disordered array will not find * +* 80 - cells. The minimum number of inspections - 80, 3240 the maximum * * * ************************************************************************/ @@ -1326,8 +1338,8 @@ /************************************************************************ * * -* Вероятно сообщение о недополучении каких-либо инициализирующих * -* пакетов для монстров, npc или других игроков. всегда пустое. * +* Probably reported shortfall of any initialization * +* packages for the monsters, npc or other players. always empty. * * * ************************************************************************/ @@ -1339,7 +1351,7 @@ /************************************************************************ * * -* Персонаж голосует за предмет в TreasurePool * +* Character vote for the subject in TreasurePool * * * ************************************************************************/ @@ -1355,7 +1367,7 @@ /************************************************************************ * * -* Персонаж отказывается от предмета в TreasurePool * +* Character of the subject refuses to TreasurePool * * * ************************************************************************/ @@ -1371,9 +1383,9 @@ /************************************************************************ * * -* Отправляем приветственное сообщение сервера. * -* По умолчанию появится сообщение <<< Welcome to "server name" >>> + * -* можно отправить дополнительные строки информации в размере 230 байт * +* We send a welcome message server. * +* By default, the message <<< Welcome to "server name" >>> + * +* You can send additional information line at a rate of 230 bytes * * * ************************************************************************/ @@ -1385,7 +1397,7 @@ /************************************************************************ * * -* Все действия с Delivery Box * +* All actions with Delivery Box * * * ************************************************************************/ @@ -1398,28 +1410,28 @@ ShowDebug(CL_CYAN"DeliveryBox Action (%02hx)\n" CL_RESET, RBUFB(data,(0x04))); PrintPacket(data); - // 0x01 - отправка клиенту старых предметов - // 0x02 - добавление предметов в список отправляемых (подготовка к отправке) - // 0x03 - подтверждение отправки (отправляем предметы) - // 0x04 - возврат неправильно отправленного предмета (отмена выполненной отправки) - // 0x05 - отправка клиенту количества новых предметов - // 0x06 - отправка клиенту новых предметов + // 0x01 - sending client older subjects + // 0x02 - adding items to the list sent by (preparing to send) + // 0x03 - send confirmation (sent items) + // 0x04 - return wrong item sent (cancellation made ​​sending) + // 0x05 - sending the client the number of new items + // 0x06 - sending customers new items // 0x07 - removes a delivered item from sending box - // 0x08 - обновление предмета в ячейке перед удалением - // 0x09 - вернуть предмет отправителю - // 0x0a - взять предмет из ячейки - // 0x0b - удаление предмета из ячейки - // 0x0c - подтверждение введенного имени в окне отправки - // 0x0d - открытие окна отправки почты - // 0x0e - открытие окна приема почты - // 0x0f - закрытие окна почты + // 0x08 - Update item in the cell before removing + // 0x09 - return the item to the sender + // 0x0a - take an object from a cell + // 0x0b - remove the item from the cell + // 0x0c - confirmation of the name entered in the Send window + // 0x0d - opening a window to send mail + // 0x0e - opening a window to receive mail + // 0x0f - closing windows mail switch (action) { case 0x01: { - // отправляем персонажу старые предметы (предметы, которые персонаж уже видел в delivery box) - // все старые предметы расположены в ячейках 0-7 + // Send character to old items (items that characters already seen in delivery box) + // All items are located in the old cells 0-7 if (boxtype == 0x01) @@ -1629,9 +1641,9 @@ } case 0x05: { - // отправляем персонажу количество новых предметов (предметы, которые персонаж еще не видел в delivery box) - // все новые предметы помещаются в контейнет начиная со значения 8 - // перемещаем новые предметы в свободные ячейки delivery box + // Send the character of the new items (items that the character has not seen in a delivery box) + // All new items are placed in konteynet starting at 8 + // Move the new items free cell delivery box if (PChar->UContainer->GetType() != UCONTAINER_DELIVERYBOX) return; @@ -1688,17 +1700,17 @@ case 0x06: case 0x08: { - // 0x08 и 0x06 идентичны + // 0x08 and 0x06 are identical // - // 0х06 - добавляем предмет в определенную ячейку - // 0х08 - обновляем предмет в определенной ячейке + // 0х06 - adds an item to a specific cell + // 0х08 - Updates item in a particular cell - // отправляем персонажу все новые предметы (предметы, которые персонаж еще не видел в delivery box) - // клиент отправляет запрос серверу для каждого нового предмета, при этом указывая, какая ячейка его интересует + // Send a character all new items (items that the character has not seen in a delivery box) + // The client sends a request to the server for each new object, in this case indicating which cell he is interested // - // сервер должен отправлять два пакета с действием 0х06 - // у первого пакета data[0x0c] равняется 0x02, у второго 0x01, в остальном заголовок идентичен - // возможно это связано с тем, что я сам отправлял себе предметы + // Server is to send two packages to the action 0x06 + // In the first packet data [0x0c] is equal to 0x02, the second 0x01, otherwise identical to the title + // Perhaps this is due to the fact that I did send yourself items // // 0x4b 0x2c 0x00 0x00 0x06 0x01 0x01 0x01 0xff 0xff 0xff 0xff 0x02 0x01 0xff 0xff // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 @@ -1706,8 +1718,8 @@ // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 // - // зачем нужен этот пустой пакет я не знаю, но и без него все отлично работает - // предположительно он отчищает целевую ячейку от предметов, на всякий случай + // Why do I need this empty package I do not know, but without it everything works fine + // Presumably it cleans the target cell from the objects, just in case if (PChar->UContainer->GetType() == UCONTAINER_DELIVERYBOX && !PChar->UContainer->IsSlotEmpty(slotID)) @@ -1886,7 +1898,7 @@ } case 0x0B: // Option: Drop { - // удаление предмета из ячейки + // Remove the object from memory if (PChar->UContainer->GetType() == UCONTAINER_DELIVERYBOX && !PChar->UContainer->IsSlotEmpty(slotID)) @@ -1997,7 +2009,7 @@ break; } - // отправка простых действий - открыть окно почты, закрыть окно почты + // Send simple steps - open the email, close the mail PChar->pushPacket(new CDeliveryBoxPacket(action, 0)); return; @@ -2005,7 +2017,7 @@ /************************************************************************ * * -* Все действия с Auction House * +* All the action from the Auction House * * * ************************************************************************/ void SmallPacket0x04E(map_session_data_t* session, CCharEntity* PChar, int8* data) @@ -2019,14 +2031,15 @@ ShowDebug(CL_CYAN"AH Action (%02hx)\n" CL_RESET, RBUFB(data,(0x04))); - // 0x04 - продажа предмета - // 0x05 - похоже, что в ответ на этот пакет мы можем открыть список продаж или предложить персонажу подождать немного - // 0x0A - получение списка продаваемых персонажем предметов - // 0x0B - подтверждение покупки - // 0x0E - покупка предмета - // 0x0С - отмена продажи - // 0x0D - обновление списка продаваемых персонажем предметов + // 0x04 - Sale of + // 0x05 - it seems that the answer to this package, we can open a list of sales or offer to wait a little character + // 0x0A - get a list of items sold by character + // 0x0B - proof of purchase + // 0x0E - Item Purchase + // 0x0С - cancellation of sale + // 0x0D - updating the list of items sold by character + switch(action) { case 0x04: @@ -2261,7 +2274,7 @@ /************************************************************************ * * -* Смена экипировки * +* Change of equipment * * * ************************************************************************/ @@ -2284,7 +2297,7 @@ /************************************************************************ * * -* Завершение синтеза * +* Completion of the synthesis * * * ************************************************************************/ @@ -2296,17 +2309,18 @@ /************************************************************************ * * -* Обновляем карты conquest, besieged, compaing * +* Update map conquest, besieged, compaing * * * ************************************************************************/ void SmallPacket0x05A(map_session_data_t* session, CCharEntity* PChar, int8* data) { + // Refresh the amount of conquest points the player has to correctly reflect on the map. PChar->pushPacket(new CConquestPacket(PChar)); PChar->pushPacket(new CCampaingPacket(PChar,0)); PChar->pushPacket(new CCampaingPacket(PChar,1)); - // пакет не на своем месте, возможно 0x0F + // the package is not in place, may 0x0F PChar->pushPacket(new CStopDownloadingPacket(PChar)); // luautils::CheckForGearSet(PChar); // also check for gear set return; @@ -2314,7 +2328,7 @@ /************************************************************************ * * -* Завершаем или обновляем текущее событие * +* Finish or update event * * * ************************************************************************/ @@ -2338,8 +2352,8 @@ /************************************************************************ * * -* Завершаем или обновляем текущее событие * -* Так же требуется обновить позицию персонажа * +* Finish or update event * +* Just want to update the position of the character * * * ************************************************************************/ @@ -2367,7 +2381,7 @@ /************************************************************************ * * -* Эмоции персонажей, включая специфические (/jobemote [job]) * +* Emotions of characters, including specific (/jobemote [job]) * * * ************************************************************************/ @@ -2385,7 +2399,7 @@ /************************************************************************ * * -* Перемещение персонажа между зонами (zoneline) * +* Move your character between areas (zoneline) * * * ************************************************************************/ @@ -2428,13 +2442,13 @@ uint32 zoneLineID = RBUFL(data,(0x04)); //TODO: verify packet in adoulin expansion - uint8 town = RBUFB(data,(0x16)); // используются при выходе из mog house - uint8 zone = RBUFB(data,(0x17)); // используются при выходе из mog house + uint8 town = RBUFB(data,(0x16)); // used when exiting the mog house + uint8 zone = RBUFB(data,(0x17)); // used when exiting the mog house - // переход между зонами с использованием таблицы zoneline + // transition between areas with tables zoneline // - // игнорируем все zoneline пакеты, - // пока не завершен текущий переход + // ignore all packets zoneline, + // not yet completed the current transition if (PChar->status == STATUS_NORMAL || PChar->status == STATUS_UPDATE) @@ -2444,9 +2458,9 @@ zoneLine_t* PZoneLine = PChar->loc.zone->GetZoneLine(zoneLineID); - if (PZoneLine == NULL) // разворачиваем персонажа на 180° и отправляем туда, откуда пришел + if (PZoneLine == NULL) // we develop the character by 180 ° and send back where you came from { - ShowError(CL_RED"SmallPacket0x5E: Zone line %u not found\n" CL_RESET, zoneLineID); // в идеале нужно добавить зону и координаты + ShowError(CL_RED"SmallPacket0x5E: Zone line %u not found\n" CL_RESET, zoneLineID); // Ideally, you want to add a zone and coordinates PChar->loc.p.rotation += 128; @@ -2456,7 +2470,7 @@ PChar->status = STATUS_UPDATE; return; }else{ - if (zoneutils::GetZone(PZoneLine->m_toZone)->GetIP() == 0) // разворачиваем персонажа на 180° и отправляем туда, откуда пришел + if (zoneutils::GetZone(PZoneLine->m_toZone)->GetLANIP() == 0 || zoneutils::GetZone(PZoneLine->m_toZone)->GetWANIP() == 0) // we develop the character by 180 ° and send back where you came from { ShowDebug(CL_CYAN"SmallPacket0x5E: Zone %u closed to chars\n" CL_RESET, PZoneLine->m_toZone); @@ -2473,7 +2487,7 @@ { uint16 prevzone = PChar->loc.prevzone; - if (zone != 0) // 0 - выход в предыдущую зону, остальные значения - выбор зоны по имени + if (zone != 0) // 0 - return to the previous area, the other values ​​- Select a named { switch (town) { @@ -2500,7 +2514,7 @@ /************************************************************************ * * -* Персонаж присылает текстовую информацию для продолжения события * +* Character sends text information to continue the event * * * ************************************************************************/ @@ -2536,7 +2550,7 @@ /************************************************************************ * * -* Завершение раскопок chocobo (chocobo gigging) * +* Completion of excavation chocobo (chocobo digging) * * * ************************************************************************/ @@ -2547,7 +2561,7 @@ /************************************************************************ * * -* Помечаем KeyItem как "увиденный" * +* KeyItem mark as "seen" * * * ************************************************************************/ @@ -2562,7 +2576,7 @@ /************************************************************************ * * -* Окончание рыбалки * +* End of fishing * * * ************************************************************************/ @@ -2579,7 +2593,7 @@ /************************************************************************ * * -* Персонаж приглашает другого персонажа в группу * +* Character invites another character in the group * * * ************************************************************************/ @@ -2588,7 +2602,7 @@ uint32 charid = RBUFL(data,0x04); uint16 targid = RBUFW(data,0x08); - // Персонаж не должен приглашать сам себя. + // Character should not invite himself. if (PChar->id == charid) return; @@ -2601,7 +2615,7 @@ if (PChar->PParty == NULL || PChar->PParty->GetLeader() == PChar) { - // если targid персонажа клиенту не известен, то получаем его из таблицы активных сессий + // if targid character client is not known, then we get it from the table of active sessions if (targid == 0) { int32 ret = Sql_Query(SqlHandle, "SELECT targid FROM accounts_sessions WHERE charid = %u LIMIT 1", charid); @@ -2666,7 +2680,7 @@ /************************************************************************ * * -* Персонаж покидает группу * +* Character leaves the group * * * ************************************************************************/ @@ -2707,7 +2721,7 @@ /************************************************************************ * * -* Лидер распускает группу * +* The leader of the group disbands * * * ************************************************************************/ @@ -2732,7 +2746,7 @@ /************************************************************************ * * -* Удаляем члена группы или linckshell * +* Remove a group member or linkshell * * * ************************************************************************/ @@ -2775,7 +2789,7 @@ /************************************************************************ * * -* Персонаж отвечает на приглашение в группу * +* Characters respond to an invitation to the group * * * ************************************************************************/ @@ -2856,7 +2870,7 @@ /************************************************************************ * * -* Персонаж запрашивает информацию о членах группы * +* A character asks for information about the members of the group * * * ************************************************************************/ @@ -2927,7 +2941,7 @@ /************************************************************************ * * -* Запрос перед поиском членов группы * +* Ask before finding members * * * ************************************************************************/ @@ -2939,7 +2953,7 @@ /************************************************************************ * * -* Покупка предмета в магазине * +* Purchase items in the store * * * ************************************************************************/ @@ -2949,7 +2963,7 @@ uint8 shopSlotID = RBUFB(data,(0x0A)); uint16 itemID = PChar->Container->getItemID(shopSlotID); - uint32 price = PChar->Container->getQuantity(shopSlotID); // здесь мы сохранили стоимость предмета + uint32 price = PChar->Container->getQuantity(shopSlotID); // Here we have kept the value of the subject CItem* gil = PChar->getStorage(LOC_INVENTORY)->GetItem(0); @@ -2973,9 +2987,9 @@ /************************************************************************ * * -* Оценка стоимости предмета перед продажей в магазин * -* Помещаем информацию о продаваемом предмете в последнюю ячейку * -* контейнера * +* Evaluation value of the subject prior to the sale in the shop * +* Put the information on to sell items to the last cell * +* container * * * ************************************************************************/ @@ -2990,7 +3004,7 @@ (PItem->getID() == itemID) && !(PItem->getFlag() & ITEM_FLAG_NOSALE) ) { - // подготавливаем предмет для продажи + // prepare the item for sale PChar->Container->setItem(16, itemID, slotID, quantity); PChar->pushPacket(new CShopAppraisePacket(slotID, PItem->getBasePrice())); } @@ -2999,9 +3013,9 @@ /************************************************************************ * * -* Продажа предмета в магазин * -* Информация о продаваемом предмете была предварительно сохранена в * -* последней (16-ой) ячейке контейнера в 0x084-ом пакете * +* Sale of the store * +* Information of valuables was previously stored in the * +* the last (16th) in the cell container 0x084-th package * * * ************************************************************************/ @@ -3022,15 +3036,15 @@ PChar->pushPacket(new CMessageStandardPacket(0, itemID, quantity, 232)); PChar->pushPacket(new CInventoryFinishPacket()); } - // очищаем ячейку для безопасности (защита от группы 0x085-ых пакетов) + // clear the box for security (protection from the group's 0x085-packages) PChar->Container->setItem(16,0,-1,0); return; } /************************************************************************ * * -* Начало синтеза * -* В нулевой ячейке будет храниться кристалл * +* Home synthesis * +* In the zero cell is stored crystal * * * ************************************************************************/ @@ -3100,7 +3114,7 @@ /************************************************************************ * * -* Генерация случайного числа (команда /diceroll) * +* Generate a random number (command / diceroll) * * * ************************************************************************/ @@ -3114,10 +3128,17 @@ /************************************************************************ * * -* Отправляем персонажу список продаваемых гильдией предметов * +* Buy an item from a guild * * * ************************************************************************/ + +/************************************************************************ +* * +* Send the character to the list of items sold by the guild * +* * +************************************************************************/ + void SmallPacket0x0AB(map_session_data_t* session, CCharEntity* PChar, int8* data) { if (PChar->PGuildShop != NULL) @@ -3163,7 +3184,7 @@ /************************************************************************ * * -* Отправляем персонажу список покупаемых гильдией предметов * +* Send the character to the list of items purchased by the guild * * * ************************************************************************/ @@ -3178,7 +3199,7 @@ /************************************************************************ * * -* Текстовое общение между персонажами (chat) * +* Text communication between characters (chat) * * * ************************************************************************/ @@ -3253,69 +3274,81 @@ /************************************************************************ * * -* Текстовое общение между персонажами /tell * +* Text communication between characters /tell * * * ************************************************************************/ void SmallPacket0x0B6(map_session_data_t* session, CCharEntity* PChar, int8* data) { - if(jailutils::InPrison(PChar)) + string_t RecipientName = data+5; + string_t message = data+20; + ShowNotice(CL_RED"SENDING MESSAGE %s TO PLAYER %s FROM PLAYER %s\n" CL_RESET,message.c_str(),RecipientName.c_str(),PChar->GetName()); + if(jailutils::InPrison(PChar)) { + ShowNotice(CL_GREEN"SENDING MESSAGE: TO SENDER JAIL\n" CL_RESET); PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 0, 316)); return; } + CCharEntity* PTargetChar = zoneutils::GetCharByName(data+5); + if(PTargetChar != NULL ) + { + ShowNotice(CL_GREEN"SENDING MESSAGE IS NOT NULL OK TO SEND\n" CL_RESET); + if (PTargetChar->nameflags.flags == FLAG_AWAY) + { + ShowNotice(CL_GREEN"SENDING MESSAGE: RECEIVER HAS AWAY FLAG SET TELL SENDER\n" CL_RESET); + PChar->pushPacket(new CMessageStandardPacket(PChar, 0, 0, 181)); + return; + } + if( PTargetChar->status != STATUS_DISAPPEAR) + { + ShowNotice(CL_GREEN"SENDING MESSAGE: RECEIVER IS NOT ZONING SEND MESSAGE OK\n" CL_RESET); + PTargetChar->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL,data+20 )); + return; + } + else + { + ShowNotice(CL_GREEN"SENDING MESSAGE: RECEIVER IS ZONEING TELL SENDER\n" CL_RESET); + PChar->pushPacket(new CMessageStandardPacket(PChar, 0, 0, 125)); + return; + } + return; + } + else + { - string_t RecipientName = data+5; + ShowNotice(CL_GREEN"SENDING MESSAGE: DO A FULL SWEEP\n" CL_RESET); + map_session_list_t::iterator it = map_session_list.begin(); + while(it != map_session_list.end()) + { + map_session_data_t* map_session_data = it->second; + CCharEntity* PCharInMog = map_session_data->PChar; + if(PCharInMog!=NULL) + { + ShowNotice(CL_GREEN"SENDING MESSAGE: PLAYER IS NOT NULL\n" CL_RESET); + PTargetChar = PCharInMog; + PCharInMog->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL,data+20 )); + break; + } + else + { + ShowNotice(CL_GREEN"SENDING MESSAGE: RECEIVER IS NOT ONLINE TELL SENDER\n" CL_RESET); + PChar->pushPacket(new CMessageStandardPacket(PChar, 0, 0, 125)); + break; + } + ++it; + } + + + return; + } + - const int8* Query = "SELECT charid, targid, pos_zone FROM chars INNER JOIN accounts_sessions USING(charid) WHERE charname = '%s' LIMIT 1"; - - int32 ret = Sql_Query(SqlHandle, Query, RecipientName.c_str()); - - if (ret != SQL_ERROR && - Sql_NumRows(SqlHandle) != 0 && - Sql_NextRow(SqlHandle) == SQL_SUCCESS) - { - uint32 CharID = (uint32)Sql_GetUIntData(SqlHandle,0); - uint16 TargID = (uint16)Sql_GetUIntData(SqlHandle,1); - uint16 ZoneID = (uint16) Sql_GetUIntData(SqlHandle,2); - - CCharEntity* PTellRecipient = (CCharEntity*)zoneutils::GetZone(ZoneID)->GetEntity(TargID, TYPE_PC); - - if(PTellRecipient==NULL && ZoneID==0){//in a moghouse, do a full sweep - map_session_list_t::iterator it = map_session_list.begin(); - while(it != map_session_list.end()) - { - map_session_data_t* map_session_data = it->second; - CCharEntity* PChar = map_session_data->PChar; - if(PChar!=NULL && PChar->id == CharID){ - PTellRecipient = PChar; - break; - } - ++it; - } - } - - if (PTellRecipient != NULL && - PTellRecipient->id == CharID && - PTellRecipient->status != STATUS_DISAPPEAR && - !jailutils::InPrison(PTellRecipient)) - { - if (PTellRecipient->nameflags.flags & FLAG_AWAY) - { - PChar->pushPacket(new CMessageStandardPacket(PChar, 0, 0, 181)); - return; - } - PTellRecipient->pushPacket(new CChatMessagePacket(PChar, MESSAGE_TELL, data+20)); - return; - } - } - PChar->pushPacket(new CMessageStandardPacket(PChar, 0, 0, 125)); - return; + return; } /************************************************************************ * * -* Меняем режим получения опыта и усиливаем/ослабляем merits * +* Change the mode to gain experience and strengthen / weaken merits * * * ************************************************************************/ @@ -3326,7 +3359,7 @@ switch(RBUFB(data,(0x04))) { - case 2: // изменение mode + case 2: // change mode { // TODO: you can switch mode anywhere except in besieged & under level restriction if (Sql_Query(SqlHandle, "UPDATE char_exp SET mode = %u WHERE charid = %u", operation, PChar->id) != SQL_ERROR) @@ -3338,11 +3371,11 @@ break; case 3: // изменение merit { - if (PChar->getZone() == 0) // все операции обрабатываются только в moghouse + if (PChar->getZone() == 0) // All transactions are processed only moghouse { MERIT_TYPE merit = (MERIT_TYPE)(RBUFW(data,(0x06)) << 1); - if (PChar->PMeritPoints->IsMeritExist(merit)) // проверяем присланный персонажем id + if (PChar->PMeritPoints->IsMeritExist(merit)) // check sent to the character id { switch (operation) { @@ -3384,7 +3417,7 @@ /************************************************************************ * * -* Создание жемчужины (Pearl) экипированной LinkShell * +* Creating Pearl (Pearl) Equipped LinkShell * * * ************************************************************************/ @@ -3410,7 +3443,7 @@ /************************************************************************ * * -* Создание и экипировка LinkShell * +* Creating and equipping LinkShell * * * ************************************************************************/ @@ -3423,7 +3456,7 @@ if (PItemLinkshell != NULL && (PItemLinkshell->getType() & ITEM_LINKSHELL)) { - if (PItemLinkshell->getID() == 512) // создание новой linkshell + if (PItemLinkshell->getID() == 512) // creation of a new linkshell { uint32 LinkshellID = 0; uint16 LinkshellColor = RBUFW(data,(0x04)); @@ -3433,7 +3466,7 @@ DecodeStringLinkshell(data+8, DecodedName); EncodeStringLinkshell(DecodedName, EncodedName); - // TODO: проверить имя на необходимость добавления окончания строки + // TODO: check the name of the need to add a line break if (LinkshellID = linkshell::RegisterNewLinkshell(DecodedName, LinkshellColor)) // здесь дейтсвительно присваивание { @@ -3521,7 +3554,7 @@ /************************************************************************ * * -* Отображаем членов группы на карте * +* Display the members of the group on the map * * * ************************************************************************/ @@ -3565,7 +3598,7 @@ /************************************************************************ * * -* Отправляем жалобу GM'y * +* Send the complaint to GM * * help desk -> i want to report -> yes -> yes -> execute * * * ************************************************************************/ @@ -3577,8 +3610,8 @@ /************************************************************************ * * -* Установка разных nameFlags: party, away, autogroup, * -* флаги в help desk и т.д. * +* installation of all nameFlags: party, away, autogroup, * +* flags help desk etc. * * * ************************************************************************/ @@ -3619,7 +3652,7 @@ /************************************************************************ * * -* Устанавливаем предпочтительный язык общения * +* Set the preferred language of communication * * * ************************************************************************/ @@ -3631,7 +3664,7 @@ /************************************************************************ * * -* Проверяем монстров или персонажей * +* Check monsters or characters * * * * 170 - seems It seems to have high evasion and defense. * * 171 - seems It seems to have high evasion. * @@ -3682,9 +3715,9 @@ uint8 MessageValue = 0; - // TODO: Логическая ошибка использовать exp для определения сложности боя - // необходимы условия, основанные на разницах уровня - // не стоит забывать, что эта разница увеличивается с ростом уровня персонажа + // TODO: The logical fallacy to use for determining the complexity exp battle + // necessary conditions, based on the level difference + // do not forget that this difference increases with the level of character if (baseExp >= 400) MessageValue = 0x46; else if (baseExp >= 240) MessageValue = 0x45; @@ -3730,8 +3763,8 @@ /************************************************************************ * * -* Устанавливаем сообщене bazaar * -* Буфера в 256 байт вполне достаточно для преобразования 120 байт * +* Sets the message bazaar * +* Buffer of 256 bytes is sufficient to convert the 120 bytes * * * ************************************************************************/ @@ -3749,9 +3782,9 @@ /************************************************************************ * * -* Комментарий, отображаемый в списке поиска * -* Не уверен насчет необходимости удаления пробелов в конце строки, * -* об их назначении мы узнаем лишь после реализации поиска * +* Comment to be displayed in the search list * +* Not sure about the need to remove trailing spaces, * +* Their appointment we learn only after the implementation of search * * * ************************************************************************/ @@ -3762,8 +3795,8 @@ PChar->search.messagetype = RBUFB(data,(0xA4)); - // в ответ на этот пакет не нужно посылать что-либо клиенту - // эта информация используется лишь при поиске персонажа + // in response to this package does not need to send anything to the client + // This information is only used when searching for a character // s a l u t //e0 4c c2 00 73 61 6c 75 74 20 20 20 20 20 20 20 @@ -3777,8 +3810,8 @@ //00 00 00 00 2f 15 4c 4b 57 49 4e 08 3f 00 00 00 //ff 00 00 00 11 00 00 00 - // сообщение максимум 120, 3 строки по 40 символов, идущие подряд, начиная с 5-го байта - // тип сообщения - 4й байт с конца + // Post a maximum of 120, 3 lines of 40 characters, consecutive, starting from the 5th byte + // type of message - 4th byte from the end //EXP party //0x11 - seek party @@ -3811,7 +3844,7 @@ /************************************************************************ * * -* Отправляем персонажу приветственное сообщение LinkShell (/lsmes) * +* Send the character to the welcome message LinkShell (/lsmes) * * * ************************************************************************/ @@ -3826,7 +3859,7 @@ /************************************************************************ * * -* Обновление преветственного cообщения LinkShell * +* Update prevetstvennogo Ups LinkShell * * * ************************************************************************/ @@ -3836,14 +3869,14 @@ if (PChar->PLinkshell != NULL && (PItemLinkshell != NULL && (PItemLinkshell->getType() & ITEM_LINKSHELL))) { - switch (RBUFB(data,(0x04)) & 0xF0) // назначение первых бит пока неизвестно + switch (RBUFB(data,(0x04)) & 0xF0) // assignment of the first bit is unknown { - case 0x20: // устанавливаем права на изменение сообщения + case 0x20: // establish the right to change the message { // TODO: .... } break; - case 0x40: // изменяем сообщение + case 0x40: // Variable Message { if (PItemLinkshell->GetLSType() == LSTYPE_LINKSHELL || PItemLinkshell->GetLSType() == LSTYPE_PEARLSACK) @@ -3876,9 +3909,9 @@ /************************************************************************ * * -* Запрос на выход из игры. Shutdown и Logout отправляют одинаковые * -* запросы. В MogHouse персонаж выходит сразу, без задержки в 30 секунд * -* * +* Request to exit from the game. Shutdown and Logout send the same * +* requests. In MogHouse character goes at once, without delay of 30 * +* seconds * * ExitType: 1 - logout; 3 - shutdown * * * ************************************************************************/ @@ -3924,8 +3957,8 @@ /************************************************************************ * * -* Отдых персонажа (восстановление жизней, выход из игры, прерывание * -* чтения заклинаний, повышенная агрессия монстров и т.д.) * +* Rest of the character (recovery of lives out of the game, the * +* interrupt reading spells, increased aggression monsters, etc.) * * * ************************************************************************/ @@ -3967,7 +4000,7 @@ /************************************************************************ * * -* Команда /sit (персонаж садится и наслаждается окружением) * +* Team / sit (character sits down and enjoys the environment) * * * ************************************************************************/ @@ -3984,7 +4017,7 @@ /************************************************************************ * * -* Удаление статус эффекта щелчком по его иконке * +* Removing the effect of the status by clicking on its icon * * * ************************************************************************/ @@ -4001,9 +4034,9 @@ /************************************************************************ * * -* Клиент сообщает серверу, что входит в подобласть зоны * -* (в простонародье - boundary). Во избежание всяких казусов мы должны * -* сразу сохранять эту переменную. * +* The client tells the server that is a subdomain of the zone * +* (in common - boundary). To prevent any incidents we have * +* immediately to keep this variable. * * * ************************************************************************/ @@ -4017,7 +4050,7 @@ /************************************************************************ * * -* Сканирование местности (Wide Scan) * +* scanning area (Wide Scan) * * * ************************************************************************/ @@ -4029,7 +4062,7 @@ /************************************************************************ * * -* Следим за выбранной целью в Wide Scan * +* We scan the selected target in Wide Scan * * * ************************************************************************/ @@ -4043,7 +4076,7 @@ /************************************************************************ * * -* Отмена слежения за целью, выбранной в Wide Scan * +* Cancel target tracking is selected in the Wide Scan * * * ************************************************************************/ @@ -4055,7 +4088,7 @@ /************************************************************************ * * -* Установка мебели в MogHouse * +* Installation of furniture in MogHouse * * * ************************************************************************/ @@ -4065,8 +4098,8 @@ if (ItemID == 0) { - // выход из режима установки мебели - // здесь мы считаем ауру и добавляем необходимый keyitem + // Exit from the installation of furniture + // Here we consider the aura and adds the necessary keyitem return; } @@ -4117,7 +4150,7 @@ /************************************************************************ * * -* Удаление мебели в MogHouse * +* Removal of furniture MogHouse * * * ************************************************************************/ @@ -4140,7 +4173,7 @@ PItem->getID() == ItemID && PItem->getType() & ITEM_FURNISHING) { - // TODO: удаление мебели может никак не повлиять на размер хранилища, если сумма Storage превышала 80 ячеек + // TODO: removal of furniture can not change the size of the repository, if the amount of more than 80 cells Storage PItemContainer = PChar->getStorage(LOC_STORAGE); @@ -4193,12 +4226,12 @@ return; } -/************************************************************************ -* * -* Смена профессии. Разрешена только в зоне с флагом MISC_MOGMENU. * -* При смене профессии с персонажа снимаются все положительные эффекты * -* * -************************************************************************/ +/******************************************************************************** +* * +* Change of profession. Permitted only in the area of ​​the flag MISC_MOGMENU. * +* When switching jobs with character removed all the positive effects * +* * +********************************************************************************/ void SmallPacket0x100(map_session_data_t* session, CCharEntity* PChar, int8* data) { @@ -4260,7 +4293,7 @@ /************************************************************************ * * -* Устанавливаем активные заклинания синего мага, модифицируем автомат * +* Set the active blue mage spells, modify machine * * * ************************************************************************/ @@ -4317,7 +4350,7 @@ if (PTarget != NULL && PTarget->id == PChar->BazaarID.id) { - // надеюсь, что персонаж прописался в массиве однажны, но на всякий случай пробегаем по всему + // I hope that person is registered in the array odnazhny, but just in case, looping around for (uint32 i = 0; i < PTarget->BazaarCustomers.size(); ++i) { if (PTarget->BazaarCustomers[i].id == PChar->targid) @@ -4409,7 +4442,7 @@ if (charutils::AddItem(PChar, LOC_INVENTORY, PItem) == ERROR_SLOTID) return; - // TODO: мне так лень делать проверки на текущее количество gil, на первое время понадеемся на клиента + // TODO: I'm so lazy to do checks on the current amount of gil, for the first time cleave to the client uint32 Price1 = (PBazaarItem->getCharPrice() * Quantity); // цена uint32 Price2 = (PChar->loc.zone->GetTax() * Price1) / 10000 + Price1; // цена + налог @@ -4470,7 +4503,7 @@ /************************************************************************ * * -* Выходим из режима установки цен bazaar * +* Exit the setting of prices bazaar * * * ************************************************************************/ @@ -4495,7 +4528,7 @@ /************************************************************************ * * -* Устанавливаем цены bazaar на предметы * +* Set prices for items bazaar * * * ************************************************************************/ @@ -4546,7 +4579,7 @@ /************************************************************************ * * -* Инициализация массива процедур * +* Array initialization procedures * * * ************************************************************************/ Index: src/map/packet_system.h =================================================================== --- src/map/packet_system.h (revision 3520) +++ src/map/packet_system.h (working copy) @@ -30,7 +30,7 @@ struct map_session_data_t; -extern uint8 PacketSize[512]; // массив размеров входящих пакетов +extern uint8 PacketSize[512]; // array size of incoming packets extern void (*PacketParser[512])(map_session_data_t*, CCharEntity*, int8*); Index: src/map/packets/action.cpp =================================================================== --- src/map/packets/action.cpp (revision 3520) +++ src/map/packets/action.cpp (working copy) @@ -38,10 +38,10 @@ /************************************************************************ * * -* ActionTargetID содержит ID цели, над которой производится действие, * -* Если над целью необходимо произвести несколько действий, то в * -* последующих структурах это поле оставляется пустым (равным нулю), * -* это говорит о том, что это действие над ранее указанной целью * +* ActionTargetID ID contains objectives on which the action is, * +* If the purpose of the need to make a few steps, then * +* subsequent structures leave this field empty (zero), * +* this suggests that this action of the previously stated purpose * * * ************************************************************************/ @@ -371,21 +371,21 @@ { TargetNum++; - bitOffset = packBitsBE(data, Action.ActionTarget->id, bitOffset, 32); // тип совершаемого действия - bitOffset = packBitsBE(data, 1, bitOffset, 4); // количество действий над целью, в данном случае одно + bitOffset = packBitsBE(data, Action.ActionTarget->id, bitOffset, 32); // type performs actions + bitOffset = packBitsBE(data, 1, bitOffset, 4); // the number of actions over the target, in this case one ActionNum = 0; } - bitOffset = packBitsBE(data, Action.reaction, bitOffset, 5); // физическая реакция на урон - bitOffset = packBitsBE(data, Action.animation+animOffset, bitOffset, 11); // анимация специальных эффектов (monster TP animations are 1800+) + bitOffset = packBitsBE(data, Action.reaction, bitOffset, 5); // physical reaction to loss + bitOffset = packBitsBE(data, Action.animation+animOffset, bitOffset, 11); // Animation Special Effects (monster TP animations are 1800+) bitOffset += 1; bitOffset = packBitsBE(data, Action.speceffect, bitOffset, 9); // specialEffect bitOffset += 1; - bitOffset = packBitsBE(data, Action.param, bitOffset, 17); // параметр сообщения (урон) - bitOffset = packBitsBE(data, Action.messageID, bitOffset, 10); // сообщение + bitOffset = packBitsBE(data, Action.param, bitOffset, 17); // Customize message (Done) + bitOffset = packBitsBE(data, Action.messageID, bitOffset, 10); // message bitOffset += 31; - bitOffset = packBitsBE(data, Action.flag, bitOffset, 2); // флаг, ??? наличие дополнительного эффекта ??? + bitOffset = packBitsBE(data, Action.flag, bitOffset, 2); // flag ??? that an additional effect ??? if (Action.flag != 0) { @@ -404,10 +404,10 @@ } bitOffset = packBitsBE(data, Action.subeffect, bitOffset, subeffectLength); - // анимация эффекта, точный размер не известен (эффектов не так уж и много, около десяти) - bitOffset = packBitsBE(data, Action.subparam, bitOffset, subparamLength); // параметр сообщения (урон) + // animation effect, the exact size is not known (effects not too much, about ten) + bitOffset = packBitsBE(data, Action.subparam, bitOffset, subparamLength); // Customize message (Done) bitOffset += 1; - bitOffset = packBitsBE(data, Action.submessageID, bitOffset, 10); // сообщение + bitOffset = packBitsBE(data, Action.submessageID, bitOffset, 10); // message bitOffset += subOffset; // extra off set needed for multiple hits } @@ -419,8 +419,8 @@ this->size = ((((WorkSize + 7) >> 1) + 1) & -2); - WBUFB(data,(0x04)-4) = WorkSize; // Workload Size - 0x23 с дополнительным эффектом - 0x29 два удара монаха - WBUFB(data,(0x09)-4) = TargetNum; // количество атакуемых целей + WBUFB(data,(0x04)-4) = WorkSize; // Workload Size - 0x23 with the additional effect - 0x29 two hits monk + WBUFB(data,(0x09)-4) = TargetNum; // number of attacked targets } // 0xE0 0x58 0xD8 0x1D 0x1A - White Magic Start Index: src/map/packets/char_stats.cpp =================================================================== --- src/map/packets/char_stats.cpp (revision 3520) +++ src/map/packets/char_stats.cpp (working copy) @@ -49,7 +49,7 @@ WBUFW(data,(0x10)-4) = PChar->jobs.exp[PChar->GetMJob()]; WBUFW(data,(0x12)-4) = charutils::GetExpNEXTLevel(PChar->jobs.job[PChar->GetMJob()]); - memcpy(data+(0x14)-4, &PChar->stats, 14); // TODO: с merits это не прокатит + memcpy(data+(0x14)-4, &PChar->stats, 14); // TODO: with the merits is not a ride WBUFW(data,(0x22)-4) = PChar->getMod(MOD_STR); WBUFW(data,(0x24)-4) = PChar->getMod(MOD_DEX); Index: src/map/packets/chat_message.cpp =================================================================== --- src/map/packets/chat_message.cpp (revision 3520) +++ src/map/packets/chat_message.cpp (working copy) @@ -44,4 +44,14 @@ memcpy(data+(0x08)-4, PChar->GetName(), PChar->name.size()); memcpy(data+(0x18)-4, buff, strlen(buff)); +} + +CNPCMessagePacket::CNPCMessagePacket(int8* name, uint8 zone, int8* dat, uint8 size) +{ + this->type = 0x17; + this->size = 32 + strlen(dat) + strlen(dat)%2; + WBUFB(data,(0x04)-4) = 0x03; + WBUFB(data,(0x06)-4) = zone; + memcpy(data+(0x08)-4, name,size); + memcpy(data+(0x18)-4, dat, strlen(dat)); } \ No newline at end of file Index: src/map/packets/chat_message.h =================================================================== --- src/map/packets/chat_message.h (revision 3520) +++ src/map/packets/chat_message.h (working copy) @@ -57,4 +57,9 @@ CChatMessagePacket(CCharEntity* PChar, CHAT_MESSAGE_TYPE MessageType, int8* buff); }; +class CNPCMessagePacket : public CBasicPacket +{ +public: + CNPCMessagePacket(int8* name, uint8 zone, int8* dat,uint8 size); +}; #endif \ No newline at end of file Index: src/map/packets/event.cpp =================================================================== --- src/map/packets/event.cpp (revision 3520) +++ src/map/packets/event.cpp (working copy) @@ -75,7 +75,7 @@ } WBUFW(data,(0x2C)-4) = EventID; - WBUFB(data,(0x2E)-4) = 8; // если патаметров меньше, чем 8, то после завершения события камера "прыгнет" за спину персонажу + WBUFB(data,(0x2E)-4) = 8; // parameter if less than 8, then after the event camera "jump" behind the character } else { Index: src/map/packets/inventory_item.cpp =================================================================== --- src/map/packets/inventory_item.cpp (revision 3520) +++ src/map/packets/inventory_item.cpp (working copy) @@ -75,7 +75,7 @@ if (((CItemUsable*)PItem)->getCurrentCharges() > 0) { - WBUFB(data,(0x12)-4) = ((CItemUsable*)PItem)->getCurrentCharges(); // количество оставшихся зарядов + WBUFB(data,(0x12)-4) = ((CItemUsable*)PItem)->getCurrentCharges(); // the number of remaining charges if (((CItemUsable*)PItem)->getReuseTime() == 0) { @@ -87,8 +87,8 @@ uint32 CurrentTime = CVanaTime::getInstance()->getVanaTime(); - WBUFL(data,(0x15)-4) = ((CItemUsable*)PItem)->getNextUseTime(); // таймер следующего использования - WBUFL(data,(0x19)-4) = ((CItemUsable*)PItem)->getUseDelay() + CurrentTime; // таймер задержки использования + WBUFL(data,(0x15)-4) = ((CItemUsable*)PItem)->getNextUseTime(); // next timer Frequency + WBUFL(data,(0x19)-4) = ((CItemUsable*)PItem)->getUseDelay() + CurrentTime; // delay timer is used } } } Index: src/map/packets/menu_merit.cpp =================================================================== --- src/map/packets/menu_merit.cpp (revision 3520) +++ src/map/packets/menu_merit.cpp (working copy) @@ -29,11 +29,11 @@ #include "../charutils.h" -CMenuMeritPacket::CMenuMeritPacket(CCharEntity* PChar) +CMenuMeritPacket::CMenuMeritPacket(CCharEntity* PChar) { this->type = 0x63; this->size = 0x06; - + WBUFB(data,(0x04)-4) = 0x02; WBUFB(data,(0x06)-4) = 0x08; @@ -42,7 +42,7 @@ if (PChar->jobs.job[PChar->GetMJob()] >= 75 && charutils::hasKeyItem(PChar, 606)) // keyitem Limit Breaker { - WBUFB(data,(0x0B)-4) = PChar->MeritMode ? 0xE0 : 0x20; // режим (0xE0 limit pints, 0x20 exp points) + WBUFB(data,(0x0B)-4) = PChar->MeritMode ? 0xE0 : 0x20; // mode (0xE0 limit pints, 0x20 exp points) } PChar->pushPacket(new CBasicPacket(*this)); @@ -72,6 +72,7 @@ 0x04, 0x00, 0x84 }; memcpy(data+(0x04)-4, &packet2, sizeof(packet2)); + } Index: src/map/packets/merit_points_categories.cpp =================================================================== --- src/map/packets/merit_points_categories.cpp (revision 3520) +++ src/map/packets/merit_points_categories.cpp (working copy) @@ -32,33 +32,33 @@ /************************************************************************ * * -* Примечание * +* Note * * * ************************************************************************/ /* -пакет, содержащий информацию об примененных меритах и количестве, необходимом для следующего усиления -информации много, отправляется в трех пакетах. начало у всех стандартное: +package containing information about the applied MERIT and the quantity required for the following enhanced +a lot of information is sent in three packages. top of all the standard: 0x8c 0x80 0x05 0x00 0x3D 0x00 0x00 0x00 -далее идут данные в виде структур +followed by data in the form of structures struct { - unsigned sort // id мерита - unsigned char // необходимое количество меритов для следующего усиления (0 - усиление этого мерита невозможно) - unsigned char // количестов усилений, сделанных персонажем + unsigned sort // id Merit + unsigned char // required number of Merit for the next gain (0 - strengthening this Merit impossible) + unsigned char // MAX gains made ​​character }; -начало категории кратно 0x40 далее идет прибавление id значения. все id кратны двум +top categories on multiple 0x40 id is adding value. id all the multiples of two -количество необходимых меритов для следующего усиления передаются персонажу только при входе в moghouse +amount needed for the next Merit gain character transmitted only when entering moghouse */ /************************************************************************ * * -* Отправляем персонажу информацию о всех merit (5 пакетов) * +* Send character information about merit (5 Packs) * * * ************************************************************************/ @@ -82,7 +82,7 @@ /************************************************************************ * * -* Отправляем персонажу информуцию об одном merit * +* Send the character of one information merit * * * ************************************************************************/ @@ -114,7 +114,7 @@ { for (uint8 i = 0; i < MAX_MERITS_IN_PACKET; ++i) { - (*(Merit_t*)(data+(0x08)-4 + sizeof(uint32) * i)).next = 0; // обнуляем значение next у всех merit + (*(Merit_t*)(data+(0x08)-4 + sizeof(uint32) * i)).next = 0; // zero out the value of all the next merit } } } @@ -126,7 +126,7 @@ * * ************************************************************************/ -// TODO: не помню, зачем я сунул это сюда (( +// TODO: I do not remember why I put it here (( /* Index: src/map/packets/message_basic.h =================================================================== --- src/map/packets/message_basic.h (revision 3520) +++ src/map/packets/message_basic.h (working copy) @@ -108,8 +108,9 @@ MSGBASIC_COUNTER_ABS_BY_SHADOW = 14, /* The 's attack is countered by the . .. of 's shadows absorbs the damage and disappears. */ /* THF */ MSGBASIC_TREASURE_HUNTER_UP = 603, /* Additional effect: Treasure Hunter effectiveness against increases to .. */ + /* DNC */ + MSGBASIC_NO_FINISHINGMOVES = 524, - /* DEBUG MESSAGES */ MSGBASIC_DEBUG_RESISTED_SPELL = 66, /* Debug: Resisted spell! */ MSGBASIC_DEBUG_RECEIVED_STATUS = 73, /* Debug: 's status is now .. */ Index: src/map/packets/quest_mission_log.cpp =================================================================== --- src/map/packets/quest_mission_log.cpp (revision 3520) +++ src/map/packets/quest_mission_log.cpp (working copy) @@ -34,9 +34,9 @@ this->type = 0x56; this->size = 0x14; - // настоятельно советую в switch(logID) ничего не менять, - // если вы НЕ УВЕРЕНЫ в том, что делаете - // даже простая перестановка case местами может привести к логическим ошибкам + // urge to switch (logID) change nothing, + // If you're not sure what you are doing + // even a simple rearrangement of case sometimes can lead to logical errors uint16 logType = 0x0000; switch(logID) { @@ -238,7 +238,7 @@ WBUFW(data,(0x0C)-4) = PChar->m_missionLog[MISSION_ZILART-11].current; // Rise of the Zilart WBUFL(data,(0x10)-4) = chains; // Chains of Promathia Missions - //WBUFB(data,(0x16)-4) = 0x30; // назначение неизвестно + //WBUFB(data,(0x16)-4) = 0x30; // destination unknown WBUFW(data,(0x18)-4) = add_on_scenarios; // A Crystalline Prophecy ,A Moogle Kupo d'Etat,A Shantotto Ascension WBUFW(data,(0x1C)-4) = PChar->m_missionLog[MISSION_ADOULIN-11].current; } Index: src/map/packets/quest_mission_log.h =================================================================== --- src/map/packets/quest_mission_log.h (revision 3520) +++ src/map/packets/quest_mission_log.h (working copy) @@ -57,7 +57,7 @@ #define MISS_COMPLETE 0xD0 #define MISS_CURRENT 0xFFFF -// MISS_CURRENT 0xFF исключая Add-on Scenarios +// MISS_CURRENT 0xFF excluding Add-on Scenarios #define EXP_MISS_COMPLETE 0xD8 #define EXP_MISS_CURRENT 0x80 @@ -100,8 +100,8 @@ CQuestMissionLogPacket(CCharEntity* PChar, uint8 logID, uint8 status); private: - // формирование пакетов вынес в отдельные функции, специально для тех, - // кто захочет понять, что же на самом деле происходит в switch(logID) + // encapsulation is in a separate function, especially for those + // who wants to understand what is really going on in switch(logID) void generateQuestPacket(CCharEntity* PChar, uint8 logID, uint8 status); void generateCurrentMissionPacket(CCharEntity* PChar); Index: src/map/packets/server_ip.cpp =================================================================== --- src/map/packets/server_ip.cpp (revision 3520) +++ src/map/packets/server_ip.cpp (working copy) @@ -33,6 +33,15 @@ this->size = 0x0E; WBUFB(data,(0x04)-4) = type; - WBUFL(data,(0x08)-4) = PChar->loc.zone->GetIP(); + + if(PChar->id > 40000) // External Accounts are assigned much higher IDs. + { + WBUFL(data,(0x08)-4) = PChar->loc.zone->GetWANIP(); + } + else + { + WBUFL(data,(0x08)-4) = PChar->loc.zone->GetLANIP(); + } + WBUFW(data,(0x0C)-4) = PChar->loc.zone->GetPort(); } Index: src/map/packets/unknown_39.cpp =================================================================== --- src/map/packets/unknown_39.cpp (revision 0) +++ src/map/packets/unknown_39.cpp (working copy) @@ -0,0 +1,46 @@ +/* +=========================================================================== + + Copyright (c) 2010-2012 Darkstar Dev Teams + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ + + This file is part of DarkStar-server source code. + +=========================================================================== +*/ + +#include "../../common/socket.h" + +#include "../baseentity.h" + +#include "unknown_39.h" + + +CUnknown0x39Packet::CUnknown0x39Packet(CBaseEntity* PEntity, uint8 param) +{ + this->type = 0x39; + this->size = 0x0A; + + WBUFL(data,(0x04)-4) = PEntity->id; + WBUFL(data,(0x08)-4) = PEntity->id; + + WBUFL(data,(0x0C)-4) = 0x6B; + WBUFL(data,(0x0D)-4) = 0x6B; + WBUFL(data,(0x0E)-4) = 0x6A; + WBUFL(data,(0x0F)-4) = param; + + WBUFW(data,(0x10)-4) = PEntity->targid; + WBUFW(data,(0x12)-4) = PEntity->targid; +} \ No newline at end of file Index: src/map/packets/unknown_39.h =================================================================== --- src/map/packets/unknown_39.h (revision 0) +++ src/map/packets/unknown_39.h (working copy) @@ -0,0 +1,46 @@ +/* +=========================================================================== + + Copyright (c) 2010-2012 Darkstar Dev Teams + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ + + This file is part of DarkStar-server source code. + +=========================================================================== +*/ + +#ifndef _CUNKNOWN39PACKET_H +#define _CUNKNOWN39PACKET_H + +#include "../../common/cbasetypes.h" + +#include "basic.h" + +/************************************************************************ +* * +* * +* * +************************************************************************/ + +class CBaseEntity; + +class CUnknown0x39Packet : public CBasicPacket +{ +public: + + CUnknown0x39Packet(CBaseEntity* PEntity, uint8 param); +}; + +#endif \ No newline at end of file Index: src/map/packets/zone_in.cpp =================================================================== --- src/map/packets/zone_in.cpp (revision 3520) +++ src/map/packets/zone_in.cpp (working copy) @@ -28,14 +28,15 @@ #include "zone_in.h" #include "../charentity.h" +#include "../charutils.h" #include "../../common/timer.h" #include "../vana_time.h" #include "../zoneutils.h" /************************************************************************ * * -* Кривое решение для вычисления ID MogHouse * -* Возможно необходим переход на uint16 формат зоны * +* Hacks for computing ID MogHouse * +* May be a shift in the format uint16 zone * * * ************************************************************************/ @@ -106,14 +107,14 @@ this->type = 0x0A; this->size = 0x82; - // необходимо для работы manaklipper - // последние 8 байт похожи на время + // Need to work Manaclipper + // Last 8 bytes are like time //unsigned char packet [] = { //0x0D, 0x3A, 0x0C, 0x00, 0x11, 0x00, 0x19, 0x00, 0x02, 0xE4, 0x93, 0x10, 0x91, 0xE5, 0x93, 0x10}; // 0x2a = 0x10 //0x89, 0x39, 0x0C, 0x00, 0x19, 0x00, 0x07, 0x00, 0x5C, 0xE1, 0x93, 0x10, 0x81, 0xE3, 0x93, 0x10}; // 0x2a = 0x08 //memcpy(data + 0x70-4, &packet, 16); - //data[0x2A-4] = 0x08;//data[0x2A-4] = 0x80; // в зоне 3 управляет путями следования транспорта 0x10 и 0x08 + //data[0x2A-4] = 0x08;//data[0x2A-4] = 0x80; // Zone 3 controls transport routes following 0x10 and 0x08 WBUFL(data,(0x04)-4) = PChar->id; WBUFW(data,(0x08)-4) = PChar->targid; @@ -157,7 +158,7 @@ if(csid != -1) { - //WBUFB(data,(0x1F)-4) = 4; // предположительно animation + //WBUFB(data,(0x1F)-4) = 4; // presumably animation //WBUFB(data,(0x20)-4) = 2; WBUFB(data,(0x40)-4) = PChar->getZone(); @@ -174,14 +175,15 @@ WBUFB(data,(0xAE)-4) = GetMosHouseFlag(PChar); // Mog House leaving flag } else { WBUFB(data,(0x80)-4) = 2; - WBUFW(data,(0x30)-4) = PChar->getZone(); // to zone - WBUFW(data,(0x42)-4) = PChar->getZone(); // to zone + WBUFW(data,(0x30)-4) = PChar->getZone(); // to zone + WBUFW(data,(0x42)-4) = PChar->getZone(); // to zone WBUFW(data,(0xAA)-4) = 0x01FF; - WBUFB(data,(0xAC)-4) = csid > 0 ? 0x01 : 0x00; //if 0x01 then pause between zone - WBUFB(data,(0xAF)-4) = PChar->loc.zone->CanUseMisc(MISC_MOGMENU); // флаг, позволяет использовать mog menu за пределами mog house + WBUFB(data,(0xAC)-4) = csid > 0 ? 0x01 : 0x00; //if 0x01 then pause between zone + WBUFB(data,(0xAF)-4) = PChar->loc.zone->CanUseMisc(MISC_MOGMENU); // flag allows mog menu outside mog house } - WBUFL(data,(0xA0)-4) = 0x00000000; // время, проведенное персонажем в игре с момента создания + WBUFL(data,(0x98)-4) = charutils::GetClientIP(PChar); + WBUFL(data,(0xA0)-4) = PChar->GetPlayTime(); // time spent by a character in a game since the // current death timestamp is less than an hour ago and the player is dead. if (PChar->m_DeathTimestamp > 0 && ((time(NULL)-PChar->m_DeathTimestamp) < (60*60)) && PChar->isDead()) Index: src/map/party.cpp =================================================================== --- src/map/party.cpp (revision 3520) +++ src/map/party.cpp (working copy) @@ -43,7 +43,7 @@ /************************************************************************ * * -* Конструктор * +* Designer * * * ************************************************************************/ @@ -68,7 +68,7 @@ /************************************************************************ * * -* Распускаем группу * +* Dissolve the group * * * ************************************************************************/ @@ -109,7 +109,7 @@ /************************************************************************ * * -* Назначаем роли участникам группы (только для персонажей) * +* Assign the role of members of the group (for the characters) * * * ************************************************************************/ @@ -139,7 +139,7 @@ /************************************************************************ * * -* Узнаем количество участников группы в указанной зоне * +* Get the number of group members in the zone * * * ************************************************************************/ @@ -159,7 +159,7 @@ /************************************************************************ * * -* Удаление персонажа из группы по имени (только для персонажей) * +* Removal of the character of the group named (for characters) * * * ************************************************************************/ @@ -180,7 +180,7 @@ /************************************************************************ * * -* Удаляем персонажа из группы * +* Delete the character of the group * * * ************************************************************************/ @@ -240,7 +240,7 @@ /************************************************************************ * * -* Лидер покидает группу * +* The leader leaves the group * * * ************************************************************************/ @@ -270,7 +270,7 @@ /************************************************************************ * * -* Добавляем персонажа в группу * +* Add the character to the group * * * ************************************************************************/ @@ -310,7 +310,7 @@ /************************************************************************ * * -* Получаем уникальный ID группы * +* Get the unique ID of * * * ************************************************************************/ @@ -321,7 +321,7 @@ /************************************************************************ * * -* Получаем указатель на лидера группы * +* Get a pointer to the group leader * * * ************************************************************************/ @@ -332,7 +332,7 @@ /************************************************************************ * * -* Получаем указатель на цель синхронизации уровней * +* Get a pointer to the target synchronization levels * * * ************************************************************************/ @@ -343,7 +343,7 @@ /************************************************************************ * * -* Получаем указатель на владельца сокровищ * +* Get a pointer to the owner of the treasure * * * ************************************************************************/ @@ -356,7 +356,7 @@ /************************************************************************ * * -* Получаем список флагов персонажа * +* Get a list of flags of the character * * * ************************************************************************/ @@ -390,7 +390,7 @@ /************************************************************************ * * -* Обновляем карту группы для всех членов группы * +* Update the map of all members of the group * * * ************************************************************************/ @@ -436,8 +436,8 @@ /************************************************************************ * * -* Обновляем статусы членов группы для выбранного персонажа * -* Возвращаем номер персонажа в группе * +* Update the status of the group for the selected character * +* Return the number of characters in * * * ************************************************************************/ @@ -473,7 +473,7 @@ /************************************************************************ * * -* Обновляем TreasurePool для указанного персонажа * +* Update TreasurePool for the specified character * * * ************************************************************************/ @@ -539,7 +539,7 @@ /************************************************************************ * * -* Устанавливаем лидера группы * +* Set the group leader * * * ************************************************************************/ @@ -559,7 +559,7 @@ /************************************************************************ * * -* Устанавливаем цель синхронизации уровней * +* Set the target synchronization levels * * * ************************************************************************/ @@ -570,7 +570,7 @@ /************************************************************************ * * -* Усранавливаем владельца сокровищ * +* Usranavlivaem owner treasure * * * ************************************************************************/ @@ -581,9 +581,9 @@ /************************************************************************ * * -* Отправляем пакет всем членам группы, если зона указана как 0 или * -* членам группы в указанной зоне. * -* Пакет для PPartyMember не отправляется в обоих случаях. * +* Send the package to all members of the group, if the zone is * +* specified as 0 or Members of the group in this area. * +* Package for PPartyMember not sent in both cases. * * * ************************************************************************/ Index: src/map/party.h =================================================================== --- src/map/party.h (revision 3520) +++ src/map/party.h (working copy) @@ -61,48 +61,48 @@ CParty(CBattleEntity* PEntity); - uint32 GetPartyID(); // узнаем уникальный ID группы - uint16 GetMemberFlags(CBattleEntity* PEntity); // получаем список флагов персонажа - uint8 MemberCount(uint8 ZoneID); // узнаем количество участников группы в указанной зоне + uint32 GetPartyID(); // find out the unique ID of + uint16 GetMemberFlags(CBattleEntity* PEntity); // get a list of character flags + uint8 MemberCount(uint8 ZoneID); // get the number of party members in the zone - CBattleEntity* GetLeader(); // узнаем лидера группы - CBattleEntity* GetSyncTarget(); // узнаем цель синхронизации - CBattleEntity* GetQuaterMaster(); // узнаем владельца сокровищ + CBattleEntity* GetLeader(); // find out the group leader + CBattleEntity* GetSyncTarget(); // learn the purpose of synchronization + CBattleEntity* GetQuaterMaster(); // find out the owner of the treasure - void DisbandParty(); // распускаем группу - void ReloadParty(); // перезагружаем карту группы для всех участников группы - void ReloadPartyMembers(CCharEntity* PChar); // oбновляем статусы участников группы для выбранного персонажа + void DisbandParty(); // group disbands + void ReloadParty(); // reload the card group for all members of the group + void ReloadPartyMembers(CCharEntity* PChar); // reload party status for the selected character void ReloadTreasurePool(CCharEntity* PChar); - void AddMember(CBattleEntity* PEntity); // добавляем персонажа в группу - void RemoveMember(CBattleEntity* PEntity); // удаление персонажа из группы - void RemoveMemberByName(int8* MemberName); // удаление персонажа из группы по имени - void AssignPartyRole(int8* MemberName, uint8 role); // назначаем роли участникам группы + void AddMember(CBattleEntity* PEntity); // add character to the group + void RemoveMember(CBattleEntity* PEntity); // remove the character from the group + void RemoveMemberByName(int8* MemberName); // remove a character from a group called + void AssignPartyRole(int8* MemberName, uint8 role); // assign roles to team members - void PushPacket(CCharEntity* PPartyMember, uint8 ZoneID, CBasicPacket* packet); // отправляем пакет всем членам группы, за исключением PPartyMember - + void PushPacket(CCharEntity* PPartyMember, uint8 ZoneID, CBasicPacket* packet); // send the packet to all members of the group, except PPartyMember + CAlliance* m_PAlliance; - // ВНИМАНИЕ: НЕ ИЗМЕНЯТЬ ЗНАЧЕНИЯ СПИСКА ВНЕ КЛАССА ГРУППЫ + // NOTE: Do not change the outside of the class LIST GROUPS - std::vector members; // список участников группы + std::vector members; // list of group members private: - uint32 m_PartyID; // уникальный ID группы - PARTYTYPE m_PartyType; // тип существ, составляющих группу + uint32 m_PartyID; // unique ID of + PARTYTYPE m_PartyType; // type of creatures that make up the group - CBattleEntity* m_PLeader; // лидер группы - CBattleEntity* m_PSyncTarget; // цель синхронизации уровней - CBattleEntity* m_PQuaterMaster; // владелец сокровищ + CBattleEntity* m_PLeader; // group leader + CBattleEntity* m_PSyncTarget; // target synchronization levels + CBattleEntity* m_PQuaterMaster; // owner of the treasure - void SetLeader(CBattleEntity* PEntity); // устанавливаем лидера группы - void SetSyncTarget(CBattleEntity* PEntity); // устанавливаем цель синхронизации уровней - void SetQuaterMaster(CBattleEntity* PEntity); // устанавливаем владельца сокровищ + void SetLeader(CBattleEntity* PEntity); // set the group leader + void SetSyncTarget(CBattleEntity* PEntity); // set the target levels of synchronization + void SetQuaterMaster(CBattleEntity* PEntity); // Set the owner of treasures - void RemovePartyLeader(CBattleEntity* PEntity); // лидер покидает группу + void RemovePartyLeader(CBattleEntity* PEntity); // leaves the group leader }; #endif \ No newline at end of file Index: src/map/petentity.h =================================================================== --- src/map/petentity.h (revision 3520) +++ src/map/petentity.h (working copy) @@ -48,8 +48,8 @@ class CPetEntity : public CBattleEntity { public: - CPetEntity(PETTYPE petType); // конструктор - ~CPetEntity(); // деструктор + CPetEntity(PETTYPE petType); // Designer + ~CPetEntity(); // Destructor PETTYPE getPetType(); bool isBstPet(); uint16 m_Family; Index: src/map/petutils.cpp =================================================================== --- src/map/petutils.cpp (revision 3520) +++ src/map/petutils.cpp (working copy) @@ -47,25 +47,25 @@ struct Pet_t { - look_t look; // внешний вид - string_t name; // имя - ECOSYSTEM EcoSystem; // эко-система + look_t look; // appearance + string_t name; // name + ECOSYSTEM EcoSystem; // eco-system - uint8 minLevel; // минимально-возможный уровень - uint8 maxLevel; // максимально-возможный уровень + uint8 minLevel; // lowest possible level + uint8 maxLevel; // maximum possible level - uint8 size; // размер модели + uint8 size; // size of the model uint16 m_Family; - uint32 time; // время существования (будет использоваться для задания длительности статус эффекта) + uint32 time; // lifetime (to be used to set the duration of the status effect) uint8 mJob; uint8 m_Element; - float HPscale; // HP boost percentage - float MPscale; // MP boost percentage + float HPscale; // HP boost percentage + float MPscale; // MP boost percentage uint8 speed; // stat ranks - uint8 strRank; + uint8 strRank; uint8 dexRank; uint8 vitRank; uint8 agiRank; @@ -113,7 +113,7 @@ /************************************************************************ * * -* Загружаем список прототипов питомцев * +* Load the list of prototypes pets * * * ************************************************************************/ @@ -221,7 +221,7 @@ /************************************************************************ * * -* Освобождаем список прототипов питомцев * +* Free the list of prototypes pets * * * ************************************************************************/ @@ -398,18 +398,18 @@ void LoadAvatarStats(CPetEntity* PChar) { - // Объявление переменных, нужных для рассчета. - float raceStat = 0; // конечное число HP для уровня на основе расы. - float jobStat = 0; // конечное число HP для уровня на основе первичной профессии. - float sJobStat = 0; // коенчное число HP для уровня на основе вторичной профессии. - int32 bonusStat = 0; // бонусное число HP которое добавляется при соблюдении некоторых условий. - int32 baseValueColumn = 0; // номер колонки с базовым количеством HP - int32 scaleTo60Column = 1; // номер колонки с модификатором до 60 уровня - int32 scaleOver30Column = 2; // номер колонки с модификатором после 30 уровня - int32 scaleOver60Column = 3; // номер колонки с модификатором после 60 уровня - int32 scaleOver75Column = 4; // номер колонки с модификатором после 75 уровня - int32 scaleOver60 = 2; // номер колонки с модификатором для расчета MP после 60 уровня - int32 scaleOver75 = 3; // номер колонки с модификатором для расчета Статов после 75-го уровня + // Declare the variables needed for the calculation. + float raceStat = 0; // HP for a finite number of levels on the basis of race. + float jobStat = 0; // ​​HP for a finite number of levels based on primary profession. + float sJobStat = 0; // number HP for a level based on a secondary profession. + int32 bonusStat = 0; // ​​number of HP bonus is added, subject to certain conditions. + int32 baseValueColumn = 0; // ​​number of the column to the base of HP + int32 scaleTo60Column = 1; // number of columns with the modifier level 60 + int32 scaleOver30Column = 2; // number of columns with the modifier after level 30 + int32 scaleOver60Column = 3; // number of columns with the modifier after level 60 + int32 scaleOver75Column = 4; // number of columns with the modifier after level 75 + int32 scaleOver60 = 2; // number of columns with the modifier to calculate MP after level 60 + int32 scaleOver75 = 3; // number of columns with the modifier for the calculation of the article after level 75 uint8 grade; @@ -417,19 +417,19 @@ JOBTYPE mjob = PChar->GetMJob(); uint8 race = 3; //Tarutaru - // Расчет прироста HP от main job - int32 mainLevelOver30 = dsp_cap(mlvl - 30, 0, 30); // Расчет условия +1HP каждый лвл после 30 уровня - int32 mainLevelUpTo60 = (mlvl < 60 ? mlvl - 1 : 59 ); // Первый режим рассчета до 60 уровня (Используется так же и для MP) - int32 mainLevelOver60To75 = dsp_cap(mlvl - 60, 0, 15); // Второй режим расчета после 60 уровня - int32 mainLevelOver75 = (mlvl < 75 ? 0 : mlvl - 75); // Третий режим расчета после 75 уровня + // Calculate the increase HP from main job + int32 mainLevelOver30 = dsp_cap(mlvl - 30, 0, 30); // Calculate the conditions +1 HP each lvl after level 30 + int32 mainLevelUpTo60 = (mlvl < 60 ? mlvl - 1 : 59 ); // The first mode calculation level 60 (used also for MP) + int32 mainLevelOver60To75 = dsp_cap(mlvl - 60, 0, 15); // The second calculation mode after level 60 + int32 mainLevelOver75 = (mlvl < 75 ? 0 : mlvl - 75); // The third mode of calculation after level 75 - //Расчет бонусного количества HP - int32 mainLevelOver10 = (mlvl < 10 ? 0 : mlvl - 10); // +2HP на каждом уровне после 10 - int32 mainLevelOver50andUnder60 = dsp_cap(mlvl - 50, 0, 10); // +2HP на каждом уровне в промежутке от 50 до 60 уровня + // Calculate the amount of bonus HP + int32 mainLevelOver10 = (mlvl < 10 ? 0 : mlvl - 10); // +2 HP on every level after 10 + int32 mainLevelOver50andUnder60 = dsp_cap(mlvl - 50, 0, 10); // +2 HP on every level in the range from 50 to 60 levels int32 mainLevelOver60 = (mlvl < 60 ? 0 : mlvl - 60); - // Расчет raceStat jobStat bonusStat sJobStat - // Расчет по расе + // Calculate the raceStat jobStat bonusStat sJobStat + // Calculation for race grade = grade::GetRaceGrades(race,0); @@ -441,7 +441,7 @@ // raceStat = (int32)(statScale[grade][baseValueColumn] + statScale[grade][scaleTo60Column] * (mlvl - 1)); - // Расчет по main job + // Calculation of main job grade = grade::GetJobGrade(mjob,0); jobStat = grade::GetHPScale(grade,baseValueColumn) + @@ -450,30 +450,30 @@ (grade::GetHPScale(grade,scaleOver60Column) * mainLevelOver60To75) + (grade::GetHPScale(grade,scaleOver75Column) * mainLevelOver75); - // Расчет бонусных HP + // Calculate the bonus HP bonusStat = (mainLevelOver10 + mainLevelOver50andUnder60) * 2; PChar->health.maxhp = (int16)(raceStat + jobStat + bonusStat + sJobStat); PChar->health.hp = PChar->health.maxhp; - //Начало расчера MP + // Start raschera MP raceStat = 0; jobStat = 0; sJobStat = 0; - // Расчет MP расе. + // Calculate the MP race. grade = grade::GetRaceGrades(race,1); - //Если у main job нет МП рейтинга, расчитиваем расовый бонус на основе уровня subjob уровня(при условии, что у него есть МП рейтинг) + // If there is no main job megapixel rating raschitivaem racial bonus based on the level subjob level (provided that it has a megapixel rating) if (grade::GetJobGrade(mjob,1) == 0) { }else{ - //Расчет нормального расового бонуса + // Calculate the normal racial bonus raceStat = grade::GetMPScale(grade,0) + grade::GetMPScale(grade,scaleTo60Column) * mainLevelUpTo60 + grade::GetMPScale(grade,scaleOver60) * mainLevelOver60; } - //Для главной профессии + // For the main occupation grade = grade::GetJobGrade(mjob,1); if (grade > 0) { @@ -482,7 +482,7 @@ grade::GetMPScale(grade,scaleOver60) * mainLevelOver60; } - PChar->health.maxmp = (int16)(raceStat + jobStat + sJobStat); // результат расчета MP + PChar->health.maxmp = (int16)(raceStat + jobStat + sJobStat); // calculation result MP //add in evasion from skill int16 evaskill = PChar->GetSkill(SKILL_EVA); int16 eva = evaskill; @@ -491,11 +491,11 @@ } PChar->setModifier(MOD_EVA,eva); - //Начало расчета характеристик + // Start the calculation of the characteristics uint8 counter = 0; for (uint8 StatIndex = 2; StatIndex <=8; ++StatIndex) { - // расчет по расе + // Calculation for race grade = grade::GetRaceGrades(race,StatIndex); raceStat = grade::GetStatScale(grade,0) + grade::GetStatScale(grade,scaleTo60Column) * mainLevelUpTo60; @@ -508,7 +508,7 @@ } } - // расчет по профессии + // Calculation of the profession grade = grade::GetJobGrade(mjob,StatIndex); jobStat = grade::GetStatScale(grade,0) + grade::GetStatScale(grade,scaleTo60Column) * mainLevelUpTo60; @@ -524,7 +524,7 @@ jobStat = jobStat * 1.5; //stats from subjob (assuming BLM/BLM for avatars) - // Вывод значения + // Output values WBUFW(&PChar->stats,counter) = (uint16)(raceStat + jobStat); counter += 2; } @@ -969,7 +969,7 @@ break; case TYPE_PC: { - // освобождаем персонажа из под контроля + // Set the character of control } break; } Index: src/map/petutils.h =================================================================== --- src/map/petutils.h (revision 3520) +++ src/map/petutils.h (working copy) @@ -63,17 +63,17 @@ namespace petutils { - void LoadPetList(); - void FreePetList(); + void LoadPetList(); + void FreePetList(); - void SpawnPet(CBattleEntity* PMaster, uint32 PetID, bool spawningFromZone); - void SpawnMobPet(CBattleEntity* PMaster, uint32 PetID); - void DespawnPet(CBattleEntity* PMaster); - void AttackTarget(CBattleEntity* PMaster, CBattleEntity* PTarget); - void RetreatToMaster(CBattleEntity* PMaster); - void MakePetStay(CBattleEntity* PMaster); - int16 PerpetuationCost(uint32 id, uint8 level); - void Familiar(CBattleEntity* PPet); + void SpawnPet(CBattleEntity* PMaster, uint32 PetID, bool spawningFromZone); + void SpawnMobPet(CBattleEntity* PMaster, uint32 PetID); + void DespawnPet(CBattleEntity* PMaster); + void AttackTarget(CBattleEntity* PMaster, CBattleEntity* PTarget); + void RetreatToMaster(CBattleEntity* PMaster); + void MakePetStay(CBattleEntity* PMaster); + int16 PerpetuationCost(uint32 id, uint8 level); + void Familiar(CBattleEntity* PPet); }; #endif \ No newline at end of file Index: src/map/recast_container.cpp =================================================================== --- src/map/recast_container.cpp (revision 3520) +++ src/map/recast_container.cpp (working copy) @@ -57,7 +57,7 @@ /************************************************************************ * * -* Получаем указатель на указанный RecastList * +* Get a pointer to the specified RecastList * * * ************************************************************************/ @@ -98,7 +98,7 @@ /************************************************************************ * * -* Добавляем запись в контейнер * +* Add an entry in the container * * * ************************************************************************/ @@ -121,8 +121,8 @@ { if (chargeTime == 0) { - recast->TimeStamp = gettick(); - recast->RecastTime = duration; + recast->TimeStamp = gettick(); + recast->RecastTime = duration; } else { @@ -139,7 +139,7 @@ /************************************************************************ * * -* Удаляем все элементы указанного типа * +* Remove all elements of the specified type * * * ************************************************************************/ @@ -156,7 +156,7 @@ /************************************************************************ * * -* Удаляем указанный элемент указанного типа * +* Removes the specified element of this type * * * ************************************************************************/ @@ -177,7 +177,7 @@ /************************************************************************ * * -* Проверяем наличие элемента с указанным ID * +* Check if the element with the specified ID * * * ************************************************************************/ @@ -230,7 +230,7 @@ /************************************************************************ * * -* Проверяем список на устаревшие записи * +* Check the list on the outdated entries * * * ************************************************************************/ @@ -257,16 +257,16 @@ } if (type == RECAST_ITEM || type == RECAST_MAGIC) { - PRecastList->erase(PRecastList->begin() + i--); - delete recast; - } + PRecastList->erase(PRecastList->begin() + i--); + delete recast; + } else { recast->RecastTime = 0; - } - } } } + } + } } /************************************************************************ Index: src/map/region.cpp =================================================================== --- src/map/region.cpp (revision 3520) +++ src/map/region.cpp (working copy) @@ -28,8 +28,8 @@ /************************************************************************ * * -* При инициализации области задаем уникальный номер в пределах зоны. * -* При попытке установить 0 в качестве номера выдаем предупреждение. * +* Initialization of the specified unique number within the zone. * +* If you try to set 0 as the number is issued a warning. * * * ************************************************************************/ @@ -45,7 +45,7 @@ /************************************************************************ * * -* Узнаем уникальный номер активной области * +* Know the unique number of the active region * * * ************************************************************************/ @@ -91,7 +91,7 @@ /************************************************************************ * * -* Устанавливаем верхний левый угол области * +* Set the upper left corner of the area * * * ************************************************************************/ @@ -104,7 +104,7 @@ /************************************************************************ * * -* Устанавливаем нижний правый угол области * +* Set the lower right corner of the area * * * ************************************************************************/ @@ -117,7 +117,7 @@ /************************************************************************ * * -* Проверяем, находится ли позиция внутри области * +* Check to see if the position is within the area * * * ************************************************************************/ Index: src/map/region.h =================================================================== --- src/map/region.h (revision 3520) +++ src/map/region.h (working copy) @@ -41,22 +41,22 @@ uint32 GetRegionID(); - int16 GetCount(); + int16 GetCount(); int16 AddCount(int16 count); int16 DelCount(int16 count); - void SetULCorner(float x, float y, float z); // верхний левый угол (Upper Left) - void SetLRCorner(float x, float y, float z); // нижний правый угол (Lower Right) + void SetULCorner(float x, float y, float z); // upper left corner (Upper Left) + void SetLRCorner(float x, float y, float z); // bottom-right corner (Lower Right) bool isPointInside(position_t pos); private: - uint32 m_RegionID; // номер региона - int16 m_Count; // количество персонажей в регионе + uint32 m_RegionID; // Region number + int16 m_Count; // number of characters in the region - float x1, y1, z1; // верхний левый угол - float x2, y2, z2; // лижний правый угол + float x1, y1, z1; // upper left corner + float x2, y2, z2; // lower right corner bool circle; }; Index: src/map/spell.cpp =================================================================== --- src/map/spell.cpp (revision 3520) +++ src/map/spell.cpp (working copy) @@ -31,12 +31,12 @@ { m_ID = id; - m_radius = 0; + m_radius = 0; m_mpCost = 0; m_castTime = 0; m_recastTime = 0; m_animation = 0; - m_AOE = 0; + m_AOE = 0; m_animationTime = 0; m_skillType = 0; m_zoneMisc = 0; @@ -380,18 +380,18 @@ /************************************************************************ * * -* Реализация namespase для работы с заклинаниями * +* Implementing namespase to work with spells * * * ************************************************************************/ namespace spell { - CSpell* PSpellList[MAX_SPELL_ID]; // список заклинаний + CSpell* PSpellList[MAX_SPELL_ID]; // Spell list std::map PMobSkillToBlueSpell[256]; // maps the skill id (key) to spell id (value). /************************************************************************ * * - * Загружаем список заклинаний * + * Load the list of spells * * * ************************************************************************/ Index: src/map/spell.h =================================================================== --- src/map/spell.h (revision 3520) +++ src/map/spell.h (working copy) @@ -33,7 +33,7 @@ #include "charentity.h" #define CANNOT_USE_SPELL 0 -#define MAX_SPELL_ID 800 +#define MAX_SPELL_ID 901 enum SPELLGROUP { @@ -153,7 +153,7 @@ uint8 m_ValidTarget; // target pc/npc/both SPELLGROUP m_spellGroup; // spellgroup uint16 m_zoneMisc; // условия чтения заклинаний в зонах - uint8 m_AOE; // aoe or single target spell + uint8 m_AOE; // aoe or single target spell uint16 m_base; // spell base damage float m_multiplier; // multiplier for upper tier spells uint16 m_element; // element of spell @@ -171,7 +171,7 @@ /************************************************************************ * * -* namespase для работы с заклинаниями * +* Namespase to work with spells * * * ************************************************************************/ Index: src/map/status_effect.h =================================================================== --- src/map/status_effect.h (revision 3520) +++ src/map/status_effect.h (working copy) @@ -45,12 +45,12 @@ EFFECTFLAG_NONE = 0x0000, EFFECTFLAG_DISPELABLE = 0x0001, EFFECTFLAG_ERASABLE = 0x0002, - EFFECTFLAG_ATTACK = 0x0004, // исчезает при нанесении урона + EFFECTFLAG_ATTACK = 0x0004, // ​​disappears on damage - EFFECTFLAG_DAMAGE = 0x0010, // исчезает при получении урона - EFFECTFLAG_DEATH = 0x0020, // исчезает при смерти - EFFECTFLAG_MAGIC_BEGIN = 0x0040, // исчезает перед началом чтения заклинания - EFFECTFLAG_MAGIC_END = 0x0080, // исчезает после прочтения заклинания + EFFECTFLAG_DAMAGE = 0x0010, // disappears when damaged + EFFECTFLAG_DEATH = 0x0020, // disappears at death + EFFECTFLAG_MAGIC_BEGIN = 0x0040, // ​​disappears before reading spells + EFFECTFLAG_MAGIC_END = 0x0080, // ​​disappears after reading spells EFFECTFLAG_ON_ZONE = 0x0100, EFFECTFLAG_NO_LOSS_MESSAGE = 0x0200, // Suppress effect worn off message. EFFECTFLAG_INVISIBLE = 0x0400, // invisible effect @@ -83,6 +83,10 @@ EFFECT_ADDLE = 21, EFFECT_INTIMIDATE = 22, EFFECT_KAUSTRA = 23, + EFFECT_ST24 = 24, + EFFECT_ST25 = 25, + EFFECT_ST26 = 26, + EFFECT_ST27 = 27, EFFECT_TERROR = 28, EFFECT_MUTE = 29, EFFECT_BANE = 30, @@ -280,6 +284,9 @@ EFFECT_DIRGE = 221, EFFECT_SCHERZO = 222, EFFECT_NOCTURNE = 223, + EFFECT_ST224 = 224, + EFFECT_ST225 = 225, + EFFECT_ST226 = 226, EFFECT_STORE_TP = 227, EFFECT_EMBRAVA = 228, EFFECT_MANAWELL = 229, @@ -425,6 +432,9 @@ EFFECT_ASPIR_SAMBA = 369, EFFECT_HASTE_SAMBA = 370, EFFECT_VELOCITY_SHOT = 371, + // . = 372, + // . = 373, + // . = 374, EFFECT_BUILDING_FLOURISH = 375, EFFECT_TRANCE = 376, EFFECT_TABULA_RASA = 377, @@ -522,13 +532,106 @@ EFFECT_PERPETUANCE = 469, EFFECT_IMMANENCE = 470, EFFECT_MIGAWARI = 471, - EFFECT_AVATAR = 491, - - EFFECT_NINJUTSU_ELE_DEBUFF = 510, - EFFECT_HEALING = 512, // TODO: > 768 - EFFECT_LEAVEGAME = 513, // TODO: > 768 - EFFECT_SKILLCHAIN = 514, // TODO: > 768 - + EFFECT_TERNARY_FLOURISH = 472, + EFFECT_MUDDLE = 473, + EFFECT_PROWESS = 474, + EFFECT_VOIDWATCHER = 475, + EFFECT_ENSPHERE = 476, + EFFECT_SACROSANCTITY = 477, + EFFECT_PALISADE = 478, + EFFECT_SCARLET_DELIRIUM_I = 479, + EFFECT_SCARLET_DELIRIUM_II = 480, + // NONE = 481, + EFFECT_DECOY_SHOT = 482, + EFFECT_HAGAKURE = 483, + EFFECT_ISSEKIGAN = 484, + EFFECT_UNBRIDLED_LEARNING = 485, + EFFECT_COUNTER_BOOST = 486, + EFFECT_ENDRAIN = 487, + EFFECT_ENASPIR = 488, + EFFECT_AFTERGLOW = 489, + EFFECT_IMMINENT_STRIKES = 490, + EFFECT_AVATAR = 491, // CONSUMMATE_COUNTER in POLutils + EFFECT_ASYLUM = 492, + EFFECT_SUBTLE_SORCERY = 493, + EFFECT_ENCOMIUM = 494, + EFFECT_BAMBOOZLE = 495, + EFFECT_RIGHTEOUS_GAURD = 496, + EFFECT_SOUL_ENSLAVEMENT = 497, + EFFECT_BST_SP2 = 498, + EFFECT_MALINCONICO = 499, + EFFECT_INSTINCTIVE_AIM = 500, + EFFECT_YAEGASUMI = 501, + EFFECT_TENGEN = 502, + EFFECT_ROUSE_WYVERN = 503, + EFFECT_ASTRAL_CONDUIT = 504, + EFFECT_UNBRIDLED_WISDOM = 505, + EFFECT_THREE_TO_ONE = 506, + EFFECT_GRAND_PAS = 507, + // EFFECT_NONE = 508, + // EFFECT_NONE = 509, + EFFECT_NINJUTSU_ELE_DEBUFF = 510, // EFFECT_ERGON_MIGHT + EFFECT_REIVE_MARK = 511, + EFFECT_HEALING = 512, // EFFECT_IONIS + EFFECT_LEAVEGAME = 513, // EFFECT_BOLSTER + EFFECT_SKILLCHAIN = 514, // EFFECT_NONE + EFFECT_LASTING_EMANATION = 515, + EFFECT_ECLIPTIC_ATTRITION = 516, + EFFECT_COLLIMATED_FERVOR = 517, + EFFECT_DEMATERIALIZE = 518, + EFFECT_THEURGIC_FOCUS = 519, + // EFFECT_NONE = 520, + // EFFECT_NONE = 521, + EFFECT_ELEMENTAL_SFORZO = 522, + EFFECT_IGNIS = 523, + EFFECT_GELUS = 524, + EFFECT_FLABRA = 525, + EFFECT_TELLUS = 526, + EFFECT_SULPOR = 527, + EFFECT_UNDA = 528, + EFFECT_LUX = 529, + EFFECT_TENEBRAE = 530, + EFFECT_VALLATION = 531, + EFFECT_SWORDPLAY = 532, + EFFECT_PFLUG = 533, + EFFECT_EMBOLDEN = 534, + EFFECT_VALIANCE = 535, + EFFECT_GAMBIT = 536, + EFFECT_LIEMENT = 537, + EFFECT_ONE_FOR_ALL = 538, + EFFECT_REGEN_II = 539, + EFFECT_POISON_II = 540, + EFFECT_REFRESH_II = 541, + EFFECT_STR_BOOST_III = 542, + EFFECT_DEX_BOOST_III = 543, + EFFECT_VIT_BOOST_III = 544, + EFFECT_AGI_BOOST_III = 545, + EFFECT_INT_BOOST_III = 546, + EFFECT_MND_BOOST_III = 547, + EFFECT_CHR_BOOST_III = 548, + EFFECT_ATTACK_BOOST_II = 549, + EFFECT_DEFENSE_BOOST_II = 550, + EFFECT_MAGIC_ATK_BOOST_II = 551, + EFFECT_MAGIC_DEF_BOOST_II = 552, + EFFECT_ACCURACY_BOOST_II = 553, + EFFECT_EVASION_BOOST_II = 554, + EFFECT_MAGIC_ACC_BOOST_II = 555, + EFFECT_MAGIC_EVASION_BOOST_II = 556, + EFFECT_ATTACK_DOWN_II = 557, + EFFECT_DEFENSE_DOWN_II = 558, + EFFECT_MAGIC_ATK_DOWN_II = 559, + EFFECT_MAGIC_DEF_DOWN_II = 560, + EFFECT_ACCURACY_DOWN_II = 561, + EFFECT_EVASION_DOWN_II = 562, + EFFECT_MAGIC_ACC_DOWN_II = 563, + EFFECT_MAGIC_EVASION_DOWN_II = 564, + EFFECT_SLOW_II = 565, + EFFECT_PARALYSIS_II = 566, + EFFECT_WEIGHT_II = 567, + EFFECT_FOIL = 568, + EFFECT_BLAZE_OF_GLORY = 569, + // 570 - 639 NONE on POL Utils + EFFECT_DYNAMIS = 800 }; @@ -536,10 +639,10 @@ /************************************************************************ * * -* Нерешенные задачи: * +* Pending problem: * * * -* - сохранение ID сущности, добавившей эффект * -* - обновление эффекта (например перезапись protect 1 на protect 2) * +* - Save ID essence, add effects * +* - Update effect (eg overwrite protect 1 to protect 2) * * * ************************************************************************/ @@ -584,7 +687,7 @@ const int8* GetName(); - std::vector modList; // список модификаторов + std::vector modList; // list of modifiers CStatusEffect( EFFECT id, @@ -600,23 +703,23 @@ private: - CBattleEntity* m_POwner; // владелец + CBattleEntity* m_POwner; // owner - EFFECT m_StatusID; // основной тип эффекта - uint16 m_SubID; // дополнительный тип эффекта - uint16 m_Icon; // иконка эффекта - uint16 m_Power; // сила эффекта + EFFECT m_StatusID; // main type of effect + uint16 m_SubID; // additional effect type + uint16 m_Icon; // Icon effect + uint16 m_Power; // force effect uint16 m_SubPower; // Secondary power of the effect uint16 m_Tier; // Tier of the effect - uint16 m_Flag; // флаг эффекта (условия его исчезновения) - uint16 m_Type; // used to enforce only one + uint16 m_Flag; // flag effect (the conditions of his disappearance) + uint16 m_Type; // used to enforce only one - uint32 m_TickTime; // время повторения эффекта (млс) - uint32 m_Duration; // продолжительность эффекта (млс) - uint32 m_StartTime; // время получения эффекта (млс) - uint32 m_LastTick; // премя последнего выполнения эффекта (млс) + uint32 m_TickTime; // the repetition effect (MLS) + uint32 m_Duration; // duration of effect (MLS) + uint32 m_StartTime; // obtain the effect of time (msec) + uint32 m_LastTick; // Prem last run effect (MLS) - string_t m_Name; // имя эффекта для скриптов + string_t m_Name; // effect name for scripts }; #endif Index: src/map/status_effect_container.cpp =================================================================== --- src/map/status_effect_container.cpp (revision 3520) +++ src/map/status_effect_container.cpp (working copy) @@ -62,7 +62,7 @@ { /************************************************************************ * * - * Контейнер параметров эффектов * + * Container effect parameters * * * ************************************************************************/ @@ -160,7 +160,7 @@ /************************************************************************ * * -* Получаем количество эффектов с указанным subid * +* Get the number of effects with this subid * * * ************************************************************************/ @@ -292,8 +292,8 @@ /************************************************************************ * * -* Добавляем статус-эффект в контейнер * -* Если не ошибаюсь, то максимально-возможное количество эффектов 32 * +* Add a status effect in the container * +* If I'm not mistaken, the maximum possible number of effects 32 * * * ************************************************************************/ @@ -361,8 +361,8 @@ /************************************************************************ * * -* Эффекты во всех методах удаляются одинаково, вынес этот код в * -* отдельную функцию. Удаляем иконки только у CharEntity. * +* The effects of all the methods are removed the same way, made this * +* code a function. Remove icons only CharEntity. * * * ************************************************************************/ @@ -406,8 +406,8 @@ /************************************************************************ * * -* Удаляем статус-эффект по его основному и дополнительному типам. * -* Возвращаем результат выполнения операции. * +* Removes status effect on its main and additional types. * +* Return the result of the operation. * * * ************************************************************************/ @@ -492,7 +492,7 @@ /************************************************************************ * * -* Удаляем все эффекты с указанными иконками * +* Remove all effects with these icons * * * ************************************************************************/ @@ -522,7 +522,7 @@ /************************************************************************ * * -* Удаляем все эффекты с указанными флагами * +* Remove all effects with the specified flag * * * ************************************************************************/ @@ -539,8 +539,8 @@ /************************************************************************ * * -* Удаляем первый добавленный отрицательный эффект с флагом erase. * -* Возвращаем результат выполнения операции. * +* Removes the first addition to the negative effect of the flag erase. * +* Return the result of the operation. * * * ************************************************************************/ @@ -586,8 +586,8 @@ /************************************************************************ * * -* Удаляем первый добавленный положительный эффект с флагом dispel. * -* Возвращаем результат выполнения операции. * +* Removes the first addition to the positive effect of the flag dispel.* +* Return the result of the operation. * * * ************************************************************************/ @@ -633,7 +633,7 @@ /************************************************************************ * * -* Проверяем наличие статус-эффекта в контейнере * +* Check if the status effect in the container * * * ************************************************************************/ @@ -794,7 +794,7 @@ /************************************************************************ * * -* Проверяем наличие статус-эффекта в контейнере с уникальным subid * +* Check if the status effect in a container with a unique subid * * * ************************************************************************/ @@ -879,7 +879,7 @@ /************************************************************************ * * -* Пересчитываем иконки всех эфффектов * +* Will recalculate all effects * * * ************************************************************************/ @@ -916,7 +916,7 @@ /************************************************************************ * * -* Устанавливаем имя эффекта для работы со скриптами * +* Set the name of the effect to work with scripts * * * ************************************************************************/ @@ -964,7 +964,7 @@ /************************************************************************ * * -* Загружаем эффекты персонажа * +* Load effects of the character * * * ************************************************************************/ @@ -1011,12 +1011,12 @@ } } } - m_POwner->UpdateHealth(); // после загрузки эффектов пересчитываем максимальное количество HP/MP + m_POwner->UpdateHealth(); // after loading effects recalculate the maximum amount of HP / MP } /************************************************************************ * * -* Сохраняем временные эффекты персонажа * +* Save time effects of the character * * * ************************************************************************/ @@ -1056,8 +1056,8 @@ /************************************************************************ * * -* Проверяем все эффекты на необходимость удаление, если их срок * -* действия истек. * +* Check all the effects of the need for removal if their duration * +* expired. * * * ************************************************************************/ Index: src/map/status_effect_container.h =================================================================== --- src/map/status_effect_container.h (revision 3520) +++ src/map/status_effect_container.h (working copy) @@ -41,8 +41,8 @@ { public: - uint64 m_Flags; // биты переполнения байтов m_StatusIcons (по два бита на каждый эффект) - uint8 m_StatusIcons[32]; // иконки статус-эффектов + uint64 m_Flags; // overflow bits bytes m_StatusIcons (two bits for each effect) + uint8 m_StatusIcons[32]; // icon status effects bool ApplyBardEffect(CStatusEffect* PStatusEffect, uint8 maxSongs); bool ApplyCorsairEffect(CStatusEffect* PStatusEffect, uint8 maxRolls, uint8 bustDuration); @@ -51,33 +51,33 @@ bool DelStatusEffect(EFFECT StatusID); bool DelStatusEffectSilent(EFFECT StatusID); bool DelStatusEffect(EFFECT StatusID, uint16 SubID); - void DelStatusEffectsByFlag(uint16 flag); // удаляем все эффекты с указанным типом - void DelStatusEffectsByIcon(uint16 IconID); // удаляем все эффекты с указанной иконкой + void DelStatusEffectsByFlag(uint16 flag); // remove all the effects of a specified type + void DelStatusEffectsByIcon(uint16 IconID); // remove all the effects of a specified icon void DelStatusEffectsByType(uint16 Type); bool DelStatusEffectWithPower(EFFECT StatusID, uint16 power); void KillAllStatusEffect(); - bool HasStatusEffect(EFFECT StatusID); // проверяем наличие эффекта - bool HasStatusEffect(EFFECT StatusID, uint16 SubID); // проверяем наличие эффекта с уникальным subid + bool HasStatusEffect(EFFECT StatusID); // check for the effect of + bool HasStatusEffect(EFFECT StatusID, uint16 SubID); // check for the effect of a unique subid bool HasStatusEffectByFlag(uint16 flag); - EFFECT EraseStatusEffect(); // удаляем первый отрицательный эффект - uint8 EraseAllStatusEffect(); // erases all status effects - EFFECT DispelStatusEffect(); // удаляем первый положительный эффект - uint8 DispelAllStatusEffect(); // dispels all status effects - CStatusEffect* StealStatusEffect(); // dispels one effect and returns it + EFFECT EraseStatusEffect(); // Removes the first negative effect + uint8 EraseAllStatusEffect(); // erases all status effects + EFFECT DispelStatusEffect(); // Removes the first positive effect + uint8 DispelAllStatusEffect(); // dispels all status effects + CStatusEffect* StealStatusEffect(); // dispels one effect and returns it CStatusEffect* GetStatusEffect(EFFECT StatusID); CStatusEffect* GetStatusEffect(EFFECT StatusID, uint16 SubID); - void UpdateStatusIcons(); // пересчитываем иконки эффектов + void UpdateStatusIcons(); // recalculate the effects will void CheckEffects(uint32 tick); void CheckRegen(uint32 tick); - void LoadStatusEffects(); // загружаем эффекты персонажа - void SaveStatusEffects(); // сохраняем эффекты персонажа + void LoadStatusEffects(); // load the effects of the character + void SaveStatusEffects(); // save the character effects - uint8 GetEffectsCount(uint16 SubID); // получаем количество эффектов с указанным subid + uint8 GetEffectsCount(uint16 SubID); // get the number of effects with this subid bool CheckForElevenRoll(); bool HasBustEffect(uint16 id); @@ -91,8 +91,8 @@ CBattleEntity* m_POwner; // void ReplaceStatusEffect(EFFECT effect); //this needs to be implemented - void RemoveStatusEffect(uint32 id, bool silent = false); // удаляем эффект по его номеру в контейнере - void SetEffectParams(CStatusEffect* StatusEffect); // устанавливаем имя эффекта + void RemoveStatusEffect(uint32 id, bool silent = false); // remove the effect on its number in the container + void SetEffectParams(CStatusEffect* StatusEffect); // Set the name of the effect void OverwriteStatusEffect(CStatusEffect* StatusEffect); Index: src/map/synthutils.cpp =================================================================== --- src/map/synthutils.cpp (revision 3520) +++ src/map/synthutils.cpp (working copy) @@ -44,7 +44,7 @@ #include "vana_time.h" #include "zoneutils.h" -//#define _DSP_SYNTH_DEBUG_MESSAGES_ // включаем отладочные сообщения +//#define _DSP_SYNTH_DEBUG_MESSAGES_ // turn on debug messages enum SYNTHESIS_ELEMENT { @@ -71,19 +71,20 @@ namespace synthutils { -/************************************************************************ -* * -* Проверяем наличие рецепта и возможности его синтеза (если его * -* сложность выше на 15 уровней, чем умение персонажа, то рецепт * -* считается сверх трудным и синтех отменяется). Так же собираем всю * -* необходимую информацию о рецепте, чтобы не обращаться к базе * -* несколько раз * -* * -* в поля itemID девятой ячейки сохраняем ID рецепта * -* в поля quantity 9-16 ячеек записываем требуемые значения skills * -* в поля itemID и slotID 10-14 ячеек записываем результаты синтеза * -* * -************************************************************************/ +/************************************************************************** +* * +* Check the presence of the counter and the possibility of its synthesis * +* (if it difficulty to 15 levels than the ability of the character, the * +* recipe is super difficult and sinteh canceled). Just collect all the * +* necessary information about the recipe, not to apply to the database * +* repeatedly * +* * +* In the field itemID ninth cells retain ID recipe * +* In the field of cell quantity 9-16 record the required values ​​of skills * +* In the field itemID slotID 10-14 cells and recorded the results of the * +* synthesis * +* * +**************************************************************************/ bool isRightRecipe(CCharEntity* PChar) { @@ -117,7 +118,7 @@ PChar->Container->getItemID(7), PChar->Container->getItemID(8)); - if (ret != SQL_ERROR && + if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS) { @@ -125,7 +126,7 @@ if ((KeyItemID == 0) || (charutils::hasKeyItem(PChar,KeyItemID))) { - // в девятую ячейку записываем id рецепта + // in the ninth cell id write a prescription PChar->Container->setItem(9, Sql_GetUIntData(SqlHandle,0),0xFF,0); #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"Recipe matches ID %u.\n" CL_RESET, PChar->Container->getItemID(9)); @@ -137,16 +138,16 @@ PChar->Container->setItem(10 + 4, (uint16)Sql_GetUIntData(SqlHandle,13), (uint8)Sql_GetUIntData(SqlHandle,17), 0); // RESULT_HQ3 uint16 skillValue = 0; - uint16 currentSkill = 0; + uint16 currentSkill = 0; for (uint8 skillID = 49; skillID < 57; ++skillID) { skillValue = (uint16)Sql_GetUIntData(SqlHandle,(skillID-49+2)); currentSkill = PChar->RealSkills.skill[skillID]; - // skill записываем в поле quantity ячеек 9-16 + // skill recorded in the quantity of cells 9-16 PChar->Container->setQuantity(skillID-40, skillValue); - + #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"Current skill = %u, Recipe skill = %u\n" CL_RESET, currentSkill, skillValue*10); #endif @@ -180,8 +181,8 @@ /************************************************************************ * * -* Расчитываем сложность синтеза для конкретного умения. Хорошо бы * -* сохранять результат в какой-нибудь ячейке контейнера (тип dooble) * +* Computes the complexity of the synthesis of a specific skill. It * +* would be nice store the result in some cell container (type double) * * * ************************************************************************/ @@ -237,7 +238,7 @@ }else if (WeekDay == LIGHTSDAY){ difficult -= 1; }else if (WeekDay == DARKSDAY){ - difficult += 1; + difficult += 1; } #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ @@ -246,20 +247,20 @@ ShowDebug(CL_CYAN"Moon = %g\n" CL_RESET, MoonPhase); ShowDebug(CL_CYAN"Difficulty = %g\n" CL_RESET, difficult); #endif - + return difficult; } /************************************************************************ * * -* Проверяем возможность создания предметов высокого качества * -* Это сделано из-за наличия в игре специфических колец. * +* Check the possibility of creating high quality items * +* This is done because of the game-specific ring. * * * ************************************************************************/ bool canSynthesizeHQ(CCharEntity* PChar, uint8 skillID) { - uint16 ModID = 0; + uint16 ModID = 0; switch (skillID) { @@ -278,8 +279,8 @@ /************************************************************************ * * -* Получаем ID главного умения в рецепте. Именно от него зависит * -* возможность создания предметов высокого качества * +* Obtain the ID of the main skills in the recipe. That depends on it * +* The ability to create high quality items * * * ************************************************************************/ @@ -287,8 +288,8 @@ { uint8 skillValue = 0; uint8 generalCraft = 0; - - for(uint8 skillID = 49; skillID < 57; skillID ++) + + for(uint8 skillID = 49; skillID < 57; skillID ++) { if (PChar->Container->getQuantity(skillID-40) > skillValue) { @@ -300,17 +301,16 @@ return generalCraft; } -/************************************************************************ -* * -* Расчет результата синтеза. * -* * -* результат синтеза записываем в поле quantity ячейки кристалла. * -* сохраняем в slotID ячейки кристалла ID умения, из-за котороги синтез * -* провалился. * -* * -************************************************************************/ +/************************************************************************** +* * +* The calculation results of synthesis. * +* * +* The result of the synthesis is recorded in the quantity of the crystal * +* cell. Store in slotID crystal cell ID skills, because synthesis Failed. * * +* * +**************************************************************************/ -uint8 calcSynthResult(CCharEntity* PChar) +uint8 calcSynthResult(CCharEntity* PChar) { uint8 count = 0; uint8 result = 0; @@ -319,18 +319,19 @@ double success = 0; double chance = 0; - for(uint8 skillID = 49; skillID < 57; ++skillID) + for(uint8 skillID = 49; skillID < 57; ++skillID) { uint8 checkSkill = PChar->Container->getQuantity(skillID-40); - if(checkSkill != 0) + if(checkSkill != 0) { double synthDiff = getSynthDifficulty(PChar, skillID); hqtier = 0; count++; - if(synthDiff <= 0) + if(synthDiff <= 0) { success = 0.95; + synthDiff -= map_config.craft_success; if((synthDiff <= 0) && (synthDiff >= -10)){ success -= (double)(PChar->Container->getType() == ELEMENT_LIGHTNING) * 0.2; @@ -344,7 +345,7 @@ }else if (synthDiff <= -71) hqtier = 5; }else{ - success = 0.95 - (synthDiff / 10) - (double)(PChar->Container->getType() == ELEMENT_LIGHTNING) * 0.2; + success = 0.95 - (synthDiff / 10) - (double)(PChar->Container->getType() == ELEMENT_LIGHTNING) * 0.2; if(success < 0.05) success = 0.05; } @@ -354,16 +355,16 @@ ShowDebug(CL_CYAN"Success: %g Random: %g\n" CL_RESET, success, random); #endif - if(random < success) + if(random < (success + map_config.craft_success*.01)) { - for(int32 i = 0; i < 3; ++i) + for(int32 i = 0; i < 3; ++i) { random = rand() / ((double) RAND_MAX); #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"HQ Tier: %i Random: %g\n" CL_RESET, hqtier, random); #endif - - switch(hqtier) + + switch(hqtier) { case 5: chance = 0.700; break; case 4: chance = 0.500; break; @@ -372,14 +373,14 @@ case 1: chance = 0.015; break; default: chance = 0.000; break; } - if(chance < random) + if((chance + map_config.craft_success*.01) < random) break; result += 1; hqtier -= 1; } }else{ - // сохраняем умение, из-за которого синтез провалился. - // используем slotID ячейки кристалла, т.к. он был удален еще в начале синтеза + // Save the ability, because of which the synthesis failed. + // Use slotID crystal cell, as it was removed at the beginning of the synthesis PChar->Container->setInvSlotID(0,skillID); result = -1; break; @@ -394,7 +395,7 @@ result = SYNTHESIS_SUCCESS; } - // результат синтеза записываем в поле quantity ячейки кристалла. + // result of synthesis is recorded in the quantity of the crystal cell. PChar->Container->setQuantity(0, result); switch(result) @@ -435,15 +436,16 @@ /************************************************************************ * * -* Пытаемся увеличить умение персонажа. * -* Desynthesis (разбор предметов на запчасть) не увеличивает умение. * +* Trying to increase the ability of the character. * +* Desynthesis (analysis of objects on spare part) does not increase * +* the skill. * * * -* Ломать не строить. Ломание столов и стульев не сделает из нас * -* плотника, значит умение в данном случае не повышается. * +* Break down than to build. Breaking tables and chairs will not make us* +* Carpenter, so in this case the ability to not rise. * * * ************************************************************************/ -int32 doSynthSkillUp(CCharEntity* PChar) +int32 doSynthSkillUp(CCharEntity* PChar) { if (PChar->Container->getType() == ELEMENT_LIGHTNING) { @@ -453,21 +455,21 @@ double MoonPhase = (double)CVanaTime::getInstance()->getMoonPhase(); double MoonCorrection = MoonPhase / 500; - for(uint8 skillID = 49; skillID < 57; ++skillID) + for(uint8 skillID = 49; skillID < 57; ++skillID) { - if (PChar->Container->getQuantity(skillID-40) == 0) // получаем необходимый уровень умения рецепта + if (PChar->Container->getQuantity(skillID-40) == 0) // ability to obtain the necessary level of prescription { continue; } - uint8 skillRank = 9; //PChar->RealSkills.rank[skillID]; - uint16 maxSkill = (skillRank+1)*100; + uint8 skillRank = PChar->RealSkills.rank[skillID]; // 9 + uint16 maxSkill = 1100; int32 charSkill = PChar->RealSkills.skill[skillID]; int32 basDiff = PChar->Container->getQuantity(skillID-40) - charSkill/10; double synthDiff = getSynthDifficulty(PChar, skillID); - if ((basDiff <= 0) || ((basDiff > 5) && (PChar->Container->getQuantity(0) == SYNTHESIS_FAIL))) // результат синтеза хранится в quantity нулевой ячейки + if (map_config.craft_skill_onfail == 0 && ((basDiff <= 0) || ((basDiff > 5) && (PChar->Container->getQuantity(0) == SYNTHESIS_FAIL)))) // the result is stored in the synthesis quantity zero cell { return 0; } @@ -475,19 +477,24 @@ if (charSkill < maxSkill) { double skillUpChance = (synthDiff*(map_config.craft_multiplier - (log(1.2 + charSkill/100) + MoonCorrection)))/10; - skillUpChance = skillUpChance/(1 + (PChar->Container->getQuantity(0) == SYNTHESIS_FAIL)); // результат синтеза хранится в quantity нулевой ячейки + if (map_config.craft_skill_onfail == 0) + { + skillUpChance = skillUpChance/(1 + (PChar->Container->getQuantity(0) == SYNTHESIS_FAIL)); // the result is stored in the synthesis quantity zero cell + } double random = rand() / ((double)RAND_MAX); #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"Skill up chance: %g Random: %g\n" CL_RESET, skillUpChance, random); #endif - if (random < skillUpChance) + if (random < (skillUpChance + map_config.craft_skillamt*.01)) { int32 satier = 0; int32 skillAmount = 1; double chance = 0; + synthDiff += (map_config.craft_skillamt*.1); + if((synthDiff >= 1) && (synthDiff < 3)){ satier = 1; }else if((synthDiff >= 3) && (synthDiff < 5)){ @@ -500,15 +507,15 @@ satier = 5; //if (skillRank > 5) // satier--; - - for(uint8 i = 0; i < 4; i ++) + + for(uint8 i = 0; i < 4; i ++) { random = rand() / ((double)RAND_MAX); #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"SkillAmount Tier: %i Random: %g\n" CL_RESET, satier, random); #endif - - switch(satier) + + switch(satier) { case 5: chance = 0.900; break; case 4: chance = 0.700; break; @@ -517,7 +524,7 @@ case 1: chance = 0.100; break; default: chance = 0.000; break; } - if(chance < random) + if((chance + map_config.craft_skillamt*.01) < random) break; skillAmount += 1; satier -= 1; @@ -528,15 +535,15 @@ skillAmount = maxSkill - charSkill; } - PChar->RealSkills.skill[skillID] += skillAmount; + PChar->RealSkills.skill[skillID] += skillAmount; PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, skillAmount, 38)); - if((charSkill/10) < (charSkill + skillAmount)/10) + if((charSkill/10) < (charSkill + skillAmount)/10) { PChar->WorkingSkills.skill[skillID] += 0x20; PChar->pushPacket(new CCharSkillsPacket(PChar)); - PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, (charSkill + skillAmount)/10, 53)); + PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, (charSkill + skillAmount)/10, 53)); } charutils::SaveCharSkills(PChar, skillID); @@ -548,22 +555,22 @@ /************************************************************************ * * -* Синтез завершился неудачей. Решаем вопрос, сколько ингредиентов * -* потеряет персонаж. Вероятность потери зависить от умения, из-за * -* которого синтез провалился. ID умения сохранен в slotID ячейки * -* кристалла. * +* Synthesis failed. Solve the question of how many ingredients * +* lose character. The probability of loss depends on the ability, * +* because of the which is the synthesis failed. ID stored in the * +* ability of the cell slotID Crystal. * * * ************************************************************************/ -int32 doSynthFail(CCharEntity* PChar) +int32 doSynthFail(CCharEntity* PChar) { uint8 carrentCraft = PChar->Container->getInvSlotID(0); double synthDiff = getSynthDifficulty(PChar, carrentCraft); double moghouseAura = 0; - if (PChar->getZone() == 0) // неправильное условие, т.к. аура действует лишь в собственном доме + if (PChar->getZone() == 0) // abnormal condition, because Aura acts only in his own home { - // Проверяем элемент синтеза + // Check item synthesis switch (PChar->Container->getType()) { case ELEMENT_FIRE: moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_FIRE); break; @@ -610,17 +617,17 @@ uint8 invSlotID = 0; uint8 nextSlotID = 0; uint8 lostCount = 0; - + double random = 0; double lostItem = 0.15 - moghouseAura + (synthDiff > 0 ? synthDiff/20 : 0); invSlotID = PChar->Container->getInvSlotID(1); - for(uint8 slotID = 1; slotID <= 8; ++slotID) + for(uint8 slotID = 1; slotID <= 8; ++slotID) { if (slotID != 8) nextSlotID = PChar->Container->getInvSlotID(slotID+1); - + random = rand() / ((double) RAND_MAX); #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"Lost Item: %g Random: %g\n" CL_RESET, lostItem, random); @@ -631,7 +638,7 @@ lostCount++; } - if(invSlotID != nextSlotID) + if(invSlotID != nextSlotID) { CItem* PItem = PChar->getStorage(LOC_INVENTORY)->GetItem(invSlotID); @@ -639,22 +646,22 @@ { PItem->setSubType(ITEM_UNLOCKED); - if(lostCount > 0) + if(lostCount > 0) { #ifdef _DSP_SYNTH_DEBUG_MESSAGES_ ShowDebug(CL_CYAN"Removing quantity %u from inventory slot %u\n" CL_RESET, lostCount, invSlotID); #endif - + charutils::UpdateItem(PChar, LOC_INVENTORY, invSlotID, -(int32)lostCount); lostCount = 0; - }else{ + }else{ PChar->pushPacket(new CInventoryAssignPacket(PItem, INV_NORMAL)); } } invSlotID = nextSlotID; nextSlotID = 0; } - if(invSlotID == 0xFF) + if(invSlotID == 0xFF) break; } @@ -675,8 +682,8 @@ /************************************************************************ * * -* Начало синтеза. * -* в поле type контейнера записываем элемент синтеза * +* Home synthesis. * +* In the container type recording element synthesis * * * ************************************************************************/ @@ -687,7 +694,7 @@ uint16 crystalType = PChar->Container->getItemID(0); - switch(crystalType) + switch(crystalType) { case 0x1000: case 0x108E: @@ -733,12 +740,12 @@ PChar->Container->setType(element); - if (!isRightRecipe(PChar)) + if (!isRightRecipe(PChar)) { return 0; } - // удаляем кристалл + // remove the crystal charutils::UpdateItem(PChar, LOC_INVENTORY, PChar->Container->getInvSlotID(0), -1); uint8 result = calcSynthResult(PChar); @@ -746,12 +753,12 @@ uint8 invSlotID = 0; uint8 tempSlotID = 0; uint16 itemID = 0; - uint32 quantity = 0; + uint32 quantity = 0; - for(uint8 slotID = 1; slotID <= 8; ++slotID) + for(uint8 slotID = 1; slotID <= 8; ++slotID) { tempSlotID = PChar->Container->getInvSlotID(slotID); - if ((tempSlotID != 0xFF) && (tempSlotID != invSlotID)) + if ((tempSlotID != 0xFF) && (tempSlotID != invSlotID)) { invSlotID = tempSlotID; @@ -770,23 +777,23 @@ if(PChar->loc.zone->GetID() != 255 && PChar->loc.zone->GetID() != 0) { - PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, new CSynthAnimationPacket(PChar,effect,result)); + PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE_SELF, new CSynthAnimationPacket(PChar,effect,result)); } else { PChar->pushPacket(new CSynthAnimationPacket(PChar, effect, result)); } - + return 0; } /************************************************************************ * * -* Отправляем результат синтеза персонажу * +* Send the result of synthesis of character * * * ************************************************************************/ -int32 doSynthResult(CCharEntity* PChar) +int32 doSynthResult(CCharEntity* PChar) { uint8 m_synthResult = PChar->Container->getQuantity(0); @@ -795,19 +802,19 @@ doSynthFail(PChar); }else{ uint16 itemID = PChar->Container->getItemID(10 + m_synthResult); - uint8 quantity = PChar->Container->getInvSlotID(10 + m_synthResult); // к сожалению поле quantity занято + uint8 quantity = PChar->Container->getInvSlotID(10 + m_synthResult); // Unfortunately field quantity employed uint8 invSlotID = 0; uint8 nextSlotID = 0; uint8 removeCount = 0; invSlotID = PChar->Container->getInvSlotID(1); - - for(uint8 slotID = 1; slotID <= 8; ++slotID) + + for(uint8 slotID = 1; slotID <= 8; ++slotID) { nextSlotID = (slotID != 8 ? PChar->Container->getInvSlotID(slotID+1) : 0); removeCount++; - + if (invSlotID != nextSlotID) { if (invSlotID != 0xFF) @@ -816,7 +823,7 @@ ShowDebug(CL_CYAN"Removing quantity %u from inventory slot %u\n" CL_RESET,removeCount,invSlotID); #endif PChar->getStorage(LOC_INVENTORY)->GetItem(invSlotID)->setSubType(ITEM_UNLOCKED); - charutils::UpdateItem(PChar, LOC_INVENTORY, invSlotID, -(int32)removeCount); + charutils::UpdateItem(PChar, LOC_INVENTORY, invSlotID, -(int32)removeCount); } invSlotID = nextSlotID; nextSlotID = 0; @@ -824,7 +831,7 @@ } } - // TODO: перейти на новую функцию AddItem, чтобы не обновлять signature ручками + // TODO: move to a new function AddItem, not to update the signature pens invSlotID = charutils::AddItem(PChar, LOC_INVENTORY, itemID, quantity); @@ -834,6 +841,7 @@ { if ((PItem->getFlag() & ITEM_FLAG_INSCRIBABLE) && (PChar->Container->getItemID(0) > 0x1080)) { + // TODO: render method uitls (add a method reverse acting) int8 encodedSignature [16]; PItem->setSignature(EncodeStringSignature((int8*)PChar->name.c_str(), encodedSignature)); @@ -868,12 +876,12 @@ /************************************************************************ * * -* Завершаем синтез * +* complete the synthesis * * * ************************************************************************/ -int32 sendSynthDone(CCharEntity* PChar) -{ +int32 sendSynthDone(CCharEntity* PChar) +{ doSynthResult(PChar); PChar->animation = ANIMATION_NONE; Index: src/map/synthutils.h =================================================================== --- src/map/synthutils.h (revision 3520) +++ src/map/synthutils.h (working copy) @@ -28,7 +28,7 @@ /************************************************************************ * * -* Все методы, необходимые для работы синтеза * +* All methods required for the synthesis * * * ************************************************************************/ Index: src/map/time_server.cpp =================================================================== --- src/map/time_server.cpp (revision 3520) +++ src/map/time_server.cpp (working copy) @@ -30,6 +30,7 @@ #include "zoneutils.h" #include "conquest_system.h" #include "lua/luautils.h" +#include "charutils.h" int32 time_server(uint32 tick,CTaskMgr::CTask* PTask) @@ -69,4 +70,10 @@ CTransportHandler::getInstance()->TransportTimer(); return 0; -} \ No newline at end of file +} + +int32 save_playtime(uint32 tick, CTaskMgr::CTask* PTask) +{ + zoneutils::SavePlayTime(); + return 0; +} Index: src/map/time_server.h =================================================================== --- src/map/time_server.h (revision 3520) +++ src/map/time_server.h (working copy) @@ -29,5 +29,6 @@ int32 time_server(uint32 tick,CTaskMgr::CTask*); +int32 save_playtime(uint32 tick, CTaskMgr::CTask*); #endif Index: src/map/trade_container.h =================================================================== --- src/map/trade_container.h (revision 3520) +++ src/map/trade_container.h (working copy) @@ -45,13 +45,13 @@ uint8 getType(); uint8 getItemsCount(); - uint8 getSlotCount(); // количество занятых ячеек - uint32 getTotalQuantity(); // общее количество предметов (gil считаются за 1) + uint8 getSlotCount(); // number of occupied cells + uint32 getTotalQuantity(); // total number of subjects (gil count as 1) CItem* getItem(uint8 slotID); uint16 getItemID(uint8 slotID); uint8 getInvSlotID(uint8 slotID); - uint32 getQuantity(uint8 slotID); // количество предметов в ячейке - uint32 getItemQuantity(uint16 itemID); // количество предметов одного типа + uint32 getQuantity(uint8 slotID); // number of items in the cell + uint32 getItemQuantity(uint16 itemID); // number of items of the same type void setType(uint8 type); void setItemsCount(uint8 count); @@ -61,12 +61,12 @@ void setQuantity(uint8 slotID, uint32 quantity); void setItem(uint8 slotID, uint16 itemID, uint8 invSlotID, uint32 quantity, CItem* item = NULL); - void Clean(); // отчищаем контейнер + void Clean(); // scrap container private: - uint8 m_type; // тип контейнера (тип кристалла, нация магазина и т.д.) - uint8 m_ItemsCount; // количество предметов в контейнере (устанавливаем самостоятельно) + uint8 m_type; // container type (type of crystal, Nation magazine, etc.) + uint8 m_ItemsCount; // number of items in a container (set your own) CItem* m_PItem[CONTAINER_SIZE]; uint8 m_slotID[CONTAINER_SIZE]; Index: src/map/trait.cpp =================================================================== --- src/map/trait.cpp (revision 3520) +++ src/map/trait.cpp (working copy) @@ -116,17 +116,17 @@ /************************************************************************ * * -* Реализация namespase для работы с traits * +* Implementing namespase to work with traits * * * ************************************************************************/ namespace traits { - TraitList_t PTraitsList[MAX_JOBTYPE]; // список traits, сгруппированный по профессиям + TraitList_t PTraitsList[MAX_JOBTYPE]; // list of traits, grouped by occupation /************************************************************************ * * - * Загружаем список traits * + * Load a list of traits * * * ************************************************************************/ @@ -176,6 +176,6 @@ void FreeTraitsList() { - // список освобождается операционной системой автоматически при завершении работы сервера + // List is released by the operating system automatically when the server } }; \ No newline at end of file Index: src/map/trait.h =================================================================== --- src/map/trait.h (revision 3520) +++ src/map/trait.h (working copy) @@ -1,4 +1,4 @@ -/* +/* =========================================================================== Copyright (c) 2010-2012 Darkstar Dev Teams @@ -79,6 +79,7 @@ TRAIT_RESIST_GRAVITY = 58, TRAIT_RESIST_SLOW = 59, TRAIT_RESIST_CHARM = 60, + TRAIT_RESIST_AMNESIA = 61, TRAIT_TREASURE_HUNTER_II = 64, TRAIT_GILFINDER_II = 65, TRAIT_KICK_ATTACKS = 66, @@ -113,9 +114,31 @@ TRAIT_OPTIMIZATION = 95, TRAIT_CLOSED_POSITION = 96, TRAIT_STORMSURGE = 97, + TRAIT_CRIT_ATK_BONUS = 98, + TRAIT_CRIT_DEF_BONUS = 99, + TRAIT_TACTICAL_PARRY = 100, + TRAIT_TACTICAL_GUARD = 101, + TRAIT_SHIELD_DEF_BONUS = 102, + TRAIT_STOUT_SERVANT = 103, + TRAIT_TRUE_SHOT = 104, + TRAIT_BLOOD_BOON = 105, + TRAIT_SKILLCHAIN_BONUS = 106, + TRAIT_FENCER = 107, + TRAIT_CONSERVE_TP = 108, + TRAIT_OCCULT_ACUMEN = 109, + TRAIT_MAGIC_BURST_BONUS = 110, + TRAIT_DIVINE_BENISON = 111, + TRAIT_ELEMENTAL_CELERITY = 112, + TRAIT_DEAD_AIM = 113, + TRAIT_TRANQUIL_HEART = 114, + TRAIT_STALWART_SOUL = 115, + TRAIT_WIDESCAN = 116, + TRAIT_CARDINAL_CHANT = 117, + TRAIT_TENACITY = 118, + TRAIT_INQUARTATA = 119, }; -#define MAX_TRAIT_ID 100 +#define MAX_TRAIT_ID 118 /************************************************************************ * * @@ -134,7 +157,7 @@ uint8 getLevel(); uint16 getMod(); int16 getValue(); - + void setJob(int8 job); void setLevel(uint8 level); void setMod(uint16 mod); @@ -143,7 +166,7 @@ private: uint8 m_id; - uint8 m_job; + uint8 m_job; uint8 m_level; uint16 m_mod; int16 m_value; @@ -151,7 +174,7 @@ /************************************************************************ * * -* namespase для работы с traits * +* Namespase to work with traits * * * ************************************************************************/ Index: src/map/transport.cpp =================================================================== --- src/map/transport.cpp (revision 3520) +++ src/map/transport.cpp (working copy) @@ -34,7 +34,7 @@ /************************************************************************ * * -* Создание глобальной ссылки на объект класса * +* Create a global reference to the class object * * * ************************************************************************/ @@ -50,7 +50,7 @@ /************************************************************************ * * -* В конструкторе инициализируем всю транспортную систему * +* In the constructor, initialize the whole transport system * * * ************************************************************************/ @@ -62,7 +62,7 @@ /************************************************************************ * * -* Инициализация транспорта (корабли и самолеты) * +* Initializing transport (ships and aircraft) * * * ************************************************************************/ @@ -128,7 +128,7 @@ /************************************************************************ * * -* Инициализация лифтов и автоматических дверей * +* Initialization elevators and automatic doors * * * ************************************************************************/ @@ -171,7 +171,7 @@ /************************************************************************ * * -* Все логика передвижения транспорта * +* All logic movement of transport * * * ************************************************************************/ @@ -179,8 +179,8 @@ { uint32 VanaTime = CVanaTime::getInstance()->getDate(); - // в портовых зонах необходимо написать макросы на случай, если персонаж вышел из игры в корабле. - // при входе в игру он должен оказаться на пристани + // To the port areas to write macros in case the person got out of the ship. + // When entering the game, he should be in the dock for(uint32 i = 0; i < TransportList.size(); ++i) { @@ -199,22 +199,22 @@ PTransport->Dock.zone->PushPacket(NULL, CHAR_INZONE, new CEntityUpdatePacket(PTransport->PTransportNPC, ENTITY_SPAWN)); } - // персонажи видят корабль, иначе ждем следующего прибытия + // Characters see the ship, or wait for the next arrival else if (PTransport->PTransportNPC->status == STATUS_NORMAL) { - // пора подтягивать пассажиров к выходу + // it's time to pull the passengers to exit if (ShipTimerOffset == PTransport->TimeAnimationArrive - 10) { PTransport->PTransportNPC->loc.boundary = 0; zoneutils::GetZone(PTransport->Dock.prevzone)->TransportDepart(PTransport->PTransportNPC); } - // корабль причалил, открываем двери пассажирам + // the ship docked, open the passenger door else if (ShipTimerOffset == PTransport->TimeAnimationArrive) { PTransport->PDoorNPC->animation = ANIMATION_OPEN_DOOR; PTransport->Dock.zone->PushPacket(PTransport->PDoorNPC, CHAR_INRANGE, new CEntityUpdatePacket(PTransport->PDoorNPC, ENTITY_UPDATE)); } - //корабль отчаливает + //ship cast off else if (ShipTimerOffset == PTransport->TimeAnimationArrive + PTransport->TimeWaiting) { PTransport->PDoorNPC->animation = ANIMATION_CLOSE_DOOR; @@ -227,7 +227,7 @@ PTransport->Dock.zone->PushPacket(PTransport->PDoorNPC, CHAR_INRANGE, new CEntityUpdatePacket(PTransport->PDoorNPC, ENTITY_UPDATE)); PTransport->Dock.zone->PushPacket(NULL, CHAR_INZONE, new CEntityUpdatePacket(PTransport->PTransportNPC, ENTITY_UPDATE)); } - //корабль исчезает + //ship disappears else if (ShipTimerOffset == PTransport->TimeAnimationArrive + PTransport->TimeWaiting + PTransport->TimeAnimationDepart) { PTransport->PTransportNPC->status = STATUS_DISAPPEAR; Index: src/map/treasure_pool.cpp =================================================================== --- src/map/treasure_pool.cpp (revision 3520) +++ src/map/treasure_pool.cpp (working copy) @@ -35,12 +35,12 @@ #include "treasure_pool.h" -#define TREASURE_CHECKTIME 2500 // частота проверки контейнера - 2.5 секунд -#define TREASURE_LIVETIME 300000 // время жизни предметов в контейнере - 5 минут +#define TREASURE_CHECKTIME 2500 // frequency test container - 2.5 seconds +#define TREASURE_LIVETIME 300000 // lifetime of objects in the container - 5 minutes /************************************************************************ * * -* Инициализация TreasurePool * +* Initialize TreasurePool * * * ************************************************************************/ @@ -60,7 +60,7 @@ /************************************************************************ * * -* Узнаем текущий тип контейнера * +* Know the current type of container * * * ************************************************************************/ @@ -135,7 +135,7 @@ /************************************************************************ * * -* Добавляем предмет в хранилище * +* Add the item to the store * * * ************************************************************************/ @@ -187,7 +187,7 @@ /************************************************************************ * * -* Добавляем предмет в хранилище * +* Add the item to the store * * * ************************************************************************/ @@ -260,7 +260,7 @@ /************************************************************************ * * -* Персонаж отказывается/голосует за предмет в хранилище * +* Character refuses / vote for the subject in store * * * ************************************************************************/ Index: src/map/treasure_pool.h =================================================================== --- src/map/treasure_pool.h (revision 3520) +++ src/map/treasure_pool.h (working copy) @@ -40,8 +40,8 @@ /************************************************************************ * * -* Для совместимости с кластерной системой, персонаж получает новый * -* TreasurePool при переходе между зонами * +* For compatibility with the cluster system, the character gains new * +* TreasurePool transition between zones * * * ************************************************************************/ Index: src/map/universal_container.cpp =================================================================== --- src/map/universal_container.cpp (revision 3520) +++ src/map/universal_container.cpp (working copy) @@ -30,7 +30,7 @@ /************************************************************************ * * -* Конструктор * +* Designer * * * ************************************************************************/ @@ -41,7 +41,7 @@ /************************************************************************ * * -* Отчищаем контейнер * +* Cleans container * * * ************************************************************************/ @@ -65,7 +65,7 @@ /************************************************************************ * * -* Узнаем цель обмена * +* Know the purpose of sharing * * * ************************************************************************/ @@ -76,7 +76,7 @@ /************************************************************************ * * -* Устанавливаем цель обмена * +* Set the target Exchange * * * ************************************************************************/ @@ -87,7 +87,7 @@ /************************************************************************ * * -* Узнаем текущий тип контейнера * +* Know the current type of container * * * ************************************************************************/ @@ -98,7 +98,7 @@ /************************************************************************ * * -* Устанавливаем текущий тип контейнера * +* Set the current type of container * * * ************************************************************************/ @@ -111,7 +111,7 @@ /************************************************************************ * * -* Запрещаем изменение содержимого контейнера * +* Do not modify the contents of the container * * * ************************************************************************/ @@ -122,7 +122,7 @@ /************************************************************************ * * -* Проверяем, заблокирован ли контейнер * +* Check whether the container is locked * * * ************************************************************************/ @@ -133,7 +133,7 @@ /************************************************************************ * * -* Проверяем, пуст ли контейнер * +* Check whether the container is empty * * * ************************************************************************/ @@ -144,7 +144,7 @@ /************************************************************************ * * -* Проверяем, пуста ли ячейка * +* Check whether the cell is empty * * * ************************************************************************/ @@ -159,7 +159,7 @@ /************************************************************************ * * -* Добавляем предмет в указанныю ячейку контейнера * +* Add item to ukazannyyu cell container * * * ************************************************************************/ @@ -178,7 +178,7 @@ /************************************************************************ * * -* Узнаем количество предметов, находящихся в контейнере * +* Get the number of objects in the container * * * ************************************************************************/ @@ -189,7 +189,7 @@ /************************************************************************ * * -* Получаем предмет из указанной ячейки контейнера * +* Get an object from a specified cell container * * * ************************************************************************/ Index: src/map/universal_container.h =================================================================== --- src/map/universal_container.h (revision 3520) +++ src/map/universal_container.h (working copy) @@ -43,11 +43,11 @@ /************************************************************************ * * -* Универсальный контейнер общего назначения * +* General purpose container * * * ************************************************************************/ -// главный предмет (gil, кристалл, используемый предмет ...) +// The main subject (gil, crystal, used items ...) class CItem; class CBaseEntity; Index: src/map/vana_time.cpp =================================================================== --- src/map/vana_time.cpp (revision 3520) +++ src/map/vana_time.cpp (working copy) @@ -221,7 +221,7 @@ { switch (m_vHour) { - // FOG и MIDNIGHT являются TIME_NIGHT (это не ошибка) + // FOG and MIDNIGHT are TIME_NIGHT (this is not an error) case 0: m_TimeType = TIME_NIGHT; return TIME_MIDNIGHT; case 2: m_TimeType = TIME_NIGHT; return TIME_FOG; Index: src/map/vana_time.h =================================================================== --- src/map/vana_time.h (revision 3520) +++ src/map/vana_time.h (working copy) @@ -95,9 +95,9 @@ uint32 m_vDay; // Vanadiel Day (Day of the week, fire,earth,wind) uint32 m_vanaDate; // Vanadiel time in integer format - TIMETYPE m_TimeType; // текущий тип времени + TIMETYPE m_TimeType; // current time type - int32 m_customOffset; // Смещение игрового времени в игровых минутах + int32 m_customOffset; // offset of playing time in the game short }; #endif \ No newline at end of file Index: src/map/zone.cpp =================================================================== --- src/map/zone.cpp (revision 3520) +++ src/map/zone.cpp (working copy) @@ -22,8 +22,8 @@ */ // TODO: -// нужно разделить класс czone на базовый и наследников. уже нарисовались: Standard, Rezident, Instance и Dinamis -// у каждой из указанных зон особое поведение +// We have to divide the class czone the base and heirs. already drawn: Standard, Rezident, Instance and Dynamis +// In each of the areas of particular behavior #include "../common/showmsg.h" #include "../common/timer.h" @@ -63,8 +63,8 @@ /************************************************************************ * * -* Cервер для обработки активности сущностей (по серверу на зону) без * -* активных областей * +* Server for processing active entities (the server for the zone) * +* without active regions * * * ************************************************************************/ @@ -76,8 +76,8 @@ /************************************************************************ * * -* Cервер для обработки активности сущностей (по серверу на зону) c * -* активными областями * +* Server for processing active entities (the server for the zone) c * +* Active regions * * * ************************************************************************/ @@ -97,7 +97,7 @@ /************************************************************************ * * -* Класс CZone * +* Class CZone * * * ************************************************************************/ @@ -123,7 +123,7 @@ /************************************************************************ * * -* Функции доступа к полям класса * +* Access functions to class fields * * * ************************************************************************/ @@ -142,11 +142,16 @@ return m_continentID; } -uint32 CZone::GetIP() +uint32 CZone::GetLANIP() { - return m_zoneIP; + return m_zoneLANIP; } +uint32 CZone::GetWANIP() +{ + return m_zoneWANIP; +} + uint16 CZone::GetPort() { return m_zonePort; @@ -224,8 +229,8 @@ /************************************************************************ * * -* Загружаем ZoneLines, необходимые для правильного перемещения между * -* зонами. * +* Load ZoneLines, necessary for proper movement between * +* Zones. * * * ************************************************************************/ @@ -255,7 +260,7 @@ /************************************************************************ * * -* Загружаем параметры погоды * +* Load parameters weather * * * ************************************************************************/ @@ -318,7 +323,7 @@ /************************************************************************ * * -* Загружаем настройки зоны из базы * +* Load zone settings from the database * * * ************************************************************************/ @@ -327,7 +332,8 @@ static const int8* Query = "SELECT " "zone.name," - "zone.zoneip," + "zone.lanip," + "zone.wanip," "zone.zoneport," "zone.music," "zone.battlesolo," @@ -347,15 +353,16 @@ { m_zoneName.insert(0, Sql_GetData(SqlHandle,0)); - m_zoneIP = (uint32)Sql_GetUIntData(SqlHandle,1); - m_zonePort = (uint16)Sql_GetUIntData(SqlHandle,2); - m_zoneMusic.m_song = (uint8)Sql_GetUIntData(SqlHandle,3); // background music - m_zoneMusic.m_bSongS = (uint8)Sql_GetUIntData(SqlHandle,4); // solo battle music - m_zoneMusic.m_bSongM = (uint8)Sql_GetUIntData(SqlHandle,5); // party battle music - m_tax = (uint16)(Sql_GetFloatData(SqlHandle,6) * 100); // tax for bazaar - m_miscMask = (uint16)Sql_GetUIntData(SqlHandle,7); + m_zoneLANIP = (uint32)Sql_GetUIntData(SqlHandle,1); + m_zoneWANIP = (uint32)Sql_GetUIntData(SqlHandle,2); + m_zonePort = (uint16)Sql_GetUIntData(SqlHandle,3); + m_zoneMusic.m_song = (uint8)Sql_GetUIntData(SqlHandle,4); // background music + m_zoneMusic.m_bSongS = (uint8)Sql_GetUIntData(SqlHandle,5); // solo battle music + m_zoneMusic.m_bSongM = (uint8)Sql_GetUIntData(SqlHandle,6); // party battle music + m_tax = (uint16)(Sql_GetFloatData(SqlHandle,7) * 100); // tax for bazaar + m_miscMask = (uint16)Sql_GetUIntData(SqlHandle,8); - if (Sql_GetData(SqlHandle,8) != NULL) // сейчас нельзя использовать bcnmid, т.к. они начинаются с нуля + if (Sql_GetData(SqlHandle,9) != NULL) // now we can not use bcnmid, because they start from scratch { m_InstanceHandler = new CInstanceHandler(m_zoneID); } @@ -372,7 +379,7 @@ /************************************************************************ * * -* Добавляем в зону MOB * +* Add the zone MOB * * * ************************************************************************/ @@ -389,7 +396,7 @@ /************************************************************************ * * -* Добавляем в зону NPC * +* Add the zone NPC * * * ************************************************************************/ @@ -418,7 +425,7 @@ /************************************************************************ * * -* Добавляем в зону PET (свободные targid 0x700-0x7FF) * +* Add the zone PET (free targid 0x700-0x7FF) * * * ************************************************************************/ @@ -463,7 +470,7 @@ /************************************************************************ * * -* Добавляем в зону активную область * +* Add the zone active area * * * ************************************************************************/ @@ -477,8 +484,8 @@ /************************************************************************ * * -* Ищем группу для монстра. Для монстров, объединенных в группу * -* работает система взаимопомощи (link) * +* We are looking for a group of monsters. For monsters, united in a * +* group mutual aid system works (link) * * * ************************************************************************/ @@ -511,7 +518,7 @@ /************************************************************************ * * -* Транспотр отправляется, необходимо собрать пассажиров * +* Transport sent, collect passengers * * * ************************************************************************/ @@ -593,8 +600,8 @@ /************************************************************************ * * -* Удаляем персонажа из зоны. Если запущен ZoneServer и персонажей * -* в зоне больше не осталось, то останавливаем ZoneServer * +* Delete the character of the zone. If you are running ZoneServer and * +* characters in the area there are no more, then stop ZoneServer * * * ************************************************************************/ @@ -691,7 +698,7 @@ } } - // TODO: могут возникать проблемы с переходом между одной и той же зоной (zone == prevzone) + // TODO: there can be problems with the transition between one and the same zone (zone == prevzone) m_charList.erase(PChar->targid); @@ -747,9 +754,9 @@ /************************************************************************ * * -* Добавляем персонажа в зону. Если ZoneServer не запущен то запускам. * -* Обязательно проверяем количество персонажей в зоне. * -* Максимальное число персонажей в одной зоне - 768 * +* Add the character to the zone. If it is not running ZoneServer * +* startups. Be sure to check the number of characters in the zone. * +* The maximum number of characters in the same area - 768 * * * ************************************************************************/ @@ -828,10 +835,10 @@ /************************************************************************ * * -* Проверка видимости монстров персонажем. Дистанцию лучше вынести в * -* глобальную переменную (настройки сервера) * -* Именно в этой функции будем проверять агрессию мостров, чтобы не * -* вычислять distance несколько раз (например в ZoneServer) * +* Check the sight of monsters character. Distance to make better * +* Global variable (server configuration) * +* It is in this function will check the Mostra aggression, not to * +* Calculate the distance several times (eg in ZoneServer) * * * ************************************************************************/ @@ -858,7 +865,7 @@ if (PChar->isDead() || PChar->nameflags.flags & FLAG_GM) continue; - // проверка ночного/дневного сна монстров уже учтена в проверке CurrentAction, т.к. во сне монстры не ходят ^^ + // Check for a night / day sleep monsters already included in the verification CurrentAction, because dream monsters do not go ^ ^ CurrentDistance += PChar->getMod(MOD_STEALTH); @@ -961,8 +968,8 @@ /************************************************************************ * * -* Проверка видимости питомцев персонажем. Для появления питомцев * -* используем UPDATE вместо SPAWN. SPAWN используется лишь при вызове * +* Check visibility pets character. For the appearance of pets * +* Use UPDATE instead of SPAWN. SPAWN is only used when calling * * * ************************************************************************/ @@ -995,7 +1002,7 @@ /************************************************************************ * * -* Проверка видимости NPCs персонажем. * +* Check the visibility of NPCs character. * * * ************************************************************************/ @@ -1030,10 +1037,10 @@ /************************************************************************ * * -* Проверка видимости персонажей. Смысл действий в том, что персонажи * -* сами себя обновляют и добавляются в списки других персонажей. * -* В оригинальной версии размер списка ограничен и изменяется в * -* пределах 25-50 видимых персонажей. * +* Check the visibility of characters. Meaning of actions that the * +* characters themselves updated and added to the lists of the other * +* characters. The original version of the list size is limited and * +* varies within 25-50 visible characters. * * * ************************************************************************/ @@ -1074,7 +1081,7 @@ /************************************************************************ * * -* Отображаем Moogle в MogHouse * +* Display the Moogle in MogHouse * * * ************************************************************************/ @@ -1097,7 +1104,7 @@ /************************************************************************ * * -* Отображаем транспотр в зоне (не хранится в основном списке) * +* Displays transport at (not stored in the main list) * * * ************************************************************************/ @@ -1112,7 +1119,7 @@ /************************************************************************ * * -* Получаем указатель на любую сущность в зоне по ее targid * +* Get a pointer to any entity in the area for its targid * * * ************************************************************************/ @@ -1173,7 +1180,7 @@ /************************************************************************ * * -* Oбработка реакции мира на смену времени суток * +* Machining World reaction to change the time of day * * * ************************************************************************/ @@ -1297,6 +1304,18 @@ luautils::OnTOTDChange(m_zoneID, TOTD); } +void CZone::SavePlayTime() +{ + if(!m_charList.empty()) + { + for(EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) + { + CCharEntity* PChar = (CCharEntity*)it->second; + charutils::SavePlayTime(PChar); + } + } +} + /************************************************************************ * * * * @@ -1321,7 +1340,7 @@ /************************************************************************ * * -* Отправляем глобальные пакеты * +* Send the global package * * * ************************************************************************/ @@ -1421,8 +1440,8 @@ /************************************************************************ * * -* Cервер для обработки активности и статус-эффектов сущностей в зоне. * -* При любом раскладе последними должны обрабатываться персонажи * +* Server for processing activities and the status of entities in the * +* area of ​​effect. In any case the latter should be handled characters * * * ************************************************************************/ @@ -1475,10 +1494,10 @@ /************************************************************************ * * -* Cервер для обработки активности и статус-эффектов сущностей в зоне. * -* Дополнительно обрабатывается проверка на вход и выход персонажей из * -* активных областей (пока реализован только вход в область). * -* При любом раскладе последними должны обрабатываться персонажи * +* Server for processing activities and the status of entities in the * +* area of ​​effect. Additionally, processed check in and out of * +* characters active regions (yet realized only entrance to the area). * +* In any case the latter should be handled characters * * * ************************************************************************/ Index: src/map/zone.h =================================================================== --- src/map/zone.h (revision 3520) +++ src/map/zone.h (working copy) @@ -400,16 +400,16 @@ enum ZONEMISC { - MISC_NONE = 0x0000, // 0x0000, // возможность использовать в любой зоне - MISC_ESCAPE = 0x0001, // 0x0001, // возможность использования заклинания escape; - MISC_TRACTOR = 0x0010, // 0x0002, // возможность использования заклинания tractor; - MISC_MAZURKA = 0x0008, // 0x0004, // возможность использования заклинания mazurka; - MISC_FELLOW = 0x0002, // 0x0008, // возможность призыва напарника npc - MISC_PET = 0x0080, // 0x0010, // возможность призыва питомца - MISC_CHOCOBO = 0x0004, // 0x0020, // возможность использования chocobo - MISC_MOGMENU = 0x0020, // 0x0040, // возможность общения с Nomad Moogle (доступ к меню mog house) - MISC_COSTUME = 0x0040, // 0x0080, // возможность использовать маскарадный костюм (costume) - MISC_TREASURE = 0x0100, // 0x0100, // наличие в зоне глобального TreasurePool + MISC_NONE = 0x0000, // 0x0000, // to use in any zone + MISC_ESCAPE = 0x0001, // 0x0001, // ability to use spells escape; + MISC_TRACTOR = 0x0010, // 0x0002, // ability to use spells tractor; + MISC_MAZURKA = 0x0008, // 0x0004, // ability to use spells mazurka; + MISC_FELLOW = 0x0002, // 0x0008, // possible recruitment partner npc + MISC_PET = 0x0080, // 0x0010, // opportunity to call your pet + MISC_CHOCOBO = 0x0004, // 0x0020, // the possibility of using chocobo + MISC_MOGMENU = 0x0020, // 0x0040, // the ability to communicate with the Nomad Moogle (menu access mog house) + MISC_COSTUME = 0x0040, // 0x0080, // the ability to use a costume (costume) + MISC_TREASURE = 0x0100, // 0x0100, // presence in the area of global TreasurePool }; /************************************************************************ @@ -420,17 +420,17 @@ struct zoneMusic_t { - uint8 m_song; // фоновая музыка - uint8 m_bSongS; // музыка в одиночном бою - uint8 m_bSongM; // музыка в групповом бою + uint8 m_song; // background music + uint8 m_bSongS; // Music in single combat + uint8 m_bSongM; // music group fight }; /************************************************************************ * * -* zoneLine - уникальный идентификатор пути из одной точки какой-либо * -* зоны в другую точку какой-либо зоны. Зоной отправления является зона,* -* хранящая данный zoneLineID. Зона прибытия и точное местоназначение * -* определены в структуре. * +* zoneLine - unique identifier of the way from a single point * +* area to another point of any area. Zone is the zone of origin, * +* stores this zoneLineID. Zone and the exact target of the arrival * +* defined in the structure. * * * ************************************************************************/ @@ -466,7 +466,8 @@ ZONEID GetID(); REGIONTYPE GetRegionID(); CONTINENTTYPE GetContinentID(); - uint32 GetIP(); + uint32 GetWANIP(); + uint32 GetLANIP(); uint16 GetPort(); uint16 GetTax(); WEATHER GetWeather(); @@ -480,39 +481,40 @@ void HealAllMobs(); CCharEntity* GetCharByName(int8* name); // finds the player if exists in zone - CBaseEntity* GetEntity(uint16 targid, uint8 filter = -1); // получаем указатель на любую сущность в зоне + CBaseEntity* GetEntity(uint16 targid, uint8 filter = -1); // get a pointer to any entity in the area - bool IsWeatherStatic(); // погода в зоне не требует изменения (никогда не меняется) + bool IsWeatherStatic(); // Weather in the area does not require a change (never change) bool CanUseMisc(uint16 misc); void SetWeather(WEATHER weatherCondition); - void SpawnPCs(CCharEntity* PChar); // отображаем персонажей в зоне - void SpawnMOBs(CCharEntity* PChar); // отображаем MOBs в зоне - void SpawnPETs(CCharEntity* PChar); // отображаем PETs в зоне - void SpawnNPCs(CCharEntity* PChar); // отображаем NPCs в зоне - void SpawnMoogle(CCharEntity* PChar); // отображаем Moogle в MogHouse - void SpawnTransport(CCharEntity* PChar); // отображаем транспорт + void SpawnPCs(CCharEntity* PChar); // display the characters in the zone + void SpawnMOBs(CCharEntity* PChar); // display the MOBs in the zone + void SpawnPETs(CCharEntity* PChar); // display the PETs in the zone + void SpawnNPCs(CCharEntity* PChar); // display the NPCs in the zone + void SpawnMoogle(CCharEntity* PChar); // display the Moogle in MogHouse + void SpawnTransport(CCharEntity* PChar); // display Transport + void SavePlayTime(); - void WideScan(CCharEntity* PChar, uint16 radius); // сканирование местности с заданным радиусом + void WideScan(CCharEntity* PChar, uint16 radius); // scan area with a specified radius - void DecreaseZoneCounter(CCharEntity* PChar); // добавляем персонажа в зону - void IncreaseZoneCounter(CCharEntity* PChar); // удаляем персонажа из зоны + void DecreaseZoneCounter(CCharEntity* PChar); // add character to the area + void IncreaseZoneCounter(CCharEntity* PChar); // remove the character from a zone - void InsertNPC(CBaseEntity* PNpc); // добавляем в зону npc - void InsertMOB(CBaseEntity* PMob); // добавляем в зону mob - void InsertPET(CBaseEntity* PPet); // добавляем в зону pet + void InsertNPC(CBaseEntity* PNpc); // add to the zone npc + void InsertMOB(CBaseEntity* PMob); // add to the zone mob + void InsertPET(CBaseEntity* PPet); // add to the zone pet void DeletePET(CBaseEntity* PPet); // derefs the pet's ID from this zone - void FindPartyForMob(CBaseEntity* PEntity); // ищем группу для монстра - void TransportDepart(CBaseEntity* PTransportNPC); // транспотр отправляется, необходимо собрать пассажиров + void FindPartyForMob(CBaseEntity* PEntity); // group looking for a monster + void TransportDepart(CBaseEntity* PTransportNPC); // transport sent, collect passengers - void InsertRegion(CRegion* Region); // добавляем в зону активную область + void InsertRegion(CRegion* Region); // add to the zone of the active region - void TOTDChange(TIMETYPE TOTD); // обработка реакции мира на смену времени суток - void PushPacket(CBaseEntity*, GLOBAL_MESSAGE_TYPE, CBasicPacket*); // отправляем глобальный пакет в пределах зоны + void TOTDChange(TIMETYPE TOTD); // processing reaction of the world to change the time of day + void PushPacket(CBaseEntity*, GLOBAL_MESSAGE_TYPE, CBasicPacket*); // send the package within the global zone - uint32 m_RegionCheckTime; // время последней проверки регионов - uint8 m_WeatherFrequency[MAX_WEATHER_ID]; // вероятность появления каждого типа погоды + uint32 m_RegionCheckTime; // time of last check Regions + uint8 m_WeatherFrequency[MAX_WEATHER_ID]; // probability of occurrence of each type of weather void ZoneServer(uint32 tick); void ZoneServerRegion(uint32 tick); @@ -525,38 +527,39 @@ private: - ZONEID m_zoneID; // ID зоны - REGIONTYPE m_regionID; // ID области - CONTINENTTYPE m_continentID; // ID континента - string_t m_zoneName; // имя зоны - uint16 m_zonePort; // порт зоны - uint32 m_zoneIP; // IP зоны + ZONEID m_zoneID; // ID area + REGIONTYPE m_regionID; // ID field + CONTINENTTYPE m_continentID; // ID of the continent + string_t m_zoneName; // area name + uint16 m_zonePort; // port area + uint32 m_zoneLANIP; // IP + uint32 m_zoneWANIP; // IP - WEATHER m_Weather; // текущая погода - uint32 m_WeatherChangeTime; // время начала текущей погоды - bool m_IsWeatherStatic; // погода в зоне никогда не меняется + WEATHER m_Weather; // current weather + uint32 m_WeatherChangeTime; // start time of current weather + bool m_IsWeatherStatic; // the weather in the area has never changed - uint16 m_tax; // налог в bazaar - uint16 m_miscMask; // битовое поле, описывающее возможности использования в зоне определенных умений + uint16 m_tax; // tax bazaar + uint16 m_miscMask; // bit field that describes the possibility of using certain skills in the area - zoneMusic_t m_zoneMusic; // информация о мелодиях, используемых в зоне + zoneMusic_t m_zoneMusic; // information about the tunes used in the area - EntityList_t m_mobList; // список всех MOBs в зоне - EntityList_t m_petList; // список всех PETs в зоне - EntityList_t m_npcList; // список всех NPCs в зоне - EntityList_t m_charList; // список всех PCs в зоне + EntityList_t m_mobList; // list of all the MOBs in the zone + EntityList_t m_petList; // list of all the PETs in the zone + EntityList_t m_npcList; // list of all the NPCs in the zone + EntityList_t m_charList; // list of all the PCs in the zone - regionList_t m_regionList; // список активных областей зоны - zoneLineList_t m_zoneLineList; // список всех доступных zonelines для зоны + regionList_t m_regionList; // list of active zone areas + zoneLineList_t m_zoneLineList; // list of all zonelines zone - CBaseEntity* m_Transport; // указатель на транспорт в зоне - CTreasurePool* m_TreasurePool; // глобальный TreasuerPool + CBaseEntity* m_Transport; // pointer to the transport in the area + CTreasurePool* m_TreasurePool; // global TreasurePool - CTaskMgr::CTask* ZoneTimer; // указатель на созданный таймер - ZoneServer. необходим для возможности его остановки + CTaskMgr::CTask* ZoneTimer; // pointer to the created timer - ZoneServer. needs to be able to stop it - void LoadZoneLines(); // список zonelines (можно было бы заменить этот метод методом InsertZoneLine) - void LoadZoneWeather(); // погода - void LoadZoneSettings(); // настройки зоны + void LoadZoneLines(); // list zonelines (could be replaced by this method InsertZoneLine) + void LoadZoneWeather(); // weather + void LoadZoneSettings(); // zone configuration }; #endif \ No newline at end of file Index: src/map/zoneutils.cpp =================================================================== --- src/map/zoneutils.cpp (revision 3520) +++ src/map/zoneutils.cpp (working copy) @@ -37,8 +37,8 @@ #include "mob_spell_list.h" -CZone* g_PZoneList[MAX_ZONEID]; // глобальный массив указателей на игровые зоны -CNpcEntity* g_PTrigger; // триггер для запуска событий +CZone* g_PZoneList[MAX_ZONEID]; // global array of pointers to the play areas +CNpcEntity* g_PTrigger; // trigger to start the event namespace zoneutils @@ -46,7 +46,7 @@ /************************************************************************ * * -* Реакция зон на смену времени суток * +* Reaction zones to replace the time of day * * * ************************************************************************/ @@ -65,7 +65,7 @@ * * ************************************************************************/ -// TOTO: общая погода для нескольких зон +// TOTO: general weather for multiple zones void UpdateWeather() { @@ -93,12 +93,21 @@ } } } - ShowDebug(CL_CYAN"UpdateWeather Finished\n" CL_RESET); + //ShowDebug(CL_CYAN"UpdateWeather Finished\n"CL_RESET); } +void SavePlayTime() +{ + for(int32 ZoneID = 0; ZoneID < MAX_ZONEID; ZoneID++) + { + g_PZoneList[ZoneID]->SavePlayTime(); + } + // ShowDebug(CL_CYAN"Player playtime saving finished\n" CL_RESET); +} + /************************************************************************ * * -* Возвращаем указатель на класс зоны с указанным ID. * +* Return a pointer to the specified zone ID. * * * ************************************************************************/ @@ -119,7 +128,7 @@ /************************************************************************ * * -* Получаем указатель на любую сущность по ID * +* Get a pointer to any entity by ID * * * ************************************************************************/ @@ -130,7 +139,7 @@ /************************************************************************ * * -* Получаем указатель на персонажа по имени * +* Get a pointer to a character named * * * ************************************************************************/ @@ -150,7 +159,7 @@ /************************************************************************ * * -* Получаем указатель на CCharEntity по id и targid * +* Get a pointer to CCharEntity of id and target * * * ************************************************************************/ @@ -171,9 +180,72 @@ return NULL; } +void LoadNPC(uint16 NpcID) +{ + const int8* Query = + "SELECT \ + npcid,\ + name,\ + pos_rot,\ + pos_x,\ + pos_y,\ + pos_z,\ + flag,\ + speed,\ + speedsub,\ + animation,\ + animationsub,\ + namevis,\ + status,\ + unknown,\ + look,\ + name_prefix,\ + zoneid\ + FROM npc_list \ + WHERE npcid = %u;"; + + int32 ret = Sql_Query(SqlHandle, Query, NpcID); + + if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) + { + CNpcEntity* PNpc = new CNpcEntity; + + PNpc->id = (uint32)Sql_GetUIntData(SqlHandle,0); + PNpc->targid = (uint16)PNpc->id & 0x0FFF; + + PNpc->name.insert(0,Sql_GetData(SqlHandle,1)); + + PNpc->loc.p.rotation = (uint8)Sql_GetIntData(SqlHandle,2); + PNpc->loc.p.x = Sql_GetFloatData(SqlHandle,3); + PNpc->loc.p.y = Sql_GetFloatData(SqlHandle,4); + PNpc->loc.p.z = Sql_GetFloatData(SqlHandle,5); + PNpc->loc.p.moving = (uint16)Sql_GetUIntData(SqlHandle,6); + + PNpc->m_TargID = (uint32)Sql_GetUIntData(SqlHandle,6) >> 16; // вполне вероятно + + PNpc->speed = (uint8)Sql_GetIntData(SqlHandle,7); + PNpc->speedsub = (uint8)Sql_GetIntData(SqlHandle,8); + PNpc->animation = (uint8)Sql_GetIntData(SqlHandle,9); + PNpc->animationsub = (uint8)Sql_GetIntData(SqlHandle,10); + + PNpc->namevis = (uint8)Sql_GetIntData(SqlHandle,11); + PNpc->status = (STATUSTYPE)Sql_GetIntData(SqlHandle,12); + PNpc->unknown = (uint32)Sql_GetUIntData(SqlHandle,13); + + PNpc->name_prefix = (uint8)Sql_GetIntData(SqlHandle,15); + + memcpy(&PNpc->look,Sql_GetData(SqlHandle,14),20); + + uint8 ZoneID = (uint8)Sql_GetIntData(SqlHandle,16); + CZone* PZone = new CZone((ZONEID)(uint8)ZoneID, GetCurrentRegion(ZoneID), GetCurrentContinent(ZoneID)); + + PZone->InsertNPC(PNpc); + } +} + /************************************************************************ * * -* Загружаем список NPC в указанную зону * +* Load the list of NPC in the target area * * * ************************************************************************/ @@ -241,7 +313,7 @@ /************************************************************************ * * -* Загружаем список монстров в указанную зону * +* Load the list of monsters in the target area * * * ************************************************************************/ @@ -276,7 +348,7 @@ PMob->id = (uint32)Sql_GetUIntData(SqlHandle,1); PMob->targid = (uint16)PMob->id & 0x0FFF; - PMob->m_SpawnPoint.rotation = (uint8)Sql_GetIntData(SqlHandle,2); + PMob->m_SpawnPoint.rotation = (uint8)Sql_GetIntData(SqlHandle,2); PMob->m_SpawnPoint.x = Sql_GetFloatData(SqlHandle,3); PMob->m_SpawnPoint.y = Sql_GetFloatData(SqlHandle,4); PMob->m_SpawnPoint.z = Sql_GetFloatData(SqlHandle,5); @@ -396,7 +468,7 @@ case SYSTEM_PLANTOID: PMob->addModifier(MOD_BEAST_KILLER, 5); break; case SYSTEM_UNDEAD: PMob->addModifier(MOD_ARCANA_KILLER, 5); break; case SYSTEM_VERMIN: PMob->addModifier(MOD_PLANTOID_KILLER, 5); break; - } + } PZone->InsertMOB(PMob); luautils::OnMobInitialise(PMob); @@ -453,13 +525,13 @@ /************************************************************************ * * -* Инициализация зон. Возрождаем всех монстров при старте сервера. * +* Initialization zones. Rethink all monsters at server startup. * * * ************************************************************************/ void LoadZoneList() { - g_PTrigger = new CNpcEntity(); // нужно в конструкторе CNpcEntity задавать модель по умолчанию + g_PTrigger = new CNpcEntity(); // CNpcEntity set to the default model for (uint16 ZoneID = 0; ZoneID < MAX_ZONEID; ZoneID++) { @@ -471,9 +543,9 @@ PZone->ZoneServer(-1); g_PZoneList[ZoneID] = PZone; - if (PZone->GetIP() != 0) + if (PZone->GetLANIP() != 0 || PZone->GetWANIP() != 0 || PZone->GetPort() != 0) { - luautils::OnZoneInitialise(PZone->GetID()); + luautils::OnZoneInitialize(PZone->GetID()); } } UpdateWeather(); @@ -481,7 +553,7 @@ /************************************************************************ * * -* Узнаем текущий регион по номеру зоны * +* View the current region is the zone number * * * ************************************************************************/ @@ -792,7 +864,7 @@ /************************************************************************ * * -* Освобождаем список зон * +* Free the list of zones * * * ************************************************************************/ Index: src/map/zoneutils.h =================================================================== --- src/map/zoneutils.h (revision 3520) +++ src/map/zoneutils.h (working copy) @@ -30,7 +30,7 @@ /************************************************************************ * * -* Задумывалось, как что-то вроде контролера зон * +* Conceived as something like the controller area * * * ************************************************************************/ @@ -40,20 +40,22 @@ namespace zoneutils { - void LoadZoneList(); // загружаем список зон - void FreeZoneList(); // освобождаем список зон + void LoadZoneList(); // load the list of zones + void FreeZoneList(); // release the list of zones - void UpdateWeather(); // обновляем погоду в зонах - void TOTDCharnge(TIMETYPE TOTD); // реакция мира на смену времени суток + void UpdateWeather(); // update the weather in areas + void TOTDCharnge(TIMETYPE TOTD); // the reaction of the world to change the time of day + void SavePlayTime(); + void LoadNPC(uint16 NpcID); // load NPC from ID REGIONTYPE GetCurrentRegion(uint8 ZoneID); CONTINENTTYPE GetCurrentContinent(uint8 ZoneID); - CZone* GetZone(uint16 ZoneID); // получаем указатель на зону - CNpcEntity* GetTrigger(uint16 TargID, uint16 ZoneID); // триггер для старта событий (как побочный эффект - вероятность появления прозрачного орка) - CBaseEntity* GetEntity(uint32 ID, uint8 filter = -1); // получаем указатель на любую сущность - CCharEntity* GetCharByName(int8* name); // получаем указатель на персонажа по имени - CCharEntity* GetCharFromRegion(uint32 charid, uint16 targid, uint8 RegionID); // получаем указатель на персонажа в указанном регионе + CZone* GetZone(uint16 ZoneID); // get a pointer to the zone + CNpcEntity* GetTrigger(uint16 TargID, uint16 ZoneID); // trigger for the start of the event (as a side effect - the probability of a transparent orc) + CBaseEntity* GetEntity(uint32 ID, uint8 filter = -1); // get a pointer to any entity + CCharEntity* GetCharByName(int8* name); // get a pointer to a character named + CCharEntity* GetCharFromRegion(uint32 charid, uint16 targid, uint8 RegionID); // get a pointer to the character in that region }; Index: src/search/data_loader.cpp =================================================================== --- src/search/data_loader.cpp (revision 3520) +++ src/search/data_loader.cpp (working copy) @@ -53,7 +53,7 @@ /************************************************************************ * * -* История продаж предмета * +* Sales history subject * * * ************************************************************************/ @@ -90,7 +90,7 @@ /************************************************************************ * * -* Список продаваемых предметов в указанной категории * +* List of sold items in this category * * The list of items sold in this category * ************************************************************************/ @@ -135,7 +135,7 @@ /************************************************************************ * * -* Количество активных игроков в мире * +* The number of active players in the world * * * ************************************************************************/ @@ -166,7 +166,7 @@ /************************************************************************ * * -* Список найденных персонажей в игровом мире * +* List of characters found in the game world * * Job ID is 0 for none specified. * ************************************************************************/ @@ -294,7 +294,7 @@ /************************************************************************ * * -* Список персонажей, состоящих в одной группе * +* List of characters who are in the same group * * * ************************************************************************/ @@ -356,7 +356,7 @@ /************************************************************************ * * -* Список персонажей, состоящих в одной linkshell * +* List of characters from more than one linkshell * * * ************************************************************************/ Index: src/search/packets/linkshell_list.cpp =================================================================== --- src/search/packets/linkshell_list.cpp (revision 3520) +++ src/search/packets/linkshell_list.cpp (working copy) @@ -50,7 +50,7 @@ WBUFB(m_data,(0x0A)) = 0x80; WBUFB(m_data,(0x0B)) = 0x82; // packet type - // WBUFB(m_data,(0x0E)) = 0x00; // количество персонажей в пакете + // WBUFB(m_data,(0x0E)) = 0x00; // the number of characters in a packet WBUFB(m_data,(0x0E)) = Total; } @@ -126,10 +126,10 @@ m_offset = packBitsLE(m_data, SEARCH_LANGUAGE, m_offset, 5); m_offset = packBitsLE(m_data, PPlayer->languages, m_offset,16); - if (m_offset%8 > 0) m_offset += 8 - m_offset%8; // побайтное выравнивание данных + if (m_offset%8 > 0) m_offset += 8 - m_offset%8; // byte to byte data alignment - WBUFB(m_data, size_offset) = m_offset/8 - size_offset - 1; // размер данных сущности - WBUFW(m_data,(0x08)) = m_offset / 8; // размер отправляемых данных + WBUFB(m_data, size_offset) = m_offset/8 - size_offset - 1; // the size of the entity data + WBUFW(m_data,(0x08)) = m_offset / 8; // the size of the data being sent delete PPlayer; } Index: src/search/search.cpp =================================================================== --- src/search/search.cpp (revision 3520) +++ src/search/search.cpp (working copy) @@ -79,7 +79,7 @@ /************************************************************************ * * -* Отображения содержимого входящего пакета в консоли * +* Display the contents of the incoming packet to the console * * * ************************************************************************/ @@ -361,7 +361,7 @@ /************************************************************************ * * -* Запрос списка персонажей (party/linkshell) * +* Request a list of characters (party/linkshell) * * * ************************************************************************/ @@ -478,14 +478,14 @@ uint8* data = (uint8*)PTCPRequest->GetData(); uint8 AHCatID = RBUFB(data,(0x16)); - //2 - уровень -- level - //3 - раса -- race - //4 - профессия -- job - //5 - урон -- damage - //6 - задержка -- delay - //7 - защита -- defense - //8 - сопротивление -- resistance - //9 - название -- name + //2 - level + //3 - race + //4 - job + //5 - damage + //6 - delay + //7 - defense + //8 - resistance + //9 - name string_t OrderByString = "ORDER BY"; uint8 paramCount = RBUFB(data,0x12); for (uint8 i = 0; i < paramCount; ++i) // параметры сортировки предметов @@ -565,8 +565,8 @@ search_req _HandleSearchRequest(CTCPRequestPacket* PTCPRequest, SOCKET socket) { - // суть в том, чтобы заполнить некоторую структуру, на основании которой будет создан запрос к базе - // результат поиска в базе отправляется клиенту + // The point is to fill a structure, based on which will create a query to the database + // Result of the search in the database is sent to the client uint32 bitOffset = 0; @@ -800,5 +800,5 @@ } return sr; - // не обрабатываем последние биты, что мешает в одну кучу например "/blacklist delete Name" и "/sea all Name" + // do not handle the last bits that interfere in one pile for example "/ blacklist delete Name" and "/ sea all Name" } \ No newline at end of file Index: win32/DSGame-server/DSGame-server.vcxproj =================================================================== --- win32/DSGame-server/DSGame-server.vcxproj (revision 3520) +++ win32/DSGame-server/DSGame-server.vcxproj (working copy) @@ -1,4 +1,4 @@ - + @@ -262,7 +262,7 @@ - + @@ -452,7 +452,7 @@ - + Index: win32/DSGame-server/DSGame-server.vcxproj.filters =================================================================== --- win32/DSGame-server/DSGame-server.vcxproj.filters (revision 3520) +++ win32/DSGame-server/DSGame-server.vcxproj.filters (working copy) @@ -1,4 +1,4 @@ - + @@ -542,7 +542,7 @@ Header Files\lua - + Header Files\packets @@ -1105,7 +1105,7 @@ Source Files\lua - + Source Files\packets