Quantcast

Jump to content

» «
Photo

[C#] Timers?

12 replies to this topic
ISOFX
  • ISOFX

    Trick

  • Members
  • Joined: 31 May 2015
  • United-Kingdom

#1

Posted 16 February 2016 - 09:01 PM Edited by ISOFX, 16 February 2016 - 09:08 PM.

I've looked into how to slow down loops in C#, and i found timers and the Thread.Sleep method however i tried Thread.Sleep but its similar to the Wait function, it pauses the whole script. I also tried timers, and when i put a timer in and set an interval for it, nothing happens and it plays my code as normal. I am trying to slow down a looped particle effect without pausing my whole script.

 

My Timer Code:

System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();

public ParticleMechanic()
{
    t.Interval = 1000;
    t.Tick += new EventHandler(timer_Tick);
    Tick += timer_Tick;
}

private void timer_Tick(object sender, EventArgs e)
{
    if (PuffParticleActive) { PlayParticleOnEntity(thePuffCar, "scr_rcbarry2", "scr_clown_appears", 1.0f); }
}

I've tried several ways and i get no changes..

I want a one second gap when looping the particle effect. Also without pausing the whole script.

I get no errors when building,

Could someone help me out?

Thank You :)


Unknown_Modder
  • Unknown_Modder

    Staff at GTA5-Mods.com

  • Members
  • Joined: 07 May 2015
  • Germany

#2

Posted 16 February 2016 - 09:27 PM

In my scripts (C++), I use a very simple function:

(In a class "script"):

static unsigned long timer;

script::loops:

if (GET_GAME_TIMER() >= timer) { timer = GET_GAME_TIMER() + 1000; } // 1 second delay

Inside a looped function:

if (GET_GAME_TIMER() >= timer) 
{ 
    // code here
}
  • ins1de likes this

Jitnaught
  • Jitnaught

    ✰✰✰✰✰✰

  • Members
  • Joined: 24 Aug 2013
  • United-States

#3

Posted 16 February 2016 - 09:51 PM

The timer has to be started for it to run, but since you are already using the built-in ScriptHookV .NET timer (Tick += timer_Tick;) you don't need the extra timer.

To change the interval for the built-in timer call "Interval = 1000;".

If you code isn't called it is probably because of the code within the timer, not the timer itself.


ISOFX
  • ISOFX

    Trick

  • Members
  • Joined: 31 May 2015
  • United-Kingdom

#4

Posted 17 February 2016 - 07:54 AM Edited by ISOFX, 17 February 2016 - 08:02 AM.

Thanks, ill try what @Unknown_Modder posted in a bit, but, @LetsPlayOrDy i tried changing the interval for OnTick and i just get the same as when the interval isnt there.. i did "Interval = 1000;" and no change on the particle.. Also i started the timer when i enable the mod, so when the checkbox in the menu is pressed 3 functions will be called:

t.Start();
PuffParticleActive = true;
UI.Notify("Particle: ~g~ON");

//and when the bool is set to false,
t.Stop();
PuffParticleActive = false;
UI.Notify("Particle: ~r~OFF");


GeorgeZhang
  • GeorgeZhang

    I'm New

  • Members
  • Joined: 04 Jul 2015
  • None

#5

Posted 17 February 2016 - 09:34 AM Edited by GeorgeZhang, 17 February 2016 - 09:36 AM.

I used to utilize Game.GameTime , but it would require the native to be called per tick in order to retrieve the gametime. This is what I do now to create a slower loop:

int ActionCounter = 0;
int interval = 1500;//1500 is about 30-40 seconds

//the following inside 'OnTick'

if (ActionCounter > 500000) ActionCounter = 0;//this is optional

ActionCounter++;

if (ActionCounter % interval == 1299)
{
     //Actions
}

Hope it helps!!

  • ISOFX likes this

ISOFX
  • ISOFX

    Trick

  • Members
  • Joined: 31 May 2015
  • United-Kingdom

#6

Posted 17 February 2016 - 06:04 PM

I used to utilize Game.GameTime , but it would require the native to be called per tick in order to retrieve the gametime. This is what I do now to create a slower loop:

int ActionCounter = 0;
int interval = 1500;//1500 is about 30-40 seconds

//the following inside 'OnTick'

if (ActionCounter > 500000) ActionCounter = 0;//this is optional

ActionCounter++;

if (ActionCounter % interval == 1299)
{
     //Actions
}

Hope it helps!!

 

Thanks, will check when i get back. :)


InfamousSabre
  • InfamousSabre

    Harpocrates

  • Members
  • Joined: 03 Jan 2013

#7

Posted 17 February 2016 - 09:10 PM

I used to utilize Game.GameTime , but it would require the native to be called per tick in order to retrieve the gametime. This is what I do now to create a slower loop:

int ActionCounter = 0;
int interval = 1500;//1500 is about 30-40 seconds

//the following inside 'OnTick'

if (ActionCounter > 500000) ActionCounter = 0;//this is optional

ActionCounter++;

if (ActionCounter % interval == 1299)
{
     //Actions
}

Hope it helps!!

I was waiting for somebody to post this. Modulo is the easiest way to make a timer for anything.

  • GeorgeZhang likes this

jedijosh920
  • jedijosh920

    ⭐⭐⭐⭐⭐

  • Members
  • Joined: 01 Mar 2012
  • United-States

#8

Posted 18 February 2016 - 07:18 AM Edited by jedijosh920, 18 February 2016 - 07:22 AM.

I've been mainly using Game.GameTime and System.DateTime as timers, but I believe this is how the System.Timers timers work:

using System.Timers; 

 System.Timers.Timer timer = new System.Timers.Timer(5000); // create new instance of a timer
 timer.Start(); // start the timer
 timer.Elapsed += (Object source, System.Timers.ElapsedEventArgs e) =>
 {
    // do whatever once 5000 milliseconds has passed
    timer.Stop();
 }
  • ShadowCoderKing and ISOFX like this

CliffHanger
  • CliffHanger

    Default Avatars are Han Solos

  • Members
  • Joined: 14 Jan 2016
  • Canada

#9

Posted 19 February 2016 - 06:22 PM

Like everyone mentioned, I find adding a timevariable++; inside the OnTick loop is the easiest solution (although it does seem to get offset as the framerate changes), you can also work with tasks if you want, since thread.sleep will not lock your current thread when using those. The only problem is that OnTick is smart enough to stop when the game is paused. Thread.sleep won't.

 


milkjunk87
  • milkjunk87

    Square Civilian

  • Members
  • Joined: 16 Nov 2015
  • United-States

#10

Posted 20 February 2016 - 10:01 PM

negative tokens nsa :myou


ISOFX
  • ISOFX

    Trick

  • Members
  • Joined: 31 May 2015
  • United-Kingdom

#11

Posted 07 March 2016 - 07:49 PM

 

I've been mainly using Game.GameTime and System.DateTime as timers, but I believe this is how the System.Timers timers work:

using System.Timers; 

 System.Timers.Timer timer = new System.Timers.Timer(5000); // create new instance of a timer
 timer.Start(); // start the timer
 timer.Elapsed += (Object source, System.Timers.ElapsedEventArgs e) =>
 {
    // do whatever once 5000 milliseconds has passed
    timer.Stop();
 }

 

Thanks bro. Just wondering, how would you use Game.Time? :)


ShadowCoderKing
  • ShadowCoderKing

    GTA V Modder

  • Members
  • Joined: 14 Aug 2008
  • None

#12

Posted 12 August 2017 - 03:45 AM

 

I've been mainly using Game.GameTime and System.DateTime as timers, but I believe this is how the System.Timers timers work:

using System.Timers; 

 System.Timers.Timer timer = new System.Timers.Timer(5000); // create new instance of a timer
 timer.Start(); // start the timer
 timer.Elapsed += (Object source, System.Timers.ElapsedEventArgs e) =>
 {
    // do whatever once 5000 milliseconds has passed
    timer.Stop();
 }

great to learn from thanks man!

  • jedijosh920 likes this

LeeC2202
  • LeeC2202

    Snitch

  • Members
  • Joined: 24 Oct 2015
  • United-Kingdom

#13

Posted 18 August 2017 - 11:28 PM Edited by LeeC2202, 18 August 2017 - 11:30 PM.

One thing to be aware of when using System.Timer, is that it ignores any changes you make to Game.TimeScale.

 

So imagine your game is running as normal and you want something to happen every 5 seconds. You'd set the System.Timer interval to 5000 and that would be fine. But then in your mod, you have a function that triggers a slow-mo and that pulls the time down to 1/4 normal speed. Suddenly, 5 seconds is now 20 seconds in game time, but your timer is still going to trigger after 5 real-time seconds regardless.

 

For that reason, I always find that creating your own TimeScale-based timers are much more effective, if you are going to be making TimeScale modifications. Something like this...

    public class VariableTimer
    {
        public delegate void TimerExpired(object sender);
        public event TimerExpired OnTimerExpired;

        // Holds the countdown value
        int TimerMax;
        decimal TimerCounter;
        bool IsRunning;
        public bool AutoReset;

        // Constructor, takes the interval as an input
        public VariableTimer(int interval)
        {
            TimerCounter = interval;
            TimerMax = interval;
        }

        public void Update(float timescale)
        {
            if (!IsRunning) return;

            // Gets the value into 0 - 1000 range
            float timerElapse = Game.LastFrameTime * 1000f;

            // Reduce the timer by the elapsed time, modified by the game's timescale. Decimal seems to be more accurate
            // when subtracting values less than 1, float can be a bit erratic.
            TimerCounter -= (decimal)(timerElapse * timescale);

            if (TimerCounter <= 0)
            {
                OnTimerExpired?.Invoke(this);

                // Reset if the AutoReset property is true
                if (AutoReset)
                {
                    // I add TimerMax rather than set it to that to allow for any overlap into the next timer period
                    TimerCounter += TimerMax;
                }
                else
                {
                    Stop();
                }
            }
        }

        public void Stop()
        {
            IsRunning = false;
        }

        public void Start()
        {
            IsRunning = true;
        }

        public void Reset()
        {
            TimerCounter = TimerMax;
        }

        // For demo purposes only...
        public int Counter
        {
            get { return (int)TimerCounter; }
        }
    }

You can just declare it with

        VariableTimer MyTimer;

And then instance it with this

            MyTimer = new VariableTimer(1000);
            MyTimer.AutoReset = true;
            MyTimer.OnTimerExpired += MyTimer_OnTimerExpired;

And then finally, update it in onTick() like this

            MyTimer.Update(TimeScaleValue);

That will give you a timer that adapts to any timescale changes and will always ensure that the interval is game-time related. TimeScaleValue is something you have to keep track of yourself, because Game.TimeScale has no getter, it is a set only property.

 

I use a simpler version of this kind of thing in my OnFootCinematic Camera mod, to ensure the cameras always expire after the same amount of game time, no matter how the user adjusts the timescale. Someone might find this code useful though, so I thought it was worth posting.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users