From 6086a33bafef96ef58dcf9096a5f274060e5837b Mon Sep 17 00:00:00 2001 From: titison Date: Sun, 27 Jul 2014 12:54:25 +0200 Subject: [PATCH 1/2] Added a bool spawnAtTarget to spawn attack in which you can define whether the unit spawns at the target or at the attacker. In Addition i changed the command which is given to the spawned unit to an attack command on the target cell. ( I think this makes way more sense than giving a move command to the meeting point) ( This also works if the spawned does not have a attack command. It will move to the enemy then) --- source/glest_game/types/skill_type.cpp | 12 ++++++++++-- source/glest_game/types/skill_type.h | 2 ++ source/glest_game/world/unit_updater.cpp | 12 +++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index 00b6bba1..01143bdf 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"); @@ -1053,6 +1059,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..67ba4266 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -298,7 +298,13 @@ bool UnitUpdater::updateUnit(Unit *unit) { 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)) { + bool placedSpawnUnit=false; + if(act->getAttackSkillType()->getSpawnUnitAtTarget()) { + placedSpawnUnit=world->placeUnit(unit->getTargetPos(), 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 @@ -309,10 +315,10 @@ bool UnitUpdater::updateUnit(Unit *unit) { spawned->create(); spawned->born(ct); world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats()); - const CommandType *ct= spawned->computeCommandType(command->getPos(),command->getUnit()); + const CommandType *ct= spawned->computeCommandType(unit->getTargetPos(),map->getCell(unit->getTargetPos())->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, unit->getMeetingPos())); + spawned->giveCommand(new Command(ct, unit->getTargetPos())); } scriptManager->onUnitCreated(spawned); From 51c1afe4e4b96d8a9b683120a5487b1972742346 Mon Sep 17 00:00:00 2001 From: titison Date: Sun, 27 Jul 2014 21:41:40 +0200 Subject: [PATCH 2/2] Added the ability for SpawnAttacks to let the units spawn when the projectile arrives at the targetpos. Unit will always try to attack if it has an attack command. Unit attacks the target POS and not the target UNIT of the attacker. --- source/glest_game/types/projectile_type.cpp | 20 ++++ source/glest_game/types/projectile_type.h | 8 ++ source/glest_game/world/unit_updater.cpp | 119 +++++++++++--------- source/glest_game/world/unit_updater.h | 1 + 4 files changed, 94 insertions(+), 54 deletions(-) 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/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index 67ba4266..775d8afa 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -270,62 +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()); - bool placedSpawnUnit=false; - if(act->getAttackSkillType()->getSpawnUnitAtTarget()) { - placedSpawnUnit=world->placeUnit(unit->getTargetPos(), 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(ct); - world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats()); - const CommandType *ct= spawned->computeCommandType(unit->getTargetPos(),map->getCell(unit->getTargetPos())->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, unit->getTargetPos())); - } - 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()); } } @@ -362,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 @@ -3304,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);