4 #include "cmd/planet_generic.h"
5 #include "cmd/unit_factory.h"
12 #include "cmd/building_generic.h"
13 #include "cmd/ai/aggressive.h"
14 #include "cmd/ai/fire.h"
15 #include "cmd/nebula_generic.h"
16 #include "cmd/asteroid_generic.h"
17 #include "cmd/enhancement_generic.h"
18 #include "cmd/script/flightgroup.h"
20 #include "cmd/atmosphere.h"
36 extern void bootstrap_draw(
const string &message, Animation *SplashScreen = NULL );
155 EnumMap::Pair(
"UNKNOWN",
UNKNOWN ),
156 EnumMap::Pair(
"Planet",
PLANET ),
157 EnumMap::Pair(
"System",
SYSTEM ),
158 EnumMap::Pair(
"Unit",
UNIT ),
160 EnumMap::Pair(
"Jump",
JUMP ),
161 EnumMap::Pair(
"Light",
LIGHT ),
162 EnumMap::Pair(
"Attenuated",
ATTEN ),
163 EnumMap::Pair(
"Diffuse",
DIFF ),
164 EnumMap::Pair(
"Specular",
SPEC ),
165 EnumMap::Pair(
"Ambient",
AMB ),
166 EnumMap::Pair(
"Terrain",
TERRAIN ),
168 EnumMap::Pair(
"Building",
BUILDING ),
169 EnumMap::Pair(
"Vehicle",
VEHICLE ),
171 EnumMap::Pair(
"Nebula",
NEBULA ),
172 EnumMap::Pair(
"Asteroid",
ASTEROID ),
173 EnumMap::Pair(
"RING",
RING ),
176 EnumMap::Pair(
"Fog",
FOG ),
181 EnumMap::Pair(
"UNKNOWN",
UNKNOWN ),
185 EnumMap::Pair(
"stars",
STARS ),
190 EnumMap::Pair(
"file",
XFILE ),
191 EnumMap::Pair(
"alpha",
ALPHA ),
194 EnumMap::Pair(
"x",
X ),
195 EnumMap::Pair(
"y",
Y ),
196 EnumMap::Pair(
"z",
Z ),
197 EnumMap::Pair(
"ri",
RI ),
198 EnumMap::Pair(
"rj",
RJ ),
199 EnumMap::Pair(
"rk",
RK ),
200 EnumMap::Pair(
"si",
SI ),
201 EnumMap::Pair(
"sj",
SJ ),
202 EnumMap::Pair(
"sk",
SK ),
203 EnumMap::Pair(
"qi",
QI ),
204 EnumMap::Pair(
"qj",
QJ ),
205 EnumMap::Pair(
"qk",
QK ),
206 EnumMap::Pair(
"name",
NAME ),
207 EnumMap::Pair(
"radius",
RADIUS ),
208 EnumMap::Pair(
"gravity",
GRAVITY ),
209 EnumMap::Pair(
"year",
YEAR ),
210 EnumMap::Pair(
"day",
DAY ),
212 EnumMap::Pair(
"MaxAlpha",
MAXALPHA ),
213 EnumMap::Pair(
"MinAlpha",
MINALPHA ),
214 EnumMap::Pair(
"DRed",
DIRED ),
215 EnumMap::Pair(
"DGreen",
DIGREEN ),
216 EnumMap::Pair(
"DBlue",
DIBLUE ),
217 EnumMap::Pair(
"DAlpha",
DIALPHA ),
218 EnumMap::Pair(
"Red",
EMRED ),
219 EnumMap::Pair(
"Green",
EMGREEN ),
220 EnumMap::Pair(
"Blue",
EMBLUE ),
221 EnumMap::Pair(
"Alfa",
EMALPHA ),
222 EnumMap::Pair(
"SRed",
SRED ),
223 EnumMap::Pair(
"SGreen",
SGREEN ),
224 EnumMap::Pair(
"SBlue",
SBLUE ),
225 EnumMap::Pair(
"SAlfa",
SALPHA ),
226 EnumMap::Pair(
"SPower",
SPOWER ),
228 EnumMap::Pair(
"faction",
FACTION ),
229 EnumMap::Pair(
"Light",
LIGHT ),
230 EnumMap::Pair(
"Mass",
MASS ),
231 EnumMap::Pair(
"ScaleX",
SCALEX ),
232 EnumMap::Pair(
"NumWraps",
NUMWRAPS ),
235 EnumMap::Pair(
"ScaleAtmosphereHeight",
SCALEATMOS ),
240 EnumMap::Pair(
"WrapX",
WRAPX ),
241 EnumMap::Pair(
"WrapY",
WRAPY ),
242 EnumMap::Pair(
"Focus",
FOCUS ),
247 EnumMap::Pair(
"serial",
SERIAL ),
248 EnumMap::Pair(
"VarName",
VARNAME ),
249 EnumMap::Pair(
"VarValue",
VARVALUE ),
253 EnumMap::Pair(
"unit",
UNIT ),
254 EnumMap::Pair(
"override",
OVERRIDE )
271 template <
typename T >
272 static bool EvalCondition(
const char *op,
const T &left,
const T &right )
283 return left >= right;
293 return left == right;
305 return left <= right;
314 return left != right;
324 static bool ConfigCondition(
const string &cond )
331 bool ok = 3 == sscanf( cond.c_str(),
"%63[-a-zA-Z_0-9] %2[<>=!] %63[-0-9.Ee]",
338 varname[
sizeof (varname)/
sizeof (*varname)-1] = 0;
339 op[
sizeof (op)/
sizeof (*op)-1] = 0;
340 varval[
sizeof (varval)/
sizeof (*varval)-1] = 0;
344 if (endptr == varval) {
346 rv = EvalCondition< string > ( op, sval, varval );
350 rv = EvalCondition< float > ( op, fval, fref );
355 static bool ConfigAllows(
string var,
float val )
358 if (var.length() == 0)
361 var = var.substr( 1 );
365 if (var.length() == 0)
367 return invert ? -x >= val : x >= val;
370 static Vector ComputeRotVel(
float rotvel,
const QVector &r,
const QVector &s )
372 if ( (r.i || r.j || r.k) && (s.i || s.j || s.k) ) {
373 QVector retval = r.Cross( s );
375 retval = retval*rotvel;
376 return retval.Cast();
378 return Vector( 0, rotvel, 0 );
382 static void GetLights(
const vector< GFXLight > &origlights, vector< GFXLightLocal > &curlights,
const char *str,
float lightSize )
386 char *tmp = strdup( str );
390 while ( ( numel = sscanf( st,
"%d%c", &tint, &isloc ) ) > 0 ) {
391 assert( tint < (
int) origlights.size() );
392 lloc.
ligh = origlights[tint];
393 lloc.
islocal = (numel > 1 && isloc ==
'l');
397 curlights.push_back( lloc );
398 while ( isspace( *st ) )
400 while ( isalnum( *st ) )
408 static void SetSubunitRotation( Unit *un,
float difficulty )
411 for (un_iter iter = un->getSubUnits(); (unit = *iter); ++iter) {
412 float x = 2*difficulty*( (float) rand() )/RAND_MAX-difficulty;
413 float y = 2*difficulty*( (float) rand() )/RAND_MAX-difficulty;
414 float z = 2*difficulty*( (float) rand() )/RAND_MAX-difficulty;
415 unit->SetAngularVelocity( Vector( x, y, z ) );
416 SetSubunitRotation( unit, difficulty );
424 if (alpha == NULL) {}
else if (alpha[0] ==
'\0') {}
else {
425 char *s = strdup( alpha );
426 char *d = strdup( alpha );
429 if ( 2 == sscanf( alpha,
"%s %s", s, d ) ) {
430 if (strcmp( s,
"true" ) != 0) {
466 using namespace StarXML;
469 vector< GFXLightLocal >curlights;
471 string varname, condition;
478 ObjSerial serial = 0;
479 float scaleatmos = 10;
481 bool insideout =
false;
483 string truncatedfilename = this->
filename;
485 string::size_type tmp;
486 if ( ( tmp = truncatedfilename.find(
".system" ) ) != string::npos )
487 truncatedfilename = truncatedfilename.substr( 0, tmp );
502 vector< string >dest;
503 map< string, string > paramOverrides;
506 string fullname =
"unknw";
511 QVector S( 0, 0, 0 ), R( 0, 0, 0 );
512 QVector pos( 0, 0, 0 );
515 AttributeList::const_iterator iter;
526 pos = QVector( 0, 0, 0 );
527 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
555 this->name =
new char[strlen( (*iter).value.c_str() )+1];
556 strcpy( this->name, (*iter).value.c_str() );
573 string myfile(
"planets/ring.png" );
579 if (p->isUnit() == PLANETPTR) {
583 float iradius = p->rSize()*1.25f;
584 float oradius = p->rSize()*1.75f;
587 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
591 myfile = (*iter).value;
630 varname = (*iter).value;
639 if ( p != NULL && ConfigAllows( varname, varvalue ) )
640 ( (Planet*) p )->AddRing( myfile, iradius, oradius, R, S, numslices, wrapx, wrapy, blendSrc, blendDst );
649 string myfile(
"elevator" );
655 if (p->isUnit() == PLANETPTR) {
657 char direction =
'b';
661 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
665 myfile = (*iter).value;
668 varname = (*iter).value;
675 if ( !(*iter).value.empty() )
676 direction = (*iter).value[0];
689 if ( p != NULL && ConfigAllows( varname, varvalue ) )
690 ( (Planet*) p )->AddSpaceElevator( myfile,
faction, direction );
702 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
717 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
746 xml->
fog.back().meshname = iter->value;
776 string myfile(
"planets/Dirt_light.png" );
781 bool inside_out =
false;
785 if (p->isUnit() == PLANETPTR) {
786 float radius = p->rSize();
787 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
791 myfile = (*iter).value;
809 varname = (*iter).value;
819 if ( ConfigAllows( varname, varvalue ) )
820 ( (Planet*) p )->AddCity( myfile, radius, wrapx, wrapy, blendSrc, blendDst, inside_out );
830 string myfile(
"sol/earthcloudmaptrans.png" );
833 bool inside_out =
false;
836 if (p->isUnit() == PLANETPTR) {
837 float radius = p->rSize()*1.075;
838 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
842 myfile = (*iter).value;
851 varname = (*iter).value;
864 if ( ConfigAllows( varname, varvalue ) )
865 ( (Planet*) p )->AddAtmosphere( myfile, radius, blendSrc, blendDst, inside_out );
873 S = QVector( 1, 0, 0 );
874 R = QVector( 0, 0, 1 );
875 pos = QVector( 0, 0, 0 );
878 position = game_options.
mass;
881 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
894 myfile = (*iter).value;
935 static Vector TerrainScale( game_options.
xscale, game_options.
yscale, game_options.
zscale );
938 float y = S.Magnitude();
940 float z = R.Magnitude();
945 t.r[3] = S.i*TerrainScale.j;
946 t.r[4] = S.j*TerrainScale.j;
947 t.r[5] = S.k*TerrainScale.j;
948 t.r[6] = R.i*TerrainScale.k;
949 t.r[7] = R.j*TerrainScale.k;
950 t.r[8] = R.k*TerrainScale.k;
952 t.r[0] = S.i*TerrainScale.i;
953 t.r[1] = S.j*TerrainScale.i;
954 t.r[2] = S.k*TerrainScale.i;
956 if ( myfile.length() ) {
958 terrains.push_back( UnitFactory::createTerrain( myfile.c_str(), TerrainScale, position, radius, t ) );
961 contterrains.push_back( UnitFactory::createContinuousTerrain( myfile.c_str(), TerrainScale, position, t ) );
968 p->setTerrain(
xml->
ct, scalex, numwraps, scaleatmos );
970 p->getTerrain( *tmpp );
998 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1015 xml->
lights.back().SetProperties( tmptarg, tmpcol );
1021 S = QVector( 1, 0, 0 );
1022 R = QVector( 0, 0, 1 );
1024 citylights = string(
"" );
1025 technique = string(
"" );
1028 paramOverrides.clear();
1030 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1037 fullname = (*iter).value;
1048 technique = (*iter).value;
1051 unitname = (*iter).value;
1057 citylights = (*iter).value;
1064 GetLights(
xml->
lights, curlights, (*iter).value.c_str(), radius );
1071 if (
faction == originalowner) {
1117 ourmat.sr = ourmat.sg = ourmat.sb = ourmat.dr = ourmat.dg = ourmat.db =
1118 ourmat.ar = ourmat.ag = ourmat.ab = 0;
1157 if (fabs(
parse_float( (*iter).value ) ) > .00001)
1161 if (fabs(
parse_float( (*iter).value ) ) > .00001)
1170 string::size_type eqpos = (*iter).value.find_first_of(
'=');
1171 if (eqpos != string::npos) {
1172 string name = (*iter).value.substr(0,eqpos);
1173 string value = (*iter).value.substr(eqpos+1);
1174 paramOverrides[
name] = value;
1185 fprintf(stderr,
"Creating planet %s with texture %s and technique %s - unitlevel > 2\n", fullname.c_str(),
filename.c_str(), technique.c_str());
1186 Unit *un =
xml->
moons[
xml->
moons.size()-1]->beginElement( R, S, velocity, ComputeRotVel( rotvel, R, S ),
1187 position, gravity, radius,
1188 filename, technique, unitname, blendSrc, blendDst, dest,
1193 fullname, insideout );
1196 un->SetSerial( serial );
1197 un->applyTechniqueOverrides(paramOverrides);
1201 fprintf(stderr,
"Creating planet %s with texture %s and technique %s - unitlevel <= 2\n", fullname.c_str(),
filename.c_str(), technique.c_str());
1203 UnitFactory::createPlanet( R, S, velocity,
1204 ComputeRotVel( rotvel, R, S ),
1205 position, gravity, radius,
1207 blendSrc, blendDst, dest,
xml->
cursun.Cast()
1209 NULL, ourmat, curlights,
faction
1217 planet->SetSerial( serial );
1218 planet->applyTechniqueOverrides(paramOverrides);
1225 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1229 condition = (*iter).value;
1235 && ConfigCondition( condition )
1250 S = QVector( 0, 1, 0 );
1251 R = QVector( 0, 0, 1 );
1252 nebfile =
new char[1];
1255 fullname =
"unkn-unit";
1257 for (iter = attributes.begin(); iter != attributes.end(); ++iter) {
1264 fullname = (*iter).value;
1271 nebfile =
new char[strlen( (*iter).value.c_str() )+1];
1272 strcpy( nebfile, (*iter).value.c_str() );
1285 if (
faction == originalowner) {
1330 varname = (*iter).value;
1336 condition = (*iter).value;
1341 && ConfigAllows( varname, varvalue )
1342 && ConfigCondition( condition ) ) {
1350 plan->AddSatellite( un = UnitFactory::createUnit(
filename.c_str(),
false,
faction,
"", fg, fg->nr_ships-1 ) );
1351 un->SetSerial( serial );
1352 un->setFullname( fullname );
1353 }
else if (elem ==
NEBULA) {
1355 plan->AddSatellite( un = UnitFactory::createNebula(
filename.c_str(),
false,
faction, fg, fg->nr_ships-1 ) );
1356 un->SetSerial( serial );
1359 plan->AddSatellite( un =
1360 UnitFactory::createAsteroid(
filename.c_str(),
faction, fg, fg->nr_ships-1, scalex
1361 < 0 ? -scalex : scalex ) );
1362 un->SetSerial( serial );
1364 plan->AddSatellite( un = UnitFactory::createEnhancement(
filename.c_str(),
faction, string(
"" ) ) );
1365 un->SetSerial( serial );
1368 for (
unsigned int i = 0; i < dest.size(); ++i)
1369 un->AddDestination( dest[i] );
1372 un->SetAI(
new PlanetaryOrbit( un, velocity, position, R, S, QVector( 0, 0, 0 ), plan ) );
1373 if (elem ==
UNIT && un->faction != neutralfaction) {
1375 un->EnqueueAI(
new Orders::FireAt( 15 ) );
1377 if (scalex < 0 && elem !=
ASTEROID)
1378 SetSubunitRotation( un, -scalex );
1381 un->SetAngularVelocity( ComputeRotVel( rotvel, R, S ) );
1384 Unit *b = UnitFactory::createBuilding(
1386 b->SetSerial( serial );
1388 b->EnqueueAI(
new Orders::AggressiveAI(
"default.agg.xml" ) );
1391 for (
unsigned int i = 0; i < dest.size(); ++i)
1392 b->AddDestination( dest[i] );
1396 Unit *b = UnitFactory::createBuilding(
1398 b->SetSerial( serial );
1400 b->EnqueueAI(
new Orders::AggressiveAI(
"default.agg.xml" ) );
1402 b->EnqueueAI(
new Orders::FireAt( 15 ) );
1405 for (
unsigned int i = 0; i < dest.size(); ++i)
1406 b->AddDestination( dest[i] );
1412 Unit *moon_unit = UnitFactory::createUnit(
filename.c_str(),
false,
faction,
"", fg, fg->nr_ships-1 );
1413 moon_unit->SetSerial( serial );
1414 moon_unit->setFullname( fullname );
1415 xml->
moons.push_back( (Planet*) moon_unit );
1416 }
else if (elem ==
NEBULA) {
1418 xml->
moons.push_back( (Planet*) UnitFactory::createNebula(
filename.c_str(),
false,
faction, fg, fg->nr_ships-1 ) );
1423 (Planet*) UnitFactory::createAsteroid(
filename.c_str(),
faction, fg, fg->nr_ships-1,
1425 ast->SetSerial( serial );
1428 xml->
moons.push_back( enh = (Planet*) UnitFactory::createEnhancement(
filename.c_str(),
faction, string(
"" ) ) );
1429 enh->SetSerial( serial );
1433 for (
unsigned int i = 0; i < dest.size(); ++i)
1434 un->AddDestination( dest[i] );
1442 if (elem ==
UNIT &&
xml->
moons.back()->faction != neutralfaction) {
1444 xml->
moons.back()->EnqueueAI(
new Orders::FireAt( 15 ) );
1445 }
else if (scalex < 0 && elem !=
ASTEROID) {
1446 SetSubunitRotation(
xml->
moons.back(), -scalex );
1460 using namespace StarXML;
1471 if (p->isUnit() == PLANETPTR)
1497 using namespace VSFileSystem;
1501 bool autogenerated =
false;
1507 autogenerated =
false;
1513 printf(
"StarSystem: file not found %s\n", file.c_str() );
1532 XML_Parser parser = XML_ParserCreate( NULL );
1533 XML_SetUserData( parser,
this );
1538 XML_Parse( parser, (fcontents).c_str(),
f.
Size(), 1 );
1541 XML_ParserFree( parser );
1543 for (i = 0; i <
xml->
moons.size(); ++i) {
1544 if (
xml->
moons[i]->isUnit() == PLANETPTR) {
1546 for ( Planet::PlanetIterator iter( (Planet*)
xml->
moons[i] ); (un = *iter); iter.advance() )