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.
This commit is contained in:
titison 2014-07-27 21:41:40 +02:00
parent 6086a33baf
commit 51c1afe4e4
4 changed files with 94 additions and 54 deletions

View File

@ -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();

View File

@ -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;}

View File

@ -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<const AttackCommandType*>(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();

View File

@ -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);