فهرست منبع

Added independent idle time and settings for homunculus share (#4761)

* Follow up to 921b3e2c3e9eae36cbf2ca35bcede6e0d73ba074
Daegaladh 5 سال پیش
والد
کامیت
ca56c060cf
9فایلهای تغییر یافته به همراه75 افزوده شده و 6 حذف شده
  1. 22 2
      conf/battle/homunc.conf
  2. 8 0
      doc/script_commands.txt
  3. 2 0
      src/map/atcommand.cpp
  4. 2 1
      src/map/battle.cpp
  5. 1 0
      src/map/battle.hpp
  6. 24 0
      src/map/clif.cpp
  7. 2 2
      src/map/mob.cpp
  8. 2 1
      src/map/pc.hpp
  9. 12 0
      src/map/script.cpp

+ 22 - 2
conf/battle/homunc.conf

@@ -62,15 +62,35 @@ homunculus_S_growth_level: 99
 // Official: yes
 homunculus_autofeed_always: yes
 
-// Is getting exp/item from the homunculus disabled when you're idle?
+// Is getting exp/item from the homunculus disabled when their master's idle?
 // Set to no, or the amount of seconds (NOT milliseconds) that need to pass before considering
 // a character idle.
 // Characters in a chat/vending are always considered idle.
 // A character's idle status is reset upon item use/skill use/attack (auto attack counts too)/movement.
-// You will only receive items if 'homunculus_autoloot' is activated,
+// Their master will only receive items if 'homunculus_autoloot' is activated,
 // otherwise they will be dropped on the ground as usual.
+// NOTE: This option uses a special timer to track idle time, separated from the normal idle timer.
 hom_idle_no_share: no
 
+// How the server should measure the homunculus master's idle time? (for homunculus exp share and autoloot ONLY) (Note 3)
+// (This will only work if 'hom_idle_no_share' is enabled).
+// 0x001 - Walk Request
+// 0x002 - UseSkillToID Request (Targetted skill use attempt)
+// 0x004 - UseSkillToPos Request (AoE skill use attempt)
+// 0x008 - UseItem Request (Including equip/unequip)
+// 0x010 - Attack Request
+// 0x020 - Chat Request (Whisper, Party, Guild, Battlegrounds, etc)
+// 0x040 - Sit/Standup Request
+// 0x080 - Emotion Request
+// 0x100 - DropItem Request
+// 0x200 - @/#Command Request
+// Please note that at least 1 option has to be enabled.
+// Be mindful that the more options used, the easier it becomes to cheat this features.
+// Default: walk (0x1) + useskilltoid (0x2) + useskilltopos (0x4) + useitem (0x8) + attack (0x10) = 0x1F
+// NOTE: This allows you to configure different settings for homunculus, separated from normal idle timer and 'idletime_option'.
+// It will only apply to homunculus-only kills and it will not affect normal autoloot and party share options.
+idletime_hom_option: 0x1F
+
 // The rate at which homunculus gain experience from kills. (Note 2)
 // Only applies to renewal mode.
 // Official: 10%

+ 8 - 0
doc/script_commands.txt

@@ -3907,6 +3907,14 @@ Name is optional, and defaults to the attached player if omitted.
 
 ---------------------------------------
 
+*checkidlehom({"<Player Name>"})
+
+Returns the time, in seconds, that the specified player has been idle for homunculus item/exp share.
+Name is optional, and defaults to the attached player if omitted.
+This will only work if 'hom_idle_no_share' and 'idletime_hom_option' are enabled (see '/conf/battle/homunc.conf').
+
+---------------------------------------
+
 *agitcheck()
 *agitcheck2()
 *agitcheck3()

+ 2 - 0
src/map/atcommand.cpp

@@ -10728,6 +10728,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
 
 	if (battle_config.idletime_option&IDLE_ATCOMMAND)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_ATCOMMAND)
+		sd->idletime_hom = last_tick;
 
 	//Clearing these to be used once more.
 	memset(command, '\0', sizeof(command));

+ 2 - 1
src/map/battle.cpp

@@ -8820,7 +8820,7 @@ static const struct _battle_data {
 	{ "fame_pharmacy_10",                   &battle_config.fame_pharmacy_10,                50,     0,      INT_MAX,        },
 	{ "mail_delay",                         &battle_config.mail_delay,                      1000,   1000,   INT_MAX,        },
 	{ "at_monsterignore",                   &battle_config.autotrade_monsterignore,         0,      0,      1,              },
-	{ "idletime_option",                    &battle_config.idletime_option,                 0x25,   1,      INT_MAX,        },
+	{ "idletime_option",                    &battle_config.idletime_option,                 0x1F,   0x1,    0xFFF,          },
 	{ "spawn_direction",                    &battle_config.spawn_direction,                 0,      0,      1,              },
 	{ "arrow_shower_knockback",             &battle_config.arrow_shower_knockback,          1,      0,      1,              },
 	{ "devotion_rdamage_skill_only",        &battle_config.devotion_rdamage_skill_only,     1,      0,      1,              },
@@ -8894,6 +8894,7 @@ static const struct _battle_data {
 	{ "boss_nopc_idleskill_rate",           &battle_config.boss_nopc_idleskill_rate,        100,    0,    100,              },
 	{ "boss_nopc_move_rate",                &battle_config.boss_nopc_move_rate,             100,    0,    100,              },
 	{ "hom_idle_no_share",                  &battle_config.hom_idle_no_share,               0,      0,      INT_MAX,        },
+	{ "idletime_hom_option",                &battle_config.idletime_hom_option,             0x1F,   0x1,    0xFFF,          },
 	{ "devotion_standup_fix",               &battle_config.devotion_standup_fix,            1,      0,      1,              },
 	{ "feature.bgqueue",                    &battle_config.feature_bgqueue,                 1,      0,      1,              },
 	{ "homunculus_exp_gain",                &battle_config.homunculus_exp_gain,             10,     0,      100,            },

+ 1 - 0
src/map/battle.hpp

@@ -672,6 +672,7 @@ struct Battle_Config
 	int boss_nopc_idleskill_rate;
 	int boss_nopc_move_rate;
 	int hom_idle_no_share;
+	int idletime_hom_option;
 	int devotion_standup_fix;
 	int feature_bgqueue;
 	int homunculus_exp_gain;

+ 24 - 0
src/map/clif.cpp

@@ -10242,6 +10242,8 @@ static bool clif_process_message(struct map_session_data* sd, bool whisperFormat
 
 	if (battle_config.idletime_option&IDLE_CHAT)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_CHAT)
+		sd->idletime_hom = last_tick;
 
 	return true;
 }
@@ -11018,6 +11020,8 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
 	//Set last idle time... [Skotlex]
 	if (battle_config.idletime_option&IDLE_WALK)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_WALK)
+		sd->idletime_hom = last_tick;
 
 	unit_walktoxy(&sd->bl, x, y, 4);
 }
@@ -11232,6 +11236,8 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd)
 
 		if (battle_config.idletime_option&IDLE_EMOTION)
 			sd->idletime = last_tick;
+		if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_EMOTION)
+			sd->idletime_hom = last_tick;
 
 		if (sd->state.block_action & PCBLOCK_EMOTION) {
 			clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1);
@@ -11316,6 +11322,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 		pc_delinvincibletimer(sd);
 		if (battle_config.idletime_option&IDLE_ATTACK)
 			sd->idletime = last_tick;
+		if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_ATTACK)
+			sd->idletime_hom = last_tick;
 		unit_attack(&sd->bl, target_id, action_type != 0);
 		break;
 	case 0x02: // sitdown
@@ -11346,6 +11354,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 
 		if (battle_config.idletime_option&IDLE_SIT)
 			sd->idletime = last_tick;
+		if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_SIT)
+			sd->idletime_hom = last_tick;
 
 		pc_setsit(sd);
 		skill_sit(sd, true);
@@ -11369,6 +11379,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 		if (pc_setstand(sd, false)) {
 			if (battle_config.idletime_option&IDLE_SIT)
 				sd->idletime = last_tick;
+			if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_SIT)
+				sd->idletime_hom = last_tick;
 			skill_sit(sd, false);
 			clif_standing(&sd->bl);
 		}
@@ -11626,6 +11638,8 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd){
 
 		if (battle_config.idletime_option&IDLE_DROPITEM)
 			sd->idletime = last_tick;
+		if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_DROPITEM)
+			sd->idletime_hom = last_tick;
 
 		return;
 	}
@@ -11656,6 +11670,8 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
 	//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
 	if (battle_config.idletime_option&IDLE_USEITEM)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_USEITEM)
+		sd->idletime_hom = last_tick;
 	n = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2;
 
 	if(n <0 || n >= MAX_INVENTORY)
@@ -11703,6 +11719,8 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
 
 	if (battle_config.idletime_option&IDLE_USEITEM)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_USEITEM)
+		sd->idletime_hom = last_tick;
 
 	//Client doesn't send the position for ammo.
 	if(sd->inventory_data[index]->type == IT_AMMO)
@@ -11742,6 +11760,8 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
 
 	if (battle_config.idletime_option&IDLE_USEITEM)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_USEITEM)
+		sd->idletime_hom = last_tick;
 
 	pc_unequipitem(sd,index,1);
 }
@@ -12391,6 +12411,8 @@ void clif_parse_skill_toid( struct map_session_data* sd, uint16 skill_id, uint16
 	// This is done here, because homunculi and mercenaries can be triggered by AI and not by the player itself
 	if (battle_config.idletime_option&IDLE_USESKILLTOID)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_USESKILLTOID)
+		sd->idletime_hom = last_tick;
 
 	if( sd->npc_id ){
 		if( pc_hasprogress( sd, WIP_DISABLE_SKILLITEM ) || !sd->npc_item_flag || !( inf & INF_SELF_SKILL ) ){
@@ -12519,6 +12541,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
 	//Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
 	if (battle_config.idletime_option&IDLE_USESKILLTOPOS)
 		sd->idletime = last_tick;
+	if (battle_config.hom_idle_no_share && sd->hd && battle_config.idletime_hom_option&IDLE_USESKILLTOPOS)
+		sd->idletime_hom = last_tick;
 
 	if( skill_isNotOk(skill_id, sd) )
 		return;

+ 2 - 2
src/map/mob.cpp

@@ -2186,8 +2186,8 @@ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, str
 	if( sd == NULL ) sd = map_charid2sd(dlist->third_charid);
 	test_autoloot = sd 
 		&& (drop_rate <= sd->state.autoloot || pc_isautolooting(sd, ditem->item_data.nameid))
-		&& (battle_config.idle_no_autoloot == 0 || DIFF_TICK(last_tick, sd->idletime) < battle_config.idle_no_autoloot)
-		&& (battle_config.homunculus_autoloot?(battle_config.hom_idle_no_share == 0 || !pc_isidle_hom(sd)):!flag);
+		&& (flag?(battle_config.homunculus_autoloot?(battle_config.hom_idle_no_share == 0 || !pc_isidle_hom(sd)):0):
+			(battle_config.idle_no_autoloot == 0 || DIFF_TICK(last_tick, sd->idletime) < battle_config.idle_no_autoloot));
 #ifdef AUTOLOOT_DISTANCE
 		test_autoloot = test_autoloot && sd->bl.m == md->bl.m
 		&& check_distance_blxy(&sd->bl, dlist->x, dlist->y, AUTOLOOT_DISTANCE);

+ 2 - 1
src/map/pc.hpp

@@ -366,6 +366,7 @@ struct map_session_data {
 	int npc_timer_id; //For player attached npc timers. [Skotlex]
 	unsigned int chatID;
 	time_t idletime;
+	time_t idletime_hom;
 
 	struct s_progressbar {
 		int npc_id;
@@ -910,7 +911,7 @@ extern struct s_job_info job_info[CLASS_COUNT];
 #define pc_isdead(sd)         ( (sd)->state.dead_sit == 1 )
 #define pc_issit(sd)          ( (sd)->vd.dead_sit == 2 )
 #define pc_isidle_party(sd)   ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
-#define pc_isidle_hom(sd)     ( (sd)->hd && ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.hom_idle_no_share ) )
+#define pc_isidle_hom(sd)     ( (sd)->hd && ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime_hom) >= battle_config.hom_idle_no_share ) )
 #define pc_istrading(sd)      ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
 #define pc_cant_act(sd)       ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
 

+ 12 - 0
src/map/script.cpp

@@ -17384,6 +17384,17 @@ BUILDIN_FUNC(checkidle)
 	return SCRIPT_CMD_SUCCESS;
 }
 
+BUILDIN_FUNC(checkidlehom)
+{
+	TBL_PC *sd = NULL;
+
+	if( script_nick2sd(2,sd) )
+		script_pushint(st, DIFF_TICK(last_tick, sd->idletime_hom));
+	else
+		script_pushint(st, 0);
+	return SCRIPT_CMD_SUCCESS;
+}
+
 BUILDIN_FUNC(searchitem)
 {
 	struct script_data* data = script_getdata(st, 2);
@@ -25082,6 +25093,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(checkvending,"?"),
 	BUILDIN_DEF(checkchatting,"?"),
 	BUILDIN_DEF(checkidle,"?"),
+	BUILDIN_DEF(checkidlehom,"?"),
 	BUILDIN_DEF(openmail,"?"),
 	BUILDIN_DEF(openauction,"?"),
 	BUILDIN_DEF(checkcell,"siii"),