45 #define strcasecmp stricmp
53 #define DEBUG_MESH_ANI
65 using namespace Orders;
91 FaceCamera = Animating = missilelock = InWarp = unused1 = WarpRamping = NoDamageParticles = 0;
92 specInterdictionOnline = 1;
93 NumAnimationPoints = 0;
95 MinWarpMultiplier = MaxWarpMultiplier = 1;
100 graphicOptions.FaceCamera = 1;
105 attack_preference =
c;
116 if ( !SubUnits.empty() ) {
117 un_fiter iter = SubUnits.fastIterator();
119 while ( (un = *iter) ) {
128 return active == activeStarSystem;
132 class StarSystem* &previouslyActiveStarSystem,
133 bool DoSightAndSound )
146 return AutoPilotToErrorMessage( un, automaticenergyrealloc, tmp );
151 afterburnenergy = aft;
171 Vector VelocityRef( 0, 0, 0 );
179 Vector vel = cumulative_velocity-VelocityRef;
180 float speed = vel.Magnitude();
184 Vector facing = cumulative_transformation_matrix.getR();
185 float ang = facing.Dot( veldir );
186 float warpfield = graphicOptions.WarpFieldStrength;
187 if (ang < 0) warpfield = 1./warpfield;
188 return ang*facing*speed*(warpfield-1)+vel+VelocityRef;
189 }
else {
return VelocityRef; }
194 prev_physical_state.position = curr_physical_state.position = pos;
199 float *nullvar = NULL;
200 return DealDamageToHullReturnArmor( pnt, Damage, nullvar );
206 curr_physical_state.to_matrix( m );
215 GetOrientation( p, q, r );
216 Vector res( NetLocalForce.i*p+NetLocalForce.j*q+NetLocalForce.k*r );
217 if (NetForce.i || NetForce.j || NetForce.k)
219 return res/GetMass();
225 GetOrientation( p, q, r );
226 Vector lref( ref*p, ref*q, ref*r );
227 float tp = (lref.i == 0) ? 0 : fabs(
Limits().
lateral/lref.i );
230 float trqmin = (tr < tq) ? tr : tq;
231 float tm = tp < trqmin ? tp : trqmin;
232 return lref.Magnitude()*tm/GetMass();
249 if (cone && computer.radar.maxcone > -.98) {
251 mm = delta.Magnitude();
252 if ( (!lock) || ( !(TargetLocked() && computer.target == target) ) ) {
253 double tempmm = mm-target->
rSize();
255 if ( (ToLocalCoordinates(
Vector( delta.i, delta.j, delta.k ) ).k/tempmm) < computer.radar.maxcone && cone )
262 if ( ( ( mm-rSize()-target->
rSize() ) > computer.radar.maxrange ) || target->
rSize() < computer.radar.mintargetsize ) {
272 return computer.target.GetUnit();
277 return computer.velocity_ref.GetUnit();
282 return computer.threat.GetUnit();
292 #ifdef CONTAINER_DEBUG
300 this->old_state.setPosition( this->curr_physical_state.position );
301 this->old_state.setOrientation( this->curr_physical_state.orientation );
302 this->old_state.setVelocity( this->Velocity );
303 this->old_state.setAcceleration( this->net_accel );
308 static bool useProjectile =
319 #define damagelevel hullpercent
322 static float flickerofftime =
324 static float minflickercycle =
326 static float flickeronprob =
328 static float hullfornoflicker =
331 if (diff > flickertime) {
336 if (tmpflicker < minflickercycle)
337 tmpflicker = minflickercycle;
338 diff = fmod( diff, tmpflicker );
341 unsigned int thus = ( (
unsigned int) (
size_t) un )>>2;
342 thus = thus%( (
unsigned int) tmpflicker );
343 diff = fmod( diff+thus, tmpflicker );
344 if (flickerofftime > diff) {
345 if (damagelevel > hullfornoflicker)
359 return norm*vel.Magnitude();
362 #define INVERSEFORCEDISTANCE 5400
367 Unit *un = dockingUn;
369 if (whichdockport != -1) {
373 if (un->
ForceDock( thus, whichdockport ) > 0) {
392 const Vector &smallnormal,
398 smalle->
reactToCollision(
this, smalllocation, smallnormal, biglocation, bignormal, dist );
403 if (crash_dock_unit) {
404 Unit *dockingun = smalle;
412 static bool crash_dock_hangar =
420 if ( !jumpReactToCollision( smalle ) ) {
421 static float kilojoules_per_damage =
423 static float collision_scale_factor =
426 static float mintime =
428 float m1 = smalle->
GetMass(), m2 = GetMass();
429 if (m1 < 1
e-6
f || m2 < 1
e-6
f) {
430 if (m1 <= 0) m1 = 0.0f;
431 if (m2 <= 0) m2 = 0.0f;
437 Vector big_velocity = GetVelocity()-GetAngularVelocity().Cross( biglocation-Position() );
440 Vector orthoz = ( (m2*bignormal)-(m1*smallnormal) ).Normalize();
446 Matrix fromNewRef( orthox, orthoy, orthoz );
447 Matrix toNewRef = fromNewRef;
454 Vector Inelastic_vf = ( m1/(m1+m2) )*small_velocity+( m2/(m1+m2) )*big_velocity;
456 small_velocity_aligned.k = (small_velocity_aligned.k*(m1-m2)/(m1+m2)+( 2.0f*m2/(m1+m2) )*big_velocity_aligned.k);
457 big_velocity_aligned.k = (big_velocity_aligned.k*(m2-
m1)/(m1+m2)+( 2.0f*m1/(m1+m2) )*small_velocity_aligned.k);
458 Vector SmallerElastic_vf =
Transform( fromNewRef, small_velocity_aligned );
469 bool isnotplayerorhasbeenmintime =
true;
474 Vector ThisFinalVelocity = inelastic_scale*Inelastic_vf+(1.0f-inelastic_scale)*ThisElastic_vf;
475 Vector SmallerFinalVelocity = inelastic_scale*Inelastic_vf+(1.0f-inelastic_scale)*SmallerElastic_vf;
481 float LargeDeltaE = (0.5f)*m2*(ThisFinalVelocity-ThisElastic_vf).MagnitudeSquared();
483 float SmallDeltaE = (0.5f)*m1*(SmallerFinalVelocity-SmallerElastic_vf).MagnitudeSquared();
485 float large_damage = (0.25f*SmallDeltaE+0.75f*LargeDeltaE)/kilojoules_per_damage*collision_scale_factor;
486 float small_damage = (0.25f*LargeDeltaE+0.75f*SmallDeltaE)/kilojoules_per_damage*collision_scale_factor;
493 (SmallerFinalVelocity
494 -small_velocity)*smalle->
GetMass()
501 isnotplayerorhasbeenmintime =
false;
507 isnotplayerorhasbeenmintime =
false;
512 this->ApplyForce( thisforce-smforce );
518 static float maxTorqueMultiplier =
520 static float maxForceMultiplier =
525 Vector force = smforce-torque;
529 float maxTorque = maxTorqueMultiplier*(smalle->
limits.
yaw
534 float tMag = torque.Magnitude();
535 float fMag = force.Magnitude();
536 if (tMag > maxTorque)
537 torque *= (maxTorque/tMag);
539 force *= (maxForce/fMag);
543 if ( (this->isUnit() !=
MISSILEPTR) && isnotplayerorhasbeenmintime ) {
545 Vector torque = thisforce/(radial_size*radial_size);
546 Vector force = thisforce-torque;
547 float maxForce = maxForceMultiplier*(limits.forward+limits.retro
548 +limits.lateral+limits.vertical);
549 float maxTorque = maxTorqueMultiplier*(limits.yaw+limits.pitch+limits.roll);
553 float tMag = torque.Magnitude();
554 float fMag = force.Magnitude();
555 if (tMag > maxTorque)
556 torque *= (maxTorque/tMag);
558 force *= (maxForce/fMag);
559 this->ApplyTorque( torque, biglocation );
560 this->ApplyForce( force-torque );
566 bool dealdamage =
true;
569 float smallmag = smalldelta.Magnitude();
571 float thismag = thisdelta.Magnitude();
572 static float collision_hack_distance =
574 static float front_collision_hack_distance =
576 if (thcp == NULL && smcp == NULL) {
577 if (smallmag > collision_hack_distance+this->rSize() && thismag > collision_hack_distance) {
578 static float front_collision_hack_angle =
581 "front_collision_avoidance_hack_angle",
585 if (smallmag > front_collision_hack_distance+this->rSize() && thismag > front_collision_hack_distance)
595 static bool collisionDamageToAI =
597 if (!collisionDamageToAI)
608 != NULL ? this->
owner : this );
610 if (smalle->
faction != upgradefac) {
611 this->ApplyDamage( smalllocation.Cast(), smallnormal, large_damage,
this,
GFXColor( 1,
615 != NULL ? smalle->
owner : smalle );
623 if ( ( ( docked&(DOCKED|DOCKED_INSIDE) ) == 0 ) && jump.drive != -2 )
624 jump.drive = destination;
643 return (
float) rand()/(
float) RAND_MAX;
651 static unsigned long int seed = 2531011;
654 unsigned int ans = (
unsigned int) tmp;
656 if ( seed < (
unsigned long int) (4294967295u*tmp) )
681 printf(
"%ld died", (
long) un );
692 return filename.substr( 0, filename.find(
"." ) );
697 char *retval = strdup( filename );
698 if (retval[0] ==
'\0')
700 if (retval[1] ==
'\0')
702 for (
int i = 0; retval[
i] != 0; ++
i)
703 if (retval[
i] ==
'.') {
721 result +=
"CAPSHIP-LIGHT ";
723 result +=
"CAPSHIP-HEAVY ";
725 result +=
"SPECIAL ";
727 result +=
"LIGHT-MISSILE ";
729 result +=
"MEDIUM-MISSILE ";
731 result +=
"HEAVY-MISSILE ";
733 result +=
"LIGHT-CAPSHIP-MISSILE ";
735 result +=
"HEAVY-CAPSHIP-MISSILE ";
737 result +=
"SPECIAL-MISSILE ";
739 result +=
"AUTOTRACKING ";
794 std::string unitModifications,
805 Init( filename, SubU, faction, unitModifications, flightgrp, fg_subnumber, netxml );
857 #ifndef NO_MOUNT_STAR
858 for (vector< Mount* >::iterator jj =
mounts.begin(); jj !=
mounts.end(); ++jj)
868 for (
unsigned int meshcount = 0; meshcount <
meshdata.size(); ++meshcount)
989 #ifdef CONTAINER_DEBUG
1053 corner_max.Set( -FLT_MAX, -FLT_MAX, -FLT_MAX );
1056 static float default_shield_tightness =
1060 default_shield_tightness;
1165 for (
unsigned int damageiterator = 0; damageiterator < numg; ++damageiterator)
1171 using namespace VSFileSystem;
1173 CSVRow GetUnitRow(
string filename,
bool subu,
int faction,
bool readLast,
bool &read );
1175 static std::string csvUnit( std::string un )
1177 string::size_type
i = un.find_last_of(
"." );
1178 string::size_type del = un.find_last_of(
"/\\:" );
1179 if (i == std::string::npos)
1181 if (del == std::string::npos || del < i)
1182 return un.substr( 0, i )+
".csv";
1189 std::string unitModifications,
1197 graphicOptions.SubUnit = SubU ? 1 : 0;
1198 graphicOptions.Animating = 1;
1199 graphicOptions.RecurseIntoSubUnitsOnCollision = !isSubUnit();
1201 SetFg( flightgrp, fg_subnumber );
1207 bool foundFile =
false;
1208 if (netxml == NULL) {
1209 if (unitModifications.length() != 0) {
1211 string filepath(
"" );
1214 if ( nonautosave.empty() ) {
1216 filepath = unitModifications+
"/"+string( filename );
1219 filepath = nonautosave+
"/"+string( filename );
1237 if (netxml == NULL) {
1241 if (UNITTAB) {}
else {
1264 unitRow =
GetUnitRow( filename, SubU, faction,
true, foundFile );
1266 foundFile = (err <=
Ok);
1267 this->filename = filename;
1269 bool istemplate = ( string::npos != ( string( filename ).find(
".template" ) ) );
1271 if ( !istemplate || (istemplate && usingtemplates) )
1272 cout<<
"Unit file "<<filename<<
" not found"<<endl;
1274 meshdata.push_back( NULL );
1275 this->fullname = filename;
1276 this->name = string(
"LOAD_FAILED" );
1277 calculate_extent(
false );
1283 pilot->SetComm(
this );
1286 this->name = this->filename;
1295 tmpbool ).getRoot() : unitRow.
getRoot() );
1298 LoadRow( unitRow, unitModifications, netxml );
1316 calculate_extent(
false );
1317 pilot->SetComm(
this );
1320 bool initsucc = pMeshAnimation->Init(filename, faction, flightgrp);
1322 pMeshAnimation->SetAniSpeed( 0.05 );
1323 pMeshAnimation->StartAnimation();
1325 delete pMeshAnimation;
1326 pMeshAnimation = NULL;
1334 Mesh *shield = meshdata.empty() ? NULL : meshdata.back();
1335 for (
int i = 0; i < nummesh(); ++i)
1336 ret.push_back( meshdata[i] );
1338 meshdata.push_back( shield );
1345 return a > b ? a :
b;
1350 bool accessory = tur->
name.get().find(
"accessory" ) != string::npos;
1362 corner_min =
Vector( FLT_MAX, FLT_MAX, FLT_MAX );
1363 corner_max =
Vector( -FLT_MAX, -FLT_MAX, -FLT_MAX );
1364 for (a = 0; a < nummesh(); ++
a) {
1365 corner_min = corner_min.Min( meshdata[a]->corner_min() );
1366 corner_max = corner_max.Max( meshdata[a]->corner_max() );
1369 for (
un_kiter iter = SubUnits.constIterator(); (un = *iter); ++iter) {
1373 if ( corner_min.i == FLT_MAX || corner_max.i == -FLT_MAX || !
FINITE( corner_min.i ) || !
FINITE( corner_max.i ) ) {
1375 corner_min.Set( 0, 0, 0 );
1376 corner_max.Set( 0, 0, 0 );
1378 float tmp1 = corner_min.Magnitude();
1379 float tmp2 = corner_max.Magnitude();
1380 radial_size = tmp1 > tmp2 ? tmp1 : tmp2;
1382 if ( !isSubUnit() && update_collide_queue && (maxhull > 0) ) {
1386 radial_size =
tmpmax(
tmpmax( corner_max.i, corner_max.j ), corner_max.k );
1391 if (activeStarSystem) {
1392 return activeStarSystem;
1404 if (activeStarSystem) {
1405 return activeStarSystem;
1422 void Unit::Fire(
unsigned int weapon_type_bitmask,
bool listen_to_owner )
1427 if ( (cloaking >= 0 && can_fire_in_cloak ==
false) || (graphicOptions.InWarp && can_fire_in_spec ==
false) ) {
1431 unsigned int mountssize = mounts.size();
1433 vector< int >gunFireRequests;
1434 vector< int >missileFireRequests;
1435 vector< int >serverUnfireRequests;
1436 for (
unsigned int counter = 0; counter < mountssize; ++counter) {
1437 unsigned int index = counter;
1441 if (i->
bank ==
true) {
1442 unsigned int best =
index;
1444 for (j = index+1; j < mountssize; ++j) {
1448 serverUnfireRequests.push_back( j );
1453 serverUnfireRequests.push_back( j );
1456 if (mounts[j].bank ==
false) {
1469 const bool locked_missile = (mis && locked_on && lockable_weapon);
1470 const bool missile_and_want_to_fire_missiles = ( mis && (weapon_type_bitmask&
ROLES::FIRE_MISSILES) );
1471 const bool gun_and_want_to_fire_guns = ( (!mis) && (weapon_type_bitmask&
ROLES::FIRE_GUNS) );
1472 if (verbose_debug && missile_and_want_to_fire_missiles && locked_missile)
1475 (fire_non_autotrackers || autotracking_gun || locked_missile)
1477 && ( (locked_on && missile_and_want_to_fire_missiles) || gun_and_want_to_fire_guns );
1483 serverUnfireRequests.push_back( index );
1491 if (!want_to_fire) {
1493 serverUnfireRequests.push_back( index );
1505 missileFireRequests.push_back( index );
1507 gunFireRequests.push_back( index );
1515 if ( i->
Fire(
this,
owner == NULL ?
this :
owner, mis, listen_to_owner ) ) {
1517 if (missile_and_want_to_fire_missiles) {
1526 vector< int >indexvec;
1527 indexvec.push_back( index );
1529 this->getStarSystem()->GetZone() );
1531 gunFireRequests.push_back( index );
1551 if ( want_to_fire ==
false
1555 serverUnfireRequests.push_back( index );
1558 if ( !gunFireRequests.empty() ) {
1560 VSServer->
BroadcastFire( this->serial, gunFireRequests, 0, this->energy, this->getStarSystem()->GetZone() );
1566 if (
SERVER && !serverUnfireRequests.empty() )
1569 if ( !
SERVER && !missileFireRequests.empty() ) {
1577 if (flightgroup != NULL) {
1579 sprintf( buffer,
"-%d", flightgroup_subnumber );
1580 return flightgroup->name+
buffer;
1589 for (
un_iter ui = getSubUnits(); (*ui) != NULL; ++ui)
1590 (*ui)->SetFaction( faction );
1602 flightgroup_subnumber = fg_subnumber;
1607 pImage->destination.push_back( dest );
1612 return pImage->destination;
1617 float trackingcone = 0;
1618 missilelock =
false;
1619 for (
int i = 0; i < GetNumMounts(); ++i) {
1621 trackingcone = computer.radar.trackingcone;
1622 if (mounts[i].status ==
Mount::ACTIVE && mounts[i].type->LockTime > 0 && mounts[i].time_to_lock <= 0)
1625 return trackingcone;
1634 if ( GetNumMounts() ) {
1640 for (
int i = 0; i < GetNumMounts(); ++i)
1642 if (
isMissile( mounts[i].type ) ==
false) {
1643 if (mounts[i].type->Range > grange)
1644 grange = mounts[i].type->Range;
1646 speed += mounts[i].type->Speed;
1650 }
else if (
isMissile( mounts[i].type ) ) {
1651 if (mounts[i].type->Range > mrange)
1652 mrange = mounts[i].type->Range;
1659 speed = speed/nummt;
1662 this->missilerange = mrange;
1663 this->gunrange = grange;
1664 this->gunspeed =
speed;
1669 if (speed == FLT_MAX)
1670 return this->Position();
1671 float difficultyscale = 1;
1673 GetVelocityDifficultyMult( difficultyscale );
1674 velocity = (cumulative_velocity.Scale( difficultyscale )-velocity);
1675 QVector posit( this->Position()-absposit );
1677 for (
unsigned int i = 0; i < 3; ++i) {
1680 time = curguess.Magnitude()/
speed;
1683 curguess = posit+GetVelocity().Cast().Scale( time );
1685 curguess = posit+velocity.Scale( time ).Cast();
1687 return curguess+absposit;
1698 return close_autotrack_cone;
1704 static float close_enough_to_autotrack =
1707 float movesqr = close_enough_to_autotrack
1709 if (dissqr < movesqr && movesqr > 0) {
1710 cone =
CloseEnoughCone( me )*(movesqr-dissqr)/movesqr+1*dissqr/movesqr;
1724 return acos( mycos );
1729 Vector Normal( cumulative_transformation_matrix.getR() );
1730 Normalize( Normal );
1731 QVector totarget( targ->
PositionITTS( cumulative_transformation.position, cumulative_velocity, speed,
false ) );
1732 totarget = totarget-cumulative_transformation.position;
1733 dist = totarget.Magnitude();
1737 tmpmax(
tmpmax( computer.max_yaw_left, computer.max_yaw_right ),
tmpmax( computer.max_pitch_up, computer.max_pitch_down ) );
1741 sqrtf( AngularVelocity.i*AngularVelocity.i+AngularVelocity.j*AngularVelocity.j ) ) );
1742 float ittsangle =
safeacos( Normal.Cast().Dot( totarget.Scale( 1./totarget.Magnitude() ) ) );
1744 float radangle =
safeacos( edgeLocation.Cast().Scale( 1./edgeLocation.Magnitude() ).Dot( totarget.Normalize() ) );
1745 float rv = ittsangle-radangle-(turnmargin ? turnangle : 0);
1747 float rsize = targ->
rSize()+rSize();
1751 dist = (dist-rsize)/range;
1755 if (!
FINITE( dist ) || dist < 0)
1757 return (rv < 0) ? 1 :
cos( rv );
1766 for (
int i = 0; i < GetNumMounts(); ++i) {
1767 float tmpdist = .001;
1768 Transformation finaltrans( mounts[i].GetMountOrientation(), mounts[i].GetMountLocation().Cast() );
1769 finaltrans.
Compose( cumulative_transformation, cumulative_transformation_matrix );
1775 tmpcos = Normal.Dot( totarget.Cast() );
1776 tmpdist = totarget.Magnitude();
1778 tmpcos = tmpdist*tmpdist-tmpcos*tmpcos;
1780 tmpcos = targ->
rSize()/tmpcos;
1785 tmpdist /= mounts[i].type->Range;
1786 if (tmpdist < 1 || tmpdist < dist) {
1787 if (tmpcos-tmpdist/2 > retval-dist/2) {
1796 #define PARANOIA (0.4f)
1801 computer.threatlevel = danger;
1802 computer.threat.SetUnit( NULL );
1803 }
else if (targ->
owner !=
this && this->owner != targ && danger >
PARANOIA && danger > computer.threatlevel) {
1804 computer.threat.SetUnit( targ );
1805 computer.threatlevel = danger;
1811 return pImage->cockpitImage.get();
1829 for (
unsigned int j = 0;
j < uhn->
mounts.size(); ++
j)
1835 return SubUnits.createIterator();
1840 return SubUnits.constIterator();
1846 invisible &= (~INVISCAMERA);
1848 invisible |= INVISCAMERA;
1854 invisible &= (~INVISUNIT);
1856 invisible |= INVISUNIT;
1862 invisible &= (~INVISGLOW);
1864 invisible |= INVISGLOW;
1879 if (s.find(
".py" ) != string::npos) {
1884 if (s.length() > 0) {
1885 if (*s.begin() ==
'_') {
1889 if (s ==
"ikarus") {
1892 string ai_agg = s+
".agg.xml";
1905 aistate->eraseType( type );
1912 PrimeOrders( pyai );
1913 }
else if (!aistate) {
1948 aistate =
new Order;
1958 Vector vec( 0, 0, 10000 );
1963 aistate->SetParent(
this );
1970 aistate->ReplaceOrder( newAI );
1979 aistate->EnqueueOrder( newAI );
1988 aistate->EnqueueOrderFirst( newAI );
1996 Unit *leader = flightgroup->leader.GetUnit();
2000 flightgroup->leader_decision = flightgroup->nr_ships;
2001 flightgroup->leader.SetUnit(
this );
2003 flightgroup->leader_decision--;
2005 if (aistate) aistate->Execute();
2006 if ( !SubUnits.empty() ) {
2009 while ( (un = *iter) ) {
2019 return getFgID()+
":"+getAIState()->createFullOrderDescription( 0 ).c_str();
2028 mmrange = missilerange;
2033 return pilot->GetEffectiveRelationship(
this, targ );
2040 target_fgid[2] = tertiary;
2053 int found_attackers = 1000;
2054 for (
GameUnit *other_unit = NULL; other_unit = *uiter; ++uiter) {
2055 string other_fgid = other_unit->getFgID();
2056 if ( other_unit->matchesFg( target_fgid[which_target] ) ) {
2059 int num_attackers = other_unit->getNumAttackers();
2060 if (num_attackers < found_attackers) {
2062 found_target = other_unit;
2063 found_attackers = num_attackers;
2064 setTarget( found_target );
2068 if (found_target == NULL) {
2070 if (which_target <= 1)
2071 ReTargetFg( which_target+1 );
2083 if (talkinturrets) {
2085 for (
un_iter iter = getSubUnits(); (un = *iter); ++iter) {
2094 for (
un_iter iter = getSubUnits(); (un = *iter); ++iter) {
2110 for (
un_iter iter = getSubUnits(); (un = *iter); ++iter) {
2139 if ( xyz.size() && (sscanf( xyz.c_str(),
"%lf %lf %lf", &pos.i, &pos.j, &pos.k ) >= 3) )
2147 if (pos.i == 0 && pos.j == 0 && pos.k == 0)
2149 QVector posnorm = pos.Normalize();
2150 posnorm.Normalize();
2152 if (cur.i == 0 && cur.j == 0 && cur.k == 0)
2154 double closest_distance = 0.0;
2155 std::string closest_system;
2158 vsUMap< std::string, class GalaxyXML::SGalaxy >::iterator
j, i = sectors->begin();
2159 for (; i != sectors->end(); ++i) {
2161 for (j = systems->begin(); j != systems->end(); ++j) {
2162 std::string place = j->second[
"xyz"];
2163 if ( place.length() ) {
2165 sscanf( place.c_str(),
"%lf %lf %lf", &pos2.i, &pos2.j, &pos2.k );
2166 if ( (pos2.i != 0 || pos2.j != 0 || pos2.k != 0) && (pos2.i != cur.i || pos2.j != cur.j || pos2.k != cur.k) ) {
2170 double test = posnorm.Dot( norm );
2173 double tmp = dir.MagnitudeSquared()/test/test/
test;
2176 if ( whereto.length() == 1+i->first.length()+j->first.length() ) {
2177 if (whereto.substr( 0,
2178 i->first.length() ) == i->first && whereto.substr( i->first.length()+1 )
2180 static float SystemWarpTargetBonus =
2182 "target_distance_to_warp_bonus",
2184 tmp /= SystemWarpTargetBonus;
2188 if (tmp < closest_distance || closest_distance == 0) {
2189 closest_distance = tmp;
2190 closest_system = i->first+
"/"+j->first;
2197 return closest_system;
2209 static float EXTRA_CARGO_SPACE_DRAG =
2215 this->last_processed_sqs = cur_sim_frame;
2216 this->cur_sim_queue_slot = (cur_sim_frame+this->sim_atom_multiplier)%
SIM_QUEUE_SIZE;
2218 this->Explode(
true, 0 );
2221 if (docked&DOCKING_UNITS)
2222 PerformDockingOperations();
2226 if (cloaking >= cloakmin) {
2227 static bool warp_energy_for_cloak =
2229 if ( pImage->cloakenergy*
SIMULATION_ATOM > (warp_energy_for_cloak ? warpenergy : energy) ) {
2233 if (pImage->cloakrate > 0 || cloaking == cloakmin) {
2234 if (warp_energy_for_cloak)
2239 if (cloaking > cloakmin) {
2240 AUDAdjustSound( sound->cloak, cumulative_transformation.position, cumulative_velocity );
2242 if ( (cloaking == (2147483647)
2243 && pImage->cloakrate > 0) || (cloaking == cloakmin+1 && pImage->cloakrate < 0) )
2247 if (cloaking <= cloakmin && pImage->cloakrate > 0)
2248 cloaking = cloakmin;
2249 if (cloaking < 0 && pImage->cloakrate < 0) {
2250 cloaking = -2147483647-1;
2260 if ( !( docked&(DOCKED|DOCKED_INSIDE) ) )
2262 prev_physical_state = curr_physical_state;
2266 SetPlanetOrbitData( NULL );
2268 planet->pps = planet->cps;
2272 if (resolveforces) {
2274 net_accel = ResolveForces( trans, transmat );
2275 if (Velocity.i > VELOCITY_MAX)
2276 Velocity.i = VELOCITY_MAX;
2278 else if (Velocity.i < -VELOCITY_MAX)
2279 Velocity.i = -VELOCITY_MAX;
2280 if (Velocity.j > VELOCITY_MAX)
2281 Velocity.j = VELOCITY_MAX;
2283 else if (Velocity.j < -VELOCITY_MAX)
2284 Velocity.j = -VELOCITY_MAX;
2285 if (Velocity.k > VELOCITY_MAX)
2286 Velocity.k = VELOCITY_MAX;
2288 else if (Velocity.k < -VELOCITY_MAX)
2289 Velocity.k = -VELOCITY_MAX;
2292 Cockpit *player_cockpit = GetVelocityDifficultyMult( difficulty );
2294 this->UpdatePhysics2( trans, old_physical_state, net_accel, difficulty, transmat, cum_vel, lastframe, uc );
2295 if (EXTRA_CARGO_SPACE_DRAG > 0) {
2297 if ( (this->faction == upgfac) || (this->name ==
"eject") || (this->name ==
"Pilot") )
2298 Velocity = Velocity*(1-EXTRA_CARGO_SPACE_DRAG);
2301 Velocity = Velocity*(1-SPACE_DRAG);
2302 float dist_sqr_to_target = FLT_MAX;
2304 bool increase_locking =
false;
2305 if (target && cloaking < 0 ) {
2308 dist_sqr_to_target = TargetPos.MagnitudeSquared();
2309 TargetPos.Normalize();
2310 if (TargetPos.k > computer.radar.lockcone)
2311 increase_locking =
true;
2314 if (!computer.force_velocity_ref && activeStarSystem) {
2315 Unit *nextVelRef = activeStarSystem->nextSignificantUnit();
2317 if ( computer.velocity_ref.GetUnit() ) {
2320 if (next_dist < dist)
2321 computer.velocity_ref = nextVelRef;
2323 computer.velocity_ref = nextVelRef;
2328 static string LockingSoundName =
vs_config->
getVariable(
"unitaudio",
"locking",
"locking.wav" );
2330 static string LockingSoundTorpName =
vs_config->
getVariable(
"unitaudio",
"locking_torp",
"locking.wav" );
2334 bool locking =
false;
2335 bool touched =
false;
2336 for (
int i = 0; (
int) i < GetNumMounts(); ++i) {
2342 if ( increase_locking && (dist_sqr_to_target < mounts[i].type->Range*mounts[i].type->Range) ) {
2345 if (!player_cockpit) {
2347 mounts[i].time_to_lock = -1;
2349 int LockingPlay = LockingSound;
2352 static bool LockTrumpsMusic =
2355 static bool TorpLockTrumpsMusic =
2357 if (mounts[i].type->LockTime > 0) {
2361 LockingPlay = LockingSoundTorp;
2364 LockingPlay = LockingSound;
2365 if (mounts[i].time_to_lock > -
SIMULATION_ATOM && mounts[i].time_to_lock <= 0) {
2373 }
else if (mounts[i].time_to_lock > 0) {
2376 if (LockingPlay == LockingSoundTorp)
2387 }
else if (mounts[i].ammo != 0) {
2388 mounts[i].time_to_lock = mounts[i].type->LockTime;
2390 }
else if (mounts[i].ammo != 0) {
2391 mounts[i].time_to_lock = mounts[i].type->LockTime;
2394 if (mounts[i].ref.gun) {
2395 static bool must_lock_to_autotrack =
2399 && (mounts[i].time_to_lock <= 0)
2400 && (player_cockpit == NULL || TargetLocked() || !must_lock_to_autotrack)
2401 && (computer.radar.trackingactive) ) ? target : NULL;
2402 float trackingcone = computer.radar.trackingcone;
2405 if (computer.radar.trackingcone < trackingcone)
2406 trackingcone = computer.radar.trackingcone;
2409 mounts[i].ref.gun->
UpdatePhysics( cumulative_transformation,
2410 cumulative_transformation_matrix,
2414 (HeatSink ? HeatSink : 1.0f)*mounts[i].functionality,
2419 mounts[i].ref.refire +=
SIMULATION_ATOM*(HeatSink ? HeatSink : 1.0f)*mounts[i].functionality;
2424 t1 = prev_physical_state;
2425 t1.
Compose( trans, transmat );
2428 static bool must_lock_to_autotrack =
2431 && computer.radar.trackingactive
2433 || player_cockpit == NULL
2435 || !must_lock_to_autotrack ) )
2436 autotrack = computer.itts ? 2 : 1;
2437 float trackingcone = computer.radar.trackingcone;
2440 if (trackingcone > computer.radar.trackingcone)
2441 trackingcone = computer.radar.trackingcone;
2448 collidemap[locind]->begin();
2449 if ( !mounts[i].PhysicsAlignedFire(
this, t1, m1, cumulative_velocity,
2450 (!isSubUnit() ||
owner == NULL) ?
this :
owner, target, autotrack,
2456 }
else if ( mounts[i].processed ==
Mount::UNFIRED || mounts[i].ref.refire > 2*mounts[i].type->Refire() ) {
2458 mounts[i].PhysicsAlignedUnfire();
2461 if (locking ==
false && touched ==
true) {
2473 UpdateSubunitPhysics( cumulative_transformation,
2474 cumulative_transformation_matrix,
2475 cumulative_velocity,
2480 static bool warp_is_interstellar =
2482 if ( warp_is_interstellar
2485 bool jumpDirect =
false;
2490 if ( !sys.empty() ) {
2499 curr_physical_state.position ),
true,
true );
2504 dead &= (pImage->pExplosion == NULL);
2508 if ( !isSubUnit() ) {
2510 if (
is_null( this->location[locind] ) )
2511 this->getStarSystem()->collidemap[locind]->insert(
Collidable(
this ) );
2526 if ( !SubUnits.empty() ) {
2529 float basesimatom = (this->sim_atom_multiplier ? backup/(
float) this->sim_atom_multiplier : backup);
2531 for (
un_iter iter = getSubUnits(); (su = *iter); ++iter)
2546 if (do_subunit_scheduling) {
2549 priority = (priority+rand()%priority)/2;
2550 if (priority < 1) priority = 1;
2561 cumulative_transformation,
2562 cumulative_transformation_matrix,
2563 cumulative_velocity,
2576 const Vector &CumulativeVelocity,
2582 cumulative_transformation_matrix,
2583 cumulative_velocity,
2598 static float bigwarphack =
2609 static double upcurvek = warpcruisemult/pow( (warpregion1-warpregion0), curvedegree );
2611 static float def_inv_interdiction = 1.
2615 Unit *testthis = NULL;
2622 (planet = *iter) || testthis;
2624 if ( !planet || !planet->Killed() ) {
2625 if (planet == NULL) {
2633 shiphack = def_inv_interdiction;
2634 if ( planet->specInterdiction != 0 && planet->graphicOptions.specInterdictionOnline != 0
2635 && (planet->specInterdiction > 0 || count_negative_warp_units) ) {
2636 shiphack = 1/fabs( planet->specInterdiction );
2643 float multipliertemp = 1;
2644 float minsizeeffect = (planet->rSize() > smallwarphack) ? planet->rSize() : smallwarphack;
2646 if (effectiverad > bigwarphack)
2647 effectiverad = bigwarphack;
2649 double udist = dir.Magnitude();
2651 if ( planet->isPlanet() && udist < (1<<28) )
2654 double dist = udist;
2655 if (dist < 0) dist = 0;
2657 if ( dist > (effectiverad+warpregion0) )
2658 multipliertemp = pow( (dist-effectiverad-warpregion0), curvedegree )*upcurvek;
2661 if (multipliertemp < minmultiplier) {
2662 minmultiplier = multipliertemp;
2663 *nearest_unit = planet;
2671 return minmultiplier;
2676 Vector VelocityRef( 0, 0, 0 );
2678 Unit *vr = computer.velocity_ref.GetUnit();
2685 static float compwarprampuptime =
2688 Vector v = Velocity-VelocityRef;
2689 float len = v.Magnitude();
2690 float lastWarpField = graphicOptions.WarpFieldStrength;
2692 v = v*( cumulative_transformation_matrix.getR().Dot( v*(1./len) ) );
2694 float warprampuptime = playa ? humanwarprampuptime : compwarprampuptime;
2696 if (graphicOptions.WarpRamping) {
2698 if (graphicOptions.InWarp == 1)
2699 graphicOptions.RampCounter = warprampuptime;
2702 graphicOptions.RampCounter = warprampdowntime;
2703 graphicOptions.WarpRamping = 0;
2705 if (graphicOptions.InWarp == 1 || graphicOptions.RampCounter != 0) {
2707 static float warpMultiplierMin =
2710 static float warpMultiplierMax =
2715 float minmultiplier = warpMultiplierMax*graphicOptions.MaxWarpMultiplier;
2716 Unit *nearest_unit = NULL;
2719 if (graphicOptions.RampCounter != 0) {
2721 if (graphicOptions.RampCounter <= 0)
2722 graphicOptions.RampCounter = 0;
2723 if (graphicOptions.InWarp == 0 && graphicOptions.RampCounter > warprampdowntime)
2724 graphicOptions.RampCounter = (1-graphicOptions.RampCounter/warprampuptime)*warprampdowntime;
2725 if (graphicOptions.InWarp == 1 && graphicOptions.RampCounter > warprampuptime)
2726 graphicOptions.RampCounter = warprampuptime;
2727 rampmult = (graphicOptions.InWarp) ? 1.0
2728 -( (graphicOptions.RampCounter
2730 *(graphicOptions.RampCounter
2731 /warprampuptime) ) : (graphicOptions.RampCounter
2732 /warprampdowntime)*(graphicOptions.RampCounter/warprampdowntime);
2734 float minWarp = warpMultiplierMin*graphicOptions.MinWarpMultiplier;
2735 float maxWarp = warpMultiplierMax*graphicOptions.MaxWarpMultiplier;
2736 if (minmultiplier < minWarp)
2737 minmultiplier = minWarp;
2738 if (minmultiplier > maxWarp)
2739 minmultiplier = maxWarp;
2740 minmultiplier *= rampmult;
2741 if (minmultiplier < 1)
2744 float vmag =
sqrt( v.i*v.i+v.j*v.j+v.k*v.k );
2745 if (vmag > warpMaxEfVel) {
2746 v *= warpMaxEfVel/vmag;
2747 minmultiplier *= warpMaxEfVel/vmag;
2749 graphicOptions.WarpFieldStrength = minmultiplier;
2751 graphicOptions.WarpFieldStrength = 1;
2754 if (graphicOptions.WarpFieldStrength != 1.0)
2755 v = GetWarpVelocity();
2759 graphicOptions.WarpFieldStrength = lastWarpField*WARPMEMORYEFFECT+(1.0-WARPMEMORYEFFECT)*graphicOptions.WarpFieldStrength;
2760 curr_physical_state.position = curr_physical_state.position+(v*
SIMULATION_ATOM*difficulty).Cast();
2777 if (AngularVelocity.i || AngularVelocity.j || AngularVelocity.k)
2781 AddVelocity( difficulty );
2783 cumulative_transformation = curr_physical_state;
2784 cumulative_transformation.Compose( trans, transmat );
2785 cumulative_transformation.to_matrix( cumulative_transformation_matrix );
2800 float bdis = ( def-
RealPosition( goal ) ).MagnitudeSquared();
2801 for (
int i = -1; i <= 1; ++i)
2802 for (
int j = -1;
j <= 1; ++
j)
2803 for (
int k = -1;
k <= 1;
k += 2) {
2808 float tmag = ( tmp-
RealPosition( goal ) ).MagnitudeSquared();
2821 static std::string err =
2823 "#ff0000Asteroids Near#000000" ) );
2827 static std::string err =
2829 "#ff0000Planetary Hazard Near#000000" ) );
2833 static std::string err =
2835 "#ff0000Enemy Near#000000" ) );
2838 static std::string err =
2840 "#ff0000Starship Near#000000" ) );
2845 bool ignore_energy_requirements,
2846 std::string &failuremessage,
2847 int recursive_level )
2849 static bool auto_valid =
2852 static std::string err =
"No Insystem Jump";
2853 failuremessage = err;
2859 return AutoPilotToErrorMessage( targ, ignore_energy_requirements, failuremessage, recursive_level );
2861 if (warpenergy < jump.insysenergy)
2862 if (!ignore_energy_requirements)
2867 static float autopilot_term_distance =
2869 static float atd_no_enemies =
2873 static float autopilot_no_enemies_multiplier =
2875 if ( isSubUnit() ) {
2876 static std::string err =
"Return To Cockpit for Auto";
2877 failuremessage = err;
2886 float totallength = (start-end).
Magnitude();
2887 bool nanspace =
false;
2888 if ( !
FINITE( totallength ) ) {
2890 start =
QVector( 100000000.0, 100000000.0, 10000000000000.0 );
2892 if ( !
FINITE( totallength ) ) {
2893 end =
QVector( 200000000.0, 100000000.0, 10000000000000.0 );
2899 float totpercent = 1;
2900 if (totallength > 1) {
2907 float percent = (
getAutoRSize(
this,
this )+rSize()+target->
rSize()+apt)/totallength;
2908 float percentne = (
getAutoRSize(
this,
this )+rSize()+target->
rSize()+aptne)/totallength;
2913 endne = start*percentne+end*(1-percentne);
2918 totpercent *= (1-percent);
2919 end = start*percent+end*(1-percent);
2925 bool unsafe =
false;
2926 if ( (!teleport_autopilot) && (!nanspace) ) {
2928 bool ignore_friendlies =
true;
2930 static bool canflythruplanets =
2934 if (un !=
this && un != target) {
2942 if ( (nedis < trad*autopilot_no_enemies_multiplier
2943 || tdis <= trad*autopilot_no_enemies_multiplier) && un->
getRelation(
this ) < 0 ) {
2947 float intersection =
2950 ignore_friendlies )+un->
rSize() );
2951 if (intersection > 0) {
2953 end = start+(end-
start)*intersection;
2954 totpercent *= intersection;
2962 }
else if (!nanspace) {
2967 static float minasteroiddistance =
2975 bool nowhere =
false;
2976 if (
this != target) {
2977 if ( (end-start).MagnitudeSquared() < rSize()*rSize() ) {
2980 "#ff0000Already Near#000000" ) );
2983 warpenergy -= totpercent*jump.insysenergy;
2984 if (unsafe ==
false && totpercent == 0)
2987 if ( (sep-end).MagnitudeSquared() > 16*rSize()*rSize() )
2996 if (auto_turn_towards) {
2997 for (
int i = 0; i < 3; ++i) {
3001 GetOrientation( p, q, r );
3002 p = methem.Cross( r );
3003 float theta = p.Magnitude();
3004 if (theta*theta > .00001) {
3005 p *= (
asin( theta )/theta);
3007 GetOrientation( p, q, r );
3009 if (r.Dot( methem ) < 0)
3011 Velocity = methem*Velocity.Magnitude();
3014 static string insys_jump_ani =
vs_config->
getVariable(
"graphics",
"insys_jump_animation",
"warp.ani" );
3017 insys_jump_ani.length() ) {
3018 static bool docache =
true;
3023 static float insys_jump_ani_size =
3025 static float insys_jump_ani_growth =
3028 rSize()*insys_jump_ani_size, insys_jump_ani_growth );
3033 GetOrientation( p, q, r );
3039 if ( warptrail && (!nowhere) ) {
3044 SetCurPosition( sep );
3047 std::string followermessage;
3048 if (getFlightgroup() != NULL) {
3050 if (recursive_level > 0) {
3053 bool leadah = ( ff == getFlightgroup() );
3061 ignore_energy_requirements,
3063 recursive_level-1 );
3092 this->warpenergy = this->fuel;
3093 this->warpenergy -= (insys ? jump.insysenergy/bleedfactor : jump.energy)*time;
3094 if (this->warpenergy < 0)
3095 this->warpenergy = 0;
3097 this->fuel = this->warpenergy;
3104 this->warpenergy = this->fuel;
3105 this->warpenergy += (insys ? jump.insysenergy : jump.energy)*time;
3106 if (this->warpenergy > this->maxwarpenergy)
3107 this->warpenergy = this->maxwarpenergy;
3109 this->fuel = this->warpenergy;
3118 && nojumpinSPEC :
false;
3120 if ( !GetDestinations().empty() ) {
3122 if (!SPEC_interference || pImage->forcejump)
3131 || (ai_jump_cheat && cp == NULL)
3133 || pImage->forcejump ) {
3140 Unit *jumppoint =
this;
3155 if ( ( !SPEC_interference && (GetJumpStatus().drive >= 0
3156 && ( warpenergy >= GetJumpStatus().energy || (ai_jump_cheat && cp == NULL) )
3158 warpenergy -= GetJumpStatus().energy;
3159 DeactivateJumpDrive();
3160 Unit *jumppoint = smalle;
3180 if ( (player_cockpit) == NULL ) {
3184 return player_cockpit;
3189 double theta = axis.Magnitude();
3191 if (theta == 0)
return;
3193 float s =
cos( theta*.5 );
3197 curr_physical_state.orientation *= rot;
3198 if (limits.limitmin > -1) {
3200 curr_physical_state.orientation.to_matrix( mat );
3201 if (limits.structurelimits.Dot( mat.
getR() ) < limits.limitmin)
3202 curr_physical_state.orientation = prev_physical_state.orientation;
3209 fuel -= fuelpct*FMass;
3238 NetForce += Vforce*GetMass();
3247 NetTorque += Vforce.Cross( (Location-curr_physical_state.position).Cast() );
3253 NetTorque += Vforce.Cross( Location );
3259 NetTorque += Vforce.Cross( Location );
3264 NetLocalTorque += ClampTorque( torque );
3272 copysign( limits.roll, torque.k ) )*torque);
3281 return normalfuelusage;
3291 float fuelclamp = (fuel <= 0) ? staticfuelclamp : 1;
3292 if (fabs( amt1.i ) > fuelclamp*limits.pitch)
3293 Res.i =
copysign( fuelclamp*limits.pitch, amt1.i );
3294 if (fabs( amt1.j ) > fuelclamp*limits.yaw)
3295 Res.j =
copysign( fuelclamp*limits.yaw, amt1.j );
3296 if (fabs( amt1.k ) > fuelclamp*limits.roll)
3297 Res.k =
copysign( fuelclamp*limits.roll, amt1.k );
3298 static float Lithium6constant =
3301 static float FMEC_exit_vel_inverse =
3306 if (
ISNAN( fuel ) ) {
3307 fprintf( stderr,
"FUEL is NAN\n" );
3311 if (fuel < 0) fuel = 0;
3312 if (warpenergy < 0) warpenergy = 0;
3313 if (WCfuelhack) warpenergy = fuel;
3320 return (!combat_mode) ? combat_mode_mult*max_combat_speed : max_combat_speed;
3327 return (!combat_mode) ? combat_mode_mult*max_combat_speed : max_combat_ab_speed;
3332 if (computer.combat_mode)
3333 computer.combat_mode =
false;
3335 computer.combat_mode =
true;
3340 return computer.combat_mode;
3347 float fuelclamp = (fuel <= 0) ? staticfuelclamp : 1;
3348 float abfuelclamp = ( fuel <= 0 || (energy < afterburnenergy*
SIMULATION_ATOM) ) ? staticabfuelclamp : 1;
3350 afterburn ? ( abfuelclamp
3351 *( computer.max_ab_speed()
3352 -computer.max_speed() )+( fuelclamp*computer.max_speed() ) ) : fuelclamp*computer.max_speed();
3353 float tmp = velocity.Magnitude();
3354 if ( tmp > fabs( limit ) )
3355 return velocity*(limit/tmp);
3361 for (
unsigned int j = 0;
j < mounts.size(); ++
j) {
3366 delete mounts[j].ref.gun;
3367 mounts[j].ref.gun = NULL;
3372 for (
un_iter i = getSubUnits(); (su = *i) != NULL; ++i)
3380 if (res.i > computer.max_pitch_down)
3381 res.i = computer.max_pitch_down;
3382 }
else if (-res.i > computer.max_pitch_up) {
3383 res.i = -computer.max_pitch_up;
3386 if (res.j > computer.max_yaw_left)
3387 res.j = computer.max_yaw_left;
3388 }
else if (-res.j > computer.max_yaw_right) {
3389 res.j = -computer.max_yaw_right;
3392 if (res.k > computer.max_roll_left)
3393 res.k = computer.max_roll_left;
3394 }
else if (-res.k > computer.max_roll_right) {
3395 res.k = -computer.max_roll_right;
3404 copysign( limits.vertical, amt1.j ),
3405 amt1.k > 0 ? limits.forward : -limits.retro )*amt1);
3415 static bool finegrainedFuelEfficiency =
3418 if (fuel > warpenergy)
3420 if (fuel < warpenergy)
3424 if ( (afterburntype == 0) && energy < instantenergy )
3426 if ( (afterburntype == 1) && fuel < 0 ) {
3430 if ( (afterburntype == 2) && warpenergy < 0 ) {
3434 if (3 == afterburntype)
3438 float fuelclamp = (fuel <= 0) ? staticfuelclamp : 1;
3439 float abfuelclamp = (fuel <= 0) ? staticabfuelclamp : 1;
3440 if ( fabs( amt1.i ) > fabs( fuelclamp*limits.lateral ) )
3441 Res.i =
copysign( fuelclamp*limits.lateral, amt1.i );
3442 if ( fabs( amt1.j ) > fabs( fuelclamp*limits.vertical ) )
3443 Res.j =
copysign( fuelclamp*limits.vertical, amt1.j );
3446 ? ( (limits.afterburn-limits.forward)*abfuelclamp+limits.forward*fuelclamp )
3448 if (amt1.k > ablimit)
3450 if (amt1.k < -limits.retro)
3451 Res.k = -limits.retro;
3452 static float Lithium6constant =
3455 static float FMEC_exit_vel_inverse =
3457 if (afterburntype == 2) {
3460 warpenergy -= afterburnenergy*
GetFuelUsage( afterburn )*SIMULATION_ATOM*Res.Magnitude()*FMEC_exit_vel_inverse
3463 if (3 == afterburntype || afterburntype == 1) {
3468 && finegrainedFuelEfficiency) ? afterburnenergy :
GetFuelUsage( afterburn ) )*SIMULATION_ATOM*Res.Magnitude()
3469 *FMEC_exit_vel_inverse/Lithium6constant;
3471 if (
ISNAN( fuel ) ) {
3472 fprintf( stderr,
"Fuel is NAN A\n" );
3477 if (afterburntype == 0) {
3480 fuel -=
GetFuelUsage(
false )*SIMULATION_ATOM*Res.Magnitude()*FMEC_exit_vel_inverse/Lithium6constant;
3482 if (
ISNAN( fuel ) ) {
3483 fprintf( stderr,
"Fuel is NAN B\n" );
3488 if ( (afterburn) && (afterburntype == 0) )
3489 energy -= instantenergy;
3491 if (fuel > warpenergy)
3493 if (fuel < warpenergy)
3501 Vector amt = ClampThrust( amt1, afterburn );
3502 ApplyLocalForce( amt );
3507 if (amt > 1.0) amt = 1.0;
3508 if (amt < -1.0) amt = -1.0;
3509 ApplyLocalForce( amt*limits.lateral*
Vector( 1, 0, 0 ) );
3514 if (amt > 1.0) amt = 1.0;
3515 if (amt < -1.0) amt = -1.0;
3516 ApplyLocalForce( amt*limits.vertical*
Vector( 0, 1, 0 ) );
3521 if (amt > 1.0) amt = 1.0;
3522 if (amt < -1.0) amt = -1.0;
3523 ApplyLocalForce( amt*limits.forward*
Vector( 0, 0, 1 ) );
3528 if (amt > limits.yaw) amt = limits.yaw;
3529 else if (amt < -limits.yaw)
3531 ApplyLocalTorque( amt*
Vector( 0, 1, 0 ) );
3536 if (amt > limits.pitch) amt = limits.pitch;
3537 else if (amt < -limits.pitch)
3538 amt = -limits.pitch;
3539 ApplyLocalTorque( amt*
Vector( 1, 0, 0 ) );
3544 if (amt > limits.roll) amt = limits.roll;
3545 else if (amt < -limits.roll)
3547 ApplyLocalTorque( amt*
Vector( 0, 0, 1 ) );
3552 static float warpenergymultiplier =
3554 static float playerwarpenergymultiplier =
3560 return player ? playerwarpenergymultiplier : warpenergymultiplier;
3564 static bool applyto(
float &shield,
const float max,
const float amt )
3569 return (shield >= max) ? 1 : 0;
3574 float maxshield = 0;
3585 maxshield = shield.
shield8.frontrighttopmax+shield.
shield8.backrighttopmax+shield.
shield8.frontlefttopmax
3587 +shield.
shield8.frontleftbottommax+shield.
shield8.backleftbottommax;
3595 float maxshield = 0;
3615 static float shieldenergycap =
3617 static bool use_max_shield_value =
3624 float maxshield = 0;
3625 switch (shield.number)
3628 maxshield = .5*(shield.shield2fb.frontmax+shield.shield2fb.backmax);
3632 *(shield.shield4fbrl.frontmax+shield.shield4fbrl.backmax+shield.shield4fbrl.leftmax
3633 +shield.shield4fbrl.rightmax);
3637 *(shield.shield8.frontrighttopmax+shield.shield8.backrighttopmax+shield.shield8.frontlefttopmax
3638 +shield.shield8.backlefttopmax+shield.shield8.frontrightbottommax+shield.shield8.backrightbottommax
3639 +shield.shield8.frontleftbottommax+shield.shield8.backleftbottommax);
3645 void Unit::RechargeEnergy()
3648 if ( (!reactor_uses_fuel) || (fuel > 0) )
3655 static float shieldenergycap =
3657 static bool energy_before_shield =
3659 static bool apply_difficulty_shields =
3661 static float shield_maintenance_cost =
3663 static bool shields_require_power =
3665 static float discharge_per_second =
3668 const float dischargerate = (1-(1-discharge_per_second)*
SIMULATION_ATOM);
3669 static float min_shield_discharge =
3671 static float low_power_mode =
3673 static float max_shield_lowers_recharge =
3675 static bool max_shield_lowers_capacitance =
3677 static bool reactor_uses_fuel =
3679 static float reactor_idle_efficiency =
3686 bool velocity_discharge =
false;
3688 float precharge = energy;
3690 if (!energy_before_shield)
3693 if (shield.number) {
3695 if (shields_in_spec || !graphicOptions.InWarp) {
3696 energy -= shield.recharge*VSD
3698 *(shield.efficiency ? shield.efficiency : 1) )/shieldenergycap*shield.number*shield_maintenance_cost
3701 velocity_discharge =
true;
3706 (velocity_discharge) ? 0 : ( (shield.recharge*VSD/100*
SIMULATION_ATOM*shield.number/shieldenergycap)
3707 > energy ) ? (energy*shieldenergycap*100/VSD
3709 if (apply_difficulty_shields) {
3715 if (graphicOptions.InWarp && !shields_in_spec) {
3717 velocity_discharge =
true;
3719 if (GetNebula() != NULL) {
3720 static float nebshields =
3726 if (computer.ecmactive) {
3729 if (energy > sim_atom_ecm)
3730 energy -= sim_atom_ecm;
3735 switch (shield.number)
3738 shield.shield2fb.front += rec;
3739 shield.shield2fb.back += rec;
3740 if (shield.shield2fb.front > shield.shield2fb.frontmax)
3741 shield.shield2fb.front = shield.shield2fb.frontmax;
3744 if (shield.shield2fb.back > shield.shield2fb.backmax)
3745 shield.shield2fb.back = shield.shield2fb.backmax;
3749 if (velocity_discharge) {
3750 if (shield.shield2fb.back > min_shield_discharge*shield.shield2fb.backmax)
3751 shield.shield2fb.back *= dischargerate;
3752 if (shield.shield2fb.front > min_shield_discharge*shield.shield2fb.frontmax)
3753 shield.shield2fb.front *= dischargerate;
3755 rec = rec*2/shieldenergycap*VSD/100;
3759 applyto( shield.shield4fbrl.front, shield.shield4fbrl.frontmax,
3760 rec )*(
applyto( shield.shield4fbrl.back, shield.shield4fbrl.backmax, rec ) )*
applyto(
3761 shield.shield4fbrl.right,
3765 shield.shield4fbrl.left,
3766 shield.shield4fbrl.leftmax,
3768 if (velocity_discharge) {
3769 if (shield.shield4fbrl.front > min_shield_discharge*shield.shield4fbrl.frontmax)
3770 shield.shield4fbrl.front *= dischargerate;
3771 if (shield.shield4fbrl.left > min_shield_discharge*shield.shield4fbrl.leftmax)
3772 shield.shield4fbrl.left *= dischargerate;
3773 if (shield.shield4fbrl.back > min_shield_discharge*shield.shield4fbrl.backmax)
3774 shield.shield4fbrl.back *= dischargerate;
3775 if (shield.shield4fbrl.right > min_shield_discharge*shield.shield4fbrl.rightmax)
3776 shield.shield4fbrl.right *= dischargerate;
3778 rec = rec*4/shieldenergycap*VSD/100;
3782 applyto( shield.shield8.frontrighttop, shield.shield8.frontrighttopmax,
3783 rec )*(
applyto( shield.shield8.backrighttop, shield.shield8.backrighttopmax, rec ) )*
applyto(
3784 shield.shield8.frontlefttop,
3785 shield.shield8.frontlefttopmax,
3786 rec )*
applyto( shield.shield8.backlefttop, shield.shield8.backlefttopmax, rec )*
applyto(
3787 shield.shield8.frontrightbottom,
3789 frontrightbottommax,
3791 *(
applyto( shield.shield8.backrightbottom, shield.shield8.backrightbottommax, rec ) )*
applyto(
3792 shield.shield8.frontleftbottom,
3793 shield.shield8.frontleftbottommax,
3794 rec )*
applyto( shield.shield8.backleftbottom, shield.shield8.backleftbottommax, rec );
3795 if (velocity_discharge) {
3796 if (shield.shield8.frontrighttop > min_shield_discharge*shield.shield8.frontrighttopmax)
3797 shield.shield8.frontrighttop *= dischargerate;
3798 if (shield.shield8.frontlefttop > min_shield_discharge*shield.shield8.frontlefttopmax)
3799 shield.shield8.frontlefttop *= dischargerate;
3800 if (shield.shield8.backrighttop > min_shield_discharge*shield.shield8.backrighttopmax)
3801 shield.shield8.backrighttop *= dischargerate;
3802 if (shield.shield8.backlefttop > min_shield_discharge*shield.shield8.backlefttopmax)
3803 shield.shield8.backlefttop *= dischargerate;
3804 if (shield.shield8.frontrightbottom > min_shield_discharge*shield.shield8.frontrightbottommax)
3805 shield.shield8.frontrightbottom *= dischargerate;
3806 if (shield.shield8.frontleftbottom > min_shield_discharge*shield.shield8.frontleftbottommax)
3807 shield.shield8.frontleftbottom *= dischargerate;
3808 if (shield.shield8.backrightbottom > min_shield_discharge*shield.shield8.backrightbottommax)
3809 shield.shield8.backrightbottom *= dischargerate;
3810 if (shield.shield8.backleftbottom > min_shield_discharge*shield.shield8.backleftbottommax)
3811 shield.shield8.backleftbottom *= dischargerate;
3813 rec = rec*8/shieldenergycap*VSD/100;
3816 if (shield.number) {
3817 if (rechargesh == 0)
3819 if (shields_require_power)
3821 if (max_shield_lowers_recharge)
3823 /( 100*(shield.efficiency ? shield.efficiency : 1) );
3824 if (!max_shield_lowers_capacitance)
3828 if (energy_before_shield)
3831 float menergy = maxenergy;
3832 if ( shield.number && (menergy-maxshield < low_power_mode) ) {
3833 menergy = maxshield+low_power_mode;
3835 if (rand() < .00005*RAND_MAX) {
3840 "**Warning** Power Supply Overdrawn: downgrade shield or purchase reactor capacitance!" );
3844 if (graphicOptions.InWarp) {
3848 if (warpenergy > bleed) {
3849 warpenergy -= bleed;
3851 graphicOptions.InWarp = 0;
3852 graphicOptions.WarpRamping = 1;
3855 float excessenergy = 0;
3857 if (menergy > maxshield) {
3859 if (energy > menergy-maxshield) {
3860 excessenergy = energy-(menergy-maxshield);
3861 energy = menergy-maxshield;
3862 if (excessenergy > 0) {
3864 float mwe = maxwarpenergy;
3865 if (mwe < jump.energy && mwe == 0)
3867 if (warpenergy > mwe) {
3876 excessenergy = (excessenergy > precharge) ? excessenergy-precharge : 0;
3877 if (reactor_uses_fuel) {
3878 static float min_reactor_efficiency =
3882 -(reactor_idle_efficiency
3883 *excessenergy) )/( min_reactor_efficiency+( pImage->LifeSupportFunctionality*(1-min_reactor_efficiency) ) ) );
3884 if (fuel < 0) fuel = 0;
3886 fprintf( stderr,
"Fuel is nan C\n" );
3890 energy = energy < 0 ? 0 : energy;
3896 SavedAccel = GetNetAcceleration();
3899 GetOrientation( p, q, r );
3900 Vector temp1( NetLocalTorque.i*p+NetLocalTorque.j*q+NetLocalTorque.k*r );
3901 if (NetTorque.i || NetTorque.j || NetTorque.k)
3904 temp1 = temp1/GetMoment();
3908 AngularVelocity += temp;
3909 static float maxplayerrotationrate =
3914 caprate = maxplayerrotationrate;
3916 caprate = maxnonplayerrotationrate;
3917 if (AngularVelocity.MagnitudeSquared() > caprate*caprate)
3918 AngularVelocity = AngularVelocity.Normalize()*caprate;
3920 Vector temp2 = (NetLocalForce.i*p+NetLocalForce.j*q+NetLocalForce.k*r);
3922 cout<<
"NetForce skrewed";
3923 if (NetForce.i || NetForce.j || NetForce.k)
3925 temp2 = temp2/GetMass();
3928 cout<<
"NetForce transform skrewed";
3929 float oldmagsquared = Velocity.MagnitudeSquared();
3933 float newmagsquared = Velocity.MagnitudeSquared();
3934 static float warpstretchcutoff =
3938 static float warpstretchoutcutoff =
3942 static float cutsqr = warpstretchcutoff*warpstretchcutoff;
3943 static float outcutsqr = warpstretchoutcutoff*warpstretchoutcutoff;
3944 bool oldbig = oldmagsquared > cutsqr;
3945 bool newbig = newmagsquared > cutsqr;
3946 bool oldoutbig = oldmagsquared > outcutsqr;
3947 bool newoutbig = newmagsquared > outcutsqr;
3948 if ( (newbig && !oldbig) || (oldoutbig && !newoutbig) ) {
3949 static string insys_jump_ani =
vs_config->
getVariable(
"graphics",
"insys_jump_animation",
"warp.ani" );
3950 static bool docache =
true;
3958 GetOrientation( p, q, r );
3965 static float endsec =
3971 float tmpsec = oldbig ? endsec : sec;
3976 if (air_res_coef || lateral_air_res_coef) {
3977 float velmag = Velocity.Magnitude();
3978 Vector AirResistance = Velocity
3979 *( air_res_coef*velmag/GetMass() )*(corner_max.i-corner_min.i)*(corner_max.j-corner_min.j);
3980 if (AirResistance.Magnitude() > velmag) {
3981 Velocity.Set( 0, 0, 0 );
3983 Velocity = Velocity-AirResistance;
3984 if (lateral_air_res_coef) {
3986 GetOrientation( p, q, r );
3987 Vector lateralVel = p*Velocity.Dot( p )+q*Velocity.Dot( q );
3988 AirResistance = lateralVel
3989 *( lateral_air_res_coef*velmag
3990 /GetMass() )*(corner_max.i-corner_min.i)*(corner_max.j-corner_min.j);
3991 if ( AirResistance.Magnitude() > lateralVel.Magnitude() )
3992 Velocity = r*Velocity.Dot( r );
3994 Velocity = Velocity-AirResistance;
3998 NetForce = NetLocalForce = NetTorque = NetLocalTorque =
Vector( 0, 0, 0 );
4008 CrossProduct( q, r, p );
4009 CrossProduct( r, p, q );
4023 curr_physical_state.orientation = Q;
4026 #define MM( A, B ) m.r[B*3+A]
4031 curr_physical_state.to_matrix( m );
4032 return Vector( v.i*
MM( 0, 0 )+v.j*
MM( 1, 0 )+v.k*
MM( 2, 0 ),
4033 v.i*
MM( 0, 1 )+v.j*
MM( 1, 1 )+v.k*
MM( 2, 1 ),
4034 v.i*
MM( 0, 2 )+v.j*
MM( 1, 2 )+v.k*
MM( 2, 2 ) );
4042 curr_physical_state.to_matrix( m );
4046 #define MM( A, B ) ( (cumulative_transformation_matrix.r[B*3+A]) )
4052 return Vector( v.i*
MM( 0, 0 )+v.j*
MM( 1, 0 )+v.k*
MM( 2, 0 ),
4053 v.i*
MM( 0, 1 )+v.j*
MM( 1, 1 )+v.k*
MM( 2, 1 ),
4054 v.i*
MM( 0, 2 )+v.j*
MM( 1, 2 )+v.k*
MM( 2, 2 ) );
4072 meshdata.back()->AddDamageFX( pnt, shieldtight ? shieldtight*normal :
Vector( 0, 0, 0 ),
mymin( 1.0f,
mymax( 0.0f,
4090 static bool apply_difficulty_enemy_damage =
4092 if (apply_difficulty_enemy_damage) {
4098 float absamt = amt >= 0 ? amt : -amt;
4099 float ppercentage = 0;
4103 if ( DockedOrDocking()&(DOCKED_INSIDE|DOCKED) )
4105 if (affectedUnit !=
this) {
4106 affectedUnit->
ApplyLocalDamage( pnt, normal, amt, affectedUnit, color, phasedamage );
4110 aistate->ChooseTarget();
4111 float leakamt = phasedamage+amt*.01*shield.leak;
4112 amt *= 1-.01*shield.leak;
4114 float spercentage = 0;
4116 if ( GetNebula() == NULL || (nebshields > 0) ) {
4117 float origabsamt = absamt;
4118 spercentage = DealDamageToShield( pnt, absamt );
4120 amt = amt >= 0 ? absamt : -absamt;
4122 if ( meshdata.back() && spercentage > 0 && (origabsamt-absamt > shield.recharge || amt == 0) ) {
4125 cpt->Shake( amt, 0 );
4126 if (GetNebula() == NULL)
4127 LightShields( pnt, normal, spercentage, color );
4131 if (shield.leak > 0 || !meshdata.back() || spercentage == 0 || absamt > 0 || phasedamage) {
4132 float tmp = this->GetHull();
4133 ppercentage = DealDamageToHull( pnt, leakamt+amt );
4135 cpt->Shake( amt+leakamt, tmp != this->GetHull() ? 2 : 1 );
4136 if (ppercentage != -1) {
4138 for (
int i = 0; i < nummesh(); ++i)
4140 meshdata[i]->AddDamageFX( pnt, shieldtight ? shieldtight*normal :
Vector( 0, 0, 0 ), ppercentage, color );
4144 if (
SERVER && (ppercentage > 0 || spercentage > 0) ) {
4145 #if 1 //def NET_SHIELD_SYSTEM_1
4149 Vector netnormal = normal;
4152 this->getStarSystem()->GetZone(), hull, shield, armor, ppercentage, spercentage, amt, netpnt,
4158 if (spercentage > 0)
4159 this->damages |= SHIELD_DAMAGED;
4160 if (ppercentage > 0)
4161 this->damages |= ARMOR_DAMAGED;
4164 return ppercentage > 0 ? 2.0f : 1.0f;
4172 if (GetNebula() == NULL || nebshields > 0) {
4174 if (meshdata.back() && spercentage > 0 && amt == 0) {
4175 if (GetNebula() == NULL)
4176 meshdata.back()->AddDamageFX( pnt, shieldtight ? shieldtight*normal :
Vector( 0, 0, 0 ), spercentage, color );
4178 cpt->
Shake( amt, 0 );
4181 if (shield.leak > 0 || !meshdata.back() || spercentage == 0 || amt > 0) {
4182 if (ppercentage != -1) {
4184 for (
int i = 0; i < nummesh(); ++i)
4186 meshdata[i]->AddDamageFX( pnt, shieldtight ? shieldtight*normal :
Vector( 0, 0, 0 ), ppercentage, color );
4188 cpt->Shake( amt, 2 );
4198 if (un == unitDoNotDereference)
4211 void *ownerDoNotDereference,
4215 float hullpercent = GetHullPercent();
4217 bool mykilled = hull < 0;
4219 Vector localnorm( ToLocalCoordinates( normal ) );
4223 bool armor_damage =
false;
4225 armor_damage = (ApplyLocalDamage( localpnt, localnorm, amt, affectedUnit, color, phasedamage ) == 2);
4229 int howmany = armor_damage ? MadnessForHullDamage : MadnessForShieldDamage;
4230 for (
int i = 0; i < howmany; ++i) {
4234 if ( this->getAIState() ) this->getAIState()->Communicate( c );
4237 Threaten( reinterpret_cast< Unit* > (ownerDoNotDereference), 10 );
4246 ScoreKill( cp, reinterpret_cast< Unit* > (ownerDoNotDereference),
this );
4258 }
else if ( hullpercent >= hull_percent_for_comm && ( (
float) GetHullPercent() ) < hull_percent_for_comm
4260 Unit *computerai = NULL;
4261 Unit *player = NULL;
4272 unsigned char gender;
4275 static bool assistallyinneed =
4277 if (assistallyinneed)
4280 if (GetHullPercent() > 0 || !cp) {
4292 float deg = fabs( 180*atan2( vec.i, vec.k )/
M_PI );
4296 if (dam < inv_max_dam) dam = inv_max_dam;
4297 if (dam > inv_min_dam) dam = inv_min_dam;
4300 degrees = 360-degrees;
4301 if (degrees >= 0 && degrees < 20) {
4303 pImage->cockpit_damage[which] *= dam;
4304 if (pImage->cockpit_damage[which] < .1)
4305 pImage->cockpit_damage[which] = 0;
4307 if (randnum >= .85) {
4308 pImage->cockpit_damage[which] *= .75;
4309 if (pImage->cockpit_damage[which] < .1)
4310 pImage->cockpit_damage[which] = 0;
4311 }
else if (randnum >= .775) {
4312 computer.itts =
false;
4313 }
else if (randnum >= .7) {
4316 int& capability = computer.radar.capability;
4317 if (capability & Capability::IFF_THREAT_ASSESSMENT)
4319 capability &= ~Capability::IFF_THREAT_ASSESSMENT;
4321 else if (capability & Capability::IFF_OBJECT_RECOGNITION)
4323 capability &= ~Capability::IFF_OBJECT_RECOGNITION;
4325 else if (capability & Capability::IFF_FRIEND_FOE)
4327 capability &= ~Capability::IFF_FRIEND_FOE;
4329 }
else if (randnum >= .5) {
4331 computer.target = NULL;
4332 }
else if (randnum >= .4) {
4333 limits.retro *= dam;
4334 }
else if (randnum >= .3275) {
4336 computer.radar.maxcone += (1-dam);
4337 if (computer.radar.maxcone > maxdam)
4338 computer.radar.maxcone = maxdam;
4339 }
else if (randnum >= .325) {
4340 static float maxdam =
4342 computer.radar.lockcone += (1-dam);
4343 if (computer.radar.lockcone > maxdam)
4344 computer.radar.lockcone = maxdam;
4345 }
else if (randnum >= .25) {
4346 static float maxdam =
4348 computer.radar.trackingcone += (1-dam);
4349 if (computer.radar.trackingcone > maxdam)
4350 computer.radar.trackingcone = maxdam;
4351 }
else if (randnum >= .175) {
4352 computer.radar.maxrange *= dam;
4355 pImage->cockpit_damage[which] *= dam;
4356 if (pImage->cockpit_damage[which] < .1)
4357 pImage->cockpit_damage[which] = 0;
4359 damages |= COMPUTER_DAMAGED;
4363 if (
rand01() < thruster_hit_chance) {
4365 float orandnum =
rand01()*.82+.18;
4367 computer.max_pitch_up *= orandnum;
4368 else if (randnum >= .8)
4369 computer.max_yaw_right *= orandnum;
4370 else if (randnum >= .6)
4371 computer.max_yaw_left *= orandnum;
4372 else if (randnum >= .4)
4373 computer.max_pitch_down *= orandnum;
4374 else if (randnum >= .2)
4375 computer.max_roll_right *= orandnum;
4376 else if (randnum >= .18)
4377 computer.max_roll_left *= orandnum;
4378 else if (randnum >= .17)
4380 else if (randnum >= .10)
4382 else if (randnum >= .03)
4383 limits.pitch *= dam;
4385 limits.lateral *= dam;
4386 damages |= LIMITS_DAMAGED;
4389 if (degrees >= 20 && degrees < 35) {
4391 if (randnum >= .65 && randnum < .9) {
4393 }
else if ( GetNumMounts() ) {
4394 unsigned int whichmount = rand()%GetNumMounts();
4397 else if (mounts[whichmount].ammo > 0 && randnum >= .75)
4399 else if (randnum >= .7)
4400 mounts[whichmount].time_to_lock += ( 100-(100*dam) );
4401 else if (randnum >= .2)
4402 mounts[whichmount].functionality *= dam;
4404 mounts[whichmount].maxfunctionality *= dam;
4406 damages |= MOUNT_DAMAGED;
4409 if (degrees >= 35 && degrees < 60) {
4411 static float fuel_damage_prob = 1.f
4413 static float warpenergy_damage_prob = fuel_damage_prob
4415 "warpenergy_damage_prob",
4417 static float ab_damage_prob = warpenergy_damage_prob
4419 static float cargovolume_damage_prob = ab_damage_prob
4421 "cargovolume_damage_prob",
4423 static float upgradevolume_damage_prob = cargovolume_damage_prob
4425 "upgradevolume_damage_prob",
4427 static float cargo_damage_prob = upgradevolume_damage_prob
4429 if (randnum >= fuel_damage_prob) {
4431 }
else if (randnum >= warpenergy_damage_prob) {
4433 }
else if (randnum >= ab_damage_prob) {
4434 this->afterburnenergy += ( (1-dam)*recharge );
4435 }
else if (randnum >= cargovolume_damage_prob) {
4436 pImage->CargoVolume *= dam;
4437 }
else if (randnum >= upgradevolume_damage_prob) {
4438 pImage->UpgradeVolume *= dam;
4439 }
else if (randnum >= cargo_damage_prob) {
4441 if (pImage->cargo.size() > 0) {
4443 unsigned int cargorand_o = rand();
4444 unsigned int cargorand;
4446 cargorand = (cargorand_o+i)%pImage->cargo.size();
4447 while ( (pImage->cargo[cargorand].quantity == 0
4448 || pImage->cargo[cargorand].mission) && (++i) < pImage->cargo.size() );
4449 pImage->cargo[cargorand].quantity *=
float_to_int( dam );
4452 damages |= CARGOFUEL_DAMAGED;
4455 if (degrees >= 90 && degrees < 120) {
4458 if (randnum >= .95) {
4459 this->cloaking = -1;
4460 damages |= CLOAK_DAMAGED;
4461 }
else if (randnum >= .78) {
4462 pImage->cloakenergy += ( (1-dam)*recharge );
4463 damages |= CLOAK_DAMAGED;
4464 }
else if (randnum >= .7) {
4465 cloakmin += ( rand()%(32000-cloakmin) );
4466 damages |= CLOAK_DAMAGED;
4468 switch (shield.number)
4471 if (randnum >= .25 && randnum < .75)
4472 shield.shield2fb.frontmax *= dam;
4474 shield.shield2fb.backmax *= dam;
4477 if (randnum >= .5 && randnum < .75)
4478 shield.shield4fbrl.frontmax *= dam;
4479 else if (randnum >= .75)
4480 shield.shield4fbrl.backmax *= dam;
4481 else if (randnum >= .25)
4482 shield.shield4fbrl.leftmax *= dam;
4484 shield.shield4fbrl.rightmax *= dam;
4488 shield.shield8.frontrighttopmax *= dam;
4489 else if (randnum < .25)
4490 shield.shield8.backrighttopmax *= dam;
4491 else if (randnum < .375)
4492 shield.shield8.frontlefttopmax *= dam;
4493 else if (randnum < .5)
4494 shield.shield8.backrighttopmax *= dam;
4495 else if (randnum < .625)
4496 shield.shield8.frontrightbottommax *= dam;
4497 else if (randnum < .75)
4498 shield.shield8.backrightbottommax *= dam;
4499 else if (randnum < .875)
4500 shield.shield8.frontleftbottommax *= dam;
4502 shield.shield8.backrightbottommax *= dam;
4505 damages |= SHIELD_DAMAGED;
4508 if (degrees >= 120 && degrees < 150) {
4511 if (randnum >= .9) {
4512 static char max_shield_leak =
4515 static char min_shield_leak =
4518 char newleak =
float_to_int(
mymax( min_shield_leak,
mymax( max_shield_leak, (
char) ( (randnum-.9)*10.0*100.0 ) ) ) );
4519 if (shield.leak < newleak)
4520 shield.leak = newleak;
4521 }
else if (randnum >= .7) {
4522 shield.recharge *= dam;
4523 }
else if (randnum >= .5) {
4527 this->recharge *= dam;
4528 }
else if (randnum >= .2) {
4529 static float mindam =
4533 this->maxenergy *= dam;
4534 }
else if (pImage->repair_droid > 0) {
4535 pImage->repair_droid--;
4537 damages |= JUMP_DAMAGED;
4540 if (degrees >= 150 && degrees <= 180) {
4543 computer.max_combat_ab_speed *= dam;
4544 else if (randnum >= .6)
4545 computer.max_combat_speed *= dam;
4546 else if (randnum >= .4)
4547 limits.afterburn *= dam;
4548 else if (randnum >= .2)
4549 limits.vertical *= dam;
4551 limits.forward *= dam;
4552 damages |= LIMITS_DAMAGED;
4560 this->colTrees->Dec();
4561 this->colTrees = NULL;
4562 if (this->sound->engine != -1) {
4566 if (this->sound->explode != -1) {
4570 if (this->sound->shield != -1) {
4574 if (this->sound->armor != -1) {
4578 if (this->sound->hull != -1) {
4582 if (this->sound->cloak != -1) {
4587 if (
SERVER && this->serial) {
4591 if ( docked&(DOCKING_UNITS) ) {
4592 static float survival =
4594 static float player_survival =
4596 static int i_survival =
float_to_int( (RAND_MAX*survival) );
4597 static int i_player_survival =
float_to_int( (RAND_MAX*player_survival) );
4599 vector< Unit* >dockedun;
4601 for (i = 0; i < pImage->dockedunits.size(); ++i) {
4603 if ( NULL != ( un = pImage->dockedunits[i]->uc.GetUnit() ) )
4604 dockedun.push_back( un );
4606 while ( !dockedun.empty() ) {
4608 dockedun.back()->UnDock(
this );
4611 dockedun.back()->Kill();
4612 dockedun.pop_back();
4619 computer.target.SetUnit( NULL );
4622 computer.threat.SetUnit( NULL );
4623 computer.velocity_ref.SetUnit( NULL );
4624 computer.force_velocity_ref =
true;
4626 aistate->ClearMessages();
4631 for (
un_iter iter = getSubUnits(); (un = *iter); ++iter)
4636 fullname.c_str(), filename.get().c_str() );
4641 if (flightgroup->leader.GetUnit() ==
this)
4642 flightgroup->leader.SetUnit( NULL );
4644 #ifdef DESTRUCTDEBUG
4650 void Unit::leach(
float damShield,
float damShieldRecharge,
float damEnRecharge )
4652 recharge *= damEnRecharge;
4653 shield.recharge *= damShieldRecharge;
4654 switch (shield.number)
4657 shield.shield2fb.frontmax *= damShield;
4658 shield.shield2fb.backmax *= damShield;
4661 shield.shield4fbrl.frontmax *= damShield;
4662 shield.shield4fbrl.backmax *= damShield;
4663 shield.shield4fbrl.leftmax *= damShield;
4664 shield.shield4fbrl.rightmax *= damShield;
4667 shield.shield8.frontrighttopmax *= damShield;
4668 shield.shield8.backrighttopmax *= damShield;
4669 shield.shield8.frontlefttopmax *= damShield;
4670 shield.shield8.backlefttopmax *= damShield;
4671 shield.shield8.frontrightbottommax *= damShield;
4672 shield.shield8.backrightbottommax *= damShield;
4673 shield.shield8.frontleftbottommax *= damShield;
4674 shield.shield8.backleftbottommax *= damShield;
4681 #ifdef CONTAINER_DEBUG
4685 if (killed && ucref == 0) {
4686 #ifdef CONTAINER_DEBUG
4691 #ifdef DESTRUCTDEBUG
4700 return expsize*rSize();
4706 armor[0] = this->armor.frontrighttop;
4707 armor[1] = this->armor.backrighttop;
4708 armor[2] = this->armor.frontlefttop;
4709 armor[3] = this->armor.backlefttop;
4710 armor[4] = this->armor.frontrightbottom;
4711 armor[5] = this->armor.backrightbottom;
4712 armor[6] = this->armor.frontleftbottom;
4713 armor[7] = this->armor.backleftbottom;
4718 return maxwarpenergy;
4728 if (maxwarpenergy > 0)
4729 return ( (
float) warpenergy )/( (
float) maxwarpenergy );
4730 if (jump.energy > 0)
4731 return ( (
float) warpenergy )/( (
float) jump.energy );
4737 static bool max_shield_lowers_capacitance =
4739 if (max_shield_lowers_capacitance) {
4744 return ( (
float) energy )/maxenergy;
4750 switch (shield.number)
4754 if (shield.shield2fb.frontmax != 0)
4755 return shield.shield2fb.front/shield.shield2fb.frontmax;
4760 if (shield.shield4fbrl.frontmax != 0)
4761 return (shield.shield4fbrl.front)/shield.shield4fbrl.frontmax;
4766 if (shield.shield8.frontrighttopmax != 0 || shield.shield8.frontrightbottommax != 0
4767 || shield.shield8.frontlefttopmax != 0 || shield.shield8.frontleftbottommax
4769 return (shield.shield8.frontrighttop+shield.shield8.frontrightbottom+shield.shield8.frontlefttop
4770 +shield.shield8.frontleftbottom)
4771 /(shield.shield8.frontrighttopmax+shield.shield8.frontrightbottommax+shield.shield8.frontlefttopmax
4772 +shield.shield8.frontleftbottommax);
4782 switch (shield.number)
4786 if (shield.shield2fb.backmax != 0)
4787 return shield.shield2fb.back/shield.shield2fb.backmax;
4792 if (shield.shield4fbrl.backmax != 0)
4793 return (shield.shield4fbrl.back)/shield.shield4fbrl.backmax;
4798 if (shield.shield8.backrighttopmax != 0 || shield.shield8.backrightbottommax != 0
4799 || shield.shield8.backlefttopmax != 0 || shield.shield8.backleftbottommax
4801 return (shield.shield8.backrighttop+shield.shield8.backrightbottom+shield.shield8.backlefttop
4802 +shield.shield8.backleftbottom)
4803 /(shield.shield8.backrighttopmax+shield.shield8.backrightbottommax+shield.shield8.backlefttopmax
4804 +shield.shield8.backleftbottommax);
4814 switch (shield.number)
4821 if (shield.shield4fbrl.leftmax != 0)
4822 return (shield.shield4fbrl.left)/shield.shield4fbrl.leftmax;
4827 if (shield.shield8.backlefttopmax != 0 || shield.shield8.backleftbottommax != 0
4828 || shield.shield8.frontlefttopmax != 0 || shield.shield8.frontleftbottommax
4830 return (shield.shield8.backlefttop+shield.shield8.backleftbottom+shield.shield8.frontlefttop
4831 +shield.shield8.frontleftbottom)
4832 /(shield.shield8.backlefttopmax+shield.shield8.backleftbottommax+shield.shield8.frontlefttopmax
4833 +shield.shield8.frontleftbottommax);
4843 switch (shield.number)
4850 if (shield.shield4fbrl.rightmax != 0)
4851 return (shield.shield4fbrl.right)/shield.shield4fbrl.rightmax;
4856 if (shield.shield8.backrighttopmax != 0 || shield.shield8.backrightbottommax != 0
4857 || shield.shield8.frontrighttopmax != 0 || shield.shield8.frontrightbottommax
4859 return (shield.shield8.backrighttop+shield.shield8.backrightbottom+shield.shield8.frontrighttop
4860 +shield.shield8.frontrightbottom)
4861 /(shield.shield8.backrighttopmax+shield.shield8.backrightbottommax+shield.shield8.frontrighttopmax
4862 +shield.shield8.frontrightbottommax);
4873 #ifdef DESTRUCTDEBUG
4878 #ifdef DESTRUCTDEBUG
4886 #ifdef DESTRUCTDEBUG
4896 for (
int i = bl->
numCargo()-1; i >= 0; i--) {
4909 string limiternam = name;
4910 if (unitdir != name)
4911 limiternam = string( unitdir )+string(
".blank" );
4924 string limiternam = string( unitdir )+string(
".template" );
4950 float chance = 1-( damage_chance*(guaranteed_chance+(maxhull-hull)/maxhull) );
4952 chance = pow( chance, numhits );
4953 return rand01() > chance;
4960 float chance = 1-( damage_chance*(guaranteed_chance+(maxhull-hull)/maxhull) );
4962 chance = pow( chance, numhits );
4963 bool ret = (
rand01() > chance);
4982 targ = &armor.frontlefttop;
4984 targ = &armor.backlefttop;
4987 targ = &armor.frontleftbottom;
4989 targ = &armor.backleftbottom;
4994 targ = &armor.frontrighttop;
4996 targ = &armor.backrighttop;
4999 targ = &armor.frontrightbottom;
5001 targ = &armor.backrightbottom;
5005 float absdamage = damage >= 0 ? damage : -damage;
5006 float denom = (*targ+hull);
5007 percent = (denom > absdamage && denom != 0) ? absdamage/denom : (denom == 0 ? 0.0 : 1.0);
5012 static float damage_factor_for_sound =
5014 bool did_hull_damage =
true;
5015 if (absdamage < *targ) {
5016 if ( (*targ)*damage_factor_for_sound <= absdamage )
5017 ArmorDamageSound( pnt );
5020 did_hull_damage =
false;
5022 static bool system_damage_on_armor =
5024 if (system_damage_on_armor || did_hull_damage) {
5025 if (did_hull_damage) {
5027 damage = damage >= 0 ? absdamage : -absdamage;
5030 if (numCargo() > 0) {
5032 int which = rand()%numCargo();
5033 static std::string Restricted_items =
vs_config->
getVariable(
"physics",
"indestructable_cargo_items",
"" );
5035 if (
GetCargo( which ).GetCategory().find(
"upgrades/" ) == 0
5037 &&
GetCargo( which ).GetContent().find(
"mult_" ) != 0
5038 && Restricted_items.find(
GetCargo( which ).GetContent() ) == string::npos) {
5039 int lenupgrades = strlen(
"upgrades/" );
5042 static bool NotActuallyDowngrade =
5045 if (!NotActuallyDowngrade) {
5046 const Unit *downgrade =
5050 double percentage = 0;
5051 this->Downgrade( downgrade, 0, 0, percentage, NULL );
5061 static float system_failure =
5064 DamageRandSys( system_failure*
rand01()+(1-system_failure)*( 1-(hull > 0 ? absdamage/hull : 1.0f) ), pnt );
5066 DamageRandSys( system_failure*
rand01()+(1-system_failure)*( 1-(hull > 0 ? absdamage/hull : 1.0f) ), pnt );
5067 if (did_hull_damage) {
5069 if (hull*damage_factor_for_sound <= damage)
5070 HullDamageSound( pnt );
5075 static float disabling_constant =
5078 pImage->LifeSupportFunctionality += disabling_constant*damage/hull;
5079 if (pImage->LifeSupportFunctionality < 0) {
5080 pImage->LifeSupportFunctionalityMax += pImage->LifeSupportFunctionality;
5081 pImage->LifeSupportFunctionality = 0;
5082 if (pImage->LifeSupportFunctionalityMax < 0)
5083 pImage->LifeSupportFunctionalityMax = 0;
5091 DamageRandSys(
rand01()*.5+.2, pnt );
5098 static float cargoejectpercent =
5101 static float hulldamtoeject =
5103 if (hull > -hulldamtoeject) {
5104 static float autoejectpercent =
5107 if (rand() < (RAND_MAX*autoejectpercent) && isUnit() ==
UNITPTR) {
5108 static bool player_autoeject =
5110 if ( faction != neutralfac && faction != upgradesfac
5112 EjectCargo( (
unsigned int) -1 );
5116 static unsigned int max_dump_cargo =
5118 unsigned int dumpedcargo = 0;
5120 if (faction != neutralfac && faction != upgradesfac) {
5121 for (
unsigned int i = 0; i < numCargo(); ++i)
5130 maxenergy = energy = 0;
5131 Split( rand()%3+1 );
5139 if ( !
FINITE( percent ) )
5146 float theta360 = theta+2*3.1415926536;
5156 float theta = atan2( pnt.i, pnt.k );
5157 float rho =
atan( pnt.j/
sqrt( pnt.k*pnt.k+pnt.i*pnt.i ) );
5159 for (
int i = 0; i < shield.number; ++i)
5161 if (shield.shield.max[i]) {
5163 float tmp = damage/shield.shield.max[i];
5164 if (tmp > percent) percent = tmp;
5166 targ = &shield.shield.cur[i];
5168 if (damage > *targ) {
5179 if ( !
FINITE( percent ) )
5186 const int shieldmin = 5;
5188 if (nebula != NULL || nebshields > 0)
5190 switch (shield.number)
5193 return ( (pnt.k > 0) ? (shield.shield2fb.front) : (shield.shield2fb.back) ) > shieldmin;
5198 return shield.shield8.frontlefttop > shieldmin;
5200 return shield.shield8.backlefttop > shieldmin;
5203 return shield.shield8.frontleftbottom > shieldmin;
5205 return shield.shield8.backleftbottom > shieldmin;
5210 return shield.shield8.frontrighttop > shieldmin;
5212 return shield.shield8.backrighttop > shieldmin;
5215 return shield.shield8.frontrightbottom > shieldmin;
5217 return shield.shield8.backrightbottom > shieldmin;
5222 if ( fabs( pnt.k ) > fabs( pnt.i ) ) {
5224 return shield.shield4fbrl.front > shieldmin;
5226 return shield.shield4fbrl.back > shieldmin;
5229 return shield.shield4fbrl.left > shieldmin;
5231 return shield.shield4fbrl.right > shieldmin;
5248 if ( !SubUnits.empty() ) {
5250 bool inrange = (targ != NULL) ? InRange( targ ) :
true;
5252 for (
un_iter iter = getSubUnits(); (su = *iter); ++iter) {
5264 static float seconds_per_parsec =
5269 sourcess->
JumpTo( un, NULL, destination,
true,
true );
5277 computer.radar.locked = myboo;
5279 computer.radar.locked =
false;
5287 if ( computer.target.GetUnit() )
5288 oldtarg = computer.target.GetUnit()->
GetSerial();
5290 if (
SERVER && computer.target.GetUnit() != NULL)
5292 computer.target.SetUnit( NULL );
5298 for (
int i = 0; i < GetNumMounts(); ++i)
5299 mounts[i].time_to_lock = mounts[i].type->LockTime;
5300 if (
SERVER && computer.target.GetUnit() != targ)
5302 computer.target.SetUnit( targ );
5303 LockTarget(
false );
5306 if (jump.drive != -1) {
5314 ActivateJumpDrive( 0 );
5321 if (
SERVER && computer.target.GetUnit() != NULL)
5323 computer.target.SetUnit( NULL );
5327 if (
SERVER && computer.target.GetUnit() != NULL)
5329 computer.target.SetUnit( NULL );
5335 computer.force_velocity_ref = !!targ;
5336 computer.velocity_ref.SetUnit( targ );
5346 damages |= CLOAK_DAMAGED;
5348 static bool warp_energy_for_cloak =
5350 if ( pImage->cloakenergy < (warp_energy_for_cloak ? warpenergy : energy) ) {
5351 pImage->cloakrate = (pImage->cloakrate >= 0) ? pImage->cloakrate : -pImage->cloakrate;
5353 if (cloaking < -1 && pImage->cloakrate != 0) {
5355 cloaking = 2147483647;
5359 pImage->cloakrate = (pImage->cloakrate >= 0) ? -pImage->cloakrate : pImage->cloakrate;
5360 if (cloaking == cloakmin)
5367 for (
int i = 0; i < GetNumMounts(); ++i)
5370 mounts[i].Activate( Missile );
5376 if (status == INACTIVE)
5384 if (status == ACTIVE)
5390 if (this->GetNumMounts() == 0) {
5392 for (
un_iter i = this->getSubUnits(); (tur = *i) != NULL; ++i)
5396 vector< int >unFireRequests;
5397 for (
int i = 0; i < GetNumMounts(); ++i) {
5401 unFireRequests.push_back( i );
5404 if ( !unFireRequests.empty() ) {
5416 for (
int j = 0;
j < 2; ++
j)
5417 for (
int i = 0; i < GetNumMounts(); ++i)
5418 if (mounts[i].type == sz) {
5420 mounts[i].Activate( ms );
5422 sz = mounts[(i+1)%GetNumMounts()].
type;
5428 template <
bool FORWARD >
5434 if ( a.size() == b.size() ) {
5435 for (WeaponGroup::const_iterator iterA = a.begin(), iterB = b.begin();
5436 iterA != a.end() && iterB != b.end();
5438 if ( (*iterA) < (*iterB) )
5440 else if ( (*iterB) < (*iterA) )
5444 }
else if ( a.size() < b.size() ) {
5456 && un->
mounts[i].ammo != 0;
5466 return !isSpecial( mount );
5471 if (un->
mounts.size() == 0) {
5474 ToggleWeaponSet( tur, missile );
5483 typename WeaponGroupSet::const_iterator iter;
5484 printf(
"ToggleWeaponSet: %s\n",
FORWARD ?
"true" :
"false" );
5485 for (i = 0; i < un->
mounts.size(); ++i)
5486 if ( checkmount( un, i, missile ) ) {
5488 for (
unsigned int j = 0;
j < un->
mounts.size(); ++
j)
5490 if ( checkmount( un,
j, missile ) )
5491 mygroup.insert(
j );
5493 myset.insert( mygroup );
5494 allWeapons.insert( i );
5495 if ( notSpecial( un->
mounts[i] ) )
5496 allWeaponsNoSpecial.insert( i );
5499 for (iter = mypairset.begin(); iter != mypairset.end(); ++iter)
5500 if ( (*iter).size() && notSpecial( un->
mounts[( *( (*iter).begin() ) )] ) ) {
5501 typename WeaponGroupSet::const_iterator iter2;
5502 for (iter2 = mypairset.begin(); iter2 != mypairset.end(); ++iter2)
5503 if ( (*iter2).size() && notSpecial( un->
mounts[( *( (*iter2).begin() ) )] ) ) {
5505 set_union( (*iter).begin(), (*iter).end(), (*iter2).begin(), (*iter2).end(),
5506 inserter( myGroup, myGroup.begin() ) );
5507 myset.insert( myGroup );
5510 static bool allow_special_with_weapons =
5512 if (allow_special_with_weapons)
5513 myset.insert( allWeapons );
5514 myset.insert( allWeaponsNoSpecial );
5515 for (iter = myset.begin(); iter != myset.end(); ++iter) {
5516 for (WeaponGroup::const_iterator iter2 = (*iter).begin(); iter2 != (*iter).end(); ++iter2)
5517 printf(
"%d:%s ", *iter2, un->
mounts[*iter2].type->weapon_name.c_str() );
5521 printf(
"CURRENT: " );
5522 for (i = 0; i < un->
mounts.size(); ++i)
5524 activeWeapons.insert( i );
5525 printf(
"%d:%s ", i, un->
mounts[i].type->weapon_name.c_str() );
5528 iter = myset.upper_bound( activeWeapons );
5529 if ( iter == myset.end() )
5530 iter = myset.begin();
5531 if ( iter == myset.end() )
5533 for (i = 0; i < un->
mounts.size(); ++i)
5534 un->
mounts[i].DeActive( missile );
5535 printf(
"ACTIVE: " );
5536 for (WeaponGroup::const_iterator iter2 = (*iter).begin(); iter2 != (*iter).end(); ++iter2) {
5537 printf(
"%d:%s ", *iter2, un->
mounts[*iter2].type->weapon_name.c_str() );
5538 un->
mounts[*iter2].Activate( missile );
5541 printf(
"ToggleWeapon end...\n" );
5557 for (
un_iter iter = getSubUnits(); (su = *iter); ++iter)
5563 bool missilelock =
false;
5564 bool dumblock =
false;
5565 for (
int i = 0; i < GetNumMounts(); ++i) {
5566 if ( mounts[i].status ==
Mount::ACTIVE && mounts[i].type->LockTime > 0 && mounts[i].time_to_lock <= 0
5569 else if (mounts[i].status ==
Mount::ACTIVE && mounts[i].type->LockTime == 0 &&
isMissile( mounts[i].type )
5570 && mounts[i].time_to_lock <= 0)
5573 return missilelock ? 1 : (dumblock ? -1 : 0);
5591 return std::min(pImage->timeexplode / debrisTime, 1.0f);
5599 for (
int beamcount = 0; beamcount < GetNumMounts(); ++beamcount)
5602 if (
SERVER && this->serial) {
5615 for (
int i = 0; i < numsubunit; ++i) {
5616 subunits[i]->CollideInfo.object.u = name;
5624 float minsofar = 1
e+10;
5627 Vector TargetPoint( cumulative_transformation_matrix.getP() );
5629 #ifdef VARIABLE_LENGTH_PQR
5631 float SizeScaleFactor = sqrtf( TargetPoint.Dot( TargetPoint ) );
5633 for (i = 0; i < nummesh(); ++i) {
5634 TargetPoint = (
Transform( cumulative_transformation_matrix, meshdata[i]->Position() ).Cast()-pnt).Cast();
5635 tmpvar = sqrtf( TargetPoint.Dot( TargetPoint ) )-meshdata[i]->rSize()
5636 #ifdef VARIABLE_LENGTH_PQR
5640 if (tmpvar < minsofar)
5644 for (
un_kiter ui = viewSubUnits(); (su = *ui); ++ui) {
5646 if (tmpvar < minsofar)
5659 float adjretval = 0;
5660 const Matrix *tmpo = &cumulative_transformation_matrix;
5663 for (i = 0; i < nummesh(); ++i) {
5664 TargetPoint =
Transform( *tmpo, meshdata[i]->Position() );
5665 Vector origPoint = TargetPoint;
5670 QVector tst = TargetPoint.Cast()-st;
5671 float k = tst.Dot( dir );
5672 TargetPoint = ( tst-k*(dir) ).Cast();
5673 perplines.push_back( origPoint-TargetPoint );
5674 if (TargetPoint.Dot( TargetPoint )
5676 +meshdata[i]->rSize()*meshdata[i]->rSize()+2*err*meshdata[i]->rSize()
5681 if (adjretval < 0) {
5682 adjretval += meshdata[i]->rSize();
5687 if ( retval > 0 && k < retval && k > -meshdata[i]->rSize() ) {
5690 if (adjretval < 0) {
5691 adjretval += meshdata[i]->rSize();
5696 if (retval < 0 && k+meshdata[i]->rSize() > retval) {
5698 adjretval = k+meshdata[i]->rSize();
5707 for (
un_kiter ui = viewSubUnits(); (su = *ui); ++ui) {
5714 if (adjretval > 0 && tmp < adjretval) {
5718 if (adjretval < 0 && tmp > adjretval) {
5735 return pImage->dockingports;
5740 std::vector< Unit* >::iterator lookcleared;
5741 if ( ( lookcleared =
5753 if ( std::find( pImage->clearedunits.begin(), pImage->clearedunits.end(), dockingunit ) == pImage->clearedunits.end() )
5754 pImage->clearedunits.push_back( dockingunit );
5760 if (pImage->dockedunits.size() == 1)
5761 docked &= (~DOCKING_UNITS);
5762 unsigned int whichdock = pImage->dockedunits[i]->whichdock;
5763 pImage->dockingports[whichdock].Occupy(
false);
5764 pImage->dockedunits[i]->uc.SetUnit( NULL );
5765 delete pImage->dockedunits[i];
5766 pImage->dockedunits.erase( pImage->dockedunits.begin()+i );
5785 static bool changeddockedorient =
5787 if (!changeddockedorient)
5797 for (
unsigned int i = 0; i < pImage->dockedunits.size(); ++i) {
5799 if ( ( un = pImage->dockedunits[i]->uc.GetUnit() ) == NULL ) {
5800 FreeDockingPort( i );
5814 for (
unsigned int i = 0; i < pImage->clearedunits.size(); ++i)
5816 if (pImage->clearedunits[i] == un) {
5817 pImage->clearedunits.erase( pImage->clearedunits.begin()+i );
5831 this->warpenergy = this->fuel;
5832 float tmp = this->maxwarpenergy;
5833 if (tmp < this->jump.energy)
5834 tmp = this->jump.energy;
5835 if (tmp > this->warpenergy) {
5836 this->warpenergy = tmp;
5838 this->fuel = this->warpenergy;
5851 utdw->
docked |= DOCKING_UNITS;
5856 SetVisible(
false );
5857 docked |= DOCKED_INSIDE;
5861 pImage->DockedTo.SetUnit( utdw );
5862 computer.set_speed = 0;
5864 this->RestoreGodliness();
5868 static float MinimumCapacityToRefuelOnLand =
5871 if ( (capdata >= MinimumCapacityToRefuelOnLand) && ( this->RefillWarpEnergy() ) ) {
5872 if ( cockpit >= 0 && cockpit < _Universe->numPlayers() ) {
5877 if ( (capdata < MinimumCapacityToRefuelOnLand) && (this->faction == utdw->
faction) ) {
5879 this->IncreaseWarpEnergy(
false, this->jump.energy );
5884 this->DecreaseWarpEnergy(
false, utdw->
jump.
energy );
5887 if ( cockpit >= 0 && cockpit < _Universe->numPlayers() ) {
5898 for (
unsigned int j = 0;
j < 100000; ++
j)
5902 return whichdockport+1;
5909 if ( docked&(DOCKED_INSIDE|DOCKED) )
5911 std::vector< Unit* >::iterator lookcleared;
5915 if ( ( whichdockport = utdw->
CanDockWithMe(
this ) ) != -1 ) {
5917 return ForceDock( utdw, whichdockport );
5945 for (
unsigned int i = 0; i < pImage->dockingports.size(); ++i)
5958 if ( ( ( un->
docked&(DOCKED_INSIDE|DOCKED) ) == 0 ) && ( !(docked&DOCKED_INSIDE) ) )
5963 else if (
insideDock( pImage->dockingports[i],
5971 for (
unsigned int i = 0; i < pImage->dockingports.size(); ++i)
5972 if (!pImage->dockingports[i].IsOccupied())
5980 return std::find( pImage->clearedunits.begin(), pImage->clearedunits.end(), DockingUnit ) != pImage->clearedunits.end();
5985 return pImage && (pImage->clearedunits.size() > 0);
5992 if ( !( d->
docked&(DOCKED_INSIDE|DOCKED) ) )
5994 for (
unsigned int i = 0; i < pImage->dockedunits.size(); ++i) {
5996 if ( ( un = pImage->dockedunits[i]->uc.GetUnit() ) != NULL )
6009 if (this->name ==
"return_to_cockpit") {
6010 if (this->faction == utdw->
faction)
6017 cerr<<
"Sending an undock notification"<<endl;
6027 docked &= ( ~(DOCKED_INSIDE|DOCKED) );
6028 pImage->DockedTo.SetUnit( NULL );
6031 static bool auto_turn_towards =
6034 auto_turn_towards =
false;
6037 if (launch_speed > 0)
6038 computer.set_speed = launch_speed;
6039 if (auto_turn_towards) {
6040 for (
int i = 0; i < 3; ++i) {
6044 GetOrientation( p, q, r );
6045 p = methem.Cross( r );
6046 float theta = p.Magnitude();
6047 if (theta*theta > .00001) {
6048 p *= (
asin( theta )/theta);
6050 GetOrientation( p, q, r );
6052 if (r.Dot( methem ) < 0)
6056 if (name ==
"return_to_cockpit" || this->name ==
"return_to_cockpit") {
6073 #define UPGRADEOK (1)
6074 #define NOTTHERE (0)
6075 #define CAUSESDOWNGRADE (-1)
6076 #define LIMITEDBYTEMPLATE (-2)
6116 return (a-b < 0) ? 0 : a-
b;
6156 static int UpgradeFloat(
double &result,
double tobeupgraded,
double upgrador,
double templatelimit,
double (*myadd)(
double,
6158 bool (*betterthan)(
double a,
6159 double b ),
double nothing,
double completeminimum,
double (*computepercentage)(
6162 double newvar ),
double &percentage,
bool forcedowngrade,
bool usetemplate,
double at_least_this,
6163 bool (*atLeastthiscompare)(
6165 double b ) =
AGreaterB,
bool clamp =
false,
bool force_nothing =
false )
6168 if (upgrador != nothing || force_nothing) {
6170 if (tobeupgraded > upgrador)
6171 upgrador = tobeupgraded;
6172 float newsum = (*myadd)(tobeupgraded, upgrador);
6174 if (!force_nothing && newsum < tobeupgraded && at_least_this >= upgrador && at_least_this > newsum && at_least_this
6177 if ( newsum != tobeupgraded && ( ( (*betterthan)(newsum, tobeupgraded) || forcedowngrade ) ) ) {
6178 if ( ( (*betterthan)(newsum, templatelimit) && usetemplate ) || newsum < completeminimum ) {
6179 if (!forcedowngrade)
6181 if (newsum < completeminimum)
6182 newsum = completeminimum;
6184 newsum = templatelimit;
6187 percentage = (*computepercentage)(tobeupgraded, upgrador, newsum);
6188 if ( (*atLeastthiscompare)(at_least_this, newsum) && (!force_nothing) ) {
6189 if ( (*atLeastthiscompare)(at_least_this, tobeupgraded) )
6191 newsum = tobeupgraded;
6194 newsum = at_least_this;
6206 int UpgradeBoolval(
int a,
int upga,
bool touchme,
bool downgrade,
int &numave,
double &percentage,
bool force_nothing )
6210 if (touchme) (a =
false);
6216 if (touchme) a =
true;
6219 }
else if (force_nothing && a && !upga) {
6220 if (touchme) a =
false;
6230 for (
int i = 0; input_buffer[i] !=
'\0'; ++i)
6231 if (input_buffer[i] ==
'\n' || input_buffer[i] ==
'\r')
6232 input_buffer[i] =
'\0';
6237 if (strcasecmp( input_buffer,
"exit" ) == 0
6238 || strcasecmp( input_buffer,
"quit" ) == 0)
6245 void Tokenize(
const string &str, vector< string > &tokens,
const string &delimiters =
" " )
6248 string::size_type lastPos = str.find_first_not_of( delimiters, 0 );
6250 string::size_type pos = str.find_first_of( delimiters, lastPos );
6251 while (string::npos != pos || string::npos != lastPos) {
6253 tokens.push_back( str.substr( lastPos, pos-lastPos ) );
6255 lastPos = str.find_first_not_of( delimiters, pos );
6257 pos = str.find_first_of( delimiters, lastPos );
6263 if (tokens.find(
"small" ) != string::npos)
6265 if (tokens.find(
"medium" ) != string::npos)
6267 if (tokens.find(
"large" ) != string::npos)
6269 if (tokens.find(
"cargo" ) != string::npos)
6271 if (tokens.find(
"LR" ) != string::npos || tokens.find(
"massive" ) != string::npos)
6283 using namespace VSFileSystem;
6284 std::map< VCString, VCString >t;
6289 char *filedata = (
char*) malloc( siz+1 );
6292 std::string
x( filedata );
6293 string::size_type len = x.find(
"," );
6294 if (len != std::string::npos) {
6295 std::string
y = x.substr( len+1 );
6296 x = x.substr( 0, len );
6297 len = y.find(
"," );
6298 y = y.substr( 0, len );
6299 sscanf( y.c_str(),
"%s", filedata );
6315 std::map< VCString, VCString >::iterator
h = turretmap.find( size );
6316 if ( h != turretmap.end() )
6318 vector< string >tokens;
6320 for (
unsigned int i = 0; i < tokens.size(); ++i) {
6321 if (tokens[i].find(
"turret" ) != string::npos) {
6323 if ( !temp.empty() )
6338 double &percentage )
6342 bool cancompletefully =
true;
6343 for (i = 0, j = mountoffset; i < up->
GetNumMounts() && i < GetNumMounts() ; ++i, ++j)
6347 bool isammo = ( string::npos != string( up->
name ).find(
"_ammo" ) );
6348 bool ismissiletype =
6350 != ( up->
mounts[i].type->size
6355 int jmod = j%GetNumMounts();
6358 if (up->
mounts[i].type->weapon_name.find(
"_UPGRADE" ) == string::npos) {
6361 if ( (
unsigned int) (up->
mounts[i].type->size) == (up->
mounts[i].type->size&mounts[jmod].size) ) {
6362 if (up->
mounts[i].type->weapon_name != mounts[jmod].type->weapon_name || mounts[jmod].status
6365 if (isammo && !ismissiletype) {
6366 cancompletefully =
false;
6372 if (templ->
mounts[jmod].volume != -1)
6378 percentage += mounts[jmod].Percentage( &upmount );
6382 mounts[jmod].ReplaceMounts(
this, &upmount );
6385 if (isammo && up->
mounts[i].type->weapon_name == mounts[jmod].type->weapon_name) {
6387 int tmpammo = mounts[jmod].ammo;
6388 if (mounts[jmod].ammo != -1 && up->
mounts[i].ammo != -1) {
6389 tmpammo += up->
mounts[i].ammo;
6392 if (templ->
mounts[jmod].volume != -1) {
6393 if (templ->
mounts[jmod].volume < mounts[jmod].type->volume*tmpammo) {
6397 +templ->
mounts[jmod].volume)
6398 /mounts[jmod].type->volume ) );
6403 if (tmpammo*mounts[jmod].type->volume > mounts[jmod].volume)
6404 tmpammo = (
int) floor( .125+( (0+mounts[jmod].
volume)/mounts[jmod].type->volume ) );
6405 if (tmpammo > mounts[jmod].ammo) {
6406 cancompletefully =
true;
6408 mounts[jmod].ammo = tmpammo;
6410 cancompletefully =
false;
6414 cancompletefully =
false;
6419 cancompletefully =
false;
6422 unsigned int siz = 0;
6426 siz = templ->
mounts[jmod].size;
6427 if ( ( (siz&up->
mounts[i].size)|mounts[jmod].size ) != mounts[jmod].size ) {
6429 mounts[jmod].size |= up->
mounts[i].size;
6433 cancompletefully =
false;
6439 if (up->
mounts[i].type->weapon_name !=
"MOUNT_UPGRADE") {
6442 for (
unsigned int k = 0;
k < (
unsigned int) GetNumMounts(); ++
k) {
6444 int jkmod = (jmod+
k)%GetNumMounts();
6449 if (strcasecmp( mounts[jkmod].type->weapon_name.c_str(),
6450 up->
mounts[i].type->weapon_name.c_str() ) == 0) {
6452 if (isammo && mounts[jkmod].ammo <= 0)
6458 percentage += mounts[jkmod].Percentage( &up->
mounts[i] );
6462 if (isammo && up->
mounts[i].ammo && up->
mounts[i].ammo != -1 && mounts[jkmod].ammo != -1) {
6464 mounts[jkmod].ammo -=
6465 (mounts[jkmod].ammo >= up->
mounts[i].ammo) ? up->
mounts[i].ammo : mounts[jkmod].ammo;
6467 if (!mounts[jkmod].ammo) {
6475 mounts[jkmod].ammo = -1;
6483 cancompletefully =
false;
6486 static bool downmount =
6490 for (
unsigned int k = 0;
k < (
unsigned int) GetNumMounts(); ++
k) {
6492 int jkmod = (jmod+
k)%GetNumMounts();
6493 if ( (up->
mounts[i].size&mounts[jkmod].size) == (up->
mounts[i].size) ) {
6495 mounts[jkmod].size &= (~up->
mounts[i].size);
6503 cancompletefully =
false;
6507 if ( i < up->GetNumMounts() )
6508 cancompletefully =
false;
6510 return cancompletefully;
6515 return new Unit( tur.c_str(),
true,
faction,
"", 0, 0 );
6520 return UpgradeSubUnitsWithFactory( up, subunitoffset, touchme, downgrade, numave, percentage, &
CreateGenericTurret );
6524 double &percentage,
Unit* (*createupgradesubunit)(std::string s,
6528 bool cancompletefully =
true;
6530 std::string turSize;
6533 for (j = 0, ui = getSubUnits(); (*ui) != NULL && j < subunitoffset; ++ui, ++j) {}
6538 if (giveAway == NULL)
6540 bool hasAnyTurrets =
false;
6543 for (upturrets = up->
viewSubUnits(); ( (*upturrets) != NULL ) && ( (*ui) != NULL ); ++ui, ++upturrets) {
6544 hasAnyTurrets =
true;
6545 const Unit *addtome;
6547 addtome = *upturrets;
6549 bool foundthis =
false;
6552 if (!downgrade || addtome->
name == giveAway->
name) {
6557 percentage += ( giveAway->
rSize()/addtome->
rSize() );
6569 Unit *addToMeNew = (*createupgradesubunit)(addtome->
name, addtome->
faction);
6591 un->
name = turSize+
"_blank";
6600 return !hasAnyTurrets;
6601 if ( (*upturrets) != NULL )
6603 return cancompletefully;
6619 bool force_change_on_nothing,
6620 bool gen_downgrade_list )
6622 return UpAndDownGrade( upgrador,
6632 force_change_on_nothing,
6633 gen_downgrade_list );
6643 bool force_change_on_nothing,
6644 bool gen_downgrade_list )
6646 return UpAndDownGrade( upgrador,
6656 force_change_on_nothing,
6657 gen_downgrade_list );
6664 const Unit *downgradelimit,
6665 bool gen_downgrade_list )
6667 return UpAndDownGrade( downgradeor,
6678 gen_downgrade_list );
6685 const Unit *downgradelimit,
6686 bool gen_downgrade_list )
6688 return UpAndDownGrade( downgradeor,
6699 gen_downgrade_list );
6704 static float MyPercentMin =
6706 return MyPercentMin;
6730 double Unit::Upgrade(
const std::string &
file,
int mountoffset,
int subunitoffset,
bool force,
bool loop_through_mounts )
6733 if (shield.number == 2)
6734 printf(
"shields before %s %f %f", file.c_str(), shield.fb[2], shield.fb[3] );
6736 printf(
"shields before %s %d %d", file.c_str(), shield.fbrl.frontmax, shield.fbrl.backmax );
6743 unsigned int cargonum;
6747 char *unitdir =
GetUnitDir( this->name.get().c_str() );
6748 string templnam = string( unitdir )+
".template";
6750 if (templ == NULL) {
6757 double percentage = 0;
6758 if (up->
name !=
"LOAD_FAILED") {
6759 for (
int i = 0; percentage == 0; ++i) {
6760 if ( !this->
Unit::Upgrade( up, mountoffset+i, subunitoffset+i,
6762 ( (templ->
name ==
"LOAD_FAILED") ? NULL : templ ),
6765 if (!loop_through_mounts || ( i+1 >= this->GetNumMounts() ) || percentage > 0)
6770 if (shield.number == 2)
6771 printf(
"shields before %s %f %f", file.c_str(), shield.fb[2], shield.fb[3] );
6773 printf(
"shields before %s %d %d", file.c_str(), shield.fbrl.frontmax, shield.fbrl.backmax );
6781 bool AddToDowngradeMap( std::string name,
double value,
int unitoffset, vsUMap< int, DoubleName > &tempdowngrademap )
6784 vsUMap< int, DoubleName >::iterator i = downgrademap.find( unitoffset );
6785 if ( i != downgrademap.end() ) {
6786 if ( (*i).second.d <= value ) {
6787 tempdowngrademap[unitoffset] =
DoubleName( name, value );
6791 tempdowngrademap[unitoffset] =
DoubleName( name, value );
6799 downgrademap.clear();
6805 vsUMap< int, DoubleName >::iterator i = downgrademap.begin();
6806 std::set< std::string >retval;
6807 for (; i != downgrademap.end(); ++i)
6808 retval.insert( (*i).second.s );
6821 if ( fac < has_recursive_data.size() ) {
6822 FactionHasRecursiveData::const_iterator iter = has_recursive_data[fac].find( name );
6823 if ( iter != has_recursive_data[fac].end() ) {
6824 UnitHasRecursiveData::const_iterator iter2 = iter->second.find( key );
6825 if ( iter2 != iter->second.end() )
6826 return iter2->second;
6829 has_recursive_data.resize( fac+1 );
6831 bool retval =
false;
6834 string::size_type lkstart = 0;
6835 string::size_type lkend = lkey.find(
'|' );
6837 while ( !retval && (lkstart != string::npos) ) {
6838 string skey = lkey.substr( lkstart, (lkend == string::npos) ? string::npos : lkend-lkstart );
6841 retval = (lus.length() != 0);
6843 lkstart = (lkend != string::npos) ? lkend+1 : string::npos;
6844 lkend = lkey.find(
'|', lkstart );
6848 string::size_type when;
6850 string::size_type ofs = 0;
6851 while ( !retval && ( ( when = upgrades.find(
'{', ofs ) ) != string::npos ) ) {
6852 string::size_type where = upgrades.find(
'}', when+1 );
6853 string upgrade = upgrades.substr( when+1, ( (where != string::npos) ? where-when-1 : string::npos ) );
6858 has_recursive_data[fac][name][key] = retval;
6862 #define STDUPGRADE_SPECIFY_DEFAULTS( my, oth, temp, noth, dgradelimer, dgradelimerdefault, clamp, value_to_lookat ) \
6870 (templ != NULL) ? temp : 0, \
6871 Adder, Comparer, noth, noth, \
6872 Percenter, temppercent, \
6875 (downgradelimit != NULL) ? dgradelimer : dgradelimerdefault, \
6878 force_change_on_nothing \
6881 if (retval == UPGRADEOK) \
6885 percentage += temppercent; \
6887 can_be_redeemed = true; \
6888 if (gen_downgrade_list) \
6889 AddToDowngradeMap( up->name, oth, ( (char*) &value_to_lookat )-(char*) this, tempdownmap ); \
6891 else if (retval != NOTTHERE) \
6893 if (retval == CAUSESDOWNGRADE) \
6894 needs_redemption = true; \
6896 cancompletefully = false; \
6901 #define STDUPGRADE( my, oth, temp, noth ) \
6902 do {STDUPGRADE_SPECIFY_DEFAULTS( my, \
6906 downgradelimit->my, \
6912 #define STDUPGRADECLAMP( my, oth, temp, noth ) \
6913 do {STDUPGRADE_SPECIFY_DEFAULTS( my, \
6917 downgradelimit->my, \
6919 !force_change_on_nothing, \
6930 bool forcetransaction,
6932 const Unit *downgradelimit,
6933 bool force_change_on_nothing,
6934 bool gen_downgrade_list )
6939 if (playernum >= 0) {
6940 ObjSerial buySerial = downgrade ? 0 : serial,
6941 sellSerial = downgrade ? serial : 0;
6943 up->
name, 0, mountoffset, subunitoffset );
6949 ObjSerial buySerial = downgrade ? 0 : serial,
6950 sellSerial = downgrade ? serial : 0;
6952 up->
name, 0, 0, 0,
false, 0,
6953 mountoffset, subunitoffset, getStarSystem()->GetZone() );
6957 bool cancompletefully =
true;
6958 bool can_be_redeemed =
false;
6959 bool needs_redemption =
false;
6960 if (mountoffset >= 0)
6961 cancompletefully = UpgradeMounts( up, mountoffset, touchme, downgrade, numave, templ, percentage );
6962 bool cancompletefully1 =
true;
6963 if (subunitoffset >= 0)
6964 cancompletefully1 = UpgradeSubUnits( up, subunitoffset, touchme, downgrade, numave, percentage );
6965 cancompletefully = cancompletefully && cancompletefully1;
6969 vsUMap< int, DoubleName >tempdownmap;
6970 if (cancompletefully && cancompletefully1 && downgrade)
6994 if (additive == 1) {
6997 }
else if (additive == 2) {
7025 static Unit *blankship = NULL;
7026 static bool initblankship =
false;
7027 if (!initblankship) {
7029 initblankship =
true;
7033 string upgrade_name = up->
name;
7035 if ( !csv_cell_null_check || force_change_on_nothing
7037 "Spec_Interdiction|Warp_Min_Multiplier|Warp_Max_Multiplier" ) ) {
7038 if ( !csv_cell_null_check || force_change_on_nothing
7041 bool interdictionUnits = specInterdiction > 0;
7042 specInterdiction = fabs( specInterdiction );
7046 specInterdiction = -specInterdiction;
7047 if ( interdictionUnits != (specInterdiction > 0) ) {
7058 if (!interdictionUnits)
7064 if ( !csv_cell_null_check || force_change_on_nothing
7066 STDUPGRADE( graphicOptions.MinWarpMultiplier,
7071 if ( !csv_cell_null_check || force_change_on_nothing
7073 STDUPGRADE( graphicOptions.MaxWarpMultiplier,
7080 if ( !csv_cell_null_check || force_change_on_nothing
7082 "Warp_Capacitor|Warp_Usage_Cost" ) ) {
7083 if ( !csv_cell_null_check || force_change_on_nothing
7086 if ( !csv_cell_null_check || force_change_on_nothing
7091 if ( !csv_cell_null_check || force_change_on_nothing
7094 if ( !csv_cell_null_check || force_change_on_nothing
7101 if ( !csv_cell_null_check || force_change_on_nothing
7112 float tmp = shield.recharge;
7113 if ( !csv_cell_null_check || force_change_on_nothing
7116 bool upgradedrecharge = (tmp != shield.recharge);
7119 if ( (maxhull < hull) && (hull != 0) )
7121 if ( !csv_cell_null_check || force_change_on_nothing
7126 if ( !csv_cell_null_check || force_change_on_nothing
7128 "Heat_Sink_Rating|Repair_Droid|Hold_Volume|Upgrade_Storage_Volume|Equipment_Space|Hidden_Hold_Volume|ECM_Rating|Primary_Capacitor|Warp_Capacitor" ) )
7130 if ( !csv_cell_null_check || force_change_on_nothing
7133 if ( !csv_cell_null_check || force_change_on_nothing
7136 if ( !csv_cell_null_check || force_change_on_nothing
7139 if ( !csv_cell_null_check || force_change_on_nothing
7142 if ( !csv_cell_null_check || force_change_on_nothing
7145 if ( !csv_cell_null_check || force_change_on_nothing
7148 if ( !csv_cell_null_check || force_change_on_nothing
7151 if ( !csv_cell_null_check || force_change_on_nothing
7156 if ( !csv_cell_null_check || force_change_on_nothing
7158 "Maneuver_Yaw|Maneuver_Pitch|Maneuver_Roll|Left_Accel|Top_Accel|Retro_Accel|Forward_Accel|Afterburner_Accel|Default_Speed_Governor|Afterburner_Speed_Governor|Yaw_Governor|Pitch_Governor|Roll_Speed_Governor" ) )
7160 if ( !csv_cell_null_check || force_change_on_nothing
7163 if ( !csv_cell_null_check || force_change_on_nothing
7166 if ( !csv_cell_null_check || force_change_on_nothing
7169 if ( !csv_cell_null_check || force_change_on_nothing
7174 if ( !csv_cell_null_check || force_change_on_nothing
7177 if ( !csv_cell_null_check || force_change_on_nothing
7180 if ( !csv_cell_null_check || force_change_on_nothing
7183 if ( !csv_cell_null_check || force_change_on_nothing
7186 if ( !csv_cell_null_check || force_change_on_nothing
7189 if ( !csv_cell_null_check || force_change_on_nothing
7192 if ( !csv_cell_null_check || force_change_on_nothing
7197 if ( !csv_cell_null_check || force_change_on_nothing
7202 if ( !csv_cell_null_check || force_change_on_nothing
7209 static bool UpgradeCockpitDamage =
7211 if (UpgradeCockpitDamage) {
7214 (unittable ? 0 : 1) );
7217 (unittable ? 0 : 1) );
7219 (unittable ? 0 : 1) );
7222 (unittable ? 0 : 1) );
7224 (unittable ? 0 : 1) );
7226 (unittable ? 0 : 1) );
7229 (unittable ? 0 : 1) );
7232 (unittable ? 0 : 1) );
7234 for (
unsigned int upgr = 0; upgr < upgrmax; upgr++)
7236 (unittable ? 0 : 1) );
7237 for (
unsigned int upgr = 0; upgr < upgrmax; ++upgr)
7240 bool upgradedshield =
false;
7241 if ( !csv_cell_null_check || force_change_on_nothing
7245 float aa, bb, cc, dd;
7246 switch (shield.number)
7249 a = shield.shield2fb.frontmax;
7250 b = shield.shield2fb.backmax;
7253 if (shield.shield2fb.frontmax != a) shield.shield2fb.front = shield.shield2fb.frontmax;
7254 if (shield.shield2fb.backmax != b) shield.shield2fb.back = shield.shield2fb.backmax;
7257 a = shield.shield4fbrl.frontmax;
7258 b = shield.shield4fbrl.backmax;
7259 c = shield.shield4fbrl.leftmax;
7260 d = shield.shield4fbrl.rightmax;
7265 if (a != shield.shield4fbrl.frontmax) shield.shield4fbrl.front = shield.shield4fbrl.frontmax;
7266 if (b != shield.shield4fbrl.backmax) shield.shield4fbrl.back = shield.shield4fbrl.backmax;
7267 if (c != shield.shield4fbrl.leftmax) shield.shield4fbrl.left = shield.shield4fbrl.leftmax;
7268 if (d != shield.shield4fbrl.rightmax) shield.shield4fbrl.right = shield.shield4fbrl.rightmax;
7271 a = shield.shield8.frontrighttopmax;
7272 b = shield.shield8.backrighttopmax;
7273 c = shield.shield8.frontlefttopmax;
7274 d = shield.shield8.backlefttopmax;
7275 aa = shield.shield8.frontrightbottommax;
7276 bb = shield.shield8.backrightbottommax;
7277 cc = shield.shield8.frontleftbottommax;
7278 dd = shield.shield8.backleftbottommax;
7295 STDUPGRADE( shield.shield8.frontrightbottommax,
7299 STDUPGRADE( shield.shield8.backrightbottommax,
7303 STDUPGRADE( shield.shield8.frontleftbottommax,
7307 STDUPGRADE( shield.shield8.backleftbottommax,
7311 if (a != shield.shield8.frontrighttopmax) shield.shield8.frontrighttop = shield.shield8.frontrighttopmax;
7312 if (b != shield.shield8.backrighttopmax) shield.shield8.backrighttop = shield.shield8.backrighttopmax;
7313 if (c != shield.shield8.frontlefttopmax) shield.shield8.frontlefttop = shield.shield8.frontlefttopmax;
7314 if (d != shield.shield8.backlefttopmax) shield.shield8.backlefttop = shield.shield8.backlefttopmax;
7315 if (aa != shield.shield8.frontrightbottommax)
7316 shield.shield8.frontrightbottom =
7317 shield.shield8.frontrightbottommax;
7318 if (bb != shield.shield8.backrightbottommax)
7319 shield.shield8.backrightbottom =
7320 shield.shield8.backrightbottommax;
7321 if (cc != shield.shield8.frontleftbottommax)
7322 shield.shield8.frontleftbottom =
7323 shield.shield8.frontleftbottommax;
7324 if (dd != shield.shield8.backleftbottommax) shield.shield8.backleftbottom = shield.shield8.backleftbottommax;
7328 upgradedshield =
true;
7330 cancompletefully =
false;
7333 if (upgradedshield || upgradedrecharge) {
7341 if ( !csv_cell_null_check || force_change_on_nothing
7343 double myleak = 100-shield.leak;
7345 double templeak = 100-(templ != NULL ? templ->
shield.
leak : 0);
7346 bool ccf = cancompletefully;
7348 if (touchme && myleak <= 100 && myleak >= 0) shield.leak = (char) 100-myleak;
7349 cancompletefully = ccf;
7355 static bool use_template_maxrange =
7358 if ( !csv_cell_null_check || force_change_on_nothing
7360 "Radar_Range|Radar_Color|ITTS|Can_Lock|Max_Cone|Lock_Cone|Tracking_Cone" ) ) {
7361 if ( !csv_cell_null_check || force_change_on_nothing
7368 if ( !csv_cell_null_check || force_change_on_nothing
7371 if ( !csv_cell_null_check || force_change_on_nothing
7379 force_change_on_nothing );
7381 if ( !csv_cell_null_check || force_change_on_nothing
7389 force_change_on_nothing );
7392 bool ccf = cancompletefully;
7393 if ( !csv_cell_null_check || force_change_on_nothing
7395 double myleak = 1-computer.radar.maxcone;
7399 if (touchme) computer.radar.maxcone = 1-myleak;
7402 double myleak = 1-computer.radar.lockcone;
7405 if (templeak == 1-lc)
7407 if ( !csv_cell_null_check || force_change_on_nothing
7410 if (touchme) computer.radar.lockcone = 1-myleak;
7414 double myleak = 1-computer.radar.trackingcone;
7417 if (templeak == 1-tc)
7419 if ( !csv_cell_null_check || force_change_on_nothing
7422 if (touchme) computer.radar.trackingcone = 1-myleak;
7425 cancompletefully = ccf;
7429 if (jump.drive >= -1 && up->
jump.
drive >= -1) {
7430 if (touchme) jump.drive = -2;
7433 if (gen_downgrade_list)
7436 if (cloaking != -1 && up->
cloaking != -1) {
7437 if (touchme) cloaking = -1;
7440 if (gen_downgrade_list)
7446 if (afterburnenergy < 32767 && afterburnenergy <= up->afterburnenergy && up->
afterburnenergy != 32767
7448 if (touchme) afterburnenergy = 32767, afterburntype = 0;
7451 if (gen_downgrade_list) {
7454 ( (
char*) &this->afterburnenergy )-( (
char*)
this ),
7461 for (
unsigned int i = 0; i < up->
pImage->
cargo.size(); ++i)
7465 if ( (cloaking == -1 && up->
cloaking != -1) || force_change_on_nothing ) {
7474 }
else if (cloaking != -1 && up->
cloaking != -1) {
7475 cancompletefully =
false;
7485 }
else if (afterburnenergy <= up->afterburnenergy && afterburnenergy >= 0 && up->
afterburnenergy > 0
7487 cancompletefully =
false;
7489 if ( (jump.drive == -2 && up->
jump.
drive >= -1) || force_change_on_nothing ) {
7495 }
else if (jump.drive >= -1 && up->
jump.
drive >= -1) {
7496 cancompletefully =
false;
7499 if (needs_redemption)
7500 if (!can_be_redeemed)
7501 cancompletefully =
false;
7505 percentage = percentage/numave;
7506 if (0 && touchme && up->
Mass && numave) {
7507 float multiplyer = ( (downgrade) ? -1 : 1 );
7508 Mass += multiplyer*percentage*up->
Mass;
7509 if ( Mass < (templ ? templ->
Mass : .000000001) )
7510 Mass = (templ ? templ->
Mass : .000000001);
7512 if ( Momentofinertia < (templ ? templ->
Momentofinertia : 0.00000001) )
7515 if (gen_downgrade_list) {
7517 if (downgrade && percentage > MyPercentMin)
7518 for (vsUMap< int, DoubleName >::iterator i = tempdownmap.begin(); i != tempdownmap.end(); ++i)
7519 downgrademap[(*i).first] = (*i).second;
7521 return cancompletefully;
7524 #undef STDUPGRADECLAMP
7526 #undef STDUPGRADE_SPECIFY_DEFAULTS
7530 vector< Cargo >savedCargo;
7531 savedCargo.swap( pImage->cargo );
7532 vector< Mount >savedWeap;
7533 savedWeap.swap( mounts );
7535 bool success =
false;
7537 if ( temprate && temprate->
name !=
string(
"LOAD_FAILED" ) ) {
7538 success = Upgrade( temprate, -1, -1, 0,
true, pct, NULL,
true );
7542 savedCargo.swap( pImage->cargo );
7543 savedWeap.swap( mounts );
7549 if ( whichmount < 0 || (
unsigned int) whichmount >= mounts.size() )
return Vector( -1, -1, -1 );
7550 return Vector( mounts[whichmount].functionality,
7551 mounts[whichmount].maxfunctionality,
7552 ( (mounts[whichmount].status ==
Mount::ACTIVE || mounts[whichmount].status
7560 for (i = 0; i < (1+MAXVDUS+UnitImages< void >::NUMGAUGES)*2; ++i)
7561 if (pImage->cockpit_damage[i] < 1)
7563 if (pImage->fireControlFunctionality < 1)
7565 if (pImage->fireControlFunctionalityMax < 1)
7567 if (pImage->SPECDriveFunctionality < 1)
7569 if (pImage->SPECDriveFunctionalityMax < 1)
7571 if (pImage->CommFunctionality < 1)
7573 if (pImage->CommFunctionalityMax < 1)
7575 if (pImage->LifeSupportFunctionality < 1)
7577 if (pImage->LifeSupportFunctionalityMax < 1)
7579 for (i = 0; i < numCargo(); ++i)
7587 vector< Cargo >savedCargo;
7588 savedCargo.swap( pImage->cargo );
7589 vector< Mount >savedWeap;
7590 savedWeap.swap( mounts );
7595 if ( temprate && temprate->
name !=
string(
"LOAD_FAILED" ) ) {
7596 success = Upgrade( temprate, -1, -1, 0,
false, pct, NULL,
false ) ? 1 : 0;
7600 savedCargo.swap( pImage->cargo );
7601 savedWeap.swap( mounts );
7603 for (
int i = 0; i < (1+MAXVDUS+UnitImages< void >::NUMGAUGES)*2; ++i)
7649 damages = NO_DAMAGE;
7650 bool ret = success && pct > 0;
7651 static bool ComponentBasedUpgrades =
7653 if (ComponentBasedUpgrades) {
7654 for (
unsigned int i = 0; i < numCargo(); ++i)
7664 for (
unsigned int i = 0; i < mpl->numCargo(); ++i)
7665 if (mpl->GetCargo( i ).GetCategory().find(
"upgrades" ) == 0) {
7676 if (recharge > maxrecharge->
recharge)
7689 extern bool isWeapon( std::string name );
7694 assert( (item!=NULL) |!
"Unit::RepairUpgradeCargo got a null item." );
7699 double price = itemPrice;
7700 if ( !credits || price <= (*credits) ) {
7701 if (credits) (*credits) -= price;
7703 unsigned int nummounts = this->GetNumMounts();
7704 bool complete =
false;
7705 for (
unsigned int i = 0; i < nummounts; ++i)
7711 if (this->mounts[i].functionality < 1.0f) {
7712 this->mounts[i].functionality = 1.0f;
7715 if (this->mounts[i].maxfunctionality < 1.0f) {
7716 this->mounts[i].maxfunctionality = 1.0f;
7719 if (complete)
break;
7727 bool notadditive = (item->
GetContent().find(
"add_" ) != 0 && item->
GetContent().find(
"mult_" ) != 0);
7729 Cargo itemCopy = *item;
7733 double price =
RepairPrice( percentage, itemPrice );
7734 if ( !credits || price <= (*credits) ) {
7736 (*credits) -= price;
7738 this->Upgrade( un, 0, 0, 0,
true, percentage,
makeTemplateUpgrade( this->name, this->faction ) );
7765 vector< Cargo >::iterator mycargo = std::find( pImage->cargo.begin(), pImage->cargo.end(), tmp );
7766 if ( mycargo == pImage->cargo.end() ) {
7776 price = (*mycargo).price;
7786 const Unit *templ = NULL;
7787 const Unit *downgradelimit = NULL;
7788 static bool staticrem =
7792 for (
unsigned int i = 0; i < mylist.size(); ++i) {
7793 bool removethis =
true ;
7795 if ( mode != 2 || (!downgrade) ) {
7799 mylist[i].cargo.GetContent(),
7804 if ( NewPart->
name ==
string(
"LOAD_FAILED" ) ) {
7805 const Unit *NewPart =
7813 if ( NewPart->
name !=
string(
"LOAD_FAILED" ) ) {
7814 int maxmountcheck = NewPart->
GetNumMounts() ? GetNumMounts() : 1;
7815 char *unitdir =
GetUnitDir( name.get().c_str() );
7816 string templnam = string( unitdir )+
".template";
7817 string limiternam = string( unitdir )+
".blank";
7820 if (templ == NULL) {
7826 if ( templ->
name == std::string(
"LOAD_FAILED" ) )
7830 if (downgradelimit == NULL) {
7836 if ( downgradelimit->
name == std::string(
"LOAD_FAILED" ) )
7837 downgradelimit = NULL;
7840 for (
int m = 0; m < maxmountcheck; ++m) {
7842 for (
un_iter ui = getSubUnits(); s == 0 || ( (*ui) != NULL ); ++ui, ++s) {
7845 if ( canDowngrade( NewPart, m, s, percent, downgradelimit ) ) {
7846 if (percent > MyPercentMin) {
7851 }
else if ( canUpgrade( NewPart, m, s, mode,
false , percent, templ ) ) {
7864 if (downgrade && staticrem) {
7865 mylist.erase( mylist.begin()+i );
7878 if (filtercargoprice) {
7881 for (
unsigned int i = 0; i < mylist.size(); ++i)
7882 if (mylist[i].cargo.price > cp->
credits) {
7887 return FilterDowngradeList( mylist,
false );
7892 return ((flightgroup != NULL) && (flightgroup->name ==
"Base"));
7897 return ( (
float) ( rand() )/RAND_MAX )*(max-
min)+min;
7911 for (
un_iter iter = getSubUnits(); (un = *iter); ++iter) {
7931 bool isplayer =
false;
7936 if ( index == (UINT_MAX-1) ) {
7939 name =
"return_to_cockpit";
7942 string playernum = string(
"player" )+( (pilotnum == 0) ?
string(
"" ) :
XMLSupport::tostring( pilotnum ) );
7945 dockedPilot.
content =
"return_to_cockpit";
7946 dockedPilot.
mass = .1;
7950 if (index == UINT_MAX) {
7954 string playernum = string(
"player" )+( (pilotnum == 0) ?
string(
"" ) :
XMLSupport::tostring( pilotnum ) );
7957 ejectedPilot.
content =
"eject";
7958 ejectedPilot.
mass = .1;
7960 tmp = &ejectedPilot;
7962 if ( index < numCargo() )
7966 string tmpcontent = tmp->
content;
7968 tmpcontent =
"Mission_Cargo";
7969 const int ulen = strlen(
"upgrades" );
7971 if ( (!tmp->
mission) && memcmp( tmp->
GetCategory().c_str(),
"upgrades", ulen ) == 0 )
7972 tmpcontent =
"Space_Salvage";
7975 const int sslen = strlen(
"starships" );
7978 if ( (!tmp->
mission) && memcmp( tmp->
GetCategory().c_str(),
"starships", sslen ) == 0 ) {
7979 string ans = tmpcontent;
7980 string::size_type blank = ans.find(
".blank" );
7981 if (blank != string::npos)
7982 ans = ans.substr( 0, blank );
8000 "1" ) )*3.1415926536/180;
8004 "60" ) )*3.1415926536/180;
8007 "0" ) )*3.1415926536/180;
8008 if (tmpcontent ==
"eject") {
8025 cargo->
owner =
this;
8028 if (eject_attacks) {
8035 }
else if (tmpcontent ==
"return_to_cockpit") {
8049 cargo->
owner =
this;
8052 static float ejectcargotime =
8054 if (cargotime == 0.0) {
8072 string tmpnam = tmpcontent+
".cargo";
8073 static std::string nam(
"Name" );
8076 tmpnam =
"generic_cargo";
8094 if (cargo->
name ==
"LOAD_FAILED") {
8109 static bool all_rotate_same =
8111 if (all_rotate_same && arot != 0) {
8112 float tmp = rotation.Magnitude();
8114 rotation.Scale( 1/tmp );
8118 if ( 0 && cargo->
rSize() >= rSize() ) {
8121 Vector tmpvel = -Velocity;
8122 if (tmpvel.MagnitudeSquared() < .00001) {
8123 tmpvel =
randVector( -rSize(), rSize() ).Cast();
8124 if (tmpvel.MagnitudeSquared() < .00001)
8125 tmpvel =
Vector( 1, 1, 1 );
8129 static float eject_cargo_offset =
8133 loc += tmpvel*1.5*rSize()+
randVector( -.5*rSize()+(index == UINT_MAX ? eject_cargo_offset/2 : 0),
8134 .5*rSize()+(index == UINT_MAX ? eject_cargo_offset : 0) );
8137 this->GetOrientation( p, q, r );
8142 cargo->
owner =
this;
8151 if (name.length() > 0)
8154 cargo->
name = tmpcontent;
8161 cp->
SetParent( cargo,
"",
"", Position() );
8162 if (tmpcontent ==
"return_to_cockpit") {
8163 static bool simulate_while_at_base =
8172 cargo->
owner =
this;
8175 cargo->
Position() = this->Position();
8189 cargo->
owner =
this;
8193 if ( (
unsigned int) index != ( (
unsigned int) -1 ) && (
unsigned int) index != ( (
unsigned int) -2 ) )
8194 if ( index < pImage->cargo.size() )
8195 RemoveCargo( index, 1,
true );
8203 if ( !( i < pImage->cargo.size() ) ) {
8204 fprintf( stderr,
"(previously) FATAL problem...removing cargo that is past the end of array bounds." );
8207 Cargo *carg = &(pImage->cargo[i]);
8220 Mass -= quantity*carg->
mass;
8224 quantity, 0, 0, getStarSystem()->GetZone() );
8227 if (carg->
quantity <= 0 && eraseZero)
8228 pImage->cargo.erase( pImage->cargo.begin()+i );
8245 carg.
quantity, 0, 0, getStarSystem()->GetZone() );
8250 pImage->cargo.push_back( carg );
8262 return pImage->HiddenCargoVolume;
8272 float total_volume = carg.
quantity*carg.
volume+( upgradep ? getUpgradeVolume() : getCargoVolume() );
8273 if ( total_volume <= ( upgradep ? getEmptyUpgradeVolume() : getEmptyCargoVolume() ) )
8277 for (
un_kiter i = viewSubUnits(); (un = *i) != NULL; ++i)
8287 return pImage->CargoVolume;
8292 return pImage->UpgradeVolume;
8298 for (
unsigned int i = 0; i < pImage->cargo.size(); ++i)
8300 result += pImage->cargo[i].quantity*pImage->cargo[i].volume;
8307 for (
unsigned int i = 0; i < pImage->cargo.size(); ++i)
8309 result += pImage->cargo[i].quantity*pImage->cargo[i].volume;
8320 return pImage->cargo[i];
8325 return pImage->cargo[i];
8333 std::string::const_iterator aiter = a.
GetCategory().begin();
8334 std::string::const_iterator aend = a.
GetCategory().end();
8335 std::string::const_iterator biter = b.
GetCategory().begin();
8336 std::string::const_iterator bend = b.
GetCategory().end();
8337 for (; aiter != aend && biter != bend; ++aiter, ++biter) {
8338 char achar = *aiter;
8339 char bchar = *biter;
8351 vector< Cargo >::iterator Begin = pImage->cargo.begin();
8352 vector< Cargo >::iterator End = pImage->cargo.end();
8353 vector< Cargo >::iterator lbound = pImage->cargo.end();
8354 vector< Cargo >::iterator ubound = pImage->cargo.end();
8356 Cargo beginningtype;
8359 lbound = std::lower_bound( Begin, End, beginningtype, Comp );
8360 beginningtype.
content =
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
8361 ubound = std::upper_bound( Begin, End, beginningtype, Comp );
8362 begin = lbound-Begin;
8378 const Unit *thus =
this;
8389 unsigned int *ind = index_cache_table.
Get( s );
8391 if ( *ind < pImage->cargo.size() ) {
8392 Cargo *guess = &pImage->cargo[*ind];
8401 vector< Cargo >::iterator tmp = std::find( pImage->cargo.begin(), pImage->cargo.end(), searchfor );
8402 if ( tmp == pImage->cargo.end() )
8404 if ( (*tmp).content == searchfor.
content ) {
8405 i = ( tmp-pImage->cargo.begin() );
8407 unsigned int *tmp =
new unsigned int;
8409 if ( index_cache_table.
Get( s ) )
8410 index_cache_table.
Delete( s );
8412 index_cache_table.
Put( s, tmp );
8420 vector< Cargo >::iterator tmp = ( std::find( pImage->cargo.begin(), pImage->cargo.end(), searchfor ) );
8421 if ( tmp == pImage->cargo.end() )
8423 i = ( tmp-pImage->cargo.begin() );
8429 return pImage->cargo.size();
8435 string mangled = pImage->cargo[i].content;
8436 static float scramblingmanifest =
8441 for (string::iterator i = mangled.begin(); i != mangled.end(); ++i) {
8443 (*i) = toupper( *i );
8444 last = (*i ==
' ' || *i ==
'_');
8447 if (CourseDeviation( oldspd, GetVelocity() ) > scramblingmanifest)
8448 for (string::iterator i = mangled.begin(); i != mangled.end(); ++i)
8449 (*i) += (rand()%3-1);
8455 if (i < 0 || i >= pImage->cargo.size() || !buyer->
CanAddCargo( pImage->cargo[i] ) || Mass < pImage->cargo[i].mass)
8457 carg = pImage->cargo[i];
8458 if (quantity > pImage->cargo[i].quantity)
8459 quantity = pImage->cargo[i].
quantity;
8463 creds += quantity*carg.
price;
8469 RemoveCargo( i, quantity );
8477 vector< Cargo >::iterator mycargo = std::find( pImage->cargo.begin(), pImage->cargo.end(), tmp );
8478 if ( mycargo == pImage->cargo.end() )
8480 return SellCargo( mycargo-pImage->cargo.begin(), quantity, creds, carg, buyer );
8485 if (!CanAddCargo( carg ) || creds < carg.
quantity*carg.
price)
8499 if (quantity > (
unsigned int) soldcargo.
quantity)
8504 if ( BuyCargo( soldcargo, creds ) ) {
8514 if ( seller->
GetCargo( cargo, i ) )
8515 return BuyCargo( i, quantity, seller, creds );
8525 void Unit::ImportPartList(
const std::string &category,
float price,
float pricedev,
float quantity,
float quantdev )
8528 float minprice = FLT_MAX;
8530 for (
unsigned int j = 0;
j < numcarg; ++
j)
8533 if (price < minprice)
8535 else if (price > maxprice)
8538 for (
unsigned int i = 0; i < numcarg; ++i) {
8541 static float aveweight =
8544 float baseprice = c.
price;
8545 c.
price *= price-pricedev;
8549 c.
price += pricedev*2*( (
float) rand() )/RAND_MAX;
8551 c.
price = ( c.
price+(baseprice*aveweight) )/(aveweight+1);
8556 else if (maxprice > minprice+.01) {
8557 float renormprice = (baseprice-minprice)/(maxprice-minprice);
8558 static float maxpricequantadj =
8560 static float minpricequantadj =
8563 renormprice = pow( renormprice, powah );
8564 renormprice *= (maxpricequantadj-minpricequantadj);
8566 if (renormprice > .001) {
8573 if (c.
price < minprice)
8576 AddCargo( c,
false );
8584 float mass = un->
Mass;
8586 for (
unsigned int i = 0; i < un->
pImage->
cargo.size(); ++i)
8602 return string(
"\" frontrighttop=\"" )+
tostring( un->
shield.
shield8.frontrighttop )+string(
"\" backrighttop=\"" )
8605 +string(
"\" backlefttop=\"" )+
tostring( un->
shield.
shield8.backlefttop )+string(
"\" frontrightbottom=\"" )
8609 +string(
"\" frontleftbottom=\"" )+
tostring( un->
shield.
shield8.frontleftbottom )+string(
"\" backleftbottom=\"" )
8618 return string(
"" );
8628 result += string(
"\" weapon=\"" )+(un->
mounts[i].type->weapon_name);
8629 if (un->
mounts[i].ammo != -1)
8631 if (un->
mounts[i].volume != -1)
8650 return string(
"" );
8667 return string(
"destroyed_blank" );
8701 unsigned char retA = unitRole();
8702 unsigned char retB = attackPreference();
8705 if (retA == inert || retB == inert) {
8706 static const std::string INERT(
"INERT");
8717 for (
unsigned int i = 0; i+1 < un->
pImage->
cargo.size(); ++i)
8742 string missioncargo;
8750 +string(
"\"/>\n" );
8757 return string(
"0" );
8759 string retval(
"" );
8762 for (
unsigned int kk = 1; kk < un->
pImage->
cargo.size(); ++kk) {
8764 retval += string(
"\t\t</Category>\n\t\t<Category file=\"" )+un->
pImage->
cargo[kk].GetCategory()+string(
8768 retval += string(
"\t\t</Category>\n\t\t<Category file=\"nothing" );
8770 retval = string(
"nothing" );
8777 if (ViewComputerData().max_ab_speed() > .001)
8778 return ( OriginalCourse-(FinalCourse) ).Magnitude()/ViewComputerData().max_ab_speed();
8780 return (FinalCourse-OriginalCourse).Magnitude();
8791 if ( getStarSystem()->RemoveUnit(
this ) ) {
8792 this->RemoveFromSystem();
8793 this->Target( NULL );
8797 if (an_active_cockpit != NULL) {
8801 activeStarSystem = Current;
8817 if (name.find(
"Weapon" ) != std::string::npos)
8819 if (name.find(
"SubUnit" ) != std::string::npos)
8821 if (name.find(
"Ammunition" ) != std::string::npos)
8826 #define REPAIRINTEGRATED( functionality, max_functionality ) \
8828 if (functionality < max_functionality) \
8830 (functionality) += ammt_repair; \
8831 if ( (functionality) > (max_functionality) ) \
8832 (functionality) = (max_functionality); \
8841 if ( (repairtime <= 0) || (checktime <= 0) )
return;
8842 if (pImage->repair_droid > 0) {
8844 unsigned int numcargo = numCargo();
8846 if ( pImage->next_repair_cargo >= numCargo() )
8847 pImage->next_repair_cargo = 0;
8849 float percentoperational = 1;
8854 && ( ( percentoperational =
8856 if (pImage->next_repair_time == -FLT_MAX) {
8862 static std::string loadfailed(
"LOAD_FAILED" );
8863 if (up->
name == loadfailed) {
8864 printf(
"Bug: Load failed cargo encountered: report to hellcatv@hotmail.com\n" );
8866 double percentage = 0;
8870 this->faction ),
false,
8872 if (percentage == 0) {
8874 stderr,
"Failed repair for unit %s, cargo item %d: %s (%s) - please report error\n",
8875 name.get().c_str(), pImage->next_repair_cargo, carg->
GetContent().c_str(),
8880 pImage->next_repair_time = -FLT_MAX;
8881 ++(pImage->next_repair_cargo);
8884 ++(pImage->next_repair_cargo);
8889 REPAIRINTEGRATED( pImage->LifeSupportFunctionality, pImage->LifeSupportFunctionalityMax );
8890 REPAIRINTEGRATED( pImage->fireControlFunctionality, pImage->fireControlFunctionalityMax );
8891 REPAIRINTEGRATED( pImage->SPECDriveFunctionality, pImage->SPECDriveFunctionalityMax );
8892 REPAIRINTEGRATED( pImage->CommFunctionality, pImage->CommFunctionalityMax );
8897 if (pImage->cockpit_damage[which] < pImage->cockpit_damage[which+numg]) {
8898 pImage->cockpit_damage[which] += hud_repair_quantity;
8899 if (pImage->cockpit_damage[which] > pImage->cockpit_damage[which+numg])
8901 pImage->cockpit_damage[which] = pImage->cockpit_damage[which+numg];
8903 if ( mounts.size() ) {
8904 static float mount_repair_quantity =
8907 if (mounts[i].functionality < mounts[i].maxfunctionality) {
8908 mounts[i].functionality += mount_repair_quantity;
8909 if (mounts[i].functionality > mounts[i].maxfunctionality)
8910 mounts[i].functionality = mounts[i].maxfunctionality;
8916 #undef REPAIRINTEGRATED
8920 if (how != tractorImmune)
8921 return (getTractorability()&how) == how;
8924 return getTractorability() == tractorImmune;
8929 tractorability_flags = how;
8934 static bool tractorability_mask_init =
false;
8935 static unsigned char tractorability_mask;
8936 if (!tractorability_mask_init) {
8937 std::string stractorability_mask =
vs_config->
getVariable(
"physics",
"PlayerTractorabilityMask",
"p" );
8938 if ( !stractorability_mask.empty() ) {
8939 tractorability_mask = tractorImmune;
8940 if (stractorability_mask.find_first_of(
"pP" ) != string::npos)
8941 tractorability_mask |= tractorPush;
8942 if (stractorability_mask.find_first_of(
"iI" ) != string::npos)
8943 tractorability_mask |= tractorIn;
8945 tractorability_mask = tractorPush;
8947 tractorability_mask_init =
true;
8949 unsigned char tflags;
8951 tflags = tractorability_flags&tractorability_mask;
8954 tflags = tractorability_flags;
8961 if ( getStarSystem() )
8962 getStarSystem()->RequestPhysics(
this, cur_sim_queue_slot );
8991 for(
unsigned int i = 0; i < in.length(); i++)
8995 case 'A': out +=
'a';
break;
8996 case 'B': out +=
'b';
break;
8997 case 'C': out +=
'c';
break;
8998 case 'D': out +=
'd';
break;
8999 case 'E': out +=
'e';
break;
9000 case 'F': out +=
'f';
break;
9001 case 'G': out +=
'g';
break;
9002 case 'H': out +=
'h';
break;
9003 case 'I': out +=
'i';
break;
9004 case 'J': out +=
'j';
break;
9005 case 'K': out +=
'k';
break;
9006 case 'L': out +=
'l';
break;
9007 case 'M': out +=
'm';
break;
9008 case 'N': out +=
'n';
break;
9009 case 'O': out +=
'o';
break;
9010 case 'P': out +=
'p';
break;
9011 case 'Q': out +=
'q';
break;
9012 case 'R': out +=
'r';
break;
9013 case 'S': out +=
's';
break;
9014 case 'T': out +=
't';
break;
9015 case 'U': out +=
'u';
break;
9016 case 'V': out +=
'v';
break;
9017 case 'W': out +=
'w';
break;
9018 case 'X': out +=
'x';
break;
9019 case 'Y': out +=
'y';
break;
9020 case 'Z': out +=
'z';
break;
9033 string fnam(filename);
9034 string::size_type pos = fnam.find(
'.');
9035 string anifilename = fnam.substr(0, pos);
9038 anifilename += string(
"_") + string(animationExt);
9040 std::vector< Mesh* > *meshes =
new vector<Mesh *>();
9042 char count[30] =
"1";
9043 string dir = anifilename;
9046 sprintf( count,
"%d", i );
9047 string unit_name =
toLowerCase(anifilename) +
"_";
9060 string path = dir +
"/" + unit_name +
".bfxm";
9064 meshes->push_back( m );
9065 #ifdef DEBUG_MESH_ANI
9075 if( meshes->size() != 0 )
9078 string animationName;
9079 sprintf( count,
"%lu", meshes->size() );
9081 animationName = string(count);
9083 animationName = animationExt;
9086 int numFrames = meshes->size();
9091 cerr <<
"Animation data loaded for unit: " << string(filename) <<
", named " <<
uniqueUnitName <<
" - with: " << numFrames <<
" frames." << endl;
9101 #ifdef DEBUG_MESH_ANI
9102 std::cerr <<
"Starting animation step of Unit: " <<
uniqueUnitName << std::endl;
9108 int numvertices = 0;
9112 #ifdef DEBUG_MESH_ANI
9113 std::cerr <<
"vertices changed from: " << numvold <<
" to: " << numvertices << std::endl;
9118 #ifdef DEBUG_MESH_ANI
9129 #ifdef DEBUG_MESH_ANI
9130 std::cerr <<
"Ending animation step of Unit: " <<
uniqueUnitName << std::endl;
9136 std::map< string, Unit * >::iterator pos;
9137 for(pos =
Units.begin(); pos !=
Units.end(); ++pos)
9140 if (pos->second->pMeshAnimation->curtime >= pos->second->pMeshAnimation->timePerFrame()) {
9141 pos->second->pMeshAnimation->AnimationStep();
9142 pos->second->pMeshAnimation->curtime = 0.0;
9159 infiniteLoop =
true;
9161 infiniteLoop =
false;
9181 string strname(name);
9278 if (capability == 0)
9280 else if ((capability == 1) || (capability == 2))
9283 return (capability & Capability::IFF_FRIEND_FOE);
9289 if ((capability == 0) || (capability == 1))
9291 else if (capability == 2)
9294 return (capability & Capability::IFF_OBJECT_RECOGNITION);
9299 return (capability & Capability::IFF_THREAT_ASSESSMENT);