11#pragma semicolon 1
22
33#include < amxmodx>
4- #include < fakemeta>
5- #include < hamsandwich>
6-
7- #tryinclude < reapi>
8-
9- #if defined _reapi_included
10- # define ROUND_CONTINUE HC_CONTINUE
11- # define ROUND_SUPERCEDE HC_SUPERCEDE
12- # define WINSTATUS_TERRORIST WINSTATUS_TERRORISTS
13- # define WINSTATUS_CT WINSTATUS_CTS
14- #else
15- #include < roundcontrol>
16- #endif
17-
18- # define PLUGIN " [API] Rounds"
19- # define AUTHOR " Hedgehog Fog"
20- # define VERSION " 1.0.0"
21-
22- # define TASKID_ROUNDTIME_EXPIRE 1
4+ #include < reapi>
235
246enum GameState {
257 GameState_NewRound,
@@ -30,41 +12,40 @@ enum GameState {
3012enum _: Hook {
3113 Hook_PluginId,
3214 Hook_FunctionId
33- }
15+ };
16+
17+ new GameState: g_iGameState;
3418
35- new g_iFwResult;
3619new g_iFwNewRound;
3720new g_iFwRoundStart;
3821new g_iFwRoundEnd;
3922new g_iFwRoundExpired;
23+ new g_iFwRoundRestart;
24+ new g_iFwRoundTimerTick;
4025
41- new GameState: g_iGamestate;
42- new Float: g_fRoundStartTime;
26+ new Array: g_irgCheckWinConditionHooks;
4327
44- new Array: g_iCheckWinConditionHooks ;
28+ new g_pCvarRoundEndDelay ;
4529
4630public plugin_init () {
47- register_plugin (PLUGIN, VERSION, AUTHOR);
48-
49- register_event (" HLTV" , " OnNewRound" , " a" , " 1=0" , " 2=0" );
50- register_logevent (" OnRoundStart" , 2 , " 1=Round_Start" );
51- register_logevent (" OnRoundEnd" , 2 , " 1=Round_End" );
52- register_event (" TextMsg" , " OnRoundEnd" , " a" , " 2=#Game_will_restart_in" );
53-
54- #if defined _reapi_included
55- RegisterHookChain (RG_CSGameRules_CheckWinConditions, " OnCheckWinConditions" );
56- #else
57- RegisterControl (RC_CheckWinConditions, " OnCheckWinConditions" );
58- #endif
31+ register_plugin (" [API] Rounds" , " 2.0.0" , " Hedgehog Fog" );
5932
60- register_message (get_user_msgid (" RoundTime" ), " OnMessage_RoundTime" );
33+ register_event (" HLTV" , " Event_NewRound" , " a" , " 1=0" , " 2=0" );
34+ RegisterHookChain (RG_CSGameRules_RestartRound, " HC_RestartRound" , .post = 0 );
35+ RegisterHookChain (RG_CSGameRules_OnRoundFreezeEnd, " HC_OnRoundFreezeEnd_Post" , .post = 1 );
36+ RegisterHookChain (RG_RoundEnd, " HC_RoundEnd" , .post = 1 );
37+ RegisterHookChain (RG_CSGameRules_CheckWinConditions, " HC_CheckWinConditions" , .post = 0 );
6138
6239 g_iFwNewRound = CreateMultiForward (" Round_Fw_NewRound" , ET_IGNORE);
6340 g_iFwRoundStart = CreateMultiForward (" Round_Fw_RoundStart" , ET_IGNORE);
64- g_iFwRoundEnd = CreateMultiForward (" Round_Fw_RoundEnd" , ET_IGNORE);
41+ g_iFwRoundEnd = CreateMultiForward (" Round_Fw_RoundEnd" , ET_IGNORE, FP_CELL );
6542 g_iFwRoundExpired = CreateMultiForward (" Round_Fw_RoundExpired" , ET_IGNORE);
43+ g_iFwRoundRestart = CreateMultiForward (" Round_Fw_RoundRestart" , ET_IGNORE);
44+ g_iFwRoundTimerTick = CreateMultiForward (" Round_Fw_RoundTimerTick" , ET_IGNORE);
6645
67- g_iCheckWinConditionHooks = ArrayCreate (Hook);
46+ g_irgCheckWinConditionHooks = ArrayCreate (Hook);
47+
48+ g_pCvarRoundEndDelay = get_cvar_pointer (" mp_round_restart_delay" );
6849}
6950
7051public plugin_natives () {
@@ -79,166 +60,175 @@ public plugin_natives() {
7960}
8061
8162public plugin_destroy () {
82- ArrayDestroy (g_iCheckWinConditionHooks );
63+ ArrayDestroy (g_irgCheckWinConditionHooks );
8364}
8465
85- /* --------------------------------[ Natives ]--------------------------------*/
66+ public server_frame () {
67+ static Float: flTime;
68+ flTime = get_gametime ();
8669
87- public Native_DispatchWin (iPluginId, iArgc) {
88- new iTeam = get_param (1 );
89- new Float: fDelay = get_param_f (2 );
90- DispatchWin (iTeam, fDelay);
91- }
70+ static Float: flNextPeriodicThink;
71+ flNextPeriodicThink = get_member_game (m_tmNextPeriodicThink);
9272
93- public Native_GetTime (iPluginId, iArgc ) {
94- return GetTime () ;
95- }
73+ if (flNextPeriodicThink < flTime ) {
74+ static bool: bFreezePeriod ;
75+ bFreezePeriod = get_member_game (m_bFreezePeriod);
9676
97- public Native_SetTime (iPluginId, iArgc) {
98- new iTime = get_param (1 );
99- SetTime (iTime);
77+ ExecuteForward (g_iFwRoundTimerTick);
78+
79+ static iRoundTimeSecs;
80+ iRoundTimeSecs = get_member_game (m_iRoundTimeSecs);
81+
82+ static Float: flStartTime;
83+ flStartTime = get_member_game (m_fRoundStartTimeReal);
84+
85+ static Float: flEndTime;
86+ flEndTime = flStartTime + float (iRoundTimeSecs);
87+
88+ if (! bFreezePeriod) {
89+ if (flTime >= flEndTime) {
90+ ExecuteForward (g_iFwRoundExpired);
91+ }
92+ }
93+ }
10094}
10195
102- public Native_GetTimeLeft (iPluginId, iArgc) {
103- return GetTimeLeft ();
96+ public HC_RestartRound () {
97+ if (! get_member_game (m_bCompleteReset)) {
98+ // g_iGameState = GameState_NewRound;
99+ // ExecuteForward(g_iFwNewRound);
100+ } else {
101+ ExecuteForward (g_iFwRoundRestart);
102+ }
104103}
105104
106- public bool: Native_IsRoundStarted (iPluginId, iArgc) {
107- return g_iGamestate > GameState_NewRound;
105+ public HC_OnRoundFreezeEnd_Post () {
106+ g_iGameState = GameState_RoundStarted;
107+ ExecuteForward (g_iFwRoundStart);
108108}
109109
110- public bool: Native_IsRoundEnd (iPluginId, iArgc) {
111- return g_iGamestate == GameState_RoundEnd;
110+ public Event_NewRound () {
111+ g_iGameState = GameState_NewRound;
112+ ExecuteForward (g_iFwNewRound);
112113}
113114
114- public Native_HookCheckWinConditions (iPluginId, iArgc) {
115- static szFunctionName[32 ];
116- get_string (1 , szFunctionName, charsmax (szFunctionName));
115+ public HC_RoundEnd (WinStatus: iStatus, ScenarioEventEndRound: iEvent, Float: flDelay) {
116+ new TeamName: iWinTeam = TEAM_UNASSIGNED;
117117
118- new hook [Hook];
119- hook [Hook_PluginId] = iPluginId;
120- hook [Hook_FunctionId] = get_func_id (szFunctionName, iPluginId);
118+ switch (iStatus) {
119+ case WINSTATUS_TERRORISTS: iWinTeam = TEAM_TERRORIST;
120+ case WINSTATUS_CTS: iWinTeam = TEAM_CT;
121+ case WINSTATUS_DRAW: iWinTeam = TEAM_SPECTATOR;
122+ }
121123
122- ArrayPushArray (g_iCheckWinConditionHooks, hook );
123- }
124+ g_iGameState = GameState_RoundEnd;
124125
125- /* --------------------------------[ Hooks ]--------------------------------*/
126+ ExecuteForward (g_iFwRoundEnd, _, _: iWinTeam);
127+ }
126128
127- public OnCheckWinConditions () {
128- new size = ArraySize (g_iCheckWinConditionHooks );
129+ public HC_CheckWinConditions () {
130+ new iSize = ArraySize (g_irgCheckWinConditionHooks );
129131
130- for (new i = 0 ; i < size ; ++ i) {
132+ for (new i = 0 ; i < iSize ; ++ i) {
131133 static hook [_: Hook];
132- ArrayGetArray (g_iCheckWinConditionHooks , i, hook );
134+ ArrayGetArray (g_irgCheckWinConditionHooks , i, hook );
133135
134136 if (callfunc_begin_i (hook [Hook_FunctionId], hook [Hook_PluginId]) == 1 ) {
135137 if (callfunc_end () > PLUGIN_CONTINUE) {
136- return ROUND_SUPERCEDE ;
138+ return HC_SUPERCEDE ;
137139 }
138140 }
139141 }
140142
141- return ROUND_CONTINUE ;
143+ return HC_CONTINUE ;
142144}
143145
144- public OnNewRound () {
145- g_iGamestate = GameState_NewRound;
146- ExecuteForward (g_iFwNewRound, g_iFwResult);
146+ public Native_DispatchWin (iPluginId, iArgc) {
147+ new iTeam = get_param (1 );
148+ new Float: flDelay = get_param_f (2 );
149+ DispatchWin (iTeam, flDelay);
147150}
148151
149- public OnRoundStart () {
150- g_iGamestate = GameState_RoundStarted;
151- g_fRoundStartTime = get_gametime ();
152- UpdateRoundTime ();
153- ExecuteForward (g_iFwRoundStart, g_iFwResult);
152+ public Native_GetTime (iPluginId, iArgc) {
153+ return get_member_game (m_iRoundTimeSecs);
154154}
155155
156- public OnRoundEnd () {
157- g_iGamestate = GameState_RoundEnd;
158- remove_task (TASKID_ROUNDTIME_EXPIRE);
159- ExecuteForward (g_iFwRoundEnd, g_iFwResult);
156+ public Native_SetTime (iPluginId, iArgc) {
157+ new iTime = get_param (1 );
158+ SetTime (iTime);
160159}
161160
162- public OnRoundTimeExpired ( ) {
163- ExecuteForward (g_iFwRoundExpired, g_iFwResult );
161+ public Native_GetTimeLeft (iPluginId, iArgc ) {
162+ return GetTimeLeft ( );
164163}
165164
166- public OnMessage_RoundTime () {
167- if (g_iGamestate == GameState_NewRound) {
168- return PLUGIN_CONTINUE;
169- }
170-
171- set_msg_arg_int (1 , ARG_SHORT, GetTimeLeft ());
165+ public bool: Native_IsRoundStarted (iPluginId, iArgc) {
166+ return g_iGameState > GameState_NewRound;
167+ }
172168
173- return PLUGIN_CONTINUE;
169+ public bool: Native_IsRoundEnd (iPluginId, iArgc) {
170+ return g_iGameState == GameState_RoundEnd;
174171}
175172
176- /* --------------------------------[ Methods ]--------------------------------*/
173+ public Native_HookCheckWinConditions (iPluginId, iArgc) {
174+ new szFunctionName[32 ];
175+ get_string (1 , szFunctionName, charsmax (szFunctionName));
177176
178- DispatchWin (iTeam, Float: fDelay) {
179- if (g_iGamestate == GameState_RoundEnd) {
177+ new hook [Hook];
178+ hook [Hook_PluginId] = iPluginId;
179+ hook [Hook_FunctionId] = get_func_id (szFunctionName, iPluginId);
180+
181+ ArrayPushArray (g_irgCheckWinConditionHooks, hook );
182+ }
183+
184+ DispatchWin (iTeam, Float: flDelay = - 1 .0 ) {
185+ if (g_iGameState == GameState_RoundEnd) {
180186 return ;
181187 }
182188
183189 if (iTeam < 1 || iTeam > 3 ) {
184190 return ;
185191 }
186192
187- new any: iWinstatus = WINSTATUS_DRAW;
193+ if (flDelay < 0 .0 ) {
194+ flDelay = g_pCvarRoundEndDelay ? get_pcvar_float (g_pCvarRoundEndDelay) : 5 .0 ;
195+ }
196+
197+ new WinStatus: iWinstatus = WINSTATUS_DRAW;
188198 if (iTeam == 1 ) {
189- iWinstatus = WINSTATUS_TERRORIST ;
199+ iWinstatus = WINSTATUS_TERRORISTS ;
190200 } else if (iTeam == 2 ) {
191- iWinstatus = WINSTATUS_CT ;
201+ iWinstatus = WINSTATUS_CTS ;
192202 }
193203
194- #if defined _reapi_included
195- new ScenarioEventEndRound: iEvent = ROUND_END_DRAW;
196- if (iTeam == 1 ) {
197- iEvent = ROUND_TERRORISTS_WIN;
198- } else if (iTeam == 2 ) {
199- iEvent = ROUND_CTS_WIN;
200- }
201-
202- rg_round_end (fDelay, iWinstatus, iEvent);
203- rg_update_teamscores (iTeam == 2 ? 1 : 0 , iTeam == 1 ? 1 : 0 );
204- #else
205- RoundEndForceControl (iWinstatus, fDelay);
206- #endif
207- }
204+ new ScenarioEventEndRound: iEvent = ROUND_END_DRAW;
205+ if (iTeam == 1 ) {
206+ iEvent = ROUND_TERRORISTS_WIN;
207+ } else if (iTeam == 2 ) {
208+ iEvent = ROUND_CTS_WIN;
209+ }
208210
209- GetTime () {
210- #if defined _reapi_included
211- return get_member_game (m_iRoundTime);
212- #else
213- return get_pgame_int (m_iRoundTime);
214- #endif
211+ rg_round_end (flDelay, iWinstatus, iEvent, _, _, true );
212+ rg_update_teamscores (iTeam == 2 ? 1 : 0 , iTeam == 1 ? 1 : 0 );
215213}
216214
217215SetTime (iTime) {
218- #if defined _reapi_included
219- set_member_game (m_iRoundTime, iTime);
220- set_member_game (m_fRoundStartTime, g_fRoundStartTime);
221- #else
222- set_pgame_int (m_iRoundTime, iTime);
223- set_pgame_float (m_fRoundCount, g_fRoundStartTime);
224- #endif
216+ new Float: flStartTime = get_member_game (m_fRoundStartTimeReal);
225217
226- UpdateRoundTime ();
227- }
218+ set_member_game (m_iRoundTime, iTime);
219+ set_member_game (m_iRoundTimeSecs, iTime);
220+ set_member_game (m_fRoundStartTime, flStartTime);
228221
229- GetTimeLeft () {
230- return floatround (g_fRoundStartTime + float (GetTime ()) - get_gametime ());
222+ UpdateTimer (0 , GetTimeLeft ());
231223}
232224
233- UpdateRoundTime () {
234- new iTimeLeft = GetTimeLeft ();
235-
236- RountTimeMessage (0 , iTimeLeft);
237- remove_task (TASKID_ROUNDTIME_EXPIRE);
238- set_task (float (iTimeLeft), " OnRoundTimeExpired" , TASKID_ROUNDTIME_EXPIRE);
225+ GetTimeLeft () {
226+ new Float: flStartTime = get_member_game (m_fRoundStartTimeReal);
227+ new iTime = get_member_game (m_iRoundTimeSecs);
228+ return floatround (flStartTime + float (iTime) - get_gametime ());
239229}
240230
241- stock RountTimeMessage (iClient, iTime) {
231+ UpdateTimer (iClient, iTime) {
242232 static iMsgId = 0 ;
243233 if (! iMsgId) {
244234 iMsgId = get_user_msgid (" RoundTime" );
0 commit comments