00001
00002
00003
00004
00005
00006
00007 #include <ent.h>
00008 #include <engine.h>
00009 #include <distanceMgr.h>
00010 #include "unitWeapons.h"
00011 #include "DEBUG.h"
00012
00013 using namespace Ogre;
00014
00015 FastEcslent::Weapon::Weapon(Entity* ent, UnitAspectType ast,const WeaponType *wtype): UnitAspect(ent, ast) {
00016 weaponType = wtype;
00017 }
00018
00019 FastEcslent::Weapon::Weapon(Entity* ent, UnitAspectType ast): UnitAspect(ent, ast) {
00020 init();
00021 }
00022
00023 void FastEcslent::Weapon::init(){
00024 distanceMgr = this->entity->engine->distanceMgr;
00025 weaponMgr = this->entity->engine->weaponMgr;
00026 weaponType = weaponMgr->weaponType[this->entity->entityType];
00027
00028 hitpoints = weaponMgr->maxHitpoints[this->entity->entityType];
00029 armor = weaponMgr->initArmor[this->entity->entityType];
00030 damageMultiplier = weaponMgr->initDamageMultiplier[this->entity->entityType];
00031
00032 m_cooldown = 0;
00033 STANDSTILL = 10;
00034 m_onfire = 0;
00035 BEINGATTACKED = 100;
00036 m_beingAttacked = 0;
00037 }
00038
00039
00040 void FastEcslent::Weapon::tick(double dt) {
00041 if(m_beingAttacked > 0){
00042 m_beingAttacked -=dt;
00043 }
00044
00045
00046 if(m_onfire > 0){
00047 m_onfire -= dt;
00048 this->entity->speed = 0;
00049 return;
00050 }
00051
00052 if(m_cooldown <= 0 && distanceMgr->closestEnemyDistance[this->entity->entityId.id] < this->weaponType->maxRange()){
00053 target.entity = this->entity->engine->entityMgr->ents[distanceMgr->closestEnemy[this->entity->entityId.id]];
00054 if (target.entity->entityState == FastEcslent::ALIVE){
00055 if(this->weaponType->explosionType() == FastEcslent::ExplosionTypes::Enemy_Splash){
00056 dealEnemySplashDamageToTarget(target,dt,this->weaponType->outerSplashRadius());
00057 }else if(this->weaponType->explosionType() == FastEcslent::ExplosionTypes::Enemy_Line_Splash){
00058 dealLineSplashDamageToTarget(target, dt, this->weaponType->outerSplashRadius(), this->weaponType->innerSplashRadius());
00059 }else {
00060 dealDamageToTarget(target, dt);
00061 }
00062 }
00063
00064
00065 }else if(m_cooldown > 0){
00066 m_cooldown -= dt;
00067 }
00068 }
00069
00070 void FastEcslent::Weapon::dealDamageToTarget(Target tgt, double dt){
00071
00072 double damage = this->weaponType->damageAmount();
00073 tgt.entity->weapon->takeDamage(damage);
00074 m_cooldown = this->weaponType->damageCooldown();
00075 this->m_onfire = STANDSTILL;
00076 }
00077
00078 void FastEcslent::Weapon::dealEnemySplashDamageToTarget(Target tgt, double dt, double radius){
00079
00080 double damage = this->weaponType->damageAmount();
00081 std::vector<FastEcslent::Entity*> ents = this->getUnitsInRadius(tgt.entity, radius, true);
00082
00083 for(unsigned int i=0;i<ents.size();i++){
00084 ents[i]->weapon->takeDamage(damage);
00085 }
00086
00087 m_cooldown = this->weaponType->damageCooldown();
00088 this->m_onfire = STANDSTILL;
00089 }
00090
00091 void FastEcslent::Weapon::dealLineSplashDamageToTarget(Target tgt, double dt, double length, double width){
00092 double damage = this->weaponType->damageAmount();
00093
00094 std::vector<FastEcslent::Entity*> ents = this->getUnitsInRectangle(this->entity, tgt.entity, length, width, true);
00095 for(unsigned int i=0;i<ents.size();i++){
00096 ents[i]->weapon->takeDamage(damage);
00097 }
00098
00099 m_cooldown = this->weaponType->damageCooldown();
00100 this->m_onfire = STANDSTILL;
00101 }
00102
00103 void FastEcslent::Weapon::takeDamage(double amt) {
00104 if (this->entity->entityState == FastEcslent::ALIVE) {
00105 m_beingAttacked = BEINGATTACKED;
00106 hitpoints -= amt * armor;
00107 if (hitpoints <= 0){
00108 this->entity->switchState(DYING);
00109 hitpoints = 0;
00110 }
00111 }
00112 }
00113 void FastEcslent::Weapon::takeDamage(double amt, double dt) {
00114 if (this->entity->entityState == FastEcslent::ALIVE) {
00115 hitpoints -= amt * armor * dt;
00116 if (hitpoints <= 0){
00117 this->entity->switchState(DYING);
00118 hitpoints = 0;
00119 }
00120 }
00121 }
00122
00123 std::vector<FastEcslent::Entity*> FastEcslent::Weapon::getUnitsInRadius(Entity* ent, double radius, bool enemyOnly){
00124 std::vector<FastEcslent::Entity*> ents;
00125 for (int i = 0; i < this->entity->engine->entityMgr->nEnts; i++){
00126
00127 if(this->entity->engine->entityMgr->ents[i]->entityState != ALIVE){
00128 continue;
00129 }
00130
00131 if(enemyOnly && this->entity->engine->entityMgr->ents[i]->entityId.side == this->entity->entityId.side){
00132 continue;
00133 }
00134 double distance = (ent->pos - this->entity->engine->entityMgr->ents[i]->pos).length();
00135 if(distance <= radius){
00136 ents.push_back(this->entity->engine->entityMgr->ents[i]);
00137 }
00138 }
00139 return ents;
00140 }
00141
00145 std::vector<FastEcslent::Entity*> FastEcslent::Weapon::getUnitsInRectangle(Entity* src, Entity* tgt, double length, double width, bool enemyOnly){
00146 Vector3 vec = tgt->pos - src->pos;
00147 Vector3 v1,v2,v3,v4;
00148
00149 double xdelta = width/2 * sin(atan2(vec.z, vec.x));
00150 double zdelta = width/2 * cos(atan2(vec.z, vec.x));
00151 v1.x = src->pos.x - xdelta;
00152 v2.x = src->pos.x + xdelta;
00153
00154 v1.z = src->pos.z + zdelta;
00155 v2.z = src->pos.z - zdelta;
00156
00157 v3.x = v2.x + length* cos(atan2(vec.z, vec.x));
00158 v3.z = v2.z + length* sin(atan2(vec.z, vec.x));
00159
00160 v4.x = v1.x + length* cos(atan2(vec.z, vec.x));
00161 v4.z = v1.z + length* sin(atan2(vec.z, vec.x));
00162
00163 std::vector<FastEcslent::Entity*> ents;
00164 for (int i = 0; i < this->entity->engine->entityMgr->nEnts; i++){
00165 if(this->entity->engine->entityMgr->ents[i]->entityState != ALIVE){
00166 continue;
00167 }
00168
00169 if(enemyOnly && this->entity->engine->entityMgr->ents[i]->entityId.side == this->entity->entityId.side){
00170 continue;
00171 }
00172
00173 if(this->isPointInRectangle(v1,v2,v3,v4, this->entity->engine->entityMgr->ents[i]->pos)){
00174 ents.push_back(this->entity->engine->entityMgr->ents[i]);
00175 }
00176 }
00177 return ents;
00178 }
00179
00183 bool FastEcslent::Weapon::isPointInRectangle(Ogre::Vector3 sp1, Ogre::Vector3 sp2, Ogre::Vector3 sp3, Ogre::Vector3 sp4, Ogre::Vector3 point){
00184 double areaRectangle = (sp1-sp2).length() * (sp2-sp3).length();
00185 double area1 = this->getAreaTriangle(sp1,sp2,point);
00186 double area2 = this->getAreaTriangle(sp2,sp3,point);
00187 double area3 = this->getAreaTriangle(sp3,sp4,point);
00188 double area4 = this->getAreaTriangle(sp4,sp1,point);
00189 double sum = area1+area2+area3+area4;
00190 if(sum - areaRectangle < 50){
00191 return true;
00192 }else {
00193 return false;
00194 }
00195 }
00196
00200 double FastEcslent::Weapon::getAreaTriangle(Ogre::Vector3 tp1, Ogre::Vector3 tp2, Ogre::Vector3 tp3){
00201 double a = (tp1-tp2).length();
00202 double b = (tp2-tp3).length();
00203 double c = (tp3-tp1).length();
00204 double p = (a + b + c)/2;
00205 return sqrt(p*(p-a)*(p-b)*(p-c));
00206 }