From c2d3c3cb60d3b794773196be88850ef6cc806105 Mon Sep 17 00:00:00 2001
From: Eason <62255465+jonathan-up@users.noreply.github.com>
Date: Fri, 28 Mar 2025 04:32:42 +0800
Subject: [PATCH] Add new native `rg_observer_find_next_player` (#325)

---
 .../scripting/include/reapi_gamedll.inc       | 12 ++++++++
 reapi/include/cssdk/dlls/API/CSPlayer.h       |  1 +
 reapi/src/natives/natives_misc.cpp            | 29 +++++++++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc
index 013eb5e..0fee9a6 100644
--- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc
+++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc
@@ -1185,6 +1185,18 @@ native rg_disappear(const player);
 */
 native rg_set_observer_mode(const player, const mode);
 
+/*
+* Call origin function CBasePlayer::Observer_FindNextPlayer()
+* @note Player must be a valid observer (m_afPhysicsFlags & PFLAG_OBSERVER).
+*
+* @param player                Player index.
+* @param bReverse              If bReverse is true, finding order will be reversed
+* @param name                  Player name to find.
+*
+* @noreturn
+*/
+native rg_observer_find_next_player(const player, const bool:bReverse = false, const name[] = "");
+
 /*
 * Emits a death notice (logs, DeathMsg event, win conditions check)
 *
diff --git a/reapi/include/cssdk/dlls/API/CSPlayer.h b/reapi/include/cssdk/dlls/API/CSPlayer.h
index 3495ee2..8290088 100644
--- a/reapi/include/cssdk/dlls/API/CSPlayer.h
+++ b/reapi/include/cssdk/dlls/API/CSPlayer.h
@@ -94,6 +94,7 @@ public:
 	virtual void SendItemStatus() = 0;
 	virtual void ReloadWeapons(CBasePlayerItem *pWeapon = nullptr, bool bForceReload = false, bool bForceRefill = false) = 0;
 	virtual void Observer_SetMode(int iMode) = 0;
+	virtual void Observer_FindNextPlayer(bool bReverse, const char *name = nullptr) = 0;
 	virtual bool SelectSpawnSpot(const char *pEntClassName, CBaseEntity* &pSpot) = 0;
 	virtual bool SwitchWeapon(CBasePlayerItem *pWeapon) = 0;
 	virtual void SwitchTeam() = 0;
diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp
index 3f6a381..1d78170 100644
--- a/reapi/src/natives/natives_misc.cpp
+++ b/reapi/src/natives/natives_misc.cpp
@@ -3242,6 +3242,34 @@ cell AMX_NATIVE_CALL rg_set_observer_mode(AMX* amx, cell* params)
 	return TRUE;
 }
 
+/*
+* Call origin function CBasePlayer::Observer_FindNextPlayer()
+* @note Player must be a valid observer (m_afPhysicsFlags & PFLAG_OBSERVER).
+*
+* @param player                Player index.
+* @param bReverse              If bReverse is true, finding order will be reversed
+* @param name                  Player name to find.
+*
+* @noreturn
+*/
+cell AMX_NATIVE_CALL rg_observer_find_next_player(AMX* amx, cell* params)
+{
+	enum args_e { arg_count, arg_index, arg_bReverse, arg_name };
+
+	CHECK_ISPLAYER(arg_index)
+
+	CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]);
+	CHECK_CONNECTED(pPlayer, arg_index);
+
+	char nameBuf[MAX_PLAYER_NAME_LENGTH];
+	const char* name = getAmxString(amx, params[arg_name], nameBuf);
+	if (strcmp(name, "") == 0)
+		name = nullptr;
+
+	pPlayer->CSPlayer()->Observer_FindNextPlayer(params[arg_bReverse] != 0, name);
+	return TRUE;
+}
+
 /*
 * Emits a death notice (logs, DeathMsg event, win conditions check)
 *
@@ -3455,6 +3483,7 @@ AMX_NATIVE_INFO Misc_Natives_RG[] =
 	{ "rg_switch_best_weapon",        rg_switch_best_weapon        },
 	{ "rg_disappear",                 rg_disappear                 },
 	{ "rg_set_observer_mode",         rg_set_observer_mode         },
+	{ "rg_observer_find_next_player", rg_observer_find_next_player },
 	{ "rg_death_notice",              rg_death_notice              },
 	{ "rg_player_relationship",       rg_player_relationship       },