JTD City functions

ArmA editing, missions, modeling, textures, terrains

Moderators: Lone Wolf, Snake Man

Post Reply
T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

JTD City functions

Post by T_Rex » 2008-10-01 12:40:41

Hey guys, long time no see. :)

A couple guys (DMarkwick is one of them) have kinda started working on some ArmA addons/mods as a group (JTD). DM's smoke/viewblock stuff was basically the first.

I've been working on some scripting stuff.

The main one right now are a set of functions dealing with cities. I've posted a beta set over at OFPEC.
http://www.ofpec.com/forum/index.php?topic=32328.0

The idea is to take the config entry and determine the general city positions in one function, then use another function to determine more accurately (although not always perfectly) the "center" of the city, then a third function to determine the boundaries of the city, and to do this for every city on the map. I've been funneling earlier version of this to Xeno for incorporation into his Domination mission.

There's more information at the OFPEC link, or I can cross post here. Would love any feedback.

:)
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Post by Snake Man » 2008-10-01 15:45:03

Yes please post here so we can all read it.
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Post by T_Rex » 2008-10-01 16:48:02

Ok, these are my first attempts at any kind of "real" scripting.

The JTD_cityInit should be run at initialization, or at the beginning of a mission. :)

Credit goes to OFPEC, hoz, Spooner, and DMarkwick.

First is the JTD City Position function. It gets the general area of a city from the config. As noted, this is almost a direct rip from one of hoz's scripts at OFPEC.

Code: Select all

/* JTD_CityPosition.sqf function.
By Trexian/hoz

The purpose of the JTDCityCenter function is to determine the location of a city area. It is almost
a direct rip of the FindClosestTown function by hoz, available at OFPEC.  All I did was change the
elements returned, and tweaked the mechanism for creating the array, as suggested by Spooner.

All credit for this function really goes to hoz.

ooooooooooooooooooooooooooooooooooooooooooooooooooo

No elements passed to it (yet), and it returns the city position from the config.

ooooooooooooooooooooooooooooooooooooooooooooooooooo
Version history
01a - released at OFPEC

01b - fixed pursuant to Spooner's suggestions
	- included demo mission
*/


//hint "position init";
//sleep 1;

_towns=[];
_townsTemp = [];
_cfgTowns = (configFile >> "cfgWorlds" >> WorldName >> "Names");
_cfgPath = "";
_return = [];


for [{_z=0}, {_z <count>> "type");
	if ((_typecity == "NAMECITY") || (_typecity == "NAMEVILLAGE") || (_typecity == "NAMECITYCAPITAL")) then 
	{
		_return = _return + [[getText (_cfgPath >> "name"),getArray (_cfgPath >> "position")]];
	};
};


_return
The second script/function uses a density test to take that position (that is passed to it) and try to find a more central... center.

Code: Select all

/* JTD_CityCenter.sqf function.
By Trexian
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Credits:
OFPEC
DMarkwick, for math
Hoz, for the FindNearestTown resource
Baddo, for findBuildingPositions sqf reference
Raven, for takeBuilding sqs reference

ooooooooooooooooooooooooooooooooooooooooooooooooooo
The purpose of the JTDCityCenter function is to roughly determine the center of a city area. 
It starts with the position passed to it (likely the config location of the city), and determines
the densities of the areas in each direction.  If one of the densities is larger than the inital,
that becomes the temporary center.  The search is repeated until the script reaches a position
that has no higher density in the surrounding area.  That position is returned.
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Version history
01a - released at OFPEC

01b - fixed pursuant to Spooner's suggestions
	- included demo mission

*/


//hint "center init";
//sleep 1;
_posTown = [0,0];
_cntThis = 0;
_initArray = [];
_initCnt = 0;
_bldgTemp = "";
_bldgPos = 0;
_t = 0;
_z = 0;
_d = 0;
_tempArray = [];
_centerBool = false;
_posCenter = [0,0,0];
_direction = 0;
_cntTemp = 0;
_posTemp = [0,0,0];
_srchPos = [0,0,0];
_srchBldg = [];
_srchArray = [];
_srchCnt = 0;
_holderCnt = 0;
_holderPos = [0,0,0];
_posElem = [];
_posX = 0;
_posY = 0;

_posElem = _this select 0;				// position array passed to function

_posX = _posElem select 0;
_posY = _posElem select 1;
_posCenter = [_posX, _posY, 0];			// initial setting of the "center"

_initPos = _posCenter;
_initCnt = 0;
_centerBool = false;
_direction = 0;

	while {! _centerBool} do
	{
		_posTemp = _posCenter;
		_holderCnt = _initCnt;
		_holderPos = _posCenter;
			for [{_d = 1},{_d <= 8},{_d = _d + 1}] do	
			{
			_direction = _direction + 45;
// builds an initial array of buildings within the search area
// the distance could be tweaked, depending on the results

			_srchPos = [((_posTemp select 0) + sin (_direction) * 100), ((_posTemp select 1) + cos (_direction) *100), 0];
				_tempArray = nearestObjects [_srchPos, ["HOUSE"], 100];
				_t = count _tempArray;
				_t = _t - 1;
				
	// this is a quick routine to make sure the buildings found are occupiable
					for [{_z = 0},{_z <_t> _holderCnt) then
				{
				_holderPos = _srchPos;
				_holderCnt = _srchCnt;
				};
	// conditional to determine if the search yielded a position different than the last center - that no higher densities were found
				if (((_holderPos select 0) != (_posCenter select 0)) && ((_holderPos select 1) != (_posCenter select 1)) && ((_d == 8))) then
				{
				_posCenter = _holderPos;
				_initCnt = _holderCnt;
				_d = 0;
				};
			};
			_tempArray = nearestObjects [_holderPos, ["HOUSE"], 50];
			if ((count _tempArray) <1> _radA)) then
			{
				_radA = _dist;
			};
		if (((_t == 2) || (_t == 4))  && (_dist > _radB)) then
			{
				_radB = _dist;
			};	
			
			_radA = _radA * _radiusFactor;
			_radB = _radB * _radiusFactor;
			_return = [_radA, _radB];				
		
	};

_return
Ooops here's the border function.

Code: Select all

/* JTD_CityBorder.sqf function.
By Trexian

The purpose of the JTDCityBorder function is to roughly determine the size of the city being analyzed.
It first determines the baseline density for the center of the city.  The analysis is different,
depending on whether it is a high-density or low-density city.  The script uses a circle of the given
radius (_radius) to compare the density within the circle to the initial density in each cardinal direction.
When it reaches a certain percentage (_densityCutoff) of the original ratio, it considers that the outer
extent of that direction.  The script uses the longer of North/South for the B radius, and East/West for
the A radius.  The _radiusFactor is basically something to increase/decrease the size of the radii by an
artificial amount, depending on the needs of the developer.  This can also be achieved by altering the
returned elements in the calling script.

Also, within the script, the areas to tweak are:
- the first conditional determines the definition between "big" and "small" cities
- the _dist is the increment for the center of the search
- the _radius determines the size of the circle the search examines to determine the ratio to compare
to the initial ratio
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Credits:
OFPEC
DMarkwick, for math
Hoz, for the FindNearestTown resource
Baddo, for findBuildingPositions sqf reference
Raven, for takeBuilding sqs reference

ooooooooooooooooooooooooooooooooooooooooooooooooooo
Version history
01a - released at OFPEC

01b - fixed pursuant to Spooner's suggestions
	- included demo mission

*/


//hint "border init";
//sleep 1;

// these are the main tweakable values
_densityCutoff = .2;
_dist = 0;
_radiusFactor = 0;

_initCnt = 0;
_t = 0;
_d = 0;
_tempArray = [];
_centerBool = false;
_posCenter = [0,0,0];
_direction = 0;
_cntTemp = 0;
_posTemp = [0,0,0];
_srchPos = [0,0,0];
_srchCnt = 0;
_radA = 10;
_radB = 10;
_tmpRatio = .2;
_angle = 0;
_radius = 50;

_posElem = _this select 0;
_return = [];
_posX = _posElem select 0;
_posY = _posElem select 1;

_posCenter = [_posX, _posY, 0];
_tempArray = nearestObjects [_posCenter, ["HOUSE"], 100];
_cntTemp = count _tempArray;
_posCenter = getPos (_tempArray select 0);
_initPos = _posCenter;
_initCnt = _cntTemp;
_initRatio = _cntTemp / 100;
_centerBool = false;
_direction = 0;

// conditional to determine whether to use the Big City function or not
if (_initRatio < .75) then
	{
		_radius = 100;
		_dist = 50;
		_densityCutoff = .2;
		_radiusFactor = .75;
	}
	else
	{
		_radius = 150;
		_dist = 50;
		_densityCutoff = .1;
		_radiusFactor = 1;
	};
	
	for [{_t = 1},{_t <4> (_initRatio * _densityCutoff)} do 
			{
				_d = _d + 1;
				
				_dist = _d * _radius;
				_direction = _t * 90;
					_srchPos = [((_posCenter select 0) + sin (_direction) * (_dist)), ((_posCenter select 1) + cos (_direction) * (_dist)), 0];
					_tempArray = nearestObjects [_srchPos, ["HOUSE"], _radius];
					_cntTemp = count _tempArray;
					_tmpRatio = (_cntTemp / _radius);
			};
			_d = 0;
// conditional to determine which direction we're looking at
		if (((_t == 1) || (_t == 3)) && (_dist > _radA)) then
			{
				_radA = _dist;
			};
		if (((_t == 2) || (_t == 4))  && (_dist > _radB)) then
			{
				_radB = _dist;
			};	
			
			_radA = _radA * _radiusFactor;
			_radB = _radB * _radiusFactor;
			_return = [_radA, _radB];				
		
	};

_return

An example of how to put this together, this is a script that I reference as an execVM from a init.sqf for a mission. It creates red markers, centered on the returned city center position, with an axis A and axis B that roughly corresponds to the borders of the city.

Code: Select all

/*
 JTD City Initialization script
 by Trexian
 
Purpose: run the JTD City functions

Implementation: executed from init or mission.sqm

Future plans will include greater information exchange.
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Version history
01a - released at OFPEC

01b - fixed pursuant to Spooner's suggestions
	- included demo mission


ooooooooooooooooooooooooooooooooooooooooooooooooooo
"JTD_CityPosition.sqf"
	- passed no parameters
	- returns an array of all cities in the config, and the config positions
"JTD_CityCenter.sqf"
	- passed a position array (most likely from JTDCityPosition)
	- determines the approximate center of the city, by density
	- returns the position of the center
"JTD_CityBorder.sqf"
	- passed a position array (most likely from JTDCityCenter)
	- determines an approximate geographic size of the city in X (radius A) and Y (radius B)
	- returns radius A/B for use in marker or trigger

The markers are created to show the scenario developer the location and size of the parameters.

This particular script loads the centers and borders in additional global arrays that are indexed in the
same order as the city list taken from the config.
*/

//hint "city init";
//sleep 1;
_i = 0;
JTD_CityTriggers = [];
JTD_CityCenters = [];
JTD_CityBorders = [];

JTD_cityPos = compile preprocessFileLineNumbers "JTD_CityPosition.sqf";
JTD_cityCent = compile preprocessFileLineNumbers "JTD_CityCenter.sqf";
JTD_cityBord = compile preprocessFileLineNumbers "JTD_CityBorder.sqf";

JTD_citylist = call JTD_cityPos;
_count = (count JTD_citylist) -1;


for [{_i = 0}, {_i <= _count}, {_i = _i + 1}] do
//for [{_i = 0}, {_i < 5}, {_i = _i + 1}] do				// for testing, to limit the iterations
{
_citypos = ((JTD_citylist select _i) select 1);
_citycenter = [_citypos] call JTD_cityCent;
_cityborder = [_citycenter] call JTD_cityBord;

_posX = _citycenter select 0;
_posY = _citycenter select 1;
_radA = _cityborder select 0;
_radB = _cityborder select 1;

	_trigName = format ["JTDTrig%1", ((JTD_citylist select _i) select 0)];
	_JTDTrigMarker = createMarker [_trigName, [_posX, _posY]];
	_JTDTrigMarker setMarkerColor "ColorRedAlpha";
	_JTDTrigMarker setMarkerShape "ELLIPSE";
	_JTDTrigMarker setMarkerSize [_radA, _radB];

// set trigger
_spawnTrig = createTrigger ["EmptyDetector", [_posX, _posY]];
_spawnTrig setTriggerArea [_radA, _radB, 0, true];
_spawnTrig setTriggerActivation ["ANY", "PRESENT", true];
_spawnTrig setTriggerStatements ["this", format ["nul = [%1] execVM 'JTD_DriveFaster.sqf'", _i], ""];  //saves the index to pass to spawn script

JTD_CityTriggers = JTD_CityTriggers + [_trigger]; // Store these variables into global array, so they are indexed to the city list.
JTD_CityCenters = JTD_CityCenters + [_citycenter];
JTD_CityBorders = JTD_CityBorders + [_cityborder];

};
And FINALLY :) the "DriveFaster" script referenced in the CityInit and used in the test mission.

Code: Select all

/*
 JTD City Functions Proof of Concept script
 by Trexian
 
Purpose: run the JTD City functions

"You dropped a bomb on me, baby,
You dropped a bomb on me."
- Th Gap Band
*/

//hint "init";
//sleep 1;

_index = _this select 0;

_name = (JTD_citylist select _index) select 0;
_cityCenter = JTD_CityCenters select _index;
_cityRadA = (JTD_CityBorders select _index) select 0;
_cityRadB = (JTD_CityBorders select _index) select 1;
_posSpawn = [_cityCenter select 0, _cityCenter select 1, 0];

hint format ["city = %1", _name];
sleep 1;

_randBombs = floor (random ((_cityRadA + _cityRadB) / 5));

// change the 30 to whatever number you want
for [{_q = 0}, {_q <= _randBombs}, {_q = _q + 1}] do 
{

	_dis = (random 50) + 25;
	_dir = random 360;
	_x = (_posSpawn select 0) + sin (_dir) * _dis;
	_y = (_posSpawn select 1) + cos (_dir) * _dis;

sleep random 5;
_smellslikeLGB = "Bo_GBU12_LGB" createVehicle [_x, _y, 20];

	
};
8-)
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Post by Snake Man » 2008-10-01 17:13:36

This looks very interesting. Only drawback is that can you be sure that terrain creator has made map labels for all his populated places? Maybe there is some terrains that have very limited labeling, its been my experience that people tend to like islands/terrains without excessive map names so they can setup their own missions using names/labels they choose. For example if you label a base "US Army Spec OP HQ 726" then it looks real lame to use that base as Russian HQ :)

Also one of the biggest "doh" effects I've seen in WRP related stuff, is that people assume that the maps center point is always set by this: centerPosition[] = {6343, 6127,0}; config line, it is not. That config is just there to setup the terrains mission editor starting location to something preferred, it has nothing to do with center point of the WRP. For example all 12km OFP islands center point is always the same 6400,6400 (or whatever it was) even though it necessarily can be nowhere near like the islands capital city or such. Okay just had to clear that one up.

But if we go past those config line issues and assume that terrain creator has setup all necessary cities there, then whoah, that script system is very cool.

Could you provide us a demo mission download?
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Post by T_Rex » 2008-10-01 17:21:27

Yes, it does rely on the config to initially get started. :( I have a couple ideas for changing that, though.

BUT... :) the other 2 (the CityCenter and CityBorder functions) only need a position to start. So, if you knew the general area of the city, you could pass that position to the center function, then that returned position to the border one. That's kinda why I split them out. There may be uses for one, but not the other.

The pbo for the demo mission is so small, I'm trying this googlepages thing as a file host. If it doesn't work, I can work something else out.

http://tdperkins2000.googlepages.com/JT ... t.Sara.pbo

Simple demo. It is you, and a humvee with a driver. When you start the mission, go to the map and you should see red ellipses around the cities. Direct the driver where you want to go, and he'll drive there. When you "enter" the city, the name of the city should be hinted. A couple seconds later... well... stuff should start exploding around the center of the city. :D
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Post by Snake Man » 2008-10-01 17:34:38

It would be great to have script that automatically gathers info from all cities in the wrp, therefore you dont need to do nothing, just place a player + init.sqf call for the scripts and you have a mission ready :)

I actually tried something similar on much more beginner level. I made alot of gamelogics called pmc_1, pmc_2, pmc_3 ... etc you get the idea, I can easily set the locations of these logics and then script picks them up automatically and do objectives, enemies, markers etc.

Your cityfunction could be developed to the dream setup as I mentioned in the first paragraph. And the immersion would be good when the markers would mention city names and it could be passed on sidechats etc.

Does this cityfunction pickup only round city shapes, or can it track down the real outline of irregular shaped big city too?
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Post by T_Rex » 2008-10-01 17:47:22

The methodology is pretty basic.

For the city center, it starts at the coordinate passed to it. It gets the density (how many "HOUSE" objects) there are in that area (100m IIRC). It then looks 100m in each of the 8 directions (N,NE,E, etc.) and compares those density ratios with the original. It then moves the "center" 100m in that direction, and repeats the 8-direction search until there are no directions that have a higher density.

A similar methodology is used for the border. And, it *could* be a rectangle, but I found that a circular shape covered the area, without seeming too artificial, I guess. I could probably get it to set up a series of circles, but my goal was to be able to get dimensions for a single trigger for the city. Anyway, the border search starts with the position that is passed to it, and gets an initial density. It then moves in the 4 cardinal directions until it reaches a percentage of the original (the size of the search and the percentage can be changed in variables). It uses the longer of the N/S for the radiusB and E/W for the radiusA.

Can you tell me more about the wrp? Is there a text config file for it?

Edit:
Pic from beta showing where it determined the city centers to be:
http://i26.photobucket.com/albums/c114/ ... 01a_01.jpg

Pic from beta of markers showing city borders.
http://i26.photobucket.com/albums/c114/ ... 02e_12.jpg
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Post by Snake Man » 2008-10-01 18:36:17

Yes WRP is the terrain file. You can find terrain configs in Desert2.pbo, desert.pbo and sara.pbo for example. Use unrap to derapify the config.bin file so you can read it in text format.
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Post by T_Rex » 2008-10-01 18:39:59

Ok, then as long as the config is set up with the cities, it should work.

Now, a map like the Sakakah one would be problematic - it is all one big city. :doh:

Oh, and it looks for entries with like TOWN, CAPITALCITY and stuff like that. Individual bases - and things like forest entries - should be eliminated in the filter.

:)
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Post by Snake Man » 2008-10-01 18:47:05

I tested your demo mission on my 51km desert terrain, it doesnt work because the terrain uses the OFP class names system. Here is example:

Code: Select all

class Names
{
	class city_01
	{
		name="city 01";
		position[]={5701.9736, 43297.9141, 0};
	};
};
It another issue if one should use the new class format or not, but I'm pretty sure there are and will be terrains out which use the above example format.

Or could it be that this is a large terrain and centerpoint is not "center" etc?
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Post by T_Rex » 2008-10-01 18:50:17

Ahhh... I see at least part of the problem. Here's the config entry for Rashidah.

Code: Select all

		class Names {
			class Sara_Rashidah {
				name = "Rashidah";
				position[] = {9585.79, 11109.2};
				type = "NameVillage";
				radiusA = 100;
				radiusB = 100;
			};
It needs the type entry.

And before you ask about the radiusA and radiusB right there in the config, those don't bear much relation at all to the actual size of the city. :) I think they are used to figure out how big to make the font in the map.

Edit:
Oh, and the "center" of the map shouldn't be a problem. It uses the position array in the config. So, as long as that is valid, it should work.

Edit2:
The types it looks for are:
"NAMECITY" "NAMEVILLAGE" "NAMECITYCAPITAL"
if that helps.

Edit3:
Hope you see this edit. :) Are cities the only entries in your "Name" area of the config? In Sarahni, there are also forests and other features. But, if you only have cities, I can remove the type filter, and it'll generate a list of all those features.

:thumbs:

Another edit:

I thought of another potential solution.

First, it would filter for the city types (as it does now), and then also for a blank "" type. That way it'll include all positions that are either a city or don't have a type specified. Then, a second filter to see how many HOUSE type buildings are returned in that location (100m radius). If it is zero, then remove that location from the array.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-19 07:53:36

Hey T Rex, time to revive this topic :)

This is ArmA editing area so lets not go too far off topic, but ArmA 2 has much more class name labeling as ArmA have you noticed that? The game logic modules like Secondary Ops and Ambient Civilians use this very heavily. Perhaps the new ArmA 2 config entries could be useful for this script.

However back to ArmA (1).

Is all the stuff you wrote above still up to date?

I'm making various random / large / never-run-same-twice missions in my huge 51km desert terrain and this city investigating script is next to try out, it would be really nice to see it working fully there as many possibilities would open to populate the cities and their boundaries (like putting heavy tanks OUTSIDE of the city, infantry INSIDE) etc.

Is it viable to configure the script for OFP, ArmA and ArmA 2 style class names?
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 13:24:53

Indeed, I'm more than happy to talk about ArmA2 stuff in the appropriate place. :) But, I ran a quick test in ArmA2, and...

http://i26.photobucket.com/albums/c114/ ... ersJTD.jpg

The basic scripts themselves work with A2 with a minimum of tweaking. (In fact, I can't remember what exactly I did, it was so minor.)

I believe the config entries that the scripts rely on are unchanged from A1 to A2 (I don't know if they work in OFP, that app is long gone from my HDD.)

I'll start a new thread about A2 location functions, and post a link to the most recent version of the city functions. What you describe, in terms of setPos-ing some units inside a city and others outside is an easy implementation.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 13:34:01

Okay looks good, go ahead and open a new ArmA 2 topic :)

In the mean time I need to add those ArmA specific class name type labels in my terrain, it still uses the old OFP method as WrpTool only writes the basic stuff. But it would be good time to upgrade my names.hpp now.

Like said my biggest problem now is that I want to add city defenses, but createVechile creating 4 T72 tanks inside a city is pretty much guaranteed to cause them to flip over buildings and then you end up with half of the tanks upside down if not completely blown up etc. Id need to find the boundary of the city, creating the vehicles there and adding waypoint into the city center. This way they at least have a chance to come there in correct formation (of course AI can still flip them but there is nothing we can do about that).

Also city functions opens tons of other possibilities to make it much nicer mission for city actions.
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 13:42:40

Understood.

In your config, do you have a "type" entry for your cities, like in my post from October? If you don't, I'll need to adjust the scripts a bit.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 13:58:07

Hehe no no. I am using out dated stuff in my terrain, I'm using OFP class names method in ArmA terrain, MY stuff is out dated, not your script.

It wouldn't be big fix to add OFP compatibility for the script, but how many guys in reality builds ArmA terrains with OFP class names besides me... not many I think. So its not a issue here. I'll just add the ArmA class names features and its fixed, I need to do that anyways to make it look cool so its all good :)
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 15:02:19

Ok, here are the files for when you are ready:
http://tdperkins2000.googlepages.com/JTD_CityFuncs.7z

It is dependent on that "type" entry, though. ;)

There is a bit of trick to using them, and I don't think I explain it very well. Basically, the 3 global arrays share the same indexing. So, index 5 in one array will mean that index 5 in another array relates to the same city. Another quirk is:
- JTD_citylist array with subarray - subarray select 0 = string of city name, select 1 = position array of config location
So, if you're looking for a specific city name, there needs to be a loop to strip the city name subarray from the city list. (Not hard - I did it at one time, and still have the code someplace.) And, as long as you iterate through the main citylist array when stripping the name list, the indexing should remain intact.

Also, I call the city init sqf from the mission init.sqf, but you could set it up to run from a trigger or addaction, too.

Also, in thinking about your issue with tanks, there's another function - a findRoads function - that I have somewhere that may be useful. What you can do is, once you have the city center that you want to use, then a random location within the border radius, look for the nearest road model to that location. I think that would improve your chances of getting the tank to spawn upright. Could probably even trim the road array to only look for the biggest road models.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 15:53:48

Thanks downloaded and will check them out.

Yeah I just now updated my terrain to use the type and radius feature in ArmA class names. Also took a peek on the ArmA 2 class names and there is even more interesting stuff like neighbor city, angle and such things. But more on those in ArmA 2 editing forum.

If you find the road function, please post it to other topic here. Sounds like something that would be very useful.
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 18:29:51

T_Rex wrote:Ok, here are the files for when you are ready:
http://tdperkins2000.googlepages.com/JTD_CityFuncs.7z
I ran that JTD_PMC_CityInit.sqf and got this error:

Code: Select all

Error in expression <select _i) select 0)];
_JTDTrigMarker = createMarker [_trigName, [_posX, _posY]]>
  Error position: <createMarker [_trigName, [_posX, _posY]]>
  Error Type Any, expected Number
File d:\ArmA\Users\Snake_Man\scripts\JTD_PMC_CityInit.sqf, line 68
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 19:38:42

Shit.

Sorry.

Here's that whole sqf with that fixed.

Code: Select all

/*
 JTD PMC City Initialization script
 by Trexian
 
Purpose: run the JTD City functions for PMC

Implementation: executed from init.sqf.
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Credits:
OFPEC
Command HQ - dos game from 1990 by Microprose, it had a mode where it randomly set your units
DMarkwick
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Version history
01a -
proof of concept

ooooooooooooooooooooooooooooooooooooooooooooooooooo
"JTD_CityPosition.sqf"
	- passed no parameters
	- returns an array of all cities in the config, and the config positions
	- JTD_citylist array with subarray - subarray select 0 = string of city name, select 1 = position array of config location
"JTD_CityCenter.sqf"
	- passed a position array (most likely from JTDCityPosition)
	- determines the approximate center of the city, by density
	- returns the position of the center
"JTD_CityBorder.sqf"
	- passed a position array (most likely from JTDCityCenter)
	- determines an approximate geographic size of the city in X (radius A) and Y (radius B)
	- returns radius A/B for use in marker or trigger
*/
//ooooooooooooooooooooooooooooooooooooooooooooooooooo
// start of city stuff
_i = 0;
JTD_CityCenters = [];
JTD_CityBorders = [];
JTD_CityDebug = false;
JTD_CityMarkers = true;

//ooooooooooooooooooooooooooooooooooooooooooooooooooo
// start the cool stuff

if (JTD_CityDebug) then
	{
	hint "DEBUG city init";
	sleep 1;
	};

JTD_cityPos = compile preprocessFileLineNumbers "JTD_CityPosition.sqf";
JTD_cityCent = compile preprocessFileLineNumbers "JTD_CityCenter.sqf";
JTD_cityBord = compile preprocessFileLineNumbers "JTD_CityBorder.sqf";

JTD_citylist = call JTD_cityPos;
_count = (count JTD_citylist) -1;

for [{_i = 0}, {_i <= _count}, {_i = _i + 1}] do
//for [{_i = 0}, {_i < 5}, {_i = _i + 1}] do				// for testing, to limit the iterations
{
_citypos = ((JTD_citylist select _i) select 1);
_citycenter = [_citypos] call JTD_cityCent;
_cityborder = [_citycenter] call JTD_cityBord;
_posX = _citycenter select 0;
_posY = _citycenter select 1;
_radA = _cityborder select 0;
_radB = _cityborder select 1;
//ooooooooooooooooooooooooooooooooooooooooooooooooooo	
// set markers
if (JTD_CityMarkers) then
	{
	_trigName = format ["JTDTrig%1", ((JTD_citylist select _i) select 0)];
	_JTDTrigMarker = createMarker [_trigName, [_posX, _posY]];
	_JTDTrigMarker setMarkerColor "ColorRedAlpha";
	_JTDTrigMarker setMarkerShape "ELLIPSE";
	_JTDTrigMarker setMarkerSize [_radA, _radB];
	};
// ooooooooooooooooooooooooooooooooooooooooooooooooooo	
JTD_CityCenters = JTD_CityCenters + [_citycenter];
JTD_CityBorders = JTD_CityBorders + [_cityborder];
};

	if (JTD_CityDebug) then
		{
		hint "City Scripts Initialized";
		sleep 1;
		};
That should work. :oops:

(Shoddy cleanup of my rough dev work.) :(
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 19:47:34

Hehe :)

Code: Select all

Error in expression <select _i) select 0)];
_JTDTrigMarker = createMarker [_trigName, [_posX, _posY]]>
  Error position: <createMarker [_trigName, [_posX, _posY]]>
  Error Type Any, expected Number
File d:\ArmA\Users\Snake_Man\missions\jtd.PMC_Desert_Hardcore\JTD_PMC_CityInit.sqf, line 71
Thats the error I get from the upgraded sqf you posted :)
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 19:57:27

FAAAAAAAAACCCCCCKKKKKK.

I am so sorry. I'll do some more digging and post another version tonight that I *know* works. :(

To make sure the functions are working, add these hints after the commented line about the markers.

Code: Select all

// set markers
hint format ["%1 center %2 rad = %3", (JTD_citylist select _i) select 0, _citycenter, _cityborder];
sleep 3;
If it doesn't get any of the values, then it is having trouble getting the functions....
Sic Semper tyrannosauro.

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 20:58:35

Ok - my init that works.

Code: Select all

/*
 JTD City Initialization script for ArmA2
 by Trexian
 
Purpose: run the JTD City functions

Implementation: executed from init or mission.sqm

Future plans will include greater information exchange.
ooooooooooooooooooooooooooooooooooooooooooooooooooo
Version history
01a - released at OFPEC for ArmA

01b - fixed pursuant to Spooner's suggestions
	- included demo mission
	
01c
- civ spawning

02
ArmA 2 version

ooooooooooooooooooooooooooooooooooooooooooooooooooo
"JTD_CityPosition.sqf"
	- passed no parameters
	- returns an array of all cities in the config, and the config positions
"JTD_CityCenter.sqf"
	- passed a position array (most likely from JTDCityPosition)
	- determines the approximate center of the city, by density
	- returns the position of the center
"JTD_CityBorder.sqf"
	- passed a position array (most likely from JTDCityCenter)
	- determines an approximate geographic size of the city in X (radius A) and Y (radius B)
	- returns radius A/B for use in marker or trigger

The markers are created to show the scenario developer the location and size of the parameters.

This particular script loads the centers and borders in additional global arrays that are indexed in the
same order as the city list taken from the config.
*/

private ["_i", "_count", "_citypos", "_citycenter", "_cityborder", "_posX", "_posY", "_radA", "_radB", "_trigName", "_JTDTrigMarker", "_spawnTrig", "_trigger"];

hint "city init";
sleep 1;

_i = 0;
JTD_CityTriggers = [];
JTD_CityCenters = [];
JTD_CityBorders = [];

JTD_cityPos = compile preprocessFileLineNumbers "JTD_CityPosition.sqf";
JTD_cityCent = compile preprocessFileLineNumbers "JTD_CityCenter.sqf";
JTD_cityBord = compile preprocessFileLineNumbers "JTD_CityBorder.sqf";

JTD_citylist = call JTD_cityPos;
_count = (count JTD_citylist) -1;


for [{_i = 0}, {_i <= _count}, {_i = _i + 1}] do
//for [{_i = 0}, {_i < 5}, {_i = _i + 1}] do				// for testing, to limit the iterations
{
_citypos = ((JTD_citylist select _i) select 1);
_citycenter = [_citypos] call JTD_cityCent;
_cityborder = [_citycenter] call JTD_cityBord;

_posX = _citycenter select 0;
_posY = _citycenter select 1;
_radA = _cityborder select 0;
_radB = _cityborder select 1;

	_trigName = format ["JTDTrig%1", ((JTD_citylist select _i) select 0)];
	_JTDTrigMarker = createMarker [_trigName, [_posX, _posY]];
	_JTDTrigMarker setMarkerColor "ColorRedAlpha";
	_JTDTrigMarker setMarkerShape "ELLIPSE";
	_JTDTrigMarker setMarkerSize [_radA, _radB];
/*
// set trigger
_spawnTrig = createTrigger ["EmptyDetector", [_posX, _posY]];
_spawnTrig setTriggerArea [_radA, _radB, 0, true];
_spawnTrig setTriggerActivation ["ANY", "PRESENT", true];
_spawnTrig setTriggerStatements ["this", format ["nul = [%1] execVM 'JTD_CivSpawnInit.sqf'", _i], ""];  //saves the index to pass to spawn script
*/
JTD_CityTriggers = JTD_CityTriggers + [_trigger]; // Store these variables into global array, so they are indexed to the city list.
JTD_CityCenters = JTD_CityCenters + [_citycenter];
JTD_CityBorders = JTD_CityBorders + [_cityborder];

};
It has stuff I don't think you really need, but it should work.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 21:20:38

Now it works, it still gives some error but it works now.

When I ran it on my 51km desert terrain with largest cities seen on ArmA, it brought my computer to a dead stop for about... hmm it was probably like 5sec or more, felt like really long time. I mean it was totally locked up when it scanned those cities.

I guess sahrani has so small cities that the script runs smooth on your tests(?).
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-21 21:26:48

Yeah, there's a little stutter, but it works.

How many cities are there?

I think there are some ways to stop the init until it is done, but I haven't investigated that much.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-21 22:12:00

Total of 60 locations which match the scripts searches. And I think even the more hard hitting thing is that these cities are huge. Maybe I'm bit exaggerating but average city in this terrain is same size as ALL sahrani cities combined... ;)
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-22 00:32:59

Ahh... I bet what is happening is the radius-finding, and to a lesser extent, the center-finding routines.

Do you know if the position in the config is pretty close to center for each city? If it is, you could do away with that one - or really just change it to make that the global for the center. Similarly, if the cities are all about the same size, you could create your own array that is more or less tailored for each city.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-22 01:48:16

T_Rex wrote:Do you know if the position in the config is pretty close to center for each city?
No. I actually noticed that the positions are bit outdated. Its long story how the city locations were created but as summary, the origin of the center location has evolved a bit.
Similarly, if the cities are all about the same size
No they are not. They are different sizes AND shapes.
you could create your own array that is more or less tailored for each city.
Hmm in that case I wouldn't need your automated city sniffing script? :)

I mean the whole point of this script is to just plug it in for any terrain and it pulls out all the city data. Great idea, great script.

Anyways.

Do the init script pull out the city data, can you put small sleep there so the script has some time to breath between cities? Would be interesting to see if that helps, or are one city just so damn big that it causes it to freeze.

My cities has a lot of houses. The largest one (which is indeed extreme case) had in the "downtown" area 13,700 houses. Yes, it was not a typo, thirteen thousand seven hundred houses :shock:

Others have less, might be even half that, but even that comes to the 5-6 thousand houses. Man that script has lot of work to do :)
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-22 02:52:43

Sure - a sleep would not be a problem at all. I'd suggest a couple places - right after the start of the for _i loop, and after each call command in the init.

Also, I found in the testing, there is kinda a balancing for the algorithms for the city center and radius. I start with the number of buildings in a given radius. The most dense area in the vicinity of the starting point is the "center." For the radius, once the number of buildings within the area reaches a low density, that is the "radius." If you know you have alot of buildings, you (or I) can change the size of the searches, so that it doesn't have to get as many buildings in each iteration.

When I first did this, I intended to make those items user-configurable, but decided they were too esoteric. :D I can certainly revisit that for you, though.
Sic Semper tyrannosauro.

Snake Man
Commander-In-Chief
Posts: 9338
Joined: 2000-07-31 22:01:01
Gaming Interests: ArmA, ArmA 2, Falcon 4.0 and OFP.
Editing Interests: All, I (try) to edit everything.
Location: PMC
Contact:

Re: JTD City functions

Post by Snake Man » 2009-07-22 11:59:13

Was just thinking that you could try this out on yourself for the PMC WRP Demo terrains, but they lack the new type = labels. I could give them to you if you want to tweak them in yourself.

I mean the freeze is no problem to me, I think I can manage through it, but was just thinking that if yourself want to improve the script as there will be terrains like this available in the future for public (well at least mine hehe).
PMC Tactical Forum New User Registration please read new info here.

PMC since 1984

Editing knowledge, visit PMC Editing Wiki
The leading, most detailed and comprehensive modification made for the Vietnam War - Vietnam: The Experience homepage
View our videos in PMC Youtube channel

PMC Tactical forum Advanced Search is power.

"ALPHA BLACK TO PAPA BEAR. ALL RUSSIANS ARE TOAST. OVER."

T_Rex
FreeFalcon
Posts: 848
Joined: 2001-03-04 23:01:01
Location: here

Re: JTD City functions

Post by T_Rex » 2009-07-22 12:56:30

Yeah, sure. :)

Is this the one that is available now? I'm finishing up an addon for A2 with JTD, but that should be about a week or so.

I've been meaning to get more into how to delay the startup to get a bunch of stuff to happen before the player is "in" - this would be the perfect testbed. :)
Sic Semper tyrannosauro.

Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests