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