EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Missile.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Allan
24 */
25 
26 #include "eve-server.h"
27 
28 #include "Client.h"
29 #include "EVEServerConfig.h"
30 #include "Profiler.h"
31 #include "character/Character.h"
33 #include "system/DestinyManager.h"
34 #include "ship/Missile.h"
35 #include "ship/Ship.h"
37 #include "system/Damage.h"
38 
40 : DynamicSystemEntity(self, services, pSystem),
41  m_modRef(modRef),
42  m_targetSE(tSE),
43  m_fromSE(pSE),
44  m_hitTimer(0),
45  m_lifeTimer(0),
46  m_damageMod(1),
47  m_alive(true),
48  m_orbitingID(0),
49  m_speed(0),
50  m_hullHP(self->GetAttribute(AttrHP).get_int())
51 {
52  if (pSE->HasPilot()) {
53  m_ownerID = pSE->GetPilot()->GetChar()->itemID();
54  } else {
55  m_ownerID = self->ownerID();
56  }
57 
58  m_warID = pSE->GetWarFactionID();
59  m_allyID = pSE->GetAllianceID();
60  m_corpID = pSE->GetCorporationID();
61 
62  double flightTime = self->GetAttribute(AttrExplosionDelay).get_float();
63 
64  // missile skills do not apply correctly in fx processor. not sure why yet.
65  if (pSE->HasPilot()) {
66  Character* pChar = pSE->GetPilot()->GetChar().get();
67  flightTime *= (1 + (0.1f * (pChar->GetSkillLevel(EvESkill::MissileBombardment, true)))); // 10% increase in flightTime
68 
69  self->MultiplyAttribute(AttrMaxVelocity, (1 + (0.1f * (pChar->GetSkillLevel(EvESkill::MissileProjection, true))))); // 10% increase in velocity
70  self->MultiplyAttribute(AttrAoeCloudSize, (1 - (0.05f * (pChar->GetSkillLevel(EvESkill::GuidedMissilePrecision, true))))); // 5% decrease in exp radius
71  self->MultiplyAttribute(AttrAoeVelocity, (1 + (0.1f * (pChar->GetSkillLevel(EvESkill::TargetNavigationPrediction, true))))); // 10% increase in exp velocity
72 
73  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::WarheadUpgrades, true)))); // 5% increase in damage (upped from 2%)
74  switch (m_self->groupID()) {
78  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::LightMissiles, true)))); // 5% increase in damage
80  m_damageMod *= (1 + (0.03f * (pChar->GetSkillLevel(EvESkill::LightMissileSpecialization, true)))); // 3% increase in damage
81  } break;
85  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::HeavyMissiles, true)))); // 5% increase in damage
87  m_damageMod *= (1 + (0.03f * (pChar->GetSkillLevel(EvESkill::HeavyMissileSpecialization, true)))); // 3% increase in damage
88  } break;
92  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::CruiseMissiles, true)))); // 5% increase in
94  m_damageMod *= (1 + (0.03f * (pChar->GetSkillLevel(EvESkill::CruiseMissileSpecialization, true)))); // 3% increase in damage
95  } break;
98  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::Torpedoes, true)))); // 5% increase in damage
100  m_damageMod *= (1 + (0.03f * (pChar->GetSkillLevel(EvESkill::TorpedoSpecialization, true)))); // 3% increase in damage
101  } break;
104  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::Rockets, true)))); // 5% increase in damage
106  m_damageMod *= (1 + (0.03f * (pChar->GetSkillLevel(EvESkill::RocketSpecialization, true)))); // 3% increase in damage
107  } break;
109  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::DefenderMissiles, true)))); // 5% increase in damage
110  } break;
113  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::HeavyAssaultMissiles, true)))); // 5% increase in damage
115  m_damageMod *= (1 + (0.03f * (pChar->GetSkillLevel(EvESkill::HeavyAssaultMissileSpecialization, true)))); // 3% increase in damage
116  } break;
118  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::CitadelCruiseMissiles, true)))); // 5% increase in damage
119  } break;
121  m_damageMod *= (1 + (0.05f * (pChar->GetSkillLevel(EvESkill::CitadelTorpedoes, true)))); // 5% increase in damage
122  } break;
123  }
124  }
125 
127  if (IsOverloaded())
128  m_damageMod *= (1 + self->GetAttribute(AttrOverloadDamageModifier).get_float());
129 
130  flightTime *= sConfig.rates.missileTime;
131 
132  // if linked, update appropriate attributes
133  if (pMod != nullptr)
134  if (pMod->IsLinked()) {
136  m_damageMod *= mod;
137  flightTime *= mod;
138  m_hullHP *= mod;
139  }
140 
141  m_lifeTimer.Start(flightTime);
142 
143  //_log(DAMAGE__MESSAGE, "Created Missile object for %s (%u)", self.get()->name(), self.get()->itemID());
144 }
145 
147 {
148 
149 }
150 
152  if (!m_alive) {
153  Delete();
154  return;
155  }
156  if (m_lifeTimer.Check(false)) {
157  EndOfLife();
158  return;
159  }
160  double profileStartTime = GetTimeUSeconds();
161  /* Enable base call to Process Targeting and Movement */
163 
164  if (m_hitTimer.Check(false)) {
166  HitTarget();
167  }
168  if (sConfig.debug.UseProfiling)
169  sProfiler.AddTime(Profile::missile, GetTimeUSeconds() - profileStartTime);
170 }
171 
173 {
174  using namespace Destiny;
175  BallHeader head = BallHeader();
176  head.entityID = GetID();
177  head.mode = Ball::Mode::MISSILE;
178  head.radius = GetRadius();
179  head.posX = x();
180  head.posY = y();
181  head.posZ = z();
182  head.flags = Ball::Flag::IsFree;
183  into.Append( head );
184  MassSector mass = MassSector();
185  mass.mass = m_destiny->GetMass();
186  mass.cloak = 0;
187  mass.harmonic = m_harmonic;
188  mass.corporationID = m_corpID;
189  mass.allianceID = (IsAlliance(m_allyID) ? m_allyID : -1);
190  into.Append( mass );
191  DataSector data = DataSector();
192  data.maxSpeed = m_speed;
193  data.velX = m_destiny->GetVelocity().x;
194  data.velY = m_destiny->GetVelocity().y;
195  data.velZ = m_destiny->GetVelocity().z;
196  data.inertia = m_destiny->GetInertia();
198  into.Append( data );
199  MISSILE_Struct miss;
200  miss.ownerID = m_ownerID;
201  miss.formationID = 0xFF;
203  miss.targetID = m_destiny->GetTargetID();
204  miss.followRange = (float)m_destiny->GetFollowDistance();
205  miss.x = x();
206  miss.y = y();
207  miss.z = z();
208  into.Append(miss);
209 
210  _log(SE__DESTINY, "Missile::EncodeDestiny(): %s - id:%li, mode:%u, flags:0x%X", GetName(), head.entityID, head.mode, head.flags);
211 }
212 
214  _log(SE__SLIMITEM, "MakeSlimItem for Missile %u", m_self->itemID());
215  PyDict *slim = new PyDict();
216  slim->SetItemString("itemID", new PyLong(m_self->itemID()));
217  slim->SetItemString("typeID", new PyInt(m_self->typeID()));
218  slim->SetItemString("groupID", new PyInt(m_self->groupID()));
219  slim->SetItemString("categoryID", new PyInt(m_self->categoryID()));
220  slim->SetItemString("name", new PyString(m_self->itemName()));
221  slim->SetItemString("sourceModuleID", new PyInt(m_modRef->itemID()));
222  slim->SetItemString("corpID", IsCorp(m_corpID) ? new PyInt(m_corpID) : PyStatic.NewNone());
223  slim->SetItemString("allianceID", IsAlliance(m_allyID) ? new PyInt(m_allyID) : PyStatic.NewNone());
224  slim->SetItemString("warFactionID", IsFaction(m_warID) ? new PyInt(m_warID) : PyStatic.NewNone());
225  slim->SetItemString("securityStatus", new PyFloat(0/*pChar->GetSecurityRating()*/));
226  slim->SetItemString("ownerID", new PyInt(m_ownerID)); // this is corp ID??
227  slim->SetItemString("numLaunchers", PyStatic.NewOne());
228  slim->SetItemString("nameID", new PyInt(0));
229  return(slim);
230 }
231 
232 void Missile::MakeDamageState(DoDestinyDamageState &into) {
233  into.shield = 1;
234  into.recharge = 10000;
235  into.timestamp = GetFileTimeNow();
236  into.armor = 1;
237  into.structure = 1.0f - (m_self->GetAttribute(AttrDamage).get_float() / m_self->GetAttribute(AttrHP).get_float());
238 }
239 
241  // Create Damage object:
243 
244  /* this is damage formula for missiles
245  * Damage = D * MIN(1, Sr/Er, (Ev/V * Sr/Er)^(ln(DRF) / ln(DRS)) )
246  *
247  * D = base damage of the missile,
248  * Sr = signature radius of the target,
249  * Er = Explosion radius of the missile,
250  * Ev = Explosion Velocity of the missile,
251  * V = velocity of the target ship,
252  * DRF = damage reduction factor of the missile.
253  * DRS = damage reduction sensitivity of the missile.
254  * MIN being a function that chooses the lower of the given vaules,
255  * ln is natural logarithm.
256  */
257  double Sr = m_targetSE->GetSelf()->GetAttribute(AttrSignatureRadius).get_float(); // this is a default number, based on itemtype
258  double Er = m_self->GetAttribute(AttrAoeCloudSize).get_float(); // Explosion Radius
259  double Ev = m_self->GetAttribute(AttrAoeVelocity).get_float(); // Explosion Velocity
260  double DRF = m_self->GetAttribute(AttrAoeDamageReductionFactor).get_float(); // Damage Reduction Factor
261  double DRS = m_self->GetAttribute(AttrAoeDamageReductionSensitivity).get_float(); // Damage Reduction Sensitivity
262 
263  GPoint Vel = m_targetSE->GetVelocity();
264  double V = Vel.length();
265  if (V <= 0)
266  V = 1;
267 
268  double v1 = Sr/Er;
269  double v2 = pow(((Ev/V) * v1), (log(DRF) / log(DRS)));
270 
271  // apply damage modifier from char skills, if applicable
272  d *= m_damageMod;
273  // apply missile damage formula to computed total damage
274  d *= EvE::min1(v1, v2);
275 
277  m_alive = false;
278 }
279 
281  m_alive = false;
282  Delete();
283 }
284 
286  // cleanup here
287  if (m_alive)
288  return;
289  // do we need to do anything else here?
291 }
void Append(const T &value)
Appends a single value to buffer.
Definition: Buffer.h:437
#define sConfig
A macro for easier access to the singleton.
SystemEntity * m_fromSE
Definition: Missile.h:70
unsigned __int8 uint8
Definition: eve-compat.h:46
virtual void Process()
double GetFollowDistance()
virtual void Delete()
Definition: Missile.cpp:285
GaExpInl GaFloat length() const
Definition: GaTypes.h:156
#define _log(type, fmt,...)
Definition: logsys.h:124
void Disable()
Definition: timer.h:39
Python string.
Definition: PyRep.h:430
DestinyManager * m_destiny
Definition: SystemEntity.h:265
double GetRadius()
Definition: SystemEntity.h:208
Python's dictionary.
Definition: PyRep.h:719
uint32 m_ownerID
Definition: SystemEntity.h:283
virtual ShipSE * GetShipSE()
Definition: SystemEntity.h:137
ShipItemRef GetShipItemRef()
Definition: Ship.h:362
virtual void Process()
Definition: Missile.cpp:151
double y()
Definition: SystemEntity.h:214
virtual bool HasPilot()
Definition: SystemEntity.h:258
#define sProfiler
Definition: dbcore.cpp:39
uint32 GetStateStamp()
virtual Client * GetPilot()
Definition: SystemEntity.h:259
Python floating point number.
Definition: PyRep.h:292
const GVector & GetVelocity() const
virtual PyDict * MakeSlimItem()
Definition: Missile.cpp:213
double m_speed
Definition: Missile.h:85
InventoryItemRef m_modRef
Definition: Missile.h:71
double m_hullHP
Definition: Missile.h:86
CharacterRef GetChar() const
Definition: Client.h:164
GaFloat x
Definition: GaTypes.h:207
int32 m_harmonic
Definition: SystemEntity.h:276
uint32 GetTargetID()
const GVector & GetVelocity()
Definition: SystemEntity.h:240
virtual void Delete()
Missile(InventoryItemRef self, PyServiceMgr &services, SystemManager *pSystem, InventoryItemRef modRef, SystemEntity *tSE, SystemEntity *pSE, GenericModule *pMod=nullptr)
Definition: Missile.cpp:39
uint16 groupID() const
float GetSpeedFraction()
Definition: gpoint.h:33
InventoryItemRef m_self
Definition: SystemEntity.h:269
double GetTimeUSeconds()
Definition: utils_time.cpp:116
Generic class for buffers.
Definition: Buffer.h:40
InventoryItemRef GetSelf()
Definition: SystemEntity.h:202
uint32 m_corpID
Definition: SystemEntity.h:281
void HitTarget()
Definition: Missile.cpp:240
PyTuple * MakeDamageState()
Definition: Damage.h:33
Python integer.
Definition: PyRep.h:231
double GetInertia()
double z()
Definition: SystemEntity.h:215
int32 GetAllianceID()
Definition: SystemEntity.h:216
uint32 GetID()
Definition: SystemEntity.h:207
bool Check(bool reset=true)
Definition: timer.cpp:62
#define PyStatic
Definition: PyRep.h:1209
X * get() const
Definition: RefPtr.h:213
const char * GetName() const
Definition: SystemEntity.h:210
double x()
Definition: SystemEntity.h:213
bool m_alive
Definition: Missile.h:79
void MultiplyAttribute(uint16 attrID, EvilNumber num, bool notify=false)
Timer m_lifeTimer
Definition: Missile.h:77
#define IsCorp(itemID)
Definition: EVE_Defines.h:234
void EndOfLife()
Definition: Missile.cpp:280
double min1(double x, double y)
Definition: misc.cpp:150
GaFloat y
Definition: GaTypes.h:207
double GetFileTimeNow()
Definition: utils_time.cpp:84
uint32 GetCorporationID()
Definition: SystemEntity.h:218
const std::string & itemName() const
EvilNumber GetAttribute(const uint16 attrID) const
#define IsFaction(itemID)
Definition: EVE_Defines.h:250
int8 GetSkillLevel(uint16 skillTypeID, bool zeroForNotInjected=true) const
Definition: Character.cpp:575
SystemEntity * m_targetSE
Definition: Missile.h:69
virtual ~Missile()
Definition: Missile.cpp:146
#define IsAlliance(itemID)
Definition: EVE_Defines.h:244
float get_float()
Definition: EvilNumber.cpp:184
bool IsOverloaded()
Definition: Missile.h:64
bool ApplyDamage(Damage &d)
Definition: Damage.cpp:108
uint16 typeID() const
float m_damageMod
Definition: Missile.h:83
uint8 categoryID() const
GaFloat z
Definition: GaTypes.h:207
uint32 itemID() const
Definition: InventoryItem.h:98
int32 GetWarFactionID()
Definition: SystemEntity.h:217
Python long integer.
Definition: PyRep.h:261
Timer m_hitTimer
Definition: Missile.h:76
virtual void EncodeDestiny(Buffer &into)
Definition: Missile.cpp:172
void Start(uint32 setTimerTime=0, bool changeResetTimer=true)
Definition: timer.cpp:81
uint8 GetLinkedCount(GenericModule *pMod)
Definition: Ship.cpp:1668