00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "FSServer.h"
00027
00028 #include "Packet.h"
00029
00030 #ifdef _DEBUG
00031 #define new DEBUG_NEW
00032 #endif
00033
00034
00035
00036 Packet::Packet(const CargoHolder &source, long speed, long driverSpeed, Planet * destination)
00037 : CargoHolder(source),
00038 mSpeed(speed),
00039 mDriverSpeed(driverSpeed),
00040 mDestination(destination),
00041 mFirstYear(true)
00042 {
00043 mID = TheGalaxy->GetPacketID();
00044 }
00045
00046 Packet::~Packet()
00047 {
00048 }
00049
00050 bool Packet::ParseNode(const TiXmlNode * node)
00051 {
00052 mFirstYear = false;
00053 if (!CargoHolder::ParseNode(node))
00054 return false;
00055
00056 mSpeed = GetLong(node->FirstChild("Speed"));
00057 if (mSpeed < 0) {
00058 Message * mess = NCGetOwner()->AddMessage("Error: Invalid packet speed");
00059 mess->AddLong("Speed", mSpeed);
00060 return false;
00061 }
00062
00063 mDestination = TheGalaxy->GetPlanet(GetString(node->FirstChild("Destination")));
00064 if (mDestination == NULL) {
00065 Message * mess = NCGetOwner()->AddMessage("Error: Invalid packet destination");
00066 mess->AddItem("Destination", GetString(node->FirstChild("Destination")));
00067 return false;
00068 }
00069
00070 TheGame->AddAlsoHere(this);
00071 return true;
00072 }
00073
00074 TiXmlNode * Packet::WriteNode(TiXmlNode * node, const Player * viewer) const
00075 {
00076 if (viewer != NULL && !SeenBy(viewer))
00077 return NULL;
00078
00079 CargoHolder::WriteNode(node, viewer);
00080 AddLong(node, "Speed", mSpeed);
00081 AddString(node, "Destination", mDestination->GetName().c_str());
00082
00083 return node;
00084 }
00085
00086 long Packet::GetCloak(const Player *, bool) const
00087 {
00088 return GetOwner()->InherentCloaking(HC_ALL);
00089 }
00090
00091 long Packet::GetScanPen() const
00092 {
00093 if (GetOwner()->PacketScanning())
00094 return mSpeed * mSpeed;
00095 else
00096 return -1;
00097 }
00098
00099 long Packet::GetScanSpace() const
00100 {
00101 if (GetOwner()->PacketScanning())
00102 return mSpeed * mSpeed;
00103 else
00104 return -1;
00105 }
00106
00107 void Packet::Collide()
00108 {
00109 Message * mess = mDestination->NCGetOwner()->AddMessage("Packet hit", mDestination);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 const Ship * defendingStarBase = mDestination->GetBaseDesign();
00120
00121 long defendingDriver = 0;
00122
00123 if (defendingStarBase != NULL) {
00124 long defendingDriver = defendingStarBase->GetDriverSpeed();
00125 defendingDriver += (defendingStarBase->CountDrivers());
00126 defendingDriver--;
00127
00128 }
00129
00130 long catchAs = defendingDriver * defendingDriver;
00131 const Player * defender = mDestination->NCGetOwner();
00132
00133 if (defender != NULL)
00134 catchAs = long(catchAs * defender->PacketCatchFactor());
00135
00136 long minsCaught;
00137
00138 long packetMass = GetCargoMass();
00139 mess->AddLong("Packet size", GetCargoMass());
00140
00141 double fractionCaught = double(GetSpeed() * GetSpeed()) / catchAs;
00142 for (CargoType i = 0; i < Rules::MaxMinType; i++)
00143 {
00144 minsCaught = int(GetContain(i) * fractionCaught + .5);
00145 packetMass -= minsCaught;
00146 minsCaught += int((GetContain(i) - minsCaught + .5) / 3.0);
00147 mDestination->AdjustAmounts(i, minsCaught);
00148 }
00149
00150
00151
00152 double rawDamage = packetMass / 160;
00153
00154
00155
00156 rawDamage = rawDamage * (1.0 - mDestination->GetDefenseValue());
00157
00158
00159
00160
00161
00162 int killed = max(long(rawDamage * 100), long((rawDamage * mDestination->GetPopulation() + 500) / 1000));
00163 mDestination->AdjustAmounts(POPULATION, -killed);
00164 mess->AddLong("Colonists killed", killed);
00165
00166
00167
00168
00169
00170
00171
00172 long numDefs = mDestination->GetDefenses();
00173 long numDefsDestroyed;
00174 numDefsDestroyed = max(long(numDefs * rawDamage / 1000), long(rawDamage / 20));
00175 numDefsDestroyed = min(numDefsDestroyed, numDefs);
00176
00177 mDestination->AdjustDefenses(-numDefsDestroyed);
00178 mess->AddLong("Defenses destroyed", numDefsDestroyed);
00179
00180 if (GetOwner()->PacketTerraform()) {
00181
00182 }
00183 }
00184
00185 bool Packet::Move(bool FirstYear)
00186 {
00187 if (FirstYear != mFirstYear)
00188 return false;
00189
00190 long distance = mSpeed * mSpeed;
00191 if (mFirstYear)
00192 distance /= 2;
00193
00194 double mPX, mPY;
00195 MoveToward(*this, *mDestination, &mPX, &mPY, distance);
00196 Location pt;
00197 pt.SetLocation(long(mPX), long(mPY));
00198
00199 distance = long(Distance(pt));
00200 SetLocation(pt);
00201
00202 Decay(distance);
00203 if (GetCargoMass() == 0)
00204 return true;
00205
00206 if (IsWith(*mDestination)) {
00207 Collide();
00208 return true;
00209 }
00210
00211 if (mFirstYear) {
00212 mFirstYear = false;
00213 TheGame->AddAlsoHere(this);
00214 } else
00215 TheGame->MoveAlsoHere(this);
00216
00217 return false;
00218 }
00219
00220 void Packet::Decay(long distance)
00221 {
00222 double decayRate;
00223 long speed = GetSpeed();
00224 long firingDriver = GetDriverSpeed();
00225 const Player * owner =NCGetOwner();
00226
00227
00228 if (owner->PacketDecayPenalty())
00229 speed = max(speed, firingDriver) + 1;
00230
00231 decayRate = (double)Rules::GetArrayFloat("PacketDecayRates", min(3L, speed - this->GetDriverSpeed())) / 100;
00232 decayRate *= owner->PacketDecayFactor();
00233 if (GetSpeed() * GetSpeed() > distance)
00234 decayRate *= GetSpeed() * GetSpeed() / distance;
00235
00236 long decay;
00237 long mindecay = long(Rules::GetConstant("PacketMinimumDecay") * owner->PacketDecayFactor() + .5);
00238 for (int i = 0; i < Rules::MaxMinType; i++) {
00239 decay = min(GetContain(i), max(mindecay, long(GetContain(i) * decayRate + .5)));
00240 AdjustAmounts(i, -decay);
00241 }
00242
00243 mMaxSize = GetCargoMass();
00244 }