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
00027
00028 #include "FSServer.h"
00029 #include "MineField.h"
00030 #include <math.h>
00031 #include <stdlib.h>
00032 #include <iostream>
00033
00034 #ifdef _DEBUG
00035 #define new DEBUG_NEW
00036 #endif
00037
00038 int Midpoint(int a, int b)
00039 {
00040 if (a < b)
00041 return a + ((b - a +1)>>1);
00042 return b + ((a - b +1)>>1);
00043 }
00044
00045 MineField::~MineField(void)
00046 {}
00047
00048 MineField::MineField(int mineType, const Location & L, int numMines, Player * owner)
00049 {
00050 posX = L.GetPosX();
00051 posY = L.GetPosY();
00052 mNumMines = numMines;
00053 mMineType = mineType;
00054 mOwner = owner;
00055 mID = mOwner->GetMineFieldID();
00056 }
00057
00058 long MineField::GetScanSpace() const
00059 {
00060 return GetOwner()->MineFieldScanning() ? long(GetRadius()) : -1;
00061 }
00062
00063 long MineField::GetCloak(const Player * p, bool pen) const
00064 {
00065 return (pen || mHadSeen[p->GetID()-1]) ? 0 : Rules::GetConstant("WormholeCloak", 75);
00066 }
00067
00068 void MineField::AddMines(const Location & L, int n)
00069 {
00070
00071 mNumMines += n;
00072 }
00073
00074 void MineField::Sweep(const Fleet * F)
00075 {
00076 double dist = Distance(*F);
00077 if (dist > GetRadius())
00078 return;
00079
00080 long swept = F->GetSweeping() / Rules::GetArrayValue("MineSweepDivisor", mMineType);
00081 if (mNumMines - swept < dist * dist)
00082 swept = mNumMines - long(dist * dist);
00083
00084 mNumMines -= swept;
00085
00086
00087 Message * mess;
00088 mess = mOwner->AddMessage("Your minefield swept", this);
00089 mess->AddLong("Mines swept", swept);
00090
00091 mess = F->NCGetOwner()->AddMessage("You've swept a minefield", this);
00092 mess->AddItem("Sweeper", F);
00093 mess->AddLong("Mines swept", swept);
00094 }
00095
00096 void MineField::Decay(int numPlanets)
00097 {
00098 double d = Rules::GetFloat("MineFieldBaseDecayRate")
00099 + Rules::GetFloat("MineFieldPlanetDecayRate") * numPlanets;
00100 d = min(d, Rules::GetFloat("MineFieldMaxDecayRate"));
00101
00102 long decay = long(mNumMines * d * GetOwner()->MineDecayFactor() + .5);
00103 decay = max(decay, long(10 * GetOwner()->MineDecayFactor() + .5));
00104 mNumMines -= decay;
00105 }
00106
00107 void MineField::ReduceFieldCollision()
00108 {
00109 if (mNumMines <= 10)
00110 mNumMines = 0;
00111 else if (mNumMines <= 200)
00112 mNumMines -=10;
00113 else if (mNumMines <= 1000)
00114 mNumMines = static_cast<int>(mNumMines * 0.95);
00115 else if (mNumMines <= 5000)
00116 mNumMines -= 50;
00117 else mNumMines = static_cast<int>(mNumMines * 0.95);
00118 }
00119
00120 bool MineField::TestCollide(const Location & L, int warp)
00121 {
00122 long radius = long(GetRadius() + .5);
00123 int negRadius = -radius;
00124 int dx = L.GetPosX() - posX;
00125 if (dx > radius || dx < negRadius) return false;
00126 int dy = L.GetPosY() - posY;
00127 if (dy > radius || dy < negRadius) return false;
00128
00129 int dr2 = dx*dx+dy*dy;
00130 int r2 = radius*radius;
00131 if (r2 >= dr2)
00132 {
00133 if (warp <= Rules::GetArrayValue("MineSafeSpeed", mMineType))
00134 return false;
00135
00136 double hitChance = double(Rules::GetArrayValue("MineHitChancePerWarp", mMineType)) / 10000 *
00137 (warp - Rules::GetArrayValue("MineSafeSpeed", mMineType));
00138 if (Randodd(hitChance))
00139 return true;
00140 }
00141 return false;
00142 }
00143
00144 bool MineField::CollisionPossible (const Location & L1, const Location & L2)
00145 {
00146
00147 if (!RectFilter(L1.GetPosX(),L1.GetPosY(),L2.GetPosX(),L2.GetPosY()))
00148 return false;
00149
00150
00151 long x1= L1.GetPosX();
00152 long y1= L1.GetPosY();
00153 long x2= L2.GetPosX();
00154 long y2= L2.GetPosY();
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 int L = static_cast<int>(sqrt((double)((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))));
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 int r= ( (y1-posY)*(y1-y2)-(y1-posY)*(y2-y1) ) / (L * L) ;
00184
00185
00186 if (r<0)
00187 {
00188 return InField(x1,y1);
00189 }
00190 if (r>1)
00191 {
00192 return InField(x2,y2);
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 int s = ((y1-posY)*(x2-x1)-(x1-posX)*(y2-y1)) / (L*L);
00218
00219
00220
00221 return (GetRadius() >= s*L);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00270
00271 bool MineField::InField(int x, int y)
00272 {
00273
00274 return (mNumMines >= ((x-posX)*(x-posX) +
00275 (y - posY)*(y - posY)));
00276 }
00277
00278 bool MineField::InField(const Location & L)
00279 {
00280 return InField(L.GetPosX(), L.GetPosY());
00281 }
00282
00283
00284 bool MineField::RectFilter(int x1, int y1, int x2, int y2)
00285 {
00286
00287
00288 if (x1 > x2)
00289 {
00290 int temp = x1;
00291 x1 = x2;
00292 x2= temp;
00293 }
00294 if (y1 > y2)
00295 {
00296 int temp = y1;
00297 y1 = y2;
00298 y2= temp;
00299 }
00300 int X1, Y1, X2, Y2;
00301 long radius = long(GetRadius() + .5);
00302 X1 = posX - radius;
00303 X2 = posX + radius;
00304 Y1 = posY - radius;
00305 Y2 = posY + radius;
00306
00307 return !((x2 < X1) || (x1 > X2) || (y2 < Y1) || (y1 > Y2));
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388