SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 09/12/2015, 06:29 PM   #1
Correlli
Godfather
 
Correlli's Avatar
 
Join Date: May 2009
Location: Slovenia
Posts: 7,169
Reputation: 361
Default How to easily cover any San Andreas part with snow

General:

Some of you may remember my releases "Snow in Los Santos" and "Snow in Desert", and now I present you an easy way to cover any part of San Andreas map by simply inserting minimum X, Y and maximum X, Y coordinates or range arguments (and some additional arguments).



Required files:

You can download the script here, rather than copying every chunk of code from the tutorial.




Code:

You'll need function which will retexture your objects with snow texture.
Code:
stock AddSnowObject(modelid, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz, Float:d_stream = 200.0)
{
	new
			object = CreateDynamicObject(modelid, (x + 0.075), (y + 0.15), (z + 0.15), rx, ry, rz, .streamdistance = d_stream);
	for(new a = 0; a < 30; a++)
		SetDynamicObjectMaterial(object, a, 17944, "lngblok_lae2", "white64bumpy");
	return object;
}

Area creation:

Next, you'll need a function to check if position is in specified area.
Code:
stock IsPosInArea(Float:pos_x, Float:pos_y, Float:min_x, Float:min_y, Float:max_x, Float:max_y)
{
	if(pos_x >= min_x && pos_x <= max_x
	&& pos_y >= min_y && pos_y <= max_y)
		return true;
	return false;
}

Now, this function will create snow objects based on your area arguments (minimum X&Y and maximum X&Y), maximum Z and minimum model size of the snow objects. Make sure to read more information below this code.
Code:
stock CreateSnowInArea(Float:min_x, Float:min_y, Float:max_x, Float:max_y, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
	new
			count;
	for(new a = 0; a < SEARCH_DATA_SIZE; a++)
	{
		if(SearchData[a][SearchZ] > max_z)
			continue;
		if(!IsPosInArea(SearchData[a][SearchX], SearchData[a][SearchY], min_x, min_y, max_x, max_y))
			continue;
		if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
			continue;
		if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
			continue;
		AddSnowObject(
			SearchData[a][Search_Model],
			SearchData[a][SearchX],
			SearchData[a][SearchY],
			SearchData[a][SearchZ],
			SearchData[a][SearchRX],
			SearchData[a][SearchRY],
			SearchData[a][SearchRZ],
			(100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
		);
		count++;
	}
	printf("Total snow objects: %i", count);
	return true;
}
This function will loop through every San Andreas map object and create the snow copies based on your arguments (min_x, min_y, max_x, max_y, max_z, min_obj_model_size). I do not encourage you to use this as it is, so you should rather use printing function below.

This function will print your raw snow object codes, which you can later copy from your "server_log.txt" file.
Code:
stock PrintSnowForArea(Float:min_x, Float:min_y, Float:max_x, Float:max_y, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
	new
			count;
	for(new a = 0; a < SEARCH_DATA_SIZE; a++)
	{
		if(SearchData[a][SearchZ] > max_z)
			continue;
		if(!IsPosInArea(SearchData[a][SearchX], SearchData[a][SearchY], min_x, min_y, max_x, max_y))
			continue;
		if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
			continue;
		if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
			continue;
		printf("AddSnowObject(%i, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.1f);",
			SearchData[a][Search_Model],
			SearchData[a][SearchX],
			SearchData[a][SearchY],
			SearchData[a][SearchZ],
			SearchData[a][SearchRX],
			SearchData[a][SearchRY],
			SearchData[a][SearchRZ],
			(100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
		);
		count++;
	}
	printf("Total snow objects: %i", count);
	return true;
}
The streaming distance of every object if based on the model size of the object. The streaming distance is 100.0 units + the model size.

Range creation:

Next, you'll need a function to check if position is in specified range.
Code:
stock IsPosInRangeOfPoint2D(Float:pos_x, Float:pos_y, Float:range, Float:range_x, Float:range_y)
{
	pos_x -= range_x;
	pos_y -= range_y;
	return ((pos_x * pos_x) + (pos_y * pos_y)) < (range * range);
}

Now, this function will create snow objects based on your range arguments (X&Y center coordinates and range), maximum Z and minimum model size of the snow objects. Make sure to read more information below this code.
Code:
stock CreateSnowInRange(Float:pos_x, Float:pos_y, Float:range, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
	new
			count;
	for(new a = 0; a < SEARCH_DATA_SIZE; a++)
	{
		if(SearchData[a][SearchZ] > max_z)
			continue;
		if(!IsPosInRangeOfPoint2D(SearchData[a][SearchX], SearchData[a][SearchY], range, pos_x, pos_y))
			continue;
		if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
			continue;
		if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
			continue;
		AddSnowObject(
			SearchData[a][Search_Model],
			SearchData[a][SearchX],
			SearchData[a][SearchY],
			SearchData[a][SearchZ],
			SearchData[a][SearchRX],
			SearchData[a][SearchRY],
			SearchData[a][SearchRZ],
			(100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
		);
		count++;
	}
	printf("Total snow objects: %i", count);
	return true;
}
This function will loop through every San Andreas map object and create the snow copies based on your arguments (pos_x, pos_y, range, max_z, min_obj_model_size). I do not encourage you to use this as it is, so you should rather use printing function below.

This function will print your raw snow object codes, which you can later copy from your "server_log.txt" file.
Code:
stock PrintSnowForRange(Float:pos_x, Float:pos_y, Float:range, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
	new
			count;
	for(new a = 0; a < SEARCH_DATA_SIZE; a++)
	{
		if(SearchData[a][SearchZ] > max_z)
			continue;
		if(!IsPosInRangeOfPoint2D(SearchData[a][SearchX], SearchData[a][SearchY], range, pos_x, pos_y))
			continue;
		if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
			continue;
		if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
			continue;
		printf("AddSnowObject(%i, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.1f);",
			SearchData[a][Search_Model],
			SearchData[a][SearchX],
			SearchData[a][SearchY],
			SearchData[a][SearchZ],
			SearchData[a][SearchRX],
			SearchData[a][SearchRY],
			SearchData[a][SearchRZ],
			(100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
		);
		count++;
	}
	printf("Total snow objects: %i", count);
	return true;
}
The streaming distance of every object if based on the model size of the object. The streaming distance is 100.0 units + the model size.



Function arguments:

Area creation:
  • @Float: min_x - minimum X coordinate for your area
  • @Float: min_y - minimum Y coordinate for your area
  • @Float: max_x - maximum X coordinate for your area
  • @Float: max_y - maximum Y coordinate for your area
  • @Float: max_z - maximum Z coordinate (this limit is useful for stopping snow object creation on interior objects which are located at 1000.0 units approximately)
  • @Float: min_obj_model_size - minimum object radius of the collision sphere

Range creation:
  • @Float: pos_x - center X coordinate for your range
  • @Float: pos_y - center Y coordinate for your range
  • @Float: range - range
  • @Float: max_z - maximum Z coordinate (this limit is useful for stopping snow object creation on interior objects which are located at 1000.0 units approximately)
  • @Float: min_obj_model_size - minimum object radius of the collision sphere



How to get minimum and maximum X, Y area coordinates:

You can read more about the area checking here.

Area example (Los Santos area).


Coordinate 1 (minimum): A1(X: 50.0, Y: -3000.0)
Coordinate 2 (maximum): A2(X: 3000.0, Y: -750.0)

Range example (San Andreas map center at 0.0 with range of 1000.0).


Use the SA-MP command "/save" while in-game to gather coordinates.



Example:

Code:
public OnGameModeInit()
{
	PrintSnowForArea(50.0, -3000.0, 3000.0, -750.0, 300.0, 30.0);
	return true;
}
This code will print 1506 snow objects for Los Santos area (marked on area map above).

Code:
public OnGameModeInit()
{
	PrintSnowForRange(0.0, 0.0, 1000.0, 500.0, 30.0);
	return true;
}
This code will print 367 snow objects for 1000.0 range of 0.0 center (marked on range map above).

Once you compile your script and execute it, it will print raw snow object code. Close the server and open your "server_log.txt" file. Clear the unnecessary logs and time prints from object code (CTRL + H -> "Search for: [hh : mm : ss]" and leave "Replace with:" empty).

Put your printed snow objects in your script and don't forget to include the streamer plugin include file in the script and to run the plugin.

This is the result for LS area.


You can download the LS area raw snow objects here (1506 snow objects).




Removed objects support:

You can skip the snow creating on areas where you removed objects (with "RemoveBuildingForPlayer" function) for your maps.

This is the code you'll need. The checking code is already added to the Create/Print functions.
Code:
#define MAX_REMOVED_OBJECTS (500) // Value of maximum objects which can be removed. Set your own value.

Code:
enum ObjectRemoved
{
	Model,
	Float:Location[3]
}

Code:
new
		RemovedObject[MAX_REMOVED_OBJECTS][ObjectRemoved],
		g_SlotID = -1
;

Code:
stock IsPosInRangeOfPoint3D(Float:pos_x, Float:pos_y, Float:pos_z, Float:range, Float:range_x, Float:range_y, Float:range_z)
{
	pos_x -= range_x;
	pos_y -= range_y;
	pos_z -= range_z;
	return ((pos_x * pos_x) + (pos_y * pos_y) + (pos_z * pos_z)) < (range * range);
}

Code:
stock RemoveObject(modelid, Float:pos_x, Float:pos_y, Float:pos_z)
{
	g_SlotID++;
	if(g_SlotID == MAX_REMOVED_OBJECTS)
	{
		printf("Error: Limit for removed objects is reached. Open your script and change \"MAX_REMOVED_OBJECTS\" definition to a bigger value if you want to have more removed objects.");
		g_SlotID--;
		return -1;
	}
	if(g_SlotID == 1000)
	{
		printf("SA-MP limit: There appears to be a limit of around 1000 lines/objects. There is no workaround.");
		g_SlotID--;
		return -1;
	}
	RemovedObject[g_SlotID][Model]		=	modelid;
	RemovedObject[g_SlotID][Location][0]	=	  pos_x;
	RemovedObject[g_SlotID][Location][1]	=	  pos_y;
	RemovedObject[g_SlotID][Location][2]	=	  pos_z;
	return g_SlotID;
}

Code:
stock GetNumberOfRemovedObjects()
	return (g_SlotID + 1);

Code:
stock IsObjectRemoved(modelid, Float:pos_x, Float:pos_y, Float:pos_z)
{
	if(!GetNumberOfRemovedObjects())
		return false;
	for(new a = 0; a < GetNumberOfRemovedObjects(); a++)
	{
		if(modelid == RemovedObject[a][Model])
		{
			if(IsPosInRangeOfPoint3D(pos_x, pos_y, pos_z, 0.5, RemovedObject[a][Location][0], RemovedObject[a][Location][1], RemovedObject[a][Location][2]))
				return true;
		}
	}
	return false;
}

Example how to use the removing function.
Code:
public OnGameModeInit()
{
	/*
		@modelid - model of your object
		@Float: pos_x - X coordinate for your object
		@Float: pos_y - Y coordinate for your object
		@Float: pos_z - Z coordinate for your object
	*/
	RemoveObject(4024, 1479.8672, -1790.3984, 56.0234);
	RemoveObject(4044, 1481.1875, -1785.0703, 22.3828);
	RemoveObject(4045, 1479.3359, -1802.2891, 12.5469);
	RemoveObject(4046, 1479.5234, -1852.6406, 24.5156);
	RemoveObject(4047, 1531.6328, -1852.6406, 24.5156);
	return true;
}

Don't forget to remove all the objects when player connects to the server.
Code:
public OnPlayerConnect(playerid)
{
	if(GetNumberOfRemovedObjects())
	{
		for(new a = 0; a < GetNumberOfRemovedObjects(); a++)
		{
			RemoveBuildingForPlayer(
				playerid,
				RemovedObject[a][Model],
				RemovedObject[a][Location][0],
				RemovedObject[a][Location][1],
				RemovedObject[a][Location][2],
				0.5
			);
		}
	}
	return true;
}

Example with removed objects.




Problems:



Textures on some objects like trees, bushes and electrical wires will look a bit wierd, so you may want to exclude these objects from the creating/printing code. I don't think there's an easy way to do that. Only way I see it, is to open the Map Editor, search for every tree, bush, electrical wire and similar objects and exclude them.

Last edited by Correlli; 11/12/2015 at 08:21 PM.
Correlli is offline   Reply With Quote
Old 09/12/2015, 06:32 PM   #2
Joron
Huge Clucker
 
Joron's Avatar
 
Join Date: Nov 2015
Location: Behind My PC
Posts: 403
Reputation: 109
Default Re: How to easily cover any San Andreas part with snow

Nice
Joron is offline   Reply With Quote
Old 09/12/2015, 06:35 PM   #3
TwinkiDaBoss
Gangsta
 
Join Date: Jul 2014
Posts: 818
Reputation: 51
Default Re: How to easily cover any San Andreas part with snow

Nice one mate! +rep
TwinkiDaBoss is offline   Reply With Quote
Old 10/12/2015, 02:11 AM   #4
MD5
Huge Clucker
 
MD5's Avatar
 
Join Date: Nov 2014
Location: United Kingdom
Posts: 257
Reputation: 24
Default Re: How to easily cover any San Andreas part with snow

May use this in my upcoming X-Mas update, thanks.
__________________
MD5 is offline   Reply With Quote
Old 10/12/2015, 04:25 AM   #5
Gammix
High-roller
 
Gammix's Avatar
 
Join Date: Jan 2015
Location: Canada
Posts: 1,739
Reputation: 790
Default Re: How to easily cover any San Andreas part with snow

You can easily bypass trees, bushes and electrical wires when you use those functions (CreateSnowInArea and PrintSnowForArea). Here is how it should be done, before checking their ColSphere:

Code:
switch (SearchData[a][Search_Model])
{
    case tree_object: continue;
}
__________________
Gammix is offline   Reply With Quote
Old 10/12/2015, 07:55 AM   #6
Correlli
Godfather
 
Correlli's Avatar
 
Join Date: May 2009
Location: Slovenia
Posts: 7,169
Reputation: 361
Default Re: How to easily cover any San Andreas part with snow

Quote:
Originally Posted by Gammix View Post
You can easily bypass trees, bushes and electrical wires when you use those functions (CreateSnowInArea and PrintSnowForArea). Here is how it should be done, before checking their ColSphere:

Code:
switch (SearchData[a][Search_Model])
{
    case tree_object: continue;
}
Indeed, but you still need model IDs.
Correlli is offline   Reply With Quote
Old 11/12/2015, 07:34 PM   #7
Correlli
Godfather
 
Correlli's Avatar
 
Join Date: May 2009
Location: Slovenia
Posts: 7,169
Reputation: 361
Default Re: How to easily cover any San Andreas part with snow

Tutorial updated.
  • The script/tutorial now supports skipping creation of removed objects,
  • range functions are added (CreateSnowInRange, PrintSnowForRange).

Example with removed objects.


Range example (San Andreas map center at 0.0 with range of 1000.0).


You can download the script here, rather than copying every chunk of code from the tutorial.
Correlli is offline   Reply With Quote
Old 11/12/2015, 08:28 PM   #8
Crayder
High-roller
 
Crayder's Avatar
 
Join Date: Sep 2013
Location: Flames of Hell
Posts: 3,865
Reputation: 588
Default Re: How to easily cover any San Andreas part with snow

Quote:
Model sizes include by Y_Less.
Well... you should be using the model sizes include that I put up. It's a LOT more accurate than the old one. And to go with it, check out the db-mode branch on the repo.
Quote:
All GTA SA Object Array include by Pottus
I also create a db-mode for this, it's packaged into Texture Studio but I might as well release it. It obviously decreases compile time and it increases operation speed (I kinda found this a bit surprising).

Not that speed or accuracy is extremely important here, but keeping up to date is always great.
__________________
Those who deserve reputation, do not need to beg for it.
Also, don't expect the help you need when offering reputation, you'll just be attracting Rep Hunters.
Join SA-MP Discord!
Crayder is offline   Reply With Quote
Old 11/12/2015, 08:50 PM   #9
Correlli
Godfather
 
Correlli's Avatar
 
Join Date: May 2009
Location: Slovenia
Posts: 7,169
Reputation: 361
Default Re: How to easily cover any San Andreas part with snow

Will sure check it out, thanks.
Correlli is offline   Reply With Quote
Old 12/11/2016, 01:19 PM   #10
Ben666
Little Clucker
 
Join Date: May 2015
Posts: 39
Reputation: 32
Default Re: How to easily cover any San Andreas part with snow

Hi, i'm trying to make San Fierro full of snow, with your script, but i have an issue. SF is really hilly, have different levels, in every streets. When i want to retexture only the grounds, many walls, buildings turns to white. Have you any advice?
Ben666 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

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


Similar Threads
Thread Thread Starter Forum Replies Last Post
[Include] >>> San Andreas Telecom - Create a phone system easily <<< ACI Includes 12 15/02/2014 05:09 PM
Snow andreas doesn't want to uninstall Andy_McKinley Everything and Nothing 3 02/10/2010 02:55 PM
San Andreas Multiplayer - the movie Part 1 Cedimedi Screenshots and Videos 13 18/01/2010 02:39 PM
NeoN - Fun Andreas (new part!) :D Ytong Screenshots and Videos 24 25/05/2009 08:36 AM
H3IST | Part One | A GTA San Andreas Machinima Aji Screenshots and Videos 6 17/04/2009 08:57 PM


All times are GMT. The time now is 11:11 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.