Script a spiral

Post your scripting questions / solutions here

Moderator: Moderators

Post Reply
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Script a spiral

Post by $oldier Of Ra »

Jv, this thread is actually directed to you as aerodynamics- and maths-wiz, I think you're the perfect person to help me.

I'd like to decorate a christmas-tree (it's the time of year!) but for that I would need to individually place all lights at the right place on the tree. But the script needs to be dynamic, so I give the values, the script does the rest.

I know it's something with the cosine and the sine but I suck at maths to much too know what. I feel that these days they don't teach you the full use of certain math functions or methods. These things can be very useful!

I can get the measurements of the tree (and input/calc those because it's needs to be dynamic)
Top height: 440.00
Base height: 140
Base width: 120
Top width: 20
Origin: local.tree.origin or ( 228 -341 0 )

I can calculate those measurements if the scale of the tree changes no problem. But how do you make 1 / 2 spirals (would be a sine one and a cosine one).

I have your math functions script, I think the latest and complete version (5 kb).
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Post by jv_map »

Well I'm sure other people here would be capable of helping too, but let me have a shot at it. Elgan once asked me much the same through e-mail, but unfortunately I can't find it anymore.

Okay so let's see. First read this and this (these articles go much deeper than you'll need, just make sure you grasp the basics).

You could take a variety of approaches for your lights script. The maths are non-trivial. One option would be this: let 's' be a running coordinate from 0 to 1, let s=0 correspond to the top of your tree and s=1 to the bottom. Your lights will be equally distributed along the path of s.

As s increases, you rotate around your tree, while at the same time increasing the distance from the stem, and going down. Thus you can parametrize your path, in cylindrical coordinates, using the single path parameter s:
r = c1 * s
theta = 2 * pi * c2 * s
z = -c3 * s

Optionally, you could add a constant to these expression to fine-tune your tree.

The next step is to determine the constants c1, c2 and c3. c1 says how far you go away from the stem. c2 says how fast you rotate around the stem. c3 indicates how fast you descent down the stem.

Since s=1 corresponds to the bottom of the tree, you find:
c1 = radius of the tree at its base
c2 = number of winds (choose freely)
c3 = the height of your tree.

r and theta are polar coordinates, you convert them to x and y as described in the article.

Finally, add the (x,y,z) world coordinates of the top of your tree to the (x,y,z) coordinates computed previously, so that your light spiral coincides with the tree.

That should get you started I'd say :). Good luck 8-)
Image
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Post by $oldier Of Ra »

Yes I've seen elgan's script where he used this, but I didn't understand.
I tried using elgan's script but it just made 1 circle around the base, wanted to rise for the second but stopped for some reason.

EDIT: Okay, thx to you jv and by looking at Elgan's script, I managed to spawn a spiral around the tree. It looks damn nice :D

However I ran into some trouble when I increased "the degrees between each corona". My game crashed with this: "no free edicts...."
I'm guessing it's because I'm using the same local. variable for each corona in 1 thread too much. I've been searching this forum and it's because I spawned too much entities...that's very odd because I spawned only 60 corona's, some other maps have more than 200 entities script-spawned and run fine, this doesn't make sense :?

Here's the script:

Code: Select all

xmas_tree:

	// spawn
	local.tree = spawn script_model 
	local.tree model "static/tree_winter_midpine.tik"
	local.tree.origin = ( 232 -340 0 )
	local.tree notsolid
	local.tree scale 1

	//////////////////////////////////////
	// Measurements and dimensions 	//
	//////////////////////////////////////
	
	// Defaults
	local.default_height = 440.00
	local.default_basewidth = 120
	local.default_topwidth = 20
	local.default_baseheight = 140

	// If scale is adjusted, redefine measurements...
	if (local.tree.scale != 1)
	{
		// get new scale application value
		local.scale_app = ( 1.0 / local.tree.scale )

		// get new measurements
		local.tree.height = ( local.default_height / local.scale_app )
		local.tree.baseheight = ( local.default_baseheight / local.scale_app )
		local.tree.topwidth = ( local.default_topwidth / local.scale_app )
		local.tree.basewidth = ( local.default_basewidth / local.scale_app )
	}
	else
	{
		local.tree.height = local.default_height
		local.tree.baseheight = local.default_baseheight
		local.tree.topwidth = local.default_topwidth
		local.tree.basewidth = local.default_basewidth
	}

	//apply new origins
	local.tree.top_origin = ( local.tree.origin[0] local.tree.origin[1] local.tree.height )
	local.tree.base_origin = ( local.tree.origin[0] local.tree.origin[1] local.tree.baseheight )

	//////////////////////////////////////
	// Other values 				//
	//////////////////////////////////////

	//get PI:
	exec global/maths.scr

	local.loops = 8
	local.degrees_away = 25
	local.height = local.tree.baseheight
	local.gain_height = ( local.tree.height - local.height ) / local.loops

	////////////////////////////
	// Cheers, Elgan and jv!!
	// ty for this !
	////////////////////////////
	local.number_of_lights = ( 360 / local.degrees_away )
	local.gain_height = (local.gain_height / local.number_of_lights)

	local.loops = 360 * local.loops
	local.baseheight = local.height

	if(local.clockwise == 1)
	{
		local.start = 0
		local.end = local.loops
		local.add = local.degrees_away
	}
	else
	{
		local.start = local.loops
		local.end = 0
		local.add = ( 0 - local.degrees_away )
	}

	for (local.i = local.start; local.i != local.end; local.i += local.add)
	{
		// from elg's script	
		local.radius = waitthread get_diameter local.tree local.height
		local.location = local.tree.origin 
		local.radian = ((local.i * level.PI) / 180 )

		local.cos = ( waitthread global/maths.scr::cos local.radian * local.radius )
		local.sin = ( waitthread global/maths.scr::sin local.radian * local.radius )

		local.location = local.location + ( local.sin local.cos local.height )

		local.height += local.gain_height
		
		local.n = randomint 99999
		local.xmas_light[local.n] = spawn script_model model "static/corona_reg.tik" 
		local.xmas_light[local.n].origin = local.location
	}
end

///////////////////////////////////////////////
// Thx to elg... Don't know what he's doing
// I think (diameter / 2) was enough...
//
get_diameter local.tree local.height:

	local.result = (local.tree.basewidth -  (local.tree.basewidth - local.tree.topwidth) / (local.tree.height - local.tree.baseheight) * (local.height - local.tree.baseheight) )

end local.result
The script is based on elgan's script when he asked you some help, it was for something like this. It's working perfectly but this little devil crashes the game:

Code: Select all

local.degrees_away = 25
When this is lower (say 20) it works but around 25, the game crashes with the no free edicts error.
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Post by $oldier Of Ra »

Okay... Uhm I think the for statement is causing the trouble; I just found out when using (20 works and looks good) local.degrees_away = 25, it spawns 950 coronas. When using 20 it only does 144 which is already A LOT. In game it doesn't look like 144, it looks more like 50 coronas...

I'm trying to find a way so that for statement does the complete spiral with enough coronas and nothing more.
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Post by jv_map »

Quote:

for (local.i = local.start; local.i != local.end; local.i += local.add)

Why not:

for (local.i = local.start; local.i <= local.end; local.i += local.add)

I haven't looked at your code in too much detail yet, but chances are i is never going to match end exactly, depending on your start value and add value.
Image
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Post by $oldier Of Ra »

My thoughts exactly :)
If clockwise it should be <=, if counter-clockwise >=.

It works perfectly like this. But I've made and put in an extra security so that the spawning is stopped if an unknowing user sets the local.degrees_away too low and the local.loops (times it winds around the tree) too high.

I calculate how many lights it will produce and if too much, I stop the script before it starts spawning.

Code: Select all

// NOTE: local.loops has been multiplied by 360 earlier! 
// The actual method for counting the lights is: ( 360 * loops ) / degrees_away
// + 1 because my calculator and mohaa don't agree
local.amount_lights = ( local.loops / local.degrees_away ) + 1
local.amount_lights = int(local.amount_lights)
if ( local.amount_lights >= 115 )
{
println ("[Christmas::Tree]: Dangerous amount of lights (= " + local.amount_lights + ") that will be spawned!!")
println "[Christmas::Tree]: Free Edict cap could be breached; terminating sequence."
end
}
Secondary measure would be restricting the amount of trees a player can spawn like this in map. Each time a tree gets spawned, level.total_trees gets + 1.

Code: Select all

if (level.total_trees == 6)
{
println "[Christmas::Tree]: You can't spawn more than 6 trees; to prevent crashes."
end
}
I derived most parts from that script (I marked it with "cheers Elgan and Jv") from Elgan's script (because I'm not so good at this :p) and Elgan used that for statement which is odd...
So I'll have to make 2 almost identical threads for spawning the lights, 1 for clockwise and the other for counter-clockwise.
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Post by jv_map »

If you want the spiral the other way around, pick a negative number for c2 :). Don't have to change anything else.
Image
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Post by $oldier Of Ra »

LOL of course :D but I think I did it the other way around if I use -local.i I get clockwise and if I use local.i I get counter-clockwise :P (bold section below)
//....

//////////////////////////////////////
// Other values //
//////////////////////////////////////

//get PI:
exec global/maths.scr

local.loops = 6
local.degrees_away = 25
local.height = local.tree.baseheight
local.gain_height = ( local.tree.height - local.height ) / local.loops

////////////////////////////
// Cheers, Elgan and jv!!
// ty for this script
////////////////////////////
local.number_of_lights = ( 360 / local.degrees_away )
local.gain_height = (local.gain_height / local.number_of_lights)

local.loops = 360 * local.loops
local.baseheight = local.height
local.clockwise = 1

local.start = 0
local.end = local.loops
local.add = local.degrees_away


local.amount_lights = ( local.loops / local.degrees_away ) + 1
local.amount_lights = int(local.amount_lights)
if ( local.amount_lights >= 115 )
{
println ("[Christmas::Tree]: Dangerous amount of lights (= " + local.amount_lights + ") that will be spawned!!")
println "[Christmas::Tree]: Free Edict cap could be breached; terminating sequence."
end
}

for (local.i = local.start; local.i <= local.end; local.i += local.add)
{
// from elg's script
local.radius = waitthread get_diameter local.tree local.height
local.location = local.tree.origin
if(local.clockwise == 1)
{
local.radian = (( -local.i * level.PI) / 180 )
}
else
{
local.radian = (( local.i * level.PI) / 180 )
}


local.cos = ( waitthread global/maths.scr::cos local.radian * local.radius )
local.sin = ( waitthread global/maths.scr::sin local.radian * local.radius )

local.location = local.location + ( local.sin local.cos local.height )

local.height += local.gain_height

local.n = randomint 99999
local.xmas_light[local.n] = spawn script_model model "static/corona_reg.tik"
local.xmas_light[local.n].origin = local.location
}
end

get_diameter local.tree local.height:

local.result = (local.tree.basewidth - (local.tree.basewidth - local.tree.topwidth) / (local.tree.height - local.tree.baseheight) * (local.height - local.tree.baseheight) )

end local.result
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
User avatar
211476
Captain
Posts: 273
Joined: Fri Feb 29, 2008 2:20 am
Location: Arizona, USA
Contact:

Post by 211476 »

I'd like to see a picture of the final product in action :D ,sounds interesting
Image
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Post by $oldier Of Ra »

Here's what I have so far:

Image

What's left to do:
- Animation scripts
- Finish kill_tree thread (called when a fatal error occurs)
- Extra measure against "no free edicts"

So you could say it's almost done :P It's also the longest script I've made so far (38kb atm). This is probably because the users have so much freedom to define their own christmas tree.

One thing that is bugging me is that the coronas with a viewlensflare light are a bit laggy and broad when viewed from far :? I might need to make a SH one where the coronas are already in lots of colours and don't lag.
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
STORMnl
Colour Sergeant
Posts: 96
Joined: Mon Oct 15, 2007 5:26 pm
Location: NIJMEGEN
Contact:

Post by STORMnl »

looks nice lennie
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Post by jv_map »

Yah that's pretty! 8-) 8-)

Makes me want to dig up my christmas tree from the basement :)
Image
$oldier Of Ra
Lieutenant Colonel
Posts: 404
Joined: Sun Oct 16, 2005 7:16 pm
Location: Belgium
Contact:

Post by $oldier Of Ra »

14 days left jv, you'd better hurry! :D
Our official website: http://www.mohaairborne.co.cc
(Still accessible through http://mohaaclantb.tk and http://users.skynet.be/mohaaclantb/)

For all your bot needs!!!!

$oldier Of Ra.
User avatar
211476
Captain
Posts: 273
Joined: Fri Feb 29, 2008 2:20 am
Location: Arizona, USA
Contact:

Post by 211476 »

is that manon on top?
:D sounds dirty :D
Image
Post Reply