Back to Main Page


So this mod is called Car Services and unsurprisingly, it focuses on locations that are car related.

 

Car Services - The ideal DIS and WGS companion mod


After having completed DIS, I felt there was a need to make the locations you could select in the vehicle services, do more than just be locations. Why go to the AutoServices if they do nothing? So Car Services is an adaptation of a companion mod I showed on the WGS page. For anyone who watched that, you'll remember the yellow markers were used for food stands and blue markers were used for vehicle related locations. Well it's the blue marker functions that this mod addresses.

Using the Quadrant Search Manager (QSM), it requests the vehicle related locations from the WGS. As you get close to a valid location, it displays a marker. As you get closer still, it displays some more info about that location and when you finally get on top of the marker, it performs a function. They're mostly not complex functions, they're just functions you'd normally have to open a trainer for.

There are 4 car related location types.

1) Gas Stations
2) Hand Car Wash (plus two automated car wash locations)
3) Auto Services
4) Car Customisation

The two that this mod deals with, are the Car Wash and the Auto Services. I would have liked to have included the Gas Stations as well but I can't find much info on the best (and efficient) way to calculate fuel usage, given the parameters I have access to. The mod now deals with three location types instead of the original two. Car Customisation is already handled by the game, so there was no point in re-inventing that wheel.

"Well this mod can't do much then", I hear from the back row and you're right, it doesn't do much at all. When you drive through a car wash, your car is cleaned. When you drive to an Auto Services, your car is repaired... that's it, that's all the mod does (at the moment). But what those two simple functions do, is take away the need to open a trainer for the clean vehicle and fix vehicle options. Now they become part of your natural driving process, instead of what feels like a cheat option.

Note: I left this section ^^^ here because it was relevant at the time and is still a good idea of how the development process can change over time. You're always aware of how much or how little your mod does... you have to be to appreciate what its benefits are.

"But the game already has car washes", shouts that voice again. And once again, you're right... but, and it's a big but... not if you're using an addon ped, or even a different game ped. If you're not one of the 3 main characters, you have no money, so paid features are off-limits. The functionality of the hand car wash has also been used on the automated car wash locations, they just don't do the animating process.

So this first video shows the Quick Repair and Quick Wash functions

 

These quick functions are about as simple as they can get. Drive over the marker, get your car cleaned or repaired. The refuelling process is a little bit more complex but I don't want to record another video that just shows a bar getting bigger or smaller, hence the next section.

Update: Just to add a bit of info about the refuelling as it uses some techniques other people might find interesting. I wanted to use the Vehicle.FuelLevel for the fuel, because that seemed to make sense and the first *instant* refuelling system used exactly that. And everything was fine, as long as you stayed above 10% fuel. See, in the normal game, there is only one way you can lose fuel and that's by having a fuel tank so damaged, that the fuel leaks out. So Rockstar tied the fuel loss in with the car damage, so once you get to 10%, sparks and smoke start coming from the exhaust and the car becomes almost impossible to drive. Great when you're car is shot-up or banged up, not so great when you've simply run low on fuel.

So what was the alternative? I disconnected the fuel process from the car completely and made it a component of the DIS HackedCar class. I simply created a FuelSystem class which managed all the levels and passed that info to the DIS for storing in the persistance file. But here was the problem, the refuelling is done by car services, the fuel level is managed by DIS... how do they share that information? My first solution, with the instant refuelling in mind, was to simply add an event in Car Services, OnCarRefuelled(int handle), that the DIS could subscribe to. That way, when Car Services had finished refuelling, it fired the event and DIS set the fuel level to maximum. But as anyone with a car will tell you, if you drive into the garage with an almost empty 60 litre tank, you're not going to be doing any instant refuelling, it takes time and I wanted to simulate that... this method didn't suit that as it wasn't practical to constantly fire a stream of events with updated values.

So I thought of a solution but it required info I hadn't been able to find in a long time and that was Decorators. Mods had been released that used them but the info about how, never seemed to make itself public... or so I thought. So I had to resort to methods I really don't approve of but as my destructive phase had burned every bridge to information sources possible, I had no other real options. Just as I had got some code working, Tobsi Cred pointed me to Eddlm's pastebin page that had the proper Lock and Unlock code I so desperately needed... so if anyone is reading this who communicates with Eddlm, tell him *Thank You* for posting that info online. So taking that basic Lock/Unlock code, I wrote a full, yet compact extension class for decorators.

"Cool (and very long) story bro, what's the reason?" Well having got that class, I could now use the decorators as a communication transport between the two mods. DIS loads and registers 3 decorators, "DIS_Car" (bool) which marks the car as being under DIS control. "Refuelling" (bool) which marks the car as being in a refuelling phase and "FuelLevel" (float), which holds the fuel level. (when it needs to)

So DIS creates the HackedCar, the FuelSystem runs down the fuel and if you get too low, the car goes into an intermittent cutout phase, where the engine cuts to zero power (and disables the accelerator) for a short period (2 to 5 seconds)and then resumes for another variable period (10 to 30 seconds)... it seems to work well. So the car now goes into a Gas Station and when you press the Handbrake while your car is stopped, Car Services says "I'll just put a "Refuelling" decorator on this car. DIS says "Hey, it looks like this car is refuelling, let me put a "FuelLevel" decorator on, with the current fuel level. Car Services now says "Cool, now I know how much fuel I am starting with, I can begin the incremental refuelling process and continues to update the FuelLevel decorator with the updating value. While this is happening, DIS has stopped calculating the fuel usage and instead, the fuel system is increasing the fuel level and updating the fuel bar with the new values. Once Car Services has finished refuelling, it removes the Refuelling decorator, DIS recognises that and goes back to normal fuel usage mode.

It's the perfect solution for mods to share entity based data handling, without relying on events or exposing public static properties or methods. I integrated the fuel display into the game in a way more in keeping with how the game shows "levels" by placing a bar under the minimap. You can also see the level displayed in relevant units in the Vehicle Information screen in DIS.

Before I even begin to describe the second part... I'll post the second and way more interesting video.

 

For anyone who has seen the video, this part of the mod is an homage to the "Hands-On Car Wash" video on YouTube... watch it, it's pure brilliance. But after watching it a few times, for research purposes obviously, I thought "I want that in my game", so I tried to make it.

Little did I know, this was going to result in a complex combination of code techniques to get it working as well as I could. So let's start at the beginning, the key component to this premium service is the girls and for this there was only one choice, alex189's Momiji conversions and luckily, I had the bikini packs. So that gave me 4 models to use... perfect. I used Map Editor to place them and then used those locations to spawn them.

I wasn't sure what the animations were in that Hands-On video but after a bit of research and some confirmation from Tobsi Cred, they were identified as the animations for the maid. It turned out there was a short looping sequence called "base", four high animations "idle_a", "idle_c", "idle_d", **"idle_e" and one low animation "idle_b". So based on that I decided to split the car into three zones, front, middle and rear. The game very kindly provided a sponge prop, so that was a simple attach process to the hand.

Each one of those zones would be categorised as Low or high... but how? The answer, like with so many things, was raycasts. I took the centre position, one a fixed distance from the MaxDimensions.Y limit and one a fixed distance from the MinDimensions.Y limit. I then compared them with the ground height for those positions and that told me how high those three zones were. It's not 100% reliable, the rays could hit a window. Nothing has a guaranteed location in this game (especially with some vehicle modders) and that's a problem. You just have to make the best of it and hope it works most of the time.

For a vehicle that shape, the front would be Low and the other two would be High

The next task was to create the task sequences and this is where once again, I walked into another situation where the SHVDN devs decided "screw the users, we're just going to default some parameters that are essential to making things work properly", in particular, the Task.GoTo, which will always force the ped to turn to 0 when it finishes, because they defaulted the heading parameter to 0. I am tired of API devs that have an inability to wrap another API in a functional manner... expose essential and hide the non-essential... heading is more than essential.

So anyway, out went the SHVDN task sequences and I did the whole thing with natives. Barring one cock-up by me and an occasional one by the game where it decides to send one of the girls to the wrong place, all went fairly well. I had to create an intermediate point for the rear position, as the girl was sliding the final short distance... and it looked bad. I marked one of those animations **, that seemed an interesting animation as it was the maid standing back to check her work and then giving it a final clean. So I used that with a 1 in 10 chance of any girl doing a high animation, also doing that one as well.

This is a video of the early animation test video.

 

And here's one with the animations from outside

 

When a girl is spawned, she is assigned one of several random scenarios, just so she doesn't stand there looking bored. When she finishes her tasks, she returns to that location and again, chooses a random scenario. It just keeps things active and less predictable.

I had the animations, I had the heights of the car zones, now I had to add the cameras. This was a hugely problematic part of the mod that still doesn't work as I want it but I don't know how to make it do that. They way it now works, is each girl is tested for her angle from the car. Based on that result, she is assigned a 90 degree quadrant. So for example, if she is to the right of the car, she is covered from 45 degrees to 135 degrees. So I wrote a ClampedAround() function that is like the GTAV Around() function but you can specify a minimum and maximum angle as well as the radius. So in the case of the right side of the car, the clamp values are 10 to 170 degrees. But because the area around the car is restricted, the radius can't be too big, so there is always a danger that the camera could be right where the girl is at that time... so you get uber-extreme close-ups. And because I am pointing the camera at the spine dummy, the close-ups are potentially eye-poppers. :D

But for anyone who understands photography, you will know that DOF is acheived through a combination of distance and f-stop, so you need to create distance between you and the subject, then zoom back in (which usually reduces the f-stop) to create the DOF. If you don't have a lot of room, that's tricky. What I suppose I should have done is fired a ray backwards along the chosen angle to find the maximum distance I could have moved in that direction, then calculated the zoom based on that distance.

The final piece of the puzzle was refining the locations the girl's would walk to. The animations put the sponge a fixed distance away from the animation point, so the animation point had to be that distance away from the car. I started by using Model.Dimensions but that's a rough guide at best. Cars like the Gauntlet have mirrors that stick out, causing the dimensions to report as being bigger than they really were. So I had to refine those sizes... it was time for another test-mod and some more raycasts... and another encounter with people who just don't understand what they are doing with model dummies.

So my first thought was, take the model dimensions and at the centres of each side, cast a ray back to the model for a fixed distance, .25f in this case. However long that ray is before it hits something, we subtract that distance from the dimensions for that side.

Sounds easy right? Well it is, unless you have a model like this. (Opens in a new tab)

I mean this is supposed to be someone who knows what they're doing. This isn't a centre-of-gravity dummy, it's a centre-of-mass dummy and they are not the same thing. There is a reason every in-game car has this dummy in the right place and it's because the physics engine expects it to be there. When you apply a physics force at the COM, it creates a physics response. If that COM isn't where the actual COM is, as far as the mass collection is concerned, wrong things can happen. People need to stop treating the dummy objects as toys to play with and start using them as the game expects them to be used. This is what it should have produced.

So as a result, I had to consider the worst case scenario and write some adaptive code that would compensate for modders who can't do things properly... the endless story of a script-modder's life sadly... (and a contributing factor to why I stopped public modding) So using some jiggery-pokery using ground height and seat position, I managed to create a fake origin which I could test round. So because it is using some more raycasts, it uses a 5 frame delayed test. What I mean by that is each component of the test is done one-per-frame over 5 frames. It might have all worked in one-frame but I have several mods that all do something the minute you get into a vehicle, so this was load-sharing for performance reasons. This is the end result of that code, as you can see, much more useful to work with.

The large spheres are the calculated animation positions, the white box defines the model limits and the small spheres and lines are the raycast locations.

The end result is that I now have code that can give me a very close result to the actual body size of the model, which is perfect. So now I could place the animations based on accurate model sizes. Just to complicate things though, the high animation places you closer than a low animation, so I had to have secondary offsets to compensate based on which animation type was being used.

The screen effects code I already had in several mods... like the Screen Effects mod, so that was simple to add. Then it was just a case of screen fades and timescale adjustment and the job was done.

Like many things I create, it's far from perfect but it's also something that wasn't in the game in any form, so that's where the satisfaction comes from. What is more satisfying than anything for me though, is this is now a third part in a 3-mod collection that all work perfectly together. WGS provides locations, DIS provides access to certain location types at the push of a button and this mod turns those locations into functional aspects of the game. The other bonus was how little these mods affect performance. With both WGS and DIS GUIs visible, I drop around 6 - 8 fps at most. That's 2 fully animating GUI based menus that use what i consider to be a very small overhead, for what they provide access to.

You also get some nice and different screenshot potential, so I will end the page with probably my favourite so far. This just feels so retro or vintage, I really like this.

Update: This is probably my final update to this site and it's just a short one. I have just implemented a fuel system into the Driver Information System mod, which like everything else, is persistent across game sessions. That means I was able to add the missing car service functionality to this mod. I added a second location for each gas station to the WGS, just in case any NPC cars are blocking the one that is already there and if you drive over any of those locations, stop the car and hold the handbrake, the car will be refuelled by this mod.