HighVoltage_ Posted August 29, 2017 Share Posted August 29, 2017 (edited) Hi, I'm working on a mod that allows the player to place a marker, the first time he drives over it a stopwatch onscreen will begin counting up, the next time, it stops. The idea is to create a tool for timing laps around community race tracks. I'm not new to programming or VS but I'm new to c# and gta modding (couldn't find this mod anywhere so I decided to have a crack at it myself and try and learn something new in the process). A loop that counts up is simple enough, but how does the game display information to the screen for the player to view, and how accurate can the timer be before the game starts to take a performance hit? (how often can the loop that is counting up refresh basically) All help would be greatly appreciated Also I've already done some basic research, watched a few tutorials etc and got the idea of how scripthook.net handles key press events, how to spawn entities, ticks and intervals etc already, looking about now how GTA displays text to the screen, but I thought I'd post here anyway just to see peoples opinions and if they have any advice for me etc etc Edited August 29, 2017 by HighVoltage_ Link to comment Share on other sites More sharing options...
Guest Posted August 29, 2017 Share Posted August 29, 2017 (edited) Easiest way to do the timer is to use a TimeSpan(). TimeSpan laptimer; When you hit the first marker, set the TimeSpan to zero. laptimer = TimeSpan.Zero; Then every frame in onTick(), get Game.LastFrameTime and multiply that by 1000, which will give you the number of milliseconds that have passed. Add that to your TimeSpan as part of a new TimeSpan. The milliseconds property is a Get only property, which is why you have to do this. int timerelapsed = (int)(Game.LastFrameTime * 1000f);laptimer += new TimeSpan(0, 0, 0, 0, timerelapsed); You can display the information in a UIText element. Put this in your declarations section. UIText TimerDisplay = new UIText("", new Point(0, 0), 1f); Then in your onTick(); TimerDisplay.Caption = string.Format("Time: {0:00}:{1:00}:{2:00}.{3:000}", laptimer.Hours, laptimer.Minutes, laptimer.Seconds, laptimer.Milliseconds);TimerDisplay.Draw(); That's the basics of it. Edited August 29, 2017 by Guest Link to comment Share on other sites More sharing options...
HighVoltage_ Posted August 29, 2017 Author Share Posted August 29, 2017 (edited) Easiest way to do the timer is to use a TimeSpan(). TimeSpan laptimer; When you hit the first marker, set the TimeSpan to zero. laptimer = TimeSpan.Zero; Then every frame in onTick(), get Game.LastFrameTime and multiply that by 1000, which will give you the number of milliseconds that have passed. Add that to your TimeSpan as part of a new TimeSpan. The milliseconds property is a Get only property, which is why you have to do this. int timerelapsed = (int)(Game.LastFrameTime * 1000f);laptimer += new TimeSpan(0, 0, 0, 0, timerelapsed); You can display the information in a UIText element. Put this in your declarations section. UIText TimerDisplay = new UIText("", new Point(0, 0), 1f); Then in your onTick(); TimerDisplay.Caption = string.Format("Time: {0:00}:{1:00}:{2:00}.{3:000}", laptimer.Hours, laptimer.Minutes, laptimer.Seconds, laptimer.Milliseconds);TimerDisplay.Draw(); That's the basics of it. Thanks for the help with the timer, that's really a big help as I was originally going to use the system timer, but timespan seems a lot more reliable. Do you know anything about markers? I tried to write a quick script to place a marker on key release and came up with this: public class LapTimer : Script{ private GTA.Math.Vector3 f0, f1; public LapTimer() { //Tick += OnTick; KeyDown += OnKeyDown; KeyUp += OnKeyUp; f0 = new GTA.Math.Vector3(0f, 0f, 0f); f1 = new GTA.Math.Vector3(1f, 1f, 1f); Interval = 1; } void OnKeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.H) { Ped player = Game.Player.Character; GTA.Math.Vector3 pos = player.Position + (player.ForwardVector * 5); GTA.Math.Vector3 posL = pos; posL.Z = player.Position.Z - player.HeightAboveGround; drawMarker(posL); } } void drawMarker(Vector3 posL) { Tick += OnTick; void OnTick(object sender, EventArgs e) { GTA.World.DrawMarker(MarkerType.VerticalCylinder, posL, f0, f0, f1, Color.Red); } } and it works, but I have absolutely no idea how to check for player interactions. Could you point me in the right direction for this? Thanks Edited August 29, 2017 by HighVoltage_ Link to comment Share on other sites More sharing options...
Guest Posted August 29, 2017 Share Posted August 29, 2017 When you say interaction, do you mean like this? https://youtu.be/wuekl9ad-yo In the most basic sense, you're simply testing for the player being within a certain distance of the marker location. I use a GetDistance() function but you can also do it with the Ped/Vehicle.IsInRangeOf() function. As an example... this will register as true if you are within 10f units of the MarkerLocation Vector3 MarkerLocation = new Vector3(0, 0, 0);if (Game.Player.Character.IsInRangeOf(MarkerLocation, 10f)){ // Do Interaction code here...} Link to comment Share on other sites More sharing options...
HighVoltage_ Posted August 29, 2017 Author Share Posted August 29, 2017 (edited) When you say interaction, do you mean like this? https://youtu.be/wuekl9ad-yo In the most basic sense, you're simply testing for the player being within a certain distance of the marker location. I use a GetDistance() function but you can also do it with the Ped/Vehicle.IsInRangeOf() function. As an example... this will register as true if you are within 10f units of the MarkerLocation Vector3 MarkerLocation = new Vector3(0, 0, 0);if (Game.Player.Character.IsInRangeOf(MarkerLocation, 10f)){ // Do Interaction code here...} That's exactly what I mean, thanks very much. I've done a bit of fiddling about and my script is almost complete, but for some reason, my code is drawing multiple timers over each other and I can't figure out why. I get that the timer is being draw while inside onTick(), so do I have to remove the old timer before I start drawing the new one? Here's a picture of what's happening: https://gyazo.com/44466e3ba8554775b77d8aa4326063ca Here's my code: public class LapTimer : Script{ UIText TimerDisplay = new UIText("", new Point(0, 0), 1f); private GTA.Math.Vector3 f0, f1; bool markerPlaced = false; public LapTimer() { //Tick += OnTick; KeyDown += OnKeyDown; KeyUp += OnKeyUp; f0 = new GTA.Math.Vector3(0f, 0f, 0f); f1 = new GTA.Math.Vector3(1f, 1f, 1f); Interval = 1; } void OnKeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.H) { Ped player = Game.Player.Character; GTA.Math.Vector3 pos = player.Position + (player.ForwardVector * 15); GTA.Math.Vector3 posL = pos; posL.Z = player.Position.Z - player.HeightAboveGround; drawMarker(posL); } } void drawMarker(Vector3 posL) { bool markerPlaced = false; if (markerPlaced == false) { Tick += OnTick; void OnTick(object sender, EventArgs e) { GTA.World.DrawMarker(MarkerType.VerticalCylinder, posL, f0, f0, (f1 * 5), Color.FromArgb(50, Color.Red)); markerPlaced = true; raceInitialise(posL); } } } void raceInitialise(Vector3 posL) { bool raceStarted = false; if (Game.Player.Character.IsInRangeOf(posL, 1f)) { if(raceStarted == false) { raceStarted = true; TimeSpan laptimer; laptimer = TimeSpan.Zero; Tick += OnTick; void OnTick(object sender, EventArgs e) { int timerelapsed = (int)(Game.LastFrameTime * 1000f); laptimer += new TimeSpan(0, 0, 0, 0, timerelapsed); TimerDisplay.Caption = string.Format("Time: {0:00}:{1:00}:{2:00}.{3:000}", laptimer.Hours, laptimer.Minutes, laptimer.Seconds, laptimer.Milliseconds); TimerDisplay.Draw(); } } } } void OnKeyDown(object sender, KeyEventArgs e) { } } Thanks for everything so far, this is my first time using C sharp and scripting in gta and you've helped me loads, I'm not knew to programming but I'm struggling to find any documentation on scripthookv.net so I really do not know what's available to me Edited August 29, 2017 by HighVoltage_ Link to comment Share on other sites More sharing options...
Guest Posted August 30, 2017 Share Posted August 30, 2017 (edited) You have too many onTick() functions in there, there should be only one and it shouldn't be inside another function. onTick() is an event handler and as such, it should only be assigned a single handler, you have two. The correct place for setting the event handler, is actually the one you have commented out. onTick() the function, should be on the same level in your code as OnKeyDown as that is also an event. So the first thing you really need to do, is get your programme structure right, then go from there, otherwise you're just going to be hitting problems before you've even got started. I don't know whether linking to other sites is allowed on here, because the site I used to be on, GTA5-Mods, had some good tutorials for C# scripting that would probably help you a lot. It might be worth checking them out. Edited August 30, 2017 by Guest Link to comment Share on other sites More sharing options...
HighVoltage_ Posted August 30, 2017 Author Share Posted August 30, 2017 (edited) You have too many onTick() functions in there, there should be only one and it shouldn't be inside another function. onTick() is an event handler and as such, it should only be assigned a single handler, you have two. The correct place for setting the event handler, is actually the one you have commented out. onTick() the function, should be on the same level in your code as OnKeyDown as that is also an event. So the first thing you really need to do, is get your programme structure right, then go from there, otherwise you're just going to be hitting problems before you've even got started. I don't know whether linking to other sites is allowed on here, because the site I used to be on, GTA5-Mods, had some good tutorials for C# scripting that would probably help you a lot. It might be worth checking them out. Had a feeling that using more than one onTick() was extremely bad practice, it just seemed like a cheat way to get something working. And I've been on gta5-mods but there seems to be a lack in response to help threads to be honest, they do have some good tutorials on there though which got me started on the markers Edited August 30, 2017 by HighVoltage_ Link to comment Share on other sites More sharing options...
Guest Posted August 30, 2017 Share Posted August 30, 2017 You have too many onTick() functions in there, there should be only one and it shouldn't be inside another function. onTick() is an event handler and as such, it should only be assigned a single handler, you have two. The correct place for setting the event handler, is actually the one you have commented out. onTick() the function, should be on the same level in your code as OnKeyDown as that is also an event. So the first thing you really need to do, is get your programme structure right, then go from there, otherwise you're just going to be hitting problems before you've even got started. I don't know whether linking to other sites is allowed on here, because the site I used to be on, GTA5-Mods, had some good tutorials for C# scripting that would probably help you a lot. It might be worth checking them out. Had a feeling that using more than one onTick() was extremely bad practice, it just seemed like a cheat way to get something working. And I've been on gta5-mods but there seems to be a lack in response to help threads to be honest, they do have some good tutorials on there though which got me started on the markers When I used to be on there, I always used to answer the help threads if I could... I was spending up to 14 hours a day on there some days. Once the new regime kicked in and they started running the site into the ground, I packed up and left. I'm not on here that often, don't really like the vibe on here but if I see something I can help with, I will try to do so. Link to comment Share on other sites More sharing options...
HighVoltage_ Posted August 30, 2017 Author Share Posted August 30, 2017 You have too many onTick() functions in there, there should be only one and it shouldn't be inside another function. onTick() is an event handler and as such, it should only be assigned a single handler, you have two. The correct place for setting the event handler, is actually the one you have commented out. onTick() the function, should be on the same level in your code as OnKeyDown as that is also an event. So the first thing you really need to do, is get your programme structure right, then go from there, otherwise you're just going to be hitting problems before you've even got started. I don't know whether linking to other sites is allowed on here, because the site I used to be on, GTA5-Mods, had some good tutorials for C# scripting that would probably help you a lot. It might be worth checking them out. Think I'm getting the hang of the whole onTick() concept now, I've come up with this: using GTA;using System;using System.Windows.Forms;using GTA.Native;using GTA.Math;using System.Drawing;public class LapTimer : Script{ UIText TimerDisplay = new UIText("", new Point(0, 0), 1f); private GTA.Math.Vector3 f0, f1; GTA.Math.Vector3 pos; GTA.Math.Vector3 posL; bool keyActivate = false; bool raceStarted = false; bool markerPlaced = false; TimeSpan laptimer; public LapTimer() { Tick += OnTick; KeyDown += OnKeyDown; KeyUp += OnKeyUp; f0 = new GTA.Math.Vector3(0f, 0f, 0f); f1 = new GTA.Math.Vector3(1f, 1f, 1f); Interval = 1; } void OnTick(object sender, EventArgs e) { if (keyActivate == true) { if (markerPlaced == false) { markerPlaced = true; keyActivate = false; Ped player = Game.Player.Character; pos = player.Position + (player.ForwardVector * 15); posL = pos; } keyActivate = false; } if (markerPlaced == true) { GTA.World.DrawMarker(MarkerType.VerticalCylinder, posL, f0, f0, (f1 * 5), Color.FromArgb(50, Color.Red)); } if (Game.Player.Character.IsInRangeOf(posL, 5f)) { if (raceStarted == false) { laptimer = TimeSpan.Zero; raceStarted = true; } } if (raceStarted == true) { int timerelapsed = (int)(Game.LastFrameTime * 1000f); laptimer += new TimeSpan(0, 0, 0, 0, timerelapsed); TimerDisplay.Caption = string.Format("Time: {0:00}:{1:00}.{2:000}", laptimer.Minutes, laptimer.Seconds, laptimer.Milliseconds); TimerDisplay.Draw(); } } void OnKeyUp(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.H) { keyActivate = true; } } void drawMarker(Vector3 posL) { bool markerPlaced = false; if (markerPlaced == false) { } } void OnKeyDown(object sender, KeyEventArgs e) { } And it works, A marker is placed and as the player runs into it a timer appears and starts increment. Now all I have to do is set a condition so if the player comes into a certain distance of the marker after a certain time has elasped (so it doesn't instantly stop), the timer stops. Thanks so much man Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now