From 1700cbba2d2d0a9ba4dc4cc1b92599c5f433b8b4 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sat, 25 Jun 2011 20:44:46 +0000 Subject: [PATCH] - working implementation of particles for new attack-boost xml tag --- source/glest_game/ai/path_finder.cpp | 2 +- source/glest_game/graphics/particle_type.cpp | 6 + source/glest_game/graphics/particle_type.h | 2 + source/glest_game/graphics/renderer.cpp | 11 +- source/glest_game/type_instances/unit.cpp | 333 ++++++++++++++---- source/glest_game/type_instances/unit.h | 42 ++- source/glest_game/types/skill_type.cpp | 145 ++++++-- source/glest_game/types/skill_type.h | 15 +- .../shared_lib/sources/graphics/particle.cpp | 13 +- 9 files changed, 456 insertions(+), 113 deletions(-) diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index fdaf2c9e..f7579e23 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -45,7 +45,7 @@ int PathFinder::pathFindNodesMax = 1500; const int PathFinder::pathFindRefresh = 10; const int PathFinder::pathFindBailoutRadius = 20; const int PathFinder::pathFindExtendRefreshForNodeCount = 25; -const int PathFinder::pathFindExtendRefreshNodeCountMin = 20; +const int PathFinder::pathFindExtendRefreshNodeCountMin = 40; const int PathFinder::pathFindExtendRefreshNodeCountMax = 60; PathFinder::PathFinder() { diff --git a/source/glest_game/graphics/particle_type.cpp b/source/glest_game/graphics/particle_type.cpp index 5519383d..4d3a8627 100644 --- a/source/glest_game/graphics/particle_type.cpp +++ b/source/glest_game/graphics/particle_type.cpp @@ -33,6 +33,8 @@ namespace Glest{ namespace Game{ // ===================================================== ParticleSystemType::ParticleSystemType() { + //printf("++ Create ParticleSystemType [%p]\n",this); + teamcolorNoEnergy=false; teamcolorEnergy=false; alternations=false; @@ -40,6 +42,10 @@ ParticleSystemType::ParticleSystemType() { model=NULL; } +ParticleSystemType::~ParticleSystemType() { + //printf("-- Delete ParticleSystemType [%p] type = [%s]\n",this,type.c_str()); +} + void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir, RendererInterface *renderer, std::map > > &loadedFileList, string parentLoader, string techtreePath) { diff --git a/source/glest_game/graphics/particle_type.h b/source/glest_game/graphics/particle_type.h index a67b9e8f..720012af 100644 --- a/source/glest_game/graphics/particle_type.h +++ b/source/glest_game/graphics/particle_type.h @@ -67,6 +67,8 @@ protected: public: ParticleSystemType(); + ~ParticleSystemType(); + void load(const XmlNode *particleSystemNode, const string &dir, RendererInterface *renderer, std::map > > &loadedFileList, string parentLoader, string techtreePath); diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index b279ebb6..07bd3426 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -3112,15 +3112,16 @@ void Renderer::renderSelectionEffects() { // Render Attack-boost circles if(showDebugUI == true) { - const std::pair > ¤tAttackBoostUnits = unit->getCurrentAttackBoostUnits(); + //const std::pair > ¤tAttackBoostUnits = unit->getCurrentAttackBoostUnits(); + const UnitAttackBoostEffectOriginator &effect = unit->getAttackBoostOriginatorEffect(); - if(currentAttackBoostUnits.first->isAttackBoostEnabled() == true) { + if(effect.skillType->isAttackBoostEnabled() == true) { glColor4f(MAGENTA.x,MAGENTA.y,MAGENTA.z,MAGENTA.w); - renderSelectionCircle(currVec, unit->getType()->getSize(), currentAttackBoostUnits.first->getAttackBoost()->radius); + renderSelectionCircle(currVec, unit->getType()->getSize(), effect.skillType->getAttackBoost()->radius); - for(unsigned int i = 0; i < currentAttackBoostUnits.second.size(); ++i) { + for(unsigned int i = 0; i < effect.currentAttackBoostUnits.size(); ++i) { // Remove attack boost upgrades from unit - Unit *affectedUnit = currentAttackBoostUnits.second[i]; + Unit *affectedUnit = effect.currentAttackBoostUnits[i]; Vec3f currVecBoost = affectedUnit->getCurrVectorFlat(); currVecBoost.y += 0.3f; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 9196a7f6..7b0da909 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -179,6 +179,39 @@ Unit *UnitReference::getUnit() const{ return NULL; } +UnitAttackBoostEffect::UnitAttackBoostEffect() { + boost = NULL; + source = NULL; + ups = NULL; + upst = NULL; +} + +UnitAttackBoostEffect::~UnitAttackBoostEffect() { + if(ups != NULL) { + //ups->fade(); + + vector particleSystemToRemove; + particleSystemToRemove.push_back(ups); + + Renderer::getInstance().cleanupUnitParticleSystems(particleSystemToRemove,rsGame); + ups = NULL; + } + + delete upst; + upst = NULL; +} + +UnitAttackBoostEffectOriginator::UnitAttackBoostEffectOriginator() { + skillType = NULL; + currentAppliedEffect = NULL; +} + +UnitAttackBoostEffectOriginator::~UnitAttackBoostEffectOriginator() { + delete currentAppliedEffect; + currentAppliedEffect = NULL; +} + + // ===================================================== // class Unit // ===================================================== @@ -278,7 +311,7 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType //starting skill this->lastModelIndexForCurrSkillType = -1; this->currSkill = getType()->getFirstStOfClass(scStop); - this->currentAttackBoostUnits.first = this->currSkill; + this->currentAttackBoostOriginatorEffect.skillType = this->currSkill; livingUnits.insert(id); livingUnitsp.insert(this); @@ -328,6 +361,14 @@ Unit::~Unit() { } stopDamageParticles(); + while(currentAttackBoostEffects.empty() == false) { + //UnitAttackBoostEffect &effect = currentAttackBoostEffects.back(); + currentAttackBoostEffects.pop_back(); + } + + delete currentAttackBoostOriginatorEffect.currentAppliedEffect; + currentAttackBoostOriginatorEffect.currentAppliedEffect = NULL; + delete this->unitPath; this->unitPath = NULL; @@ -678,6 +719,18 @@ void Unit::setVisible(const bool visible) { for(UnitParticleSystems::iterator it= damageParticleSystems.begin(); it != damageParticleSystems.end(); ++it) { (*it)->setVisible(visible); } + + for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { + UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; + if(effect.ups != NULL) { + effect.ups->setVisible(visible); + } + } + if(currentAttackBoostOriginatorEffect.currentAppliedEffect != NULL) { + if(currentAttackBoostOriginatorEffect.currentAppliedEffect->ups != NULL) { + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setVisible(visible); + } + } } // =============================== Render related ================================== @@ -1019,15 +1072,15 @@ void Unit::undertake() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] about to undertake unit id = %d [%s] [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->id, this->getFullName().c_str(),this->getDesc().c_str()); // Remove any units that were previously in attack-boost range - if(currentAttackBoostUnits.second.size() > 0) { - for(unsigned int i = 0; i < currentAttackBoostUnits.second.size(); ++i) { + if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0) { + for(unsigned int i = 0; i < currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size(); ++i) { // Remove attack boost upgrades from unit - Unit *affectedUnit = currentAttackBoostUnits.second[i]; - affectedUnit->deapplyAttackBoost(currentAttackBoostUnits.first->getAttackBoost(), this); + Unit *affectedUnit = currentAttackBoostOriginatorEffect.currentAttackBoostUnits[i]; + affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); //printf("!!!! DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); } - currentAttackBoostUnits.second.clear(); + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.clear(); } UnitUpdater *unitUpdater = game->getWorld()->getUnitUpdater(); @@ -1221,6 +1274,20 @@ bool Unit::update() { (*it)->setRotation(getRotation()); } + for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { + UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; + if(effect.ups != NULL) { + effect.ups->setPos(getCurrVector()); + effect.ups->setRotation(getRotation()); + } + } + if(currentAttackBoostOriginatorEffect.currentAppliedEffect != NULL) { + if(currentAttackBoostOriginatorEffect.currentAppliedEffect->ups != NULL) { + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setPos(getCurrVector()); + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setRotation(getRotation()); + } + } + //checks if(animProgress > 1.f) { animProgress = currSkill->getClass() == scDie? 1.f: 0.f; @@ -1245,34 +1312,124 @@ bool Unit::update() { } } - // Remove any units that were previously in range - if(currentAttackBoostUnits.second.size() > 0) { - for(unsigned int i = 0; i < currentAttackBoostUnits.second.size(); ++i) { - // Remove attack boost upgrades from unit - Unit *affectedUnit = currentAttackBoostUnits.second[i]; - affectedUnit->deapplyAttackBoost(currentAttackBoostUnits.first->getAttackBoost(), this); + if(currSkill != currentAttackBoostOriginatorEffect.skillType) { + if(currentAttackBoostOriginatorEffect.currentAppliedEffect != NULL) { + delete currentAttackBoostOriginatorEffect.currentAppliedEffect; + currentAttackBoostOriginatorEffect.currentAppliedEffect = NULL; - //printf("!!!! DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); + //printf("- #1 DE-APPLY ATTACK BOOST SELF PARTICLE to unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId()); + } + + // Remove any units that were previously in range + if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0) { + for(unsigned int i = 0; i < currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size(); ++i) { + // Remove attack boost upgrades from unit + Unit *affectedUnit = currentAttackBoostOriginatorEffect.currentAttackBoostUnits[i]; + affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); + + //printf("- #1 DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); + } + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.clear(); + } + currentAttackBoostOriginatorEffect.skillType = currSkill; + + if(currSkill->isAttackBoostEnabled() == true) { + // Search for units in range of this unit which apply to the + // attack-boost and temporarily upgrade them + UnitUpdater *unitUpdater = this->game->getWorld()->getUnitUpdater(); + + const AttackBoost *attackBoost = currSkill->getAttackBoost(); + vector candidates = unitUpdater->findUnitsInRange(this, attackBoost->radius); + for(unsigned int i = 0; i < candidates.size(); ++i) { + Unit *affectedUnit = candidates[i]; + if(attackBoost->isAffected(this,affectedUnit) == true) { + if(affectedUnit->applyAttackBoost(attackBoost, this) == true) { + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.push_back(affectedUnit); + + //printf("+ #1 APPLY ATTACK BOOST to unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); + } + } + } + + if(showUnitParticles == true) { + if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0) { + if(attackBoost->unitParticleSystemTypeForSourceUnit != NULL) { + currentAttackBoostOriginatorEffect.currentAppliedEffect = new UnitAttackBoostEffect(); + currentAttackBoostOriginatorEffect.currentAppliedEffect->upst = new UnitParticleSystemType(); + *currentAttackBoostOriginatorEffect.currentAppliedEffect->upst = *attackBoost->unitParticleSystemTypeForSourceUnit; + //effect.upst = boost->unitParticleSystemTypeForAffectedUnit; + + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups = new UnitParticleSystem(200); + currentAttackBoostOriginatorEffect.currentAppliedEffect->upst->setValues(currentAttackBoostOriginatorEffect.currentAppliedEffect->ups); + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setPos(getCurrVector()); + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + Renderer::getInstance().manageParticleSystem(currentAttackBoostOriginatorEffect.currentAppliedEffect->ups, rsGame); + + //printf("+ #1 APPLY ATTACK BOOST SELF PARTICLE to unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId()); + } + } + } } - currentAttackBoostUnits.second.clear(); } - currentAttackBoostUnits.first = currSkill; + else { + if(currSkill->isAttackBoostEnabled() == true) { + // Search for units in range of this unit which apply to the + // attack-boost and temporarily upgrade them + UnitUpdater *unitUpdater = this->game->getWorld()->getUnitUpdater(); - if(currSkill->isAttackBoostEnabled() == true) { - // Search for units in range of this unit which apply to the - // attack-boost and temporarily upgrade them - UnitUpdater *unitUpdater = this->game->getWorld()->getUnitUpdater(); + const AttackBoost *attackBoost = currSkill->getAttackBoost(); + vector candidates = unitUpdater->findUnitsInRange(this, attackBoost->radius); + for(unsigned int i = 0; i < candidates.size(); ++i) { + Unit *affectedUnit = candidates[i]; - const AttackBoost *attackBoost = currSkill->getAttackBoost(); - vector candidates = unitUpdater->findUnitsInRange(this, attackBoost->radius); - for(unsigned int i = 0; i < candidates.size(); ++i) { - Unit *affectedUnit = candidates[i]; - if(attackBoost->isAffected(this,affectedUnit) == true) { - affectedUnit->applyAttackBoost(attackBoost, this); + std::vector::iterator iterFound = std::find(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.begin(), currentAttackBoostOriginatorEffect.currentAttackBoostUnits.end(), affectedUnit); - currentAttackBoostUnits.second.push_back(affectedUnit); + if(attackBoost->isAffected(this,affectedUnit) == true) { + if(iterFound == currentAttackBoostOriginatorEffect.currentAttackBoostUnits.end()) { + if(affectedUnit->applyAttackBoost(attackBoost, this) == true) { + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.push_back(affectedUnit); - //printf("@@@@ APPLY ATTACK BOOST to unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); + //printf("+ #2 APPLY ATTACK BOOST to unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); + } + } + } + else { + if(iterFound != currentAttackBoostOriginatorEffect.currentAttackBoostUnits.end()) { + affectedUnit->deapplyAttackBoost(currentAttackBoostOriginatorEffect.skillType->getAttackBoost(), this); + currentAttackBoostOriginatorEffect.currentAttackBoostUnits.erase(iterFound); + + //printf("- #2 DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId()); + } + } + } + + if(showUnitParticles == true) { + if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() > 0) { + if( attackBoost->unitParticleSystemTypeForSourceUnit != NULL && + currentAttackBoostOriginatorEffect.currentAppliedEffect == NULL) { + + currentAttackBoostOriginatorEffect.currentAppliedEffect = new UnitAttackBoostEffect(); + currentAttackBoostOriginatorEffect.currentAppliedEffect->upst = new UnitParticleSystemType(); + *currentAttackBoostOriginatorEffect.currentAppliedEffect->upst = *attackBoost->unitParticleSystemTypeForSourceUnit; + //effect.upst = boost->unitParticleSystemTypeForAffectedUnit; + + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups = new UnitParticleSystem(200); + currentAttackBoostOriginatorEffect.currentAppliedEffect->upst->setValues(currentAttackBoostOriginatorEffect.currentAppliedEffect->ups); + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setPos(getCurrVector()); + currentAttackBoostOriginatorEffect.currentAppliedEffect->ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + Renderer::getInstance().manageParticleSystem(currentAttackBoostOriginatorEffect.currentAppliedEffect->ups, rsGame); + + //printf("+ #2 APPLY ATTACK BOOST SELF PARTICLE to unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId()); + } + } + else if(currentAttackBoostOriginatorEffect.currentAttackBoostUnits.size() <= 0) { + if(currentAttackBoostOriginatorEffect.currentAppliedEffect != NULL) { + delete currentAttackBoostOriginatorEffect.currentAppliedEffect; + currentAttackBoostOriginatorEffect.currentAppliedEffect = NULL; + + //printf("- #2 DE-APPLY ATTACK BOOST SELF PARTICLE to unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId()); + } + } } } } @@ -1280,6 +1437,94 @@ bool Unit::update() { return return_value; } +bool Unit::unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const { + bool result = false; + for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { + const UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; + if( effect.boost == boost && + effect.source->getType()->getId() == source->getType()->getId()) { + result = true; + break; + } + } + return result; +} + +bool Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) { + if(boost == NULL) { + char szBuf[4096]=""; + sprintf(szBuf,"In [%s::%s Line: %d] ERROR: boost == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str()); + throw runtime_error(szBuf); + } + + //printf("APPLYING ATTACK BOOST to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); + + bool shouldApplyAttackBoost = true; + if(boost->allowMultipleBoosts == false) { + // Check if we already have this boost from this unit type and multiples + // are not allowed + bool alreadyHasAttackBoost = this->unitHasAttackBoost(boost, source); + if(alreadyHasAttackBoost == true) { + shouldApplyAttackBoost = false; + } + } + + if(shouldApplyAttackBoost == true) { + currentAttackBoostEffects.push_back(UnitAttackBoostEffect()); + UnitAttackBoostEffect &effect = currentAttackBoostEffects[currentAttackBoostEffects.size()-1]; + effect.boost = boost; + effect.source = source; + + //if(boost->isAffected(source, this)) { + totalUpgrade.apply(&boost->boostUpgrade); + + checkItemInVault(&this->hp,this->hp); + hp += boost->boostUpgrade.getMaxHp(); + addItemToVault(&this->hp,this->hp); + //} + + if(showUnitParticles == true) { + effect.upst = new UnitParticleSystemType(); + *effect.upst = *boost->unitParticleSystemTypeForAffectedUnit; + //effect.upst = boost->unitParticleSystemTypeForAffectedUnit; + + effect.ups = new UnitParticleSystem(200); + effect.upst->setValues(effect.ups); + effect.ups->setPos(getCurrVector()); + effect.ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + Renderer::getInstance().manageParticleSystem(effect.ups, rsGame); + } + //currentAttackBoostEffects.push_back(effect); + } + return shouldApplyAttackBoost; +} + +void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) { + if(boost == NULL) { + char szBuf[4096]=""; + sprintf(szBuf,"In [%s::%s Line: %d] ERROR: boost == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str()); + throw runtime_error(szBuf); + } + + //printf("DE-APPLYING ATTACK BOOST to unit [%s - %d] from unit [%s - %d]\n",this->getType()->getName().c_str(),this->getId(),source->getType()->getName().c_str(),source->getId()); + + //if(boost->isAffected(source, this)) { + totalUpgrade.deapply(&boost->boostUpgrade); + + checkItemInVault(&this->hp,this->hp); + hp -= boost->boostUpgrade.getMaxHp(); + addItemToVault(&this->hp,this->hp); + //} + + for(unsigned int i = 0; i < currentAttackBoostEffects.size(); ++i) { + UnitAttackBoostEffect &effect = currentAttackBoostEffects[i]; + if(effect.boost == boost && effect.source == source) { + currentAttackBoostEffects.erase(currentAttackBoostEffects.begin() + i); + break; + } + } +} + void Unit::tick() { if(isAlive()) { @@ -1562,38 +1807,6 @@ string Unit::getDesc() const { return str; } -void Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) { - if(boost == NULL) { - char szBuf[4096]=""; - sprintf(szBuf,"In [%s::%s Line: %d] ERROR: boost == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str()); - throw runtime_error(szBuf); - } - - //if(boost->isAffected(source, this)) { - totalUpgrade.apply(&boost->boostUpgrade); - - checkItemInVault(&this->hp,this->hp); - hp += boost->boostUpgrade.getMaxHp(); - addItemToVault(&this->hp,this->hp); - //} -} - -void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) { - if(boost == NULL) { - char szBuf[4096]=""; - sprintf(szBuf,"In [%s::%s Line: %d] ERROR: boost == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str()); - throw runtime_error(szBuf); - } - - //if(boost->isAffected(source, this)) { - totalUpgrade.deapply(&boost->boostUpgrade); - - checkItemInVault(&this->hp,this->hp); - hp -= boost->boostUpgrade.getMaxHp(); - addItemToVault(&this->hp,this->hp); - //} -} - void Unit::applyUpgrade(const UpgradeType *upgradeType){ if(upgradeType == NULL) { char szBuf[4096]=""; @@ -2182,7 +2395,7 @@ void Unit::setLastHarvestResourceTarget(const Vec2i *pos) { // as a bad one const int addInterval = (GameConstants::updateFps * 5); if(lastHarvestResourceTarget.second - getFrameCount() >= addInterval) { - printf("-----------------------> setLastHarvestResourceTarget() [%d][%d]\n",getFrameCount(),lastHarvestResourceTarget.second); + //printf("-----------------------> setLastHarvestResourceTarget() [%d][%d]\n",getFrameCount(),lastHarvestResourceTarget.second); addBadHarvestPos(resourceLocation); } } diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index 8997f274..088af721 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -52,7 +52,7 @@ class MorphCommandType; class Game; class Unit; -enum CommandResult{ +enum CommandResult { crSuccess, crFailRes, crFailReqs, @@ -61,7 +61,7 @@ enum CommandResult{ crSomeFailed }; -enum InterestingUnitType{ +enum InterestingUnitType { iutIdleHarvester, iutBuiltBuilding, iutProducer, @@ -73,7 +73,7 @@ enum InterestingUnitType{ // class UnitObserver // ===================================================== -class UnitObserver{ +class UnitObserver { public: enum Event{ eKill @@ -88,7 +88,7 @@ public: // class UnitReference // ===================================================== -class UnitReference{ +class UnitReference { private: int id; Faction *faction; @@ -236,6 +236,30 @@ public: /// A game unit or building // =============================== +class UnitAttackBoostEffect { +public: + + UnitAttackBoostEffect(); + ~UnitAttackBoostEffect(); + + const AttackBoost *boost; + const Unit *source; + UnitParticleSystem *ups; + UnitParticleSystemType *upst; + +}; + +class UnitAttackBoostEffectOriginator { +public: + + UnitAttackBoostEffectOriginator(); + ~UnitAttackBoostEffectOriginator(); + + const SkillType *skillType; + std::vector currentAttackBoostUnits; + UnitAttackBoostEffect *currentAppliedEffect; +}; + class Unit : public ValueCheckerVault { private: typedef list Commands; @@ -344,7 +368,9 @@ private: bool usePathfinderExtendedMaxNodes; int maxQueuedCommandDisplayCount; - std::pair > currentAttackBoostUnits; + UnitAttackBoostEffectOriginator currentAttackBoostOriginatorEffect; + + std::vector currentAttackBoostEffects; public: Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing); @@ -352,7 +378,9 @@ public: static void setGame(Game *value) { game=value;} - const std::pair > & getCurrentAttackBoostUnits() const { return currentAttackBoostUnits; } + //const std::pair > & getCurrentAttackBoostUnits() const { return currentAttackBoostUnits; } + const UnitAttackBoostEffectOriginator & getAttackBoostOriginatorEffect() const { return currentAttackBoostOriginatorEffect; } + bool unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const; //queries void setIgnoreCheckCommand(bool value) { ignoreCheckCommand=value;} @@ -470,7 +498,7 @@ public: bool update(); void tick(); - void applyAttackBoost(const AttackBoost *boost, const Unit *source); + bool applyAttackBoost(const AttackBoost *boost, const Unit *source); void deapplyAttackBoost(const AttackBoost *boost, const Unit *source); void applyUpgrade(const UpgradeType *upgradeType); diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index 58b86a1c..1669521c 100644 --- a/source/glest_game/types/skill_type.cpp +++ b/source/glest_game/types/skill_type.cpp @@ -30,47 +30,70 @@ namespace Glest{ namespace Game{ AttackBoost::AttackBoost() { - enabled = false; - radius = 0; - boostAllUnits = false; + enabled = false; + allowMultipleBoosts = false; + radius = 0; + targetType = abtFaction; + unitParticleSystemTypeForSourceUnit = NULL; + unitParticleSystemTypeForAffectedUnit = NULL; } + +AttackBoost::~AttackBoost() { + delete unitParticleSystemTypeForSourceUnit; + unitParticleSystemTypeForSourceUnit = NULL; + + delete unitParticleSystemTypeForAffectedUnit; + unitParticleSystemTypeForAffectedUnit = NULL; +} + bool AttackBoost::isAffected(const Unit *source, const Unit *dest) const { bool result = false; - if(enabled == true && source != NULL && dest != NULL && - source != dest) { + if(enabled == true && source != NULL && dest != NULL && source != dest) { + bool destUnitMightApply = false; // All units are affected (including enemies) - if(boostAllUnits == true) { + if(targetType == abtAll) { + destUnitMightApply = true; + } + // Only same faction units are affected + else if(targetType == abtFaction) { + if(boostUnitList.size() == 0) { + if(source->getFactionIndex() == dest->getFactionIndex()) { + destUnitMightApply = true; + } + } + } + // Only ally units are affected + else if(targetType == abtAlly) { + if(boostUnitList.size() == 0) { + if(source->isAlly(dest) == true) { + destUnitMightApply = true; + } + } + } + // Only foe units are affected + else if(targetType == abtFoe) { + if(boostUnitList.size() == 0) { + if(source->isAlly(dest) == false) { + destUnitMightApply = true; + } + } + } + else if(targetType == abtUnitTypes) { + // Specify which units are affected + for(unsigned int i = 0; i < boostUnitList.size(); ++i) { + const UnitType *ut = boostUnitList[i]; + if(dest->getType()->getId() == ut->getId()) { + destUnitMightApply = true; + } + } + } + + if(destUnitMightApply == true) { float distance = source->getCenteredPos().dist(dest->getCenteredPos()); if(distance <= radius) { result = true; } } - else { - // Only same faction units are affected - if(boostUnitList.size() == 0) { - //if(source->isAlly(dest) == true) { - //} - if(source->getFactionIndex() == dest->getFactionIndex()) { - float distance = source->getCenteredPos().dist(dest->getCenteredPos()); - if(distance <= radius) { - result = true; - } - } - } - // Specify which units are affected - else { - for(unsigned int i = 0; i < boostUnitList.size(); ++i) { - const UnitType *ut = boostUnitList[i]; - if(dest->getType()->getId() == ut->getId()) { - float distance = source->getCenteredPos().dist(dest->getCenteredPos()); - if(distance <= radius) { - result = true; - break; - } - } - } - } - } } return result; @@ -185,17 +208,63 @@ void SkillType::load(const XmlNode *sn, const string &dir, const TechTree *tt, attackBoost.enabled = true; const XmlNode *attackBoostNode = sn->getChild("attack-boost"); + attackBoost.allowMultipleBoosts = attackBoostNode->getChild("allow-multiple-boosts")->getAttribute("value")->getBoolValue(); attackBoost.radius = attackBoostNode->getChild("radius")->getAttribute("value")->getIntValue(); - attackBoost.boostAllUnits = attackBoostNode->getChild("boost-all-units")->getAttribute("value")->getBoolValue(); - if(attackBoost.boostAllUnits == false) { - for(int i = 0; i < attackBoostNode->getChild("boost-all-units")->getChildCount(); ++i) { - const XmlNode *boostUnitNode= attackBoostNode->getChild("boost-all-units")->getChild("unit-type", i); + + string targetType = attackBoostNode->getChild("target")->getAttribute("value")->getValue(); + if(targetType == "ally") { + attackBoost.targetType = abtAlly; + } + else if(targetType == "foe") { + attackBoost.targetType = abtFoe; + } + else if(targetType == "faction") { + attackBoost.targetType = abtFaction; + } + else if(targetType == "unit-types") { + attackBoost.targetType = abtUnitTypes; + + for(int i = 0; i < attackBoostNode->getChild("target")->getChildCount(); ++i) { + const XmlNode *boostUnitNode= attackBoostNode->getChild("target")->getChild("unit-type", i); attackBoost.boostUnitList.push_back(ft->getUnitType(boostUnitNode->getAttribute("name")->getRestrictedValue())); } } - attackBoost.boostUpgrade.load(attackBoostNode); - } + else if(targetType == "all") { + attackBoost.targetType = abtAll; + } + else { + char szBuf[4096]=""; + sprintf(szBuf,"Unsupported target [%s] specified for attack boost for skill [%s] in [%s]",targetType.c_str(),name.c_str(),parentLoader.c_str()); + throw runtime_error(szBuf); + } + attackBoost.boostUpgrade.load(attackBoostNode); + + //particles + if(attackBoostNode->hasChild("particles") == true) { + const XmlNode *particleNode= attackBoostNode->getChild("particles"); + bool particleEnabled= particleNode->getAttribute("value")->getBoolValue(); + if(particleEnabled == true) { + if(particleNode->hasChild("originator-particle-file") == true) { + const XmlNode *particleFileNode= particleNode->getChild("originator-particle-file"); + string path= particleFileNode->getAttribute("path")->getRestrictedValue(); + attackBoost.unitParticleSystemTypeForSourceUnit = new UnitParticleSystemType(); + attackBoost.unitParticleSystemTypeForSourceUnit->load(dir, currentPath + path, &Renderer::getInstance(), + loadedFileList,parentLoader,tt->getPath()); + loadedFileList[currentPath + path].push_back(make_pair(parentLoader,particleFileNode->getAttribute("path")->getRestrictedValue())); + + } + if(particleNode->hasChild("affected-particle-file") == true) { + const XmlNode *particleFileNode= particleNode->getChild("affected-particle-file"); + string path= particleFileNode->getAttribute("path")->getRestrictedValue(); + attackBoost.unitParticleSystemTypeForAffectedUnit = new UnitParticleSystemType(); + attackBoost.unitParticleSystemTypeForAffectedUnit->load(dir, currentPath + path, &Renderer::getInstance(), + loadedFileList,parentLoader,tt->getPath()); + loadedFileList[currentPath + path].push_back(make_pair(parentLoader,particleFileNode->getAttribute("path")->getRestrictedValue())); + } + } + } + } } Model *SkillType::getAnimation(float animProgress, const Unit *unit, int *lastAnimationIndex) const { diff --git a/source/glest_game/types/skill_type.h b/source/glest_game/types/skill_type.h index 34f64de2..22da2d29 100644 --- a/source/glest_game/types/skill_type.h +++ b/source/glest_game/types/skill_type.h @@ -74,15 +74,28 @@ typedef list UnitParticleSystemTypes; /// A basic action that an unit can perform // ===================================================== +enum AttackBoostTargetType { + abtAlly, + abtFoe, + abtFaction, + abtUnitTypes, + abtAll +}; + class AttackBoost { public: AttackBoost(); + ~AttackBoost(); bool enabled; + bool allowMultipleBoosts; int radius; - bool boostAllUnits; + AttackBoostTargetType targetType; vector boostUnitList; UpgradeTypeBase boostUpgrade; + UnitParticleSystemType *unitParticleSystemTypeForSourceUnit; + UnitParticleSystemType *unitParticleSystemTypeForAffectedUnit; + bool isAffected(const Unit *source, const Unit *dest) const; }; diff --git a/source/shared_lib/sources/graphics/particle.cpp b/source/shared_lib/sources/graphics/particle.cpp index 7f48ea01..13e2de62 100644 --- a/source/shared_lib/sources/graphics/particle.cpp +++ b/source/shared_lib/sources/graphics/particle.cpp @@ -33,7 +33,9 @@ namespace Graphics { // class ParticleSystem // ===================================================== -ParticleSystem::ParticleSystem(int particleCount){ +ParticleSystem::ParticleSystem(int particleCount) { + //printf("++ Create ParticleSystem [%p]\n",this); + //init particle vector blendMode= bmOne; //particles= new Particle[particleCount]; @@ -67,6 +69,8 @@ ParticleSystem::ParticleSystem(int particleCount){ } ParticleSystem::~ParticleSystem(){ + //printf("-- Delete ParticleSystem [%p]\n",this); + //delete [] particles; particles.clear(); } @@ -182,6 +186,13 @@ void ParticleSystem::setVisible(bool visible){ // =============== MISC ========================= void ParticleSystem::fade(){ if(particleObserver != NULL){ + if(state != sPlay) { + char szBuf[4096]=""; + sprintf(szBuf,"state != sPlay, state = [%d]",state); + //throw runtime_error(szBuf); + //printf(szBuf); + SystemFlags::OutputDebug(SystemFlags::debugError,"%s",szBuf); + } assert(state == sPlay); } state= sFade;