- initial implementation of attack-boost logic (this is in progress code which is only triggered by new xml entries). Will explain later once tested.

This commit is contained in:
Mark Vejvoda 2011-06-25 08:53:53 +00:00
parent 5dda269151
commit c252402e71
8 changed files with 204 additions and 13 deletions

View File

@ -278,6 +278,8 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType
//starting skill
this->lastModelIndexForCurrSkillType = -1;
this->currSkill = getType()->getFirstStOfClass(scStop);
this->currentAttackBoostUnits.first = this->currSkill;
livingUnits.insert(id);
livingUnitsp.insert(this);
@ -1231,6 +1233,40 @@ bool Unit::update() {
}
}
//if(currSkill != currentAttackBoostUnits.first) {
// First remove any units that were previosuly in range
if(currentAttackBoostUnits.second.size() > 0) {
for(unsigned int i = 0; i < currentAttackBoostUnits.second.size(); ++i) {
// Remove attack boost upgrades from unit
Unit *affectedUnit = currentAttackBoostUnits.second[i];
affectedUnit->deapplyAttackBoost(currentAttackBoostUnits.first->getAttackBoost(), this);
//printf("!!!! DE-APPLY ATTACK BOOST from unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId());
}
currentAttackBoostUnits.second.clear();
}
//}
currentAttackBoostUnits.first = currSkill;
if(currSkill->isAttackBoostEnabled() == true) {
// Search for units in range of this unit which apply to the
// attack-boost and temporarily upgrade them
UnitUpdater *unitUpdater = this->game->getWorld()->getUnitUpdater();
const AttackBoost *attackBoost = currSkill->getAttackBoost();
vector<Unit *> candidates = unitUpdater->findUnitsInRange(this, attackBoost->radius);
for(unsigned int i = 0; i < candidates.size(); ++i) {
Unit *affectedUnit = candidates[i];
if(attackBoost->isAffected(this,affectedUnit) == true) {
affectedUnit->applyAttackBoost(attackBoost, this);
currentAttackBoostUnits.second.push_back(affectedUnit);
//printf("@@@@ APPLY ATTACK BOOST to unit [%s - %d]\n",affectedUnit->getType()->getName().c_str(),affectedUnit->getId());
}
}
}
return return_value;
}
@ -1516,6 +1552,38 @@ string Unit::getDesc() const {
return str;
}
void Unit::applyAttackBoost(const AttackBoost *boost, const Unit *source) {
if(boost == NULL) {
char szBuf[4096]="";
sprintf(szBuf,"In [%s::%s Line: %d] ERROR: boost == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str());
throw runtime_error(szBuf);
}
if(boost->isAffected(source, this)) {
totalUpgrade.apply(&boost->boostUpgrade);
checkItemInVault(&this->hp,this->hp);
hp += boost->boostUpgrade.getMaxHp();
addItemToVault(&this->hp,this->hp);
}
}
void Unit::deapplyAttackBoost(const AttackBoost *boost, const Unit *source) {
if(boost == NULL) {
char szBuf[4096]="";
sprintf(szBuf,"In [%s::%s Line: %d] ERROR: boost == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str());
throw runtime_error(szBuf);
}
if(boost->isAffected(source, this)) {
totalUpgrade.deapply(&boost->boostUpgrade);
checkItemInVault(&this->hp,this->hp);
hp -= boost->boostUpgrade.getMaxHp();
addItemToVault(&this->hp,this->hp);
}
}
void Unit::applyUpgrade(const UpgradeType *upgradeType){
if(upgradeType == NULL) {
char szBuf[4096]="";

View File

@ -19,6 +19,7 @@
#include "game_constants.h"
#include <set>
#include "platform_common.h"
#include <vector>
#include "leak_dumper.h"
namespace Glest { namespace Game {
@ -49,6 +50,7 @@ class UpgradeType;
class Level;
class MorphCommandType;
class Game;
class Unit;
enum CommandResult{
crSuccess,
@ -342,6 +344,8 @@ private:
bool usePathfinderExtendedMaxNodes;
int maxQueuedCommandDisplayCount;
std::pair<const SkillType *,std::vector<Unit *> > currentAttackBoostUnits;
public:
Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing);
~Unit();
@ -463,6 +467,10 @@ public:
int update2();
bool update();
void tick();
void applyAttackBoost(const AttackBoost *boost, const Unit *source);
void deapplyAttackBoost(const AttackBoost *boost, const Unit *source);
void applyUpgrade(const UpgradeType *upgradeType);
void computeTotalUpgrade();
void incKills(int team);

View File

@ -28,6 +28,55 @@ using namespace Shared::Graphics;
namespace Glest{ namespace Game{
AttackBoost::AttackBoost() {
enabled = false;
radius = 0;
boostAllUnits = false;
}
bool AttackBoost::isAffected(const Unit *source, const Unit *dest) const {
bool result = false;
if(enabled == true && source != NULL && dest != NULL &&
source != dest) {
// All units are affected (including enemies)
if(boostAllUnits == true) {
float distance = source->getCenteredPos().dist(dest->getCenteredPos());
if(distance <= radius) {
result = true;
}
}
else {
// Only same faction units are affected
if(boostUnitList.size() == 0) {
//if(source->isAlly(dest) == true) {
//}
if(source->getFactionIndex() == dest->getFactionIndex()) {
float distance = source->getCenteredPos().dist(dest->getCenteredPos());
if(distance <= radius) {
result = true;
}
}
}
// Specify which units are affected
else {
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
const UnitType *ut = boostUnitList[i];
if(dest->getType()->getId() == ut->getId()) {
float distance = source->getCenteredPos().dist(dest->getCenteredPos());
if(distance <= radius) {
result = true;
break;
}
}
}
}
}
}
return result;
}
// =====================================================
// class SkillType
// =====================================================

View File

@ -41,6 +41,7 @@ class FactionType;
class TechTree;
class Lang;
class TotalUpgrade;
class Unit;
enum Field{
@ -75,16 +76,14 @@ typedef list<UnitParticleSystemType*> UnitParticleSystemTypes;
class AttackBoost {
public:
AttackBoost() {
enabled = false;
radius = 0;
boostAllUnits = false;
}
AttackBoost();
bool enabled;
int radius;
bool boostAllUnits;
vector<const UnitType *> boostUnitList;
UpgradeTypeBase boostUpgrade;
bool isAffected(const Unit *source, const Unit *dest) const;
};
class SkillType {
@ -123,6 +122,9 @@ public:
StaticSound *getSound() const {return sounds.getRandSound();}
float getSoundStartTime() const {return soundStartTime;}
bool isAttackBoostEnabled() const { return attackBoost.enabled; }
const AttackBoost * getAttackBoost() const { return &attackBoost; }
//other
virtual string toString() const= 0;
virtual int getTotalSpeed(const TotalUpgrade *) const {return speed;}

View File

@ -232,11 +232,11 @@ string UpgradeType::getReqDesc() const{
// class TotalUpgrade
// ===============================
TotalUpgrade::TotalUpgrade(){
TotalUpgrade::TotalUpgrade() {
reset();
}
void TotalUpgrade::reset(){
void TotalUpgrade::reset() {
maxHp= 0;
maxEp= 0;
sight=0;
@ -247,7 +247,7 @@ void TotalUpgrade::reset(){
prodSpeed=0;
}
void TotalUpgrade::sum(const UpgradeType *ut){
void TotalUpgrade::sum(const UpgradeTypeBase *ut) {
maxHp+= ut->getMaxHp();
maxEp+= ut->getMaxEp();
sight+= ut->getSight();
@ -258,11 +258,26 @@ void TotalUpgrade::sum(const UpgradeType *ut){
prodSpeed+= ut->getProdSpeed();
}
void TotalUpgrade::incLevel(const UnitType *ut){
void TotalUpgrade::incLevel(const UnitType *ut) {
maxHp+= ut->getMaxHp()*50/100;
maxEp+= ut->getMaxEp()*50/100;
sight+= ut->getSight()*20/100;
armor+= ut->getArmor()*50/100;
}
void TotalUpgrade::apply(const UpgradeTypeBase *ut) {
sum(ut);
}
void TotalUpgrade::deapply(const UpgradeTypeBase *ut) {
maxHp-= ut->getMaxHp();
maxEp-= ut->getMaxEp();
sight-= ut->getSight();
armor-= ut->getArmor();
attackStrength-= ut->getAttackStrength();
attackRange-= ut->getAttackRange();
moveSpeed-= ut->getMoveSpeed();
prodSpeed-= ut->getProdSpeed();
}
}}//end namespace

View File

@ -22,7 +22,7 @@ using Shared::Util::Checksum;
using namespace Shared::Util;
using namespace Shared::Xml;
namespace Glest{ namespace Game{
namespace Glest { namespace Game {
class TechTree;
class FactionType;
@ -75,7 +75,7 @@ public:
// class UpgradeType
// ===============================
class UpgradeType: public UpgradeTypeBase, public ProducibleType{
class UpgradeType: public UpgradeTypeBase, public ProducibleType {
private:
vector<const UnitType*> effects;
@ -98,13 +98,16 @@ public:
// class TotalUpgrade
// ===============================
class TotalUpgrade: public UpgradeTypeBase{
class TotalUpgrade: public UpgradeTypeBase {
public:
TotalUpgrade();
void reset();
void sum(const UpgradeType *ut);
void sum(const UpgradeTypeBase *ut);
void incLevel(const UnitType *ut);
void apply(const UpgradeTypeBase *ut);
void deapply(const UpgradeTypeBase *ut);
};
}}//end namespace

View File

@ -2330,6 +2330,49 @@ vector<Unit*> UnitUpdater::enemyUnitsOnRange(const Unit *unit,const AttackSkillT
return enemies;
}
void UnitUpdater::findUnitsForCell(Cell *cell, const Unit *unit,vector<Unit*> &units) {
//all fields
for(int k = 0; k < fieldCount; k++) {
Field f= static_cast<Field>(k);
//check field
Unit *cellUnit = cell->getUnit(f);
if(cellUnit != NULL && cellUnit->isAlive()) {
units.push_back(cellUnit);
}
}
}
vector<Unit*> UnitUpdater::findUnitsInRange(const Unit *unit, int radius) {
int range = radius;
vector<Unit*> units;
//aux vars
int size = unit->getType()->getSize();
Vec2i center = unit->getPos();
Vec2f floatCenter = unit->getFloatCenteredPos();
//nearby cells
UnitRangeCellsLookupItem cacheItem;
for(int i = center.x - range; i < center.x + range + size; ++i) {
for(int j = center.y - range; j < center.y + range + size; ++j) {
//cells inside map and in range
#ifdef USE_STREFLOP
if(map->isInside(i, j) && streflop::floor(floatCenter.dist(Vec2f((float)i, (float)j))) <= (range+1)){
#else
if(map->isInside(i, j) && floor(floatCenter.dist(Vec2f((float)i, (float)j))) <= (range+1)){
#endif
Cell *cell = map->getCell(i,j);
findUnitsForCell(cell,unit,units);
}
}
}
return units;
}
// =====================================================
// class ParticleDamager
// =====================================================

View File

@ -121,6 +121,9 @@ public:
vector<Unit*> enemyUnitsOnRange(const Unit *unit,const AttackSkillType *ast);
void findEnemiesForCell(const Vec2i pos, int size, int sightRange, const Faction *faction, vector<Unit*> &enemies, bool attackersOnly) const;
void findUnitsForCell(Cell *cell, const Unit *unit,vector<Unit*> &units);
vector<Unit*> findUnitsInRange(const Unit *unit, int radius);
private:
//attack
void hit(Unit *attacker);