From 850825695ea1a6735cdb9aa602543f17de9529a6 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Fri, 1 Jul 2011 21:47:54 +0000 Subject: [PATCH] - added support for min / max hp associated with damage particles --- source/glest_game/graphics/particle_type.cpp | 7 +- source/glest_game/graphics/particle_type.h | 15 ++ source/glest_game/type_instances/unit.cpp | 225 +++++++++++++------ source/glest_game/type_instances/unit.h | 6 +- source/glest_game/types/skill_type.cpp | 10 +- source/glest_game/types/unit_type.cpp | 12 + source/glest_game/types/unit_type.h | 2 +- 7 files changed, 202 insertions(+), 75 deletions(-) diff --git a/source/glest_game/graphics/particle_type.cpp b/source/glest_game/graphics/particle_type.cpp index 4d3a8627..0b57fb08 100644 --- a/source/glest_game/graphics/particle_type.cpp +++ b/source/glest_game/graphics/particle_type.cpp @@ -40,6 +40,10 @@ ParticleSystemType::ParticleSystemType() { alternations=false; texture=NULL; model=NULL; + minmaxEnabled=false; + minHp=0; + maxHp=0; + minmaxIsPercent=false; } ParticleSystemType::~ParticleSystemType() { @@ -162,8 +166,7 @@ void ParticleSystemType::load(const XmlNode *particleSystemNode, const string &d const XmlNode *modeNode= particleSystemNode->getChild("mode"); mode= modeNode->getAttribute("value")->getRestrictedValue(); } - else - { + else { mode="normal"; } } diff --git a/source/glest_game/graphics/particle_type.h b/source/glest_game/graphics/particle_type.h index 720012af..4e5e8086 100644 --- a/source/glest_game/graphics/particle_type.h +++ b/source/glest_game/graphics/particle_type.h @@ -65,6 +65,11 @@ protected: bool teamcolorEnergy; int alternations; + bool minmaxEnabled; + int minHp; + int maxHp; + bool minmaxIsPercent; + public: ParticleSystemType(); ~ParticleSystemType(); @@ -76,6 +81,16 @@ public: bool hasTexture() const { return(texture != NULL); } bool hasModel() const { return(model != NULL); } + bool getMinmaxEnabled() const { return minmaxEnabled;} + int getMinHp() const { return minHp;} + int getMaxHp() const { return maxHp;} + bool getMinmaxIsPercent() const { return minmaxIsPercent; } + + void setMinmaxEnabled(bool value) { minmaxEnabled=value;} + void setMinHp(int value) { minHp=value;} + void setMaxHp(int value) { maxHp=value;} + void setMinmaxIsPercent(bool value) { minmaxIsPercent=value; } + protected: }; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index b067d703..65a797f6 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -360,7 +360,7 @@ Unit::~Unit() { unitParticleSystems.back()->fade(); unitParticleSystems.pop_back(); } - stopDamageParticles(); + stopDamageParticles(true); while(currentAttackBoostEffects.empty() == false) { //UnitAttackBoostEffect &effect = currentAttackBoostEffects.back(); @@ -1574,9 +1574,7 @@ void Unit::tick() { } //stop DamageParticles - if(hp > type->getTotalMaxHp(&totalUpgrade) / 2) { - stopDamageParticles(); - } + stopDamageParticles(false); checkItemInVault(&this->ep,this->ep); //regenerate ep @@ -1676,9 +1674,8 @@ bool Unit::repair(){ addItemToVault(&this->hp,this->hp); //stop DamageParticles - if(hp > type->getTotalMaxHp(&totalUpgrade)/2 ) { - stopDamageParticles(); - } + stopDamageParticles(false); + return false; } @@ -1699,9 +1696,7 @@ bool Unit::decHp(int i) { } //startDamageParticles - if(hp < type->getMaxHp() / 2 ) { - startDamageParticles(); - } + startDamageParticles(); //stop DamageParticles on death if(hp <= 0) { @@ -1709,7 +1704,7 @@ bool Unit::decHp(int i) { hp=0; addItemToVault(&this->hp,this->hp); - stopDamageParticles(); + stopDamageParticles(true); return true; } return false; @@ -2142,74 +2137,168 @@ CommandResult Unit::undoCommand(Command *command){ return crSuccess; } -void Unit::stopDamageParticles() { +void Unit::stopDamageParticles(bool force) { + if(force == true || (hp > type->getTotalMaxHp(&totalUpgrade) / 2) ) { + if(Renderer::getInstance().validateParticleSystemStillExists(fire,rsGame) == false) { + fire = NULL; + } - if(Renderer::getInstance().validateParticleSystemStillExists(fire,rsGame) == false) { - fire = NULL; + // stop fire + if(fire != NULL) { + fire->fade(); + fire = NULL; + } + // stop additional particles + + for(unsigned int i = damageParticleSystems.size()-1; i <= 0; --i) { + UnitParticleSystem *ps = damageParticleSystems[i]; + UnitParticleSystemType *pst = NULL; + int foundParticleIndexType = -1; + for(std::map::iterator iterMap = damageParticleSystemsInUse.begin(); + iterMap != damageParticleSystemsInUse.end(); ++iterMap) { + if(iterMap->second == ps) { + foundParticleIndexType = iterMap->first; + pst = type->damageParticleSystemTypes[foundParticleIndexType]; + break; + } + } + if(force == true || pst == NULL || + pst->getMinmaxEnabled() == false) { + damageParticleSystemsInUse.erase(foundParticleIndexType); + ps->fade(); + damageParticleSystems.pop_back(); + } + } } - // stop fire - if(fire != NULL) { - fire->fade(); - fire = NULL; + checkCustomizedParticleTriggers(force); +} + +void Unit::checkCustomizedParticleTriggers(bool force) { + // Now check if we have special hp triggered particles + for(unsigned int i = damageParticleSystems.size()-1; i <= 0; --i) { + UnitParticleSystem *ps = damageParticleSystems[i]; + UnitParticleSystemType *pst = NULL; + int foundParticleIndexType = -1; + for(std::map::iterator iterMap = damageParticleSystemsInUse.begin(); + iterMap != damageParticleSystemsInUse.end(); ++iterMap) { + if(iterMap->second == ps) { + foundParticleIndexType = iterMap->first; + pst = type->damageParticleSystemTypes[foundParticleIndexType]; + break; + } + } + + if(force == true || (pst != NULL && pst->getMinmaxEnabled() == true)) { + bool stopParticle = force; + if(force == false && pst->getMinmaxIsPercent() == false) { + if(hp < pst->getMinHp() || hp > pst->getMaxHp()) { + stopParticle = true; + } + } + + //printf("CHECKING to STOP customized particle trigger by HP [%d to %d percentbased = %d] current hp = %d stopParticle = %d\n",pst->getMinHp(),pst->getMaxHp(),pst->getMinmaxIsPercent(),hp,stopParticle); + + if(stopParticle == true) { + //printf("STOPPING customized particle trigger by HP [%d to %d] current hp = %d\n",pst->getMinHp(),pst->getMaxHp(),hp); + + damageParticleSystemsInUse.erase(foundParticleIndexType); + ps->fade(); + damageParticleSystems.pop_back(); + } + } } - // stop additional particles - while(damageParticleSystems.empty() == false) { - damageParticleSystems.back()->fade(); - damageParticleSystems.pop_back(); + + // Now check if we have special hp triggered particles + //start additional particles + if( showUnitParticles && (type->damageParticleSystemTypes.empty() == false) ) { + for(unsigned int i = 0; i < type->damageParticleSystemTypes.size(); ++i) { + UnitParticleSystemType *pst = type->damageParticleSystemTypes[i]; + + if(pst->getMinmaxEnabled() == true && damageParticleSystemsInUse.find(i) == damageParticleSystemsInUse.end()) { + bool showParticle = false; + if(pst->getMinmaxIsPercent() == false) { + if(hp >= pst->getMinHp() && hp <= pst->getMaxHp()) { + showParticle = true; + } + } + + //printf("CHECKING to START customized particle trigger by HP [%d to %d percentbased = %d] current hp = %d showParticle = %d\n",pst->getMinHp(),pst->getMaxHp(),pst->getMinmaxIsPercent(),hp,showParticle); + + if(showParticle == true) { + //printf("STARTING customized particle trigger by HP [%d to %d] current hp = %d\n",pst->getMinHp(),pst->getMaxHp(),hp); + + UnitParticleSystem *ups = new UnitParticleSystem(200); + pst->setValues(ups); + ups->setPos(getCurrVector()); + ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + damageParticleSystems.push_back(ups); + damageParticleSystemsInUse[i] = ups; + Renderer::getInstance().manageParticleSystem(ups, rsGame); + } + } + } } } -void Unit::startDamageParticles(){ - //start additional particles - if( showUnitParticles && (!type->damageParticleSystemTypes.empty()) - && (damageParticleSystems.empty()) ){ - for(UnitParticleSystemTypes::const_iterator it= type->damageParticleSystemTypes.begin(); it!=type->damageParticleSystemTypes.end(); ++it){ - UnitParticleSystem *ups; - ups= new UnitParticleSystem(200); - (*it)->setValues(ups); - ups->setPos(getCurrVector()); - ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); - damageParticleSystems.push_back(ups); - Renderer::getInstance().manageParticleSystem(ups, rsGame); - } - } - // start fire - if(type->getProperty(UnitType::pBurnable) && fire == NULL) { - FireParticleSystem *fps = new FireParticleSystem(200); - const Game *game = Renderer::getInstance().getGame(); - fps->setSpeed(2.5f / game->getWorld()->getUpdateFps(this->getFactionIndex())); - fps->setPos(getCurrVector()); - fps->setRadius(type->getSize()/3.f); - fps->setTexture(CoreData::getInstance().getFireTexture()); - fps->setParticleSize(type->getSize()/3.f); - fire= fps; - fireParticleSystems.push_back(fps); +void Unit::startDamageParticles() { + if(hp < type->getMaxHp() / 2 && hp > 0) { + //start additional particles + if( showUnitParticles && (!type->damageParticleSystemTypes.empty()) ) { + for(unsigned int i = 0; i < type->damageParticleSystemTypes.size(); ++i) { + UnitParticleSystemType *pst = type->damageParticleSystemTypes[i]; - Renderer::getInstance().manageParticleSystem(fps, rsGame); - if(showUnitParticles) { - // smoke - UnitParticleSystem *ups= new UnitParticleSystem(400); - ups->setColorNoEnergy(Vec4f(0.0f, 0.0f, 0.0f, 0.13f)); - ups->setColor(Vec4f(0.115f, 0.115f, 0.115f, 0.22f)); - ups->setPos(getCurrVector()); - ups->setBlendMode(ups->strToBlendMode("black")); - ups->setOffset(Vec3f(0,2,0)); - ups->setDirection(Vec3f(0,1,-0.2f)); - ups->setRadius(type->getSize()/3.f); - ups->setTexture(CoreData::getInstance().getFireTexture()); + if(pst->getMinmaxEnabled() == false && damageParticleSystemsInUse.find(i) == damageParticleSystemsInUse.end()) { + UnitParticleSystem *ups = new UnitParticleSystem(200); + pst->setValues(ups); + ups->setPos(getCurrVector()); + ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + damageParticleSystems.push_back(ups); + damageParticleSystemsInUse[i] = ups; + Renderer::getInstance().manageParticleSystem(ups, rsGame); + } + } + } + + // start fire + if(type->getProperty(UnitType::pBurnable) && fire == NULL) { + FireParticleSystem *fps = new FireParticleSystem(200); const Game *game = Renderer::getInstance().getGame(); - ups->setSpeed(2.0f / game->getWorld()->getUpdateFps(this->getFactionIndex())); - ups->setGravity(0.0004f); - ups->setEmissionRate(1); - ups->setMaxParticleEnergy(150); - ups->setSizeNoEnergy(type->getSize()*0.6f); - ups->setParticleSize(type->getSize()*0.8f); - damageParticleSystems.push_back(ups); - Renderer::getInstance().manageParticleSystem(ups, rsGame); - } + fps->setSpeed(2.5f / game->getWorld()->getUpdateFps(this->getFactionIndex())); + fps->setPos(getCurrVector()); + fps->setRadius(type->getSize()/3.f); + fps->setTexture(CoreData::getInstance().getFireTexture()); + fps->setParticleSize(type->getSize()/3.f); + fire= fps; + fireParticleSystems.push_back(fps); + Renderer::getInstance().manageParticleSystem(fps, rsGame); + if(showUnitParticles) { + // smoke + UnitParticleSystem *ups= new UnitParticleSystem(400); + ups->setColorNoEnergy(Vec4f(0.0f, 0.0f, 0.0f, 0.13f)); + ups->setColor(Vec4f(0.115f, 0.115f, 0.115f, 0.22f)); + ups->setPos(getCurrVector()); + ups->setBlendMode(ups->strToBlendMode("black")); + ups->setOffset(Vec3f(0,2,0)); + ups->setDirection(Vec3f(0,1,-0.2f)); + ups->setRadius(type->getSize()/3.f); + ups->setTexture(CoreData::getInstance().getFireTexture()); + const Game *game = Renderer::getInstance().getGame(); + ups->setSpeed(2.0f / game->getWorld()->getUpdateFps(this->getFactionIndex())); + ups->setGravity(0.0004f); + ups->setEmissionRate(1); + ups->setMaxParticleEnergy(150); + ups->setSizeNoEnergy(type->getSize()*0.6f); + ups->setParticleSize(type->getSize()*0.8f); + damageParticleSystems.push_back(ups); + damageParticleSystemsInUse[-1] = ups; + Renderer::getInstance().manageParticleSystem(ups, rsGame); + } + } } + + checkCustomizedParticleTriggers(false); } void Unit::setTargetVec(const Vec3f &targetVec) { diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index b368c59b..42144b5b 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -1,4 +1,3 @@ -// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 Marti�o Figueroa @@ -328,6 +327,8 @@ private: Observers observers; vector unitParticleSystems; UnitParticleSystems damageParticleSystems; + std::map damageParticleSystemsInUse; + vector fireParticleSystems; CardinalDir modelFacing; @@ -573,10 +574,11 @@ private: void clearCommands(); void deleteQueuedCommand(Command *command); CommandResult undoCommand(Command *command); - void stopDamageParticles(); + void stopDamageParticles(bool force); void startDamageParticles(); int getFrameCount() const; + void checkCustomizedParticleTriggers(bool force); }; }}// end namespace diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index cc2a491f..be27bd91 100644 --- a/source/glest_game/types/skill_type.cpp +++ b/source/glest_game/types/skill_type.cpp @@ -297,6 +297,7 @@ Model *SkillType::getAnimation(float animProgress, const Unit *unit, if(modelIndex < 0 || animProgress > 1.0f) { bool canCycle = CanCycleNextRandomAnimation(animationRandomCycleCount); if(canCycle == true) { + vector filteredAnimations; bool foundSpecificAnimation = false; if(unit != NULL) { for(unsigned int i = 0; i < animationAttributes.size(); ++i) { @@ -305,9 +306,9 @@ Model *SkillType::getAnimation(float animProgress, const Unit *unit, if(unit->getHp() >= attributes.fromHp && unit->getHp() <= attributes.toHp) { modelIndex = i; foundSpecificAnimation = true; - + filteredAnimations.push_back(i); //printf("SELECTING Model index = %d [%s] model attributes [%d to %d] for unit [%s - %d] with HP = %d\n",i,animations[modelIndex]->getFileName().c_str(),attributes.fromHp,attributes.toHp,unit->getType()->getName().c_str(),unit->getId(),unit->getHp()); - break; + //break; } } } @@ -321,6 +322,11 @@ Model *SkillType::getAnimation(float animProgress, const Unit *unit, //const AnimationAttributes &attributes = animationAttributes[modelIndex]; //printf("SELECTING RANDOM Model index = %d [%s] model attributes [%d to %d] for unit [%s - %d] with HP = %d\n",modelIndex,animations[modelIndex]->getFileName().c_str(),attributes.fromHp,attributes.toHp,unit->getType()->getName().c_str(),unit->getId(),unit->getHp()); } + else { + srand(time(NULL) + unit->getId()); + int filteredModelIndex = rand() % filteredAnimations.size(); + modelIndex = filteredAnimations[filteredModelIndex]; + } } } } diff --git a/source/glest_game/types/unit_type.cpp b/source/glest_game/types/unit_type.cpp index 06734c75..1019390e 100644 --- a/source/glest_game/types/unit_type.cpp +++ b/source/glest_game/types/unit_type.cpp @@ -304,6 +304,18 @@ void UnitType::load(int id,const string &dir, const TechTree *techTree, //Renderer::getInstance().endLastTexture(rsGame,true); //} + if(particleFileNode->getAttribute("minHp",false) != NULL && particleFileNode->getAttribute("maxHp",false) != NULL) { + unitParticleSystemType->setMinmaxEnabled(true); + unitParticleSystemType->setMinHp(particleFileNode->getAttribute("minHp")->getIntValue()); + unitParticleSystemType->setMaxHp(particleFileNode->getAttribute("maxHp")->getIntValue()); + + if(particleFileNode->getAttribute("ispercentbased",false) != NULL) { + unitParticleSystemType->setMinmaxIsPercent(particleFileNode->getAttribute("ispercentbased")->getBoolValue()); + } + + //printf("Found customized particle trigger by HP [%d to %d]\n",unitParticleSystemType->getMinHp(),unitParticleSystemType->getMaxHp()); + } + damageParticleSystemTypes.push_back(unitParticleSystemType); } } diff --git a/source/glest_game/types/unit_type.h b/source/glest_game/types/unit_type.h index cfd02cd1..f8290b9d 100644 --- a/source/glest_game/types/unit_type.h +++ b/source/glest_game/types/unit_type.h @@ -64,7 +64,7 @@ enum UnitClass { ucBuilding }; -typedef list DamageParticleSystemTypes; +typedef vector DamageParticleSystemTypes; class UnitType: public ProducibleType, public ValueCheckerVault { public: