Raised This Month: $ Target: $400
 0% 

[Solved] change_task()


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Prajch
Senior Member
Join Date: Dec 2007
Location: anger++
Old 09-29-2008 , 10:17   [Solved] change_task()
Reply With Quote #1

When you provide the time parameter to change_task(), does it replace the original delay, or is it added to the delay?

For example, if I made a task set to activate in 30 seconds, and after 15 seconds I execute change_task(id, 15.0), will the task activate 45 seconds after the original call, or will it activate immediately?

Last edited by Prajch; 10-01-2008 at 05:11.
Prajch is offline
anakin_cstrike
Veteran Member
Join Date: Nov 2007
Location: Romania
Old 09-29-2008 , 10:57   Re: change_task()
Reply With Quote #2

Quote:
change_task - Changes the time of a task.
change_task ( id = 0, Float:newTime=1.0, outside = 0 )
new time not adding time.
__________________

anakin_cstrike is offline
Prajch
Senior Member
Join Date: Dec 2007
Location: anger++
Old 09-29-2008 , 11:27   Re: change_task()
Reply With Quote #3

Quote:
Originally Posted by anakin_cstrike View Post
new time not adding time.
Yeah I looked at that... I was asking because "newTime" is still a bit ambiguous, possibly meaning relative to the current time.
Prajch is offline
MeRcyLeZZ
Veteran Member
Join Date: Dec 2007
Old 09-30-2008 , 23:27   Re: change_task()
Reply With Quote #4

Quote:
Originally Posted by Prajch
Yeah I looked at that... I was asking because "newTime" is still a bit ambiguous, possibly meaning relative to the current time.
Yes, it's supposed to replace the original time of the task. Basically a shortcut to doing: remove_task() and then set_task() again.

Though, I found out a special case where calling change_task() will actually set the task to "newTime * 2" for its first iteration. This only happens if your task has the loop flag ("b" or "a") set and you're calling the native inside the same task which you're changing the time for. OK, that sounded confusing even to me, so I'll show some code:
Code:
#include <amxmodx> #define TASK_TEST 1234 new counter public plugin_init() {     register_plugin("Tasks", "0.0", "Test")         register_clcmd("say task", "say_task") } public say_task(id) {     // We set a task to loop every 5 secs     set_task(5.0, "some_task", TASK_TEST+id, _, _, "b")         client_print(id, print_chat, "[TEST] Task started, looping every 5 seconds - current time: %.1f", get_gametime())         return PLUGIN_HANDLED; } public some_task(taskid) {     new id = taskid - TASK_TEST         counter++     if (counter == 3)     {           // Now we want to make it loop every 10 secs instead         change_task(TASK_TEST+id, 10.0)                 client_print(id, print_chat, "[TEST] Task changed to loop every 10 seconds - current time: %.1f", get_gametime())     }     else     {         client_print(id, print_chat, "[TEST] Task executed - current time: %.1f", get_gametime())     } }
Outputs:
Code:
[TEST] Task started, looping every 5 seconds - current time: 16.1
[TEST] Task executed - current time: 21.1
[TEST] Task executed - current time: 26.1
[TEST] Task changed to loop every 10 seconds - current time: 31.1
[TEST] Task executed - current time: 51.1 <--- hey, wtf!!
[TEST] Task executed - current time: 61.1
[TEST] Task executed - current time: 71.1
__________________
MeRcyLeZZ is offline
Styles
Veteran Member
Join Date: Jul 2004
Location: California
Old 10-01-2008 , 00:15   Re: change_task()
Reply With Quote #5

Submit a bug report
Styles is offline
Send a message via AIM to Styles
AntiBots
Veteran Member
Join Date: May 2008
Location: Brazil
Old 10-01-2008 , 00:21   Re: change_task()
Reply With Quote #6

Thank the tutotial MeRcyLeZZ
__________________
AntiBots is offline
Send a message via ICQ to AntiBots Send a message via MSN to AntiBots Send a message via Skype™ to AntiBots
Prajch
Senior Member
Join Date: Dec 2007
Location: anger++
Old 10-01-2008 , 04:01   Re: change_task()
Reply With Quote #7

Thanks man, luckily I almost never use the loop flags.

Last edited by Prajch; 10-01-2008 at 04:07.
Prajch is offline
MeRcyLeZZ
Veteran Member
Join Date: Dec 2007
Old 10-01-2008 , 23:31   Re: [Solved] change_task()
Reply With Quote #8

All right, found the reason.

When we use change_task() AMXX does the following:
* Sets the new task interval: m_fBase
* Updates the next execution time: m_fNextExecTime
Code:
int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
{
	CTaskDescriptor descriptor(iId, pAmx);
	TaskListIter iter = m_Tasks.find(descriptor);
	int i = 0;
	
	while (iter)
	{
		iter->changeBase(fNewBase);
		iter->resetNextExecTime(*m_pTmr_CurrentTime);
		++i;
		iter = m_Tasks.find(++iter, descriptor);
	}
	
	return i;
}

void CTaskMngr::CTask::changeBase(float fNewBase)
{
	m_fBase = fNewBase;
}

void CTaskMngr::CTask::resetNextExecTime(float fCurrentTime)
{
	m_fNextExecTime = fCurrentTime + m_fBase;
}
Looks all good, so where's the problem? Let's take a look at the code that executes the tasks...
Code:
void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft)
{
	bool execute = false;
	bool done = false;
	
	if (m_bAfterStart)
	{
		if (fCurrentTime - fTimeLeft + 1.0f >= m_fBase)
			execute = true;
	}
	else if (m_bBeforeEnd)
	{
		if (fTimeLimit != 0.0f && (fTimeLeft + fTimeLimit * 60.0f) - fCurrentTime - 1.0f <= m_fBase)
			execute = true;
	}
	else if (m_fNextExecTime <= fCurrentTime)
	{
		execute = true;
	}

	if (execute)
	{
		//only bother calling if we have something to call
		if (!(m_bLoop && !m_iRepeat))
		{
			m_bInExecute = true;
			if (m_iParamLen)	// call with parameters
			{
				cell arr = prepareCellArray(m_pParams, m_iParamLen);
				executeForwards(m_iFunc, arr, m_iId);
			} else {
				executeForwards(m_iFunc, m_iId);
			}
			m_bInExecute = false;
		}
	
		if (isFree())
			return;

		// set new exec time OR remove the task if needed
		if (m_bLoop)
		{
			if (m_iRepeat != -1 && --m_iRepeat <= 0)
				done = true;
		} else {
			done = true;
		}

		if (done)
		{
			clear();
		} else {
			m_fNextExecTime += m_fBase;
		}
	}
}
Note at the very end that if the task should continue looping, the next execution time is updated by doing: m_fNextExecTime += m_fBase;. But, if we called change_task() during task execution, m_fNextExecTime will already be set to the right value, and doing m_fNextExecTime += m_fBase; will effectively end up adding m_fBase*2.

Quick fix would be doing:
Code:
	if (done)
	{
		clear();
	} else {
		m_fNextExecTime = fCurrentTime + m_fBase;
	}
Though I'm not sure if that would bring any other issues...
__________________
MeRcyLeZZ is offline
MeRcyLeZZ
Veteran Member
Join Date: Dec 2007
Old 10-07-2008 , 12:38   Re: [Solved] change_task()
Reply With Quote #9

Ok, just submitted a bug report:
https://bugs.alliedmods.net/show_bug.cgi?id=3302
__________________
MeRcyLeZZ is offline
Prajch
Senior Member
Join Date: Dec 2007
Location: anger++
Old 10-07-2008 , 12:51   Re: [Solved] change_task()
Reply With Quote #10

Thanks.
Prajch is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 12:37.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode