spawn units on death
as requested here https://forum.megaglest.org/index.php?topic=9879.0
This commit is contained in:
parent
661b512a8a
commit
374634b630
|
@ -1354,6 +1354,13 @@ void MorphSkillType::saveGame(XmlNode *rootNode) {
|
|||
DieSkillType::DieSkillType(){
|
||||
skillClass= scDie;
|
||||
fade=false;
|
||||
spawn=false;
|
||||
spawnStartTime=0;
|
||||
spawnUnit="";
|
||||
spawnUnitcount=0;
|
||||
spawnUnitHealthPercentMin=100;
|
||||
spawnUnitHealthPercentMax=100;
|
||||
spawnProbability=100;
|
||||
}
|
||||
|
||||
void DieSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
|
||||
|
@ -1363,6 +1370,18 @@ void DieSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode,
|
|||
SkillType::load(sn, attackBoostsNode,dir, tt, ft, loadedFileList, parentLoader);
|
||||
|
||||
fade= sn->getChild("fade")->getAttribute("value")->getBoolValue();
|
||||
if(sn->hasChild("spawn")){
|
||||
const XmlNode *spawnNode= sn->getChild("spawn");
|
||||
spawn=true;
|
||||
spawnStartTime=spawnNode->getAttribute("start-time")->getFloatValue();
|
||||
spawnUnit = spawnNode->getChild("unit")->getAttribute("value")->getValue();
|
||||
spawnUnitcount = spawnNode->hasChild("amount")?spawnNode->getChild("amount")->getAttribute("value")->getIntValue():0;
|
||||
if(spawnNode->hasChild("health-percent")){
|
||||
spawnUnitHealthPercentMin = spawnNode->getChild("health-percent")->getAttribute("min")->getIntValue();
|
||||
spawnUnitHealthPercentMax = spawnNode->getChild("health-percent")->getAttribute("max")->getIntValue();
|
||||
}
|
||||
spawnProbability = spawnNode->hasChild("probability")?spawnNode->getChild("probability")->getAttribute("value")->getIntValue():spawnProbability;
|
||||
} // else keep defaults
|
||||
}
|
||||
|
||||
string DieSkillType::toString(bool translatedValue) const{
|
||||
|
@ -1379,6 +1398,7 @@ void DieSkillType::saveGame(XmlNode *rootNode) {
|
|||
XmlNode *dieSkillTypeNode = rootNode->addChild("DieSkillType");
|
||||
|
||||
dieSkillTypeNode->addAttribute("fade",intToStr(fade), mapTagReplacements);
|
||||
// no need to save spawn attributes
|
||||
}
|
||||
|
||||
StaticSound *DieSkillType::getSound() const{
|
||||
|
|
|
@ -476,16 +476,31 @@ public:
|
|||
class DieSkillType: public SkillType {
|
||||
private:
|
||||
bool fade;
|
||||
bool spawn;
|
||||
float spawnStartTime;
|
||||
string spawnUnit;
|
||||
int spawnUnitcount;
|
||||
int spawnUnitHealthPercentMin;
|
||||
int spawnUnitHealthPercentMax;
|
||||
int spawnProbability;
|
||||
|
||||
public:
|
||||
DieSkillType();
|
||||
bool getFade() const {return fade;}
|
||||
|
||||
virtual void load(const XmlNode *sn, const XmlNode *attackBoostsNode, const string &dir, const TechTree *tt,
|
||||
const FactionType *ft, std::map<string,vector<pair<string, string> > > &loadedFileList,
|
||||
string parentLoader);
|
||||
virtual string toString(bool translatedValue) const;
|
||||
|
||||
bool getFade() const {return fade;}
|
||||
bool getSpawn() const {return spawn;}
|
||||
inline int getSpawnStartTime() const {return spawnStartTime;}
|
||||
inline string getSpawnUnit() const {return spawnUnit;}
|
||||
inline int getSpawnUnitCount() const {return spawnUnitcount;}
|
||||
inline int getSpawnUnitHealthPercentMin() const {return spawnUnitHealthPercentMin;}
|
||||
inline int getSpawnUnitHealthPercentMax() const {return spawnUnitHealthPercentMax;}
|
||||
inline int getSpawnProbability() const {return spawnProbability;}
|
||||
|
||||
virtual void saveGame(XmlNode *rootNode);
|
||||
StaticSound *getSound() const;
|
||||
};
|
||||
|
|
|
@ -182,6 +182,27 @@ bool UnitUpdater::updateUnit(Unit *unit) {
|
|||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after playsound]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||
|
||||
|
||||
//start attack particle system
|
||||
if(unit->getCurrSkill()->getClass() == scDie) {
|
||||
const DieSkillType *dst= static_cast<const DieSkillType*>(unit->getCurrSkill());
|
||||
|
||||
if(dst->getSpawn() == true){
|
||||
float spawnStartTime = truncateDecimal<float>(dst->getSpawnStartTime(),6);
|
||||
float lastAnimProgress = truncateDecimal<float>(unit->getLastAnimProgressAsFloat(),6);
|
||||
float animProgress = truncateDecimal<float>(unit->getAnimProgressAsFloat(),6);
|
||||
|
||||
bool startSpawnNow = (spawnStartTime >= lastAnimProgress && spawnStartTime < animProgress);
|
||||
if(startSpawnNow){
|
||||
// spawn the units
|
||||
spawn(unit, dst->getSpawnUnit(), dst->getSpawnUnitCount(),
|
||||
dst->getSpawnUnitHealthPercentMin(),
|
||||
dst->getSpawnUnitHealthPercentMax(),
|
||||
dst->getSpawnProbability());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//start attack particle system
|
||||
if(unit->getCurrSkill()->getClass() == scAttack) {
|
||||
const AttackSkillType *ast= static_cast<const AttackSkillType*>(unit->getCurrSkill());
|
||||
|
@ -275,7 +296,10 @@ bool UnitUpdater::updateUnit(Unit *unit) {
|
|||
if (act != NULL && act->getAttackSkillType() != NULL
|
||||
&& act->getAttackSkillType()->getSpawnUnit() != ""
|
||||
&& act->getAttackSkillType()->getSpawnUnitCount() > 0) {
|
||||
spawnAttack(unit,act->getAttackSkillType()->getSpawnUnit(),act->getAttackSkillType()->getSpawnUnitCount(),act->getAttackSkillType()->getSpawnUnitAtTarget());
|
||||
spawnAttack(unit, act->getAttackSkillType()->getSpawnUnit(),
|
||||
act->getAttackSkillType()->getSpawnUnitCount(), 100,
|
||||
100, 100,
|
||||
act->getAttackSkillType()->getSpawnUnitAtTarget());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,51 +337,46 @@ bool UnitUpdater::updateUnit(Unit *unit) {
|
|||
return processUnitCommand;
|
||||
}
|
||||
|
||||
void UnitUpdater::spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,bool spawnUnitAtTarget,Vec2i targetPos) {
|
||||
void UnitUpdater::spawn(Unit *unit,string spawnUnit,int spawnUnitcount,int healthMin,int healthMax,int probability) {
|
||||
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;
|
||||
if (probability > 0 && probability < 100
|
||||
&& unit->getRandom()->randRange(1, 100) <= probability) {
|
||||
continue;
|
||||
}
|
||||
Unit* spawned=this->spawnUnit(unit,spawnUnit);
|
||||
if(spawned!=NULL){
|
||||
if(healthMin>0 && healthMin<100 && healthMax>=healthMin && healthMax<=100){
|
||||
int damagePercent=100-unit->getRandom()->randRange(healthMin, healthMax);
|
||||
//printf("damagePercent=%d\n",damagePercent);
|
||||
spawned->decHp((spawned->getHp()*damagePercent)/100);
|
||||
}
|
||||
}
|
||||
UnitPathInterface *newpath = NULL;
|
||||
switch(this->game->getGameSettings()->getPathFinderType()) {
|
||||
case pfBasic:
|
||||
newpath = new UnitPathBasic();
|
||||
break;
|
||||
default:
|
||||
throw megaglest_runtime_error("detected unsupported pathfinder type!");
|
||||
}
|
||||
// no stat count !!
|
||||
//world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
void UnitUpdater::spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,int healthMin,int healthMax,int probability,bool spawnUnitAtTarget,Vec2i targetPos) {
|
||||
if(spawnUnit != "" && spawnUnitcount > 0) {
|
||||
|
||||
// This will also cleanup newPath
|
||||
delete spawned;
|
||||
spawned = NULL;
|
||||
int spawnCount = spawnUnitcount;
|
||||
for (int y=0; y < spawnCount; ++y) {
|
||||
if (probability > 0 && probability < 100
|
||||
&& unit->getRandom()->randRange(1, 100) <= probability) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
spawned->create();
|
||||
spawned->born(NULL);
|
||||
world->getStats()->produce(unit->getFactionIndex(),spawned->getType()->getCountUnitProductionInStats());
|
||||
Unit* spawned=this->spawnUnit(unit,spawnUnit,spawnUnitAtTarget?targetPos:unit->getCenteredPos());
|
||||
if(spawned!=NULL){
|
||||
if(healthMin>0 && healthMin<100 && healthMax>=healthMin && healthMax<=100){
|
||||
int damagePercent=100-unit->getRandom()->randRange(healthMin, healthMax);
|
||||
//printf("damagePercent=%d\n",damagePercent);
|
||||
spawned->decHp((spawned->getHp()*damagePercent)/100);
|
||||
}
|
||||
// no stat count !!
|
||||
// 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()));
|
||||
|
@ -366,12 +385,54 @@ void UnitUpdater::spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,boo
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Unit* UnitUpdater::spawnUnit(Unit *unit,string spawnUnit,Vec2i spawnPos) {
|
||||
const FactionType *ft= unit->getFaction()->getType();
|
||||
const UnitType *spawnUnitType = ft->getUnitType(spawnUnit);
|
||||
Vec2i _spawnPos=spawnPos;
|
||||
if(_spawnPos==Vec2i(-10,-10)) {
|
||||
_spawnPos=unit->getCenteredPos();
|
||||
}
|
||||
if(spawnUnitType->getMaxUnitCount() > 0) {
|
||||
if(spawnUnitType->getMaxUnitCount() <= unit->getFaction()->getCountForMaxUnitCount(spawnUnitType)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
bool placedSpawnUnit=world->placeUnit(_spawnPos, 10, spawned);
|
||||
|
||||
if(!placedSpawnUnit) {
|
||||
// This will also cleanup newPath
|
||||
delete spawned;
|
||||
spawned = NULL;
|
||||
}
|
||||
else {
|
||||
spawned->create();
|
||||
spawned->born(NULL);
|
||||
scriptManager->onUnitCreated(spawned);
|
||||
}
|
||||
return spawned;
|
||||
}
|
||||
|
||||
|
||||
// ==================== progress commands ====================
|
||||
|
||||
//VERY IMPORTANT: compute next state depending on the first order of the list
|
||||
|
@ -3339,7 +3400,9 @@ void ParticleDamager::update(ParticleSystem *particleSystem) {
|
|||
|
||||
//check for spawnattack
|
||||
if(projectileType->getSpawnUnit()!="" && projectileType->getSpawnUnitcount()>0 ){
|
||||
unitUpdater->spawnAttack(attacker,projectileType->getSpawnUnit(),projectileType->getSpawnUnitcount(),projectileType->getSpawnUnitAtTarget(),targetPos);
|
||||
unitUpdater->spawnAttack(attacker, projectileType->getSpawnUnit(), 100,
|
||||
100, 100, projectileType->getSpawnUnitcount(),
|
||||
projectileType->getSpawnUnitAtTarget(), targetPos);
|
||||
}
|
||||
|
||||
// check for shake and shake
|
||||
|
|
|
@ -103,7 +103,6 @@ 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);
|
||||
|
@ -153,6 +152,10 @@ private:
|
|||
bool unitOnRange(Unit *unit, int range, Unit **enemyPtr, const AttackSkillType *ast,bool evalMode=false);
|
||||
void enemiesAtDistance(const Unit *unit, const Unit *priorityUnit, int distance, vector<Unit*> &enemies);
|
||||
|
||||
void spawn(Unit *unit,string spawnUnit,int spawnUnitcount,int healthMin,int healthMax,int probability);
|
||||
void spawnAttack(Unit *unit,string spawnUnit,int spawnUnitcount,int healthMin,int healthMax,int probability,bool spawnUnitAtTarget,Vec2i targetPos=Vec2i(-10,-10));
|
||||
Unit* spawnUnit(Unit *unit,string spawnUnit,Vec2i targetPos=Vec2i(-10,-10));
|
||||
|
||||
Unit * findPeerUnitBuilder(Unit *unit);
|
||||
void SwapActiveCommand(Unit *unitSrc, Unit *unitDest);
|
||||
void SwapActiveCommandState(Unit *unit, CommandStateType commandStateType,
|
||||
|
|
Loading…
Reference in New Issue