diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 1 | ||||
-rw-r--r-- | src/map/battle.h | 2 | ||||
-rw-r--r-- | src/map/packets.h | 311 | ||||
-rw-r--r-- | src/map/pc.c | 6 | ||||
-rw-r--r-- | src/map/pc.h | 8 | ||||
-rw-r--r-- | src/map/script.c | 1591 | ||||
-rw-r--r-- | src/map/script.h | 75 | ||||
-rw-r--r-- | src/map/unit.c | 10 |
8 files changed, 1976 insertions, 28 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 63252caf7..fdea849fb 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7333,6 +7333,7 @@ static const struct battle_data { { "max_summoner_parameter", &battle_config.max_summoner_parameter, 120, 10, 10000, }, { "mvp_exp_reward_message", &battle_config.mvp_exp_reward_message, 0, 0, 1, }, { "monster_eye_range_bonus", &battle_config.mob_eye_range_bonus, 0, 0, 10, }, + { "prevent_logout_trigger", &battle_config.prevent_logout_trigger, 0xE, 0, 0xF, } }; #ifndef STATS_OPT_OUT /** diff --git a/src/map/battle.h b/src/map/battle.h index 806b07a20..b5846e457 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -552,6 +552,8 @@ struct Battle_Config { int mvp_exp_reward_message; int mob_eye_range_bonus; //Vulture's Eye and Snake's Eye range bonus + + int prevent_logout_trigger; }; /* criteria for battle_config.idletime_critera */ diff --git a/src/map/packets.h b/src/map/packets.h index 418beb41a..cc2312356 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -2222,6 +2222,44 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x0436,4,clif->pDull); // CZ_GANGSI_RANK #endif +// 2012-09-25aRagexe +#if PACKETVER >= 20120925 +// new packets (not all) + packet(0x0998,8,clif->pEquipItem,2,4); +#endif + +// 2013-02-06aRagexe +#if PACKETVER >= 20130206 +// new packets + packet(0x09a4,18); // ZC_DISPATCH_TIMING_INFO_CHN +// changed packet sizes +#endif + +// 2013-03-06aRagexe +#if PACKETVER >= 20130306 +// new packets + packet(0x09a6,12); // ZC_BANKING_CHECK + packet(0x09a7,14,clif->pDull/*,XXX*/); // CZ_REQ_BANKING_DEPOSIT + packet(0x09a8,4); // ZC_ACK_BANKING_DEPOSIT + packet(0x09a9,14,clif->pDull/*,XXX*/); // CZ_REQ_BANKING_WITHDRAW + packet(0x09aa,4); // ZC_ACK_BANKING_WITHDRAW +// changed packet sizes +#endif + +// 2013-03-13aRagexe +#if PACKETVER >= 20130313 +// new packets + packet(0x09ab,-1,clif->pDull/*,XXX*/); // CZ_REQ_BANKING_CHECK + packet(0x09ac,20,clif->pDull/*,XXX*/); // CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO + packet(0x09ad,6); // ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO + packet(0x09ae,-1,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM + packet(0x09af,-1); // ZC_ACK_APPLY_BARGAIN_SALE_ITEM + packet(0x09b0,8,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM + packet(0x09b1,6); // ZC_ACK_REMOVE_BARGAIN_SALE_ITEM + packet(0x09b2,-1); // ZC_NOTIFY_BARGAIN_SALE_SELLING +// changed packet sizes +#endif + //2013-03-20Ragexe (Judas + Yommy) #if PACKETVER >= 20130320 // Shuffle Start @@ -2260,13 +2298,36 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x095a,8,clif->pDull); // CZ_JOIN_BATTLE_FIELD // Shuffle End - // New Packets - packet(0x0998,8,clif->pEquipItem,2,4); + // New Packets (wrong version or packet not exists) packet(0x0447,2); // PACKET_CZ_BLOCKING_PLAY_CANCEL packet(0x099f,24); // New Packets End #endif +#if PACKETVER >= 20130320 +// new packets +// changed packet sizes + packet(0x09a7,10,clif->pBankDeposit,2,4,6); // CZ_REQ_BANKING_DEPOSIT + packet(0x09a8,12); // ZC_ACK_BANKING_DEPOSIT + packet(0x09a9,10,clif->pBankWithdraw,2,4,6); // CZ_REQ_BANKING_WITHDRAW + packet(0x09aa,12); // ZC_ACK_BANKING_WITHDRAW + packet(0x09ab,6,clif->pBankCheck,2,4); // CZ_REQ_BANKING_CHECK +#endif + +// 2013-03-27bRagexe +#if PACKETVER >= 20130327 +// new packets + packet(0x09ac,-1,clif->pDull/*,XXX*/); // CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO + packet(0x09ad,10); // ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO + packet(0x09ae,17,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM + packet(0x09af,4); // ZC_ACK_APPLY_BARGAIN_SALE_ITEM + packet(0x09b0,8,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM + packet(0x09b1,4); // ZC_ACK_REMOVE_BARGAIN_SALE_ITEM + packet(0x09b2,6); // ZC_NOTIFY_BARGAIN_SALE_SELLING + packet(0x09b3,6); // ZC_NOTIFY_BARGAIN_SALE_CLOSE +// changed packet sizes +#endif + //2013-05-15aRagexe (Shakto) #if PACKETVER >= 20130515 // Shuffle Start @@ -2529,20 +2590,74 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x0436,4,clif->pDull); // CZ_GANGSI_RANK #endif -/* Bank System [Yommy/Hercules] */ -#if PACKETVER >= 20130724 -// shuffle packets not added - packet(0x09A6,12); // ZC_BANKING_CHECK - packet(0x09A7,10,clif->pBankDeposit,2,4,6); - packet(0x09A8,16); // ZC_ACK_BANKING_DEPOSIT - packet(0x09A9,10,clif->pBankWithdraw,2,4,6); - packet(0x09AA,16); // ZC_ACK_BANKING_WITHDRAW - packet(0x09AB,6,clif->pBankCheck,2,4); - //// - packet(0x09B6,6,clif->pBankOpen,2,4); - packet(0x09B7,4); // ZC_ACK_OPEN_BANKING - packet(0x09B8,6,clif->pBankClose,2,4); - packet(0x09B9,4); // ZC_ACK_CLOSE_BANKING +// 2013-04-17aRagexe +#if PACKETVER >= 20130417 +// new packets + packet(0x09b4,6,clif->pDull/*,XXX*/); // CZ_OPEN_BARGAIN_SALE_TOOL + packet(0x09b5,2); // ZC_OPEN_BARGAIN_SALE_TOOL + packet(0x09b6,6,clif->pBankOpen,2,4); // CZ_REQ_OPEN_BANKING + packet(0x09b7,4); // ZC_ACK_OPEN_BANKING + packet(0x09b8,6,clif->pBankClose,2,4); // CZ_REQ_CLOSE_BANKING + packet(0x09b9,4); // ZC_ACK_CLOSE_BANKING +// changed packet sizes +#endif + +// 2013-04-24aRagexe +#if PACKETVER >= 20130424 +// new packets + packet(0x09ba,6,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_GUILD_STORAGE + packet(0x09bb,4); // ZC_ACK_OPEN_GUILD_STORAGE + packet(0x09bc,6,clif->pDull/*,XXX*/); // CZ_CLOSE_BARGAIN_SALE_TOOL + packet(0x09bd,2); // ZC_CLOSE_BARGAIN_SALE_TOOL +// changed packet sizes +#endif + +// 2013-05-02aRagexe +#if PACKETVER >= 20130502 +// new packets + packet(0x09be,6,clif->pDull/*,XXX*/); // CZ_REQ_CLOSE_GUILD_STORAGE + packet(0x09bf,4); // ZC_ACK_CLOSE_GUILD_STORAGE +// changed packet sizes + packet(0x09bb,6); // ZC_ACK_OPEN_GUILD_STORAGE +#endif + +// 2013-05-15aRagexe +#if PACKETVER >= 20130515 +// new packets + packet(0x09c0,11); // ZC_ACTION_MOVE + packet(0x09c1,11); // ZC_C_MARKERINFO +// changed packet sizes + packet(0x09a8,16); // ZC_ACK_BANKING_DEPOSIT + packet(0x09aa,16); // ZC_ACK_BANKING_WITHDRAW +#endif + +// 2013-05-29Ragexe +#if PACKETVER >= 20130529 +// new packets + packet(0x09c3,8,clif->pDull/*,XXX*/); // CZ_REQ_COUNT_BARGAIN_SALE_ITEM +// changed packet sizes +#endif + +// 2013-06-05Ragexe +#if PACKETVER >= 20130605 +// new packets + packet(0x09c4,8); // ZC_ACK_COUNT_BARGAIN_SALE_ITEM +#endif + +// 2013-06-18aRagexe +#if PACKETVER >= 20130618 +// new packets + packet(0x09ca,23); // ZC_SKILL_ENTRY5 +// changed packet sizes +#endif + +// 2013-07-17cRagexe +#if PACKETVER >= 20130717 +// new packets + packet(0x09cb,17); // ZC_USE_SKILL2 + packet(0x09cc,-1); // ZC_SECRETSCAN_DATA +// changed packet sizes + packet(0x09c1,10); // ZC_C_MARKERINFO #endif //2013-08-07Ragexe (Shakto) @@ -2582,6 +2697,13 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x0436,4,clif->pDull); // CZ_GANGSI_RANK #endif +// 2013-08-07aRagexe +#if PACKETVER >= 20130807 +// new packets + packet(0x09cd,8); // ZC_MSG_COLOR +// changed packet sizes +#endif + //2013-08-14aRagexe - Themon #if PACKETVER >= 20130814 packet(0x0874,7,clif->pActionRequest,2,6); @@ -2619,6 +2741,84 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x0896,8,clif->pDull); // CZ_JOIN_BATTLE_FIELD #endif +// 2013-08-14aRagexe +#if PACKETVER >= 20130814 +// new packets + packet(0x09ce,102,clif->pGM_Monster_Item,2); // CZ_ITEM_CREATE_EX + packet(0x09cf,-1); // ZC_NPROTECTGAMEGUARDCSAUTH + packet(0x09d0,-1,clif->pDull/*,XXX*/); // CZ_NPROTECTGAMEGUARDCSAUTH +// changed packet sizes +#endif + +// 2013-08-21bRagexe +#if PACKETVER >= 20130821 +// new packets + packet(0x09d1,14); // ZC_PROGRESS_ACTOR +// changed packet sizes +#endif + +// 2013-08-28bRagexe +#if PACKETVER >= 20130828 +// new packets + packet(0x09d2,-1); // ZC_GUILDSTORAGE_ITEMLIST_NORMAL_V5 + packet(0x09d3,-1); // ZC_GUILDSTORAGE_ITEMLIST_EQUIP_V5 +// changed packet sizes + packet(0x09ba,2,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_GUILD_STORAGE + packet(0x09be,2,clif->pDull/*,XXX*/); // CZ_REQ_CLOSE_GUILD_STORAGE +#endif + +// 2013-09-04aRagexe +#if PACKETVER >= 20130904 +// new packets +// changed packet sizes + packet(0x09ca,-1); // ZC_SKILL_ENTRY5 +#endif + +// 2013-09-11aRagexe +#if PACKETVER >= 20130911 +// new packets + packet(0x09d4,2,clif->pNPCShopClosed); // CZ_NPC_TRADE_QUIT + packet(0x09d5,-1); // ZC_NPC_MARKET_OPEN + packet(0x09d6,-1,clif->pNPCMarketPurchase); // CZ_NPC_MARKET_PURCHASE + packet(0x09d7,-1); // ZC_NPC_MARKET_PURCHASE_RESULT + packet(0x09d8,2,clif->pNPCMarketClosed); // CZ_NPC_MARKET_CLOSE + packet(0x09d9,2,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG + packet(0x09da,2); // ZC_ACK_GUILDSTORAGE_LOG +// changed packet sizes +#endif + +// 2013-09-25aRagexe +#if PACKETVER >= 20130925 +// new packets +// changed packet sizes + packet(0x09da,10); // ZC_ACK_GUILDSTORAGE_LOG +#endif + +// 2013-10-02aRagexe +#if PACKETVER >= 20131002 +// new packets +// changed packet sizes + packet(0x09d9,4,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG + packet(0x09da,-1); // ZC_ACK_GUILDSTORAGE_LOG +#endif + +// 2013-10-16aRagexe +#if PACKETVER >= 20131016 +// new packets +// changed packet sizes + packet(0x09d9,6,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG +#endif + +// 2013-10-23aRagexe +#if PACKETVER >= 20131023 +// new packets + packet(0x09db,-1); // ZC_NOTIFY_MOVEENTRY10 + packet(0x09dc,-1); // ZC_NOTIFY_NEWENTRY10 + packet(0x09dd,-1); // ZC_NOTIFY_STANDENTRY10 +// changed packet sizes + packet(0x09d9,4,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG +#endif + // 2013-10-30aRagexe #if PACKETVER >= 20131030 // new packets @@ -2627,6 +2827,43 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x09e0,-1); // SC_LOGIN_ANSWER_WITH_ID #endif +// 2013-11-06aRagexe +#if PACKETVER >= 20131106 +// new packets + packet(0x09e1,8,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_BODY_TO_GUILDSTORAGE + packet(0x09e2,8,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_GUILDSTORAGE_TO_BODY + packet(0x09e3,8,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_CART_TO_GUILDSTORAGE + packet(0x09e4,8,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_GUILDSTORAGE_TO_CART +// changed packet sizes +#endif + +// 2013-11-20dRagexe +#if PACKETVER >= 20131120 +// new packets + packet(0x09e5,14); // ZC_DELETEITEM_FROM_MCSTORE2 + packet(0x09e6,18); // ZC_UPDATE_ITEM_FROM_BUYING_STORE2 +// changed packet sizes +#endif + +// 2013-11-27bRagexe +#if PACKETVER >= 20131127 +// new packets +// changed packet sizes + packet(0x09e5,18); // ZC_DELETEITEM_FROM_MCSTORE2 + packet(0x09e6,22); // ZC_UPDATE_ITEM_FROM_BUYING_STORE2 +#endif + +// 2013-12-11dRagexe +#if PACKETVER >= 20131211 +// new packets + packet(0x09e7,2); // ZC_NOTIFY_UNREAD_RODEX + packet(0x09e8,18,clif->pDull/*,XXX*/); // CZ_OPEN_RODEXBOX + packet(0x09e9,2,clif->pDull/*,XXX*/); // CZ_CLOSE_RODEXBOX + packet(0x09ed,-1); // ZC_ACK_SEND_RODEX + packet(0x09ee,-1,clif->pDull/*,XXX*/); // CZ_REQ_NEXT_RODEX +// changed packet sizes +#endif + // 2013-12-18bRagexe - Yommy #if PACKETVER >= 20131218 packet(0x0369,7,clif->pActionRequest,2,6); @@ -2658,12 +2895,20 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x085C,36,clif->pStoragePassword,0); packet(0x0363,8,clif->pDull); // CZ_JOIN_BATTLE_FIELD packet(0x087b,4,clif->pDull); // CZ_GANGSI_RANK - /* New */ - packet(0x09d4,2,clif->pNPCShopClosed); - packet(0x09ce,102,clif->pGM_Monster_Item,2); - /* NPC Market */ - packet(0x09d8,2,clif->pNPCMarketClosed); - packet(0x09d6,-1,clif->pNPCMarketPurchase); +#endif + +// 2013-12-18bRagexe +#if PACKETVER >= 20131218 +// new packets + packet(0x09ea,10,clif->pDull/*,XXX*/); // CZ_REQ_READ_RODEX + packet(0x09eb,14); // ZC_ACK_READ_RODEX + packet(0x09ef,11,clif->pDull/*,XXX*/); // CZ_REQ_REFRESH_RODEX + packet(0x09f0,-1); // ZC_ACK_RODEX_LIST + packet(0x09f5,11,clif->pDull/*,XXX*/); // CZ_REQ_DELETE_RODEX + packet(0x09f6,11); // ZC_ACK_DELETE_RODEX +// changed packet sizes + packet(0x09e8,10,clif->pDull/*,XXX*/); // CZ_OPEN_RODEXBOX + packet(0x09ee,11,clif->pDull/*,XXX*/); // CZ_REQ_NEXT_RODEX #endif // 2013-12-23cRagexe - Yommy @@ -2697,7 +2942,14 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x08A4,36,clif->pStoragePassword,0); packet(0x0363,8,clif->pDull); // CZ_JOIN_BATTLE_FIELD packet(0x0436,4,clif->pDull); // CZ_GANGSI_RANK - packet(0x09cb,17); +#endif + +// 2013-12-23bRagexe +#if PACKETVER >= 20131223 +// new packets +// changed packet sizes + packet(0x09ea,11,clif->pDull/*,XXX*/); // CZ_REQ_READ_RODEX + packet(0x09eb,24); // ZC_ACK_READ_RODEX #endif // 2013-12-30aRagexe - Yommy @@ -2733,6 +2985,16 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x093e,8,clif->pDull); // CZ_JOIN_BATTLE_FIELD #endif +// 2013-12-30aRagexe +#if PACKETVER >= 20131230 +// new packets + packet(0x09ec,-1,clif->pDull/*,XXX*/); // CZ_REQ_SEND_RODEX + packet(0x09ed,3); // ZC_ACK_SEND_RODEX + packet(0x09f7,75); // ZC_PROPERTY_HOMUN_2 +// changed packet sizes + packet(0x09eb,23); // ZC_ACK_READ_RODEX +#endif + // 2014 Packet Data // 2014-01-15eRagexe @@ -3213,8 +3475,6 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x0936,36,clif->pStoragePassword,0); packet(0x0363,8,clif->pDull); // CZ_JOIN_BATTLE_FIELD packet(0x0922,4,clif->pDull); // CZ_GANGSI_RANK - packet(0x09e5,18); // ZC_DELETEITEM_FROM_MCSTORE2 - packet(0x09e6,22); // ZC_UPDATE_ITEM_FROM_BUYING_STORE2 #endif // 2014-10-22bRagexe - YomRawr @@ -3730,7 +3990,6 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x0817,5,clif->pHomMenu,2,4); packet(0x0923,36,clif->pStoragePassword,0); packet(0x0a27,8); // ZC_RECOVERY2 - packet(0x09f7,75); // ZC_PROPERTY_HOMUN_2 #endif // 2015-05-20aRagexeRE diff --git a/src/map/pc.c b/src/map/pc.c index f5c0d29f5..6da0bf035 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -741,7 +741,8 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo sd->client_tick = client_tick; sd->state.active = 0; //to be set to 1 after player is fully authed and loaded. sd->bl.type = BL_PC; - sd->canlog_tick = timer->gettick(); + if (battle_config.prevent_logout_trigger & PLT_LOGIN) + sd->canlog_tick = timer->gettick(); //Required to prevent homunculus copuing a base speed of 0. sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; sd->state.warp_clean = 1; @@ -7715,7 +7716,8 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h if( sd->status.ele_id > 0 ) elemental->set_target(sd,src); - sd->canlog_tick = timer->gettick(); + if (battle_config.prevent_logout_trigger & PLT_DAMAGE) + sd->canlog_tick = timer->gettick(); } /*========================================== diff --git a/src/map/pc.h b/src/map/pc.h index 0e4f1affd..482e30c41 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -73,6 +73,14 @@ enum equip_index { EQI_MAX }; +enum prevent_logout_trigger { + PLT_NONE = 0x0, + PLT_LOGIN = 0x1, + PLT_ATTACK = 0x2, + PLT_SKILL = 0x4, + PLT_DAMAGE = 0x8 +}; + enum pc_unequipitem_flag { PCUNEQUIPITEM_NONE = 0x0, ///< Just unequip PCUNEQUIPITEM_RECALC = 0x1, ///< Recalculate status after unequipping diff --git a/src/map/script.c b/src/map/script.c index 8604b62f7..c9c51afbc 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -17744,6 +17744,1592 @@ BUILDIN(getunittype) { return true; } +/** + * Sets real-time unit data for a game object. + * Setunitdata <GUID>,<DataType>,<Val1>{,<Val2>,<Val3>} + * @param1 GUID GID of the unit. + * @param2 DataType Type of Data to be set for the unit. + * @param3 Value#1 Value to be passed as change in data. + * @param4 Value#2 Optional int value to be passed for certain data types. + * @param5 Value#3 Optional int value to be passed for certain data types. + * @return 1 on success, 0 on failure. + */ +BUILDIN(setunitdata) +{ + struct block_list *bl = NULL; + const char *mapname = NULL, *udtype = NULL; + int type = 0, val = 0, val2 = 0, val3 = 0; + struct map_session_data *tsd = NULL; + + bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_setunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + type = script_getnum(st, 3); + + /* type bounds */ + if (type < UDT_SIZE || type >= UDT_MAX) { // Note: UDT_TYPE is not valid here + ShowError("buildin_setunitdata: Invalid unit data type %d provided.\n", type); + script_pushint(st, 0); + return false; + } + + /* Mandatory Argument 3 */ + if (type == UDT_MAPIDXY) { + if (!script_isstringtype(st, 4)) { + ShowError("buildin_setunitdata: Invalid data type for argument #3.\n"); + script_pushint(st, 0); + return false; + } + mapname = script_getstr(st, 4); + } else { + if (script_isstringtype(st, 4)) { + ShowError("buildin_setunitdata: Invalid data type for argument #3.\n"); + script_pushint(st, 0); + return false; + } + val = script_getnum(st, 4); + } +/* checks if value is out of bounds. */ +#define setunitdata_check_bounds(arg, min, max) \ + do { \ + if (script_getnum(st, (arg)) < (min) || script_getnum(st, (arg)) > (max)) { \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", script_getnum(st, (arg)), (arg)-1, (min), (max)); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if value is out of bounds. */ +#define setunitdata_check_min(arg, min) \ + do { \ + if (script_getnum(st, (arg)) < (min)) { \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d)\n", script_getnum(st, (arg)), (arg)-1, (min)); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if the argument doesn't exist, if required. + * also checks if the argument exists, if not required. */ +#define setunitdata_assert_arg(arg, required) \ + do { \ + if (required && !script_hasdata(st, (arg))) { \ + ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, (arg)-1); \ + script_pushint(st, 0); \ + return false; \ + } else if (!required && script_hasdata(st, arg)) { \ + ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", (arg)-1, type); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while (0); +/* checks if the data is an integer. */ +#define setunitdata_check_int(arg) \ + do { \ + setunitdata_assert_arg((arg), true); \ + if (script_isstringtype(st, (arg))) { \ + ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", (arg)-1); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); +/* checks if the data is a string. */ +#define setunitdata_check_string(arg) \ + do { \ + setunitdata_assert_arg((arg), true); \ + if (script_isinttype(st, (arg))) { \ + ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", (arg)-1); \ + script_pushint(st, 0); \ + return false; \ + } \ + } while(0); + + if (type != UDT_MAPIDXY && type != UDT_WALKTOXY) { + setunitdata_assert_arg(5, false); + setunitdata_assert_arg(6, false); + } + + switch (type) + { + case UDT_SIZE: + setunitdata_check_bounds(4, SZ_SMALL, SZ_BIG); + break; + case UDT_LEVEL: + case UDT_HP: + case UDT_MAXHP: + case UDT_SP: + case UDT_MAXSP: + case UDT_CLASS: + case UDT_HEADBOTTOM: + case UDT_HEADMIDDLE: + case UDT_HEADTOP: + case UDT_CLOTHCOLOR: + case UDT_SHIELD: + case UDT_WEAPON: + case UDT_INTIMACY: + case UDT_LIFETIME: + case UDT_MERC_KILLCOUNT: + setunitdata_check_min(4, 0); + break; + case UDT_MASTERAID: + setunitdata_check_min(4, 0); + tsd = map->id2sd(val); + if (tsd == NULL) { + ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n",val); + script_pushint(st, 0); + return false; + } + break; + case UDT_MASTERCID: + setunitdata_check_min(4, 0); + tsd = map->charid2sd(val); + if (tsd == NULL) { + ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n",val); + script_pushint(st, 0); + return false; + } + break; + case UDT_MAPIDXY: + if ((val = map->mapname2mapid(mapname)) == -1) { + ShowError("buildin_setunitdata: Non-existent map %s provided.\n", mapname); + return false; + } + setunitdata_check_int(5); + setunitdata_check_int(6); + setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2); + setunitdata_check_bounds(6, 0, MAX_MAP_SIZE/2); + val2 = script_getnum(st, 5); + val3 = script_getnum(st, 6); + break; + case UDT_WALKTOXY: + setunitdata_assert_arg(6, false); + setunitdata_check_int(5); + val2 = script_getnum(st, 5); + setunitdata_check_bounds(4, 0, MAX_MAP_SIZE/2); + setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2); + break; + case UDT_SPEED: + setunitdata_check_bounds(4, 0, MAX_WALK_SPEED); + break; + case UDT_MODE: + setunitdata_check_bounds(4, MD_NONE, MD_MASK); + break; + case UDT_AI: + setunitdata_check_bounds(4, AI_NONE, AI_MAX-1); + break; + case UDT_SCOPTION: + setunitdata_check_bounds(4, OPTION_NOTHING, OPTION_COSTUME); + break; + case UDT_SEX: + setunitdata_check_bounds(4, SEX_FEMALE, SEX_MALE); + break; + case UDT_HAIRSTYLE: + setunitdata_check_bounds(4, 0, battle->bc->max_hair_style); + break; + case UDT_HAIRCOLOR: + setunitdata_check_bounds(4, 0, battle->bc->max_hair_color); + break; + case UDT_LOOKDIR: + setunitdata_check_bounds(4, 0, 7); + break; + case UDT_CANMOVETICK: + setunitdata_check_min(4, 0); + break; + case UDT_STR: + case UDT_AGI: + case UDT_VIT: + case UDT_INT: + case UDT_DEX: + case UDT_LUK: + case UDT_STATPOINT: + case UDT_ATKRANGE: + case UDT_ATKMIN: + case UDT_ATKMAX: + case UDT_MATKMIN: + case UDT_MATKMAX: + case UDT_AMOTION: + case UDT_ADELAY: + case UDT_DMOTION: + setunitdata_check_bounds(4, 0, USHRT_MAX); + break; + case UDT_DEF: + case UDT_MDEF: + case UDT_HIT: + case UDT_FLEE: + case UDT_PDODGE: + case UDT_CRIT: + setunitdata_check_bounds(4, 0, SHRT_MAX); + break; + case UDT_HUNGER: + setunitdata_check_bounds(4, 0, 99); + break; + case UDT_RACE: + case UDT_ELETYPE: + case UDT_ELELEVEL: + setunitdata_check_bounds(4, 0, CHAR_MAX); + break; + default: + break; + } + +#undef setunitdata_check_bounds +#undef setunitdata_assert_arg +#undef setunitdata_check_int +#undef setunitdata_check_string + + /* Set the values */ + switch (bl->type) { + case BL_MOB: + { + struct mob_data *md = BL_UCAST(BL_MOB, bl); + nullpo_retr(false, md); + + switch (type) + { + case UDT_SIZE: + md->status.size = (unsigned char) val; + break; + case UDT_LEVEL: + md->level = val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + clif->charnameack(0, &md->bl); + break; + case UDT_MAXHP: + md->status.max_hp = (unsigned int) val; + clif->charnameack(0, &md->bl); + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + md->status.max_sp = (unsigned int) val; + break; + case UDT_MASTERAID: + md->master_id = val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + md->status.speed = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_MODE: + md->status.mode = (enum e_mode) val; + break; + case UDT_AI: + md->special_state.ai = (enum ai) val; + break; + case UDT_SCOPTION: + md->sc.option = (unsigned int) val; + break; + case UDT_SEX: + md->vd->sex = (char) val; + break; + case UDT_CLASS: + mob->class_change(md, val); + break; + case UDT_HAIRSTYLE: + clif->changelook(bl, LOOK_HAIR, val); + break; + case UDT_HAIRCOLOR: + clif->changelook(bl, LOOK_HAIR_COLOR, val); + break; + case UDT_HEADBOTTOM: + clif->changelook(bl, LOOK_HEAD_BOTTOM, val); + break; + case UDT_HEADMIDDLE: + clif->changelook(bl, LOOK_HEAD_MID, val); + break; + case UDT_HEADTOP: + clif->changelook(bl, LOOK_HEAD_TOP, val); + break; + case UDT_CLOTHCOLOR: + clif->changelook(bl, LOOK_CLOTHES_COLOR, val); + break; + case UDT_SHIELD: + clif->changelook(bl, LOOK_SHIELD, val); + break; + case UDT_WEAPON: + clif->changelook(bl, LOOK_WEAPON, val); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (uint8) val); + break; + case UDT_CANMOVETICK: + md->ud.canmove_tick = val; + break; + case UDT_STR: + md->status.str = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_AGI: + md->status.agi = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_VIT: + md->status.vit = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_INT: + md->status.int_ = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_DEX: + md->status.dex = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_LUK: + md->status.luk = (unsigned short) val; + status->calc_misc(bl, &md->status, md->level); + break; + case UDT_ATKRANGE: + md->status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + md->status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + md->status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + md->status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + md->status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + md->status.def = (defType) val; + break; + case UDT_MDEF: + md->status.mdef = (defType) val; + break; + case UDT_HIT: + md->status.hit = (short) val; + break; + case UDT_FLEE: + md->status.flee = (short) val; + break; + case UDT_PDODGE: + md->status.flee2 = (short) val; + break; + case UDT_CRIT: + md->status.cri = (short) val; + break; + case UDT_RACE: + md->status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + md->status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + md->status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + md->status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + md->status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + md->status.dmotion = (unsigned short) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for mob unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_HOM: + { + struct homun_data *hd = BL_UCAST(BL_HOM, bl); + + nullpo_retr(false, hd); + + switch (type) + { + case UDT_SIZE: + hd->base_status.size = (unsigned char) val; + break; + case UDT_LEVEL: + hd->homunculus.level = (short) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + hd->homunculus.max_hp = val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + hd->homunculus.max_sp = val; + break; + case UDT_MASTERCID: + hd->homunculus.char_id = val; + hd->master = tsd; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + hd->base_status.speed = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + hd->ud.canmove_tick = val; + break; + case UDT_STR: + hd->base_status.str = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_AGI: + hd->base_status.agi = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_VIT: + hd->base_status.vit = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_INT: + hd->base_status.int_ = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_DEX: + hd->base_status.dex = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_LUK: + hd->base_status.luk = (unsigned short) val; + status->calc_misc(bl, &hd->base_status, hd->homunculus.level); + break; + case UDT_ATKRANGE: + hd->base_status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + hd->base_status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + hd->base_status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + hd->base_status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + hd->base_status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + hd->base_status.def = (defType) val; + break; + case UDT_MDEF: + hd->base_status.mdef = (defType) val; + break; + case UDT_HIT: + hd->base_status.hit = (short) val; + break; + case UDT_FLEE: + hd->base_status.flee = (short) val; + break; + case UDT_PDODGE: + hd->base_status.flee2 = (short) val; + break; + case UDT_CRIT: + hd->base_status.cri = (short) val; + break; + case UDT_RACE: + hd->base_status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + hd->base_status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + hd->base_status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + hd->base_status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + hd->base_status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + hd->base_status.dmotion = (unsigned short) val; + break; + case UDT_HUNGER: + hd->homunculus.hunger = (short) val; + clif->send_homdata(hd->master, SP_HUNGRY, hd->homunculus.hunger); + break; + case UDT_INTIMACY: + homun->add_intimacy(hd, (unsigned int) val); + clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100); + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for homunculus unit.\n", udtype); + script_pushint(st, 0); + return false; + } + + clif->send_homdata(hd->master, SP_ACK, 0); // send homun data + } + break; + case BL_PET: + { + struct pet_data *pd = BL_UCAST(BL_PET, bl); + + nullpo_retr(false, pd); + + switch (type) + { + case UDT_SIZE: + pd->status.size = (unsigned char) val; + break; + case UDT_LEVEL: + pd->pet.level = (short) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + pd->status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + pd->status.max_sp = (unsigned int) val; + break; + case UDT_MASTERAID: + pd->pet.account_id = val; + pd->msd = tsd; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + pd->status.speed = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + pd->ud.canmove_tick = val; + break; + case UDT_STR: + pd->status.str = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_AGI: + pd->status.agi = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_VIT: + pd->status.vit = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_INT: + pd->status.int_ = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_DEX: + pd->status.dex = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_LUK: + pd->status.luk = (unsigned short) val; + status->calc_misc(bl, &pd->status, pd->pet.level); + break; + case UDT_ATKRANGE: + pd->status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + pd->status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + pd->status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + pd->status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + pd->status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + pd->status.def = (defType) val; + break; + case UDT_MDEF: + pd->status.mdef = (defType) val; + break; + case UDT_HIT: + pd->status.hit = (short) val; + break; + case UDT_FLEE: + pd->status.flee = (short) val; + break; + case UDT_PDODGE: + pd->status.flee2 = (short) val; + break; + case UDT_CRIT: + pd->status.cri = (short) val; + break; + case UDT_RACE: + pd->status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + pd->status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + pd->status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + pd->status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + pd->status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + pd->status.dmotion = (unsigned short) val; + break; + case UDT_INTIMACY: + pet->set_intimate(pd, val); + clif->send_petdata(pd->msd, pd, 1, pd->pet.intimate); + break; + case UDT_HUNGER: + pd->pet.hungry = (short) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for pet unit.\n", udtype); + script_pushint(st, 0); + return false; + } + clif->send_petstatus(pd->msd); // send pet data + } + break; + case BL_MER: + { + struct mercenary_data *mc = BL_UCAST(BL_MER, bl); + + nullpo_retr(false, mc); + + switch (type) + { + case UDT_SIZE: + mc->base_status.size = (unsigned char) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + mc->base_status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + mc->base_status.max_sp = (unsigned int) val; + break; + case UDT_MASTERCID: + mc->mercenary.char_id = val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + mc->base_status.size = (unsigned char) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + mc->ud.canmove_tick = val; + break; + case UDT_STR: + mc->base_status.str = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_AGI: + mc->base_status.agi = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_VIT: + mc->base_status.vit = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_INT: + mc->base_status.int_ = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_DEX: + mc->base_status.dex = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_LUK: + mc->base_status.luk = (unsigned short) val; + status->calc_misc(bl, &mc->base_status, mc->db->lv); + break; + case UDT_ATKRANGE: + mc->base_status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + mc->base_status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + mc->base_status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + mc->base_status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + mc->base_status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + mc->base_status.def = (defType) val; + break; + case UDT_MDEF: + mc->base_status.mdef = (defType) val; + break; + case UDT_HIT: + mc->base_status.hit = (short) val; + break; + case UDT_FLEE: + mc->base_status.flee = (short) val; + break; + case UDT_PDODGE: + mc->base_status.flee2 = (short) val; + break; + case UDT_CRIT: + mc->base_status.cri = (short) val; + break; + case UDT_RACE: + mc->base_status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + mc->base_status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + mc->base_status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + mc->base_status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + mc->base_status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + mc->base_status.dmotion = (unsigned short) val; + break; + case UDT_MERC_KILLCOUNT: + mc->mercenary.kill_count = (unsigned int) val; + break; + case UDT_LIFETIME: + mc->mercenary.life_time = (unsigned int) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for mercenary unit.\n", udtype); + script_pushint(st, 0); + return false; + } + + clif->mercenary_info(map->charid2sd(mc->mercenary.char_id)); + clif->mercenary_skillblock(map->charid2sd(mc->mercenary.char_id)); + } + break; + case BL_ELEM: + { + struct elemental_data *ed = BL_UCAST(BL_ELEM, bl); + + nullpo_retr(false, ed); + + switch (type) + { + case UDT_SIZE: + ed->base_status.size = (unsigned char) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + ed->base_status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + ed->base_status.max_sp = (unsigned int) val; + break; + case UDT_MASTERCID: + ed->elemental.char_id = val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_SPEED: + ed->base_status.speed = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_CANMOVETICK: + ed->ud.canmove_tick = val; + break; + case UDT_STR: + ed->base_status.str = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_AGI: + ed->base_status.agi = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_VIT: + ed->base_status.vit = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_INT: + ed->base_status.int_ = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_DEX: + ed->base_status.dex = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_LUK: + ed->base_status.luk = (unsigned short) val; + status->calc_misc(bl, &ed->base_status, ed->db->lv); + break; + case UDT_ATKRANGE: + ed->base_status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + ed->base_status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + ed->base_status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + ed->base_status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + ed->base_status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + ed->base_status.def = (defType) val; + break; + case UDT_MDEF: + ed->base_status.mdef = (defType) val; + break; + case UDT_HIT: + ed->base_status.hit = (short) val; + break; + case UDT_FLEE: + ed->base_status.flee = (short) val; + break; + case UDT_PDODGE: + ed->base_status.flee2 = (short) val; + break; + case UDT_CRIT: + ed->base_status.cri = (short) val; + break; + case UDT_RACE: + ed->base_status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + ed->base_status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + ed->base_status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + ed->base_status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + ed->base_status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + ed->base_status.dmotion = (unsigned short) val; + break; + case UDT_LIFETIME: + ed->elemental.life_time = val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for elemental unit.\n", udtype); + script_pushint(st, 0); + return false; + } + clif->elemental_info(ed->master); + } + break; + case BL_NPC: + { + struct npc_data *nd = BL_UCAST(BL_NPC, bl); + + nullpo_retr(false, nd); + + switch (type) + { + case UDT_SIZE: + nd->status.size = (unsigned char) val; + break; + case UDT_LEVEL: + nd->level = (unsigned short) val; + break; + case UDT_HP: + status->set_hp(bl, (unsigned int) val, 0); + break; + case UDT_MAXHP: + nd->status.max_hp = (unsigned int) val; + break; + case UDT_SP: + status->set_sp(bl, (unsigned int) val, 0); + break; + case UDT_MAXSP: + nd->status.max_sp = (unsigned int) val; + break; + case UDT_MAPIDXY: + unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + break; + case UDT_WALKTOXY: + if (!unit->walktoxy(bl, (short) val, (short) val2, 2)) + unit->movepos(bl, (short) val, (short) val2, 0, 0); + break; + case UDT_CLASS: + npc->setclass(nd, (short) val); + break; + case UDT_SPEED: + nd->speed = (short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_LOOKDIR: + unit->setdir(bl, (unsigned char) val); + break; + case UDT_STR: + nd->status.str = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_AGI: + nd->status.agi = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_VIT: + nd->status.vit = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_INT: + nd->status.int_ = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_DEX: + nd->status.dex = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_LUK: + nd->status.luk = (unsigned short) val; + status->calc_misc(bl, &nd->status, nd->level); + break; + case UDT_STATPOINT: + nd->stat_point = (unsigned short) val; + break; + case UDT_ATKRANGE: + nd->status.rhw.range = (unsigned short) val; + break; + case UDT_ATKMIN: + nd->status.rhw.atk = (unsigned short) val; + break; + case UDT_ATKMAX: + nd->status.rhw.atk2 = (unsigned short) val; + break; + case UDT_MATKMIN: + nd->status.matk_min = (unsigned short) val; + break; + case UDT_MATKMAX: + nd->status.matk_max = (unsigned short) val; + break; + case UDT_DEF: + nd->status.def = (defType) val; + break; + case UDT_MDEF: + nd->status.mdef = (defType) val; + break; + case UDT_HIT: + nd->status.hit = (short) val; + break; + case UDT_FLEE: + nd->status.flee = (short) val; + break; + case UDT_PDODGE: + nd->status.flee2 = (short) val; + break; + case UDT_CRIT: + nd->status.cri = (short) val; + break; + case UDT_RACE: + nd->status.race = (unsigned char) val; + break; + case UDT_ELETYPE: + nd->status.def_ele = (unsigned char) val; + break; + case UDT_ELELEVEL: + nd->status.ele_lv = (unsigned char) val; + break; + case UDT_AMOTION: + nd->status.amotion = (unsigned short) val; + break; + case UDT_ADELAY: + nd->status.adelay = (unsigned short) val; + break; + case UDT_DMOTION: + nd->status.dmotion = (unsigned short) val; + break; + default: + ShowWarning("buildin_setunitdata: Invalid data type '%s' for NPC unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + default: + ShowError("buildin_setunitdata: Unknown object!\n"); + script_pushint(st, 0); + return false; + } // end of bl->type switch + + script_pushint(st, 1); + return true; +} + +/** + * Retrieves real-time data for a game object. + * Getunitdata <GUID>,<DataType>{,<Variable>} + * @param1 GUID Game object unique Id. + * @param2 DataType Type of Data to be set for the unit. + * @param3 Variable array reference to store data into. (used for UDT_MAPIDXY) + * @return 0 on failure, <value> on success + */ +BUILDIN(getunitdata) +{ + struct block_list *bl; + const char *udtype = NULL; + const struct map_session_data *sd = NULL; + int type = 0; + char* name = NULL; + struct script_data *data = script_hasdata(st,4)?script_getdata(st, 4):NULL; + + bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_getunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + type = script_getnum(st, 3); + + /* Type check */ + if (type < UDT_TYPE || type >= UDT_MAX) { + ShowError("buildin_getunitdata: Invalid unit data type %d provided.\n", type); + script_pushint(st, 0); + return false; + } + + /* Argument checks */ + if (type == UDT_MAPIDXY) { + if (data == NULL || !data_isreference(data)) { + ShowWarning("buildin_getunitdata: Error in argument 3. Please provide a reference variable to store values in.\n"); + script_pushint(st, 0); + return false; + } + + name = reference_getname(data); + + if (not_server_variable(*name)) { + sd = script->rid2sd(st); + if (sd == NULL) { + ShowWarning("buildin_getunitdata: Player not attached! Cannot use player variable %s.\n",name); + script_pushint(st, 0); + return true;// no player attached + } + } + } + +#define getunitdata_sub(idx__,var__) script->setd_sub(st,NULL,name,(idx__),(void *)h64BPTRSIZE((int)(var__)),data->ref); + + switch (bl->type) { + case BL_MOB: + { + const struct mob_data *md = BL_UCAST(BL_MOB, bl); + + nullpo_retr(false, md); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_MOB); break; + case UDT_SIZE: script_pushint(st, md->status.size); break; + case UDT_LEVEL: script_pushint(st, md->level); break; + case UDT_HP: script_pushint(st, md->status.hp); break; + case UDT_MAXHP: script_pushint(st, md->status.max_hp); break; + case UDT_SP: script_pushint(st, md->status.sp); break; + case UDT_MAXSP: script_pushint(st, md->status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, md->bl.m); + getunitdata_sub(1, md->bl.x); + getunitdata_sub(2, md->bl.y); + break; + case UDT_SPEED: script_pushint(st, md->status.speed); break; + case UDT_MODE: script_pushint(st, md->status.mode); break; + case UDT_AI: script_pushint(st, md->special_state.ai); break; + case UDT_SCOPTION: script_pushint(st, md->sc.option); break; + case UDT_SEX: script_pushint(st, md->vd->sex); break; + case UDT_CLASS: script_pushint(st, md->vd->class); break; + case UDT_HAIRSTYLE: script_pushint(st, md->vd->hair_style); break; + case UDT_HAIRCOLOR: script_pushint(st, md->vd->hair_color); break; + case UDT_HEADBOTTOM: script_pushint(st, md->vd->head_bottom); break; + case UDT_HEADMIDDLE: script_pushint(st, md->vd->head_mid); break; + case UDT_HEADTOP: script_pushint(st, md->vd->head_top); break; + case UDT_CLOTHCOLOR: script_pushint(st, md->vd->cloth_color); break; + case UDT_SHIELD: script_pushint(st, md->vd->shield); break; + case UDT_WEAPON: script_pushint(st, md->vd->weapon); break; + case UDT_LOOKDIR: script_pushint(st, md->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, md->ud.canmove_tick); break; + case UDT_STR: script_pushint(st, md->status.str); break; + case UDT_AGI: script_pushint(st, md->status.agi); break; + case UDT_VIT: script_pushint(st, md->status.vit); break; + case UDT_INT: script_pushint(st, md->status.int_); break; + case UDT_DEX: script_pushint(st, md->status.dex); break; + case UDT_LUK: script_pushint(st, md->status.luk); break; + case UDT_ATKRANGE: script_pushint(st, md->status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, md->status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, md->status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, md->status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, md->status.matk_max); break; + case UDT_DEF: script_pushint(st, md->status.def); break; + case UDT_MDEF: script_pushint(st, md->status.mdef); break; + case UDT_HIT: script_pushint(st, md->status.hit); break; + case UDT_FLEE: script_pushint(st, md->status.flee); break; + case UDT_PDODGE: script_pushint(st, md->status.flee2); break; + case UDT_CRIT: script_pushint(st, md->status.cri); break; + case UDT_RACE: script_pushint(st, md->status.race); break; + case UDT_ELETYPE: script_pushint(st, md->status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, md->status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, md->status.amotion); break; + case UDT_ADELAY: script_pushint(st, md->status.adelay); break; + case UDT_DMOTION: script_pushint(st, md->status.dmotion); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mob unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_HOM: + { + const struct homun_data *hd = BL_UCAST(BL_HOM, bl); + + nullpo_retr(false, hd); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_HOM); break; + case UDT_SIZE: script_pushint(st, hd->base_status.size); break; + case UDT_LEVEL: script_pushint(st, hd->homunculus.level); break; + case UDT_HP: script_pushint(st, hd->base_status.hp); break; + case UDT_MAXHP: script_pushint(st, hd->base_status.max_hp); break; + case UDT_SP: script_pushint(st, hd->base_status.sp); break; + case UDT_MAXSP: script_pushint(st, hd->base_status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, hd->bl.m); + getunitdata_sub(1, hd->bl.x); + getunitdata_sub(2, hd->bl.y); + break; + case UDT_SPEED: script_pushint(st, hd->base_status.speed); break; + case UDT_LOOKDIR: script_pushint(st, hd->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, hd->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, hd->base_status.mode); break; + case UDT_STR: script_pushint(st, hd->base_status.str); break; + case UDT_AGI: script_pushint(st, hd->base_status.agi); break; + case UDT_VIT: script_pushint(st, hd->base_status.vit); break; + case UDT_INT: script_pushint(st, hd->base_status.int_); break; + case UDT_DEX: script_pushint(st, hd->base_status.dex); break; + case UDT_LUK: script_pushint(st, hd->base_status.luk); break; + case UDT_ATKRANGE: script_pushint(st, hd->base_status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, hd->base_status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, hd->base_status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, hd->base_status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, hd->base_status.matk_max); break; + case UDT_DEF: script_pushint(st, hd->base_status.def); break; + case UDT_MDEF: script_pushint(st, hd->base_status.mdef); break; + case UDT_HIT: script_pushint(st, hd->base_status.hit); break; + case UDT_FLEE: script_pushint(st, hd->base_status.flee); break; + case UDT_PDODGE: script_pushint(st, hd->base_status.flee2); break; + case UDT_CRIT: script_pushint(st, hd->base_status.cri); break; + case UDT_RACE: script_pushint(st, hd->base_status.race); break; + case UDT_ELETYPE: script_pushint(st, hd->base_status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, hd->base_status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, hd->base_status.amotion); break; + case UDT_ADELAY: script_pushint(st, hd->base_status.adelay); break; + case UDT_DMOTION: script_pushint(st, hd->base_status.dmotion); break; + case UDT_MASTERCID: script_pushint(st, hd->homunculus.char_id); break; + case UDT_HUNGER: script_pushint(st, hd->homunculus.hunger); break; + case UDT_INTIMACY: script_pushint(st, hd->homunculus.intimacy); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Homunculus unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_PET: + { + const struct pet_data *pd = BL_UCAST(BL_PET, bl); + + nullpo_retr(false, pd); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_PET); break; + case UDT_SIZE: script_pushint(st, pd->status.size); break; + case UDT_LEVEL: script_pushint(st, pd->pet.level); break; + case UDT_HP: script_pushint(st, pd->status.hp); break; + case UDT_MAXHP: script_pushint(st, pd->status.max_hp); break; + case UDT_SP: script_pushint(st, pd->status.sp); break; + case UDT_MAXSP: script_pushint(st, pd->status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, pd->bl.m); + getunitdata_sub(1, pd->bl.x); + getunitdata_sub(2, pd->bl.y); + break; + case UDT_SPEED: script_pushint(st, pd->status.speed); break; + case UDT_LOOKDIR: script_pushint(st, pd->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, pd->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, pd->status.mode); break; + case UDT_STR: script_pushint(st, pd->status.str); break; + case UDT_AGI: script_pushint(st, pd->status.agi); break; + case UDT_VIT: script_pushint(st, pd->status.vit); break; + case UDT_INT: script_pushint(st, pd->status.int_); break; + case UDT_DEX: script_pushint(st, pd->status.dex); break; + case UDT_LUK: script_pushint(st, pd->status.luk); break; + case UDT_ATKRANGE: script_pushint(st, pd->status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, pd->status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, pd->status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, pd->status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, pd->status.matk_max); break; + case UDT_DEF: script_pushint(st, pd->status.def); break; + case UDT_MDEF: script_pushint(st, pd->status.mdef); break; + case UDT_HIT: script_pushint(st, pd->status.hit); break; + case UDT_FLEE: script_pushint(st, pd->status.flee); break; + case UDT_PDODGE: script_pushint(st, pd->status.flee2); break; + case UDT_CRIT: script_pushint(st, pd->status.cri); break; + case UDT_RACE: script_pushint(st, pd->status.race); break; + case UDT_ELETYPE: script_pushint(st, pd->status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, pd->status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, pd->status.amotion); break; + case UDT_ADELAY: script_pushint(st, pd->status.adelay); break; + case UDT_DMOTION: script_pushint(st, pd->status.dmotion); break; + case UDT_MASTERAID: script_pushint(st, pd->pet.account_id); break; + case UDT_HUNGER: script_pushint(st, pd->pet.hungry); break; + case UDT_INTIMACY: script_pushint(st, pd->pet.intimate); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Pet unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_MER: + { + const struct mercenary_data *mc = BL_UCAST(BL_MER, bl); + + nullpo_retr(false, mc); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_MER); break; + case UDT_SIZE: script_pushint(st, mc->base_status.size); break; + case UDT_HP: script_pushint(st, mc->base_status.hp); break; + case UDT_MAXHP: script_pushint(st, mc->base_status.max_hp); break; + case UDT_SP: script_pushint(st, mc->base_status.sp); break; + case UDT_MAXSP: script_pushint(st, mc->base_status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, mc->bl.m); + getunitdata_sub(1, mc->bl.x); + getunitdata_sub(2, mc->bl.y); + break; + case UDT_SPEED: script_pushint(st, mc->base_status.speed); break; + case UDT_LOOKDIR: script_pushint(st, mc->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, mc->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, mc->base_status.mode); break; + case UDT_STR: script_pushint(st, mc->base_status.str); break; + case UDT_AGI: script_pushint(st, mc->base_status.agi); break; + case UDT_VIT: script_pushint(st, mc->base_status.vit); break; + case UDT_INT: script_pushint(st, mc->base_status.int_); break; + case UDT_DEX: script_pushint(st, mc->base_status.dex); break; + case UDT_LUK: script_pushint(st, mc->base_status.luk); break; + case UDT_ATKRANGE: script_pushint(st, mc->base_status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, mc->base_status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, mc->base_status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, mc->base_status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, mc->base_status.matk_max); break; + case UDT_DEF: script_pushint(st, mc->base_status.def); break; + case UDT_MDEF: script_pushint(st, mc->base_status.mdef); break; + case UDT_HIT: script_pushint(st, mc->base_status.hit); break; + case UDT_FLEE: script_pushint(st, mc->base_status.flee); break; + case UDT_PDODGE: script_pushint(st, mc->base_status.flee2); break; + case UDT_CRIT: script_pushint(st, mc->base_status.cri); break; + case UDT_RACE: script_pushint(st, mc->base_status.race); break; + case UDT_ELETYPE: script_pushint(st, mc->base_status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, mc->base_status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, mc->base_status.amotion); break; + case UDT_ADELAY: script_pushint(st, mc->base_status.adelay); break; + case UDT_DMOTION: script_pushint(st, mc->base_status.dmotion); break; + case UDT_MASTERCID: script_pushint(st, mc->mercenary.char_id); break; + case UDT_MERC_KILLCOUNT: script_pushint(st, mc->mercenary.kill_count); break; + case UDT_LIFETIME: script_pushint(st, mc->mercenary.life_time); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mercenary unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_ELEM: + { + const struct elemental_data *ed = BL_UCAST(BL_ELEM, bl); + + nullpo_retr(false, ed); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_ELEM); break; + case UDT_SIZE: script_pushint(st, ed->base_status.size); break; + case UDT_HP: script_pushint(st, ed->base_status.hp); break; + case UDT_MAXHP: script_pushint(st, ed->base_status.max_hp); break; + case UDT_SP: script_pushint(st, ed->base_status.sp); break; + case UDT_MAXSP: script_pushint(st, ed->base_status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, ed->bl.m); + getunitdata_sub(1, ed->bl.x); + getunitdata_sub(2, ed->bl.y); + break; + case UDT_SPEED: script_pushint(st, ed->base_status.speed); break; + case UDT_LOOKDIR: script_pushint(st, ed->ud.dir); break; + case UDT_CANMOVETICK: script_pushint(st, ed->ud.canmove_tick); break; + case UDT_MODE: script_pushint(st, ed->base_status.mode); break; + case UDT_STR: script_pushint(st, ed->base_status.str); break; + case UDT_AGI: script_pushint(st, ed->base_status.agi); break; + case UDT_VIT: script_pushint(st, ed->base_status.vit); break; + case UDT_INT: script_pushint(st, ed->base_status.int_); break; + case UDT_DEX: script_pushint(st, ed->base_status.dex); break; + case UDT_LUK: script_pushint(st, ed->base_status.luk); break; + case UDT_ATKRANGE: script_pushint(st, ed->base_status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, ed->base_status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, ed->base_status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, ed->base_status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, ed->base_status.matk_max); break; + case UDT_DEF: script_pushint(st, ed->base_status.def); break; + case UDT_MDEF: script_pushint(st, ed->base_status.mdef); break; + case UDT_HIT: script_pushint(st, ed->base_status.hit); break; + case UDT_FLEE: script_pushint(st, ed->base_status.flee); break; + case UDT_PDODGE: script_pushint(st, ed->base_status.flee2); break; + case UDT_CRIT: script_pushint(st, ed->base_status.cri); break; + case UDT_RACE: script_pushint(st, ed->base_status.race); break; + case UDT_ELETYPE: script_pushint(st, ed->base_status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, ed->base_status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, ed->base_status.amotion); break; + case UDT_ADELAY: script_pushint(st, ed->base_status.adelay); break; + case UDT_DMOTION: script_pushint(st, ed->base_status.dmotion); break; + case UDT_MASTERCID: script_pushint(st, ed->elemental.char_id); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for Elemental unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + case BL_NPC: + { + const struct npc_data *nd = BL_UCAST(BL_NPC, bl); + + nullpo_retr(false, nd); + + switch (type) + { + case UDT_TYPE: script_pushint(st, BL_NPC); break; + case UDT_SIZE: script_pushint(st, nd->status.size); break; + case UDT_HP: script_pushint(st, nd->status.hp); break; + case UDT_MAXHP: script_pushint(st, nd->status.max_hp); break; + case UDT_SP: script_pushint(st, nd->status.sp); break; + case UDT_MAXSP: script_pushint(st, nd->status.max_sp); break; + case UDT_MAPIDXY: + getunitdata_sub(0, bl->m); + getunitdata_sub(1, bl->x); + getunitdata_sub(2, bl->y); + break; + case UDT_SPEED: script_pushint(st, nd->status.speed); break; + case UDT_LOOKDIR: script_pushint(st, nd->ud->dir); break; + case UDT_CANMOVETICK: script_pushint(st, nd->ud->canmove_tick); break; + case UDT_MODE: script_pushint(st, nd->status.mode); break; + case UDT_STR: script_pushint(st, nd->status.str); break; + case UDT_AGI: script_pushint(st, nd->status.agi); break; + case UDT_VIT: script_pushint(st, nd->status.vit); break; + case UDT_INT: script_pushint(st, nd->status.int_); break; + case UDT_DEX: script_pushint(st, nd->status.dex); break; + case UDT_LUK: script_pushint(st, nd->status.luk); break; + case UDT_ATKRANGE: script_pushint(st, nd->status.rhw.range); break; + case UDT_ATKMIN: script_pushint(st, nd->status.rhw.atk); break; + case UDT_ATKMAX: script_pushint(st, nd->status.rhw.atk2); break; + case UDT_MATKMIN: script_pushint(st, nd->status.matk_min); break; + case UDT_MATKMAX: script_pushint(st, nd->status.matk_max); break; + case UDT_DEF: script_pushint(st, nd->status.def); break; + case UDT_MDEF: script_pushint(st, nd->status.mdef); break; + case UDT_HIT: script_pushint(st, nd->status.hit); break; + case UDT_FLEE: script_pushint(st, nd->status.flee); break; + case UDT_PDODGE: script_pushint(st, nd->status.flee2); break; + case UDT_CRIT: script_pushint(st, nd->status.cri); break; + case UDT_RACE: script_pushint(st, nd->status.race); break; + case UDT_ELETYPE: script_pushint(st, nd->status.def_ele); break; + case UDT_ELELEVEL: script_pushint(st, nd->status.ele_lv); break; + case UDT_AMOTION: script_pushint(st, nd->status.amotion); break; + case UDT_ADELAY: script_pushint(st, nd->status.adelay); break; + case UDT_DMOTION: script_pushint(st, nd->status.dmotion); break; + default: + ShowWarning("buildin_getunitdata: Invalid data type '%s' for NPC unit.\n", udtype); + script_pushint(st, 0); + return false; + } + } + break; + default: + ShowError("buildin_getunitdata: Unknown object!\n"); + script_pushint(st, 0); + return false; + } // end of bl->type switch + +#undef getunitdata_sub + + return false; +} + +/** + * Gets the name of a Unit. + * Supported types are [MOB|HOM|PET|NPC]. + * MER and ELEM don't support custom names. + * + * @command getunitname <GUID>; + * @param GUID Game Object Unique ID. + * @return boolean or Name of the game object. + */ +BUILDIN(getunitname) +{ + const struct block_list* bl = NULL; + + bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_getunitname: Error in finding object with given game ID %d!\n", script_getnum(st, 2)); + script_pushconststr(st, "Unknown"); + return false; + } + + script_pushstrcopy(st, status->get_name(bl)); + + return true; +} + +/** + * Changes the name of a bl. + * Supported types are [MOB|HOM|PET]. + * For NPC see 'setnpcdisplay', MER and ELEM don't support custom names. + * + * @command setunitname <GUID>,<name>; + * @param GUID Game object unique ID. + * @param Name as string. + * @return boolean. + */ +BUILDIN(setunitname) +{ + struct block_list* bl = map->id2bl(script_getnum(st, 2)); + + if (bl == NULL) { + ShowWarning("buildin_setunitname: Game object with ID %d was not found!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + switch (bl->type) { + case BL_MOB: + { + struct mob_data *md = BL_UCAST(BL_MOB, bl); + if (md == NULL) { + ShowWarning("buildin_setunitname: Error in finding object BL_MOB!\n"); + script_pushint(st, 0); + return false; + } + safestrncpy(md->name, script_getstr(st, 3), NAME_LENGTH); + } + break; + case BL_HOM: + { + struct homun_data *hd = BL_UCAST(BL_HOM, bl); + if (hd == NULL) { + ShowWarning("buildin_setunitname: Error in finding object BL_HOM!\n"); + script_pushint(st, 0); + return false; + } + safestrncpy(hd->homunculus.name, script_getstr(st, 3), NAME_LENGTH); + } + break; + case BL_PET: + { + struct pet_data *pd = BL_UCAST(BL_PET, bl); + if (pd == NULL) { + ShowWarning("buildin_setunitname: Error in finding object BL_PET!\n"); + script_pushint(st, 0); + return false; + } + safestrncpy(pd->pet.name, script_getstr(st, 3), NAME_LENGTH); + } + break; + default: + script_pushint(st, 0); + ShowWarning("buildin_setunitname: Unknown object type!\n"); + return false; + } + + script_pushint(st, 1); + clif->charnameack(0, bl); // Send update to client. + + return true; +} + /// Makes the unit walk to target position or target id /// Returns if it was successfull /// @@ -21857,6 +23443,11 @@ void script_parse_builtin(void) { // <--- [zBuffer] List of player cont commands // [zBuffer] List of mob control commands ---> BUILDIN_DEF(getunittype,"i"), + /* Unit Data */ + BUILDIN_DEF(setunitdata,"iiv??"), + BUILDIN_DEF(getunitdata,"ii?"), + BUILDIN_DEF(getunitname,"i"), + BUILDIN_DEF(setunitname,"is"), BUILDIN_DEF(unitwalk,"ii?"), BUILDIN_DEF(unitkill,"i"), BUILDIN_DEF(unitwarp,"isii"), diff --git a/src/map/script.h b/src/map/script.h index 0c967a94e..8caec961a 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -350,6 +350,81 @@ enum navigation_service { }; /** + * Unit Types for script handling. + */ +enum script_unit_types { + UNIT_PC = 0, + UNIT_NPC, + UNIT_PET, + UNIT_MOB, + UNIT_HOM, + UNIT_MER, + UNIT_ELEM, +}; + +/** + * Unit Data Types for script handling. + */ +enum script_unit_data_types { + UDT_TYPE = 0, + UDT_SIZE, + UDT_LEVEL, + UDT_HP, + UDT_MAXHP, + UDT_SP, + UDT_MAXSP, + UDT_MASTERAID, + UDT_MASTERCID, + UDT_MAPIDXY, + UDT_WALKTOXY, + UDT_SPEED, + UDT_MODE, + UDT_AI, + UDT_SCOPTION, + UDT_SEX, + UDT_CLASS, + UDT_HAIRSTYLE, + UDT_HAIRCOLOR, + UDT_HEADBOTTOM, + UDT_HEADMIDDLE, + UDT_HEADTOP, + UDT_CLOTHCOLOR, + UDT_SHIELD, + UDT_WEAPON, + UDT_LOOKDIR, + UDT_CANMOVETICK, + UDT_STR, + UDT_AGI, + UDT_VIT, + UDT_INT, + UDT_DEX, + UDT_LUK, + UDT_ATKRANGE, + UDT_ATKMIN, + UDT_ATKMAX, + UDT_MATKMIN, + UDT_MATKMAX, + UDT_DEF, + UDT_MDEF, + UDT_HIT, + UDT_FLEE, + UDT_PDODGE, + UDT_CRIT, + UDT_RACE, + UDT_ELETYPE, + UDT_ELELEVEL, + UDT_AMOTION, + UDT_ADELAY, + UDT_DMOTION, + UDT_HUNGER, + UDT_INTIMACY, + UDT_LIFETIME, + UDT_MERC_KILLCOUNT, + UDT_STATPOINT, + UDT_MAX +}; + +/** * Structures **/ diff --git a/src/map/unit.c b/src/map/unit.c index 7d68bef66..79abb8c6a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1667,6 +1667,9 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } else skill->castend_id(ud->skilltimer,tick,src->id,0); + if (sd != NULL && battle_config.prevent_logout_trigger & PLT_SKILL) + sd->canlog_tick = timer->gettick(); + return 1; } @@ -1813,6 +1816,10 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui ud->skilltimer = INVALID_TIMER; skill->castend_pos(ud->skilltimer,tick,src->id,0); } + + if (sd != NULL && battle_config.prevent_logout_trigger & PLT_SKILL) + sd->canlog_tick = timer->gettick(); + return 1; } @@ -2253,6 +2260,9 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) ud->attacktimer = timer->add(ud->attackabletime,unit->attack_timer,src->id,0); } + if (sd != NULL && battle_config.prevent_logout_trigger & PLT_ATTACK) + sd->canlog_tick = timer->gettick(); + return 1; } |