diff --git a/source/glest_game/types/projectile_type.cpp b/source/glest_game/types/projectile_type.cpp index fb10075e..672c2dc2 100644 --- a/source/glest_game/types/projectile_type.cpp +++ b/source/glest_game/types/projectile_type.cpp @@ -24,6 +24,10 @@ ProjectileType::ProjectileType() { projectileParticleSystemType=NULL; attackStartTime=0.0f; + spawnUnit=""; + spawnUnitcount=0; + spawnUnitAtTarget=false; + shake=false; shakeIntensity=0; shakeDuration=0; @@ -70,6 +74,22 @@ void ProjectileType::load(const XmlNode *projectileNode, const string &dir, cons loadedFileList[currentPath + path].push_back(make_pair(parentLoader,particleNode->getAttribute("path")->getRestrictedValue())); setProjectileParticleSystemType(projectileParticleSystemType); + //spawnattack + if (projectileNode->hasChild("unit")) { + spawnUnit = projectileNode->getChild("unit")->getAttribute("value")->getValue(); + spawnUnitcount = projectileNode->getChild("unit")->getAttribute("amount")->getIntValue(); + if(projectileNode->getChild("unit")->hasAttribute("spawnAtTarget")) { + spawnUnitAtTarget = projectileNode->getChild("unit")->getAttribute("spawnAtTarget")->getBoolValue(); + } else { + spawnUnitAtTarget = false; + } + } else { + spawnUnit = ""; + spawnUnitcount = 0; + spawnUnitAtTarget = false; + } + + if(projectileNode->hasChild("hitshake")){ const XmlNode *hitShakeNode= projectileNode->getChild("hitshake"); shake=hitShakeNode->getAttribute("enabled")->getBoolValue(); diff --git a/source/glest_game/types/projectile_type.h b/source/glest_game/types/projectile_type.h index 27aaeb48..d3871ef1 100644 --- a/source/glest_game/types/projectile_type.h +++ b/source/glest_game/types/projectile_type.h @@ -41,6 +41,10 @@ protected: SoundContainer hitSounds; float attackStartTime; + string spawnUnit; + int spawnUnitcount; + bool spawnUnitAtTarget; + bool shake; int shakeIntensity; int shakeDuration; @@ -64,6 +68,10 @@ public: float getAttackStartTime() const {return attackStartTime;} void setAttackStartTime(float value) {attackStartTime=value;} + string getSpawnUnit() const{return spawnUnit;} + int getSpawnUnitcount() const{return spawnUnitcount;} + bool getSpawnUnitAtTarget() const{return spawnUnitAtTarget;} + bool isShake() const{return shake;} bool isShakeCameraDistanceAffected() const{return shakeCameraDistanceAffected;} int getShakeDuration() const{return shakeDuration;} diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index c988181e..5f53b1c5 100644 --- a/source/glest_game/types/skill_type.cpp +++ b/source/glest_game/types/skill_type.cpp @@ -834,6 +834,7 @@ AttackSkillType::AttackSkillType() { splashRadius= 0; spawnUnit=""; spawnUnitcount=0; + spawnUnitAtTarget=false; splashParticleSystemType= NULL; for(int i = 0; i < fieldCount; ++i) { @@ -886,11 +887,16 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode, if (sn->hasChild("unit")) { spawnUnit = sn->getChild("unit")->getAttribute("value")->getValue(); - spawnUnitcount - = sn->getChild("unit")->getAttribute("amount")->getIntValue(); + spawnUnitcount = sn->getChild("unit")->getAttribute("amount")->getIntValue(); + if(sn->getChild("unit")->hasAttribute("spawnAtTarget")) { + spawnUnitAtTarget = sn->getChild("unit")->getAttribute("spawnAtTarget")->getBoolValue(); + } else { + spawnUnitAtTarget = false; + } } else { spawnUnit = ""; spawnUnitcount = 0; + spawnUnitAtTarget = false; } //attack fields const XmlNode *attackFieldsNode= sn->getChild("attack-fields"); @@ -1055,6 +1061,8 @@ void AttackSkillType::saveGame(XmlNode *rootNode) { attackSkillTypeNode->addAttribute("spawnUnit",spawnUnit, mapTagReplacements); // int spawnUnitcount; attackSkillTypeNode->addAttribute("spawnUnitcount",intToStr(spawnUnitcount), mapTagReplacements); +// bool spawnUnitAtTarget; + attackSkillTypeNode->addAttribute("spawnUnitAtTarget",intToStr(spawnUnitAtTarget), mapTagReplacements); // bool projectile; attackSkillTypeNode->addAttribute("projectile",intToStr(projectile), mapTagReplacements); // ParticleSystemTypeProjectile* projectileParticleSystemType; diff --git a/source/glest_game/types/skill_type.h b/source/glest_game/types/skill_type.h index 290c1903..c0b4f3b8 100644 --- a/source/glest_game/types/skill_type.h +++ b/source/glest_game/types/skill_type.h @@ -292,6 +292,7 @@ private: string spawnUnit; int spawnUnitcount; + bool spawnUnitAtTarget; bool projectile; //ParticleSystemTypeProjectile* projectileParticleSystemType; SoundContainer projSounds; @@ -318,6 +319,7 @@ public: inline float getAttackStartTime() const {return attackStartTime;} inline string getSpawnUnit() const {return spawnUnit;} inline int getSpawnUnitCount() const {return spawnUnitcount;} + inline bool getSpawnUnitAtTarget() const {return spawnUnitAtTarget;} //get proj inline bool getProjectile() const {return projectile;} diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index c9dc9e7f..775d8afa 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -270,56 +270,9 @@ bool UnitUpdater::updateUnit(Unit *unit) { else if(unit->getCommandSize() > 0) { Command *command= unit->getCurrCommand(); if(command != NULL) { - const CommandType *ct = command->getCommandType(); const AttackCommandType *act= dynamic_cast(command->getCommandType()); - if( act != NULL && act->getAttackSkillType() != NULL && - act->getAttackSkillType()->getSpawnUnit() != "" && act->getAttackSkillType()->getSpawnUnitCount() > 0) { - - const FactionType *ft= unit->getFaction()->getType(); - const UnitType *spawnUnitType = ft->getUnitType(act->getAttackSkillType()->getSpawnUnit()); - int spawnCount = act->getAttackSkillType()->getSpawnUnitCount(); - for (int y=0; y < spawnCount; ++y) { - if(spawnUnitType->getMaxUnitCount() > 0) { - if(spawnUnitType->getMaxUnitCount() <= unit->getFaction()->getCountForMaxUnitCount(spawnUnitType)) { - break; - } - } - UnitPathInterface *newpath = NULL; - switch(this->game->getGameSettings()->getPathFinderType()) { - case pfBasic: - newpath = new UnitPathBasic(); - break; - default: - throw megaglest_runtime_error("detected unsupported pathfinder type!"); - } - - Unit *spawned= new Unit(world->getNextUnitId(unit->getFaction()), newpath, - Vec2i(0), spawnUnitType, unit->getFaction(), - world->getMap(), CardinalDir::NORTH); - //SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to place unit for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,spawned->toString().c_str()); - if(!world->placeUnit(unit->getCenteredPos(), 10, spawned)) { - //SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] COULD NOT PLACE UNIT for unitID [%d]\n",__FILE__,__FUNCTION__,__LINE__,spawned->getId()); - - // This will also cleanup newPath - delete spawned; - spawned = NULL; - } - else { - spawned->create(); - spawned->born(ct); - world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats()); - const CommandType *ct= spawned->computeCommandType(command->getPos(),command->getUnit()); - if(ct != NULL){ - if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - spawned->giveCommand(new Command(ct, unit->getMeetingPos())); - } - scriptManager->onUnitCreated(spawned); - - if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); - } - } - } + spawnAttack(unit,act->getAttackSkillType()->getSpawnUnit(),act->getAttackSkillType()->getSpawnUnitCount(),act->getAttackSkillType()->getSpawnUnitAtTarget()); } } @@ -356,6 +309,65 @@ bool UnitUpdater::updateUnit(Unit *unit) { return processUnitCommand; } +void UnitUpdater::spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,bool spawnUnitAtTarget,Vec2i targetPos) { + if(spawnUnit != "" && spawnUnitcount > 0) { + + const FactionType *ft= unit->getFaction()->getType(); + const UnitType *spawnUnitType = ft->getUnitType(spawnUnit); + int spawnCount = spawnUnitcount; + for (int y=0; y < spawnCount; ++y) { + if(spawnUnitType->getMaxUnitCount() > 0) { + if(spawnUnitType->getMaxUnitCount() <= unit->getFaction()->getCountForMaxUnitCount(spawnUnitType)) { + break; + } + } + UnitPathInterface *newpath = NULL; + switch(this->game->getGameSettings()->getPathFinderType()) { + case pfBasic: + newpath = new UnitPathBasic(); + break; + default: + throw megaglest_runtime_error("detected unsupported pathfinder type!"); + } + + Unit *spawned= new Unit(world->getNextUnitId(unit->getFaction()), newpath, + Vec2i(0), spawnUnitType, unit->getFaction(), + world->getMap(), CardinalDir::NORTH); + //SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] about to place unit for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,spawned->toString().c_str()); + bool placedSpawnUnit=false; + if(targetPos==Vec2i(-10,-10)) { + targetPos=unit->getTargetPos(); + } + if(spawnUnitAtTarget) { + placedSpawnUnit=world->placeUnit(targetPos, 10, spawned); + } else { + placedSpawnUnit=world->placeUnit(unit->getCenteredPos(), 10, spawned); + } + if(!placedSpawnUnit) { + //SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] COULD NOT PLACE UNIT for unitID [%d]\n",__FILE__,__FUNCTION__,__LINE__,spawned->getId()); + + // This will also cleanup newPath + delete spawned; + spawned = NULL; + } + else { + spawned->create(); + spawned->born(NULL); + world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats()); + const CommandType *ct= spawned->getType()->getFirstAttackCommand(unit->getTargetField()); + if(ct == NULL){ + ct= spawned->computeCommandType(targetPos,map->getCell(targetPos)->getUnit(unit->getTargetField())); + } + if(ct != NULL){ + if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + spawned->giveCommand(new Command(ct, targetPos)); + } + scriptManager->onUnitCreated(spawned); + } + } + } +} + // ==================== progress commands ==================== //VERY IMPORTANT: compute next state depending on the first order of the list @@ -3298,6 +3310,11 @@ void ParticleDamager::update(ParticleSystem *particleSystem) { SoundRenderer::getInstance().playFx(projSound, attacker->getCurrVector(), gameCamera->getPos()); } + //check for spawnattack + if(projectileType->getSpawnUnit()!=""){ + unitUpdater->spawnAttack(attacker,projectileType->getSpawnUnit(),projectileType->getSpawnUnitcount(),projectileType->getSpawnUnitAtTarget(),targetPos); + } + // check for shake and shake if(projectileType->isShake()==true){ World *world=attacker->getFaction()->getWorld(); diff --git a/source/glest_game/world/unit_updater.h b/source/glest_game/world/unit_updater.h index b40060fd..fae218b8 100644 --- a/source/glest_game/world/unit_updater.h +++ b/source/glest_game/world/unit_updater.h @@ -103,6 +103,7 @@ public: //update skills bool updateUnit(Unit *unit); + void spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,bool spawnUnitAtTarget,Vec2i targetPos=Vec2i(-10,-10)); //update commands void updateUnitCommand(Unit *unit, int frameIndex);